From 5b9b882fc360e23aaa076f8ef8fd4ee165d8d953 Mon Sep 17 00:00:00 2001 From: "shengxiang.chen" Date: Sat, 13 Jul 2013 13:14:20 +0800 Subject: [PATCH 001/141] optimize --- cocos2d/CCCamera.js | 3 +- cocos2d/base_nodes/CCNode.js | 207 ++++++++---------- .../CCLayer.js | 17 +- 3 files changed, 93 insertions(+), 134 deletions(-) diff --git a/cocos2d/CCCamera.js b/cocos2d/CCCamera.js index eef780d2e2..a3e3469c08 100644 --- a/cocos2d/CCCamera.js +++ b/cocos2d/CCCamera.js @@ -59,9 +59,10 @@ cc.Camera = cc.Class.extend(/** @lends cc.Action# */{ _upZ:null, _dirty:null, - _lookupMatrix:new cc.kmMat4(), + _lookupMatrix:null, ctor:function () { + this._lookupMatrix = new cc.kmMat4(); this.restore(); }, diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index ee492ad9d9..832a76c37d 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -165,15 +165,14 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ this._anchorPointInPoints = cc.p(0, 0); this._contentSize = cc.size(0, 0); this._position = cc.p(0, 0); + this._children = []; var director = cc.Director.getInstance(); this._actionManager = director.getActionManager(); this._scheduler = director.getScheduler(); this._initializedNode = true; this._additionalTransform = cc.AffineTransformMakeIdentity(); - this._additionalTransformDirty = false; this._componentContainer = new cc.ComponentContainer(this); - this._isTransitionFinished = false; }, /** @@ -195,49 +194,56 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ if (!array || array.length === 0) return; - var i, len = array.length; + var i, len = array.length,node; var nodeCallbackType = cc.Node.StateCallbackType; switch (callbackType) { case nodeCallbackType.onEnter: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onEnter(); + node = array[i]; + if (node) + node.onEnter(); } break; case nodeCallbackType.onExit: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onExit(); + node = array[i]; + if (node) + node.onExit(); } break; case nodeCallbackType.onEnterTransitionDidFinish: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onEnterTransitionDidFinish(); + node = array[i]; + if (node) + node.onEnterTransitionDidFinish(); } break; case nodeCallbackType.cleanup: for (i = 0; i < len; i++) { - if (array[i]) - array[i].cleanup(); + node = array[i]; + if (node) + node.cleanup(); } break; case nodeCallbackType.updateTransform: for (i = 0; i < len; i++) { - if (array[i]) - array[i].updateTransform(); + node = array[i]; + if (node) + node.updateTransform(); } break; case nodeCallbackType.onExitTransitionDidStart: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onExitTransitionDidStart(); + node = array[i]; + if (node) + node.onExitTransitionDidStart(); } break; case nodeCallbackType.sortAllChildren: for (i = 0; i < len; i++) { - if (array[i]) - array[i].sortAllChildren(); + node = array[i]; + if (node) + node.sortAllChildren(); } break; default : @@ -246,13 +252,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ } }, - /** - * set the dirty node - */ - setNodeDirty:function () { - this._transformDirty = this._inverseDirty = true; - }, - /** *

get the skew degrees in X
* The X skew angle of the node in degrees.
@@ -589,7 +588,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @return {Number} The amount of children. */ getChildrenCount:function () { - return this._children ? this._children.length : 0; + return this._children.length; }, /** @@ -604,8 +603,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * } */ getChildren:function () { - if (!this._children) - this._children = []; return this._children; }, @@ -941,10 +938,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ return ""; }, - _childrenAlloc:function () { - this._children = []; - }, - // composition: GET /** * Gets a child from the container given its tag @@ -985,16 +978,12 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ cc.Assert(child._parent === null, "child already added. It can't be added again"); return; } - var tempzOrder = (zOrder != null) ? zOrder : child.getZOrder(); - var tmptag = (tag != null) ? tag : child.getTag(); - child.setTag(tmptag); - if (!this._children) - this._childrenAlloc(); - - this._insertChild(child, tempzOrder); + var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder; + child._tag = (tag != null) ? tag : child._tag; + this._insertChild(child, tmpzOrder); + child._parent = this; - child.setParent(this); if (this._running) { child.onEnter(); // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter @@ -1041,7 +1030,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ removeChild:function (child, cleanup) { // explicit nil handling - if (this._children == null) + if (this._children.length === 0) return; if (cleanup == null) @@ -1181,20 +1170,22 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { - var i, j, length = this._children.length; - var localChildren = this._children; + var _children = this._children; + var i, j, length = _children.length,tempChild; + // insertion sort for (i = 0; i < length; i++) { - var tempItem = localChildren[i]; + var tempItem = _children[i]; j = i - 1; + tempChild = _children[j]; //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller - while (j >= 0 && ( tempItem._zOrder < localChildren[j]._zOrder || - ( tempItem._zOrder == localChildren[j]._zOrder && tempItem._orderOfArrival < localChildren[j]._orderOfArrival ))) { - localChildren[j + 1] = localChildren[j]; + while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || + ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { + _children[j + 1] = tempChild; j = j - 1; } - localChildren[j + 1] = tempItem; + _children[j + 1] = tempItem; } //don't need to check children recursively, that's done in visit of each child @@ -2045,15 +2036,14 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ this._anchorPointInPoints = cc.p(0, 0); this._contentSize = cc.size(0, 0); this._position = cc.p(0, 0); + this._children = []; var director = cc.Director.getInstance(); this._actionManager = director.getActionManager(); this._scheduler = director.getScheduler(); this._initializedNode = true; this._additionalTransform = cc.AffineTransformMakeIdentity(); - this._additionalTransformDirty = false; this._componentContainer = new cc.ComponentContainer(this); - this._isTransitionFinished = false; }, /** @@ -2075,49 +2065,56 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ if (!array || array.length === 0) return; - var i, len = array.length; + var i, len = array.length,node; var nodeCallbackType = cc.Node.StateCallbackType; switch (callbackType) { case nodeCallbackType.onEnter: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onEnter(); + node = array[i]; + if (node) + node.onEnter(); } break; case nodeCallbackType.onExit: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onExit(); + node = array[i]; + if (node) + node.onExit(); } break; case nodeCallbackType.onEnterTransitionDidFinish: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onEnterTransitionDidFinish(); + node = array[i]; + if (node) + node.onEnterTransitionDidFinish(); } break; case nodeCallbackType.cleanup: for (i = 0; i < len; i++) { - if (array[i]) - array[i].cleanup(); + node = array[i]; + if (node) + node.cleanup(); } break; case nodeCallbackType.updateTransform: for (i = 0; i < len; i++) { - if (array[i]) - array[i].updateTransform(); + node = array[i]; + if (node) + node.updateTransform(); } break; case nodeCallbackType.onExitTransitionDidStart: for (i = 0; i < len; i++) { - if (array[i]) - array[i].onExitTransitionDidStart(); + node = array[i]; + if (node) + node.onExitTransitionDidStart(); } break; case nodeCallbackType.sortAllChildren: for (i = 0; i < len; i++) { - if (array[i]) - array[i].sortAllChildren(); + node = array[i]; + if (node) + node.sortAllChildren(); } break; default : @@ -2126,13 +2123,6 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ } }, - /** - * set the dirty node - */ - setNodeDirty:function () { - this._transformDirty = this._inverseDirty = true; - }, - /** *

get the skew degrees in X
* The X skew angle of the node in degrees.
@@ -2468,7 +2458,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @return {Number} The amount of children. */ getChildrenCount:function () { - return this._children ? this._children.length : 0; + return this._children.length; }, /** @@ -2483,8 +2473,6 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * } */ getChildren:function () { - if (!this._children) - this._children = []; return this._children; }, @@ -2821,10 +2809,6 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ return ""; }, - _childrenAlloc:function () { - this._children = []; - }, - // composition: GET /** * Gets a child from the container given its tag @@ -2865,16 +2849,12 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ cc.Assert(child._parent === null, "child already added. It can't be added again"); return; } - var tempzOrder = (zOrder != null) ? zOrder : child.getZOrder(); - var tmptag = (tag != null) ? tag : child.getTag(); - child.setTag(tmptag); - - if (!this._children) - this._childrenAlloc(); - this._insertChild(child, tempzOrder); + var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder; + child._tag = (tag != null) ? tag : child._tag; + this._insertChild(child, tmpzOrder); + child._parent = this; - child.setParent(this); if (this._running) { child.onEnter(); // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter @@ -2920,7 +2900,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ removeChild:function (child, cleanup) { // explicit nil handling - if (this._children == null) + if (this._children.length === 0) return; if (cleanup == null) @@ -3010,7 +2990,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ child.cleanup(); // set parent nil at the end - child.setParent(null); + child._parent = null; cc.ArrayRemoveObject(this._children, child); }, @@ -3060,20 +3040,22 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { - var i, j, length = this._children.length; + var _children = this._children; + var i, j, length = _children.length,tempChild; // insertion sort for (i = 0; i < length; i++) { - var tempItem = this._children[i]; + var tempItem = _children[i]; j = i - 1; + tempChild = _children[j]; //continue moving element downwards while zOrder is smaller or when zOrder is the same but mutatedIndex is smaller - while (j >= 0 && ( tempItem._zOrder < this._children[j]._zOrder || - ( tempItem._zOrder == this._children[j]._zOrder && tempItem._orderOfArrival < this._children[j]._orderOfArrival ))) { - this._children[j + 1] = this._children[j]; + while (j >= 0 && ( tempItem._zOrder < tempChild._zOrder || + ( tempItem._zOrder == tempChild._zOrder && tempItem._orderOfArrival < tempChild._orderOfArrival ))) { + _children[j + 1] = tempChild; j = j - 1; } - this._children[j + 1] = tempItem; + _children[j + 1] = tempItem; } //don't need to check children recursively, that's done in visit of each child @@ -3561,7 +3543,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ //visit for canvas var context = ctx || cc.renderContext, i; - var children = this._children; + var children = this._children,child; context.save(); this.transform(context); if (children && children.length > 0) { @@ -3569,15 +3551,17 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ this.sortAllChildren(); // draw children zOrder < 0 for (i = 0; i < len; i++) { - if (children[i] && children[i]._zOrder < 0) - children[i].visit(context); + child = children[i]; + if (child && child._zOrder < 0) + child.visit(context); else break; } this.draw(context); for (; i < len; i++) { - if (children[i] && children[i]._zOrder >= 0) - children[i].visit(context); + child = children[i]; + if (child && child._zOrder >= 0) + child.visit(context); } } else @@ -3755,30 +3739,15 @@ cc.Node = cc.Browser.supportWebGL ? cc.NodeWebGL : cc.NodeCanvas; */ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ RGBAProtocol:true, - _displayedOpacity:0, - _realOpacity:0, - _displayedColor:null, - _realColor:null, + _displayedOpacity:255, + _realOpacity:255, + _displayedColor:cc.WHITE, + _realColor:cc.WHITE, _cascadeColorEnabled:false, _cascadeOpacityEnabled:false, - ctor:function(){ - cc.Node.prototype.ctor.call(this); - this._displayedOpacity = 255; - this._realOpacity = 255; - this._displayedColor = cc.WHITE; - this._realColor = cc.WHITE; - this._cascadeColorEnabled = false; - this._cascadeOpacityEnabled = false; - }, - - init:function(){ if(cc.Node.prototype.init.call(this)){ - this._displayedOpacity = this._realOpacity = 255; - this._displayedColor = cc.WHITE; - this._realColor = cc.WHITE; - this._cascadeOpacityEnabled = this._cascadeColorEnabled = false; return true; } return false; @@ -3871,4 +3840,4 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ isOpacityModifyRGB:function(){ return false; } -}); +}); \ No newline at end of file diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index ce43b27e32..4298cddf0b 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -47,26 +47,15 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ _isMouseEnabled:false, _mousePriority:0, - _initLayer:function () { - this.setAnchorPoint(cc.p(0.5, 0.5)); - this._ignoreAnchorPointForPosition = true; - - var director = cc.Director.getInstance(); - this.setContentSize(director.getWinSize()); - this._isTouchEnabled = false; - this._isAccelerometerEnabled = false; - this._isMouseEnabled = false; - this._touchMode = cc.TOUCH_ALL_AT_ONCE; - this._touchPriority = 0; - }, - /** * * @return {Boolean} */ init:function () { cc.Node.prototype.init.call(this); - this._initLayer(); + this._ignoreAnchorPointForPosition = true; + this.setAnchorPoint(cc.p(0.5, 0.5)); + this.setContentSize(cc.Director.getInstance().getWinSize()); return true; }, From 66d568f4c9bc415f78dcadd40359396f0099ba52 Mon Sep 17 00:00:00 2001 From: "shengxiang.chen" Date: Thu, 25 Jul 2013 00:19:53 +0800 Subject: [PATCH 002/141] optimize --- cocos2d/base_nodes/CCNode.js | 41 ++++++++++++++++++++++--------- cocos2d/platform/CCApplication.js | 14 +++++------ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 832a76c37d..7ac7c5d73c 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -3546,23 +3546,40 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ var children = this._children,child; context.save(); this.transform(context); - if (children && children.length > 0) { - var len = children.length; + var len = children.length; + if (len > 0) { this.sortAllChildren(); // draw children zOrder < 0 - for (i = 0; i < len; i++) { - child = children[i]; - if (child && child._zOrder < 0) - child.visit(context); - else - break; + /*var tag = children[0]._zOrder,tmpTag; + if(tag >= 0){ + this.draw(); } - this.draw(context); - for (; i < len; i++) { + for(i = 0; i < len;i++){ child = children[i]; - if (child && child._zOrder >= 0) - child.visit(context); + tmpTag = child._zOrder; + if(tmpTag>=0 && tag < 0){ + this.draw(); + } + child.visit(context); + tag = tmpTag; } + if(tag<0){ + this.draw(); + }*/ + + for (i = 0; i < len; i++) { + child = children[i]; + if (child._zOrder < 0) + child.visit(context); + else + break; + } + this.draw(context); + for (; i < len; i++) { + child = children[i]; + if (child._zOrder >= 0) + child.visit(context); + } } else this.draw(context); diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js index 2333a44075..ec22b28636 100644 --- a/cocos2d/platform/CCApplication.js +++ b/cocos2d/platform/CCApplication.js @@ -341,17 +341,17 @@ cc.Application = cc.Class.extend(/** @lends cc.Application# */{ if (!this.applicationDidFinishLaunching()) return 0; - var callback; - if (window.requestAnimFrame && this._animationInterval == 1 / 60) { + var callback, director = cc.Director.getInstance(), w = window; + if (w.requestAnimFrame && this._animationInterval == 1 / 60) { callback = function () { - cc.Director.getInstance().mainLoop(); - window.requestAnimFrame(callback); + director.mainLoop(); + w.requestAnimFrame(callback); }; - cc.log(window.requestAnimFrame); - window.requestAnimFrame(callback); + //cc.log(window.requestAnimFrame); + w.requestAnimFrame(callback); } else { callback = function () { - cc.Director.getInstance().mainLoop(); + director.mainLoop(); }; setInterval(callback, this._animationInterval * 1000); } From 7e30cfceb39338359548fa37dffee268ec30b1f9 Mon Sep 17 00:00:00 2001 From: "shengxiang.chen" Date: Tue, 30 Jul 2013 16:29:27 +0800 Subject: [PATCH 003/141] fixed #2452:optimize javascript code --- cocos2d/base_nodes/CCNode.js | 38 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 6e1eb36288..876efdc95c 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -3549,37 +3549,19 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ if (len > 0) { this.sortAllChildren(); // draw children zOrder < 0 - /*var tag = children[0]._zOrder,tmpTag; - if(tag >= 0){ - this.draw(); + for (i = 0; i < len; i++) { + child = children[i]; + if (child._zOrder < 0) + child.visit(context); + else + break; } - for(i = 0; i < len;i++){ + this.draw(context); + for (; i < len; i++) { child = children[i]; - tmpTag = child._zOrder; - if(tmpTag>=0 && tag < 0){ - this.draw(); - } - child.visit(context); - tag = tmpTag; + if (child._zOrder >= 0) + child.visit(context); } - if(tag<0){ - this.draw(); - }*/ - - for (i = 0; i < len; i++) { - child = children[i]; - if (child._zOrder < 0) - child.visit(context); - else - break; - } - this.draw(context); - for (; i < len; i++) { - child = children[i]; - if (child._zOrder >= 0) - child.visit(context); - } - } else this.draw(context); From d885745130f3aca85bd9fc3cffa2fb24c3ecb0fd Mon Sep 17 00:00:00 2001 From: "shengxiang.chen" Date: Tue, 30 Jul 2013 16:48:31 +0800 Subject: [PATCH 004/141] fixed #2452:optimize javascript code --- cocos2d/layers_scenes_transitions_nodes/CCLayer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 80632ba72f..42e3f5401e 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -580,6 +580,7 @@ cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{ _cascadeColorEnabled: false, ctor: function () { + cc.Layer.prototype.ctor.call(this); this.RGBAProtocol = true; this._displayedOpacity = 255; this._realOpacity = 255; From 4b2c707d30bfe215acd1df499ff0150c2025114a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:43:31 +0800 Subject: [PATCH 005/141] Fixed #2441 avoid using temp cc.p for cc.Follow --- cocos2d/actions/CCAction.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/cocos2d/actions/CCAction.js b/cocos2d/actions/CCAction.js index 0f5a7e7cf4..82890d79b0 100644 --- a/cocos2d/actions/CCAction.js +++ b/cocos2d/actions/CCAction.js @@ -48,8 +48,8 @@ cc.Action = cc.Class.extend(/** @lends cc.Action# */{ _tag:cc.ACTION_TAG_INVALID, //**************Public Functions*********** - ctor:function(){ - this._originalTarget = null; + ctor:function () { + this._originalTarget = null; this._target = null; this._tag = cc.ACTION_TAG_INVALID; }, @@ -73,7 +73,7 @@ cc.Action = cc.Class.extend(/** @lends cc.Action# */{ * returns a clone of action * @return {cc.Action} */ - clone:function(){ + clone:function () { var action = new cc.Action(); action._originalTarget = null; action._target = null; @@ -211,7 +211,7 @@ cc.FiniteTimeAction = cc.Action.extend(/** @lends cc.FiniteTimeAction# */{ //! duration in seconds _duration:0, - ctor: function () { + ctor:function () { cc.Action.prototype.ctor.call(this); this._duration = 0; }, @@ -244,7 +244,7 @@ cc.FiniteTimeAction = cc.Action.extend(/** @lends cc.FiniteTimeAction# */{ /** * */ - clone:function(){ + clone:function () { return new cc.FiniteTimeAction(); } }); @@ -261,8 +261,8 @@ cc.Speed = cc.Action.extend(/** @lends cc.Speed# */{ _speed:0.0, _innerAction:null, - ctor:function(){ - cc.Action.prototype.ctor.call(this); + ctor:function () { + cc.Action.prototype.ctor.call(this); this._speed = 0; this._innerAction = null; }, @@ -297,7 +297,7 @@ cc.Speed = cc.Action.extend(/** @lends cc.Speed# */{ * returns a clone of action * @returns {cc.Speed} */ - clone:function(){ + clone:function () { var action = new cc.Speed(); action.initWithAction(this._innerAction.clone(), this._speed); return action; @@ -411,7 +411,7 @@ cc.Follow = cc.Action.extend(/** @lends cc.Follow# */{ bottomBoundary:0.0, _worldRect:null, - ctor: function () { + ctor:function () { cc.Action.prototype.ctor.call(this); this._followedNode = null; this._boundarySet = false; @@ -427,7 +427,7 @@ cc.Follow = cc.Action.extend(/** @lends cc.Follow# */{ this._worldRect = cc.RectZero(); }, - clone:function(){ + clone:function () { var action = new cc.Follow(); var locRect = this._worldRect; var rect = new cc.Rect(locRect.x, locRect.y, locRect.width, locRect.height); @@ -497,17 +497,20 @@ cc.Follow = cc.Action.extend(/** @lends cc.Follow# */{ * @param {Number} dt */ step:function (dt) { + var tempPosX = this._followedNode.getPositionX(); + var tempPosY = this._followedNode.getPositionY(); + tempPosX = this._halfScreenSize.x - tempPosX; + tempPosY = this._halfScreenSize.y - tempPosY; + if (this._boundarySet) { // whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased if (this._boundaryFullyCovered) return; - var tempPos = cc.pSub(this._halfScreenSize, this._followedNode.getPosition()); - - this._target.setPosition(cc.p(cc.clampf(tempPos.x, this.leftBoundary, this.rightBoundary), - cc.clampf(tempPos.y, this.bottomBoundary, this.topBoundary))); + this._target.setPosition(cc.clampf(tempPosX, this.leftBoundary, this.rightBoundary), + cc.clampf(tempPosY, this.bottomBoundary, this.topBoundary)); } else { - this._target.setPosition(cc.pSub(this._halfScreenSize, this._followedNode.getPosition())); + this._target.setPosition(tempPosX, tempPosY); } }, From b6c89966474283f42201a1e3292ec2ee3753408e Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:45:48 +0800 Subject: [PATCH 006/141] Fixed #2441 avoid using temp cc.p for cc.CardinalSplineTo/cc.CardinalSplineBy --- cocos2d/actions/CCActionCatmullRom.js | 73 +++++++++++++++------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/cocos2d/actions/CCActionCatmullRom.js b/cocos2d/actions/CCActionCatmullRom.js index bba06639c0..7407e7a7be 100644 --- a/cocos2d/actions/CCActionCatmullRom.js +++ b/cocos2d/actions/CCActionCatmullRom.js @@ -45,7 +45,7 @@ * @param {Number} t * @return {cc.Point} */ - cc.CardinalSplineAt = function (p0, p1, p2, p3, tension, t) { +cc.CardinalSplineAt = function (p0, p1, p2, p3, tension, t) { var t2 = t * t; var t3 = t2 * t; @@ -69,7 +69,7 @@ * returns a new copy of the array reversed. * @return {Array} */ -cc.reverseControlPoints = function( controlPoints ) { +cc.reverseControlPoints = function (controlPoints) { var newArray = []; for (var i = controlPoints.length - 1; i >= 0; i--) { newArray.push(cc.p(controlPoints[i].x, controlPoints[i].y)); @@ -77,9 +77,9 @@ cc.reverseControlPoints = function( controlPoints ) { return newArray; }; -cc.copyControlPoints = function( controlPoints){ +cc.copyControlPoints = function (controlPoints) { var newArray = []; - for (var i = 0; i< controlPoints.length; i++) + for (var i = 0; i < controlPoints.length; i++) newArray.push(cc.p(controlPoints[i].x, controlPoints[i].y)); return newArray; }; @@ -90,8 +90,8 @@ cc.copyControlPoints = function( controlPoints){ * @param {Number} pos * @return {Array} */ -cc.getControlPointAt = function( controlPoints, pos ) { - var p = Math.min( controlPoints.length-1, Math.max(pos,0)); +cc.getControlPointAt = function (controlPoints, pos) { + var p = Math.min(controlPoints.length - 1, Math.max(pos, 0)); return controlPoints[p]; }; @@ -160,8 +160,8 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * * returns a new clone of the action * @returns {cc.CardinalSplineTo} */ - clone:function(){ - var action = new cc.CardinalSplineTo(); + clone:function () { + var action = new cc.CardinalSplineTo(); action.initWithDuration(this._duration, cc.copyControlPoints(this._points), this._tension); return action; }, @@ -172,7 +172,7 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); // Issue #1441 from cocos2d-iphone - this._deltaT = 1 / (this._points.length-1); + this._deltaT = 1 / (this._points.length - 1); this._previousPosition = this._target.getPosition(); this._accumulatedDiff = cc.p(0, 0); @@ -197,18 +197,21 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * } var newPos = cc.CardinalSplineAt( - cc.getControlPointAt( this._points, p - 1), - cc.getControlPointAt( this._points, p - 0), - cc.getControlPointAt( this._points, p + 1), - cc.getControlPointAt( this._points, p + 2), + cc.getControlPointAt(this._points, p - 1), + cc.getControlPointAt(this._points, p - 0), + cc.getControlPointAt(this._points, p + 1), + cc.getControlPointAt(this._points, p + 2), this._tension, lt); - if(cc.ENABLE_STACKABLE_ACTIONS){ - var node = this._target; - var diff = cc.pSub(node.getPosition(), this._previousPosition); - if (diff.x != 0 || diff.y != 0) { - this._accumulatedDiff = cc.pAdd(this._accumulatedDiff, diff); - newPos = cc.pAdd(newPos, this._accumulatedDiff); + if (cc.ENABLE_STACKABLE_ACTIONS) { + var tempX, tempY; + tempX = this._target.getPositionX() - this._previousPosition.x; + tempY = this._target.getPositionY() - this._previousPosition.y; + if (tempX != 0 || tempY != 0) { + this._accumulatedDiff.x += tempX; + this._accumulatedDiff.y += tempY; + newPos.x += this._accumulatedDiff.x; + newPos.y += this._accumulatedDiff.y; } } this.updatePosition(newPos); @@ -315,20 +318,24 @@ cc.CardinalSplineBy = cc.CardinalSplineTo.extend(/** @lends cc.CardinalSplineBy# } // convert to "diffs" to "reverse absolute" - var reverseArray = cc.reverseControlPoints( copyConfig ); + var reverseArray = cc.reverseControlPoints(copyConfig); // 1st element (which should be 0,0) should be here too p = reverseArray[ reverseArray.length - 1 ]; reverseArray.pop(); - p = cc.pNeg(p); + p.x = -p.x; + p.y = -p.y; + reverseArray.unshift(p); - for (i = 1; i < reverseArray.length; ++i) { + for (var i = 1; i < reverseArray.length; ++i) { current = reverseArray[i]; - current = cc.pNeg(current); - var abs = cc.pAdd(current, p); - reverseArray[i] = abs; - p = abs; + current.x = -current.x; + current.y = -current.y; + current.x += p.x; + current.y += p.y; + reverseArray[i] = current; + p = current; } return cc.CardinalSplineBy.create(this._duration, reverseArray, this._tension); }, @@ -338,16 +345,18 @@ cc.CardinalSplineBy = cc.CardinalSplineTo.extend(/** @lends cc.CardinalSplineBy# * @param {cc.Point} newPos */ updatePosition:function (newPos) { - var p = cc.pAdd(newPos, this._startPosition); - this._target.setPosition(p); - this._previousPosition = p; + var posX = newPos.x + this._startPosition.x; + var posY = newPos.y + this._startPosition.y; + this._target.setPosition(posX, posY); + this._previousPosition.x = posX; + this._previousPosition.y = posY; }, /** * returns a new clone of the action * @returns {cc.CardinalSplineBy} */ - clone:function(){ + clone:function () { var a = new cc.CardinalSplineBy(); a.initWithDuration(this._duration, cc.copyControlPoints(this._points), this._tension); return a; @@ -393,7 +402,7 @@ cc.CatmullRomTo = cc.CardinalSplineTo.extend(/** @lends cc.CatmullRomTo# */{ * returns a new clone of the action * @returns {cc.CatmullRomTo} */ - clone:function(){ + clone:function () { var action = new cc.CatmullRomTo(); action.initWithDuration(this._duration, cc.copyControlPoints(this._points)); return action; @@ -438,7 +447,7 @@ cc.CatmullRomBy = cc.CardinalSplineBy.extend({ * returns a new clone of the action * @returns {cc.CatmullRomBy} */ - clone:function(){ + clone:function () { var action = new cc.CatmullRomBy(); action.initWithDuration(this._duration, cc.copyControlPoints(this._points)); return action; From 1a1736182e9b7c2ad273cfd2168f2258d15442a3 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:48:32 +0800 Subject: [PATCH 007/141] Fixed #2441 avoid using temp cc.p for cc.Grid3DAction --- cocos2d/actions/CCActionGrid3D.js | 113 ++++++++++++++++++------------ 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/cocos2d/actions/CCActionGrid3D.js b/cocos2d/actions/CCActionGrid3D.js index 36eb310623..3a7c812544 100644 --- a/cocos2d/actions/CCActionGrid3D.js +++ b/cocos2d/actions/CCActionGrid3D.js @@ -25,8 +25,8 @@ ****************************************************************************/ cc.RAND_MAX = 0xffffff; -cc.rand = function(){ - return Math.random() * cc.RAND_MAX; +cc.rand = function () { + return Math.random() * cc.RAND_MAX; }; /** * cc.Waves3D action @@ -38,7 +38,7 @@ cc.Waves3D = cc.Grid3DAction.extend(/** @lends cc.Waves3D# */{ _amplitude:null, _amplitudeRate:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._waves = 0; @@ -98,7 +98,7 @@ cc.Waves3D = cc.Grid3DAction.extend(/** @lends cc.Waves3D# */{ update:function (time) { var locGridSize = this._gridSize; - var locAmplitude = this._amplitude, locPos = cc.p(0,0); + var locAmplitude = this._amplitude, locPos = cc.p(0, 0); var locAmplitudeRate = this._amplitudeRate, locWaves = this._waves; for (var i = 0; i < locGridSize.width + 1; ++i) { for (var j = 0; j < locGridSize.height + 1; ++j) { @@ -164,9 +164,11 @@ cc.FlipX3D = cc.Grid3DAction.extend(/** @lends cc.Waves3D# */{ var mx = Math.cos(angle); var diff = new cc.Vertex3F(); - - var v0 = this.originalVertex(cc.p(1, 1)); - var v1 = this.originalVertex(cc.p(0, 0)); + var tempVer = cc.p(0, 0); + tempVer.x = tempVer.y = 1; + var v0 = this.originalVertex(tempVer); + tempVer.x = tempVer.y = 0; + var v1 = this.originalVertex(tempVer); var x0 = v0.x; var x1 = v1.x; @@ -243,8 +245,11 @@ cc.FlipY3D = cc.FlipX3D.extend(/** @lends cc.FlipY3D# */{ var diff = new cc.Vertex3F(); - var v0 = this.originalVertex(cc.p(1, 1)); - var v1 = this.originalVertex(cc.p(0, 0)); + var tempP = cc.p(0, 0); + tempP.x = tempP.y = 1; + var v0 = this.originalVertex(tempP); + tempP.x = tempP.y = 0; + var v1 = this.originalVertex(tempP); var y0 = v0.y; var y1 = v1.y; @@ -322,10 +327,10 @@ cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{ _concave:false, _dirty:false, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); - this._position = null; + this._position = cc.p(0, 0); this._radius = 0; this._lensEffect = 0; this._concave = false; @@ -352,7 +357,7 @@ cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{ * Set whether lens is concave * @param {Boolean} concave */ - setConcave:function(concave){ + setConcave:function (concave) { this._concave = concave; }, @@ -385,7 +390,8 @@ cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{ */ initWithDuration:function (duration, gridSize, position, radius) { if (cc.Grid3DAction.prototype.initWithDuration.call(this, duration, gridSize)) { - this._position = cc.p(-1, -1); + this._position.x = -1; + this._position.y = -1; this.setPosition(position); this._radius = radius; this._lensEffect = 0.7; @@ -399,27 +405,35 @@ cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{ if (this._dirty) { var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height; var locRadius = this._radius, locLensEffect = this._lensEffect; - var locPos = cc.p(0,0); + var locPos = cc.p(0, 0); + var vect = cc.p(0, 0); + var v, r, l, new_r, pre_log; for (var i = 0; i < locGridSizeWidth + 1; ++i) { for (var j = 0; j < locGridSizeHeight + 1; ++j) { locPos.x = i; locPos.y = j; - var v = this.originalVertex(locPos); - var vect = cc.pSub(this._position, v); - var r = cc.pLength(vect); + v = this.originalVertex(locPos); + vect.x = this._position.x - v.x; + vect.y = this._position.y - v.y; + r = cc.pLength(vect); if (r < locRadius) { r = locRadius - r; - var pre_log = r / locRadius; + pre_log = r / locRadius; if (pre_log == 0) pre_log = 0.001; - var l = Math.log(pre_log) * locLensEffect; - var new_r = Math.exp(l) * locRadius; + l = Math.log(pre_log) * locLensEffect; + new_r = Math.exp(l) * locRadius; + + r = cc.pLength(vect); + if (r > 0) { + vect.x = vect.x / r; + vect.y = vect.y / r; - if (cc.pLength(vect) > 0) { - vect = cc.pNormalize(vect); - v.z += cc.pLength(cc.pMult(vect, new_r)) * locLensEffect; + vect.x = vect.x * new_r; + vect.y = vect.y * new_r; + v.z += cc.pLength(vect) * locLensEffect; } } this.setVertex(locPos, v); @@ -457,7 +471,7 @@ cc.Ripple3D = cc.Grid3DAction.extend(/** @lends cc.Ripple3D# */{ _amplitude:null, _amplitudeRate:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._position = null; @@ -539,14 +553,18 @@ cc.Ripple3D = cc.Grid3DAction.extend(/** @lends cc.Ripple3D# */{ update:function (time) { var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height; - var locPos = cc.p(0,0), locRadius = this._radius; + var locPos = cc.p(0, 0), locRadius = this._radius; var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate; + var v, r, tempPos = cc.p(0, 0); for (var i = 0; i < (locGridSizeWidth + 1); ++i) { for (var j = 0; j < (locGridSizeHeight + 1); ++j) { locPos.x = i; locPos.y = j; - var v = this.originalVertex(locPos); - var r = cc.pLength(cc.pSub(this._position, v)); + v = this.originalVertex(locPos); + + tempPos.x = this._position.x - v.x; + tempPos.y = this._position.y - v.y; + r = cc.pLength(tempPos); if (r < locRadius) { r = locRadius - r; @@ -584,7 +602,7 @@ cc.Shaky3D = cc.Grid3DAction.extend(/** @lends cc.Shaky3D# */{ _randRange:null, _shakeZ:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._randRange = 0; @@ -610,12 +628,13 @@ cc.Shaky3D = cc.Grid3DAction.extend(/** @lends cc.Shaky3D# */{ update:function (time) { var locGridSizeWidth = this._gridSize.width, locGridSizeHeight = this._gridSize.height; - var locRandRange = this._randRange, locShakeZ = this._shakeZ, locP = cc.p(0,0); + var locRandRange = this._randRange, locShakeZ = this._shakeZ, locP = cc.p(0, 0); + var v; for (var i = 0; i < (locGridSizeWidth + 1); ++i) { for (var j = 0; j < (locGridSizeHeight + 1); ++j) { locP.x = i; locP.y = j; - var v = this.originalVertex(locP); + v = this.originalVertex(locP); v.x += (cc.rand() % (locRandRange * 2)) - locRandRange; v.y += (cc.rand() % (locRandRange * 2)) - locRandRange; if (locShakeZ) @@ -650,7 +669,7 @@ cc.Liquid = cc.Grid3DAction.extend(/** @lends cc.Liquid# */{ _amplitude:null, _amplitudeRate:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._waves = 0; @@ -709,13 +728,14 @@ cc.Liquid = cc.Grid3DAction.extend(/** @lends cc.Liquid# */{ }, update:function (time) { - var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0,0); + var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0); var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate; + var v; for (var i = 1; i < locSizeWidth; ++i) { for (var j = 1; j < locSizeHeight; ++j) { locPos.x = i; locPos.y = j; - var v = this.originalVertex(locPos); + v = this.originalVertex(locPos); v.x = (v.x + (Math.sin(time * Math.PI * locWaves * 2 + v.x * .01) * locAmplitude * locAmplitudeRate)); v.y = (v.y + (Math.sin(time * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate)); this.setVertex(locPos, v); @@ -750,7 +770,7 @@ cc.Waves = cc.Grid3DAction.extend(/** @lends cc.Waves# */{ _vertical:null, _horizontal:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._waves = 0; @@ -815,14 +835,15 @@ cc.Waves = cc.Grid3DAction.extend(/** @lends cc.Waves# */{ }, update:function (time) { - var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0,0); + var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0); var locVertical = this._vertical, locHorizontal = this._horizontal; var locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate; + var v; for (var i = 0; i < locSizeWidth + 1; ++i) { for (var j = 0; j < locSizeHeight + 1; ++j) { locPos.x = i; locPos.y = j; - var v = this.originalVertex(locPos); + v = this.originalVertex(locPos); if (locVertical) v.x = (v.x + (Math.sin(time * Math.PI * locWaves * 2 + v.y * .01) * locAmplitude * locAmplitudeRate)); if (locHorizontal) @@ -862,7 +883,7 @@ cc.Twirl = cc.Grid3DAction.extend({ _amplitude:null, _amplitudeRate:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._position = null; @@ -933,22 +954,26 @@ cc.Twirl = cc.Grid3DAction.extend({ update:function (time) { var c = this._position; - var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0,0); + var locSizeWidth = this._gridSize.width, locSizeHeight = this._gridSize.height, locPos = cc.p(0, 0); var amp = 0.1 * this._amplitude * this._amplitudeRate; var locTwirls = this._twirls; + var v, a, dX, dY, avg = cc.p(0, 0); for (var i = 0; i < (locSizeWidth + 1); ++i) { for (var j = 0; j < (locSizeHeight + 1); ++j) { locPos.x = i; locPos.y = j; - var v = this.originalVertex(locPos); + v = this.originalVertex(locPos); + + avg.x = i - (locSizeWidth / 2.0); + avg.y = j - (locSizeHeight / 2.0); - var avg = cc.p(i - (locSizeWidth / 2.0), j - (locSizeHeight / 2.0)); + a = cc.pLength(avg) * Math.cos(Math.PI / 2.0 + time * Math.PI * locTwirls * 2) * amp; - var a = cc.pLength(avg) * Math.cos(Math.PI / 2.0 + time * Math.PI * locTwirls * 2) * amp; - var d = cc.p(Math.sin(a) * (v.y - c.y) + Math.cos(a) * (v.x - c.x), Math.cos(a) * (v.y - c.y) - Math.sin(a) * (v.x - c.x)); + dX = Math.sin(a) * (v.y - c.y) + Math.cos(a) * (v.x - c.x); + dY = Math.cos(a) * (v.y - c.y) - Math.sin(a) * (v.x - c.x); - v.x = c.x + d.x; - v.y = c.y + d.y; + v.x = c.x + dX; + v.y = c.y + dY; this.setVertex(locPos, v); } From 53a086d5eb51573f59c2b6cb782a4dc6edd4aeb4 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:52:12 +0800 Subject: [PATCH 008/141] Fixed #2441 avoid using temp cc.p for cc.ActionInterval --- cocos2d/actions/CCActionInterval.js | 271 +++++++++++++++------------- 1 file changed, 147 insertions(+), 124 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 8029c44972..7bc4f0abb9 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -47,7 +47,7 @@ cc.ActionInterval = cc.FiniteTimeAction.extend(/** @lends cc.ActionInterval# */{ _elapsed:0, _firstTick:false, - ctor:function(){ + ctor:function () { cc.FiniteTimeAction.prototype.ctor.call(this); this._elapsed = 0; this._firstTick = false; @@ -85,7 +85,7 @@ cc.ActionInterval = cc.FiniteTimeAction.extend(/** @lends cc.ActionInterval# */{ * returns a new clone of the action * @returns {cc.ActionInterval} */ - clone:function(){ + clone:function () { var action = new cc.ActionInterval(); action.initWithDuration(this._duration); return action; @@ -197,7 +197,7 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ * returns a new clone of the action * @returns {cc.Sequence} */ - clone:function(){ + clone:function () { var action = new cc.Sequence(); action.initOneTwo(this._actions[0].clone(), this._actions[1].clone()); return action; @@ -232,7 +232,7 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ // action[0] new_t = (locSplit) ? time / locSplit : 1; - if(found === 0 && locLast === 1){ + if (found === 0 && locLast === 1) { // Reverse mode ? // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode" // since it will require a hack to know if an action is on reverse mode or not. @@ -259,7 +259,7 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ } // Last action found and it is done. - if(locLast === found && locActions[found].isDone()) + if (locLast === found && locActions[found].isDone()) return; // Last action found and it is done @@ -298,7 +298,7 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ */ cc.Sequence.create = function (/*Multiple Arguments*/tempArray) { var paraArray = (tempArray instanceof Array) ? tempArray : arguments; - if((paraArray.length > 0) && (paraArray[paraArray.length-1] == null)) + if ((paraArray.length > 0) && (paraArray[paraArray.length - 1] == null)) cc.log("parameters should not be ending with null in Javascript"); var prev = paraArray[0]; @@ -334,7 +334,7 @@ cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{ _actionInstant:false, _innerAction:null, //CCFiniteTimeAction - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._times = 0; this._total = 0; @@ -366,7 +366,7 @@ cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{ * returns a new clone of the action * @returns {cc.Repeat} */ - clone:function(){ + clone:function () { var action = new cc.Repeat(); action.initWithAction(this._innerAction.clone(), this._times); return action; @@ -481,7 +481,7 @@ cc.Repeat.create = function (action, times) { cc.RepeatForever = cc.ActionInterval.extend(/** @lends cc.RepeatForever# */{ _innerAction:null, //CCActionInterval - ctor:function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._innerAction = null; }, @@ -501,7 +501,7 @@ cc.RepeatForever = cc.ActionInterval.extend(/** @lends cc.RepeatForever# */{ * returns a new clone of the action * @returns {cc.RepeatForever} */ - clone:function(){ + clone:function () { var action = new cc.RepeatForever(); action.initWithAction(this._innerAction.clone()); return action; @@ -586,7 +586,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ _one:null, _two:null, - ctor: function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._one = null; this._two = null; @@ -625,7 +625,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ * returns a new clone of the action * @returns {cc.Spawn} */ - clone:function(){ + clone:function () { var action = new cc.Spawn(); action.initOneTwo(this._one.clone(), this._two.clone()); return action; @@ -676,7 +676,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ */ cc.Spawn.create = function (/*Multiple Arguments*/tempArray) { var paramArray = (tempArray instanceof Array) ? tempArray : arguments; - if((paramArray.length > 0) && (paramArray[paramArray.length-1] == null)) + if ((paramArray.length > 0) && (paramArray[paramArray.length - 1] == null)) cc.log("parameters should not be ending with null in Javascript"); var prev = paramArray[0]; @@ -715,7 +715,7 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ _startAngleY:0, _diffAngleY:0, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._dstAngleX = 0; this._startAngleX = 0; @@ -745,7 +745,7 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ * returns a new clone of the action * @returns {cc.RotateTo} */ - clone:function(){ + clone:function () { var action = new cc.RotateTo(); action.initWithDuration(this._duration, this._dstAngleX, this._dstAngleY); return action; @@ -760,9 +760,9 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ // Calculate X var locStartAngleX = target.getRotationX() % 360.0; var locDiffAngleX = this._dstAngleX - locStartAngleX; - if(locDiffAngleX > 180) + if (locDiffAngleX > 180) locDiffAngleX -= 360; - if(locDiffAngleX < -180) + if (locDiffAngleX < -180) locDiffAngleX += 360; this._startAngleX = locStartAngleX; this._diffAngleX = locDiffAngleX; @@ -770,11 +770,11 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ // Calculate Y It's duplicated from calculating X since the rotation wrap should be the same this._startAngleY = target.getRotationY() % 360.0; var locDiffAngleY = this._dstAngleY - this._startAngleY; - if(locDiffAngleY > 180) + if (locDiffAngleY > 180) locDiffAngleY -= 360; - if(locDiffAngleY < -180) + if (locDiffAngleY < -180) locDiffAngleY += 360; - this._diffAngleY = locDiffAngleY + this._diffAngleY = locDiffAngleY }, /** @@ -788,7 +788,7 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ * @param {Number} time time in seconds */ update:function (time) { - if (this._target){ + if (this._target) { this._target.setRotationX(this._startAngleX + this._diffAngleX * time); this._target.setRotationY(this._startAngleY + this._diffAngleY * time); } @@ -807,7 +807,7 @@ cc.RotateTo = cc.ActionInterval.extend(/** @lends cc.RotateTo# */{ */ cc.RotateTo.create = function (duration, deltaAngleX, deltaAngleY) { var rotateTo = new cc.RotateTo(); - rotateTo.initWithDuration(duration, deltaAngleX,deltaAngleY); + rotateTo.initWithDuration(duration, deltaAngleX, deltaAngleY); return rotateTo; }; @@ -822,7 +822,7 @@ cc.RotateBy = cc.ActionInterval.extend(/** @lends cc.RotateBy# */{ _angleY:0, _startAngleY:0, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._angleX = 0; this._startAngleX = 0; @@ -849,7 +849,7 @@ cc.RotateBy = cc.ActionInterval.extend(/** @lends cc.RotateBy# */{ * returns a new clone of the action * @returns {cc.RotateBy} */ - clone:function(){ + clone:function () { var action = new cc.RotateBy(); action.initWithDuration(this._duration, this._angleX, this._angleY); return action; @@ -913,7 +913,7 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ _startPosition:null, _previousPosition:null, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._positionDelta = cc.p(0, 0); @@ -938,7 +938,7 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ * returns a new clone of the action * @returns {cc.MoveBy} */ - clone: function () { + clone:function () { var action = new cc.MoveBy(); action.initWithDuration(this._duration, this._positionDelta) return action; @@ -949,9 +949,12 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ */ startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - var locPos = target.getPosition(); - this._previousPosition = cc.p(locPos.x, locPos.y); - this._startPosition = cc.p(locPos.x, locPos.y); + var locPosX = target.getPositionX(); + var locPosY = target.getPositionY(); + this._previousPosition.x = locPosX; + this._previousPosition.y = locPosY; + this._startPosition.x = locPosX; + this._startPosition.y = locPosY; }, /** @@ -959,16 +962,22 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ */ update:function (time) { if (this._target) { - if(cc.ENABLE_STACKABLE_ACTIONS){ - var currentPos = this._target.getPosition(); - var diff = cc.pSub(currentPos, this._previousPosition); - this._startPosition = cc.pAdd(this._startPosition, diff); - var newPos = cc.p(this._startPosition.x + this._positionDelta.x * time, - this._startPosition.y + this._positionDelta.y * time); - this._target.setPosition(newPos); - this._previousPosition = newPos; - } else{ - this._target.setPosition(cc.pAdd(this._startPosition, cc.pMult(this._positionDelta, t))); + var x = this._positionDelta.x * time; + var y = this._positionDelta.y * time; + + if (cc.ENABLE_STACKABLE_ACTIONS) { + var targetX = this._target.getPositionX(); + var targetY = this._target.getPositionY(); + this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; + this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; + x = x + this._startPosition.x; + y = y + this._startPosition.y; + + this._target.setPosition(x, y); + this._previousPosition.x = x; + this._previousPosition.y = y; + } else { + this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); } } }, @@ -977,7 +986,7 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ * MoveTo reverse is not implemented */ reverse:function () { - return cc.MoveBy.create(this._duration, cc.p( -this._positionDelta.x, -this._positionDelta.y)); + return cc.MoveBy.create(this._duration, cc.p(-this._positionDelta.x, -this._positionDelta.y)); } }); @@ -1005,7 +1014,7 @@ cc.MoveBy.create = function (duration, deltaPosition) { */ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ _endPosition:null, - ctor: function () { + ctor:function () { cc.MoveBy.prototype.ctor.call(this); this._endPosition = cc.p(0, 0); }, @@ -1027,7 +1036,7 @@ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ * returns a new clone of the action * @returns {cc.MoveTo} */ - clone: function () { + clone:function () { var action = new cc.MoveTo(); action.initWithDuration(this._duration, this._endPosition); return action; @@ -1038,7 +1047,8 @@ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ */ startWithTarget:function (target) { cc.MoveBy.prototype.startWithTarget.call(this, target); - this._positionDelta = cc.pSub(this._endPosition, target.getPosition()); + this._positionDelta.x = this._endPosition.x - target.getPositionX(); + this._positionDelta.y = this._endPosition.y - target.getPositionY(); } }); /** @@ -1070,7 +1080,7 @@ cc.SkewTo = cc.ActionInterval.extend(/** @lends cc.SkewTo# */{ _deltaX:0, _deltaY:0, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._skewX = 0; this._skewY = 0; @@ -1102,7 +1112,7 @@ cc.SkewTo = cc.ActionInterval.extend(/** @lends cc.SkewTo# */{ * returns a new clone of the action * @returns {cc.SkewTo} */ - clone: function () { + clone:function () { var action = new cc.SkewTo(); action.initWithDuration(this._duration, this._endSkewX, this._endSkewY); return action; @@ -1178,7 +1188,7 @@ cc.SkewBy = cc.SkewTo.extend(/** @lends cc.SkewBy# */{ * returns a new clone of the action * @returns {cc.SkewBy} */ - clone: function () { + clone:function () { var action = new cc.SkewBy(); action.initWithDuration(this._duration, this._skewX, this._skewY); return action; @@ -1230,7 +1240,7 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ _jumps:0, _previousPosition:null, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._startPosition = cc.p(0, 0); this._previousPosition = cc.p(0, 0); @@ -1259,7 +1269,7 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ * returns a new clone of the action * @returns {cc.JumpBy} */ - clone: function () { + clone:function () { var action = new cc.JumpBy(); action.initWithDuration(this._duration, this._delta, this._height, this._jumps); return action; @@ -1270,9 +1280,12 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ */ startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - var locPos = target.getPosition(); - this._previousPosition = cc.p(locPos.x, locPos.y); - this._startPosition = cc.p(locPos.x, locPos.y); + var locPosX = target.getPositionX(); + var locPosY = target.getPositionY(); + this._previousPosition.x = locPosX; + this._previousPosition.y = locPosY; + this._startPosition.x = locPosX; + this._startPosition.y = locPosY; }, /** @@ -1285,16 +1298,19 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ y += this._delta.y * time; var x = this._delta.x * time; - if(cc.ENABLE_STACKABLE_ACTIONS){ - var currentPos = this._target.getPosition(); - - var diff = cc.pSub(currentPos, this._previousPosition); - this._startPosition = cc.pAdd(diff, this._startPosition); - var newPos = cc.pAdd(this._startPosition, cc.p(x, y)); - this._target.setPosition(newPos); - this._previousPosition = newPos; + if (cc.ENABLE_STACKABLE_ACTIONS) { + var targetX = this._target.getPositionX(); + var targetY = this._target.getPositionY(); + this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; + this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; + x = x + this._startPosition.x; + y = y + this._startPosition.y; + + this._target.setPosition(x, y); + this._previousPosition.x = x; + this._previousPosition.y = y; } else { - this._target.setPosition(cc.pAdd(this._startPosition, cc.p(x,y))); + this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); } } }, @@ -1333,14 +1349,15 @@ cc.JumpTo = cc.JumpBy.extend(/** @lends cc.JumpTo# */{ */ startWithTarget:function (target) { cc.JumpBy.prototype.startWithTarget.call(this, target); - this._delta = cc.p(this._delta.x - this._startPosition.x, this._delta.y - this._startPosition.y); + this._delta.x = this._delta.x - this._startPosition.x; + this._delta.y = this._delta.y - this._startPosition.y; }, /** * returns a new clone of the action * @returns {cc.JumpTo} */ - clone: function(){ + clone:function () { var action = new cc.JumpTo(); action.initWithDuration(this._duration, this._delta, this._height, this._jumps); return action; @@ -1384,14 +1401,14 @@ cc.bezierAt = function (a, b, c, d, t) { * @extends cc.ActionInterval */ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ - _config: null, - _startPosition: null, - _previousPosition: null, + _config:null, + _startPosition:null, + _previousPosition:null, /** * Constructor */ - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._config = []; this._startPosition = cc.p(0, 0); @@ -1414,10 +1431,10 @@ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ * returns a new clone of the action * @returns {cc.BezierBy} */ - clone:function(){ + clone:function () { var action = new cc.BezierBy(); var newConfigs = []; - for(var i = 0; i < this._config.length; i++){ + for (var i = 0; i < this._config.length; i++) { var selConf = this._config[i]; newConfigs.push(cc.p(selConf.x, selConf.y)); } @@ -1430,9 +1447,12 @@ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ */ startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); - var locPos = target.getPosition(); - this._previousPosition = cc.p(locPos.x, locPos.y); - this._startPosition = cc.p(locPos.x, locPos.y); + var locPosX = target.getPositionX(); + var locPosY = target.getPositionY(); + this._previousPosition.x = locPosX; + this._previousPosition.y = locPosY; + this._startPosition.x = locPosX; + this._startPosition.y = locPosY; }, /** @@ -1454,16 +1474,18 @@ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ var x = cc.bezierAt(xa, xb, xc, xd, time); var y = cc.bezierAt(ya, yb, yc, yd, time); - if(cc.ENABLE_STACKABLE_ACTIONS){ - var currentPos = this._target.getPosition(); - var diff = cc.pSub(currentPos, this._previousPosition); - this._startPosition = cc.pAdd(this._startPosition, diff); - var newPos = cc.pAdd(this._startPosition, cc.p(x, y)); - - this._target.setPosition(newPos); - this._previousPosition = newPos; + if (cc.ENABLE_STACKABLE_ACTIONS) { + var targetX = this._target.getPositionX(); + var targetY = this._target.getPositionY(); + this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; + this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; + x = x + this._startPosition.x; + y = y + this._startPosition.y; + this._target.setPosition(x, y); + this._previousPosition.x = x; + this._previousPosition.y = y; } else { - this._target.setPosition(cc.pAdd(this._startPosition, cc.p(x,y))); + this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); } } }, @@ -1474,8 +1496,8 @@ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ reverse:function () { var locConfig = this._config; var r = [ - cc.pAdd(locConfig[1], cc.pNeg(locConfig[2]) ), - cc.pAdd(locConfig[0], cc.pNeg(locConfig[2]) ), + cc.pAdd(locConfig[1], cc.pNeg(locConfig[2])), + cc.pAdd(locConfig[0], cc.pNeg(locConfig[2])), cc.pNeg(locConfig[2]) ]; return cc.BezierBy.create(this._duration, r); } @@ -1505,7 +1527,7 @@ cc.BezierBy.create = function (t, c) { cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{ _toConfig:null, - ctor: function () { + ctor:function () { cc.BezierBy.prototype.ctor.call(this); this._toConfig = []; }, @@ -1516,7 +1538,7 @@ cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{ * @return {Boolean} */ initWithDuration:function (t, c) { - if(cc.ActionInterval.prototype.initWithDuration.call(this, t)){ + if (cc.ActionInterval.prototype.initWithDuration.call(this, t)) { this._toConfig = c; return true; } @@ -1527,7 +1549,7 @@ cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{ * returns a new clone of the action * @returns {cc.BezierTo} */ - clone: function () { + clone:function () { var action = new cc.BezierTo(); action.initWithDuration(this._duration, this._toConfig); return action; @@ -1541,6 +1563,7 @@ cc.BezierTo = cc.BezierBy.extend(/** @lends cc.BezierTo# */{ var locStartPos = this._startPosition; var locToConfig = this._toConfig; var locConfig = this._config; + locConfig[0] = cc.pSub(locToConfig[0], locStartPos); locConfig[1] = cc.pSub(locToConfig[1], locStartPos); locConfig[2] = cc.pSub(locToConfig[2], locStartPos); @@ -1577,7 +1600,7 @@ cc.ScaleTo = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{ _deltaX:0, _deltaY:0, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._scaleX = 1; this._scaleY = 1; @@ -1608,7 +1631,7 @@ cc.ScaleTo = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{ * returns a new clone of the action * @returns {cc.ScaleTo} */ - clone: function(){ + clone:function () { var action = new cc.ScaleTo(); action.initWithDuration(this._duration, this._endScaleX, this._endScaleY); return action; @@ -1646,7 +1669,7 @@ cc.ScaleTo = cc.ActionInterval.extend(/** @lends cc.ScaleTo# */{ * // It scales to 0.5 in x and 2 in Y * var actionTo = cc.ScaleTo.create(2, 0.5, 2); */ -cc.ScaleTo.create = function (duration, sx, sy){ //function overload +cc.ScaleTo.create = function (duration, sx, sy) { //function overload var scaleTo = new cc.ScaleTo(); scaleTo.initWithDuration(duration, sx, sy); return scaleTo; @@ -1678,7 +1701,7 @@ cc.ScaleBy = cc.ScaleTo.extend(/** @lends cc.ScaleBy# */{ * returns a new clone of the action * @returns {cc.ScaleBy} */ - clone: function(){ + clone:function () { var action = new cc.ScaleBy(); action.initWithDuration(this._duration, this._endScaleX, this._endScaleY); return action; @@ -1710,7 +1733,7 @@ cc.Blink = cc.ActionInterval.extend(/** @lends cc.Blink# */{ _times:0, _originalState:false, - ctor: function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._times = 0; this._originalState = false; @@ -1733,7 +1756,7 @@ cc.Blink = cc.ActionInterval.extend(/** @lends cc.Blink# */{ * returns a new clone of the action * @returns {cc.Blink} */ - clone: function(){ + clone:function () { var action = new cc.Blink(); action.initWithDuration(this._duration, this._times); return action; @@ -1750,12 +1773,12 @@ cc.Blink = cc.ActionInterval.extend(/** @lends cc.Blink# */{ } }, - startWithTarget:function(target){ + startWithTarget:function (target) { cc.ActionInterval.prototype.startWithTarget.call(this, target); this._originalState = target.isVisible(); }, - stop:function(){ + stop:function () { this._target.setVisible(this._originalState); cc.ActionInterval.prototype.stop.call(this); }, @@ -1805,7 +1828,7 @@ cc.FadeIn = cc.ActionInterval.extend(/** @lends cc.FadeIn# */{ * returns a new clone of the action * @returns {cc.FadeIn} */ - clone: function () { + clone:function () { var action = new cc.FadeIn(); action.initWithDuration(this._duration); return action; @@ -1850,7 +1873,7 @@ cc.FadeOut = cc.ActionInterval.extend(/** @lends cc.FadeOut# */{ * returns a new clone of the action * @returns {cc.FadeOut} */ - clone: function(){ + clone:function () { var action = new cc.FadeOut(); action.initWithDuration(this._duration); return action; @@ -1876,10 +1899,10 @@ cc.FadeOut.create = function (d) { * @extends cc.ActionInterval */ cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{ - _toOpacity: null, - _fromOpacity: null, + _toOpacity:null, + _fromOpacity:null, - ctor: function () { + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._toOpacity = 0; this._fromOpacity = 0; @@ -1902,7 +1925,7 @@ cc.FadeTo = cc.ActionInterval.extend(/** @lends cc.FadeTo# */{ * returns a new clone of the action * @returns {cc.FadeTo} */ - clone: function(){ + clone:function () { var action = new cc.FadeTo(); action.initWithDuration(this._duration, this._toOpacity); return action; @@ -1947,7 +1970,7 @@ cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{ _to:null, _from:null, - ctor: function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._to = cc.c3b(0, 0, 0); this._from = cc.c3b(0, 0, 0); @@ -1972,7 +1995,7 @@ cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{ * returns a new clone of the action * @returns {cc.TintTo} */ - clone:function(){ + clone:function () { var action = new cc.TintTo(); var locTo = this._to; action.initWithDuration(this._duration, locTo.r, locTo.g, locTo.b); @@ -1993,7 +2016,7 @@ cc.TintTo = cc.ActionInterval.extend(/** @lends cc.TintTo# */{ update:function (time) { var locFrom = this._from, locTo = this._to; this._target.setColor(cc.c3b(locFrom.r + (locTo.r - locFrom.r) * time, - (locFrom.g + (locTo.g - locFrom.g) * time),(locFrom.b + (locTo.b - locFrom.b) * time))); + (locFrom.g + (locTo.g - locFrom.g) * time), (locFrom.b + (locTo.b - locFrom.b) * time))); } }); @@ -2027,14 +2050,14 @@ cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{ _fromG:0, _fromB:0, - ctor:function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); - this._deltaR=0; - this._deltaG=0; - this._deltaB=0; - this._fromR=0; - this._fromG=0; - this._fromB=0; + this._deltaR = 0; + this._deltaG = 0; + this._deltaB = 0; + this._fromR = 0; + this._fromG = 0; + this._fromB = 0; }, /** @@ -2058,7 +2081,7 @@ cc.TintBy = cc.ActionInterval.extend(/** @lends cc.TintBy# */{ * returns a new clone of the action * @returns {cc.TintBy} */ - clone: function(){ + clone:function () { var action = new cc.TintBy(); action.initWithDuration(this._duration, this._deltaR, this._deltaG, this._deltaB); return action; @@ -2134,8 +2157,8 @@ cc.DelayTime = cc.ActionInterval.extend(/** @lends cc.DelayTime# */{ * returns a new clone of the action * @returns {cc.DelayTime} */ - clone: function(){ - var action = new cc.DelayTime(); + clone:function () { + var action = new cc.DelayTime(); action.initWithDuration(this._duration); return action; } @@ -2166,7 +2189,7 @@ cc.DelayTime.create = function (d) { cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{ _other:null, - ctor:function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._other = null; }, @@ -2191,7 +2214,7 @@ cc.ReverseTime = cc.ActionInterval.extend(/** @lends cc.ReverseTime# */{ * returns a new clone of the action * @returns {cc.ReverseTime} */ - clone: function(){ + clone:function () { var action = new cc.ReverseTime(); action.initWithAction(this._other.clone()); return action; @@ -2254,13 +2277,13 @@ cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{ _executedLoops:0, _splitTimes:null, - ctor:function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); - this._animation=null; - this._nextFrame=0; - this._origFrame=null; - this._executedLoops=0; - this._splitTimes=null; + this._animation = null; + this._nextFrame = 0; + this._origFrame = null; + this._executedLoops = 0; + this._splitTimes = null; }, /** @@ -2314,7 +2337,7 @@ cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{ * returns a new clone of the action * @returns {cc.Animate} */ - clone: function(){ + clone:function () { var action = new cc.Animate(); action.initWithAnimation(this._animation.clone()); return action; @@ -2356,7 +2379,7 @@ cc.Animate = cc.ActionInterval.extend(/** @lends cc.Animate# */{ if (locSplitTimes[i] <= time) { this._target.setDisplayFrame(frames[i].getSpriteFrame()); this._nextFrame = i + 1; - }else{ + } else { // Issue 1438. Could be more than one frame per tick, due to low frame rate or frame delta < 1/FPS break; } @@ -2421,7 +2444,7 @@ cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{ _action:null, _forcedTarget:null, - ctor: function(){ + ctor:function () { cc.ActionInterval.prototype.ctor.call(this); this._action = null; this._forcedTarget = null; @@ -2446,7 +2469,7 @@ cc.TargetedAction = cc.ActionInterval.extend(/** @lends cc.TargetedAction# */{ * returns a new clone of the action * @returns {cc.TargetedAction} */ - clone:function(){ + clone:function () { var action = new cc.TargetedAction(); action.initWithTarget(this._forcedTarget, this._action.clone()); return action; From 85151f9816b211afb76417938e6398aeb9f202f6 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:52:54 +0800 Subject: [PATCH 009/141] Fixed #2441 avoid using temp cc.p for cc.PageTurn3D --- cocos2d/actions/CCActionPageTurn3D.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cocos2d/actions/CCActionPageTurn3D.js b/cocos2d/actions/CCActionPageTurn3D.js index 0f7980e8a6..7341694a25 100644 --- a/cocos2d/actions/CCActionPageTurn3D.js +++ b/cocos2d/actions/CCActionPageTurn3D.js @@ -52,10 +52,13 @@ cc.PageTurn3D = cc.Grid3DAction.extend(/** @lends cc.PageTurn3D# */{ var cosTheta = Math.cos(theta); var locGridSize = this._gridSize; + var locVer = cc.p(0, 0); for (var i = 0; i <= locGridSize.width; ++i) { for (var j = 0; j <= locGridSize.height; ++j) { + locVer.x = i; + locVer.y = j; // Get original vertex - var p = this.originalVertex(cc.p(i, j)); + var p = this.originalVertex(locVer); var R = Math.sqrt((p.x * p.x) + ((p.y - ay) * (p.y - ay))); var r = R * sinTheta; @@ -82,7 +85,7 @@ cc.PageTurn3D = cc.Grid3DAction.extend(/** @lends cc.PageTurn3D# */{ p.z = 0.5; // Set new coords - this.setVertex(cc.p(i, j), p); + this.setVertex(locVer, p); } } } From e8c71d012328f177e8ebdea111d028de74a429e5 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 11:53:39 +0800 Subject: [PATCH 010/141] Fixed #2441 avoid using temp cc.p for cc.TiledGrid3DAction --- cocos2d/actions/CCActionTiledGrid.js | 107 +++++++++++++++++---------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/cocos2d/actions/CCActionTiledGrid.js b/cocos2d/actions/CCActionTiledGrid.js index da347808a9..4cd0a55bce 100644 --- a/cocos2d/actions/CCActionTiledGrid.js +++ b/cocos2d/actions/CCActionTiledGrid.js @@ -33,7 +33,7 @@ cc.ShakyTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShakyTiles3D# */{ _randRange:0, _shakeZ:false, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._randRange = 0; this._shakeZ = false; @@ -58,9 +58,12 @@ cc.ShakyTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShakyTiles3D# */{ update:function (time) { var locGridSize = this._gridSize, locRandRange = this._randRange; + var locPos = cc.p(0, 0); for (var i = 0; i < locGridSize.width; ++i) { for (var j = 0; j < locGridSize.height; ++j) { - var coords = this.originalTile(cc.p(i, j)); + locPos.x = i; + locPos.y = j; + var coords = this.originalTile(locPos); // X coords.bl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange; @@ -81,7 +84,7 @@ cc.ShakyTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShakyTiles3D# */{ coords.tr.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange; } - this.setTile(cc.p(i, j), coords); + this.setTile(locPos, coords); } } } @@ -111,7 +114,7 @@ cc.ShatteredTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShatteredTiles3D _once:false, _shatterZ:false, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._randRange = 0; this._shakeZ = false; @@ -139,9 +142,12 @@ cc.ShatteredTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShatteredTiles3D update:function (time) { if (this._once === false) { var locGridSize = this._gridSize, locRandRange = this._randRange; + var coords, locPos = cc.p(0, 0); for (var i = 0; i < locGridSize.width; ++i) { for (var j = 0; j < locGridSize.height; ++j) { - var coords = this.originalTile(cc.p(i, j)); + locPos.x = i; + locPos.y = j; + coords = this.originalTile(locPos); // X coords.bl.x += ( cc.rand() % (locRandRange * 2) ) - locRandRange; @@ -161,7 +167,7 @@ cc.ShatteredTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.ShatteredTiles3D coords.tl.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange; coords.tr.z += ( cc.rand() % (locRandRange * 2) ) - locRandRange; } - this.setTile(cc.p(i, j), coords); + this.setTile(locPos, coords); } } this._once = true; @@ -319,11 +325,15 @@ cc.ShuffleTiles = cc.TiledGrid3DAction.extend(/** @lends cc.ShuffleTiles# */{ update:function (time) { var tileIndex = 0, locGridSize = this._gridSize, locTiles = this._tiles; + var selTile, locPos = cc.p(0, 0); for (var i = 0; i < locGridSize.width; ++i) { for (var j = 0; j < locGridSize.height; ++j) { - var selTile = locTiles[tileIndex]; - selTile.position = cc.pMult(cc.p(selTile.delta.width, selTile.delta.height), time); - this.placeTile(cc.p(i, j), selTile); + locPos.x = i; + locPos.y = j; + selTile = locTiles[tileIndex]; + selTile.position.x = selTile.delta.width * time; + selTile.position.y = selTile.delta.height * time; + this.placeTile(locPos, selTile); ++tileIndex; } } @@ -354,10 +364,11 @@ cc.FadeOutTRTiles = cc.TiledGrid3DAction.extend(/** @lends cc.FadeOutTRTiles# */ * @param {Number} time */ testFunc:function (pos, time) { - var n = cc.pMult(cc.p(this._gridSize.width, this._gridSize.height), time); - if ((n.x + n.y) == 0.0) + var locX = this._gridSize.width * time; + var locY = this._gridSize.height * time; + if ((locX + locY) == 0.0) return 1.0; - return Math.pow((pos.width + pos.height) / (n.x + n.y), 6); + return Math.pow((pos.width + pos.height) / (locX + locY), 6); }, /** @@ -402,15 +413,20 @@ cc.FadeOutTRTiles = cc.TiledGrid3DAction.extend(/** @lends cc.FadeOutTRTiles# */ update:function (time) { var locGridSize = this._gridSize; + var locPos = cc.p(0, 0), locSize = cc.size(0, 0), distance; for (var i = 0; i < locGridSize.width; ++i) { for (var j = 0; j < locGridSize.height; ++j) { - var distance = this.testFunc(cc.SizeMake(i, j), time); + locPos.x = i; + locPos.y = j; + locSize.width = i; + locSize.height = j; + distance = this.testFunc(locSize, time); if (distance == 0) - this.turnOffTile(cc.p(i, j)); + this.turnOffTile(locPos); else if (distance < 1) - this.transformTile(cc.p(i, j), distance); + this.transformTile(locPos, distance); else - this.turnOnTile(cc.p(i, j)); + this.turnOnTile(locPos); } } } @@ -439,11 +455,12 @@ cc.FadeOutBLTiles = cc.FadeOutTRTiles.extend(/** @lends cc.FadeOutBLTiles# */{ * @param {Number} time */ testFunc:function (pos, time) { - var n = cc.pMult(cc.p(this._gridSize.width, this._gridSize.height), (1.0 - time)); + var locX = this._gridSize.width * (1.0 - time); + var locY = this._gridSize.height * (1.0 - time); if ((pos.width + pos.height) == 0) return 1.0; - return Math.pow((n.x + n.y) / (pos.width + pos.height), 6); + return Math.pow((locX + locY) / (pos.width + pos.height), 6); } }); @@ -466,10 +483,10 @@ cc.FadeOutBLTiles.create = function (duration, gridSize) { */ cc.FadeOutUpTiles = cc.FadeOutTRTiles.extend(/** @lends cc.FadeOutUpTiles# */{ testFunc:function (pos, time) { - var n = cc.pMult(cc.p(this._gridSize.width, this._gridSize.height), time); - if (n.y == 0.0) + var locY = this._gridSize.height * time; + if (locY == 0.0) return 1.0; - return Math.pow(pos.height / n.y, 6); + return Math.pow(pos.height / locY, 6); }, transformTile:function (pos, distance) { @@ -504,10 +521,10 @@ cc.FadeOutUpTiles.create = function (duration, gridSize) { */ cc.FadeOutDownTiles = cc.FadeOutUpTiles.extend(/** @lends cc.FadeOutDownTiles# */{ testFunc:function (pos, time) { - var n = cc.pMult(cc.p(this._gridSize.width, this._gridSize.height), (1.0 - time)); + var locY = this._gridSize.height * (1.0 - time); if (pos.height == 0) return 1.0; - return Math.pow(n.y / pos.height, 6); + return Math.pow(locY / pos.height, 6); } }); @@ -603,9 +620,11 @@ cc.TurnOffTiles = cc.TiledGrid3DAction.extend(/** @lends cc.TurnOffTiles# */{ */ update:function (time) { var l = 0 | (time * this._tilesCount), locGridSize = this._gridSize; + var t,tilePos = cc.p(0,0); for (var i = 0; i < this._tilesCount; i++) { - var t = this._tilesOrder[i]; - var tilePos = cc.p(0 | (t / locGridSize.height), t % (0 | locGridSize.height)); + t = this._tilesOrder[i]; + tilePos.x = 0 | (t / locGridSize.height); + tilePos.y = t % (0 | locGridSize.height); if (i < l) this.turnOffTile(tilePos); else @@ -645,7 +664,7 @@ cc.WavesTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.WavesTiles3D# */{ _amplitude:0, _amplitudeRate:0, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._waves = 0; this._amplitude = 0; @@ -704,15 +723,18 @@ cc.WavesTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.WavesTiles3D# */{ update:function (time) { var locGridSize = this._gridSize, locWaves = this._waves, locAmplitude = this._amplitude, locAmplitudeRate = this._amplitudeRate; + var locPos = cc.p(0, 0), coords; for (var i = 0; i < locGridSize.width; i++) { for (var j = 0; j < locGridSize.height; j++) { - var coords = this.originalTile(cc.p(i, j)); + locPos.x = i; + locPos.y = j; + coords = this.originalTile(locPos); coords.bl.z = (Math.sin(time * Math.PI * locWaves * 2 + (coords.bl.y + coords.bl.x) * 0.01) * locAmplitude * locAmplitudeRate); coords.br.z = coords.bl.z; coords.tl.z = coords.bl.z; coords.tr.z = coords.bl.z; - this.setTile(cc.p(i, j), coords); + this.setTile(locPos, coords); } } } @@ -742,7 +764,7 @@ cc.JumpTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.JumpTiles3D# */{ _amplitude:0, _amplitudeRate:0, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._jumps = 0; this._amplitude = 0; @@ -804,11 +826,14 @@ cc.JumpTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.JumpTiles3D# */{ var locGridSize = this._gridSize; var locGrid = this._target.getGrid(); + var coords, locPos = cc.p(0, 0); for (var i = 0; i < locGridSize.width; i++) { for (var j = 0; j < locGridSize.height; j++) { + locPos.x = i; + locPos.y = j; //hack for html5 //var coords = this.originalTile(cc.p(i, j)); - var coords = locGrid.originalTile(cc.p(i, j)); + coords = locGrid.originalTile(locPos); if (((i + j) % 2) == 0) { coords.bl.z += sinz; @@ -823,7 +848,7 @@ cc.JumpTiles3D = cc.TiledGrid3DAction.extend(/** @lends cc.JumpTiles3D# */{ } //hack for html5 //this.setTile(cc.p(i, j), coords); - locGrid.setTile(cc.p(i, j), coords); + locGrid.setTile(locPos, coords); } } } @@ -852,7 +877,7 @@ cc.SplitRows = cc.TiledGrid3DAction.extend(/** @lends cc.SplitRows# */{ _rows:0, _winSize:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._rows = 0; this._winSize = null; @@ -871,9 +896,11 @@ cc.SplitRows = cc.TiledGrid3DAction.extend(/** @lends cc.SplitRows# */{ update:function (time) { var locGridSize = this._gridSize, locWinSizeWidth = this._winSize.width; + var coords, direction, locPos = cc.p(0, 0); for (var j = 0; j < locGridSize.height; ++j) { - var coords = this.originalTile(cc.p(0, j)); - var direction = 1; + locPos.y = j; + coords = this.originalTile(locPos); + direction = 1; if ((j % 2 ) == 0) direction = -1; @@ -883,7 +910,7 @@ cc.SplitRows = cc.TiledGrid3DAction.extend(/** @lends cc.SplitRows# */{ coords.tl.x += direction * locWinSizeWidth * time; coords.tr.x += direction * locWinSizeWidth * time; - this.setTile(cc.p(0, j), coords); + this.setTile(locPos, coords); } }, @@ -914,7 +941,7 @@ cc.SplitCols = cc.TiledGrid3DAction.extend(/** @lends cc.SplitCols# */{ _cols:0, _winSize:null, - ctor:function(){ + ctor:function () { cc.GridAction.prototype.ctor.call(this); this._cols = 0; this._winSize = null; @@ -932,9 +959,11 @@ cc.SplitCols = cc.TiledGrid3DAction.extend(/** @lends cc.SplitCols# */{ update:function (time) { var locGridSizeWidth = this._gridSize.width, locWinSizeHeight = this._winSize.height; + var coords, direction, locPos = cc.p(0, 0); for (var i = 0; i < locGridSizeWidth; ++i) { - var coords = this.originalTile(cc.p(i, 0)); - var direction = 1; + locPos.x = i; + coords = this.originalTile(locPos); + direction = 1; if ((i % 2 ) == 0) direction = -1; @@ -944,7 +973,7 @@ cc.SplitCols = cc.TiledGrid3DAction.extend(/** @lends cc.SplitCols# */{ coords.tl.y += direction * locWinSizeHeight * time; coords.tr.y += direction * locWinSizeHeight * time; - this.setTile(cc.p(i, 0), coords); + this.setTile(locPos, coords); } }, From cfbbdd78bdae481d881144b756f7fe73696e0c05 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 31 Jul 2013 14:22:13 +0800 Subject: [PATCH 011/141] Issue #2445 refactor code for rendering classes --- cocos2d/base_nodes/CCNode.js | 201 ++++++++++------------ cocos2d/kazmath/mat4.js | 3 +- cocos2d/label_nodes/CCLabelTTF.js | 64 ++----- cocos2d/platform/CCApplication.js | 4 +- cocos2d/sprite_nodes/CCAnimation.js | 6 +- cocos2d/sprite_nodes/CCAnimationCache.js | 1 - cocos2d/sprite_nodes/CCSprite.js | 172 +++--------------- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 148 +++++++--------- cocos2d/sprite_nodes/CCSpriteFrame.js | 10 +- 9 files changed, 198 insertions(+), 411 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 553ec00c9b..0b34abf088 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -48,9 +48,6 @@ cc.NODE_ON_EXIT = null; cc.s_globalOrderOfArrival = 1; - -//cc.NodeBase = cc.Class.extend(/** @lends cc.Node# */{ - /**

cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.
The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu. (WebGL implement)

@@ -160,6 +157,9 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ _componentContainer:null, _isTransitionFinished:false, + _rotationRadiansX: 0, + _rotationRadiansY: 0, + _initNode:function () { this._anchorPoint = cc.p(0, 0); this._anchorPointInPoints = cc.p(0, 0); @@ -250,7 +250,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * set the dirty node */ setNodeDirty:function () { - this._transformDirty = this._inverseDirty = true; + if(this._transformDirty === false) + this._transformDirty = this._inverseDirty = true; }, /** @@ -384,8 +385,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ return this._rotationX; }, - _rotationRadiansX: 0, - _rotationRadiansY: 0, /** *

* Sets the rotation (angle) of the node in degrees.
@@ -527,31 +526,24 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * node.setPosition( cc.p(size.width/2, size.height/2) ) */ setPosition:function (newPosOrxValue, yValue) { + var locPosition = this._position; if (arguments.length == 2) { - this._position = new cc.Point(newPosOrxValue, yValue); + locPosition.x = newPosOrxValue; + locPosition.y = yValue; } else if (arguments.length == 1) { - this._position = new cc.Point(newPosOrxValue.x, newPosOrxValue.y); - } - this.setNodeDirty(); - }, - - _setPositionByValue:function (newPosOrxValue, yValue) { - if (arguments.length == 2) { - this._position.x = newPosOrxValue; - this._position.y = yValue; - } else if (arguments.length == 1) { - this._position.x = newPosOrxValue.x; - this._position.y = newPosOrxValue.y; + locPosition.x = newPosOrxValue.x; + locPosition.y = newPosOrxValue.y; } this.setNodeDirty(); }, /** *

Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner.

+ * @const * @return {cc.Point} */ getPosition:function () { - return cc.p(this._position.x, this._position.y); + return this._position; //cc.p(this._position.x, this._position.y); }, /** @@ -634,10 +626,11 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
* But you can use values higher than (1,1) and lower than (0,0) too.
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node.

+ * @const * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { - return cc.p(this._anchorPoint.x, this._anchorPoint.y); + return this._anchorPoint; //cc.p(this._anchorPoint.x, this._anchorPoint.y); }, /** @@ -653,9 +646,13 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @param {cc.Point} point The anchor point of node. */ setAnchorPoint:function (point) { - if (!cc.pointEqualToPoint(point, this._anchorPoint)) { - this._anchorPoint = new cc.Point(point.x, point.y); - this._anchorPointInPoints = new cc.Point(this._contentSize.width * point.x, this._contentSize.height * point.y); + var locAnchorPoint = this._anchorPoint; + if (!cc.pointEqualToPoint(point, locAnchorPoint)) { + locAnchorPoint.x = point.x; + locAnchorPoint.y = point.y; + var locAPP = this._anchorPointInPoints, locSize = this._contentSize; + locAPP.x = locSize.width * point.x; + locAPP.y = locSize.height * point.y; this.setNodeDirty(); } }, @@ -664,20 +661,22 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * The anchorPoint in absolute pixels.
* you can only read it. If you wish to modify it, use anchorPoint instead * @see getAnchorPoint() + * @const * @return {cc.Point} The anchor point in absolute pixels. */ getAnchorPointInPoints:function () { - return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); + return this._anchorPointInPoints; //cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); }, /** *

The untransformed size of the node.
* The contentSize remains the same no matter the node is scaled or rotated.
* All nodes has a size. Layer and Scene has the same size of the screen.

+ * @const * @return {cc.Size} The untransformed size of the node. */ getContentSize:function () { - return cc.size(this._contentSize.width, this._contentSize.height); + return this._contentSize; //cc.size(this._contentSize.width, this._contentSize.height); }, /** @@ -690,9 +689,13 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @param {cc.Size} size The untransformed size of the node. */ setContentSize:function (size) { - if (!cc.sizeEqualToSize(size, this._contentSize)) { - this._contentSize = new cc.Size(size.width, size.height); - this._anchorPointInPoints = new cc.Point(this._contentSize.width * this._anchorPoint.x, this._contentSize.height * this._anchorPoint.y); + var locContentSize = this._contentSize; + if (!cc.sizeEqualToSize(size, locContentSize)) { + locContentSize.width = size.width; + locContentSize.height = size.height; + var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint; + locAPP.x = locContentSize.width * locAnchorPoint.x; + locAPP.y = locContentSize.height * locAnchorPoint.y; this.setNodeDirty(); } }, @@ -915,6 +918,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * Returns a "local" axis aligned bounding box of the node.
* The returned box is relative only to its parent. * @note This method returns a temporaty variable, so it can't returns const CCRect& + * @const * @return {cc.Rect} */ getBoundingBox:function () { @@ -1688,7 +1692,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ if (!this._visible) return; var context = cc.renderContext, i, currentStack = cc.current_stack; - this._stackMatrix = this._stackMatrix || new cc.kmMat4(); + //cc.kmGLPushMatrixWitMat4(this._stackMatrix); //optimize performance for javascript currentStack.stack.push(currentStack.top); @@ -1737,12 +1741,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ transform:function () { //optimize performance for javascript var t4x4 = this._transform4x4, topMat4 = cc.current_stack.top; - if(!t4x4){ - t4x4 = new cc.kmMat4(); - t4x4.mat[2] = t4x4.mat[3] = t4x4.mat[6] = t4x4.mat[7] = t4x4.mat[8] = t4x4.mat[9] = t4x4.mat[11] = t4x4.mat[14] = 0.0; - t4x4.mat[10] = t4x4.mat[15] = 1.0; - this._transform4x4 = t4x4; - } // Convert 3x3 into 4x4 matrix //cc.CGAffineToGL(this.nodeToParentTransform(), this._transform4x4.mat); @@ -1839,13 +1837,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ return this._transform; }, - /** - * set the dirty node - */ - setNodeDirty:function () { - this._transformDirty = this._inverseDirty = true; - }, - /** * Returns a camera object that lets you move the node using a gluLookAt * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt @@ -1917,25 +1908,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ } }); -/** - * cc.Node's state callback type - * @constant - * @type Number - */ -cc.NodeWebGL.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7}; - -/** - * allocates and initializes a node. - * @constructs - * @return {cc.NodeWebGL} - * @example - * // example - * var node = cc.NodeWebGL.create(); - */ -cc.NodeWebGL.create = function () { - return new cc.NodeWebGL(); -}; - /**

cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.
The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu. (Canvas implement)

@@ -2039,6 +2011,9 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ _componentContainer:null, _isTransitionFinished:false, + _rotationRadiansX:0, + _rotationRadiansY:0, + _initNode:function () { this._anchorPoint = cc.p(0, 0); this._anchorPointInPoints = cc.p(0, 0); @@ -2125,13 +2100,6 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ } }, - /** - * set the dirty node - */ - setNodeDirty:function () { - this._transformDirty = this._inverseDirty = true; - }, - /** *

get the skew degrees in X
* The X skew angle of the node in degrees.
@@ -2263,8 +2231,6 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ return this._rotationX; }, - _rotationRadiansX:0, - _rotationRadiansY:0, /** *

* Sets the rotation (angle) of the node in degrees.
@@ -2405,31 +2371,24 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * node.setPosition( cc.p(size.width/2, size.height/2) ) */ setPosition:function (newPosOrxValue, yValue) { - if (arguments.length === 2) { - this._position = new cc.Point(newPosOrxValue, yValue); - } else if (arguments.length === 1) { - this._position = new cc.Point(newPosOrxValue.x, newPosOrxValue.y); - } - this.setNodeDirty(); - }, - - _setPositionByValue:function (newPosOrxValue, yValue) { - if (arguments.length === 2) { - this._position.x = newPosOrxValue; - this._position.y = yValue; - } else if (arguments.length === 1) { - this._position.x = newPosOrxValue.x; - this._position.y = newPosOrxValue.y; + var locPosition = this._position; + if (arguments.length == 2) { + locPosition.x = newPosOrxValue; + locPosition.y = yValue; + } else if (arguments.length == 1) { + locPosition.x = newPosOrxValue.x; + locPosition.y = newPosOrxValue.y; } this.setNodeDirty(); }, /** *

Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner.

+ * @const * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates */ getPosition:function () { - return cc.p(this._position.x, this._position.y); + return this._position; //cc.p(this._position.x, this._position.y); }, /** @@ -2512,10 +2471,11 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
* But you can use values higher than (1,1) and lower than (0,0) too.
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node.

+ * @const * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { - return cc.p(this._anchorPoint.x, this._anchorPoint.y); + return this._anchorPoint; //cc.p(this._anchorPoint.x, this._anchorPoint.y); }, /** @@ -2531,9 +2491,13 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @param {cc.Point} point The anchor point of node. */ setAnchorPoint:function (point) { - if (!cc.pointEqualToPoint(point, this._anchorPoint)) { - this._anchorPoint = new cc.Point(point.x, point.y); - this._anchorPointInPoints = new cc.Point(this._contentSize.width * point.x, this._contentSize.height * point.y); + var locAnchorPoint = this._anchorPoint; + if (!cc.pointEqualToPoint(point, locAnchorPoint)) { + locAnchorPoint.x = point.x; + locAnchorPoint.y = point.y; + var locAPP = this._anchorPointInPoints, locSize = this._contentSize; + locAPP.x = locSize.width * point.x; + locAPP.y = locSize.height * point.y; this.setNodeDirty(); } }, @@ -2542,20 +2506,22 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * The anchorPoint in absolute pixels.
* you can only read it. If you wish to modify it, use anchorPoint instead * @see getAnchorPoint() + * @const * @return {cc.Point} The anchor point in absolute pixels. */ getAnchorPointInPoints:function () { - return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); + return this._anchorPointInPoints; //cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); }, /** *

The untransformed size of the node.
* The contentSize remains the same no matter the node is scaled or rotated.
* All nodes has a size. Layer and Scene has the same size of the screen.

+ * @const * @return {cc.Size} The untransformed size of the node. */ getContentSize:function () { - return cc.size(this._contentSize.width, this._contentSize.height); + return this._contentSize; //cc.size(this._contentSize.width, this._contentSize.height); }, /** @@ -2568,9 +2534,13 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @param {cc.Size} size The untransformed size of the node. */ setContentSize:function (size) { - if (!cc.sizeEqualToSize(size, this._contentSize)) { - this._contentSize = new cc.Size(size.width, size.height); - this._anchorPointInPoints = new cc.Point(this._contentSize.width * this._anchorPoint.x, this._contentSize.height * this._anchorPoint.y); + var locContentSize = this._contentSize; + if (!cc.sizeEqualToSize(size, locContentSize)) { + locContentSize.width = size.width; + locContentSize.height = size.height; + var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint; + locAPP.x = locContentSize.width * locAnchorPoint.x; + locAPP.y = locContentSize.height * locAnchorPoint.y; this.setNodeDirty(); } }, @@ -3683,7 +3653,8 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setNodeDirty:function () { this._setNodeDirtyForCache(); - this._transformDirty = this._inverseDirty = true; + if(this._transformDirty === false) + this._transformDirty = this._inverseDirty = true; }, _setNodeDirtyForCache:function () { @@ -3717,26 +3688,26 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ } }); -/** - * cc.Node's state callback type - * @constant - * @type Number - */ -cc.NodeCanvas.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7}; +cc.Node = cc.Browser.supportWebGL ? cc.NodeWebGL : cc.NodeCanvas; /** * allocates and initializes a node. * @constructs - * @return {cc.NodeCanvas} + * @return {cc.Node} * @example * // example - * var node = cc.NodeWebGL.create(); + * var node = cc.Node.create(); */ -cc.NodeCanvas.create = function () { - return new cc.NodeCanvas(); +cc.Node.create = function () { + return new cc.Node(); }; -cc.Node = cc.Browser.supportWebGL ? cc.NodeWebGL : cc.NodeCanvas; +/** + * cc.Node's state callback type + * @constant + * @type Number + */ +cc.Node.StateCallbackType = {onEnter:1, onExit:2, cleanup:3, onEnterTransitionDidFinish:4, updateTransform:5, onExitTransitionDidStart:6, sortAllChildren:7}; /** *

@@ -3754,8 +3725,8 @@ cc.Node = cc.Browser.supportWebGL ? cc.NodeWebGL : cc.NodeCanvas; */ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ RGBAProtocol:true, - _displayedOpacity:0, - _realOpacity:0, + _displayedOpacity:255, + _realOpacity:255, _displayedColor:null, _realColor:null, _cascadeColorEnabled:false, @@ -3771,7 +3742,6 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ this._cascadeOpacityEnabled = false; }, - init:function(){ if(cc.Node.prototype.init.call(this)){ this._displayedOpacity = this._realOpacity = 255; @@ -3831,8 +3801,13 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ }, setColor:function(color){ - this._displayedColor = cc.c3b(color.r, color.g, color.b); - this._realColor = cc.c3b(color.r, color.g, color.b); + var locDisplayedColor = this._displayedColor, locRealColor = this._realColor; + locDisplayedColor.r = color.r; + locDisplayedColor.g = color.g; + locDisplayedColor.b = color.b; + locRealColor.r = color.r; + locRealColor.g = color.g; + locRealColor.b = color.b; if (this._cascadeColorEnabled) { var parentColor = cc.white(); diff --git a/cocos2d/kazmath/mat4.js b/cocos2d/kazmath/mat4.js index eed25b2efe..74e88b88e9 100644 --- a/cocos2d/kazmath/mat4.js +++ b/cocos2d/kazmath/mat4.js @@ -27,8 +27,9 @@ /* A 4x4 matrix + mat = | 0 4 8 12 | - mat = | 1 5 9 13 | + | 1 5 9 13 | | 2 6 10 14 | | 3 7 11 15 | */ diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 37c49d5e79..9317c9b566 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -111,7 +111,8 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ }, _setColorStyleStr:function () { - this._colorStyleStr = "rgba(" + this._textFillColor.r + "," + this._textFillColor.g + "," + this._textFillColor.b + ", " + this._realOpacity / 255 + ")"; + var locFillColor = this._textFillColor; + this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._realOpacity / 255 + ")"; }, /** @@ -201,8 +202,8 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._hAlignment = hAlignment; this._vAlignment = vAlignment; this._fontSize = fontSize * cc.CONTENT_SCALE_FACTOR(); - this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); + this._fontStyleStr = this._fontSize + "px '" + fontName + "'"; + this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize); this.setString(strInfo); return true; } @@ -258,9 +259,10 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ if (false === this._shadowEnabled) this._shadowEnabled = true; - if ((this._shadowOffset.width != shadowOffset.width) || (this._shadowOffset.height != shadowOffset.height)) { - this._shadowOffset.width = shadowOffset.width; - this._shadowOffset.height = shadowOffset.height; + var locShadowOffset = this._shadowOffset; + if ((locShadowOffset.width != shadowOffset.width) || (locShadowOffset.height != shadowOffset.height)) { + locShadowOffset.width = shadowOffset.width; + locShadowOffset.height = shadowOffset.height; } if (this._shadowOpacity != shadowOpacity ) @@ -616,42 +618,6 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ } }); -cc.LabelTTFCanvas._textAlign = ["left", "center", "right"]; - -cc.LabelTTFCanvas._textBaseline = ["top", "middle", "bottom"]; - -/** - * creates a cc.LabelTTF from a fontname, alignment, dimension and font size - * @param {String} label - * @param {String} fontName - * @param {Number} fontSize - * @param {cc.Size} dimensions - * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment - * @return {cc.LabelTTF|Null} - * @example - * // Example - * var myLabel = cc.LabelTTF.create('label text', 'Times New Roman', 32, cc.size(32,16), cc.TEXT_ALIGNMENT_LEFT); - */ -cc.LabelTTFCanvas.create = function (/* Multi arguments */) { - var ret = new cc.LabelTTFCanvas(); - if (ret.initWithString(arguments)) - return ret; - return null; -}; - -/** - * Create a label with string and a font definition - * @param {String} text - * @param {cc.FontDefinition} textDefinition - * @return {cc.LabelTTF|Null} - */ -cc.LabelTTFCanvas.createWithFontDefinition = function(text, textDefinition){ - var ret = new cc.LabelTTF(); - if(ret && ret.initWithStringAndTextDefinition(text, textDefinition)) - return ret; - return null; -}; - /** * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels (WebGL implement)
* All features from cc.TextureNode are valid in cc.LabelTTF
@@ -1413,9 +1379,11 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ } }); -cc.LabelTTFWebGL._textAlign = ["left", "center", "right"]; +cc.LabelTTF = (cc.Browser.supportWebGL) ? cc.LabelTTFWebGL : cc.LabelTTFCanvas; + +cc.LabelTTF._textAlign = ["left", "center", "right"]; -cc.LabelTTFWebGL._textBaseline = ["top", "middle", "bottom"]; +cc.LabelTTF._textBaseline = ["top", "middle", "bottom"]; /** * creates a cc.LabelTTF from a fontname, alignment, dimension and font size @@ -1429,8 +1397,8 @@ cc.LabelTTFWebGL._textBaseline = ["top", "middle", "bottom"]; * // Example * var myLabel = cc.LabelTTF.create('label text', 'Times New Roman', 32, cc.size(32,16), cc.TEXT_ALIGNMENT_LEFT); */ -cc.LabelTTFWebGL.create = function (/* Multi arguments */) { - var ret = new cc.LabelTTFWebGL(); +cc.LabelTTF.create = function (/* Multi arguments */) { + var ret = new cc.LabelTTF(); if (ret.initWithString(arguments)) return ret; return null; @@ -1442,15 +1410,13 @@ cc.LabelTTFWebGL.create = function (/* Multi arguments */) { * @param {cc.FontDefinition} textDefinition * @return {cc.LabelTTF|Null} */ -cc.LabelTTFWebGL.createWithFontDefinition = function(text, textDefinition){ +cc.LabelTTF.createWithFontDefinition = function(text, textDefinition){ var ret = new cc.LabelTTF(); if(ret && ret.initWithStringAndTextDefinition(text, textDefinition)) return ret; return null; }; -cc.LabelTTF = (cc.Browser.supportWebGL) ? cc.LabelTTFWebGL : cc.LabelTTFCanvas; - if(cc.USE_LA88_LABELS) cc.LabelTTF._SHADER_PROGRAM = cc.SHADER_POSITION_TEXTURECOLOR; else diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js index d3422b498e..3e86f6310f 100644 --- a/cocos2d/platform/CCApplication.js +++ b/cocos2d/platform/CCApplication.js @@ -94,8 +94,8 @@ cc.WEBGL = 1; cc.drawingUtil = null; /** - * main Canvas 2D Context of game engine - * @type CanvasContext + * main Canvas 2D/3D Context of game engine + * @type CanvasRenderingContext2D|WebGLRenderingContext */ cc.renderContext = null; diff --git a/cocos2d/sprite_nodes/CCAnimation.js b/cocos2d/sprite_nodes/CCAnimation.js index 1e2b817d96..e1cc01cdcb 100644 --- a/cocos2d/sprite_nodes/CCAnimation.js +++ b/cocos2d/sprite_nodes/CCAnimation.js @@ -67,9 +67,9 @@ cc.AnimationFrame = cc.Class.extend(/** @lends cc.AnimationFrame# */{ * @param {object} userInfo */ initWithSpriteFrame:function (spriteFrame, delayUnits, userInfo) { - this.setSpriteFrame(spriteFrame); - this.setDelayUnits(delayUnits); - this.setUserInfo(userInfo); + this._spriteFrame = spriteFrame; + this._delayPerUnit = delayUnits; + this._userInfo = userInfo; return true; }, diff --git a/cocos2d/sprite_nodes/CCAnimationCache.js b/cocos2d/sprite_nodes/CCAnimationCache.js index 5bae6e3379..f6bcf49d30 100644 --- a/cocos2d/sprite_nodes/CCAnimationCache.js +++ b/cocos2d/sprite_nodes/CCAnimationCache.js @@ -36,7 +36,6 @@ * cc.AnimationCache.getInstance().addAnimation(animation,"animation1"); */ cc.AnimationCache = cc.Class.extend(/** @lends cc.AnimationCache# */{ - /** * Adds a cc.Animation with a name. * @param {cc.Animation} animation diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 3f7e2f7856..e62dd0ac31 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -656,6 +656,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ *

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} [scaleY=] * @override */ setScale:function (scale, scaleY) { @@ -1047,22 +1048,23 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ //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()) { + if (this._dirty) { // If it is not visible, or one of its ancestors is not visible, then do nothing: - if (!this._visible || ( this._parent && this._parent != this._batchNode && this._parent._shouldBeHidden)) { + var locParent = this._parent; + if (!this._visible || ( locParent && locParent != this._batchNode && locParent._shouldBeHidden)) { this._shouldBeHidden = true; } else { this._shouldBeHidden = false; - if (!this._parent || this._parent == this._batchNode) { + 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(), this._parent._transformToBatch); + this._transformToBatch = cc.AffineTransformConcat(this.nodeToParentTransform(), locParent._transformToBatch); } } this._recursiveDirty = false; - this.setDirty(false); + this._dirty = false; } // recursively iterate over children @@ -1125,7 +1127,11 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ */ setDisplayFrame:function (newFrame) { this.setNodeDirty(); - this._unflippedOffsetPositionFromCenter = newFrame.getOffset(); + + var frameOffset = newFrame.getOffset(); + this._unflippedOffsetPositionFromCenter.x = frameOffset.x; + this._unflippedOffsetPositionFromCenter.y = frameOffset.y; + var pNewTexture = newFrame.getTexture(); // update texture before updating texture rect if (pNewTexture != this._texture) @@ -1283,140 +1289,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ } }); -/** - *

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

- * @constructs - * @param {HTMLImageElement|HTMLCanvasElement|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. - * @param {cc.Point} offset offset of the texture - * @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)); - * - * //create a sprite with texture and rect and offset - * var sprite3 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320),cc.p(0,0)); - */ -cc.SpriteCanvas.createWithTexture = function (texture, rect, offset) { - var argnum = arguments.length; - var sprite = new cc.SpriteCanvas(); - 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; - - case 3: - /** Creates an sprite with a texture, a rect and offset. */ - // not implement - cc.Assert(0, ""); - 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.SpriteCanvas.create = function (fileName, rect) { - var argnum = arguments.length; - var sprite = new cc.SpriteCanvas(); - if (argnum === 0) { - if (sprite.init()) - return sprite; - } else { - if (sprite && sprite.init(fileName, rect)) - return sprite; - } - return null; -}; - -/** - * Creates a sprite with a sprite frame name - * @param {String} spriteFrameName name - * @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.SpriteCanvas.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.SpriteCanvas(); - if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { - return sprite; - } - return null; -}; - -/** - * Creates a sprite with a sprite frame. - * @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.SpriteCanvas.createWithSpriteFrame = function (spriteFrame) { - var sprite = new cc.SpriteCanvas(); - if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { - return sprite; - } - return null; -}; - /** *

cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) (WebGL implement)
* @@ -2682,6 +2554,8 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } }); +cc.Sprite = cc.Browser.supportWebGL ? cc.SpriteWebGL : cc.SpriteCanvas; + /** *

* Creates a sprite with an exsiting texture contained in a CCTexture2D object
@@ -2705,9 +2579,9 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * //create a sprite with texture and rect and offset * var sprite3 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320),cc.p(0,0)); */ -cc.SpriteWebGL.createWithTexture = function (texture, rect, offset) { +cc.Sprite.createWithTexture = function (texture, rect, offset) { var argnum = arguments.length; - var sprite = new cc.SpriteWebGL(); + var sprite = new cc.Sprite(); switch (argnum) { case 1: /** Creates an sprite with a texture. @@ -2756,9 +2630,9 @@ cc.SpriteWebGL.createWithTexture = function (texture, rect, offset) { * //create a sprite with filename and rect * var sprite2 = cc.Sprite.create("HelloHTML5World.png",cc.rect(0,0,480,320)); */ -cc.SpriteWebGL.create = function (fileName, rect) { +cc.Sprite.create = function (fileName, rect) { var argnum = arguments.length; - var sprite = new cc.SpriteWebGL(); + var sprite = new cc.Sprite(); if (argnum === 0) { if (sprite.init()) return sprite; @@ -2787,7 +2661,7 @@ cc.SpriteWebGL.create = function (fileName, rect) { * //create a sprite with a sprite frame * var sprite = cc.Sprite.createWithSpriteFrameName('grossini_dance_01.png'); */ -cc.SpriteWebGL.createWithSpriteFrameName = function (spriteFrameName) { +cc.Sprite.createWithSpriteFrameName = function (spriteFrameName) { var spriteFrame = null; if (typeof(spriteFrameName) == 'string') { spriteFrame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); @@ -2799,7 +2673,7 @@ cc.SpriteWebGL.createWithSpriteFrameName = function (spriteFrameName) { cc.log("Invalid argument. Expecting string."); return null; } - var sprite = new cc.SpriteWebGL(); + var sprite = new cc.Sprite(); if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { return sprite; } @@ -2822,12 +2696,10 @@ cc.SpriteWebGL.createWithSpriteFrameName = function (spriteFrameName) { * //create a sprite with a sprite frame * var sprite = cc.Sprite.createWithSpriteFrame(spriteFrame); */ -cc.SpriteWebGL.createWithSpriteFrame = function (spriteFrame) { - var sprite = new cc.SpriteWebGL(); +cc.Sprite.createWithSpriteFrame = function (spriteFrame) { + var sprite = new cc.Sprite(); if (sprite && sprite.initWithSpriteFrame(spriteFrame)) { return sprite; } return null; }; - -cc.Sprite = cc.Browser.supportWebGL ? cc.SpriteWebGL : cc.SpriteCanvas; diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index 04e42a2131..d037c01f08 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -78,15 +78,15 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * child.setAtlasIndex(z); // XXX: optimize with a binary search - var i = 0; - if (this._descendants && this._descendants.length > 0) { - for (var index = 0; index < this._descendants.length; index++) { - var obj = this._descendants[index]; + var i = 0, locDescendants = this._descendants; + if (locDescendants && locDescendants.length > 0) { + for (var index = 0; index < locDescendants.length; index++) { + var obj = locDescendants[index]; if (obj && (obj.getAtlasIndex() >= z)) ++i; } } - this._descendants = cc.ArrayAppendObjectToIndex(this._descendants, child, i); + this._descendants = cc.ArrayAppendObjectToIndex(locDescendants, child, i); // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array cc.Node.prototype.addChild.call(this, child, z, aTag); @@ -372,8 +372,9 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * if (fileImage) this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY); - this._renderTexture = cc.RenderTexture.create(cc.canvas.width, cc.canvas.height); - this.setContentSize(cc.size(cc.canvas.width, cc.canvas.height)); + var locCanvas = cc.canvas; + this._renderTexture = cc.RenderTexture.create(locCanvas.width, locCanvas.height); + this.setContentSize(cc.size(locCanvas.width, locCanvas.height)); }, /** @@ -462,7 +463,7 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * sprite.setBatchNode(this); sprite.setDirty(true); - cc.ArrayAppendObject(this._descendants, sprite); + this._descendants.push(sprite); var index = this._descendants.length - 1; sprite.setAtlasIndex(index); @@ -479,15 +480,15 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * removeSpriteFromAtlas:function (sprite) { // Cleanup sprite. It might be reused (issue #569) sprite.setBatchNode(null); - - var index = cc.ArrayGetIndexOfObject(this._descendants, sprite); + var locDescendants = this._descendants; + var index = cc.ArrayGetIndexOfObject(locDescendants, sprite); if (index != -1) { - cc.ArrayRemoveObjectAtIndex(this._descendants, index); + cc.ArrayRemoveObjectAtIndex(locDescendants, index); // update all sprites beyond this one - var len = this._descendants.length; + var len = locDescendants.length; for (; index < len; ++index) { - var s = this._descendants[index]; + var s = locDescendants[index]; s.setAtlasIndex(s.getAtlasIndex() - 1); } } @@ -517,14 +518,15 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * */ setTexture:function (texture) { this._textureForCanvas = texture; - for (var i = 0; i < this._children.length; i++) - this._children[i].setTexture(texture); + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) + locChildren[i].setTexture(texture); }, /** * don't call visit on it's children ( override visit of cc.Node ) * @override - * @param {CanvasContext} ctx + * @param {CanvasRenderingContext2D} ctx */ visit:function (ctx) { var context = ctx || cc.renderContext; @@ -534,31 +536,32 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * context.save(); this.transform(ctx); - var i; + var i, locChildren = this._children; if (this._useCache) { if (this._cacheDirty) { //add dirty region - this._renderTexture.clear(); - this._renderTexture.context.save(); - this._renderTexture.context.translate(this._anchorPointInPoints.x, -(this._anchorPointInPoints.y )); - if (this._children) { + var locRenderTexture = this._renderTexture; + locRenderTexture.clear(); + locRenderTexture.context.save(); + locRenderTexture.context.translate(this._anchorPointInPoints.x, -(this._anchorPointInPoints.y )); + if (locChildren) { this.sortAllChildren(); - for (i = 0; i < this._children.length; i++) { - if (this._children[i]) - this._children[i].visit(this._renderTexture.context); + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) + locChildren[i].visit(locRenderTexture.context); } } - this._renderTexture.context.restore(); + locRenderTexture.context.restore(); this._cacheDirty = false; } // draw RenderTexture this.draw(ctx); } else { - if (this._children) { + if (locChildren) { this.sortAllChildren(); - for (i = 0; i < this._children.length; i++) { - if (this._children[i]) - this._children[i].visit(context); + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) + locChildren[i].visit(context); } } } @@ -602,10 +605,11 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * removeAllChildren:function (cleanup) { // Invalidate atlas index. issue #569 // useSelfRender should be performed on all descendants. issue #1216 - if (this._descendants && this._descendants.length > 0) { - for (var i = 0; i < this._descendants.length; i++) { - if (this._descendants[i]) - this._descendants[i].setBatchNode(null); + var locDescendants = this._descendants; + if (locDescendants && locDescendants.length > 0) { + for (var i = 0; i < locDescendants.length; i++) { + if (locDescendants[i]) + locDescendants[i].setBatchNode(null); } } @@ -615,25 +619,26 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * sortAllChildren:function () { if (this._reorderChildDirty) { - var i = 0, j = 0, length = this._children.length; + var i, j = 0, locChildren = this._children; + var length = locChildren.length; //insertion sort for (i = 1; i < length; i++) { - var tempItem = this._children[i]; + var tempItem = locChildren[i]; j = i - 1; //continue moving element downwards while zOrder is smaller or when zOrder is the same but orderOfArrival is smaller - while (j >= 0 && (tempItem.getZOrder() < this._children[j].getZOrder() || - (tempItem.getZOrder() == this._children[j].getZOrder() && tempItem.getOrderOfArrival() < this._children[j].getOrderOfArrival()))) { - this._children[j + 1] = this._children[j]; + while (j >= 0 && (tempItem.getZOrder() < locChildren[j].getZOrder() || + (tempItem.getZOrder() == locChildren[j].getZOrder() && tempItem.getOrderOfArrival() < locChildren[j].getOrderOfArrival()))) { + locChildren[j + 1] = locChildren[j]; j--; } - this._children[j + 1] = tempItem; + locChildren[j + 1] = tempItem; } //sorted now check all children - if (this._children.length > 0) { + if (locChildren.length > 0) { //first sort all children recursively based on zOrder - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.sortAllChildren); + this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); } this._reorderChildDirty = false; } @@ -641,54 +646,19 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * /** * draw cc.SpriteBatchNode (override draw of cc.Node) - * @param {CanvasContext} ctx + * @param {CanvasRenderingContext2D} ctx */ draw:function (ctx) { var context = ctx || cc.renderContext; //context.globalAlpha = this._opacity / 255; - var pos = cc.p(0 | ( -this._anchorPointInPoints.x), 0 | ( -this._anchorPointInPoints.y)); + var posX = 0 | ( -this._anchorPointInPoints.x), posY = 0 | ( -this._anchorPointInPoints.y); + var locRenderTexture = this._renderTexture; //direct draw image by canvas drawImage - if (this._renderTexture) - context.drawImage(this._renderTexture.getCanvas(), pos.x, -(pos.y + this._renderTexture.getCanvas().height)); + if (locRenderTexture) + context.drawImage(locRenderTexture.getCanvas(), posX, -(posY + locRenderTexture.getCanvas().height)); } }); -/** - *

- * creates a cc.SpriteBatchNodeCanvas with a file image (.png, .jpg etc) with a default capacity of 29 children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr.
- *

- * @param {String} fileImage - * @param {Number} capacity - * @return {cc.SpriteBatchNodeCanvas} - * @example - * //create a SpriteBatchNode - * var parent2 = cc.SpriteBatchNode.create("res/animations/grossini.png", 50); - */ -cc.SpriteBatchNodeCanvas.create = function (fileImage, capacity) { - capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY; - var batchNode = new cc.SpriteBatchNodeCanvas(); - batchNode.init(fileImage, capacity); - return batchNode; -}; - -/** - *

- * creates a cc.SpriteBatchNodeCanvas with a texture2d and a default capacity of 29 children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- *

- * @param {cc.Texture2D} texture - * @param {Number} capacity - * @return {cc.SpriteBatchNodeCanvas} - */ -cc.SpriteBatchNodeCanvas.createWithTexture = function (texture, capacity) { - capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY; - var batchNode = new cc.SpriteBatchNodeCanvas(); - batchNode.initWithTexture(texture, capacity); - return batchNode; -}; - /** *

* In WebGL render mode ,cc.SpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call
@@ -1426,6 +1396,8 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ } }); +cc.SpriteBatchNode = (cc.Browser.supportWebGL)?cc.SpriteBatchNodeWebGL:cc.SpriteBatchNodeCanvas; + /** *

* creates a cc.SpriteBatchNodeCanvas with a file image (.png, .jpg etc) with a default capacity of 29 children.
@@ -1434,14 +1406,14 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ *

* @param {String} fileImage * @param {Number} capacity - * @return {cc.SpriteBatchNodeWebGL} + * @return {cc.SpriteBatchNode} * @example * //create a SpriteBatchNode * var parent2 = cc.SpriteBatchNode.create("res/animations/grossini.png", 50); */ -cc.SpriteBatchNodeWebGL.create = function (fileImage, capacity) { +cc.SpriteBatchNode.create = function (fileImage, capacity) { capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY; - var batchNode = new cc.SpriteBatchNodeWebGL(); + var batchNode = new cc.SpriteBatchNode(); batchNode.init(fileImage, capacity); return batchNode; }; @@ -1453,15 +1425,13 @@ cc.SpriteBatchNodeWebGL.create = function (fileImage, capacity) { *

* @param {cc.Texture2D} texture * @param {Number} capacity - * @return {cc.SpriteBatchNodeWebGL} + * @return {cc.SpriteBatchNode} */ -cc.SpriteBatchNodeWebGL.createWithTexture = function (texture, capacity) { +cc.SpriteBatchNode.createWithTexture = function (texture, capacity) { capacity = capacity || cc.DEFAULT_SPRITE_BATCH_CAPACITY; - var batchNode = new cc.SpriteBatchNodeWebGL(); + var batchNode = new cc.SpriteBatchNode(); batchNode.initWithTexture(texture, capacity); return batchNode; }; -cc.SpriteBatchNode = (cc.Browser.supportWebGL)?cc.SpriteBatchNodeWebGL:cc.SpriteBatchNodeCanvas; - diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 83ba993c6d..8ffd2bf9d6 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -132,6 +132,7 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ /** * get original size of the trimmed image + * @const * @return {cc.Size} */ getOriginalSizeInPixels:function () { @@ -148,10 +149,11 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ /** * get original size of the trimmed image + * @const * @return {cc.Size} */ getOriginalSize:function () { - return cc.size(this._originalSize.width, this._originalSize.height); + return this._originalSize; //cc.size(this._originalSize.width, this._originalSize.height); }, /** @@ -186,10 +188,11 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ /** * Offset getter + * @const * @return {cc.Point} */ getOffset:function () { - return cc.p(this._offset.x, this._offset.y); + return this._offset; //cc.p(this._offset.x, this._offset.y); }, /** @@ -197,7 +200,8 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ * @param {cc.Point} offsets */ setOffset:function (offsets) { - this._offset = offsets; + this._offset.x = offsets.x; + this._offset.y = offsets.y; }, clone: function(){ From ccd4949cfa01ff6bdbb1059834918dc85ab885f1 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 14:29:00 +0800 Subject: [PATCH 012/141] Issue #2441 reduce read accumulatedDiff times in cc.CardinalSplineTo update --- cocos2d/actions/CCActionCatmullRom.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cocos2d/actions/CCActionCatmullRom.js b/cocos2d/actions/CCActionCatmullRom.js index 7407e7a7be..4e0164879a 100644 --- a/cocos2d/actions/CCActionCatmullRom.js +++ b/cocos2d/actions/CCActionCatmullRom.js @@ -208,10 +208,12 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * tempX = this._target.getPositionX() - this._previousPosition.x; tempY = this._target.getPositionY() - this._previousPosition.y; if (tempX != 0 || tempY != 0) { - this._accumulatedDiff.x += tempX; - this._accumulatedDiff.y += tempY; - newPos.x += this._accumulatedDiff.x; - newPos.y += this._accumulatedDiff.y; + tempX = this._accumulatedDiff.x + tempX; + tempY = this._accumulatedDiff.y + tempY; + this._accumulatedDiff.x = tempX; + this._accumulatedDiff.y = tempY; + newPos.x += tempX; + newPos.y += tempY; } } this.updatePosition(newPos); From 1baaf9623ef71c7ba6fe4c24c4ff6ea439a05f76 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 31 Jul 2013 15:15:57 +0800 Subject: [PATCH 013/141] fixed #2454 Fix a bug of EditBox that position is wrong when _resolutionPolicy of EGLView is NOBORDER --- cocos2d/base_nodes/CCdomNode.js | 36 ++++++++++++++++++++++++++++++++- cocos2d/platform/CCEGLView.js | 1 + 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/cocos2d/base_nodes/CCdomNode.js b/cocos2d/base_nodes/CCdomNode.js index 106b194d6e..79da7fbe80 100644 --- a/cocos2d/base_nodes/CCdomNode.js +++ b/cocos2d/base_nodes/CCdomNode.js @@ -294,6 +294,40 @@ cc.DOM.methods = /** @lends cc.DOM# */{ } } }; + +cc.DOM._resetEGLViewDiv = function(){ + var eglViewDiv = cc.$("#EGLViewDiv"); + if(eglViewDiv){ + var eglViewer = cc.EGLView.getInstance(); + var designSize = eglViewer.getDesignResolutionSize(); + var viewPortRect = eglViewer.getViewPortRect(); + var screenSize = eglViewer.getFrameSize(); + var designSizeWidth = designSize.width, designSizeHeight = designSize.height; + if((designSize.width === 0) && (designSize.height === 0)){ + designSizeWidth = screenSize.width; + designSizeHeight = screenSize.height; + } + + var viewPortWidth = viewPortRect.size.width, viewPortHeight = viewPortRect.size.height; + if((viewPortRect.size.width === 0) && (viewPortRect.size.height === 0)){ + viewPortWidth = screenSize.width; + viewPortHeight = screenSize.height; + } + + eglViewDiv.style.position = 'absolute'; + eglViewDiv.style.bottom = 0; + //x.dom.style.display='block'; + eglViewDiv.style.width = designSizeWidth + "px"; + eglViewDiv.style.maxHeight = designSizeHeight + "px"; + eglViewDiv.style.margin = 0; + + eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); + eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 + + (screenSize.width - viewPortWidth ) / 2) + "px"; + eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + } +}; + /** * @function * @private @@ -349,7 +383,7 @@ cc.DOM.parentDOM = function (x) { eglViewDiv.style.maxHeight = designSizeHeight + "px"; eglViewDiv.style.margin = 0; - eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleX()); + eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 + (screenSize.width - viewPortWidth ) / 2) + "px"; eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; diff --git a/cocos2d/platform/CCEGLView.js b/cocos2d/platform/CCEGLView.js index 196e16df8a..eb3d974ef3 100644 --- a/cocos2d/platform/CCEGLView.js +++ b/cocos2d/platform/CCEGLView.js @@ -329,6 +329,7 @@ cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{ director._createStatsLabel(); director.setGLDefaultValues(); } + cc.DOM._resetEGLViewDiv(); }, /** From 007f1d1194a3ad7a5f365190d790871b1f7b777b Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 31 Jul 2013 16:24:35 +0800 Subject: [PATCH 014/141] Issue #2441 add local pointer to reduce read times --- cocos2d/actions/CCActionCatmullRom.js | 31 +++++++------ cocos2d/actions/CCActionEase.js | 11 +++-- cocos2d/actions/CCActionInterval.js | 66 +++++++++++++++------------ 3 files changed, 61 insertions(+), 47 deletions(-) diff --git a/cocos2d/actions/CCActionCatmullRom.js b/cocos2d/actions/CCActionCatmullRom.js index 4e0164879a..1ee9973741 100644 --- a/cocos2d/actions/CCActionCatmullRom.js +++ b/cocos2d/actions/CCActionCatmullRom.js @@ -183,24 +183,25 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * */ update:function (time) { var p, lt; - + var ps = this._points; // eg. // p..p..p..p..p..p..p // 1..2..3..4..5..6..7 // want p to be 1, 2, 3, 4, 5, 6 if (time == 1) { - p = this._points.length - 1; + p = ps.length - 1; lt = 1; } else { - p = 0 | (time / this._deltaT); - lt = (time - this._deltaT * p) / this._deltaT; + var locDT = this._deltaT; + p = 0 | (time / locDT); + lt = (time - locDT * p) / locDT; } var newPos = cc.CardinalSplineAt( - cc.getControlPointAt(this._points, p - 1), - cc.getControlPointAt(this._points, p - 0), - cc.getControlPointAt(this._points, p + 1), - cc.getControlPointAt(this._points, p + 2), + cc.getControlPointAt(ps, p - 1), + cc.getControlPointAt(ps, p - 0), + cc.getControlPointAt(ps, p + 1), + cc.getControlPointAt(ps, p + 2), this._tension, lt); if (cc.ENABLE_STACKABLE_ACTIONS) { @@ -208,10 +209,11 @@ cc.CardinalSplineTo = cc.ActionInterval.extend(/** @lends cc.CardinalSplineTo# * tempX = this._target.getPositionX() - this._previousPosition.x; tempY = this._target.getPositionY() - this._previousPosition.y; if (tempX != 0 || tempY != 0) { - tempX = this._accumulatedDiff.x + tempX; - tempY = this._accumulatedDiff.y + tempY; - this._accumulatedDiff.x = tempX; - this._accumulatedDiff.y = tempY; + var locAccDiff = this._accumulatedDiff; + tempX = locAccDiff.x + tempX; + tempY = locAccDiff.y + tempY; + locAccDiff.x = tempX; + locAccDiff.y = tempY; newPos.x += tempX; newPos.y += tempY; } @@ -347,8 +349,9 @@ cc.CardinalSplineBy = cc.CardinalSplineTo.extend(/** @lends cc.CardinalSplineBy# * @param {cc.Point} newPos */ updatePosition:function (newPos) { - var posX = newPos.x + this._startPosition.x; - var posY = newPos.y + this._startPosition.y; + var pos = this._startPosition; + var posX = newPos.x + pos.x; + var posY = newPos.y + pos.y; this._target.setPosition(posX, posY); this._previousPosition.x = posX; this._previousPosition.y = posY; diff --git a/cocos2d/actions/CCActionEase.js b/cocos2d/actions/CCActionEase.js index 79e5a39b11..6c3dda7314 100644 --- a/cocos2d/actions/CCActionEase.js +++ b/cocos2d/actions/CCActionEase.js @@ -746,19 +746,20 @@ cc.EaseElasticInOut = cc.EaseElastic.extend(/** @lends cc.EaseElasticInOut# */{ */ update:function (time1) { var newT = 0; + var locPeriod = this._period if (time1 === 0 || time1 == 1) { newT = time1; } else { time1 = time1 * 2; - if (!this._period) - this._period = 0.3 * 1.5; + if (!locPeriod) + locPeriod = this._period = 0.3 * 1.5; - var s = this._period / 4; + var s = locPeriod / 4; time1 = time1 - 1; if (time1 < 0) - newT = -0.5 * Math.pow(2, 10 * time1) * Math.sin((time1 - s) * Math.PI * 2 / this._period); + newT = -0.5 * Math.pow(2, 10 * time1) * Math.sin((time1 - s) * Math.PI * 2 / locPeriod); else - newT = Math.pow(2, -10 * time1) * Math.sin((time1 - s) * Math.PI * 2 / this._period) * 0.5 + 1; + newT = Math.pow(2, -10 * time1) * Math.sin((time1 - s) * Math.PI * 2 / locPeriod) * 0.5 + 1; } this._inner.update(newT); }, diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index 7bc4f0abb9..e5096a74f0 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -237,8 +237,8 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ // XXX: Bug. this case doesn't contemplate when _last==-1, found=0 and in "reverse mode" // since it will require a hack to know if an action is on reverse mode or not. // "step" should be overriden, and the "reverseMode" value propagated to inner Sequences. - this._actions[1].update(0); - this._actions[1].stop(); + locActions[1].update(0); + locActions[1].stop(); } } else { // action[1] @@ -397,14 +397,16 @@ cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{ var locInnerAction = this._innerAction; var locDuration = this._duration; var locTimes = this._times; + var locNextDt = this._nextDt; - if (time >= this._nextDt) { - while (time > this._nextDt && this._total < locTimes) { + if (time >= locNextDt) { + while (time > locNextDt && this._total < locTimes) { locInnerAction.update(1); this._total++; locInnerAction.stop(); locInnerAction.startWithTarget(this._target); - this._nextDt += locInnerAction.getDuration() / locDuration; + locNextDt += locInnerAction.getDuration() / locDuration; + this._nextDt = locNextDt; } // fix for issue #1288, incorrect end value of repeat @@ -418,7 +420,7 @@ cc.Repeat = cc.ActionInterval.extend(/** @lends cc.Repeat# */{ locInnerAction.stop(); } else { // issue #390 prevent jerk, use right update - locInnerAction.update(time - (this._nextDt - locInnerAction.getDuration() / locDuration)); + locInnerAction.update(time - (locNextDt - locInnerAction.getDuration() / locDuration)); } } } else { @@ -964,20 +966,22 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ if (this._target) { var x = this._positionDelta.x * time; var y = this._positionDelta.y * time; - + var locStartPosition = this._startPosition; if (cc.ENABLE_STACKABLE_ACTIONS) { var targetX = this._target.getPositionX(); var targetY = this._target.getPositionY(); - this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; - this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; - x = x + this._startPosition.x; - y = y + this._startPosition.y; + var locPreviousPosition = this._previousPosition; + + locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x; + locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y; + x = x + locStartPosition.x; + y = y + locStartPosition.y; this._target.setPosition(x, y); - this._previousPosition.x = x; - this._previousPosition.y = y; + locPreviousPosition.x = x; + locPreviousPosition.y = y; } else { - this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); + this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y); } } }, @@ -1298,19 +1302,22 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ y += this._delta.y * time; var x = this._delta.x * time; + var locStartPosition = this._startPosition; if (cc.ENABLE_STACKABLE_ACTIONS) { var targetX = this._target.getPositionX(); var targetY = this._target.getPositionY(); - this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; - this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; - x = x + this._startPosition.x; - y = y + this._startPosition.y; + var locPreviousPosition = this._previousPosition; + + locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x; + locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y; + x = x + locStartPosition.x; + y = y + locStartPosition.y; this._target.setPosition(x, y); - this._previousPosition.x = x; - this._previousPosition.y = y; + locPreviousPosition.x = x; + locPreviousPosition.y = y; } else { - this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); + this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y); } } }, @@ -1474,18 +1481,21 @@ cc.BezierBy = cc.ActionInterval.extend(/** @lends cc.BezierBy# */{ var x = cc.bezierAt(xa, xb, xc, xd, time); var y = cc.bezierAt(ya, yb, yc, yd, time); + var locStartPosition = this._startPosition; if (cc.ENABLE_STACKABLE_ACTIONS) { var targetX = this._target.getPositionX(); var targetY = this._target.getPositionY(); - this._startPosition.x = this._startPosition.x + targetX - this._previousPosition.x; - this._startPosition.y = this._startPosition.y + targetY - this._previousPosition.y; - x = x + this._startPosition.x; - y = y + this._startPosition.y; + var locPreviousPosition = this._previousPosition; + + locStartPosition.x = locStartPosition.x + targetX - locPreviousPosition.x; + locStartPosition.y = locStartPosition.y + targetY - locPreviousPosition.y; + x = x + locStartPosition.x; + y = y + locStartPosition.y; this._target.setPosition(x, y); - this._previousPosition.x = x; - this._previousPosition.y = y; + locPreviousPosition.x = x; + locPreviousPosition.y = y; } else { - this._target.setPosition(this._startPosition.x + x, this._startPosition.y + y); + this._target.setPosition(locStartPosition.x + x, locStartPosition.y + y); } } }, From 5984f4405918c9f10a02e43036f4324aed10cba1 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 1 Aug 2013 15:01:33 +0800 Subject: [PATCH 015/141] fixed #2445 refactor code for Performance --- cocos2d/CCScheduler.js | 32 +-- cocos2d/base_nodes/CCNode.js | 16 +- cocos2d/draw_nodes/CCDrawNode.js | 83 +++---- cocos2d/label_nodes/CCLabelAtlas.js | 31 +-- .../CCLayer.js | 49 +--- cocos2d/sprite_nodes/CCSpriteFrame.js | 4 +- cocos2d/textures/CCTextureCache.js | 32 +-- .../GUI/CCControlExtension/CCScale9Sprite.js | 221 ++++++++++-------- extensions/GUI/CCScrollView/CCScrollView.js | 186 +++++++++------ extensions/GUI/CCScrollView/CCTableView.js | 101 ++++---- 10 files changed, 371 insertions(+), 384 deletions(-) diff --git a/cocos2d/CCScheduler.js b/cocos2d/CCScheduler.js index 442db0169c..da3ebf5812 100644 --- a/cocos2d/CCScheduler.js +++ b/cocos2d/CCScheduler.js @@ -170,8 +170,8 @@ cc.ArrayContainsObject = function (arr, findObj) { /** * find object from array by target * @param {Array} arr source array - * @param {cc.ListEntry|cc.HashUpdateEntry|cc.HashSelectorEntry} findInt find target - * @return {cc.ListEntry|cc.HashUpdateEntry|cc.HashSelectorEntry} + * @param {cc.ListEntry|cc.HashUpdateEntry} findInt find target + * @return {cc.ListEntry|cc.HashUpdateEntry} */ cc.HASH_FIND_INT = function (arr, findInt) { if (arr == null) { @@ -331,40 +331,43 @@ cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{ this._elapsed = 0; this._timesExecuted = 0; } else { + var locTarget = this._target, locSelector = this._selector; + var locElapsed = this._elapsed; if (this._runForever && !this._useDelay) { //standard timer usage - this._elapsed += dt; + locElapsed += dt; - if (this._elapsed >= this._interval) { - if (this._target && this._selector) + if (locElapsed >= this._interval) { + if (locTarget && locSelector) this._callSelector(); - this._elapsed = 0; + locElapsed = 0; } } else { //advanced usage - this._elapsed += dt; + locElapsed += dt; if (this._useDelay) { - if (this._elapsed >= this._delay) { - if (this._target && this._selector) + if (locElapsed >= this._delay) { + if (locTarget && locSelector) this._callSelector(); - this._elapsed = this._elapsed - this._delay; + locElapsed = locElapsed - this._delay; this._timesExecuted += 1; this._useDelay = false; } } else { - if (this._elapsed >= this._interval) { - if (this._target && this._selector) + if (locElapsed >= this._interval) { + if (locTarget && locSelector) this._callSelector(); - this._elapsed = 0; + locElapsed = 0; this._timesExecuted += 1; } } if (this._timesExecuted > this._repeat) - cc.Director.getInstance().getScheduler().unscheduleCallbackForTarget(this._target, this._selector); + cc.Director.getInstance().getScheduler().unscheduleCallbackForTarget(locTarget, locSelector); } + this._elapsed = locElapsed; } } }); @@ -999,4 +1002,3 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{ } }); - diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 0b34abf088..f567963a09 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -543,7 +543,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @return {cc.Point} */ getPosition:function () { - return this._position; //cc.p(this._position.x, this._position.y); + return cc.p(this._position.x, this._position.y); }, /** @@ -630,7 +630,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { - return this._anchorPoint; //cc.p(this._anchorPoint.x, this._anchorPoint.y); + return cc.p(this._anchorPoint.x, this._anchorPoint.y); }, /** @@ -665,7 +665,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @return {cc.Point} The anchor point in absolute pixels. */ getAnchorPointInPoints:function () { - return this._anchorPointInPoints; //cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); + return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); }, /** @@ -676,7 +676,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * @return {cc.Size} The untransformed size of the node. */ getContentSize:function () { - return this._contentSize; //cc.size(this._contentSize.width, this._contentSize.height); + return cc.size(this._contentSize.width, this._contentSize.height); }, /** @@ -2388,7 +2388,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates */ getPosition:function () { - return this._position; //cc.p(this._position.x, this._position.y); + return cc.p(this._position.x, this._position.y); }, /** @@ -2475,7 +2475,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { - return this._anchorPoint; //cc.p(this._anchorPoint.x, this._anchorPoint.y); + return cc.p(this._anchorPoint.x, this._anchorPoint.y); }, /** @@ -2510,7 +2510,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @return {cc.Point} The anchor point in absolute pixels. */ getAnchorPointInPoints:function () { - return this._anchorPointInPoints; //cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); + return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); }, /** @@ -2521,7 +2521,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ * @return {cc.Size} The untransformed size of the node. */ getContentSize:function () { - return this._contentSize; //cc.size(this._contentSize.width, this._contentSize.height); + return cc.size(this._contentSize.width, this._contentSize.height); }, /** diff --git a/cocos2d/draw_nodes/CCDrawNode.js b/cocos2d/draw_nodes/CCDrawNode.js index 9085aed136..866379fa9e 100644 --- a/cocos2d/draw_nodes/CCDrawNode.js +++ b/cocos2d/draw_nodes/CCDrawNode.js @@ -115,19 +115,19 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ for (var i = 0; i < this._buffer.length; i++) { var element = this._buffer[i]; - if (element.type === cc.DRAWNODE_TYPE_DOT) { + if (element.type === cc.DrawNode.TYPE_DOT) { context.fillStyle = "rgba(" + (0 | (element.color.r * 255)) + "," + (0 | (element.color.g * 255)) + "," + (0 | (element.color.b * 255)) + "," + element.color.a + ")"; cc.drawingUtil.drawPoint(element.position, element.radius); } - if (element.type === cc.DRAWNODE_TYPE_SEGMENT) { + if (element.type === cc.DrawNode.TYPE_SEGMENT) { context.strokeStyle = "rgba(" + (0 | (element.color.r * 255)) + "," + (0 | (element.color.g * 255)) + "," + (0 | (element.color.b * 255)) + "," + element.color.a + ")"; context.lineWidth = element.radius * 2; context.lineCap = "round"; cc.drawingUtil.drawLine(element.from, element.to); } - if (element.type === cc.DRAWNODE_TYPE_POLY) { + if (element.type === cc.DrawNode.TYPE_POLY ) { context.fillStyle = "rgba(" + (0 | (element.fillColor.r * 255)) + "," + (0 | (element.fillColor.g * 255)) + "," + (0 | (element.fillColor.b * 255)) + "," + element.fillColor.a + ")"; cc.drawingUtil.drawPoly(element.verts, element.count, false, true); @@ -147,7 +147,7 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ * @param {cc.Color4F} color */ drawDot:function (pos, radius, color) { - var element = new cc._DrawNodeElement(cc.DRAWNODE_TYPE_DOT); + var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT); element.position = pos; element.radius = radius; element.color = color; @@ -162,7 +162,7 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ * @param {cc.Color4F} color */ drawSegment:function (from, to, radius, color) { - var element = new cc._DrawNodeElement(cc.DRAWNODE_TYPE_SEGMENT); + var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_SEGMENT); element.from = from; element.to = to; element.radius = radius; @@ -178,7 +178,7 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ * @param {cc.Color4F} borderColor */ drawPoly:function (verts, fillColor, borderWidth, borderColor) { - var element = new cc._DrawNodeElement(cc.DRAWNODE_TYPE_POLY); + var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY ); element.verts = verts; element.count = verts.length; element.fillColor = fillColor; @@ -195,17 +195,6 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ } }); -/** - * Creates a DrawNodeCanvas - * @return {cc.DrawNodeCanvas} - */ -cc.DrawNodeCanvas.create = function () { - var ret = new cc.DrawNodeCanvas(); - if (ret && ret.init()) - return ret; - return null; -}; - /** *

CCDrawNode for WebGL
* Node that draws dots, segments and polygons.
@@ -276,20 +265,21 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ _ensureCapacity:function(count){ if(this._buffer.length + count > this._bufferCapacity){ + var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT; this._bufferCapacity += Math.max(this._bufferCapacity, count); //re alloc if((this._buffer == null) || (this._buffer.length === 0)){ //init this._buffer = []; - this._trianglesArrayBuffer = new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT * this._bufferCapacity); + this._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity); this._trianglesReader = new Uint8Array(this._trianglesArrayBuffer); } else { var newTriangles = []; - var newArrayBuffer = new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT * this._bufferCapacity); + var newArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity); for(var i = 0; i < this._buffer.length;i++){ newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(this._buffer[i].a,this._buffer[i].b,this._buffer[i].c, - newArrayBuffer,i * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT); + newArrayBuffer,i * TriangleLength); } this._trianglesReader = new Uint8Array(newArrayBuffer); this._buffer = newTriangles; @@ -351,29 +341,30 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw)); var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw)); + var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer; this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))}, {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)}, {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))}, {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + triangleBuffer, this._buffer.length * TriangleLength)); this._dirty = true; }, @@ -405,14 +396,16 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ var vertexCount = 3 * triangleCount; this._ensureCapacity(vertexCount); + var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer; + var locBuffer = this._buffer; var inset = (outline == false ? 0.5 : 0.0); for (i = 0; i < count - 2; i++) { v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset)); v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset)); v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset)); - this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, + locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + trianglesBuffer, locBuffer.length * triangleBytesLen)); } for (i = 0; i < count; i++) { @@ -429,19 +422,19 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5)); if (outline) { - this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, + locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); - this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, + trianglesBuffer, locBuffer.length * triangleBytesLen)); + locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + trianglesBuffer, locBuffer.length * triangleBytesLen)); } else { - this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, + locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); - this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, + trianglesBuffer, locBuffer.length * triangleBytesLen)); + locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)}, - this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT)); + trianglesBuffer, locBuffer.length * triangleBytesLen)); } } extrude = null; @@ -457,23 +450,23 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ } }); +cc.DrawNode = cc.Browser.supportWebGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas; + /** - * Creates a DrawNodeCanvas - * @return {cc.DrawNodeWebGL} + * Creates a DrawNode + * @return {cc.DrawNode} */ -cc.DrawNodeWebGL.create = function () { - var ret = new cc.DrawNodeWebGL(); +cc.DrawNode.create = function () { + var ret = new cc.DrawNode(); if (ret && ret.init()) return ret; return null; }; -cc.DrawNode = cc.Browser.supportWebGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas; - cc._DrawNodeElement = function (type) { this.type = type; }; -cc.DRAWNODE_TYPE_DOT = 0; -cc.DRAWNODE_TYPE_SEGMENT = 1; -cc.DRAWNODE_TYPE_POLY = 2; +cc.DrawNode.TYPE_DOT = 0; +cc.DrawNode.TYPE_SEGMENT = 1; +cc.DrawNode.TYPE_POLY = 2; diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index aa417c5e58..f04bbbfe8b 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -184,27 +184,6 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ } }); -/** - * It accepts two groups of parameters: - * a) string, fntFile - * b) label, textureFilename, width, height, startChar - * @return {cc.LabelAtlas|Null} returns the LabelAtlas object on success - * @example - * //Example - * //creates the cc.LabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas - * var myLabel = cc.LabelAtlas.create('Text to display', 'CharMapfile.png', 12, 20, ' ') - * - * //creates the cc.LabelAtlas with a string, a fnt file - * var myLabel = cc.LabelAtlas.create('Text to display', 'CharMapFile.plist‘); - */ -cc.LabelAtlasCanvas.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) { - var ret = new cc.LabelAtlasCanvas(); - if (ret && cc.LabelAtlasCanvas.prototype.initWithString.apply(ret,arguments)) { - return ret; - } - return null; -}; - /** * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont (WebGL version) * @class @@ -390,6 +369,8 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ } }); +cc.LabelAtlas = cc.Browser.supportWebGL ? cc.LabelAtlasWebGL : cc.LabelAtlasCanvas; + /** * It accepts two groups of parameters: * a) string, fntFile @@ -408,13 +389,11 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ * //creates the cc.LabelAtlas with a string, a fnt file * var myLabel = cc.LabelAtlas.create('Text to display', 'CharMapFile.plist‘); */ -cc.LabelAtlasWebGL.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) { - var ret = new cc.LabelAtlasWebGL(); - if (ret && cc.LabelAtlasWebGL.prototype.initWithString.apply(ret,arguments)) { +cc.LabelAtlas.create = function (strText, charMapFile, itemWidth, itemHeight, startCharMap) { + var ret = new cc.LabelAtlas(); + if (ret && cc.LabelAtlas.prototype.initWithString.apply(ret,arguments)) { return ret; } return null; }; -cc.LabelAtlas = cc.Browser.supportWebGL ? cc.LabelAtlasWebGL : cc.LabelAtlasCanvas; - diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 2cf2d02271..bb8fa342d6 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -840,7 +840,7 @@ cc.LayerColorCanvas = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ /** * renders the layer - * @param {CanvasContext|Null} ctx + * @param {CanvasRenderingContext2D|Null} ctx */ draw:function (ctx) { var context = ctx || cc.renderContext; @@ -856,41 +856,6 @@ cc.LayerColorCanvas = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ } }); -/** - * creates a cc.LayerColorCanvas with color, width and height in Points - * @param {cc.Color4B} color - * @param {Number|Null} width - * @param {Number|Null} height - * @return {cc.LayerColor} - * @example - * // Example - * //Create a yellow color layer as background - * var yellowBackground = cc.LayerColor.create(cc.c4b(255,255,0,255)); - * //If you didnt pass in width and height, it defaults to the same size as the canvas - * - * //create a yellow box, 200 by 200 in size - * var yellowBox = cc.LayerColorCanvas.create(cc.c3b(255,255,0,255), 200, 200); - */ -cc.LayerColorCanvas.create = function (color, width, height) { - var ret = new cc.LayerColorCanvas(); - switch (arguments.length) { - case 0: - ret.init(); - break; - case 1: - ret.init(color); - break; - case 3: - ret.init(color, width, height); - break; - default : - ret.init(); - break; - } - return ret; -}; - - /** * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. (WebGL implement)
* All features from CCLayer are valid, plus the following new features:
@@ -1098,11 +1063,13 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ } }); +cc.LayerColor = cc.Browser.supportWebGL ? cc.LayerColorWebGL : cc.LayerColorCanvas; + /** * creates a cc.Layer with color, width and height in Points * @param {cc.Color4B} color - * @param {Number|Null} width - * @param {Number|Null} height + * @param {Number|Null} [width=] + * @param {Number|Null} [height=] * @return {cc.LayerColor} * @example * // Example @@ -1113,8 +1080,8 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ * //create a yellow box, 200 by 200 in size * var yellowBox = cc.LayerColor.create(cc.c4b(255,255,0,255), 200, 200); */ -cc.LayerColorWebGL.create = function (color, width, height) { - var ret = new cc.LayerColorWebGL(); +cc.LayerColor.create = function (color, width, height) { + var ret = new cc.LayerColor(); switch (arguments.length) { case 0: ret.init(); @@ -1132,8 +1099,6 @@ cc.LayerColorWebGL.create = function (color, width, height) { return ret; }; -cc.LayerColor = cc.Browser.supportWebGL ? cc.LayerColorWebGL : cc.LayerColorCanvas; - /** *

* CCLayerGradient is a subclass of cc.LayerColor that draws gradients across the background.
diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 8ffd2bf9d6..09aa85ae7f 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -153,7 +153,7 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ * @return {cc.Size} */ getOriginalSize:function () { - return this._originalSize; //cc.size(this._originalSize.width, this._originalSize.height); + return cc.size(this._originalSize.width, this._originalSize.height); }, /** @@ -192,7 +192,7 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ * @return {cc.Point} */ getOffset:function () { - return this._offset; //cc.p(this._offset.x, this._offset.y); + return cc.p(this._offset.x, this._offset.y); }, /** diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index 8b3363e41b..dd7a4b2cde 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -406,23 +406,11 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ }); /** - * Return ths shared instance of the cache - * @return {cc.TextureCache} - */ -cc.TextureCacheCanvas.getInstance = function () { - if (!cc.g_sharedTextureCache) - cc.g_sharedTextureCache = new cc.TextureCacheCanvas(); - return cc.g_sharedTextureCache; -}; - -/** - * Purges the cache. It releases the retained instance. + * Implementation TextureCache (WebGL implement) + * @class + * @extends cc.Class */ -cc.TextureCacheCanvas.purgeSharedTextureCache = function () { - cc.g_sharedTextureCache = null; -}; - -cc.TextureCacheWebGL = cc.Class.extend({ +cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ /// ---- common properties start ---- _textures:null, _textureColorsCache:null, @@ -821,23 +809,21 @@ cc.TextureCacheWebGL = cc.Class.extend({ } }); +cc.TextureCache = cc.Browser.supportWebGL ? cc.TextureCacheWebGL : cc.TextureCacheCanvas; + /** * Return ths shared instance of the cache * @return {cc.TextureCache} */ -cc.TextureCacheWebGL.getInstance = function () { +cc.TextureCache.getInstance = function () { if (!cc.g_sharedTextureCache) - cc.g_sharedTextureCache = new cc.TextureCacheWebGL(); + cc.g_sharedTextureCache = new cc.TextureCache(); return cc.g_sharedTextureCache; }; /** * Purges the cache. It releases the retained instance. */ -cc.TextureCacheWebGL.purgeSharedTextureCache = function () { +cc.TextureCache.purgeSharedTextureCache = function () { cc.g_sharedTextureCache = null; }; - -cc.TextureCache = cc.Browser.supportWebGL ? cc.TextureCacheWebGL : cc.TextureCacheCanvas; - - diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 2b1b1fd5fa..4e33fc42c3 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -82,16 +82,18 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ _spriteFrameRotated: false, _updateCapInset: function () { - var insets; - if (this._insetLeft == 0 && this._insetTop == 0 && this._insetRight == 0 && this._insetBottom == 0) { + var insets, locInsetLeft = this._insetLeft, locInsetTop = this._insetTop, locInsetRight = this._insetRight; + var locSpriteRect = this._spriteRect, locInsetBottom = this._insetBottom; + if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) { insets = cc.RectZero(); } else { - insets = this._spriteFrameRotated ? cc.RectMake(this._insetBottom, this._insetLeft, - this._spriteRect.width - this._insetRight - this._insetLeft, - this._spriteRect.height - this._insetTop - this._insetBottom) : - cc.RectMake(this._insetLeft, this._insetTop, - this._spriteRect.width - this._insetLeft - this._insetRight, - this._spriteRect.height - this._insetTop - this._insetBottom); + + insets = this._spriteFrameRotated ? cc.RectMake(locInsetBottom, locInsetLeft, + locSpriteRect.width - locInsetRight - locInsetLeft, + locSpriteRect.height - locInsetTop - locInsetBottom) : + cc.RectMake(locInsetLeft, locInsetTop, + locSpriteRect.width - locInsetLeft - locInsetRight, + locSpriteRect.height - locInsetTop - locInsetBottom); } this.setCapInsets(insets); }, @@ -105,64 +107,70 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ } var size = this._contentSize; - var sizableWidth = size.width - this._topLeft.getContentSize().width - this._topRight.getContentSize().width; - var sizableHeight = size.height - this._topLeft.getContentSize().height - this._bottomRight.getContentSize().height; - var horizontalScale = sizableWidth / this._centre.getContentSize().width; - var verticalScale = sizableHeight / this._centre.getContentSize().height; - var rescaledWidth = this._centre.getContentSize().width * horizontalScale; - var rescaledHeight = this._centre.getContentSize().height * verticalScale; + var locTopLeft = this._topLeft, locTopRight = this._topRight, locBottomRight = this._bottomRight; + var locCenter = this._centre, locCenterContentSize = this._centre.getContentSize(); + + var sizableWidth = size.width - locTopLeft.getContentSize().width - locTopRight.getContentSize().width; + var sizableHeight = size.height - locTopLeft.getContentSize().height - locBottomRight.getContentSize().height; + var horizontalScale = sizableWidth / locCenterContentSize.width; + var verticalScale = sizableHeight / locCenterContentSize.height; + var rescaledWidth = locCenterContentSize.width * horizontalScale; + var rescaledHeight = locCenterContentSize.height * verticalScale; - var leftWidth = this._bottomLeft.getContentSize().width; - var bottomHeight = this._bottomLeft.getContentSize().height; + var locBottomLeft = this._bottomLeft; + var leftWidth = locBottomLeft.getContentSize().width; + var bottomHeight = locBottomLeft.getContentSize().height; if(!cc.Browser.supportWebGL) { //browser is in canvas mode, need to manually control rounding to prevent overlapping pixels var roundedRescaledWidth = Math.round(rescaledWidth); if(rescaledWidth != roundedRescaledWidth) { rescaledWidth = roundedRescaledWidth; - horizontalScale = rescaledWidth/this._centre.getContentSize().width; + horizontalScale = rescaledWidth/locCenterContentSize.width; } var roundedRescaledHeight = Math.round(rescaledHeight); if(rescaledHeight != roundedRescaledHeight) { rescaledHeight = roundedRescaledHeight; - verticalScale = rescaledHeight/this._centre.getContentSize().height; + verticalScale = rescaledHeight/locCenterContentSize.height; } } - this._centre.setScaleX(horizontalScale); - this._centre.setScaleY(verticalScale); - - this._bottomLeft.setAnchorPoint(cc.p(0, 0)); - this._bottomRight.setAnchorPoint(cc.p(0, 0)); - this._topLeft.setAnchorPoint(cc.p(0, 0)); - this._topRight.setAnchorPoint(cc.p(0, 0)); - this._left.setAnchorPoint(cc.p(0, 0)); - this._right.setAnchorPoint(cc.p(0, 0)); - this._top.setAnchorPoint(cc.p(0, 0)); - this._bottom.setAnchorPoint(cc.p(0, 0)); - this._centre.setAnchorPoint(cc.p(0, 0)); + locCenter.setScaleX(horizontalScale); + locCenter.setScaleY(verticalScale); + + var locLeft = this._left, locRight = this._right, locTop = this._top, locBottom = this._bottom; + var tempAP = cc.p(0, 0); + locBottomLeft.setAnchorPoint(tempAP); + locBottomRight.setAnchorPoint(tempAP); + locTopLeft.setAnchorPoint(tempAP); + locTopRight.setAnchorPoint(tempAP); + locLeft.setAnchorPoint(tempAP); + locRight.setAnchorPoint(tempAP); + locTop.setAnchorPoint(tempAP); + locBottom.setAnchorPoint(tempAP); + locCenter.setAnchorPoint(tempAP); // Position corners - this._bottomLeft.setPosition(cc.p(0, 0)); - this._bottomRight.setPosition(cc.p(leftWidth + rescaledWidth, 0)); - this._topLeft.setPosition(cc.p(0, bottomHeight + rescaledHeight)); - this._topRight.setPosition(cc.p(leftWidth + rescaledWidth, bottomHeight + rescaledHeight)); + locBottomLeft.setPosition(0, 0); + locBottomRight.setPosition(leftWidth + rescaledWidth, 0); + locTopLeft.setPosition(0, bottomHeight + rescaledHeight); + locTopRight.setPosition(leftWidth + rescaledWidth, bottomHeight + rescaledHeight); // Scale and position borders - this._left.setPosition(cc.p(0, bottomHeight)); - this._left.setScaleY(verticalScale); - this._right.setPosition(cc.p(leftWidth + rescaledWidth, bottomHeight)); - this._right.setScaleY(verticalScale); - this._bottom.setPosition(cc.p(leftWidth, 0)); - this._bottom.setScaleX(horizontalScale); - this._top.setPosition(cc.p(leftWidth, bottomHeight + rescaledHeight)); - this._top.setScaleX(horizontalScale); + locLeft.setPosition(0, bottomHeight); + locLeft.setScaleY(verticalScale); + locRight.setPosition(leftWidth + rescaledWidth, bottomHeight); + locRight.setScaleY(verticalScale); + locBottom.setPosition(leftWidth, 0); + locBottom.setScaleX(horizontalScale); + locTop.setPosition(leftWidth, bottomHeight + rescaledHeight); + locTop.setScaleX(horizontalScale); // Position centre - this._centre.setPosition(cc.p(leftWidth, bottomHeight)); + locCenter.setPosition(leftWidth, bottomHeight); }, ctor: function () { - this._super(); + cc.Node.prototype.ctor.call(this); this._spriteRect = cc.RectZero(); this._capInsetsInternal = cc.RectZero(); @@ -196,9 +204,9 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ this._opacity = opacity; var scaleChildren = this._scale9Image.getChildren(); for (var i = 0; i < scaleChildren.length; i++) { - if (scaleChildren[i] && scaleChildren[i].RGBAProtocol) { - scaleChildren[i].setOpacity(this._opacity); - } + var selChild = scaleChildren[i]; + if (selChild && selChild.RGBAProtocol) + selChild.setOpacity(opacity); } }, @@ -210,9 +218,9 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ this._color = color; var scaleChildren = this._scale9Image.getChildren(); for (var i = 0; i < scaleChildren.length; i++) { - if (scaleChildren[i] && scaleChildren[i].RGBAProtocol) { - scaleChildren[i].setColor(this._color); - } + var selChild = scaleChildren[i]; + if (selChild && selChild.RGBAProtocol) + selChild.setColor(color); } }, @@ -443,10 +451,11 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ if (this._scale9Image != batchNode) this._scale9Image = batchNode; - this._scale9Image.removeAllChildren(true); + var locScale9Image = this._scale9Image; + locScale9Image.removeAllChildren(true); this._capInsets = capInsets; - var selTexture = this._scale9Image.getTexture(); + var selTexture = locScale9Image.getTexture(); var rectZero = cc.RectZero(); // If there is no given rect @@ -463,24 +472,36 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ // Set the given rect's size as original size this._spriteRect = rect; var rectSize = rect.size; - this._originalSize = new cc.Size(rectSize.width, rectSize.height); - this._preferredSize = new cc.Size(rectSize.width, rectSize.height); - this._capInsetsInternal = capInsets || cc.RectZero(); + this._originalSize.width = rectSize.width; + this._originalSize.height = rectSize.height; + this._preferredSize.width = rectSize.width; + this._preferredSize.height = rectSize.height; + + var locCapInsetsInternal = this._capInsetsInternal; + if(!capInsets){ + locCapInsetsInternal.x = capInsets.x; + locCapInsetsInternal.y = capInsets.y; + locCapInsetsInternal.width = capInsets.width; + locCapInsetsInternal.height = capInsets.height; + } var w = rectSize.width; var h = rectSize.height; // If there is no specified center region - if (cc.rectEqualToRect(this._capInsetsInternal, rectZero)) { + if (cc.rectEqualToRect(locCapInsetsInternal, rectZero)) { // CCLog("... cap insets not specified : using default cap insets ..."); - this._capInsetsInternal = cc.rect(w / 3, h / 3, w / 3, h / 3); + locCapInsetsInternal.x = w / 3; + locCapInsetsInternal.y = h / 3; + locCapInsetsInternal.width = w / 3; + locCapInsetsInternal.height = h / 3; } - var left_w = this._capInsetsInternal.x; - var center_w = this._capInsetsInternal.width; + var left_w = locCapInsetsInternal.x; + var center_w = locCapInsetsInternal.width; var right_w = w - (left_w + center_w); - var top_h = this._capInsetsInternal.y; - var center_h = this._capInsetsInternal.height; + var top_h = locCapInsetsInternal.y; + var center_h = locCapInsetsInternal.height; var bottom_h = h - (top_h + center_h); // calculate rects @@ -532,9 +553,9 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ x += center_w; var rightbottombounds = cc.RectMake(x, y, right_w, bottom_h); + var t = cc.AffineTransformMakeIdentity(); if (!rotated) { // CCLog("!rotated"); - var t = cc.AffineTransformMakeIdentity(); t = cc.AffineTransformTranslate(t, rect.x, rect.y); centerbounds = cc.RectApplyAffineTransform(centerbounds, t); @@ -550,55 +571,52 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ // Centre this._centre = new cc.Sprite(); this._centre.initWithTexture(selTexture, centerbounds); - this._scale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE); + locScale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE); // Top this._top = new cc.Sprite(); this._top.initWithTexture(selTexture, centertopbounds); - this._scale9Image.addChild(this._top, 1, cc.POSITIONS_TOP); + locScale9Image.addChild(this._top, 1, cc.POSITIONS_TOP); // Bottom this._bottom = new cc.Sprite(); this._bottom.initWithTexture(selTexture, centerbottombounds); - this._scale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM); + locScale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM); // Left this._left = new cc.Sprite(); this._left.initWithTexture(selTexture, leftcenterbounds); - this._scale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT); + locScale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT); // Right this._right = new cc.Sprite(); this._right.initWithTexture(selTexture, rightcenterbounds); - this._scale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT); + locScale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT); // Top left this._topLeft = new cc.Sprite(); this._topLeft.initWithTexture(selTexture, lefttopbounds); - this._scale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT); + locScale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT); // Top right this._topRight = new cc.Sprite(); this._topRight.initWithTexture(selTexture, righttopbounds); - this._scale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT); + locScale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT); // Bottom left this._bottomLeft = new cc.Sprite(); this._bottomLeft.initWithTexture(selTexture, leftbottombounds); - this._scale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT); + locScale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT); // Bottom right this._bottomRight = new cc.Sprite(); this._bottomRight.initWithTexture(selTexture, rightbottombounds); - this._scale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT); + locScale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT); } else { // set up transformation of coordinates // to handle the case where the sprite is stored rotated // in the spritesheet // CCLog("rotated"); - - var t = cc.AffineTransformMakeIdentity(); - var rotatedcenterbounds = centerbounds; var rotatedrightbottombounds = rightbottombounds; var rotatedleftbottombounds = leftbottombounds; @@ -622,64 +640,81 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ centerbottombounds = cc.RectApplyAffineTransform(centerbottombounds, t); centertopbounds = cc.RectApplyAffineTransform(centertopbounds, t); - rotatedcenterbounds.origin = {x: centerbounds.x, y: centerbounds.y}; - rotatedrightbottombounds.origin = {x: rightbottombounds.x, y: rightbottombounds.y}; - rotatedleftbottombounds.origin = {x: leftbottombounds.x, y: leftbottombounds.y}; - rotatedrighttopbounds.origin = {x: righttopbounds.x, y: righttopbounds.y}; - rotatedlefttopbounds.origin = {x: lefttopbounds.x, y: lefttopbounds.y}; - rotatedrightcenterbounds.origin = {x: rightcenterbounds.x, y: rightcenterbounds.y}; - rotatedleftcenterbounds.origin = {x: leftcenterbounds.x, y: leftcenterbounds.y}; - rotatedcenterbottombounds.origin = {x: centerbottombounds.x, y: centerbottombounds.y}; - rotatedcentertopbounds.origin = {x: centertopbounds.x, y: centertopbounds.y}; + rotatedcenterbounds.x = centerbounds.x; + rotatedcenterbounds.y = centerbounds.y; + + rotatedrightbottombounds.x = rightbottombounds.x; + rotatedrightbottombounds.y = rightbottombounds.y; + + rotatedleftbottombounds.x = leftbottombounds.x; + rotatedleftbottombounds.y = leftbottombounds.y; + + rotatedrighttopbounds.x = righttopbounds.x; + rotatedrighttopbounds.y = righttopbounds.y; + + rotatedlefttopbounds.x = lefttopbounds.x; + rotatedlefttopbounds.y = lefttopbounds.y; + + rotatedrightcenterbounds.x = rightcenterbounds.x; + rotatedrightcenterbounds.y = rightcenterbounds.y; + + rotatedleftcenterbounds.x = leftcenterbounds.x; + rotatedleftcenterbounds.y = leftcenterbounds.y; + + rotatedcenterbottombounds.x = centerbottombounds.x; + rotatedcenterbottombounds.y = centerbottombounds.y; + + rotatedcentertopbounds.x = centertopbounds.x; + rotatedcentertopbounds.y = centertopbounds.y; // Centre this._centre = new cc.Sprite(); this._centre.initWithTexture(selTexture, rotatedcenterbounds, true); - this._scale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE); + locScale9Image.addChild(this._centre, 0, cc.POSITIONS_CENTRE); // Top this._top = new cc.Sprite(); this._top.initWithTexture(selTexture, rotatedcentertopbounds, true); - this._scale9Image.addChild(this._top, 1, cc.POSITIONS_TOP); + locScale9Image.addChild(this._top, 1, cc.POSITIONS_TOP); // Bottom this._bottom = new cc.Sprite(); this._bottom.initWithTexture(selTexture, rotatedcenterbottombounds, true); - this._scale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM); + locScale9Image.addChild(this._bottom, 1, cc.POSITIONS_BOTTOM); // Left this._left = new cc.Sprite(); this._left.initWithTexture(selTexture, rotatedleftcenterbounds, true); - this._scale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT); + locScale9Image.addChild(this._left, 1, cc.POSITIONS_LEFT); // Right this._right = new cc.Sprite(); this._right.initWithTexture(selTexture, rotatedrightcenterbounds, true); - this._scale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT); + locScale9Image.addChild(this._right, 1, cc.POSITIONS_RIGHT); // Top left this._topLeft = new cc.Sprite(); this._topLeft.initWithTexture(selTexture, rotatedlefttopbounds, true); - this._scale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT); + locScale9Image.addChild(this._topLeft, 2, cc.POSITIONS_TOPLEFT); // Top right this._topRight = new cc.Sprite(); this._topRight.initWithTexture(selTexture, rotatedrighttopbounds, true); - this._scale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT); + locScale9Image.addChild(this._topRight, 2, cc.POSITIONS_TOPRIGHT); // Bottom left this._bottomLeft = new cc.Sprite(); this._bottomLeft.initWithTexture(selTexture, rotatedleftbottombounds, true); - this._scale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT); + locScale9Image.addChild(this._bottomLeft, 2, cc.POSITIONS_BOTTOMLEFT); // Bottom right this._bottomRight = new cc.Sprite(); this._bottomRight.initWithTexture(selTexture, rotatedrightbottombounds, true); - this._scale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT); + locScale9Image.addChild(this._bottomRight, 2, cc.POSITIONS_BOTTOMRIGHT); } this.setContentSize(rect.size); - this.addChild(this._scale9Image); + this.addChild(locScale9Image); if (this._spritesGenerated) { // Restore color and opacity diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index a384204931..670cffbadd 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -79,14 +79,20 @@ cc.ScrollView = cc.Layer.extend({ _parentScissorRect:null, _scissorRestored:false, + // cache object + _tmpViewRect:null, + ctor:function () { - this._super(); + cc.Layer.prototype.ctor.call(this); + this._contentOffset = new cc.Point(0,0); this._maxInset = new cc.Point(0, 0); this._minInset = new cc.Point(0, 0); this._scrollDistance = new cc.Point(0, 0); this._touchPoint = new cc.Point(0, 0); this._touches = []; this._viewSize = new cc.Size(0, 0); + this._parentScissorRect = new cc.Rect(0,0,0,0); + this._tmpViewRect = new cc.Rect(0,0,0,0); }, init:function () { @@ -104,26 +110,27 @@ cc.ScrollView = cc.Layer.extend({ * @return {Boolean} */ initWithViewSize:function (size, container) { + var pZero = cc.p(0,0); if (cc.Layer.prototype.init.call(this)) { this._container = container; if (!this._container) { this._container = cc.Layer.create(); this._container.ignoreAnchorPointForPosition(false); - this._container.setAnchorPoint(cc.p(0.0, 0.0)); + this._container.setAnchorPoint(pZero); } this.setViewSize(size); this.setTouchEnabled(true); - this._touches = []; + this._touches.length = 0; this._delegate = null; this._bounceable = true; this._clippingToBounds = true; //this._container.setContentSize(CCSizeZero); this._direction = cc.SCROLLVIEW_DIRECTION_BOTH; - this._container.setPosition(cc.p(0.0, 0.0)); + this._container.setPosition(pZero); this._touchLength = 0.0; this.addChild(this._container); @@ -137,7 +144,7 @@ cc.ScrollView = cc.Layer.extend({ * Sets a new content offset. It ignores max/min offset. It just sets what's given. (just like UIKit's UIScrollView) * * @param {cc.Point} offset new offset - * @param {Number} animated If YES, the view scrolls to the new offset + * @param {Number} [animated=] If YES, the view scrolls to the new offset */ setContentOffset:function (offset, animated) { if (animated) { //animate scrolling @@ -152,8 +159,9 @@ cc.ScrollView = cc.Layer.extend({ } this._container.setPosition(offset); - if (this._delegate != null && this._delegate.scrollViewDidScroll) { - this._delegate.scrollViewDidScroll(this); + var locDelegate = this._delegate; + if (locDelegate != null && locDelegate.scrollViewDidScroll) { + locDelegate.scrollViewDidScroll(this); } } }, @@ -184,7 +192,8 @@ cc.ScrollView = cc.Layer.extend({ */ setZoomScale:function (scale, animated) { if (arguments.length === 1) { - if (this._container.getScale() != scale) { + var locContainer = this._container; + if (locContainer.getScale() != scale) { var oldCenter, newCenter; var center; @@ -194,15 +203,15 @@ cc.ScrollView = cc.Layer.extend({ } else center = this._touchPoint; - oldCenter = this._container.convertToNodeSpace(center); - this._container.setScale(Math.max(this._minScale, Math.min(this._maxScale, scale))); - newCenter = this._container.convertToWorldSpace(oldCenter); + oldCenter = locContainer.convertToNodeSpace(center); + locContainer.setScale(Math.max(this._minScale, Math.min(this._maxScale, scale))); + newCenter = locContainer.convertToWorldSpace(oldCenter); var offset = cc.pSub(center, newCenter); if (this._delegate != null) { this._delegate.scrollViewDidZoom(this); } - this.setContentOffset(cc.pAdd(this._container.getPosition(), offset)); + this.setContentOffset(cc.pAdd(locContainer.getPosition(), offset)); } } else if (arguments.length === 2) { if (animated) @@ -237,8 +246,9 @@ cc.ScrollView = cc.Layer.extend({ * Returns the current container's minimum offset. You may want this while you animate scrolling by yourself */ minContainerOffset:function () { - return cc.p(this._viewSize.width - this._container.getContentSize().width * this._container.getScaleX(), - this._viewSize.height - this._container.getContentSize().height * this._container.getScaleY()); + var locContentSize = this._container.getContentSize(); + return cc.p(this._viewSize.width - locContentSize.width * this._container.getScaleX(), + this._viewSize.height - locContentSize.height * this._container.getScaleY()); }, /** @@ -260,7 +270,7 @@ cc.ScrollView = cc.Layer.extend({ var viewRect = cc.RectMake(-offset.x / scale, -offset.y / scale, size.width / scale, size.height / scale); - return cc.CCRectIntersectsRect(viewRect, node.getBoundingBox()); + return cc.rectIntersectsRect(viewRect, node.getBoundingBox()); }, /** @@ -362,25 +372,28 @@ cc.ScrollView = cc.Layer.extend({ var frame = this._getViewRect(); //dispatcher does not know about clipping. reject touches outside visible bounds. - var locPoint = this._container.convertToWorldSpace(this._container.convertTouchToNodeSpace(touch)); - if (this._touches.length > 2 || this._touchMoved || !cc.rectContainsPoint(frame, locPoint)) + var locContainer = this._container; + var locPoint = locContainer.convertToWorldSpace(locContainer.convertTouchToNodeSpace(touch)); + var locTouches = this._touches; + if (locTouches.length > 2 || this._touchMoved || !cc.rectContainsPoint(frame, locPoint)) return false; //if (!cc.ArrayContainsObject(this._touches, touch)) { - this._touches.push(touch); + locTouches.push(touch); //} - if (this._touches.length == 1) { // scrolling + if (locTouches.length == 1) { // scrolling this._touchPoint = this.convertTouchToNodeSpace(touch); this._touchMoved = false; this._dragging = true; //dragging started - this._scrollDistance = cc.p(0.0, 0.0); + this._scrollDistance.x = 0; + this._scrollDistance.y = 0; this._touchLength = 0.0; - } else if (this._touches.length == 2) { - this._touchPoint = cc.pMidpoint(this.convertTouchToNodeSpace(this._touches[0]), - this.convertTouchToNodeSpace(this._touches[1])); - this._touchLength = cc.pDistance(this._container.convertTouchToNodeSpace(this._touches[0]), - this._container.convertTouchToNodeSpace(this._touches[1])); + } else if (locTouches.length == 2) { + this._touchPoint = cc.pMidpoint(this.convertTouchToNodeSpace(locTouches[0]), + this.convertTouchToNodeSpace(locTouches[1])); + this._touchLength = cc.pDistance(locContainer.convertTouchToNodeSpace(locTouches[0]), + locContainer.convertTouchToNodeSpace(locTouches[1])); this._dragging = false; } return true; @@ -407,7 +420,7 @@ cc.ScrollView = cc.Layer.extend({ else if (this._direction === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) dis = moveDistance.x; else - dis = Math.sqrt(moveDistance.x * moveDistance.x + moveDistance.y*moveDistance.y); + dis = Math.sqrt(moveDistance.x * moveDistance.x + moveDistance.y * moveDistance.y); if (!this._touchMoved && Math.abs(cc.convertDistanceFromPointToInch(dis)) < MOVE_INCH ){ //CCLOG("Invalid movement, distance = [%f, %f], disInch = %f", moveDistance.x, moveDistance.y); @@ -425,22 +438,23 @@ cc.ScrollView = cc.Layer.extend({ if (cc.rectContainsPoint(frame, this.convertToWorldSpace(newPoint))) { switch (this._direction) { case cc.SCROLLVIEW_DIRECTION_VERTICAL: - moveDistance = cc.p(0.0, moveDistance.y); + moveDistance.x = 0.0; break; case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: - moveDistance = cc.p(moveDistance.x, 0.0); + moveDistance.y = 0.0; break; default: break; } - var newX = this._container.getPosition().x + moveDistance.x; - var newY = this._container.getPosition().y + moveDistance.y; + var locPosition = this._container.getPosition(); + var newX = locPosition.x + moveDistance.x; + var newY = locPosition.y + moveDistance.y; this._scrollDistance = moveDistance; this.setContentOffset(cc.p(newX, newY)); } - } else if (this._touches.length == 2 && !this._dragging) { + } else if (this._touches.length === 2 && !this._dragging) { var len = cc.pDistance(this._container.convertTouchToNodeSpace(this._touches[0]), this._container.convertTouchToNodeSpace(this._touches[1])); this.setZoomScale(this.getZoomScale() * len / this._touchLength); @@ -481,12 +495,13 @@ cc.ScrollView = cc.Layer.extend({ updateInset:function () { if (this.getContainer() != null) { - this._maxInset = this.maxContainerOffset(); - this._maxInset = cc.p(this._maxInset.x + this._viewSize.width * INSET_RATIO, - this._maxInset.y + this._viewSize.height * INSET_RATIO); - this._minInset = this.minContainerOffset(); - this._minInset = cc.p(this._minInset.x - this._viewSize.width * INSET_RATIO, - this._minInset.y - this._viewSize.height * INSET_RATIO); + var locViewSize = this._viewSize; + var tempOffset = this.maxContainerOffset(); + this._maxInset.x = tempOffset.x + locViewSize.width * INSET_RATIO; + this._maxInset.y = tempOffset.y + locViewSize.height * INSET_RATIO; + tempOffset = this.minContainerOffset(); + this._minInset.x = tempOffset.x - locViewSize.width * INSET_RATIO; + this._minInset.y = tempOffset.y - locViewSize.height * INSET_RATIO; } }, @@ -507,18 +522,20 @@ cc.ScrollView = cc.Layer.extend({ return; var context = ctx || cc.renderContext; - var i; + var i, locChildren = this._children, selChild, childrenLen; if (cc.renderContextType === cc.CANVAS) { context.save(); this.transform(context); this._beforeDraw(context); - if (this._children && this._children.length > 0) { + if (locChildren && locChildren.length > 0) { + childrenLen = locChildren.length; this.sortAllChildren(); // draw children zOrder < 0 - for (i = 0; i < this._children.length; i++) { - if (this._children[i] && this._children[i]._zOrder < 0) - this._children[i].visit(context); + for (i = 0; i < childrenLen; i++) { + selChild = locChildren[i]; + if (selChild && selChild._zOrder < 0) + selChild.visit(context); else break; } @@ -526,12 +543,8 @@ cc.ScrollView = cc.Layer.extend({ this.draw(context); // self draw // draw children zOrder >= 0 - if (this._children) { - for (; i < this._children.length; i++) { - if (this._children[i] && this._children[i]._zOrder >= 0) - this._children[i].visit(context); - } - } + for (; i < childrenLen; i++) + locChildren[i].visit(context); } else this.draw(context); // self draw @@ -540,19 +553,21 @@ cc.ScrollView = cc.Layer.extend({ context.restore(); } else { cc.kmGLPushMatrix(); - if (this._grid && this._grid.isActive()) { - this._grid.beforeDraw(); + var locGrid = this._grid; + if (locGrid && locGrid.isActive()) { + locGrid.beforeDraw(); this.transformAncestors(); } this.transform(context); this._beforeDraw(context); - if (this._children) { - i = 0; + if (locChildren && locChildren.length > 0) { + childrenLen = locChildren.length; // draw children zOrder < 0 - for (; i < this._children.length; i++) { - if (this._children[i].getZOrder() < 0) - this._children[i].visit(); + for (i = 0; i < childrenLen; i++) { + selChild = locChildren[i]; + if (selChild && selChild._zOrder < 0) + selChild.visit(); else break; } @@ -561,14 +576,14 @@ cc.ScrollView = cc.Layer.extend({ this.draw(context); // draw children zOrder >= 0 - for (; i < this._children.length; i++) - this._children[i].visit(); + for (; i < childrenLen; i++) + locChildren[i].visit(); } else this.draw(context); this._afterDraw(context); - if (this._grid && this._grid.isActive()) - this._grid.afterDraw(this); + if (locGrid && locGrid.isActive()) + locGrid.afterDraw(this); cc.kmGLPopMatrix(); } @@ -617,16 +632,17 @@ cc.ScrollView = cc.Layer.extend({ _relocateContainer:function (animated) { var min = this.minContainerOffset(); var max = this.maxContainerOffset(); + var locDirection = this._direction; var oldPoint = this._container.getPosition(); var newX = oldPoint.x; var newY = oldPoint.y; - if (this._direction == cc.SCROLLVIEW_DIRECTION_BOTH || this._direction == cc.SCROLLVIEW_DIRECTION_HORIZONTAL) { + if (locDirection === cc.SCROLLVIEW_DIRECTION_BOTH || locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) { newX = Math.max(newX, min.x); newX = Math.min(newX, max.x); } - if (this._direction == cc.SCROLLVIEW_DIRECTION_BOTH || this._direction == cc.SCROLLVIEW_DIRECTION_VERTICAL) { + if (locDirection == cc.SCROLLVIEW_DIRECTION_BOTH || locDirection == cc.SCROLLVIEW_DIRECTION_VERTICAL) { newY = Math.min(newY, max.y); newY = Math.max(newY, min.y); } @@ -648,7 +664,9 @@ cc.ScrollView = cc.Layer.extend({ } var maxInset, minInset; - this._container.setPosition(cc.pAdd(this._container.getPosition(), this._scrollDistance)); + var oldPosition = this._container.getPosition(); + var locScrollDistance = this._scrollDistance; + this._container.setPosition(oldPosition.x + locScrollDistance.x , oldPosition.y + locScrollDistance.y); if (this._bounceable) { maxInset = this._maxInset; minInset = this._minInset; @@ -662,15 +680,21 @@ cc.ScrollView = cc.Layer.extend({ newX = Math.max(newX, minInset.x); var newY = Math.min(this._container.getPosition().y, maxInset.y); newY = Math.max(newY, minInset.y);*/ - var newX = this._container.getPosition().x; - var newY = this._container.getPosition().y; + oldPosition = this._container.getPosition(); + var newX = oldPosition.x; + var newY = oldPosition.y; + + //this._scrollDistance = cc.pSub(this._scrollDistance, cc.p(newX - this._container.getPosition().x, newY - this._container.getPosition().y)); + //= this._scrollDistance = cc.pSub(this._scrollDistance, cc.p(0, 0)); = do nothing + + //this._scrollDistance = cc.pMult(this._scrollDistance, SCROLL_DEACCEL_RATE); + locScrollDistance.x = locScrollDistance.x * SCROLL_DEACCEL_RATE; + locScrollDistance.y = locScrollDistance.y * SCROLL_DEACCEL_RATE; - this._scrollDistance = cc.pSub(this._scrollDistance, cc.p(newX - this._container.getPosition().x, newY - this._container.getPosition().y)); - this._scrollDistance = cc.pMult(this._scrollDistance, SCROLL_DEACCEL_RATE); this.setContentOffset(cc.p(newX, newY)); - if ((Math.abs(this._scrollDistance.x) <= SCROLL_DEACCEL_DIST && - Math.abs(this._scrollDistance.y) <= SCROLL_DEACCEL_DIST) || + if ((Math.abs(locScrollDistance.x) <= SCROLL_DEACCEL_DIST && + Math.abs(locScrollDistance.y) <= SCROLL_DEACCEL_DIST) || newY > maxInset.y || newY < minInset.y || newX > maxInset.x || newX < minInset.x || newX == maxInset.x || newX == minInset.x || @@ -726,9 +750,10 @@ cc.ScrollView = cc.Layer.extend({ ctx.clip(); ctx.closePath(); } else { - if(cc.EGLView.getInstance().isScissorEnabled()){ + var EGLViewer = cc.EGLView.getInstance(); + if(EGLViewer.isScissorEnabled()){ this._scissorRestored = true; - this._parentScissorRect = cc.EGLView.getInstance().getScissorRect(); + this._parentScissorRect = EGLViewer.getScissorRect(); //set the intersection of m_tParentScissorRect and frame as the new scissor rect if (cc.rectIntersection(frame, this._parentScissorRect)) { var locPSRect = this._parentScissorRect; @@ -736,12 +761,12 @@ cc.ScrollView = cc.Layer.extend({ var y = Math.max(frame.y, locPSRect.y); var xx = Math.min(frame.x + frame.width, locPSRect.x + locPSRect.width); var yy = Math.min(frame.y + frame.height, locPSRect.y + locPSRect.height); - cc.EGLView.getInstance().setScissorInPoints(x, y, xx - x, yy - y); + EGLViewer.setScissorInPoints(x, y, xx - x, yy - y); } }else{ ctx.enable(ctx.SCISSOR_TEST); //clip - cc.EGLView.getInstance().setScissorInPoints(frame.x, frame.y, frame.width, frame.height); + EGLViewer.setScissorInPoints(frame.x, frame.y, frame.width, frame.height); } } @@ -770,6 +795,7 @@ cc.ScrollView = cc.Layer.extend({ _getViewRect:function(){ var screenPos = this.convertToWorldSpace(cc.PointZero()); + var locViewSize = this._viewSize; var scaleX = this.getScaleX(); var scaleY = this.getScaleY(); @@ -782,15 +808,21 @@ cc.ScrollView = cc.Layer.extend({ // Support negative scaling. Not doing so causes intersectsRect calls // (eg: to check if the touch was within the bounds) to return false. // Note, CCNode::getScale will assert if X and Y scales are different. - if(scaleX<0) { - screenPos.x += this._viewSize.width*scaleX; + if (scaleX < 0) { + screenPos.x += locViewSize.width * scaleX; scaleX = -scaleX; } - if(scaleY<0) { - screenPos.y += this._viewSize.height*scaleY; + if (scaleY < 0) { + screenPos.y += locViewSize.height * scaleY; scaleY = -scaleY; } - return cc.RectMake(screenPos.x, screenPos.y, this._viewSize.width * scaleX, this._viewSize.height * scaleY); + + var locViewRect = this._tmpViewRect; + locViewRect.x = screenPos.x; + locViewRect.y = screenPos.y; + locViewRect.width = locViewSize.width * scaleX; + locViewRect.height = locViewSize.height * scaleY; + return locViewRect; } }); diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index a015bc0ee1..dcb5afbeaf 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -175,9 +175,9 @@ cc.TableView = cc.ScrollView.extend({ var offset = this.__offsetFromIndex(index); var cellSize = this._dataSource.cellSizeForTable(this); - if (this._vOrdering == cc.TABLEVIEW_FILL_TOPDOWN) { + if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) offset.y = this.getContainer().getContentSize().height - offset.y - cellSize.height; - } + return offset; }, @@ -262,11 +262,7 @@ cc.TableView = cc.ScrollView.extend({ return this._tableViewDelegate; }, - setDelegate:function (delegate, isDirectCall) { - if (isDirectCall != null && isDirectCall == true) { - this._super(delegate); - return; - } + setDelegate:function (delegate) { this._tableViewDelegate = delegate; }, @@ -286,7 +282,7 @@ cc.TableView = cc.ScrollView.extend({ }, initWithViewSize:function (size, container) { - if (this._super(size, container)) { + if (cc.ScrollView.prototype.initWithViewSize.call(this, size, container)) { this._cellsUsed = new cc.ArrayForObjectSorting(); this._cellsFreed = new cc.ArrayForObjectSorting(); this._indices = new cc.Set(); @@ -294,7 +290,7 @@ cc.TableView = cc.ScrollView.extend({ this._vOrdering = cc.TABLEVIEW_FILL_BOTTOMUP; this.setDirection(cc.SCROLLVIEW_DIRECTION_VERTICAL); - this.setDelegate(this, true); + cc.ScrollView.prototype.setDelegate.call(this, this); return true; } return false; @@ -311,9 +307,8 @@ cc.TableView = cc.ScrollView.extend({ } var cell = this._cellWithIndex(idx); - if (cell) { + if (cell) this._moveCellOutOfSight(cell); - } cell = this._dataSource.tableCellAtIndex(this, idx); this._setIndexForCell(idx, cell); @@ -330,13 +325,12 @@ cc.TableView = cc.ScrollView.extend({ return; } - var newIdx; - - var cell = this._cellsUsed.objectWithObjectID(idx); + var newIdx, locCellsUsed = this._cellsUsed; + var cell = locCellsUsed.objectWithObjectID(idx); if (cell) { - newIdx = this._cellsUsed.indexOfSortedObject(cell); - for (var i = newIdx; i < this._cellsUsed.count(); i++) { - cell = this._cellsUsed.objectAtIndex(i); + newIdx = locCellsUsed.indexOfSortedObject(cell); + for (var i = newIdx; i < locCellsUsed.count(); i++) { + cell = locCellsUsed.objectAtIndex(i); this._setIndexForCell(cell.getIdx() + 1, cell); } } @@ -360,11 +354,11 @@ cc.TableView = cc.ScrollView.extend({ } var cell = this._cellWithIndex(idx); - if (!cell) { + if (!cell) return; - } - var newIdx = this._cellsUsed.indexOfSortedObject(cell); + var locCellsUsed = this._cellsUsed; + var newIdx = locCellsUsed.indexOfSortedObject(cell); //remove first this._moveCellOutOfSight(cell); @@ -372,8 +366,8 @@ cc.TableView = cc.ScrollView.extend({ this._indices.removeObject(idx); //cc.ArrayRemoveObjectAtIndex(this._indices,idx); - for (var i = this._cellsUsed.count() - 1; i > newIdx; i--) { - cell = this._cellsUsed.objectAtIndex(i); + for (var i = locCellsUsed.count() - 1; i > newIdx; i--) { + cell = locCellsUsed.objectAtIndex(i); this._setIndexForCell(cell.getIdx() - 1, cell); } }, @@ -382,8 +376,9 @@ cc.TableView = cc.ScrollView.extend({ * reloads data from data source. the view will be refreshed. */ reloadData:function () { - for (var i = 0; i < this._cellsUsed.count(); i++) { - var cell = this._cellsUsed.objectAtIndex(i); + var locCellsUsed = this._cellsUsed; + for (var i = 0; i < locCellsUsed.count(); i++) { + var cell = locCellsUsed.objectAtIndex(i); this._cellsFreed.addObject(cell); cell.reset(); if (cell.getParent() == this.getContainer()) { @@ -426,7 +421,8 @@ cc.TableView = cc.ScrollView.extend({ }, scrollViewDidScroll:function (view) { - var countOfItems = this._dataSource.numberOfCellsInTableView(this); + var locDataSource = this._dataSource; + var countOfItems = locDataSource.numberOfCellsInTableView(this); if (0 === countOfItems) return; @@ -435,32 +431,32 @@ cc.TableView = cc.ScrollView.extend({ var idx = 0; var offset = cc.pMult(this.getContentOffset(), -1); - var maxIdx = Math.max(this._dataSource.numberOfCellsInTableView(this) - 1, 0); - - var cellSize = this._dataSource.cellSizeForTable(this); + var maxIdx = Math.max(locDataSource.numberOfCellsInTableView(this) - 1, 0); - if (this._vOrdering == cc.TABLEVIEW_FILL_TOPDOWN) { - offset.y = offset.y + this._viewSize.height / this.getContainer().getScaleY() - cellSize.height; + var cellSize = locDataSource.cellSizeForTable(this); + var locViewSize = this._viewSize, locContainer = this.getContainer(); + if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) { + offset.y = offset.y + locViewSize.height / locContainer.getScaleY() - cellSize.height; } var startIdx = 0 | this._indexFromOffset(offset); - if (this._vOrdering == cc.TABLEVIEW_FILL_TOPDOWN) { - offset.y -= this._viewSize.height / this.getContainer().getScaleY(); + if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) { + offset.y -= locViewSize.height / locContainer.getScaleY(); } else { - offset.y += this._viewSize.height / this.getContainer().getScaleY(); + offset.y += locViewSize.height / locContainer.getScaleY(); } - offset.x += this._viewSize.width / this.getContainer().getScaleX(); + offset.x += locViewSize.width / locContainer.getScaleX(); var endIdx = 0 | this._indexFromOffset(offset); - var cell; - if (this._cellsUsed.count() > 0) { - cell = this._cellsUsed.objectAtIndex(0); + var cell, locCellsUsed = this._cellsUsed; + if (locCellsUsed.count() > 0) { + cell = locCellsUsed.objectAtIndex(0); idx = cell.getIdx(); while (idx < startIdx) { this._moveCellOutOfSight(cell); - if (this._cellsUsed.count() > 0) { - cell = this._cellsUsed.objectAtIndex(0); + if (locCellsUsed.count() > 0) { + cell = locCellsUsed.objectAtIndex(0); idx = cell.getIdx(); } else { break; @@ -468,13 +464,13 @@ cc.TableView = cc.ScrollView.extend({ } } - if (this._cellsUsed.count() > 0) { - cell = this._cellsUsed.lastObject(); + if (locCellsUsed.count() > 0) { + cell = locCellsUsed.lastObject(); idx = cell.getIdx(); while (idx <= maxIdx && idx > endIdx) { this._moveCellOutOfSight(cell); - if (this._cellsUsed.count() > 0) { - cell = this._cellsUsed.lastObject(); + if (locCellsUsed.count() > 0) { + cell = locCellsUsed.lastObject(); idx = cell.getIdx(); } else { break; @@ -483,9 +479,8 @@ cc.TableView = cc.ScrollView.extend({ } for (var i = startIdx; i <= endIdx; i++) { - if (this._indices.containsObject(i)) { + if (this._indices.containsObject(i)) continue; - } this.updateCellAtIndex(i); } }, @@ -494,12 +489,12 @@ cc.TableView = cc.ScrollView.extend({ }, onTouchEnded:function (touch, event) { - if (!this.isVisible()) { + if (!this.isVisible()) return; - } + if (this._touches.length == 1 && !this.isTouchMoved()) { var point = this.getContainer().convertTouchToNodeSpace(touch); - if (this._vOrdering == cc.TABLEVIEW_FILL_TOPDOWN) { + if (this._vOrdering === cc.TABLEVIEW_FILL_TOPDOWN) { var cellSize = this._dataSource.cellSizeForTable(this); point.y -= cellSize.height; } @@ -510,17 +505,17 @@ cc.TableView = cc.ScrollView.extend({ this._tableViewDelegate.tableCellTouched(this, cell); } } - this._super(touch, event); + cc.ScrollView.prototype.call(this, touch, event); } }); /** * An initialized table view object * - * @param dataSource data source; - * @param size view size - * @param container parent object for cells - * @return table view + * @param {cc.TableViewDataSource} dataSource data source; + * @param {cc.Size} size view size + * @param {cc.Node} container parent object for cells + * @return {cc.TableView} table view */ cc.TableView.create = function (dataSource, size, container) { var table = new cc.TableView(); From 744e5143e607301a6ce632dd441753a9168fe5c1 Mon Sep 17 00:00:00 2001 From: ShengxiangChen Date: Thu, 1 Aug 2013 15:30:06 +0800 Subject: [PATCH 016/141] fixed #2459: fix Accelerometer bug on UCWeb version 9.0 and below. --- .../CCLayer.js | 7 +--- cocos2d/platform/CCAccelerometer.js | 37 ++++++++++--------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 42e3f5401e..7e8ef55fd3 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -222,15 +222,12 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ */ setAccelerometerInterval:function (interval) { if (this._isAccelerometerEnabled) { - if (this._running) { - var director = cc.Director.getInstance(); - director.getAccelerometer().setAccelerometerInterval(interval); - } + cc.Director.getInstance().getAccelerometer().setAccelerometerInterval(interval); } }, onAccelerometer:function (accelerationValue) { - //Layer#onAccelerometer override me + cc.Assert(false, "Layer#onAccelerometer override me"); }, /** diff --git a/cocos2d/platform/CCAccelerometer.js b/cocos2d/platform/CCAccelerometer.js index 19ac9788a2..322a97cf29 100644 --- a/cocos2d/platform/CCAccelerometer.js +++ b/cocos2d/platform/CCAccelerometer.js @@ -47,10 +47,10 @@ cc.Acceleration = function (x, y, z, timestamp) { * @extends cc.Class */ cc.Accelerometer = cc.Class.extend(/** @lends cc.Accelerometer# */{ - setDelegate:function (delegate) { + setDelegate: function (delegate) { cc.AccelerometerDispatcher.getInstance().addDelegate(delegate); }, - setAccelerometerInterval:function (interval) { + setAccelerometerInterval: function (interval) { cc.AccelerometerDispatcher.getInstance().setAccelerometerInterval(interval); } }); @@ -63,31 +63,31 @@ cc.Accelerometer = cc.Class.extend(/** @lends cc.Accelerometer# */{ * @extends cc.Class */ cc.AccelerometerDispatcher = cc.Class.extend(/** @lends cc.AccelerometerDispatcher# */{ - _delegate:null, - _acceleration:null, - _deviceEvent:null, - //_orientation:0, - _interval:0.1, - _minus:1, - init:function () { + _delegate: null, + _acceleration: null, + _deviceEvent: null, + _interval: 0, + _minus: 1, + init: function () { this._acceleration = new cc.Acceleration(); this._deviceEvent = window.DeviceMotionEvent || window.DeviceOrientationEvent; var ua = navigator.userAgent; - if(/Android/.test(ua)){ + if (/Android/.test(ua) || (/Adr/.test(ua) && cc.Browser.type == "ucbrowser")) { this._minus = -1; } + //TODO fix DeviceMotionEvent bug on QQ Browser version 4.1 and below. - /*if(ua.indexOf("qqbrowser")){ + if (cc.Browser.type == "mqqbrowser") { this._deviceEvent = window.DeviceOrientationEvent; - }*/ + } return true; }, - getDelegate:function () { + getDelegate: function () { return this._delegate; }, - addDelegate:function (delegate) { + addDelegate: function (delegate) { this._delegate = delegate; var acc = this.didAccelerate.bind(this); @@ -109,18 +109,20 @@ cc.AccelerometerDispatcher = cc.Class.extend(/** @lends cc.AccelerometerDispatch } }, - setAccelerometerInterval:function (interval) { - //not available on browser + setAccelerometerInterval: function (interval) { if (this._interval !== interval) { this._interval = interval; } }, - didAccelerate:function (eventData) { + didAccelerate: function (eventData) { if (!this._delegate) { return; } + var now = Date.now(); + if ((now - this._acceleration.timestamp) / 1000 < this._interval) return; + if (this._deviceEvent == window.DeviceMotionEvent) { var acceleration = eventData.accelerationIncludingGravity; this._acceleration.x = this._minus * acceleration.x * 0.1; @@ -132,7 +134,6 @@ cc.AccelerometerDispatcher = cc.Class.extend(/** @lends cc.AccelerometerDispatch this._acceleration.y = -(eventData.beta / 90) * 0.981; this._acceleration.z = (eventData.alpha / 90) * 0.981; } - this._acceleration.timestamp = Date.now(); var tmp = this._acceleration.x; From 24d41a4ef37444a78f1ac8e9eb8c9fc6fc089f3b Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 1 Aug 2013 17:06:45 +0800 Subject: [PATCH 017/141] fixed #2445 refactor code for rendering classes to optimize performance --- extensions/GUI/CCScrollView/CCTableView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index dcb5afbeaf..2948ee6e89 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -505,7 +505,7 @@ cc.TableView = cc.ScrollView.extend({ this._tableViewDelegate.tableCellTouched(this, cell); } } - cc.ScrollView.prototype.call(this, touch, event); + cc.ScrollView.prototype.onTouchEnded.call(this, touch, event); } }); From e16afc6a36bc7800306029ae5dcbca1679fb5185 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 1 Aug 2013 17:36:59 +0800 Subject: [PATCH 018/141] Fixed #2445 correct a mistake in CCScheduler.js when refactoring code for performance --- cocos2d/CCScheduler.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/cocos2d/CCScheduler.js b/cocos2d/CCScheduler.js index da3ebf5812..5fd64c219e 100644 --- a/cocos2d/CCScheduler.js +++ b/cocos2d/CCScheduler.js @@ -332,34 +332,33 @@ cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{ this._timesExecuted = 0; } else { var locTarget = this._target, locSelector = this._selector; - var locElapsed = this._elapsed; if (this._runForever && !this._useDelay) { //standard timer usage - locElapsed += dt; + this._elapsed += dt; - if (locElapsed >= this._interval) { + if (this._elapsed >= this._interval) { if (locTarget && locSelector) this._callSelector(); - locElapsed = 0; + this._elapsed = 0; } } else { //advanced usage - locElapsed += dt; + this._elapsed += dt; if (this._useDelay) { - if (locElapsed >= this._delay) { + if (this._elapsed >= this._delay) { if (locTarget && locSelector) this._callSelector(); - locElapsed = locElapsed - this._delay; + this._elapsed = this._elapsed - this._delay; this._timesExecuted += 1; this._useDelay = false; } } else { - if (locElapsed >= this._interval) { + if (this._elapsed >= this._interval) { if (locTarget && locSelector) this._callSelector(); - locElapsed = 0; + this._elapsed = 0; this._timesExecuted += 1; } } @@ -367,7 +366,6 @@ cc.Timer = cc.Class.extend(/** @lends cc.Timer# */{ if (this._timesExecuted > this._repeat) cc.Director.getInstance().getScheduler().unscheduleCallbackForTarget(locTarget, locSelector); } - this._elapsed = locElapsed; } } }); From 22244e30b9a5d28b867639814be14d2292707d17 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 2 Aug 2013 17:28:00 +0800 Subject: [PATCH 019/141] fixed #2468 Fixed a bug of CCBReader that ControlButton doesn't work when controller is _jsControlled --- extensions/CCBReader/CCBReader.js | 5 ++++- extensions/CCEditBox.js | 2 +- extensions/GUI/CCControlExtension/CCControl.js | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index 219a091310..a45b1f3f00 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -974,7 +974,10 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { callbackName = documentCallbackNames[j]; callbackNode = documentCallbackNodes[j]; - callbackNode.setCallback(controller[callbackName], controller); + if(callbackNode instanceof cc.ControlButton) + callbackNode.addTargetWithActionForControlEvents(controller, controller[callbackName], 255); //register all type of events + else + callbackNode.setCallback(controller[callbackName], controller); } // Variables diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index e38dac23e2..73b94bf9a5 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -417,7 +417,7 @@ cc.EditBox = cc.ControlButton.extend({ this.setZoomOnTouchDown(false); this.setPreferredSize(size); this.setPosition(cc.p(0, 0)); - this.addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE); + this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE); return true; } return false; diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/GUI/CCControlExtension/CCControl.js index 3acede8898..905942a8b8 100644 --- a/extensions/GUI/CCControlExtension/CCControl.js +++ b/extensions/GUI/CCControlExtension/CCControl.js @@ -217,7 +217,7 @@ cc.Control = cc.LayerRGBA.extend({ for (var i = 0; i < cc.CONTROL_EVENT_TOTAL_NUMBER; i++) { // If the given controlEvents bitmask contains the curent event if ((controlEvents & (1 << i))) { - this.addTargetWithActionForControlEvent(target, action, 1 << i); + this._addTargetWithActionForControlEvent(target, action, 1 << i); } } }, @@ -321,7 +321,7 @@ cc.Control = cc.LayerRGBA.extend({ * @param controlEvent A control event for which the action message is sent. * See "CCControlEvent" for constants. */ - addTargetWithActionForControlEvent:function (target, action, controlEvent) { + _addTargetWithActionForControlEvent:function (target, action, controlEvent) { // Create the invocation object var invocation = new cc.Invocation(target, action, controlEvent); From f59d9f0e5cef7ed82bb426c74b09ea79d426e293 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 5 Aug 2013 11:24:34 +0800 Subject: [PATCH 020/141] fixed #2468 CCBReader has supported loading ControlEvents of ControlButton on _jsControlled Mode --- extensions/CCBReader/CCBAnimationManager.js | 10 ++++++++++ extensions/CCBReader/CCBReader.js | 16 ++++++++++++---- extensions/CCBReader/CCNodeLoader.js | 2 ++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/CCBReader/CCBAnimationManager.js index 9174416846..3005295504 100644 --- a/extensions/CCBReader/CCBAnimationManager.js +++ b/extensions/CCBReader/CCBAnimationManager.js @@ -45,6 +45,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ _documentOutletNodes:null, _documentCallbackNames:null, _documentCallbackNodes:null, + _documentCallbackControlEvents:null, _documentControllerName:"", _lastCompletedSequenceName:"", _keyframeCallbacks:null, @@ -68,6 +69,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ this._documentOutletNodes = []; this._documentCallbackNames = []; this._documentCallbackNodes = []; + this._documentCallbackControlEvents = []; this._keyframeCallbacks = []; this._keyframeCallFuncs = {}; @@ -112,6 +114,10 @@ cc.BuilderAnimationManager = cc.Class.extend({ this._documentCallbackNames.push(name); }, + addDocumentCallbackControlEvents:function(controlEvents){ + this._documentCallbackControlEvents.push(controlEvents); + }, + addDocumentOutletNode:function(node){ this._documentOutletNodes.push(node); }, @@ -136,6 +142,10 @@ cc.BuilderAnimationManager = cc.Class.extend({ return this._documentCallbackNodes; }, + getDocumentCallbackControlEvents:function(){ + return this._documentCallbackControlEvents; + }, + getDocumentOutletNames:function(){ return this._documentOutletNames; }, diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index a45b1f3f00..6d791ed86e 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -486,6 +486,10 @@ cc.BuilderReader = cc.Class.extend({ this._actionManager.addDocumentCallbackNode(node); }, + addDocumentCallbackControlEvents:function(controlEvents){ + this._actionManager.addDocumentCallbackControlEvents(controlEvents); + }, + readFileWithCleanUp:function (cleanUp) { if (!this._readHeader()) return null; @@ -922,7 +926,7 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { var node = reader.readNodeGraphFromFile(ccbFilePath, owner, parentSize); var i; - var callbackName, callbackNode, outletName, outletNode; + var callbackName, callbackNode, callbackControlEvents, outletName, outletNode; // Assign owner callbacks & member variables if (owner) { // Callbacks @@ -931,7 +935,10 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { for (i = 0; i < ownerCallbackNames.length; i++) { callbackName = ownerCallbackNames[i]; callbackNode = ownerCallbackNodes[i]; - callbackNode.setCallback(owner[callbackName], owner); + if(callbackNode instanceof cc.ControlButton) + callbackNode.addTargetWithActionForControlEvents(owner, owner[callbackName], 255); //register all type of events + else + callbackNode.setCallback(owner[callbackName], owner); } // Variables @@ -970,12 +977,13 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { // Callbacks var documentCallbackNames = animationManager.getDocumentCallbackNames(); var documentCallbackNodes = animationManager.getDocumentCallbackNodes(); + var documentCallbackControlEvents = animationManager.getDocumentCallbackControlEvents(); for (j = 0; j < documentCallbackNames.length; j++) { callbackName = documentCallbackNames[j]; callbackNode = documentCallbackNodes[j]; - + callbackControlEvents = documentCallbackControlEvents[j]; if(callbackNode instanceof cc.ControlButton) - callbackNode.addTargetWithActionForControlEvents(controller, controller[callbackName], 255); //register all type of events + callbackNode.addTargetWithActionForControlEvents(controller, controller[callbackName], callbackControlEvents); //register all type of events else callbackNode.setCallback(controller[callbackName], controller); } diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/CCBReader/CCNodeLoader.js index 4f42cc1127..b986d6ea45 100644 --- a/extensions/CCBReader/CCNodeLoader.js +++ b/extensions/CCBReader/CCNodeLoader.js @@ -662,6 +662,7 @@ cc.NodeLoader = cc.Class.extend({ if(selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT){ ccbReader.addDocumentCallbackNode(node); ccbReader.addDocumentCallbackName(selectorName); + ccbReader.addDocumentCallbackControlEvents(0); } else { ccbReader.addOwnerCallbackNode(node); ccbReader.addOwnerCallbackName(selectorName); @@ -714,6 +715,7 @@ cc.NodeLoader = cc.Class.extend({ if(selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT){ ccbReader.addDocumentCallbackNode(node); ccbReader.addDocumentCallbackName(selectorName); + ccbReader.addDocumentCallbackControlEvents(controlEvents); } else { ccbReader.addOwnerCallbackNode(node); ccbReader.addOwnerCallbackName(selectorName); From 8727c49c107edcf8a492a249afd05ff0aa00825d Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 5 Aug 2013 11:45:09 +0800 Subject: [PATCH 021/141] Fixed #2445 Fixed bug for sortAllChildren ,that tempChild is a changing var --- cocos2d/base_nodes/CCNode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index f620db75ac..d148aae0ee 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -1193,6 +1193,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ //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 ))) { + tempChild = _children[j]; _children[j + 1] = tempChild; j = j - 1; } From 9669d08a6d968e2868519b3cfef3ab42957afc19 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 5 Aug 2013 11:52:05 +0800 Subject: [PATCH 022/141] Fixed #2445 Fixed bug for sortAllChildren ,that tempChild is a changing Var. --- cocos2d/base_nodes/CCNode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index d148aae0ee..f57ebb7ca6 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -3036,6 +3036,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ //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 ))) { + tempChild = _children[j]; _children[j + 1] = tempChild; j = j - 1; } From c27186e8f064381dba385a646192eb64935b3ee9 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 5 Aug 2013 15:00:28 +0800 Subject: [PATCH 023/141] fixed #1056 The bug of cc.ProgressTimer has fixed that Midpoint is wrong on Canvas Mode. --- cocos2d/misc_nodes/CCProgressTimer.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index a27babe44f..42b181adf1 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -165,10 +165,10 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * }, /// ---- common properties end ---- - _origin:cc.PointZero(), - _originSize:cc.SizeZero(), - _drawSize:cc.SizeZero(), - _drawPosition:cc.PointZero(), + _origin:null, + _originSize:null, + _drawSize:null, + _drawPosition:null, _startAngle:270, _endAngle:270, _radius:0, @@ -364,8 +364,7 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * var textureSize = this._sprite.getTextureRect().size; var locMidPoint = this._midPoint; if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { - - this._origin = cc.p(-(size.width * (0.5 - locMidPoint.x)), -(size.height * (0.5 - locMidPoint.y))); + this._origin = cc.p(-(size.width * (0.5 - locMidPoint.x)), -(size.height * (locMidPoint.y - 0.5))); this._radius = Math.round(Math.sqrt(size.width * size.width + size.height * size.height)); if (this._reverseDirection) { this._startAngle = 270 - 3.6 * this._percentage; From fd27bb73f0537b59fe321cfcce2d298067aeb75f Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 5 Aug 2013 15:48:13 +0800 Subject: [PATCH 024/141] fixed #2468 Corrected a mistake of cc.NodeLoader --- extensions/CCBReader/CCNodeLoader.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/CCBReader/CCNodeLoader.js index b986d6ea45..4505a08bd7 100644 --- a/extensions/CCBReader/CCNodeLoader.js +++ b/extensions/CCBReader/CCNodeLoader.js @@ -491,9 +491,10 @@ cc.NodeLoader = cc.Class.extend({ var texture = cc.TextureCache.getInstance().addImage(spriteFile); var bounds; if(texture instanceof cc.Texture2D){ - bounds = cc.RectMake(0, 0, texture.getContentSize().width, texture.getContentSize().height); + var locContentSize = texture.getContentSize(); + bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); }else{ - bounds = cc.RECT_PIXELS_TO_POINTS(bounds); + bounds = cc.RECT_PIXELS_TO_POINTS(cc.RectMake(0, 0, texture.width, texture.height)); } spriteFrame = cc.SpriteFrame.createWithTexture(texture, bounds); } else { From eb7f801842bc30e75b28f66e1a9756bc7ad56079 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Wed, 7 Aug 2013 15:34:59 +0800 Subject: [PATCH 025/141] fixed #2497 : setSearchPaths Bug --- cocos2d/platform/CCFileUtils.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/platform/CCFileUtils.js b/cocos2d/platform/CCFileUtils.js index 4fdf1b9f3a..a6f5ee816d 100644 --- a/cocos2d/platform/CCFileUtils.js +++ b/cocos2d/platform/CCFileUtils.js @@ -158,6 +158,7 @@ cc.FileUtils = cc.Class.extend({ * @warning If you get the file data succeed,you must delete it after used. */ getByteArrayFromFile:function (fileName, mode, size) { + fileName = this.fullPathForFilename(fileName); if (this._fileDataCache.hasOwnProperty(fileName)) return this._fileDataCache[fileName]; return this._loadBinaryFileData(fileName); @@ -177,7 +178,7 @@ cc.FileUtils = cc.Class.extend({ }, preloadBinaryFileData:function (fileUrl) { - fileUrl = this.fullPathFromRelativePath(fileUrl); + fileUrl = this.fullPathForFilename(fileUrl); var selfPointer = this; var xhr = this._getXMLHttpRequest(); @@ -254,7 +255,7 @@ cc.FileUtils = cc.Class.extend({ }, preloadTextFileData:function (fileUrl) { - fileUrl = this.fullPathFromRelativePath(fileUrl); + fileUrl = this.fullPathForFilename(fileUrl); var selfPointer = this; var xhr = this._getXMLHttpRequest(); From 64740a06f6be135c94269744daf27dd67628f2cc Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 7 Aug 2013 16:23:37 +0800 Subject: [PATCH 026/141] Fixed #2481 Re-write Canvas Mode of RenderTexture to adapt WebGL interface --- cocos2d/misc_nodes/CCRenderTexture.js | 578 ++++++++++++------ cocos2d/particle_nodes/CCParticleSystem.js | 2 - cocos2d/platform/CCApplication.js | 3 +- cocos2d/sprite_nodes/CCSprite.js | 25 +- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 97 +-- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 89 ++- .../GUI/CCControlExtension/CCControl.js | 2 +- .../GUI/CCControlExtension/CCControlButton.js | 2 +- 8 files changed, 538 insertions(+), 260 deletions(-) diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js index 4d3fb87708..99df12b674 100644 --- a/cocos2d/misc_nodes/CCRenderTexture.js +++ b/cocos2d/misc_nodes/CCRenderTexture.js @@ -69,23 +69,18 @@ cc.NextPOT = function (x) { * @class * @extends cc.Node */ -cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ +cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ /** * the offscreen canvas for rendering and storing the texture * @type HTMLCanvasElement */ - canvas:null, + _cacheCanvas:null, /** * stores a reference to the canvas context object - * @type CanvasContext + * @type CanvasRenderingContext2D */ - context:null, - _fBO:0, - _depthRenderBuffer:0, - _oldFBO:0, - _texture:null, - _textureCopy:null, - _uITextureImage:null, + _cacheContext:null, + _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, _sprite:null, @@ -96,35 +91,25 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ _clearStencil:0, _autoDraw:false, + _clearColorStr:null, + /** * Constructor */ ctor:function () { cc.Node.prototype.ctor.call(this); + this._clearColor = cc.c4f(1,1,1,1); + this._clearColorStr = "rgba(255,255,255,1)"; - if (cc.renderContextType === cc.CANVAS) { - this.canvas = document.createElement('canvas'); - this.context = this.canvas.getContext('2d'); - this.setAnchorPoint(cc.p(0, 0)); - } else { - this._clearColor = cc.c4f(0, 0, 0, 0); - } + this._cacheCanvas = document.createElement('canvas'); + this._cacheContext = this._cacheCanvas.getContext('2d'); + this.setAnchorPoint(cc.p(0, 0)); }, onExit:function () { cc.Node.prototype.onExit.call(this); - if (cc.renderContextType === cc.WEBGL) { - this._sprite = null; - this._textureCopy = null; - - var gl = cc.renderContext; - gl.deleteFramebuffer(this._fBO); - if (this._depthRenderBuffer) - gl.deleteRenderbuffer(this._depthRenderBuffer); - this._uITextureImage = null; - if(this._texture) - this._texture.releaseTexture(); - } + this._cacheContext = null; + this._cacheCanvas = null; }, /** @@ -143,27 +128,314 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ }, /** - * @return {HTMLCanvasElement} + * @param {Number} width + * @param {Number} height + * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format + * @param {Number} depthStencilFormat + * @return {Boolean} + */ + initWithWidthAndHeight:function (width, height, format, depthStencilFormat) { + this._cacheCanvas.width = width || 10; + this._cacheCanvas.height = height || 10; + this._cacheContext.translate(0, this._cacheCanvas.height); + this._sprite = cc.Sprite.createWithTexture(this._cacheCanvas); + return true; + }, + + /** + * starts grabbing + */ + begin:function () { + cc.renderContext = this._cacheContext; + + /*// Save the current matrix + cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); + cc.kmGLPushMatrix(); + cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); + cc.kmGLPushMatrix();*/ + }, + + /** + * starts rendering to the texture while clearing the texture first.
+ * This is more efficient then calling -clear first and then -begin + * @param {Number} r red 0-1 + * @param {Number} g green 0-1 + * @param {Number} b blue 0-1 + * @param {Number} a alpha 0-1 0 is transparent + * @param {Number} depthValue + * @param {Number} stencilValue + */ + beginWithClear:function (r, g, b, a, depthValue, stencilValue) { + var gl = cc.renderContext; + depthValue = depthValue || gl.COLOR_BUFFER_BIT; + stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + + this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)); + }, + + _beginWithClear:function (r, g, b, a, depthValue, stencilValue, flags) { + this.begin(); + + r = r || 0; + g = g || 0; + b = b || 0; + a = a || 1; + + var context = cc.renderContext; + var locCanvas = this._cacheCanvas; + context.save(); + context.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")"; + context.clearRect(0,0,locCanvas.width, -locCanvas.height); + context.fillRect(0,0,locCanvas.width, -locCanvas.height); + context.restore(); + }, + + /** + * ends grabbing */ - getCanvas:function () { - return this.canvas; + end:function () { + cc.renderContext = cc.mainRenderContextBackup; + + //TODO + /*//restore viewport + director.setViewport(); + cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); + cc.kmGLPopMatrix(); + cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); + cc.kmGLPopMatrix();*/ + }, + + /** + * clears the texture with a color + * @param {Number|cc.Rect} r red 0-1 + * @param {Number} g green 0-1 + * @param {Number} b blue 0-1 + * @param {Number} a alpha 0-1 + */ + clear:function (r, g, b, a) { + this.beginWithClear(r, g, b, a); + this.end(); }, /** - * @param {cc.Size} size + * clears the texture with a specified depth value + * @param {Number} depthValue */ - setContentSize:function (size) { - if (!size) + clearDepth:function (depthValue) { + cc.log("clearDepth isn't supported on Cocos2d-Html5"); + }, + + /** + * clears the texture with a specified stencil value + * @param {Number} stencilValue + */ + clearStencil:function (stencilValue) { + cc.log("clearDepth isn't supported on Cocos2d-Html5"); + }, + + visit:function (ctx) { + // override visit. + // Don't call visit on its children + if (!this._visible) return; - //if (!cc.Size.CCSizeEqualToSize(size, this._contentSize)) { - this._super(size); - if(cc.renderContextType === cc.CANVAS){ - this.canvas.width = size.width * 1.5; - this.canvas.height = size.height * 1.5; - this.context.translate(0, this.canvas.height); + ctx = ctx || cc.renderContext; + ctx.save(); + + this.draw(ctx); // update children of RenderTexture before + this.transform(ctx); + this._sprite.visit(); // draw the RenderTexture + + ctx.restore(); + + this._orderOfArrival = 0; + }, + + draw:function (ctx) { + ctx = ctx || cc.renderContext; + if (this._autoDraw) { + this.begin(); + + if (this._clearFlags) { + var locCanvas = this._cacheCanvas; + ctx.save(); + ctx.fillStyle = this._clearColorStr; + ctx.clearRect(0,0,locCanvas.width, -locCanvas.height); + ctx.fillRect(0,0,locCanvas.width, -locCanvas.height); + ctx.restore(); + } + + //! make sure all children are drawn + this.sortAllChildren(); + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) { + var getChild = locChildren[i]; + if (getChild != this._sprite) + getChild.visit(); + } + + this.end(); } - //} + }, + + /** + * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete. + * @return {cc.Image} + */ + newCCImage:function (flipImage) { + cc.log("saveToFile isn't supported on Cocos2d-Html5"); + return null; + }, + + _memcpy:function (destArr, destIndex, srcArr, srcIndex, size) { + for (var i = 0; i < size; i++) { + destArr[destIndex + i] = srcArr[srcIndex + i]; + } + }, + + /** + * saves the texture into a file using JPEG format. The file will be saved in the Documents folder. + * Returns YES if the operation is successful. + * (doesn't support in HTML5) + * @param {Number} filePath + * @param {Number} format + */ + saveToFile:function (filePath, format) { + cc.log("saveToFile isn't supported on Cocos2d-Html5"); + }, + + /** + * Listen "come to background" message, and save render texture. It only has effect on Android. + * @param {cc.Class} obj + */ + listenToBackground:function (obj) { + cc.log("listenToBackground isn't supported on Cocos2d-Html5"); + }, + + /** + * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android. + * @param {cc.Class} obj + */ + listenToForeground:function (obj) { + cc.log("listenToForeground isn't supported on Cocos2d-Html5"); + }, + + /** + * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES. + * @return {Number} + */ + getClearFlags:function () { + return this._clearFlags; + }, + + setClearFlags:function (clearFlags) { + this._clearFlags = clearFlags; + }, + + /** + * Clear color value. Valid only when "autoDraw" is true. + * @return {cc.Color4F} + */ + getClearColor:function () { + return this._clearColor; + }, + + setClearColor:function (clearColor) { + this._clearColor = cc.c4f(clearColor.r, clearColor.g, clearColor.b, clearColor.a); + this._clearColorStr = "rgba(" + (0 | (clearColor.r * 255)) + "," + (0 | (clearColor.g * 255)) + "," + (0 | (clearColor.b * 255)) + "," + clearColor.a + ")"; + }, + + /** + * Value for clearDepth. Valid only when autoDraw is true. + * @return {Number} + */ + getClearDepth:function () { + return this._clearDepth; + }, + + setClearDepth:function (clearDepth) { + this._clearDepth = clearDepth; + }, + + /** + * Value for clear Stencil. Valid only when autoDraw is true + * @return {Number} + */ + getClearStencil:function () { + return this._clearStencil; + }, + + setClearStencil:function (clearStencil) { + this._clearStencil = clearStencil; + }, + + /** + * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons.
+ * Will be enabled in the future. + * @return {Boolean} + */ + isAutoDraw:function () { + return this._autoDraw; + }, + + setAutoDraw:function (autoDraw) { + this._autoDraw = autoDraw; + } +}); + +cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ + _fBO:0, + _depthRenderBuffer:0, + _oldFBO:0, + _texture:null, + _textureCopy:null, + _uITextureImage:null, + _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, + _sprite:null, + + //code for "auto" update + _clearFlags:0, + _clearColor:null, + _clearDepth:0, + _clearStencil:0, + _autoDraw:false, + + /** + * Constructor + */ + ctor:function () { + cc.Node.prototype.ctor.call(this); + this._clearColor = cc.c4f(0, 0, 0, 0); + }, + + onExit: function () { + cc.Node.prototype.onExit.call(this); + + this._sprite = null; + this._textureCopy = null; + + var gl = cc.renderContext; + gl.deleteFramebuffer(this._fBO); + if (this._depthRenderBuffer) + gl.deleteRenderbuffer(this._depthRenderBuffer); + this._uITextureImage = null; + if (this._texture) + this._texture.releaseTexture(); + }, + + /** + * The sprite + * @return {cc.Sprite} + */ + getSprite:function () { + return this._sprite; + }, + + /** + * @param {cc.Sprite} sprite + */ + setSprite:function (sprite) { + this._sprite = sprite; }, /** @@ -174,108 +446,95 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @return {Boolean} */ initWithWidthAndHeight:function (width, height, format, depthStencilFormat) { - if (cc.renderContextType === cc.CANVAS) { - this.canvas.width = width || 10; - this.canvas.height = height || 10; + cc.Assert(format != cc.TEXTURE_2D_PIXEL_FORMAT_A8, "only RGB and RGBA formats are valid for a render texture"); - this.context.translate(0, this.canvas.height); - this._sprite = cc.Sprite.createWithTexture(this.canvas); - - return true; - } else { - cc.Assert(format != cc.TEXTURE_2D_PIXEL_FORMAT_A8, "only RGB and RGBA formats are valid for a render texture"); - - var gl = cc.renderContext; + var gl = cc.renderContext; - width = 0 | (width * cc.CONTENT_SCALE_FACTOR()); - height = 0 | (height * cc.CONTENT_SCALE_FACTOR()); + width = 0 | (width * cc.CONTENT_SCALE_FACTOR()); + height = 0 | (height * cc.CONTENT_SCALE_FACTOR()); - this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING); + this._oldFBO = gl.getParameter(gl.FRAMEBUFFER_BINDING); - // textures must be power of two squared - var powW , powH; + // textures must be power of two squared + var powW , powH; - if (cc.Configuration.getInstance().supportsNPOT()) { - powW = width; - powH = height; - } else { - powW = cc.NextPOT(width); - powH = cc.NextPOT(height); - } + if (cc.Configuration.getInstance().supportsNPOT()) { + powW = width; + powH = height; + } else { + powW = cc.NextPOT(width); + powH = cc.NextPOT(height); + } - //void *data = malloc(powW * powH * 4); - var dataLen = powW * powH * 4; - var data = new Uint8Array(dataLen); - //memset(data, 0, (int)(powW * powH * 4)); - for (var i = 0; i < powW * powH * 4; i++) - data[i] = 0; + //void *data = malloc(powW * powH * 4); + var dataLen = powW * powH * 4; + var data = new Uint8Array(dataLen); + //memset(data, 0, (int)(powW * powH * 4)); + for (var i = 0; i < powW * powH * 4; i++) + data[i] = 0; - this._pixelFormat = format; + this._pixelFormat = format; - this._texture = new cc.Texture2D(); - if (!this._texture) - return false; + this._texture = new cc.Texture2D(); + if (!this._texture) + return false; - this._texture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); - //free( data ); + this._texture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); + //free( data ); - var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING); + var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING); - if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) { - this._textureCopy = new cc.Texture2D(); - if (!this._textureCopy) { - return false; - } - this._textureCopy.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); + if (cc.Configuration.getInstance().checkForGLExtension("GL_QCOM")) { + this._textureCopy = new cc.Texture2D(); + if (!this._textureCopy) { + return false; } + this._textureCopy.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); + } - // generate FBO - this._fBO = gl.createFramebuffer(); - gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO); + // generate FBO + this._fBO = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO); - // associate texture with FBO - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0); + // associate texture with FBO + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0); - if (depthStencilFormat != 0) { - //create and attach depth buffer - this._depthRenderBuffer = gl.createRenderbuffer(); - gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH); - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer); + if (depthStencilFormat != 0) { + //create and attach depth buffer + this._depthRenderBuffer = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, this._depthRenderBuffer); + gl.renderbufferStorage(gl.RENDERBUFFER, depthStencilFormat, powW, powH); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer); - // if depth format is the one with stencil part, bind same render buffer as stencil attachment - //if (depthStencilFormat == gl.DEPTH24_STENCIL8) - // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer); - } + // if depth format is the one with stencil part, bind same render buffer as stencil attachment + //if (depthStencilFormat == gl.DEPTH24_STENCIL8) + // gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this._depthRenderBuffer); + } - // check if it worked (probably worth doing :) ) - cc.Assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); + // check if it worked (probably worth doing :) ) + cc.Assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); - this._texture.setAliasTexParameters(); + this._texture.setAliasTexParameters(); - this._sprite = cc.Sprite.createWithTexture(this._texture); - this._sprite.setScaleY(-1); - this._sprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + this._sprite = cc.Sprite.createWithTexture(this._texture); + this._sprite.setScaleY(-1); + this._sprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); - gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO); - gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO); + gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO); + gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO); - // Diabled by default. - this._autoDraw = false; + // Diabled by default. + this._autoDraw = false; - // add sprite for backward compatibility - this.addChild(this._sprite); - return true; - } + // add sprite for backward compatibility + this.addChild(this._sprite); + return true; }, /** * starts grabbing */ begin:function () { - if (cc.renderContextType === cc.CANVAS) - return; - // Save the current matrix cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); cc.kmGLPushMatrix(); @@ -338,9 +597,6 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ }, _beginWithClear:function (r, g, b, a, depthValue, stencilValue, flags) { - if (cc.renderContextType === cc.CANVAS) - return; - this.begin(); var gl = cc.renderContext; @@ -382,9 +638,6 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * ends grabbing */ end:function () { - if (cc.renderContextType === cc.CANVAS) - return; - var gl = cc.renderContext; var director = cc.Director.getInstance(); gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO); @@ -398,15 +651,15 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ /* var size = director.getWinSizeInPixels(); - // restore viewport - gl.viewport(0, 0, size.width * cc.CONTENT_SCALE_FACTOR(), size.height * cc.CONTENT_SCALE_FACTOR()); + // restore viewport + gl.viewport(0, 0, size.width * cc.CONTENT_SCALE_FACTOR(), size.height * cc.CONTENT_SCALE_FACTOR()); - // special viewport for 3d projection + retina display - if (director.getProjection() == cc.DIRECTOR_PROJECTION_3D && cc.CONTENT_SCALE_FACTOR() != 1) { - gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.CONTENT_SCALE_FACTOR()), (size.height * cc.CONTENT_SCALE_FACTOR())); - } + // special viewport for 3d projection + retina display + if (director.getProjection() == cc.DIRECTOR_PROJECTION_3D && cc.CONTENT_SCALE_FACTOR() != 1) { + gl.viewport((-size.width / 2), (-size.height / 2), (size.width * cc.CONTENT_SCALE_FACTOR()), (size.height * cc.CONTENT_SCALE_FACTOR())); + } - director.setProjection(director.getProjection());*/ + director.setProjection(director.getProjection());*/ }, /** @@ -417,16 +670,8 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {Number} a alpha 0-1 */ clear:function (r, g, b, a) { - if (cc.renderContextType === cc.CANVAS) { - var rect = r; - if (rect) - this.context.clearRect(rect.x, rect.y, rect.width, rect.height); - else - this.context.clearRect(0, 0, this.canvas.width, -this.canvas.height); - } else { - this.beginWithClear(r, g, b, a); - this.end(); - } + this.beginWithClear(r, g, b, a); + this.end(); }, /** @@ -434,9 +679,6 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {Number} depthValue */ clearDepth:function (depthValue) { - if (cc.renderContextType === cc.CANVAS) - return; - this.begin(); var gl = cc.renderContext; @@ -456,9 +698,6 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {Number} stencilValue */ clearStencil:function (stencilValue) { - if (cc.renderContextType === cc.CANVAS) - return; - var gl = cc.renderContext; // save old stencil value var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE); @@ -471,10 +710,6 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ }, visit:function (ctx) { - if (cc.renderContextType === cc.CANVAS) { - this._super(ctx); - return; - } // override visit. // Don't call visit on its children if (!this._visible) @@ -482,8 +717,9 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ cc.kmGLPushMatrix(); - if (this._grid && this._grid.isActive()) { - this._grid.beforeDraw(); + var locGrid = this._grid; + if (locGrid && locGrid.isActive()) { + locGrid.beforeDraw(); this.transformAncestors(); } @@ -491,8 +727,8 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ this._sprite.visit(); this.draw(ctx); - if (this._grid && this._grid.isActive()) - this._grid.afterDraw(this); + if (locGrid && locGrid.isActive()) + locGrid.afterDraw(this); cc.kmGLPopMatrix(); @@ -500,55 +736,51 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ }, draw:function (ctx) { - if (cc.renderContextType === cc.CANVAS) { - this._super(ctx); - return; - } - var gl = cc.renderContext; if (this._autoDraw) { this.begin(); - if (this._clearFlags) { + var locClearFlags = this._clearFlags; + if (locClearFlags) { var oldClearColor = [0.0, 0.0, 0.0, 0.0]; var oldDepthClearValue = 0.0; var oldStencilClearValue = 0; // backup and set - if (this._clearFlags & gl.COLOR_BUFFER_BIT) { + if (locClearFlags & gl.COLOR_BUFFER_BIT) { oldClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); gl.clearColor(this._clearColor.r, this._clearColor.g, this._clearColor.b, this._clearColor.a); } - if (this._clearFlags & gl.DEPTH_BUFFER_BIT) { + if (locClearFlags & gl.DEPTH_BUFFER_BIT) { oldDepthClearValue = gl.getParameter(gl.DEPTH_CLEAR_VALUE); gl.clearDepth(this._clearDepth); } - if (this._clearFlags & gl.STENCIL_BUFFER_BIT) { + if (locClearFlags & gl.STENCIL_BUFFER_BIT) { oldStencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE); gl.clearStencil(this._clearStencil); } // clear - gl.clear(this._clearFlags); + gl.clear(locClearFlags); // restore - if (this._clearFlags & gl.COLOR_BUFFER_BIT) + if (locClearFlags & gl.COLOR_BUFFER_BIT) gl.clearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[3]); - if (this._clearFlags & gl.DEPTH_BUFFER_BIT) + if (locClearFlags & gl.DEPTH_BUFFER_BIT) gl.clearDepth(oldDepthClearValue); - if (this._clearFlags & gl.STENCIL_BUFFER_BIT) + if (locClearFlags & gl.STENCIL_BUFFER_BIT) gl.clearStencil(oldStencilClearValue); } //! make sure all children are drawn this.sortAllChildren(); - - for (var i = 0; i < this._children.length; i++) { - var getChild = this._children[i]; + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) { + var getChild = locChildren[i]; if (getChild != this._sprite) getChild.visit(); } @@ -621,7 +853,7 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {Number} format */ saveToFile:function (filePath, format) { - cc.log("saveToFile is NoSupported on Cocos2d-Html5"); + cc.log("saveToFile isn't supported on Cocos2d-Html5"); }, /** @@ -629,7 +861,7 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {cc.Class} obj */ listenToBackground:function (obj) { - cc.log("listenToBackground is NoSupported on Cocos2d-Html5"); + cc.log("listenToBackground isn't supported on Cocos2d-Html5"); }, /** @@ -637,7 +869,7 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ * @param {cc.Class} obj */ listenToForeground:function (obj) { - cc.log("listenToForeground is NoSupported on Cocos2d-Html5"); + cc.log("listenToForeground isn't supported on Cocos2d-Html5"); }, /** @@ -702,6 +934,8 @@ cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ } }); +cc.RenderTexture = cc.Browser.supportWebGL ? cc.RenderTextureWebGL : cc.RenderTextureCanvas; + /** * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid * @param {Number} width diff --git a/cocos2d/particle_nodes/CCParticleSystem.js b/cocos2d/particle_nodes/CCParticleSystem.js index 1d33a1740e..79e8c43f9c 100644 --- a/cocos2d/particle_nodes/CCParticleSystem.js +++ b/cocos2d/particle_nodes/CCParticleSystem.js @@ -1889,8 +1889,6 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ if (!this._batchNode) this.postStep(); - - //cc.PROFILER_STOP_CATEGORY(kCCProfilerCategoryParticles , "cc.ParticleSystem - update"); }, updateWithNoTime:function () { diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js index 3c7099284a..6fbc4adb15 100644 --- a/cocos2d/platform/CCApplication.js +++ b/cocos2d/platform/CCApplication.js @@ -208,11 +208,12 @@ cc.setup = function (el, width, height) { cc.renderContext = cc.webglContext = cc.create3DContext(cc.canvas,{'stencil': true, 'preserveDrawingBuffer': true, 'alpha': false }); if(cc.renderContext){ cc.renderContextType = cc.WEBGL; - gl = cc.renderContext; // global variable declared in CCMacro.js + window.gl = cc.renderContext; // global variable declared in CCMacro.js cc.drawingUtil = new cc.DrawingPrimitiveWebGL(cc.renderContext); cc.TextureCache.getInstance()._initializingRenderer(); } else { cc.renderContext = cc.canvas.getContext("2d"); + cc.mainRenderContextBackup = cc.renderContext; cc.renderContextType = cc.CANVAS; cc.renderContext.translate(0, cc.canvas.height); cc.drawingUtil = new cc.DrawingPrimitiveCanvas(cc.renderContext); diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 460545df8b..aa8a5540a1 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -478,18 +478,19 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ sortAllChildren:function () { if (this._reorderChildDirty) { - var j, tempItem, locChildren = this._children; + 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 orderOfArrival is smaller - while (j >= 0 && ( tempItem.getZOrder() < locChildren[j].getZOrder() || ( tempItem.getZOrder() === locChildren[j].getZOrder() - && tempItem.getOrderOfArrival() < locChildren[j].getOrderOfArrival() ) )) { - locChildren[j + 1] = 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 ))) { + tempChild = locChildren[j]; + locChildren[j + 1] = tempChild; j = j - 1; } - locChildren[j + 1] = tempItem; } @@ -1522,15 +1523,17 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ sortAllChildren:function () { if (this._reorderChildDirty) { - var j, tempItem, locChildren = this._children; + 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 orderOfArrival is smaller - while (j >= 0 && ( tempItem.getZOrder() < locChildren[j].getZOrder() || ( tempItem.getZOrder() === locChildren[j].getZOrder() - && tempItem.getOrderOfArrival() < locChildren[j].getOrderOfArrival() ) )) { - locChildren[j + 1] = 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 ))) { + tempChild = locChildren[j]; + locChildren[j + 1] = tempChild; j = j - 1; } locChildren[j + 1] = tempItem; diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index d037c01f08..855a89bbf3 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -359,7 +359,6 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * /// ---- common properties end ---- _textureForCanvas:null, - _renderTexture:null, _useCache:false, _originalTexture:null, @@ -371,10 +370,6 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * cc.Node.prototype.ctor.call(this); if (fileImage) this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY); - - var locCanvas = cc.canvas; - this._renderTexture = cc.RenderTexture.create(locCanvas.width, locCanvas.height); - this.setContentSize(cc.size(locCanvas.width, locCanvas.height)); }, /** @@ -427,13 +422,6 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * this._children = cc.ArrayAppendObjectToIndex(this._children, sprite, index); }, - setContentSize:function (size) { - if (!size) - return; - cc.Node.prototype.setContentSize.call(this, size); - this._renderTexture.setContentSize(size); - }, - /** *

* initializes a CCSpriteBatchNode with a texture2d and capacity of children.
@@ -507,8 +495,6 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} */ getTexture:function () { - if (this._useCache) - return this._renderTexture.getCanvas(); return this._textureForCanvas; }, @@ -537,34 +523,15 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * context.save(); this.transform(ctx); var i, locChildren = this._children; - if (this._useCache) { - if (this._cacheDirty) { - //add dirty region - var locRenderTexture = this._renderTexture; - locRenderTexture.clear(); - locRenderTexture.context.save(); - locRenderTexture.context.translate(this._anchorPointInPoints.x, -(this._anchorPointInPoints.y )); - if (locChildren) { - this.sortAllChildren(); - for (i = 0; i < locChildren.length; i++) { - if (locChildren[i]) - locChildren[i].visit(locRenderTexture.context); - } - } - locRenderTexture.context.restore(); - this._cacheDirty = false; - } - // draw RenderTexture - this.draw(ctx); - } else { - if (locChildren) { - this.sortAllChildren(); - for (i = 0; i < locChildren.length; i++) { - if (locChildren[i]) - locChildren[i].visit(context); - } + + if (locChildren) { + this.sortAllChildren(); + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) + locChildren[i].visit(context); } } + context.restore(); }, @@ -620,17 +587,19 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * sortAllChildren:function () { if (this._reorderChildDirty) { var i, j = 0, locChildren = this._children; - var length = locChildren.length; + var length = locChildren.length, tempChild; //insertion sort for (i = 1; i < length; i++) { var tempItem = locChildren[i]; j = i - 1; - - //continue moving element downwards while zOrder is smaller or when zOrder is the same but orderOfArrival is smaller - while (j >= 0 && (tempItem.getZOrder() < locChildren[j].getZOrder() || - (tempItem.getZOrder() == locChildren[j].getZOrder() && tempItem.getOrderOfArrival() < locChildren[j].getOrderOfArrival()))) { - locChildren[j + 1] = locChildren[j]; - j--; + 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 ))) { + tempChild = locChildren[j]; + locChildren[j + 1] = tempChild; + j = j - 1; } locChildren[j + 1] = tempItem; } @@ -642,20 +611,6 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * } this._reorderChildDirty = false; } - }, - - /** - * draw cc.SpriteBatchNode (override draw of cc.Node) - * @param {CanvasRenderingContext2D} ctx - */ - draw:function (ctx) { - var context = ctx || cc.renderContext; - //context.globalAlpha = this._opacity / 255; - var posX = 0 | ( -this._anchorPointInPoints.x), posY = 0 | ( -this._anchorPointInPoints.y); - var locRenderTexture = this._renderTexture; - //direct draw image by canvas drawImage - if (locRenderTexture) - context.drawImage(locRenderTexture.getCanvas(), posX, -(posY + locRenderTexture.getCanvas().height)); } }); @@ -1265,11 +1220,10 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ /** * don't call visit on it's children ( override visit of cc.Node ) * @override - * @param {CanvasContext} ctx + * @param {WebGLRenderingContext} ctx */ visit:function (ctx) { var gl = ctx || cc.renderContext; - //cc.PROFILER_START_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit"); // CAREFUL: // This visit is almost identical to CocosNode#visit @@ -1292,7 +1246,6 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ this._grid.afterDraw(this); cc.kmGLPopMatrix(); this.setOrderOfArrival(0); - //cc.PROFILER_STOP_CATEGORY(kCCProfilerCategoryBatchSprite, "CCSpriteBatchNode - visit"); }, /** @@ -1349,17 +1302,19 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ sortAllChildren:function () { if (this._reorderChildDirty) { var childrenArr = this._children; - var i, j = 0, length = childrenArr.length; + var i, j = 0, length = childrenArr.length, tempChild; //insertion sort for (i = 1; i < length; i++) { var tempItem = childrenArr[i]; j = i - 1; - - //continue moving element downwards while zOrder is smaller or when zOrder is the same but orderOfArrival is smaller - while (j >= 0 && (tempItem.getZOrder() < childrenArr[j].getZOrder() || - (tempItem.getZOrder() == childrenArr[j].getZOrder() && tempItem.getOrderOfArrival() < childrenArr[j].getOrderOfArrival()))) { - childrenArr[j + 1] = childrenArr[j]; - j--; + tempChild = childrenArr[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 ))) { + tempChild = childrenArr[j]; + childrenArr[j + 1] = tempChild; + j = j - 1; } childrenArr[j + 1] = tempItem; } diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index 4a4539ffc8..47aa16b306 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -69,6 +69,9 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ //used for retina display _contentScaleFactor: null, + _cacheCanvas:null, + _cacheContext:null, + /** * Constructor */ @@ -76,9 +79,93 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ cc.SpriteBatchNode.prototype.ctor.call(this); this._children = []; this._descendants = []; - this._useCache = true; + this._layerSize = cc.SizeZero(); this._mapTileSize = cc.SizeZero(); + + if(cc.renderContextType === cc.CANVAS){ + var locCanvas = cc.canvas; + var tmpCanvas = document.createElement('canvas'); + tmpCanvas.width = locCanvas.width; + tmpCanvas.height = locCanvas.height; + this._cacheCanvas = tmpCanvas; + this._cacheContext = this._cacheCanvas.getContext('2d'); + this.setContentSize(cc.size(locCanvas.width, locCanvas.height)); + } + }, + + setContentSize:function (size) { + if (!size) + return; + cc.Node.prototype.setContentSize.call(this, size); + + if(cc.renderContextType === cc.CANVAS){ + this._cacheCanvas.width = size.width * 1.5; + this._cacheCanvas.height = size.height * 1.5; + this._cacheContext.translate(0, this._cacheCanvas.height); + } + }, + + /** + * Return texture of cc.SpriteBatchNode + * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} + */ + getTexture:function () { + return this._cacheCanvas; + }, + + /** + * don't call visit on it's children ( override visit of cc.Node ) + * @override + * @param {CanvasRenderingContext2D} ctx + */ + visit:function (ctx) { + if (cc.renderContextType === cc.WEBGL) { + cc.SpriteBatchNode.prototype.visit.call(this, ctx); + return; + } + var context = ctx || cc.renderContext; + // quick return if not visible + if (!this._visible) + return; + + context.save(); + this.transform(ctx); + var i, locChildren = this._children; + + if (this._cacheDirty) { + //add dirty region + var locCacheContext = this._cacheContext, locCacheCanvas = this._cacheCanvas; + locCacheContext.clearRect(0, 0, locCacheCanvas.width, -locCacheCanvas.height); + locCacheContext.save(); + locCacheContext.translate(this._anchorPointInPoints.x, -(this._anchorPointInPoints.y )); + if (locChildren) { + this.sortAllChildren(); + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) + locChildren[i].visit(locCacheContext); + } + } + locCacheContext.restore(); + this._cacheDirty = false; + } + // draw RenderTexture + this.draw(ctx); + context.restore(); + }, + + /** + * draw cc.SpriteBatchNode (override draw of cc.Node) + * @param {CanvasRenderingContext2D} ctx + */ + draw:function (ctx) { + var context = ctx || cc.renderContext; + //context.globalAlpha = this._opacity / 255; + var posX = 0 | ( -this._anchorPointInPoints.x), posY = 0 | ( -this._anchorPointInPoints.y); + var locCacheCanvas = this._cacheCanvas; + //direct draw image by canvas drawImage + if (locCacheCanvas) + context.drawImage(locCacheCanvas, posX, -(posY + locCacheCanvas.height)); }, /** diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/GUI/CCControlExtension/CCControl.js index 905942a8b8..79b890e607 100644 --- a/extensions/GUI/CCControlExtension/CCControl.js +++ b/extensions/GUI/CCControlExtension/CCControl.js @@ -176,7 +176,7 @@ cc.Control = cc.LayerRGBA.extend({ this._super(); }, registerWithTouchDispatcher:function () { - cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, cc.MENU_HANDLER_PRIORITY, true); + cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this.getTouchPriority(), true); }, /** diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/GUI/CCControlExtension/CCControlButton.js index 159996cf82..4612689f3e 100644 --- a/extensions/GUI/CCControlExtension/CCControlButton.js +++ b/extensions/GUI/CCControlExtension/CCControlButton.js @@ -490,7 +490,7 @@ cc.ControlButton = cc.Control.extend({ * If a property is not specified for a state, the default is to use * the CCButtonStateNormal value. * - * @param title The title label to use for the specified state. + * @param titleLabel The title label to use for the specified state. * @param state The state that uses the specified title. The values are described * in "CCControlState". */ From eeaef0222157798e048c9360e4967dabcad2621d Mon Sep 17 00:00:00 2001 From: NeroChan Date: Wed, 7 Aug 2013 17:04:22 +0800 Subject: [PATCH 027/141] fixed #2497 : setSearchPaths Bug --- cocos2d/sprite_nodes/CCSprite.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index a514f31fe3..64fb10c0eb 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -929,6 +929,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ var selfPointer = this; var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { + filename = cc.FileUtils.getInstance().fullPathForFilename(filename); this._visible = false; var loadImg = new Image(); loadImg.addEventListener("load", function () { @@ -2127,6 +2128,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { + filename = cc.FileUtils.getInstance().fullPathForFilename(filename); this._visible = false; var loadImg = new Image(); loadImg.addEventListener("load", function () { From 285555b22af1c0dbf6903c8d147130eef03ae2da Mon Sep 17 00:00:00 2001 From: xingsenma Date: Fri, 2 Aug 2013 15:35:23 +0800 Subject: [PATCH 028/141] Fixed #2444 Re-write cc.Texture for Canvas Mode. Texture2D was used Image/Canvas instead on Canvas Mode , now rewritten it. Conflicts: cocos2d/misc_nodes/CCRenderTexture.js cocos2d/sprite_nodes/CCSprite.js extensions/GUI/CCControlExtension/CCScale9Sprite.js --- cocos2d/CCLoader.js | 13 +- cocos2d/base_nodes/CCAtlasNode.js | 20 +- cocos2d/label_nodes/CCLabelBMFont.js | 7 +- cocos2d/misc_nodes/CCProgressTimer.js | 17 +- cocos2d/particle_nodes/CCParticleSystem.js | 5 +- .../particle_nodes/CCParticleSystemQuad.js | 37 +-- cocos2d/sprite_nodes/CCAnimation.js | 6 +- cocos2d/sprite_nodes/CCSprite.js | 151 +++++---- cocos2d/sprite_nodes/CCSpriteFrameCache.js | 13 +- cocos2d/textures/CCTexture2D.js | 309 ++++++++++-------- cocos2d/textures/CCTextureCache.js | 46 ++- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 3 +- extensions/CCBReader/CCBReader.js | 6 +- .../GUI/CCControlExtension/CCControlSwitch.js | 21 +- .../GUI/CCControlExtension/CCScale9Sprite.js | 9 +- samples | 2 +- 16 files changed, 342 insertions(+), 323 deletions(-) diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index f2ea27542d..3b4b6d8cb5 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -437,14 +437,11 @@ cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{ }, _initStage: function (centerPos) { - if (cc.renderContextType === cc.CANVAS) { - this._logo = cc.Sprite.createWithTexture(this._logoTexture); - } else { - this._texture2d = new cc.Texture2D(); - this._texture2d.initWithElement(this._logoTexture); - this._texture2d.handleLoadedTexture(); - this._logo = cc.Sprite.createWithTexture(this._texture2d); - } + this._texture2d = new cc.Texture2D(); + this._texture2d.initWithElement(this._logoTexture); + this._texture2d.handleLoadedTexture(); + this._logo = cc.Sprite.createWithTexture(this._texture2d); + this._logo.setPosition(centerPos); this._bgLayer.addChild(this._logo, 10); diff --git a/cocos2d/base_nodes/CCAtlasNode.js b/cocos2d/base_nodes/CCAtlasNode.js index fa64826a00..fb3e1d34cb 100644 --- a/cocos2d/base_nodes/CCAtlasNode.js +++ b/cocos2d/base_nodes/CCAtlasNode.js @@ -201,13 +201,19 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ temp.b = temp.b * this._displayedOpacity / 255; } cc.NodeRGBA.prototype.setColor.call(this, color3); + if (this.getTexture()) { - var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture); + var element = this._originalTexture.getHtmlElementObj(); + if(!element) + return; + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); if (cacheTextureForColor) { - var tx = this._originalTexture; - var textureRect = cc.rect(0, 0, tx.width, tx.height); - var colorTexture = cc.generateTintImage(tx, cacheTextureForColor, this._realColor, textureRect); - this.setTexture(colorTexture); + var textureRect = cc.rect(0, 0, element.width, element.height); + element = cc.generateTintImage(element, cacheTextureForColor, this._realColor, textureRect); + var locTexture = new cc.Texture2D(); + locTexture.initWithElement(element); + locTexture.handleLoadedTexture(); + this.setTexture(locTexture); } } }, @@ -234,7 +240,7 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ }, /** sets a new texture. it will be retained - * @param {HTMLCanvasElement|HTMLImageElement} texture + * @param {cc.Texture2D} texture */ setTexture:function (texture) { this._textureForCanvas = texture; @@ -242,7 +248,7 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ _calculateMaxItems:function () { var selTexture = this.getTexture(); - var size = cc.size(selTexture.width, selTexture.height); + var size = selTexture.getContentSize(); this._itemsPerColumn = 0 | (size.height / this._itemHeight); this._itemsPerRow = 0 | (size.width / this._itemWidth); diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index 421d707939..fc25cc3aec 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -643,8 +643,11 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._configuration = newConf; this._fntFile = fntFile; texture = cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName()); - } else - texture = (cc.renderContextType === cc.CANVAS) ? new Image() : new cc.Texture2D(); + } else{ + texture = new cc.Texture2D(); + var image = new Image(); + texture.initWithElement(image); + } if (this.initWithTexture(texture, theString.length)) { this._alignment = alignment || cc.TEXT_ALIGNMENT_LEFT; diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index 42b181adf1..2d14f6ef45 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -311,21 +311,22 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * var pos; var offsetPixels = locSprite._offsetPosition, locSpriteTexture = locSprite._texture, locSpriteRect = locSprite._rect; var locOrigin = this._origin; + var locElement = locSpriteTexture.getHtmlElementObj(); if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { pos = cc.p(( -spriteAnchorPoint.x + offsetPixels.x + this._drawPosition.x), ( -spriteAnchorPoint.y + offsetPixels.y + this._drawPosition.y)); var locOriginSize = this._originSize; - if (locSpriteTexture instanceof HTMLImageElement) { + if (locElement instanceof HTMLImageElement) { if ((locOriginSize.width != 0) && (locOriginSize.height != 0)) { - context.drawImage(locSpriteTexture, + context.drawImage(locElement, locSpriteRect.x + locOrigin.x, locSpriteRect.y + locOrigin.y, locOriginSize.width, locOriginSize.height, pos.x, -(pos.y + this._drawSize.height), locOriginSize.width, locOriginSize.height); } - } else if (locSpriteTexture instanceof HTMLCanvasElement) { + } else if (locElement instanceof HTMLCanvasElement) { if ((locOriginSize.width != 0) && (locOriginSize.height != 0)) { - context.drawImage(locSpriteTexture, + context.drawImage(locElement, locOrigin.x, locOrigin.y, locOriginSize.width, locOriginSize.height, pos.x, -(pos.y + this._drawSize.height), @@ -342,14 +343,14 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * pos = cc.p(0 | ( -spriteAnchorPoint.x + offsetPixels.x), 0 | ( -spriteAnchorPoint.y + offsetPixels.y)); - if (locSpriteTexture instanceof HTMLImageElement) { - context.drawImage(locSpriteTexture, + if (locElement instanceof HTMLImageElement) { + context.drawImage(locElement, locSpriteRect.x, locSpriteRect.y, locSpriteRect.width, locSpriteRect.height, pos.x, -(pos.y + locSpriteRect.height), locSpriteRect.width, locSpriteRect.height); - } else if (locSpriteTexture instanceof HTMLCanvasElement) { - context.drawImage(locSpriteTexture, + } else if (locElement instanceof HTMLCanvasElement) { + context.drawImage(locElement, 0, 0, locSpriteRect.width, locSpriteRect.height, pos.x, -(pos.y + locSpriteRect.height), diff --git a/cocos2d/particle_nodes/CCParticleSystem.js b/cocos2d/particle_nodes/CCParticleSystem.js index 79e8c43f9c..7a2ec5c0b6 100644 --- a/cocos2d/particle_nodes/CCParticleSystem.js +++ b/cocos2d/particle_nodes/CCParticleSystem.js @@ -1454,10 +1454,7 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ cc.Assert(addTexture != null, "cc.ParticleSystem: error loading the texture"); - if (cc.renderContextType === cc.CANVAS) - this.setTexture(canvasObj); - else - this.setTexture(addTexture); + this.setTexture(addTexture); } } diff --git a/cocos2d/particle_nodes/CCParticleSystemQuad.js b/cocos2d/particle_nodes/CCParticleSystemQuad.js index d8b9a4f132..743932d362 100644 --- a/cocos2d/particle_nodes/CCParticleSystemQuad.js +++ b/cocos2d/particle_nodes/CCParticleSystemQuad.js @@ -108,13 +108,8 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua var high = pointRect.height; if (this._texture) { - if ((this._texture instanceof HTMLImageElement) || (this._texture instanceof HTMLCanvasElement)) { - wide = this._texture.width; - high = this._texture.height; - } else { - wide = this._texture.getPixelsWide(); - high = this._texture.getPixelsHigh(); - } + wide = this._texture.getPixelsWide(); + high = this._texture.getPixelsHigh(); } if(cc.renderContextType === cc.CANVAS) @@ -273,10 +268,7 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua retParticle._opacityModifyRGB = this._opacityModifyRGB; // texture - if (this._texture instanceof cc.Texture2D) - retParticle._texture = this._texture; - else - retParticle._texture = this._texture; + retParticle._texture = this._texture; } } return retParticle; @@ -358,11 +350,8 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua cc.ParticleSystem.prototype.setTexture.call(this, texture); return; } - var size = null; - if ((texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) - size = cc.size(texture.width, texture.height); - else - size = texture.getContentSize(); + + var size = texture.getContentSize(); this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height)); }, @@ -531,10 +520,10 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua if (this._drawMode == cc.PARTICLE_TEXTURE_MODE) { - var drawTexture = this.getTexture(); + var element = this._texture.getHtmlElementObj(); // Delay drawing until the texture is fully loaded by the browser - if (!drawTexture.width || !drawTexture.height) + if (!element.width || !element.height) continue; context.save(); @@ -557,21 +546,21 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua context.translate(-(0 | (w / 2)), -(0 | (h / 2))); if (particle.isChangeColor) { - var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(drawTexture); + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); if (cacheTextureForColor) { // Create another cache for the tinted version // This speeds up things by a fair bit if (!cacheTextureForColor.tintCache) { cacheTextureForColor.tintCache = document.createElement('canvas'); - cacheTextureForColor.tintCache.width = drawTexture.width; - cacheTextureForColor.tintCache.height = drawTexture.height; + cacheTextureForColor.tintCache.width = element.width; + cacheTextureForColor.tintCache.height = element.height; } - cc.generateTintImage(drawTexture, cacheTextureForColor, particle.color, this._pointRect, cacheTextureForColor.tintCache); - drawTexture = cacheTextureForColor.tintCache; + cc.generateTintImage(element, cacheTextureForColor, particle.color, this._pointRect, cacheTextureForColor.tintCache); + element = cacheTextureForColor.tintCache; } } - context.drawImage(drawTexture, 0, 0); + context.drawImage(element, 0, 0); context.restore(); } else { diff --git a/cocos2d/sprite_nodes/CCAnimation.js b/cocos2d/sprite_nodes/CCAnimation.js index e1cc01cdcb..912b042855 100644 --- a/cocos2d/sprite_nodes/CCAnimation.js +++ b/cocos2d/sprite_nodes/CCAnimation.js @@ -199,11 +199,7 @@ cc.Animation = cc.Class.extend(/** @lends cc.Animation# */{ addSpriteFrameWithFile:function (fileName) { var texture = cc.TextureCache.getInstance().addImage(fileName); var rect = cc.RectZero(); - if ((texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) { - rect.size = cc.size(texture.width, texture.height); - } else { - rect.size = texture.getContentSize(); - } + rect.size = texture.getContentSize(); var frame = cc.SpriteFrame.createWithTexture(texture, rect); this.addSpriteFrame(frame); }, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index aa8a5540a1..3a88542f5d 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -207,7 +207,7 @@ cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCan ctx.drawImage(tintedImgCache[2], rect.x, rect.y, w, h, 0, 0, w, h); } - if((selColor.r === 0) && (selColor.g === 0) &&(selColor.b === 0)){ + if ((selColor.r === 0) && (selColor.g === 0) && (selColor.b === 0)) { ctx.globalAlpha = a; ctx.drawImage(tintedImgCache[3], rect.x, rect.y, w, h, 0, 0, w, h); } @@ -257,7 +257,7 @@ cc.TransformValues = function (pos, scale, rotation, skew, ap, visible) { cc.RENDER_IN_SUBPIXEL = function (A) { return (0 | A); }; -if(cc.SPRITEBATCHNODE_RENDER_SUBPIXEL){ +if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) { cc.RENDER_IN_SUBPIXEL = function (A) { return A; }; @@ -298,28 +298,28 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // // Data used when the sprite is rendered using a CCSpriteSheet // - _textureAtlas:null, //cc.SpriteBatchNode texture atlas + _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 + _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 + _blendFunc:null, //It's required for CCTextureProtocol inheritance + _texture:null, //cc.Texture2D object that is used to render the sprite // // Shared data // // texture - _rect:cc.rect(0, 0, 0, 0), //Retangle of cc.Texture2D - _rectRotated:false, //Whether the texture is rotated + _rect:cc.rect(0, 0, 0, 0), //Retangle of cc.Texture2D + _rectRotated:false, //Whether the texture is rotated // Offset Position (used by Zwoptex) _offsetPosition:null, // absolute @@ -328,8 +328,8 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ _opacityModifyRGB:false, // image is flipped - _flipX:false, //Whether the sprite is flipped horizontally or not. - _flipY:false, //Whether the sprite is flipped vertically or not. + _flipX:false, //Whether the sprite is flipped horizontally or not. + _flipY:false, //Whether the sprite is flipped vertically or not. /** * Whether or not the Sprite needs to be updated in the Atlas @@ -703,7 +703,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ */ ignoreAnchorPointForPosition:function (relative) { cc.Assert(!this._batchNode, "ignoreAnchorPointForPosition is invalid in cc.Sprite"); - cc.Node.prototype.ignoreAnchorPointForPosition.call(this,relative); + cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); }, /** @@ -768,7 +768,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ * @param {Boolean} modify */ setOpacityModifyRGB:function (modify) { - if(this._opacityModifyRGB !== modify){ + if (this._opacityModifyRGB !== modify) { this._opacityModifyRGB = modify; this.setNodeDirty(); } @@ -782,7 +782,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ return this._opacityModifyRGB; }, - updateDisplayedOpacity:function(parentOpacity){ + updateDisplayedOpacity:function (parentOpacity) { cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); this._changeTextureColor(); this.setNodeDirty(); @@ -860,6 +860,11 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ this.initWithBatchNode(fileName, rect); } } 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) } } @@ -884,7 +889,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ * @return {Boolean} */ init:function () { - if(arguments.length > 0) + if (arguments.length > 0) return this.initWithFile(arguments[0], arguments[1]); cc.NodeRGBA.prototype.init.call(this); @@ -938,7 +943,10 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ rect = cc.rect(0, 0, loadImg.width, loadImg.height); rect = cc.RECT_PIXELS_TO_POINTS(rect); } - selfPointer.initWithTexture(loadImg, rect); + var texture2d = new cc.Texture2D(); + texture2d.initWithElement(loadImg); + texture2d.handleLoadedTexture(); + selfPointer.initWithTexture(texture2d, rect); cc.TextureCache.getInstance().cacheImage(filename, loadImg); selfPointer._visible = true; }); @@ -948,13 +956,11 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ loadImg.src = filename; return true; } else { - if (texture) { - if (!rect) { - rect = cc.rect(0, 0, texture.width, texture.height); - rect = cc.RECT_PIXELS_TO_POINTS(rect); - } - return this.initWithTexture(texture, rect); + if (!rect) { + var size = texture.getContentSize(); + rect = cc.rect(0, 0, size.width, size.height); } + return this.initWithTexture(texture, rect); } return false; }, @@ -978,7 +984,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ rotated = rotated || false; - if(!cc.NodeRGBA.prototype.init.call(this)) + if (!cc.NodeRGBA.prototype.init.call(this)) return false; this._batchNode = null; @@ -1001,8 +1007,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (!rect) { rect = cc.rect(0, 0, 0, 0); - if ((texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) { - rect.size = cc.size(texture.width, texture.height); + rect.size = texture.getContentSize(); rect = cc.RECT_PIXELS_TO_POINTS(rect); } } @@ -1120,7 +1125,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ this.setNodeDirty(); }, - updateDisplayedColor:function(parentColor){ + updateDisplayedColor:function (parentColor) { cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); this._changeTextureColor(); this.setNodeDirty(); @@ -1211,14 +1216,9 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ */ setTexture:function (texture) { // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet - cc.Assert(!texture || texture instanceof HTMLImageElement || texture instanceof HTMLCanvasElement, "setTexture expects a CCTexture2D. Invalid argument"); - + cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument"); if (this._texture != texture) { - if (texture instanceof HTMLImageElement) { - if (!this._rect || cc.rectEqualToRect(this._rect, cc.RectZero())) { - this._rect = cc.rect(0, 0, texture.width, texture.height); - this._rect = cc.RECT_PIXELS_TO_POINTS(this._rect); - } + if(texture&&texture.getHtmlElementObj() instanceof HTMLImageElement){ this._originalTexture = texture; } this._texture = texture; @@ -1226,17 +1226,25 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ }, _changeTextureColor:function () { - if (this.getTexture()) { - var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture); + var locElement, locTexture = this._texture; + if (locTexture) { + locElement = locTexture.getHtmlElementObj(); + if (!locElement) + return; + + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj()); if (cacheTextureForColor) { this._colorized = true; //generate color texture cache - var rect = cc.RECT_POINTS_TO_PIXELS(this._rect); - if (this._texture instanceof HTMLCanvasElement && !this._rectRotated) - cc.generateTintImage(this.getTexture(), cacheTextureForColor, this._displayedColor, rect, this._texture); + if (locElement instanceof HTMLCanvasElement && !this._rectRotated) + cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect(), locElement); else { - var colorTexture = cc.generateTintImage(this.getTexture(), cacheTextureForColor, this._displayedColor, rect); - this.setTexture(colorTexture); + + locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect()); + locTexture = new cc.Texture2D(); + locTexture.initWithElement(locElement); + locTexture.handleLoadedTexture(); + this.setTexture(locTexture); } } } @@ -1263,13 +1271,13 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ context.scale(1, -1); } if (this._texture) { - var scaleFactor = cc.CONTENT_SCALE_FACTOR(); + var image = this._texture.getHtmlElementObj(); if (this._colorized) { - context.drawImage(this._texture, + context.drawImage(image, 0, 0, locRect.width * scaleFactor, locRect.height * scaleFactor, flipXOffset, flipYOffset, locRect.width, locRect.height); } else { - context.drawImage(this._texture, + context.drawImage(image, locRect.x * scaleFactor, locRect.y * scaleFactor, locRect.width * scaleFactor, locRect.height * scaleFactor, flipXOffset, flipYOffset, locRect.width, locRect.height); } @@ -1334,28 +1342,28 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ // // Data used when the sprite is rendered using a CCSpriteSheet // - _textureAtlas:null, //cc.SpriteBatchNode texture atlas + _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 + _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 + _blendFunc:null, //It's required for CCTextureProtocol inheritance + _texture:null, //cc.Texture2D object that is used to render the sprite // // Shared data // // texture - _rect:cc.rect(0, 0, 0, 0), //Retangle of cc.Texture2D - _rectRotated:false, //Whether the texture is rotated + _rect:cc.rect(0, 0, 0, 0), //Retangle of cc.Texture2D + _rectRotated:false, //Whether the texture is rotated // Offset Position (used by Zwoptex) _offsetPosition:null, // absolute @@ -1365,8 +1373,8 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ _opacityModifyRGB:false, // image is flipped - _flipX:false, //Whether the sprite is flipped horizontally or not. - _flipY:false, //Whether the sprite is flipped vertically or not. + _flipX:false, //Whether the sprite is flipped horizontally or not. + _flipY:false, //Whether the sprite is flipped vertically or not. /** * Whether or not the Sprite needs to be updated in the Atlas @@ -1750,7 +1758,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ */ ignoreAnchorPointForPosition:function (relative) { cc.Assert(!this._batchNode, "ignoreAnchorPointForPosition is invalid in cc.Sprite"); - cc.Node.prototype.ignoreAnchorPointForPosition.call(this,relative); + cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); }, /** @@ -1829,7 +1837,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ return this._opacityModifyRGB; }, - updateDisplayedOpacity:function(parentOpacity){ + updateDisplayedOpacity:function (parentOpacity) { cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); this.updateColor(); }, @@ -1877,7 +1885,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ }, /// ---- common properties end ---- - _quad:null, // vertex coords, texture coords and color info + _quad:null, // vertex coords, texture coords and color info _quadWebBuffer:null, _quadDirty:false, @@ -1946,7 +1954,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * @return {Boolean} */ init:function () { - if(arguments.length > 0) + if (arguments.length > 0) return this.initWithFile(arguments[0], arguments[1]); cc.NodeRGBA.prototype.init.call(this); @@ -2051,7 +2059,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ rotated = rotated || false; - if(!cc.NodeRGBA.prototype.init.call(this)) + if (!cc.NodeRGBA.prototype.init.call(this)) return false; this._batchNode = null; @@ -2252,11 +2260,10 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ updateColor:function () { var color4 = {r:this._displayedColor.r, g:this._displayedColor.g, b:this._displayedColor.b, a:this._displayedOpacity}; // special opacity for premultiplied textures - if (this._opacityModifyRGB) - { - color4.r *= this._displayedOpacity/255.0; - color4.g *= this._displayedOpacity/255.0; - color4.b *= this._displayedOpacity/255.0; + if (this._opacityModifyRGB) { + color4.r *= this._displayedOpacity / 255.0; + color4.g *= this._displayedOpacity / 255.0; + color4.b *= this._displayedOpacity / 255.0; } this._quad.bl.colors = color4; this._quad.br.colors = color4; @@ -2297,7 +2304,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ this.updateColor(); }, - updateDisplayedColor:function(parentColor){ + updateDisplayedColor:function (parentColor) { cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); this.updateColor(); }, @@ -2390,7 +2397,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ // If batchnode, then texture id should be the same cc.Assert(!this._batchNode, "cc.Sprite: Batched sprites should use the same texture as the batchnode"); - if(texture) + if (texture) this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); else this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); @@ -2504,7 +2511,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ //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){ + if (locTexture._isLoaded) { this._shaderProgram.use(); this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); @@ -2514,7 +2521,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX); gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); - if(this._quadDirty){ + if (this._quadDirty) { gl.bufferData(gl.ARRAY_BUFFER, this._quad.arrayBuffer, gl.DYNAMIC_DRAW); this._quadDirty = false; } @@ -2534,7 +2541,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_COLOR); gl.bindBuffer(gl.ARRAY_BUFFER, this._quadWebBuffer); - if(this._quadDirty){ + if (this._quadDirty) { cc.renderContext.bufferData(cc.renderContext.ARRAY_BUFFER, this._quad.arrayBuffer, cc.renderContext.STATIC_DRAW); this._quadDirty = false; } @@ -2543,7 +2550,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } cc.g_NumberOfDraws++; - if(cc.SPRITE_DEBUG_DRAW === 0) + if (cc.SPRITE_DEBUG_DRAW === 0) return; if (cc.SPRITE_DEBUG_DRAW === 1) { diff --git a/cocos2d/sprite_nodes/CCSpriteFrameCache.js b/cocos2d/sprite_nodes/CCSpriteFrameCache.js index c6d7b9da23..f0dc3faadb 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrameCache.js +++ b/cocos2d/sprite_nodes/CCSpriteFrameCache.js @@ -138,10 +138,16 @@ cc.SpriteFrameCache = cc.Class.extend(/** @lends cc.SpriteFrameCache# */{ if(cc.renderContextType === cc.CANVAS && spriteFrame.isRotated()){ //clip to canvas - var tempTexture = cc.cutRotateImageToCanvas(spriteFrame.getTexture(), spriteFrame.getRect()); + var tempElement = spriteFrame.getTexture().getHtmlElementObj(); + tempElement = cc.cutRotateImageToCanvas(tempElement, spriteFrame.getRect()); + var tempTexture = new cc.Texture2D(); + tempTexture.initWithElement(tempElement); + tempTexture.handleLoadedTexture(); + spriteFrame.setTexture(tempTexture); + var rect = spriteFrame.getRect(); spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height)); - spriteFrame.setTexture(tempTexture); + } // add sprite frame @@ -225,7 +231,8 @@ cc.SpriteFrameCache = cc.Class.extend(/** @lends cc.SpriteFrameCache# */{ } break; case 2: - if ((texture instanceof cc.Texture2D) || (texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) { + //if ((texture instanceof cc.Texture2D) || (texture instanceof HTMLImageElement) || (texture instanceof HTMLCanvasElement)) { + if (texture instanceof cc.Texture2D) { /** Adds multiple Sprite Frames from a plist file. The texture will be associated with the created sprite frames. */ this._addSpriteFramesWithDictionary(dict, texture); } else { diff --git a/cocos2d/textures/CCTexture2D.js b/cocos2d/textures/CCTexture2D.js index 03fc2d2867..8d56928595 100644 --- a/cocos2d/textures/CCTexture2D.js +++ b/cocos2d/textures/CCTexture2D.js @@ -170,9 +170,9 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ this._webTextureObj = null; }, - releaseTexture:function(){ - if(this._webTextureObj) - cc.renderContext.deleteTexture(this._webTextureObj); + releaseTexture:function () { + if (this._webTextureObj) + cc.renderContext.deleteTexture(this._webTextureObj); }, /** @@ -185,7 +185,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ /** * width in pixels - * @return {Number} + * @return {Number} */ getPixelsWide:function () { return this._pixelsWide; @@ -211,7 +211,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * content size * @return {cc.Size} */ - getContentSize:function(){ + getContentSize:function () { return cc.size(this._contentSize.width / cc.CONTENT_SCALE_FACTOR(), this._contentSize.height / cc.CONTENT_SCALE_FACTOR()); }, @@ -241,7 +241,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * return shader program used by drawAtPoint and drawInRect * @return {cc.GLProgram} */ - getShaderProgram:function(){ + getShaderProgram:function () { return this._shaderProgram; }, @@ -249,7 +249,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * set shader program used by drawAtPoint and drawInRect * @param {cc.GLProgram} shaderProgram */ - setShaderProgram:function(shaderProgram){ + setShaderProgram:function (shaderProgram) { this._shaderProgram = shaderProgram; }, @@ -261,7 +261,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ return this._hasPremultipliedAlpha; }, - hasMipmaps:function(){ + hasMipmaps:function () { return this._hasMipmaps; }, @@ -293,64 +293,66 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * @return {Boolean} */ initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) { - var gl = cc.renderContext; - - var bitsPerPixel = 0; - //Hack: bitsPerPixelForFormat returns wrong number for RGB_888 textures. See function. - if(pixelFormat === cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888){ - bitsPerPixel = 24; - }else{ - bitsPerPixel = this.bitsPerPixelForFormat(pixelFormat); - } + if (cc.Browser.supportWebGL) { + var gl = cc.renderContext; - var bytesPerRow = pixelsWide * bitsPerPixel/8; - if(bytesPerRow % 8 === 0){ - gl.pixelStorei(gl.UNPACK_ALIGNMENT,8); - } else if(bytesPerRow % 4 === 0){ - gl.pixelStorei(gl.UNPACK_ALIGNMENT,4); - } else if(bytesPerRow % 2 === 0){ - gl.pixelStorei(gl.UNPACK_ALIGNMENT,2); - } else { - gl.pixelStorei(gl.UNPACK_ALIGNMENT,1); - } - - this._webTextureObj = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this._webTextureObj); + var bitsPerPixel = 0; + //Hack: bitsPerPixelForFormat returns wrong number for RGB_888 textures. See function. + if (pixelFormat === cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888) { + bitsPerPixel = 24; + } else { + bitsPerPixel = this.bitsPerPixelForFormat(pixelFormat); + } - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); + var bytesPerRow = pixelsWide * bitsPerPixel / 8; + if (bytesPerRow % 8 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8); + } else if (bytesPerRow % 4 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); + } else if (bytesPerRow % 2 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2); + } else { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); + } - // Specify OpenGL texture image - switch (pixelFormat) { - case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_AI88: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, pixelsWide, pixelsHigh, 0, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_A8: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, pixelsWide, pixelsHigh, 0, gl.ALPHA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_I8: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, pixelsWide, pixelsHigh, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data); - break; - default: - cc.Assert(0, "NSInternalInconsistencyException"); - break; + this._webTextureObj = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, this._webTextureObj); + + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + // Specify OpenGL texture image + switch (pixelFormat) { + case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_AI88: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, pixelsWide, pixelsHigh, 0, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_A8: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, pixelsWide, pixelsHigh, 0, gl.ALPHA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_I8: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, pixelsWide, pixelsHigh, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data); + break; + default: + cc.Assert(0, "NSInternalInconsistencyException"); + break; + } } this._contentSize = contentSize; @@ -394,11 +396,11 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ point.x, height + point.y, 0.0, width + point.x, height + point.y, 0.0 ]; - cc.glEnableVertexAttribs( cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS ); + cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS); this._shaderProgram.use(); this._shaderProgram.setUniformsForBuiltins(); - cc.glBindTexture2D( this ); + cc.glBindTexture2D(this); var gl = cc.renderContext; gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices); @@ -423,11 +425,11 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ rect.x, rect.y + rect.height, /*0.0,*/ rect.x + rect.width, rect.y + rect.height /*0.0*/ ]; - cc.glEnableVertexAttribs( cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS ); + cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION | cc.VERTEX_ATTRIB_FLAG_TEXCOORDS); this._shaderProgram.use(); this._shaderProgram.setUniformsForBuiltins(); - cc.glBindTexture2D( this ); + cc.glBindTexture2D(this); var gl = cc.renderContext; gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, vertices); @@ -459,7 +461,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ var maxTextureSize = conf.getMaxTextureSize(); if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) { - cc.log("cocos2d: WARNING: Image (" + imageWidth + " x " + imageHeight+ ") is bigger than the supported " + maxTextureSize + " x " + maxTextureSize); + cc.log("cocos2d: WARNING: Image (" + imageWidth + " x " + imageHeight + ") is bigger than the supported " + maxTextureSize + " x " + maxTextureSize); return false; } this._isLoaded = true; @@ -468,39 +470,53 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ return this._initPremultipliedATextureWithImage(uiImage, imageWidth, imageHeight); }, - initWithElement:function(element){ - if(!element) + initWithElement:function (element) { + if (!element) return; - - this._webTextureObj = cc.renderContext.createTexture(); + if (cc.Browser.supportWebGL) { + this._webTextureObj = cc.renderContext.createTexture(); + } this._htmlElementObj = element; }, - isLoaded:function(){ - return this._isLoaded; + /** + * HTMLElement Object getter + * @return {HTMLElement} + */ + getHtmlElementObj:function(){ + return this._htmlElementObj; + }, + + isLoaded:function () { + return this._isLoaded; }, - handleLoadedTexture:function(){ + handleLoadedTexture:function () { this._isLoaded = true; //upload image to buffer - var gl = cc.renderContext; + if (cc.Browser.supportWebGL) { + var gl = cc.renderContext; - var pixelsWide = this._htmlElementObj.width; - var pixelsHigh = this._htmlElementObj.height; + cc.glBindTexture2D(this); - cc.glBindTexture2D(this); + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); + + // Specify OpenGL texture image + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._htmlElementObj); - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - // Specify OpenGL texture image - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._htmlElementObj); + this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE)); + gl.bindTexture(gl.TEXTURE_2D, null); + } - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + var pixelsWide = this._htmlElementObj.width; + var pixelsHigh = this._htmlElementObj.height; - this._contentSize = new cc.Size(pixelsWide,pixelsHigh); + this._contentSize = new cc.Size(pixelsWide, pixelsHigh); this._pixelsWide = pixelsWide; this._pixelsHigh = pixelsHigh; this._pixelFormat = cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888; @@ -510,9 +526,6 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ this._hasPremultipliedAlpha = false; this._hasMipmaps = false; - this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE)); - - gl.bindTexture(gl.TEXTURE_2D, null); }, /** @@ -539,20 +552,20 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ } /*if (cc.ENABLE_CACHE_TEXTURE_DATA) { - // cache the texture data - cc.VolatileTexture.addStringTexture(this, text, dimensions, alignment, fontName, fontSize); - }*/ + // cache the texture data + cc.VolatileTexture.addStringTexture(this, text, dimensions, alignment, fontName, fontSize); + }*/ var image = new cc.Image(); - var eAlign ; + var eAlign; - if(cc.VERTICAL_TEXT_ALIGNMENT_TOP === vAlignment){ + if (cc.VERTICAL_TEXT_ALIGNMENT_TOP === vAlignment) { eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_TOP : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_TOP_LEFT : cc.ALIGN_TOP_RIGHT; - }else if(cc.VERTICAL_TEXT_ALIGNMENT_CENTER === vAlignment){ + } else if (cc.VERTICAL_TEXT_ALIGNMENT_CENTER === vAlignment) { eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_CENTER : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_LEFT : cc.ALIGN_RIGHT; - }else if(cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM === vAlignment){ + } else if (cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM === vAlignment) { eAlign = (cc.TEXT_ALIGNMENT_CENTER === hAlignment) ? cc.ALIGN_BOTTOM : (cc.TEXT_ALIGNMENT_LEFT === hAlignment) ? cc.ALIGN_BOTTOM_LEFT : cc.ALIGN_BOTTOM_RIGHT; } else { @@ -571,7 +584,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * @param {String} file * @return {Boolean} */ - initWithETCFile:function(file){ + initWithETCFile:function (file) { return false; }, @@ -635,20 +648,22 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * @param texParams */ setTexParameters:function (texParams) { - var gl = cc.renderContext; + if (cc.Browser.supportWebGL) { + var gl = cc.renderContext; - cc.Assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) || - (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE), - "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures"); + cc.Assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) || + (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE), + "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures"); - cc.glBindTexture2D(this); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT); + cc.glBindTexture2D(this); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT); - //TODO - //VolatileTexture::setTexParameters(this, texParams); + //TODO + //VolatileTexture::setTexParameters(this, texParams); + } }, /** @@ -657,19 +672,21 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * - GL_TEXTURE_MAG_FILTER = GL_NEAREST */ setAntiAliasTexParameters:function () { - var gl = cc.renderContext; - - cc.glBindTexture2D(this); - if(!this._hasMipmaps) - gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.LINEAR); - else - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - //TODO - /*#if CC_ENABLE_CACHE_TEXTURE_DATA - ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE}; - VolatileTexture::setTexParameters(this, &texParams); - #endif*/ + if (cc.Browser.supportWebGL) { + var gl = cc.renderContext; + + cc.glBindTexture2D(this); + if (!this._hasMipmaps) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + else + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + //TODO + /*#if CC_ENABLE_CACHE_TEXTURE_DATA + ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE}; + VolatileTexture::setTexParameters(this, &texParams); + #endif*/ + } }, /** @@ -677,21 +694,23 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * GL_TEXTURE_MIN_FILTER = GL_NEAREST * GL_TEXTURE_MAG_FILTER = GL_NEAREST */ - setAliasTexParameters:function(){ - var gl = cc.renderContext; - - cc.glBindTexture2D(this); - if(!this._hasMipmaps) - gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.NEAREST); - else - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); - gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); - - //TODO - /*#if CC_ENABLE_CACHE_TEXTURE_DATA - ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE}; - VolatileTexture::setTexParameters(this, &texParams); - #endif*/ + setAliasTexParameters:function () { + if (cc.Browser.supportWebGL) { + var gl = cc.renderContext; + + cc.glBindTexture2D(this); + if (!this._hasMipmaps) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + else + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + //TODO + /*#if CC_ENABLE_CACHE_TEXTURE_DATA + ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE}; + VolatileTexture::setTexParameters(this, &texParams); + #endif*/ + } }, /** @@ -699,18 +718,20 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * It only works if the texture size is POT (power of 2). */ generateMipmap:function () { - cc.Assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures"); + if (cc.Browser.supportWebGL) { + cc.Assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures"); - cc.glBindTexture2D(this); - cc.renderContext.generateMipmap(cc.renderContext.TEXTURE_2D); - this._hasMipmaps = true; + cc.glBindTexture2D(this); + cc.renderContext.generateMipmap(cc.renderContext.TEXTURE_2D); + this._hasMipmaps = true; + } }, /** * returns the pixel format. * @return {String} */ - stringForFormat:function(){ + stringForFormat:function () { switch (this._pixelFormat) { case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888: return "RGBA8888"; @@ -743,11 +764,11 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ return "PVRTC2"; default: - cc.Assert(false , "unrecognized pixel format"); + cc.Assert(false, "unrecognized pixel format"); cc.log("stringForFormat: " + this._pixelFormat + ", cannot give useful result"); break; } - return ""; + return ""; }, /** diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index dd7a4b2cde..6c8925edf6 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -295,7 +295,9 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ delete that._textures[path]; }); texture.src = path; - this._textures[path] = texture; + var texture2d = new cc.Texture2D(); + texture2d.initWithElement(texture); + this._textures[path] = texture2d; } return this._textures[path]; }, @@ -327,6 +329,8 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ var that = this; texture.addEventListener("load", function () { cc.Loader.getInstance().onResLoaded(); + if (that._textures.hasOwnProperty(path)) + that._textures[path].handleLoadedTexture(); }); texture.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); @@ -335,7 +339,9 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ delete that._textures[path]; }); texture.src = path; - this._textures[path] = texture; + var texture2d = new cc.Texture2D(); + texture2d.initWithElement(texture); + this._textures[path] = texture2d; } return this._textures[path]; @@ -347,7 +353,14 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ * @param {Image|HTMLImageElement|HTMLCanvasElement} texture */ cacheImage:function (path, texture) { - this._textures[path] = texture; + if(texture instanceof cc.Texture2D){ + this._textures[path] = texture; + return ; + } + var texture2d = new cc.Texture2D(); + texture2d.initWithElement(texture); + texture2d.handleLoadedTexture(); + this._textures[path] = texture2d; }, /** @@ -363,16 +376,19 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ addUIImage:function (image, key) { cc.Assert(image != null, "TextureCache: image MUST not be nulll"); - if (key && this._textures.hasOwnProperty(key) && this._textures[key]) - return this._textures[key]; + if (key) { + if (this._textures.hasOwnProperty(key) && this._textures[key]) + return this._textures[key]; + } // prevents overloading the autorelease pool - if ((key != null) && (image != null)) - this._textures[key] = image; + var texture = new cc.Texture2D(); + texture.initWithImage(image); + if ((key != null) && (texture != null)) + this._textures[key] = texture; else cc.log("cocos2d: Couldn't add UIImage in TextureCache"); - - return image; + return texture; }, /** @@ -385,19 +401,19 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ for (var key in this._textures) { var selTexture = this._textures[key]; count++; - if (selTexture instanceof HTMLImageElement) - cc.log("cocos2d: '" + key + "' id=" + selTexture.src + " " + selTexture.width + " x " + selTexture.height); + if (selTexture.getHtmlElementObj() instanceof HTMLImageElement) + cc.log("cocos2d: '" + key + "' id=" + selTexture.getHtmlElementObj().src + " " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); else { - cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.width + " x " + selTexture.height); - totalBytes += selTexture.width * selTexture.height * 4; + cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); + totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; } } for (key in this._textureColorsCache) { var selCanvas = this._textureColorsCache[key]; count++; - cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.width + " x " + selCanvas.height); - totalBytes += selCanvas.width * selCanvas.height * 4; + cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.getPixelsWide() + " x " + selCanvas.getPixelsHigh()); + totalBytes += selCanvas.getPixelsWide() * selCanvas.getPixelsHigh() * 4; } cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for " diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index 47aa16b306..6a54eb99f4 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -525,8 +525,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ setupTiles:function () { // Optimization: quick hack that sets the image size on the tileset if (cc.renderContextType === cc.CANVAS) { - var textureCache = this._originalTexture; - this._tileSet.imageSize = cc.size(textureCache.width, textureCache.height); + this._tileSet.imageSize = this._originalTexture.getContentSizeInPixels(); } else { this._tileSet.imageSize = this._textureAtlas.getTexture().getContentSizeInPixels(); diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index 6d791ed86e..d2fb41301b 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -634,11 +634,7 @@ cc.BuilderReader = cc.Class.extend({ if (spriteSheet == "") { spriteFile = this._ccbRootPath + spriteFile; var texture = cc.TextureCache.getInstance().addImage(spriteFile); - var bounds; - if (cc.renderContextType == cc.CANVAS) - bounds = cc.RectMake(0, 0, texture.width, texture.height); - else - bounds = cc.RectMake(0, 0, texture.getContentSize().width, texture.getContentSize().height); + var bounds = cc.RectMake(0, 0, texture.getContentSize().width, texture.getContentSize().height); value = cc.SpriteFrame.createWithTexture(texture, bounds); } else { spriteSheet = this._ccbRootPath + spriteSheet; diff --git a/extensions/GUI/CCControlExtension/CCControlSwitch.js b/extensions/GUI/CCControlExtension/CCControlSwitch.js index eaa20a029d..d551196e1e 100644 --- a/extensions/GUI/CCControlExtension/CCControlSwitch.js +++ b/extensions/GUI/CCControlExtension/CCControlSwitch.js @@ -222,11 +222,7 @@ cc.ControlSwitchSprite = cc.Sprite.extend({ //this._maskLocation = cc.renderContext.getUniformLocation(this.getShaderProgram().getProgram(), "u_mask"); //cc.CHECK_GL_ERROR_DEBUG(); - if(cc.renderContextType==cc.CANVAS){ - this.setContentSize(cc.size(this._maskTexture.width,this._maskTexture.height)); - }else{ - this.setContentSize(this._maskTexture.getContentSize()); - } + this.setContentSize(this._maskTexture.getContentSize()); this.needsLayout(); return true; @@ -283,17 +279,10 @@ cc.ControlSwitchSprite = cc.Sprite.extend({ this._offLabel.setPosition(cc.p(this._offSprite.getPosition().x + this._thumbSprite.getContentSize().width / 6, this._offSprite.getContentSize().height / 2)); } - var rt ; - if(cc.renderContextType==cc.CANVAS){ - this._thumbSprite.setPosition(cc.p(this._onSprite.getContentSize().width + this._sliderXPosition, - this._maskTexture.height / 2)); - rt = cc.RenderTexture.create(this._maskTexture.width, this._maskTexture.height); - }else{ - this._thumbSprite.setPosition(cc.p(this._onSprite.getContentSize().width + this._sliderXPosition, - this._maskTexture.getContentSize().height / 2)); - rt = cc.RenderTexture.create(this._maskTexture.getContentSize().width, this._maskTexture.getContentSize().height); - } - + var locMaskSize = this._maskTexture.getContentSize(); + this._thumbSprite.setPosition(cc.p(this._onSprite.getContentSize().width + this._sliderXPosition, + locMaskSize.height / 2)); + var rt = cc.RenderTexture.create(locMaskSize.width, locMaskSize.height); rt.begin(); this._onSprite.visit(); diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 1a88e7a41b..bc26ba5c56 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -461,13 +461,8 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ // If there is no given rect if (cc.rectEqualToRect(rect, rectZero)) { // Get the texture size as original - if (selTexture instanceof cc.Texture2D) { - var textureSize = selTexture.getContentSize(); - rect = cc.RectMake(0, 0, textureSize.width, textureSize.height); - } else { - rect = cc.RectMake(0, 0, selTexture.width, selTexture.height); - rect = cc.RECT_PIXELS_TO_POINTS(rect); - } + var textureSize = selTexture.getContentSize(); + rect = cc.RectMake(0, 0, textureSize.width, textureSize.height); } // Set the given rect's size as original size diff --git a/samples b/samples index 714ea94824..703281713b 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit 714ea9482432a94a2d58ca265c97c61b5b369919 +Subproject commit 703281713bb75cef546907443ef565b3523124db From 90649baa78f16e8fe74e7cf47d65e509f1c8a23b Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 7 Aug 2013 14:14:59 +0800 Subject: [PATCH 029/141] Fixed #2444 Split cc.Texture2D as cc.Texture2DWebGL and cc.Texture2DCanvas --- cocos2d/textures/CCTexture2D.js | 562 +++++++++++++++++++++++++------- 1 file changed, 439 insertions(+), 123 deletions(-) diff --git a/cocos2d/textures/CCTexture2D.js b/cocos2d/textures/CCTexture2D.js index 8d56928595..a3a93013e9 100644 --- a/cocos2d/textures/CCTexture2D.js +++ b/cocos2d/textures/CCTexture2D.js @@ -131,7 +131,7 @@ cc._texParams = function (minFilter, magFilter, wrapS, wrapT) { * @class * @extends cc.Class */ -cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ +cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ // By default PVR images are treated as if they don't have the alpha channel premultiplied _pVRHaveAlphaPremultiplied:null, _pixelFormat:null, @@ -293,68 +293,67 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * @return {Boolean} */ initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) { - if (cc.Browser.supportWebGL) { - var gl = cc.renderContext; + var gl = cc.renderContext; - var bitsPerPixel = 0; - //Hack: bitsPerPixelForFormat returns wrong number for RGB_888 textures. See function. - if (pixelFormat === cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888) { - bitsPerPixel = 24; - } else { - bitsPerPixel = this.bitsPerPixelForFormat(pixelFormat); - } + var bitsPerPixel = 0; + //Hack: bitsPerPixelForFormat returns wrong number for RGB_888 textures. See function. + if (pixelFormat === cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888) { + bitsPerPixel = 24; + } else { + bitsPerPixel = this.bitsPerPixelForFormat(pixelFormat); + } - var bytesPerRow = pixelsWide * bitsPerPixel / 8; - if (bytesPerRow % 8 === 0) { - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8); - } else if (bytesPerRow % 4 === 0) { - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); - } else if (bytesPerRow % 2 === 0) { - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2); - } else { - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); - } + var bytesPerRow = pixelsWide * bitsPerPixel / 8; + if (bytesPerRow % 8 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 8); + } else if (bytesPerRow % 4 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); + } else if (bytesPerRow % 2 === 0) { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 2); + } else { + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); + } - this._webTextureObj = gl.createTexture(); - gl.bindTexture(gl.TEXTURE_2D, this._webTextureObj); + this._webTextureObj = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, this._webTextureObj); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - // Specify OpenGL texture image - switch (pixelFormat) { - case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_AI88: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, pixelsWide, pixelsHigh, 0, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_A8: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, pixelsWide, pixelsHigh, 0, gl.ALPHA, gl.UNSIGNED_BYTE, data); - break; - case cc.TEXTURE_2D_PIXEL_FORMAT_I8: - gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, pixelsWide, pixelsHigh, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data); - break; - default: - cc.Assert(0, "NSInternalInconsistencyException"); - break; - } + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + + // Specify OpenGL texture image + switch (pixelFormat) { + case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB888: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGBA4444: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_4_4_4_4, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB5A1: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, pixelsWide, pixelsHigh, 0, gl.RGBA, gl.UNSIGNED_SHORT_5_5_5_1, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_RGB565: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, pixelsWide, pixelsHigh, 0, gl.RGB, gl.UNSIGNED_SHORT_5_6_5, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_AI88: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE_ALPHA, pixelsWide, pixelsHigh, 0, gl.LUMINANCE_ALPHA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_A8: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, pixelsWide, pixelsHigh, 0, gl.ALPHA, gl.UNSIGNED_BYTE, data); + break; + case cc.TEXTURE_2D_PIXEL_FORMAT_I8: + gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, pixelsWide, pixelsHigh, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data); + break; + default: + cc.Assert(0, "NSInternalInconsistencyException"); + break; } + this._contentSize = contentSize; this._pixelsWide = pixelsWide; this._pixelsHigh = pixelsHigh; @@ -473,9 +472,7 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ initWithElement:function (element) { if (!element) return; - if (cc.Browser.supportWebGL) { - this._webTextureObj = cc.renderContext.createTexture(); - } + this._webTextureObj = cc.renderContext.createTexture(); this._htmlElementObj = element; }, @@ -494,24 +491,22 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ handleLoadedTexture:function () { this._isLoaded = true; //upload image to buffer - if (cc.Browser.supportWebGL) { - var gl = cc.renderContext; + var gl = cc.renderContext; - cc.glBindTexture2D(this); + cc.glBindTexture2D(this); - gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); + gl.pixelStorei(gl.UNPACK_ALIGNMENT, 4); - // Specify OpenGL texture image - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._htmlElementObj); + // Specify OpenGL texture image + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._htmlElementObj); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE)); - gl.bindTexture(gl.TEXTURE_2D, null); - } + this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURE)); + gl.bindTexture(gl.TEXTURE_2D, null); var pixelsWide = this._htmlElementObj.width; var pixelsHigh = this._htmlElementObj.height; @@ -648,22 +643,20 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * @param texParams */ setTexParameters:function (texParams) { - if (cc.Browser.supportWebGL) { - var gl = cc.renderContext; + var gl = cc.renderContext; - cc.Assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) || - (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE), - "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures"); + cc.Assert((this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh)) || + (texParams.wrapS == gl.CLAMP_TO_EDGE && texParams.wrapT == gl.CLAMP_TO_EDGE), + "WebGLRenderingContext.CLAMP_TO_EDGE should be used in NPOT textures"); - cc.glBindTexture2D(this); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT); + cc.glBindTexture2D(this); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, texParams.minFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, texParams.magFilter); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, texParams.wrapS); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, texParams.wrapT); - //TODO - //VolatileTexture::setTexParameters(this, texParams); - } + //TODO + //VolatileTexture::setTexParameters(this, texParams); }, /** @@ -672,21 +665,19 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * - GL_TEXTURE_MAG_FILTER = GL_NEAREST */ setAntiAliasTexParameters:function () { - if (cc.Browser.supportWebGL) { - var gl = cc.renderContext; - - cc.glBindTexture2D(this); - if (!this._hasMipmaps) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - else - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - //TODO - /*#if CC_ENABLE_CACHE_TEXTURE_DATA - ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE}; - VolatileTexture::setTexParameters(this, &texParams); - #endif*/ - } + var gl = cc.renderContext; + + cc.glBindTexture2D(this); + if (!this._hasMipmaps) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); + else + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + //TODO + /*#if CC_ENABLE_CACHE_TEXTURE_DATA + ccTexParams texParams = {m_bHasMipmaps?GL_LINEAR_MIPMAP_NEAREST:GL_LINEAR,GL_LINEAR,GL_NONE,GL_NONE}; + VolatileTexture::setTexParameters(this, &texParams); + #endif*/ }, /** @@ -695,22 +686,20 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * GL_TEXTURE_MAG_FILTER = GL_NEAREST */ setAliasTexParameters:function () { - if (cc.Browser.supportWebGL) { - var gl = cc.renderContext; - - cc.glBindTexture2D(this); - if (!this._hasMipmaps) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - else - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - - //TODO - /*#if CC_ENABLE_CACHE_TEXTURE_DATA - ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE}; - VolatileTexture::setTexParameters(this, &texParams); - #endif*/ - } + var gl = cc.renderContext; + + cc.glBindTexture2D(this); + if (!this._hasMipmaps) + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + else + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST_MIPMAP_NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + + //TODO + /*#if CC_ENABLE_CACHE_TEXTURE_DATA + ccTexParams texParams = {m_bHasMipmaps?GL_NEAREST_MIPMAP_NEAREST:GL_NEAREST,GL_NEAREST,GL_NONE,GL_NONE}; + VolatileTexture::setTexParameters(this, &texParams); + #endif*/ }, /** @@ -718,13 +707,11 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ * It only works if the texture size is POT (power of 2). */ generateMipmap:function () { - if (cc.Browser.supportWebGL) { - cc.Assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures"); + cc.Assert(this._pixelsWide == cc.NextPOT(this._pixelsWide) && this._pixelsHigh == cc.NextPOT(this._pixelsHigh), "Mimpap texture only works in POT textures"); - cc.glBindTexture2D(this); - cc.renderContext.generateMipmap(cc.renderContext.TEXTURE_2D); - this._hasMipmaps = true; - } + cc.glBindTexture2D(this); + cc.renderContext.generateMipmap(cc.renderContext.TEXTURE_2D); + this._hasMipmaps = true; }, /** @@ -919,6 +906,335 @@ cc.Texture2D = cc.Class.extend(/** @lends cc.Texture2D# */{ } }); +/** + *

+ * This class allows to easily create Canvas 2D textures from images, text or raw data.
+ * The created cc.Texture2D object will always have power-of-two dimensions.
+ * Depending on how you create the cc.Texture2D object, the actual image area of the texture might be smaller than the texture dimensions
+ * i.e. "contentSize" != (pixelsWide, pixelsHigh) and (maxS, maxT) != (1.0, 1.0).
+ * Be aware that the content of the generated textures will be upside-down!

+ * @class + * @extends cc.Class + */ +cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ + _contentSize:null, + _isLoaded:false, + _htmlElementObj:null, + /*public:*/ + ctor:function () { + this._contentSize = cc.size(0,0); + this._isLoaded = false; + this._htmlElementObj = null; + }, + + /** + * width in pixels + * @return {Number} + */ + getPixelsWide:function () { + return this._contentSize.width; + }, + + /** + * hight in pixels + * @return {Number} + */ + getPixelsHigh:function () { + return this._contentSize.height; + }, + + /** + * content size + * @return {cc.Size} + */ + getContentSize:function () { + return cc.size(this._contentSize.width / cc.CONTENT_SCALE_FACTOR(), this._contentSize.height / cc.CONTENT_SCALE_FACTOR()); + }, + + getContentSizeInPixels:function () { + return this._contentSize; + }, + + initWithElement:function (element) { + if (!element) + return; + this._htmlElementObj = element; + }, + + /** + * HTMLElement Object getter + * @return {HTMLElement} + */ + getHtmlElementObj:function(){ + return this._htmlElementObj; + }, + + isLoaded:function () { + return this._isLoaded; + }, + + handleLoadedTexture:function () { + this._isLoaded = true; + + var pixelsWide = this._htmlElementObj.width; + var pixelsHigh = this._htmlElementObj.height; + + this._contentSize = new cc.Size(pixelsWide, pixelsHigh); + }, + + description:function () { + return ""; + }, + + /** + * Intializes with a texture2d with data + * @param {Array} data + * @param {Number} pixelFormat + * @param {Number} pixelsWide + * @param {Number} pixelsHigh + * @param {cc.Size} contentSize + * @return {Boolean} + */ + initWithData:function (data, pixelFormat, pixelsWide, pixelsHigh, contentSize) { + //support only in WebGl rendering mode + return false; + }, + + /** + Extensions to make it easy to create a CCTexture2D object from an image file. + Note that RGBA type textures will have their alpha premultiplied - use the blending mode (gl.ONE, gl.ONE_MINUS_SRC_ALPHA). + */ + /** + * Initializes a texture from a UIImage object + * @param uiImage + * @return {Boolean} + */ + initWithImage:function (uiImage) { + //support only in WebGl rendering mode + return false; + }, + + /** + Extensions to make it easy to create a cc.Texture2D object from a string of text. + Note that the generated textures are of type A8 - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA). + */ + /** + * Initializes a texture from a string with dimensions, alignment, font name and font size (note: initWithString does not support on HTML5) + * @param {String} text + * @param {String | cc.FontDefinition} fontName or fontDefinition + * @param {Number} fontSize + * @param {cc.Size} dimensions + * @param {Number} hAlignment + * @param {Number} vAlignment + * @return {Boolean} + */ + initWithString:function (text, fontName, fontSize, dimensions, hAlignment, vAlignment) { + //support only in WebGl rendering mode + return false; + }, + + releaseTexture:function () { + //support only in WebGl rendering mode + }, + + /** + * get WebGLTexture Object + * @return {WebGLTexture} + */ + getName:function () { + //support only in WebGl rendering mode + return null; + }, + + /** texture max S */ + getMaxS:function () { + //support only in WebGl rendering mode + return 1; + }, + + setMaxS:function (maxS) { + //support only in WebGl rendering mode + }, + + /** texture max T */ + getMaxT:function () { + return 1; + }, + + setMaxT:function (maxT) { + //support only in WebGl rendering mode + }, + + /** + * return shader program used by drawAtPoint and drawInRect + * @return {cc.GLProgram} + */ + getShaderProgram:function () { + //support only in WebGl rendering mode + return null; + }, + + /** + * set shader program used by drawAtPoint and drawInRect + * @param {cc.GLProgram} shaderProgram + */ + setShaderProgram:function (shaderProgram) { + //support only in WebGl rendering mode + }, + + /** + * whether or not the texture has their Alpha premultiplied + * @return {Boolean} + */ + hasPremultipliedAlpha:function () { + //support only in WebGl rendering mode + return false; + }, + + hasMipmaps:function () { + //support only in WebGl rendering mode + return false; + }, + + + + /** + * These functions are needed to create mutable textures + * @param {Array} data + */ + releaseData:function (data) { + //support only in WebGl rendering mode + data = null; + }, + + keepData:function (data, length) { + //support only in WebGl rendering mode + return data; + }, + + + + /** + Drawing extensions to make it easy to draw basic quads using a CCTexture2D object. + These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled. + */ + + /** + * draws a texture at a given point + * @param {cc.Point} point + */ + drawAtPoint:function (point) { + //support only in WebGl rendering mode + }, + + /** + * draws a texture inside a rect + * @param {cc.Rect} rect + */ + drawInRect:function (rect) { + //support only in WebGl rendering mode + }, + + + + /** + * Initializes a texture from a ETC file (note: initWithETCFile does not support on HTML5) + * @note Compatible to Cocos2d-x + * @param {String} file + * @return {Boolean} + */ + initWithETCFile:function (file) { + //support only in WebGl rendering mode + return false; + }, + + /** + * Initializes a texture from a PVR file + * @param {String} file + * @return {Boolean} + */ + initWithPVRFile:function (file) { + //support only in WebGl rendering mode + return false; + }, + + /** + Extensions to make it easy to create a cc.Texture2D object from a PVRTC file + Note that the generated textures don't have their alpha premultiplied - use the blending mode (gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA). + */ + /** + * Initializes a texture from a PVRTC buffer + * @note compatible to cocos2d-iphone interface. + * @param {Array} data + * @param {Number} level + * @param {Number} bpp + * @param {Boolean} hasAlpha + * @param {Number} length + * @param {Number} pixelFormat + * @return {Boolean} + */ + initWithPVRTCData:function (data, level, bpp, hasAlpha, length, pixelFormat) { + //support only in WebGl rendering mode + return true; + }, + + /** + * sets the min filter, mag filter, wrap s and wrap t texture parameters.
+ * If the texture size is NPOT (non power of 2), then in can only use gl.CLAMP_TO_EDGE in gl.TEXTURE_WRAP_{S,T}. + * @param texParams + */ + setTexParameters:function (texParams) { + //support only in WebGl rendering mode + }, + + /** + * sets antialias texture parameters:
+ * - GL_TEXTURE_MIN_FILTER = GL_NEAREST
+ * - GL_TEXTURE_MAG_FILTER = GL_NEAREST + */ + setAntiAliasTexParameters:function () { + //support only in WebGl rendering mode + }, + + /** + * sets alias texture parameters: + * GL_TEXTURE_MIN_FILTER = GL_NEAREST + * GL_TEXTURE_MAG_FILTER = GL_NEAREST + */ + setAliasTexParameters:function () { + //support only in WebGl rendering mode + }, + + /** + * Generates mipmap images for the texture.
+ * It only works if the texture size is POT (power of 2). + */ + generateMipmap:function () { + //support only in WebGl rendering mode + }, + + /** + * returns the pixel format. + * @return {String} + */ + stringForFormat:function () { + //support only in WebGl rendering mode + return ""; + }, + + /** + * returns the bits-per-pixel of the in-memory OpenGL texture + * @return {Number} + */ + bitsPerPixelForFormat:function (format) { + //support only in WebGl rendering mode + return -1; + } + +}); + +cc.Texture2D = cc.Browser.supportWebGL ? cc.Texture2DWebGL : cc.Texture2DCanvas; + /** *

* sets the default pixel format for UIImagescontains alpha channel.
From e0a6d44ece7a4f3c1bac2b38b03845435463d2fd Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 7 Aug 2013 14:16:46 +0800 Subject: [PATCH 030/141] Fixed #2444 Fixed bug that cc.PointZero use as a value ,but it is a function. --- extensions/GUI/CCControlExtension/CCControlColourPicker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/GUI/CCControlExtension/CCControlColourPicker.js b/extensions/GUI/CCControlExtension/CCControlColourPicker.js index 024cf1dfd2..d6cf2706f7 100644 --- a/extensions/GUI/CCControlExtension/CCControlColourPicker.js +++ b/extensions/GUI/CCControlExtension/CCControlColourPicker.js @@ -101,7 +101,7 @@ cc.ControlColourPicker = cc.Control.extend({ this._hsv = new cc.HSV(0, 0, 0); // Add image - this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("menuColourPanelBackground.png", spriteSheet, cc.PointZero, cc.p(0.5, 0.5)); + this._background = cc.ControlUtils.addSpriteToTargetWithPosAndAnchor("menuColourPanelBackground.png", spriteSheet, cc.PointZero(), cc.p(0.5, 0.5)); var backgroundPointZero = cc.pSub(this._background.getPosition(), cc.p(this._background.getContentSize().width / 2, this._background.getContentSize().height / 2)); From e81726b2866e66975532b410b9978ae605fdd865 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 8 Aug 2013 10:21:33 +0800 Subject: [PATCH 031/141] Fixed #2444 Fixed some bug about merged the code --- cocos2d/misc_nodes/CCRenderTexture.js | 5 ++++- cocos2d/sprite_nodes/CCSprite.js | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js index 99df12b674..8d5b8ac8e9 100644 --- a/cocos2d/misc_nodes/CCRenderTexture.js +++ b/cocos2d/misc_nodes/CCRenderTexture.js @@ -138,7 +138,10 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ this._cacheCanvas.width = width || 10; this._cacheCanvas.height = height || 10; this._cacheContext.translate(0, this._cacheCanvas.height); - this._sprite = cc.Sprite.createWithTexture(this._cacheCanvas); + var texture = new cc.Texture2D(); + texture.initWithElement(this._cacheCanvas); + texture.handleLoadedTexture(); + this._sprite = cc.Sprite.createWithTexture(texture); return true; }, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 3a88542f5d..c08dd723fe 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1008,8 +1008,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (!rect) { rect = cc.rect(0, 0, 0, 0); rect.size = texture.getContentSize(); - rect = cc.RECT_PIXELS_TO_POINTS(rect); - } } this._originalTexture = texture; @@ -1274,11 +1272,11 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ var image = this._texture.getHtmlElementObj(); if (this._colorized) { context.drawImage(image, - 0, 0, locRect.width * scaleFactor, locRect.height * scaleFactor, + 0, 0, locRect.width , locRect.height , flipXOffset, flipYOffset, locRect.width, locRect.height); } else { context.drawImage(image, - locRect.x * scaleFactor, locRect.y * scaleFactor, locRect.width * scaleFactor, locRect.height * scaleFactor, + locRect.x , locRect.y , locRect.width , locRect.height , flipXOffset, flipYOffset, locRect.width, locRect.height); } } else if (this._contentSize.width !== 0) { From 34743c157663463b80556d4345ab43736f73e313 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 8 Aug 2013 10:45:49 +0800 Subject: [PATCH 032/141] Fixed #2496 Fixed a bug of cc.TextureCache that the status of texture is wrong in callback --- cocos2d/textures/CCTextureCache.js | 100 ++++++++++++++++++++--------- 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index 6c8925edf6..ae44271464 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -277,26 +277,37 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ cc.Assert(path != null, "TextureCache: path MUST not be null"); path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; - + var image; if (texture) { - this._addImageAsyncCallBack(target, selector); + if(texture.isLoaded()){ + this._addImageAsyncCallBack(target, selector); + }else{ + var that = this; + image = texture.getHtmlElementObj(); + image.addEventListener("load", function () { + texture.handleLoadedTexture(); + that._addImageAsyncCallBack(target, selector); + }); + } } else { - texture = new Image(); - texture.crossOrigin = "Anonymous"; + image = new Image(); + image.crossOrigin = "Anonymous"; var that = this; - texture.addEventListener("load", function () { + image.addEventListener("load", function () { + if (that._textures.hasOwnProperty(path)) + that._textures[path].handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); }); - texture.addEventListener("error", function () { + image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; }); - texture.src = path; + image.src = path; var texture2d = new cc.Texture2D(); - texture2d.initWithElement(texture); + texture2d.initWithElement(image); this._textures[path] = texture2d; } return this._textures[path]; @@ -320,27 +331,36 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; + var image; if (texture) { - cc.Loader.getInstance().onResLoaded(); + if (texture.isLoaded()) { + cc.Loader.getInstance().onResLoaded(); + } else { + image = texture.getHtmlElementObj(); + image.addEventListener("load", function () { + texture.handleLoadedTexture(); + cc.Loader.getInstance().onResLoaded(); + }); + } } else { - texture = new Image(); - texture.crossOrigin = "Anonymous"; + image = new Image(); + image.crossOrigin = "Anonymous"; var that = this; - texture.addEventListener("load", function () { + image.addEventListener("load", function () { cc.Loader.getInstance().onResLoaded(); if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); }); - texture.addEventListener("error", function () { + image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; }); - texture.src = path; + image.src = path; var texture2d = new cc.Texture2D(); - texture2d.initWithElement(texture); + texture2d.initWithElement(image); this._textures[path] = texture2d; } @@ -668,28 +688,37 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Assert(path != null, "TextureCache: path MUST not be null"); path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; - + var image; if (texture) { - this._addImageAsyncCallBack(target, selector); + if(texture.isLoaded()){ + this._addImageAsyncCallBack(target, selector); + }else{ + var that = this; + image = texture.getHtmlElementObj(); + image.addEventListener("load", function () { + texture.handleLoadedTexture(); + that._addImageAsyncCallBack(target, selector); + }); + } } else { - texture = new Image(); - texture.crossOrigin = "Anonymous"; + image = new Image(); + image.crossOrigin = "Anonymous"; var that = this; - texture.addEventListener("load", function () { + image.addEventListener("load", function () { if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); }); - texture.addEventListener("error", function () { + image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; }); - texture.src = path; + image.src = path; var texture2d = new cc.Texture2D(); - texture2d.initWithElement(texture); + texture2d.initWithElement(image); this._textures[path] = texture2d; } return this._textures[path]; @@ -726,34 +755,43 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ */ addImage:function (path) { cc.Assert(path != null, "TextureCache: path MUST not be null"); - if(!this._rendererInitialized) + if (!this._rendererInitialized) return this._addImageBeforeRenderer(path); path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; + var image; if (texture) { - cc.Loader.getInstance().onResLoaded(); + if (texture.isLoaded()) { + cc.Loader.getInstance().onResLoaded(); + } else { + image = texture.getHtmlElementObj(); + image.addEventListener("load", function () { + texture.handleLoadedTexture(); + cc.Loader.getInstance().onResLoaded(); + }); + } } else { - texture = new Image(); - texture.crossOrigin = "Anonymous"; + image = new Image(); + image.crossOrigin = "Anonymous"; var that = this; - texture.addEventListener("load", function () { + image.addEventListener("load", function () { cc.Loader.getInstance().onResLoaded(); if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); }); - texture.addEventListener("error", function () { + image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; }); - texture.src = path; + image.src = path; var texture2d = new cc.Texture2D(); - texture2d.initWithElement(texture); + texture2d.initWithElement(image); this._textures[path] = texture2d; } From 3ee3082a81ac6d3312804b31e4c9f8c74ccc63db Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 8 Aug 2013 11:56:15 +0800 Subject: [PATCH 033/141] Fixed #2482 Add the deprecated information to function of cc.UserDefault --- cocos2d/support/CCUserDefault.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cocos2d/support/CCUserDefault.js b/cocos2d/support/CCUserDefault.js index 109888daa5..6c40730469 100644 --- a/cocos2d/support/CCUserDefault.js +++ b/cocos2d/support/CCUserDefault.js @@ -69,6 +69,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Boolean} */ getBoolForKey:function (key, defaultValue) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getBoolForKey."); var value = this._getValueForKey(key); var ret = defaultValue || false; if (value == "true") { @@ -93,6 +94,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getIntegerForKey:function (key, defaultValue) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getIntegerForKey."); var value = this._getValueForKey(key); var ret = defaultValue || 0; @@ -112,6 +114,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getFloatForKey:function (key, defaultValue) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getFloatForKey."); var value = this._getValueForKey(key); var ret = defaultValue || 0; @@ -131,6 +134,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getDoubleForKey:function (key, defaultValue) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getDoubleForKey."); return this.getFloatForKey(key, defaultValue); }, @@ -143,6 +147,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {String} */ getStringForKey:function (key, defaultValue) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getStringForKey."); var value = this._getValueForKey(key); var ret = defaultValue || ""; @@ -169,6 +174,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Boolean} value */ setBoolForKey:function (key, value) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setBoolForKey."); // save bool value as sring this.setStringForKey(key, String(value)); }, @@ -180,6 +186,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setIntegerForKey:function (key, value) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setIntegerForKey."); // check key if (!key) { return; @@ -195,6 +202,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setFloatForKey:function (key, value) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setFloatForKey."); // check key if (!key) { return; @@ -210,6 +218,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setDoubleForKey:function (key, value) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setDoubleForKey."); return this.setFloatForKey(key, value); }, @@ -220,6 +229,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {String} value */ setStringForKey:function (key, value) { + cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setStringForKey."); // check key if (!key) { return; From 41a6c525785a02c869b8862254bfabb6c7b129f7 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 8 Aug 2013 13:58:43 +0800 Subject: [PATCH 034/141] Fixed #2482 Add the deprecated information to function of cc.UserDefault --- cocos2d/support/CCUserDefault.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/cocos2d/support/CCUserDefault.js b/cocos2d/support/CCUserDefault.js index 6c40730469..fd53f8c3d0 100644 --- a/cocos2d/support/CCUserDefault.js +++ b/cocos2d/support/CCUserDefault.js @@ -69,7 +69,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Boolean} */ getBoolForKey:function (key, defaultValue) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getBoolForKey."); + cc.log("getBoolForKey is deprecated. Use sys.localStorage.getItem instead."); var value = this._getValueForKey(key); var ret = defaultValue || false; if (value == "true") { @@ -94,7 +94,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getIntegerForKey:function (key, defaultValue) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getIntegerForKey."); + cc.log("getIntegerForKey is deprecated. Use sys.localStorage.getItem instead."); var value = this._getValueForKey(key); var ret = defaultValue || 0; @@ -114,7 +114,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getFloatForKey:function (key, defaultValue) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getFloatForKey."); + cc.log("getFloatForKey is deprecated. Use sys.localStorage.getItem instead."); var value = this._getValueForKey(key); var ret = defaultValue || 0; @@ -134,7 +134,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {Number} */ getDoubleForKey:function (key, defaultValue) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getDoubleForKey."); + cc.log("getDoubleForKey is deprecated. Use sys.localStorage.getItem instead."); return this.getFloatForKey(key, defaultValue); }, @@ -147,7 +147,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {String} */ getStringForKey:function (key, defaultValue) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.getItem instead of getStringForKey."); + cc.log("getStringForKey is deprecated. Use sys.localStorage.getItem instead."); var value = this._getValueForKey(key); var ret = defaultValue || ""; @@ -174,7 +174,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Boolean} value */ setBoolForKey:function (key, value) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setBoolForKey."); + cc.log("setBoolForKey is deprecated. Use sys.localStorage.setItem instead."); // save bool value as sring this.setStringForKey(key, String(value)); }, @@ -186,7 +186,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setIntegerForKey:function (key, value) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setIntegerForKey."); + cc.log("setIntegerForKey is deprecated. Use sys.localStorage.setItem instead."); // check key if (!key) { return; @@ -202,7 +202,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setFloatForKey:function (key, value) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setFloatForKey."); + cc.log("setFloatForKey is deprecated. Use sys.localStorage.setItem instead."); // check key if (!key) { return; @@ -218,7 +218,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {Number} value */ setDoubleForKey:function (key, value) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setDoubleForKey."); + cc.log("setDoubleForKey is deprecated. Use sys.localStorage.setItem instead."); return this.setFloatForKey(key, value); }, @@ -229,7 +229,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @param {String} value */ setStringForKey:function (key, value) { - cc.log("cc.UserDefault will not be supported in the future,i suggest you to use sys.localStorage.setItem instead of setStringForKey."); + cc.log("setStringForKey is deprecated. Use sys.localStorage.setItem instead."); // check key if (!key) { return; @@ -251,6 +251,7 @@ cc.UserDefault = cc.Class.extend(/** @lends cc.UserDefault# */{ * @return {cc.UserDefault|} */ cc.UserDefault.getInstance = function () { + cc.log("cc.UserDefault is deprecated. Use sys.localStorage instead."); if (!this._sUserDefault) { this._sUserDefault = new cc.UserDefault(); this._sUserDefault.init(); From bc1bcba133bd677f69b6ecbada8179ba8607072a Mon Sep 17 00:00:00 2001 From: SmallJun <536762164@qq.com> Date: Thu, 8 Aug 2013 14:51:04 +0800 Subject: [PATCH 035/141] fixed the bug of ScrollView while change the position of it`s parent node. --- extensions/GUI/CCScrollView/CCScrollView.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index a384204931..fd54271d79 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -710,16 +710,15 @@ cc.ScrollView = cc.Layer.extend({ this._scissorRestored = false; var frame = this._getViewRect(); - var screenPos; - var scaleValue = this.getScale(); + var scaleX = this.getScaleX(); + var scaleY = this.getScaleY(); var ctx = context || cc.renderContext; if (cc.renderContextType === cc.CANVAS) { - screenPos = this.getParent().getPosition(); - var getWidth = (this._viewSize.width * scaleValue); - var getHeight = (this._viewSize.height * scaleValue); - var startX = screenPos.x * scaleValue; - var startY = screenPos.y * scaleValue;// + this._anchorPointInPoints.y; + var getWidth = (this._viewSize.width * scaleX); + var getHeight = (this._viewSize.height * scaleY); + var startX = 0; + var startY = 0; ctx.beginPath(); ctx.rect(startX, startY, getWidth, -getHeight); From e71329e1ff04c3b9968c4f002396bbbd9f5cf418 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 9 Aug 2013 16:40:41 +0800 Subject: [PATCH 036/141] Fixed #2511 fixed a bug of cc.EditBox and a bug of cc.Scale9Sprite --- cocos2d/base_nodes/CCdomNode.js | 82 +++++++++---------- cocos2d/label_nodes/CCLabelTTF.js | 2 +- .../GUI/CCControlExtension/CCScale9Sprite.js | 1 + 3 files changed, 43 insertions(+), 42 deletions(-) diff --git a/cocos2d/base_nodes/CCdomNode.js b/cocos2d/base_nodes/CCdomNode.js index 79da7fbe80..89357a38fc 100644 --- a/cocos2d/base_nodes/CCdomNode.js +++ b/cocos2d/base_nodes/CCdomNode.js @@ -285,7 +285,7 @@ cc.DOM.methods = /** @lends cc.DOM# */{ redraw:function () { if (this.isSprite) { var tmp = this._children; - this._children = null; + this._children = []; cc.Sprite.prototype.visit.call(this, this.ctx); this._children = tmp; } @@ -351,47 +351,47 @@ cc.DOM.parentDOM = function (x) { cc.DOM.parentDOM(p); } else { //parent has no more parent, if its running, then add it to the container - //if (p.isRunning()) { - //find EGLView div - var eglViewDiv = cc.$("#EGLViewDiv"); - if(eglViewDiv){ - p.dom.appendTo(eglViewDiv); - } else { - eglViewDiv = cc.$new("div"); - eglViewDiv.id = "EGLViewDiv"; - - var eglViewer = cc.EGLView.getInstance(); - var designSize = eglViewer.getDesignResolutionSize(); - var viewPortRect = eglViewer.getViewPortRect(); - var screenSize = eglViewer.getFrameSize(); - var designSizeWidth = designSize.width, designSizeHeight = designSize.height; - if((designSize.width === 0) && (designSize.height === 0)){ - designSizeWidth = screenSize.width; - designSizeHeight = screenSize.height; - } - - var viewPortWidth = viewPortRect.size.width, viewPortHeight = viewPortRect.size.height; - if((viewPortRect.size.width === 0) && (viewPortRect.size.height === 0)){ - viewPortWidth = screenSize.width; - viewPortHeight = screenSize.height; + if (p.isRunning()) { + //find EGLView div + var eglViewDiv = cc.$("#EGLViewDiv"); + if (eglViewDiv) { + p.dom.appendTo(eglViewDiv); + } else { + eglViewDiv = cc.$new("div"); + eglViewDiv.id = "EGLViewDiv"; + + var eglViewer = cc.EGLView.getInstance(); + var designSize = eglViewer.getDesignResolutionSize(); + var viewPortRect = eglViewer.getViewPortRect(); + var screenSize = eglViewer.getFrameSize(); + var designSizeWidth = designSize.width, designSizeHeight = designSize.height; + if ((designSize.width === 0) && (designSize.height === 0)) { + designSizeWidth = screenSize.width; + designSizeHeight = screenSize.height; + } + + var viewPortWidth = viewPortRect.size.width, viewPortHeight = viewPortRect.size.height; + if ((viewPortRect.size.width === 0) && (viewPortRect.size.height === 0)) { + viewPortWidth = screenSize.width; + viewPortHeight = screenSize.height; + } + + eglViewDiv.style.position = 'absolute'; + eglViewDiv.style.bottom = 0; + //x.dom.style.display='block'; + eglViewDiv.style.width = designSizeWidth + "px"; + eglViewDiv.style.maxHeight = designSizeHeight + "px"; + eglViewDiv.style.margin = 0; + + eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); + eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 + + (screenSize.width - viewPortWidth ) / 2) + "px"; + eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + + p.dom.appendTo(eglViewDiv); + eglViewDiv.appendTo(cc.container); } - - eglViewDiv.style.position = 'absolute'; - eglViewDiv.style.bottom = 0; - //x.dom.style.display='block'; - eglViewDiv.style.width = designSizeWidth + "px"; - eglViewDiv.style.maxHeight = designSizeHeight + "px"; - eglViewDiv.style.margin = 0; - - eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); - eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 - + (screenSize.width - viewPortWidth ) / 2) + "px"; - eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; - - p.dom.appendTo(eglViewDiv); - eglViewDiv.appendTo(cc.container); } - //} } return true; }; @@ -410,7 +410,7 @@ cc.DOM.setTransform = function (x) { x.ctx.translate(x.getAnchorPointInPoints().x, x.getAnchorPointInPoints().y); if (x.isSprite) { var tmp = x._children; - x._children = null; + x._children = []; cc.Sprite.prototype.visit.call(x, x.ctx); x._children = tmp; } diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 9317c9b566..1db1d04de5 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -1265,7 +1265,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ }, setPosition:function(posX, posY){ - if(posY) + if (arguments.length == 2) this._originalPosition = cc.p(posX, posY); else this._originalPosition = cc.p(posX.x, posX.y); diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index bc26ba5c56..78cb10bfed 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -230,6 +230,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ setCapInsets: function (capInsets) { var contentSize = this._contentSize; + contentSize = new cc.Size(contentSize.width,contentSize.height); this.updateWithBatchNode(this._scale9Image, this._spriteRect, this._spriteFrameRotated, capInsets); this.setContentSize(contentSize); }, From 05b55f0faaee92923c1b8311d7a25bb120740494 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 14 Aug 2013 16:51:30 +0800 Subject: [PATCH 037/141] Fixed #2454: Fixed a bug of EditBox that position is wrong when EGLView Mode is NOBORDER --- cocos2d/base_nodes/CCdomNode.js | 34 +++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/cocos2d/base_nodes/CCdomNode.js b/cocos2d/base_nodes/CCdomNode.js index 89357a38fc..7bd78d3300 100644 --- a/cocos2d/base_nodes/CCdomNode.js +++ b/cocos2d/base_nodes/CCdomNode.js @@ -315,16 +315,25 @@ cc.DOM._resetEGLViewDiv = function(){ } eglViewDiv.style.position = 'absolute'; - eglViewDiv.style.bottom = 0; //x.dom.style.display='block'; eglViewDiv.style.width = designSizeWidth + "px"; eglViewDiv.style.maxHeight = designSizeHeight + "px"; eglViewDiv.style.margin = 0; eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); - eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 - + (screenSize.width - viewPortWidth ) / 2) + "px"; - eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + + if (viewPortWidth < screenSize.width) { + eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 + + (screenSize.width - viewPortWidth ) / 2) + "px"; + } else { + eglViewDiv.style.left = (viewPortWidth - designSizeWidth) / 2 + "px"; + } + + if (viewPortHeight < screenSize.height) { + eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + } else { + eglViewDiv.style.bottom = "0px"; + } } }; @@ -377,16 +386,25 @@ cc.DOM.parentDOM = function (x) { } eglViewDiv.style.position = 'absolute'; - eglViewDiv.style.bottom = 0; //x.dom.style.display='block'; eglViewDiv.style.width = designSizeWidth + "px"; eglViewDiv.style.maxHeight = designSizeHeight + "px"; eglViewDiv.style.margin = 0; eglViewDiv.resize(eglViewer.getScaleX(), eglViewer.getScaleY()); - eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 - + (screenSize.width - viewPortWidth ) / 2) + "px"; - eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + + if (viewPortWidth < screenSize.width) { + eglViewDiv.style.left = ((viewPortWidth - designSizeWidth) / 2 + + (screenSize.width - viewPortWidth ) / 2) + "px"; + } else { + eglViewDiv.style.left = (viewPortWidth - designSizeWidth) / 2 + "px"; + } + + if (viewPortHeight < screenSize.height) { + eglViewDiv.style.bottom = ((screenSize.height - viewPortHeight ) / 2) + "px"; + } else { + eglViewDiv.style.bottom = "0px"; + } p.dom.appendTo(eglViewDiv); eglViewDiv.appendTo(cc.container); From 0e6f84632cb27610f16519a3308fba05a40c147c Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 14 Aug 2013 16:57:17 +0800 Subject: [PATCH 038/141] Fixed #2454 Fixed a bug that preloadTextFileData have a wrong cache --- cocos2d/platform/CCFileUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/platform/CCFileUtils.js b/cocos2d/platform/CCFileUtils.js index a6f5ee816d..ad90b6d610 100644 --- a/cocos2d/platform/CCFileUtils.js +++ b/cocos2d/platform/CCFileUtils.js @@ -279,7 +279,7 @@ cc.FileUtils = cc.Class.extend({ xhr.onload = function (e) { if (xhr.responseText) { cc.Loader.getInstance().onResLoaded(); - selfPointer._fileDataCache[fileUrl] = xhr.responseText; + selfPointer._textFileCache[fileUrl] = xhr.responseText; } }; } From 71e82f56ab4b259a145cec6be2df7360e8d0f536 Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Thu, 15 Aug 2013 23:47:19 +0800 Subject: [PATCH 039/141] update cc.RectApplyAffineTransform --- cocos2d/cocoa/CCAffineTransform.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/cocoa/CCAffineTransform.js b/cocos2d/cocoa/CCAffineTransform.js index e5642b93c7..fbf7f30a9d 100644 --- a/cocos2d/cocoa/CCAffineTransform.js +++ b/cocos2d/cocoa/CCAffineTransform.js @@ -127,10 +127,10 @@ cc.RectApplyAffineTransform = function (rect, anAffineTransform) { var bottomLeft = cc.PointApplyAffineTransform(cc.p(left, bottom), anAffineTransform); var bottomRight = cc.PointApplyAffineTransform(cc.p(right, bottom), anAffineTransform); - var minX = Math.min(Math.min(topLeft.x, topRight.x), Math.min(bottomLeft.x, bottomRight.x)); - var maxX = Math.max(Math.max(topLeft.x, topRight.x), Math.max(bottomLeft.x, bottomRight.x)); - var minY = Math.min(Math.min(topLeft.y, topRight.y), Math.min(bottomLeft.y, bottomRight.y)); - var maxY = Math.max(Math.max(topLeft.y, topRight.y), Math.max(bottomLeft.y, bottomRight.y)); + var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); + var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); + var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); + var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); return cc.rect(minX, minY, (maxX - minX), (maxY - minY)); }; From 46f3a133b74f25239306e7966019ecc009d8c68b Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Thu, 15 Aug 2013 23:57:18 +0800 Subject: [PATCH 040/141] use native sort function when sort children --- cocos2d/base_nodes/CCNode.js | 50 ++++++++---------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index f57ebb7ca6..26d54ae743 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -402,8 +402,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setRotation: function (newRotation) { this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationX * (Math.PI / 180); - this._rotationRadiansY = this._rotationY * (Math.PI / 180); + this._rotationRadiansX = this._rotationRadiansY = newRotation * (Math.PI / 180); this.setNodeDirty(); }, @@ -473,7 +472,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setScale:function (scale, scaleY) { this._scaleX = scale; - this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale; + this._scaleY = scaleY === undefined ? scale : scaleY; this.setNodeDirty(); }, @@ -1181,24 +1180,10 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { - var _children = this._children; - var i, j, length = _children.length,tempChild; - // insertion sort - for (i = 0; i < length; i++) { - var tempItem = _children[i]; - j = i - 1; - tempChild = _children[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 ))) { - tempChild = _children[j]; - _children[j + 1] = tempChild; - j = j - 1; - } - _children[j + 1] = tempItem; - } + this._children.sort(function(a, b){ + return a._zOrder === b._zOrder ? a._orderOfArrival - b._orderOfArrival : a._zOrder - b._zOrder; + }); //don't need to check children recursively, that's done in visit of each child this._reorderChildDirty = false; @@ -2247,8 +2232,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setRotation:function (newRotation) { this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); - this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); + this._rotationRadiansX = this._rotationRadiansY = newRotation * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, @@ -2318,7 +2302,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setScale:function (scale, scaleY) { this._scaleX = scale; - this._scaleY = scaleY || scale; + this._scaleY = scaleY === undefined ? scale : scaleY; this.setNodeDirty(); }, @@ -3024,24 +3008,10 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { - var _children = this._children; - var i, j, length = _children.length,tempChild; - // insertion sort - for (i = 0; i < length; i++) { - var tempItem = _children[i]; - j = i - 1; - tempChild = _children[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 ))) { - tempChild = _children[j]; - _children[j + 1] = tempChild; - j = j - 1; - } - _children[j + 1] = tempItem; - } + this._childre.sort(function(a, b){ + return a._zOrder === b._zOrder ? a._orderOfArrival - b._orderOfArrival : a._zOrder - b._zOrder; + }); //don't need to check children recursively, that's done in visit of each child this._reorderChildDirty = false; From 4065f898072f535c4f6a22b808818a870d2c3cc2 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 16 Aug 2013 10:18:17 +0800 Subject: [PATCH 041/141] fixed #2530 LabelTTF's Stroke style has been modified to outer stroke --- cocos2d/label_nodes/CCLabelTTF.js | 49 ++++++++++++++++++------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 9317c9b566..965717b8b2 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -334,6 +334,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._fontName = textDefinition.fontName; this._fontSize = textDefinition.fontSize; this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; + this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); // shadow if ( textDefinition.shadowEnabled) @@ -537,9 +538,8 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ /** * renders the label * @param {CanvasRenderingContext2D|Null} ctx - * @param {Number} renderType */ - draw:function (ctx, renderType) { + draw:function (ctx) { var context = ctx || cc.renderContext; if (this._flipX) context.scale(-1, 1); @@ -553,8 +553,9 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ context.font = this._fontStyleStr; //stroke style setup - if(this._strokeEnabled){ - context.lineWidth = this._strokeSize; + var locStrokeEnabled = this._strokeEnabled; + if(locStrokeEnabled){ + context.lineWidth = this._strokeSize * 2; context.strokeStyle = this._strokeColorStr; } @@ -579,29 +580,34 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER) xoffset = locContentSizeWidth / 2; if (this._isMultiLine) { + var locStrings = this._strings; var yOffset = 0, strLen = this._strings.length; if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) yOffset = locFontHeight + locContentSizeHeight - locFontHeight * strLen; else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER) yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * strLen) / 2; + var tmpLineStr = null, tmpYOffset = null; for (var i = 0; i < strLen; i++) { - var line = this._strings[i]; - context.fillText(line, xoffset, -locContentSizeHeight + (locFontHeight * i) + yOffset); + tmpLineStr = locStrings[i]; + tmpYOffset = -locContentSizeHeight + (locFontHeight * i) + yOffset; + if(locStrokeEnabled) + context.strokeText(tmpLineStr, xoffset, tmpYOffset); + context.fillText(tmpLineStr, xoffset, tmpYOffset); } } else { if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM){ - context.fillText(this._string, xoffset, 0); - if(this._strokeEnabled) + if(locStrokeEnabled) context.strokeText(this._string, xoffset, 0); + context.fillText(this._string, xoffset, 0); }else if(locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP){ - context.fillText(this._string, xoffset, -locContentSizeHeight); - if(this._strokeEnabled) + if(locStrokeEnabled) context.strokeText(this._string, xoffset, -locContentSizeHeight); + context.fillText(this._string, xoffset, -locContentSizeHeight); }else{ - context.fillText(this._string, xoffset, -locContentSizeHeight/2); - if(this._strokeEnabled) + if(locStrokeEnabled) context.strokeText(this._string, xoffset, -locContentSizeHeight/2); + context.fillText(this._string, xoffset, -locContentSizeHeight/2); } } @@ -1107,7 +1113,8 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ context.fillStyle = this._fillColorStr; //stroke style setup - if (this._strokeEnabled) { + var locStrokeEnabled = this._strokeEnabled; + if (locStrokeEnabled) { context.lineWidth = this._strokeSize; context.strokeStyle = this._strokeColorStr; } @@ -1156,26 +1163,26 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ for (var i = 0; i < locStrLen; i++) { var line = this._strings[i]; var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset; - context.fillText(line, xOffset, tmpOffsetY); - if (this._strokeEnabled) + if (locStrokeEnabled) context.strokeText(line, xOffset, tmpOffsetY); + context.fillText(line, xOffset, tmpOffsetY); } } else { if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) { yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY : 0; - context.fillText(this._string, xOffset, yOffset); - if (this._strokeEnabled) + if (locStrokeEnabled) context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) { yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY/2 -locContentSizeHeight : - locContentSizeHeight + locStrokeShadowOffsetY/2; - context.fillText(this._string, xOffset, yOffset); - if (this._strokeEnabled) + if (locStrokeEnabled) context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); } else { yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY -locContentSizeHeight / 2 : - locContentSizeHeight / 2; - context.fillText(this._string, xOffset, yOffset); - if (this._strokeEnabled) + if (locStrokeEnabled) context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); } } }, From a148f3770b1ce80042456457cc81bca4a4d1867b Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 16 Aug 2013 11:06:27 +0800 Subject: [PATCH 042/141] fixed #2481 add a clearRect function to cc.RenderTexture --- cocos2d/misc_nodes/CCRenderTexture.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js index 8d5b8ac8e9..d6506e8017 100644 --- a/cocos2d/misc_nodes/CCRenderTexture.js +++ b/cocos2d/misc_nodes/CCRenderTexture.js @@ -220,6 +220,10 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ this.end(); }, + clearRect:function(x, y, width, height){ + this._cacheContext.clearRect(x, y, width, height); + }, + /** * clears the texture with a specified depth value * @param {Number} depthValue @@ -271,9 +275,11 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ //! make sure all children are drawn this.sortAllChildren(); var locChildren = this._children; - for (var i = 0; i < locChildren.length; i++) { + var childrenLen = locChildren.length; + var selfSprite = this._sprite; + for (var i = 0; i < childrenLen; i++) { var getChild = locChildren[i]; - if (getChild != this._sprite) + if (getChild != selfSprite) getChild.visit(); } From 76b339805735e0098b0d5417ede262666b07a79e Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 16 Aug 2013 11:13:09 +0800 Subject: [PATCH 043/141] fixed #2481 add a clearRect function to cc.RenderTexture --- cocos2d/misc_nodes/CCRenderTexture.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js index d6506e8017..24a472fdbc 100644 --- a/cocos2d/misc_nodes/CCRenderTexture.js +++ b/cocos2d/misc_nodes/CCRenderTexture.js @@ -221,7 +221,7 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ }, clearRect:function(x, y, width, height){ - this._cacheContext.clearRect(x, y, width, height); + this._cacheContext.clearRect(x, y, width, -height); }, /** From 9b29125679e0ca22f91a656291dc3aa3783f17ad Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Fri, 16 Aug 2013 21:30:24 +0800 Subject: [PATCH 044/141] Revert "use native sort function when sort children" This reverts commit 46f3a133b74f25239306e7966019ecc009d8c68b. --- cocos2d/base_nodes/CCNode.js | 50 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 26d54ae743..f57ebb7ca6 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -402,7 +402,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setRotation: function (newRotation) { this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationRadiansY = newRotation * (Math.PI / 180); + this._rotationRadiansX = this._rotationX * (Math.PI / 180); + this._rotationRadiansY = this._rotationY * (Math.PI / 180); this.setNodeDirty(); }, @@ -472,7 +473,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setScale:function (scale, scaleY) { this._scaleX = scale; - this._scaleY = scaleY === undefined ? scale : scaleY; + this._scaleY = (scaleY || scaleY === 0) ? scaleY : scale; this.setNodeDirty(); }, @@ -1180,10 +1181,24 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { + var _children = this._children; + var i, j, length = _children.length,tempChild; + // insertion sort - this._children.sort(function(a, b){ - return a._zOrder === b._zOrder ? a._orderOfArrival - b._orderOfArrival : a._zOrder - b._zOrder; - }); + for (i = 0; i < length; i++) { + var tempItem = _children[i]; + j = i - 1; + tempChild = _children[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 ))) { + tempChild = _children[j]; + _children[j + 1] = tempChild; + j = j - 1; + } + _children[j + 1] = tempItem; + } //don't need to check children recursively, that's done in visit of each child this._reorderChildDirty = false; @@ -2232,7 +2247,8 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setRotation:function (newRotation) { this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationRadiansY = newRotation * 0.017453292519943295; //(Math.PI / 180); + this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); + this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, @@ -2302,7 +2318,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setScale:function (scale, scaleY) { this._scaleX = scale; - this._scaleY = scaleY === undefined ? scale : scaleY; + this._scaleY = scaleY || scale; this.setNodeDirty(); }, @@ -3008,10 +3024,24 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ sortAllChildren:function () { if (this._reorderChildDirty) { + var _children = this._children; + var i, j, length = _children.length,tempChild; + // insertion sort - this._childre.sort(function(a, b){ - return a._zOrder === b._zOrder ? a._orderOfArrival - b._orderOfArrival : a._zOrder - b._zOrder; - }); + for (i = 0; i < length; i++) { + var tempItem = _children[i]; + j = i - 1; + tempChild = _children[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 ))) { + tempChild = _children[j]; + _children[j + 1] = tempChild; + j = j - 1; + } + _children[j + 1] = tempItem; + } //don't need to check children recursively, that's done in visit of each child this._reorderChildDirty = false; From 51093cdd911e295dc443027f3e43a84ca7d85c3e Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Fri, 16 Aug 2013 21:32:58 +0800 Subject: [PATCH 045/141] fix setScale bug --- cocos2d/base_nodes/CCNode.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index f57ebb7ca6..ea08902136 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -2318,7 +2318,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ setScale:function (scale, scaleY) { this._scaleX = scale; - this._scaleY = scaleY || scale; + this._scaleY = scaleY === undefined ? scale : scaleY; this.setNodeDirty(); }, From a347ebe4ac7a631553146562d22a3ca888578eae Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 19 Aug 2013 17:02:31 +0800 Subject: [PATCH 046/141] Fixed #2550 Fixed TableView's bug that contentSize is wrong when changing datasource --- extensions/GUI/CCScrollView/CCTableView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index 2948ee6e89..0cc114dcd8 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -376,6 +376,7 @@ cc.TableView = cc.ScrollView.extend({ * reloads data from data source. the view will be refreshed. */ reloadData:function () { + this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE; var locCellsUsed = this._cellsUsed; for (var i = 0; i < locCellsUsed.count(); i++) { var cell = locCellsUsed.objectAtIndex(i); From 5b278dc6855377c3f02acc33b6da70eb61b378e1 Mon Sep 17 00:00:00 2001 From: WanderWang Date: Mon, 19 Aug 2013 18:06:37 +0800 Subject: [PATCH 047/141] Improve performance cost when creating lots of CCLabelTTF add cc.LabelTTF.__fontHeightCache to cache cc.LabelTTF.__getFontHeightByDiv 's result --- cocos2d/label_nodes/CCLabelTTF.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 9317c9b566..df62f64150 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -1432,11 +1432,17 @@ cc.LabelTTF.__labelHeightDiv.style.lineHeight = "normal"; document.body.appendChild(cc.LabelTTF.__labelHeightDiv); cc.LabelTTF.__getFontHeightByDiv = function(fontName, fontSize){ + var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize]; + if (clientHeight > 0) return clientHeight; var labelDiv = cc.LabelTTF.__labelHeightDiv; labelDiv.style.fontFamily = fontName; labelDiv.style.fontSize = fontSize + "px"; - return labelDiv.clientHeight ; + clientHeight = labelDiv.clientHeight ; + cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight; + return clientHeight; }; +cc.LabelTTF.__fontHeightCache = {}; + From ee4c9b7b8b24b8698a8dc4291a1c96258eef87c0 Mon Sep 17 00:00:00 2001 From: "christian.schwartz@gmail.com" Date: Mon, 19 Aug 2013 12:56:50 +0200 Subject: [PATCH 048/141] fixed SpriteFrame.initWithTextureFilename converted (pixel-based) rect to pixels --- cocos2d/sprite_nodes/CCSpriteFrame.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 09aa85ae7f..8f90447d3b 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -278,14 +278,13 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ * @param {cc.Size} originalSize */ initWithTextureFilename:function (filename, rect, rotated, offset, originalSize) { - var rectInPixels = cc.RECT_POINTS_TO_PIXELS(rect); offset = offset || cc.size(0, 0); - originalSize = originalSize || rectInPixels.size; + originalSize = originalSize || rect.size; this._texture = null; this._textureFilename = filename; - this._rectInPixels = rectInPixels; - this._rect = cc.RECT_PIXELS_TO_POINTS(rectInPixels); + this._rectInPixels = rect; + this._rect = cc.RECT_PIXELS_TO_POINTS(rect); this._rotated = rotated || false; this._offsetInPixels = offset; this._offset = cc.POINT_PIXELS_TO_POINTS(offset); From 1061b359dccff486d911372ef4b24d9a6b359a5a Mon Sep 17 00:00:00 2001 From: "christian.schwartz@gmail.com" Date: Tue, 20 Aug 2013 08:58:03 +0200 Subject: [PATCH 049/141] fixed UnitTest.SpriteFrame.initWithTexture --- cocos2d/sprite_nodes/CCSpriteFrame.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 8f90447d3b..1c1920e525 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -242,8 +242,7 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ It is assumed that the frame was not trimmed. */ case 2: - var rectInPixels = cc.RECT_POINTS_TO_PIXELS(rect); - return this.initWithTexture(texture, rectInPixels, false, cc.PointZero(), rectInPixels.size); + return this.initWithTexture(texture, rect, false, cc.PointZero(), rect.size); break; /** Initializes a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. From 17d94574087111a3ca4c3cdc255147c08583b508 Mon Sep 17 00:00:00 2001 From: WanderWang Date: Tue, 20 Aug 2013 16:42:52 +0800 Subject: [PATCH 050/141] Update CCScheduler.scheduleCallbackForTarget 's comment Update CCScheduler.scheduleCallbackForTarget 's comment @example has a mistake --- cocos2d/CCScheduler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/CCScheduler.js b/cocos2d/CCScheduler.js index 5fd64c219e..1936d460cd 100644 --- a/cocos2d/CCScheduler.js +++ b/cocos2d/CCScheduler.js @@ -641,7 +641,7 @@ cc.Scheduler = cc.Class.extend(/** @lends cc.Scheduler# */{ * @param {Boolean} paused * @example * //register a schedule to scheduler - * cc.Director.getInstance().getScheduler().scheduleCallbackForTarget(function, this, interval, repeat, delay, !this._isRunning ); + * cc.Director.getInstance().getScheduler().scheduleCallbackForTarget(this, function, interval, repeat, delay, !this._isRunning ); */ scheduleCallbackForTarget:function (target, callback_fn, interval, repeat, delay, paused) { cc.Assert(callback_fn, "scheduler.scheduleCallbackForTarget() Argument callback_fn must be non-NULL"); From 381a77d4f049bfddd0b49e991900b9006dd7ae0b Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 20 Aug 2013 17:18:25 +0800 Subject: [PATCH 051/141] Fixed #2467 Fixed a bug of cc.LabelBMFont that it's very slow when calling setString --- cocos2d/label_nodes/CCLabelBMFont.js | 63 ++++++++++++++++++++++------ cocos2d/sprite_nodes/CCSprite.js | 21 +++++----- 2 files changed, 61 insertions(+), 23 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index fc25cc3aec..1d7eb2e581 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -574,8 +574,15 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._displayedOpacity = this._realOpacity * parentOpacity/255.0; var locChildren = this._children; for(var i = 0; i< locChildren; i++){ - locChildren[i].updateDisplayedOpacity(this._displayedOpacity); + var locChild = locChildren[i]; + if(cc.Browser.supportWebGL){ + locChild.updateDisplayedOpacity(this._displayedOpacity); + }else{ + cc.NodeRGBA.prototype.updateDisplayedOpacity.call(locChild, this._displayedOpacity); + locChild.setNodeDirty(); + } } + this._changeTextureColor(); }, isCascadeOpacityEnabled:function(){ @@ -603,7 +610,38 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ var locChildren = this._children; for(var i = 0;i < locChildren.length;i++){ - locChildren[i].updateDisplayedColor(this._displayedColor); + var locChild = locChildren[i]; + if(cc.Browser.supportWebGL){ + locChild.updateDisplayedColor(this._displayedColor); + }else{ + cc.NodeRGBA.prototype.updateDisplayedColor.call(locChild, this._displayedColor); + locChild.setNodeDirty(); + } + } + this._changeTextureColor(); + }, + + _changeTextureColor:function(){ + if(cc.Browser.supportWebGL){ + return; + } + var locElement, locTexture = this.getTexture(); + if (locTexture) { + locElement = locTexture.getHtmlElementObj(); + if (!locElement) + return; + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(this._originalTexture.getHtmlElementObj()); + if (cacheTextureForColor) { + if (locElement instanceof HTMLCanvasElement && !this._rectRotated) + cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, null, locElement); + else{ + locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor); + locTexture = new cc.Texture2D(); + locTexture.initWithElement(locElement); + locTexture.handleLoadedTexture(); + this.setTexture(locTexture); + } + } } }, @@ -744,22 +782,17 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ if (!fontChar) { fontChar = new cc.Sprite(); if ((key === 32) && (locContextType === cc.CANVAS)) { - fontChar.init(); - fontChar.setTextureRect(cc.RectZero(), false, cc.SizeZero()); + fontChar.initWithTexture(locTexture, cc.RectZero(), false); } else fontChar.initWithTexture(locTexture, rect, false); this.addChild(fontChar, 0, i); } else { if ((key === 32) && (locContextType === cc.CANVAS)) { - fontChar.init(); - fontChar.setTextureRect(cc.RectZero(), false, cc.SizeZero()); + fontChar.setTextureRect(rect, false, cc.SizeZero()); } else { // updating previous sprite - if (locContextType === cc.CANVAS) - fontChar.initWithTexture(locTexture, rect, false); - else - fontChar.setTextureRect(rect, false, rect.size); + fontChar.setTextureRect(rect, false, rect.size); // restore to default in case they were modified fontChar.setVisible(true); } @@ -767,8 +800,14 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ // Apply label properties fontChar.setOpacityModifyRGB(this._opacityModifyRGB); // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on - fontChar.updateDisplayedColor(this._displayedColor); - fontChar.updateDisplayedOpacity(this._displayedOpacity); + if(cc.Browser.supportWebGL){ + fontChar.updateDisplayedColor(this._displayedColor); + fontChar.updateDisplayedOpacity(this._displayedOpacity); + }else{ + cc.NodeRGBA.prototype.updateDisplayedColor.call(fontChar, this._displayedColor); + cc.NodeRGBA.prototype.updateDisplayedOpacity.call(fontChar, this._displayedOpacity); + fontChar.setNodeDirty(); + } var yOffset = this._configuration.commonHeight - fontDef.yOffset; var fontPos = cc.p(nextFontPositionX + fontDef.xOffset + fontDef.rect.width * 0.5 + kerningAmount, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index d7083774f0..206353645f 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1224,9 +1224,9 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ } }, - _changeTextureColor:function () { - var locElement, locTexture = this._texture; - if (locTexture) { + _changeTextureColor: function () { + var locElement, locTexture = this._texture, locRect = this.getTextureRect(); + if (locTexture && locRect.width > 0) { locElement = locTexture.getHtmlElementObj(); if (!locElement) return; @@ -1235,16 +1235,15 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (cacheTextureForColor) { this._colorized = true; //generate color texture cache - if (locElement instanceof HTMLCanvasElement && !this._rectRotated) - cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect(), locElement); - else { - - locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect()); + /*if (locElement instanceof HTMLCanvasElement && !this._rectRotated) + 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); - } + //} } } }, @@ -1258,7 +1257,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (this._isLighterMode) context.globalCompositeOperation = 'lighter'; - context.globalAlpha = this._realOpacity / 255; + context.globalAlpha = this._displayedOpacity / 255; var locRect = this._rect; var flipXOffset = 0 | (this._offsetPosition.x), flipYOffset = -this._offsetPosition.y - locRect.height; if (this._flipX) { @@ -1269,7 +1268,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ flipYOffset = this._offsetPosition.y; context.scale(1, -1); } - if (this._texture) { + if (this._texture && locRect.width > 0 && locRect.height > 0) { var image = this._texture.getHtmlElementObj(); if (this._colorized) { context.drawImage(image, From 7b1ff857a0738f836115a6e7af59d425e0e419e9 Mon Sep 17 00:00:00 2001 From: xbruce Date: Tue, 20 Aug 2013 21:44:10 +0800 Subject: [PATCH 052/141] Update CCSAXParser.js Improve Plist file loading error message to more friendly --- cocos2d/platform/CCSAXParser.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cocos2d/platform/CCSAXParser.js b/cocos2d/platform/CCSAXParser.js index b2067405bc..9654aef41e 100644 --- a/cocos2d/platform/CCSAXParser.js +++ b/cocos2d/platform/CCSAXParser.js @@ -46,6 +46,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @return {Array} plist object array */ parse:function (textxml) { + var path = textxml; textxml = this.getList(textxml); // get a reference to the requested corresponding xml file if (window.DOMParser) { @@ -61,7 +62,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ var plist = this.xmlDoc.documentElement; if (plist.tagName != 'plist') - throw "cocos2d:Not a plist file"; + throw "cocos2d: " + path + " is not a plist file"; // Get first real node var node = null; @@ -245,4 +246,4 @@ cc.SAXParser.getInstance = function () { return this._instance; }; -cc.SAXParser._instance = null; \ No newline at end of file +cc.SAXParser._instance = null; From 24091bdb069174b5c80c8416bf61ee87fdc87700 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 21 Aug 2013 10:03:43 +0800 Subject: [PATCH 053/141] fixed #2531 Asynchronous loading resources for rendering classes has been implemented. --- HelloHTML5World/cocos2d.js | 2 +- cocos2d/CCLoader.js | 4 +- cocos2d/label_nodes/CCLabelTTF.js | 6 + cocos2d/menu_nodes/CCMenuItem.js | 56 +++- .../particle_nodes/CCParticleSystemQuad.js | 27 +- cocos2d/sprite_nodes/CCSprite.js | 270 ++++++++++++------ cocos2d/sprite_nodes/CCSpriteFrame.js | 124 ++++---- cocos2d/sprite_nodes/CCSpriteFrameCache.js | 22 +- cocos2d/textures/CCTexture2D.js | 47 ++- cocos2d/textures/CCTextureCache.js | 6 +- extensions/CCBReader/CCNodeLoader.js | 10 +- .../GUI/CCControlExtension/CCControlButton.js | 12 +- .../GUI/CCControlExtension/CCScale9Sprite.js | 19 +- 13 files changed, 404 insertions(+), 201 deletions(-) diff --git a/HelloHTML5World/cocos2d.js b/HelloHTML5World/cocos2d.js index 30638e6410..fb091f964f 100644 --- a/HelloHTML5World/cocos2d.js +++ b/HelloHTML5World/cocos2d.js @@ -33,7 +33,7 @@ showFPS:true, frameRate:60, loadExtension:false, - renderMode:0, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only) + renderMode:1, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only) tag:'gameCanvas', //the dom element to run cocos2d on engineDir:'../cocos2d/', //SingleEngineFile:'', diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index 3b4b6d8cb5..68c55b566e 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -223,7 +223,6 @@ cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{ } }, - _schedulePreload: function () { var _self = this; this._interval = setInterval(function () { @@ -235,7 +234,6 @@ cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{ clearInterval(this._interval); }, - _getResType: function (resInfo) { var isFont = resInfo.fontName; if (isFont != null) { @@ -270,9 +268,9 @@ cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{ this._selector(this); } - this._curNumber = 0; this._loadedNumber = 0; + this._totalNumber = 0; }, _registerFaceFont: function (fontRes) { diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index e5f1d8d315..680c8f2d6d 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -540,6 +540,9 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ * @param {CanvasRenderingContext2D|Null} ctx */ draw:function (ctx) { + if(!this._string || this._string == "") + return; + var context = ctx || cc.renderContext; if (this._flipX) context.scale(-1, 1); @@ -1334,6 +1337,9 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {WebGLRenderingContext} ctx 3d context of canvas */ draw:function (ctx) { + if(!this._string || this._string == "") + return; + var gl = ctx || 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"); diff --git a/cocos2d/menu_nodes/CCMenuItem.js b/cocos2d/menu_nodes/CCMenuItem.js index 65b8f313af..ea1ff9fc7a 100644 --- a/cocos2d/menu_nodes/CCMenuItem.js +++ b/cocos2d/menu_nodes/CCMenuItem.js @@ -601,14 +601,14 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ }, /** - * @return {cc.Node} + * @return {cc.Sprite} */ getNormalImage:function () { return this._normalImage; }, /** - * @param {cc.Node} normalImage + * @param {cc.Sprite} normalImage */ setNormalImage:function (normalImage) { if (this._normalImage == normalImage) { @@ -623,19 +623,26 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ } this._normalImage = normalImage; - this.setContentSize(this._normalImage.getContentSize()); - this._updateImagesVisibility(); + if(normalImage.textureLoaded()){ + this.setContentSize(this._normalImage.getContentSize()); + this._updateImagesVisibility(); + } else { + normalImage.addLoadedEventListener(function(sender){ + this.setContentSize(sender.getContentSize()); + this._updateImagesVisibility(); + }, this); + } }, /** - * @return {cc.Node} + * @return {cc.Sprite} */ getSelectedImage:function () { return this._selectedImage; }, /** - * @param {cc.Node} selectedImage + * @param {cc.Sprite} selectedImage */ setSelectedImage:function (selectedImage) { if (this._selectedImage == selectedImage) @@ -651,7 +658,13 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ } this._selectedImage = selectedImage; - this._updateImagesVisibility(); + if(selectedImage.textureLoaded()){ + this._updateImagesVisibility(); + } else { + selectedImage.addLoadedEventListener(function(sender){ + this._updateImagesVisibility(); + }, this); + } }, /** @@ -662,7 +675,7 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ }, /** - * @param {cc.Node} disabledImage + * @param {cc.Sprite} disabledImage */ setDisabledImage:function (disabledImage) { if (this._disabledImage == disabledImage) @@ -677,7 +690,13 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ this.removeChild(this._disabledImage, true); this._disabledImage = disabledImage; - this._updateImagesVisibility(); + if(disabledImage.textureLoaded()){ + this._updateImagesVisibility(); + } else { + disabledImage.addLoadedEventListener(function(sender){ + this._updateImagesVisibility(); + }, this); + } }, /** @@ -693,11 +712,22 @@ cc.MenuItemSprite = cc.MenuItem.extend(/** @lends cc.MenuItemSprite# */{ this.setNormalImage(normalSprite); this.setSelectedImage(selectedSprite); this.setDisabledImage(disabledSprite); - if (this._normalImage) - this.setContentSize(this._normalImage.getContentSize()); + var locNormalImage = this._normalImage; + if (locNormalImage){ + if(locNormalImage.textureLoaded()){ + this.setContentSize(locNormalImage.getContentSize()); + this.setCascadeColorEnabled(true); + this.setCascadeOpacityEnabled(true); + } else{ + locNormalImage.addLoadedEventListener(function(sender){ + this.setContentSize(sender.getContentSize()); + this.setCascadeColorEnabled(true); + this.setCascadeOpacityEnabled(true); + }, this); + } + } + - this.setCascadeColorEnabled(true); - this.setCascadeOpacityEnabled(true); return true; }, diff --git a/cocos2d/particle_nodes/CCParticleSystemQuad.js b/cocos2d/particle_nodes/CCParticleSystemQuad.js index 743932d362..8eb273f696 100644 --- a/cocos2d/particle_nodes/CCParticleSystemQuad.js +++ b/cocos2d/particle_nodes/CCParticleSystemQuad.js @@ -55,6 +55,8 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua _buffersVBO:null, _pointRect:null, + _textureLoaded: null, + /** * Constructor * @override @@ -65,6 +67,7 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua this._quads = []; this._indices = []; this._pointRect = cc.RectZero(); + this._textureLoaded = true; if (cc.renderContextType === cc.WEBGL) { this._quadsArrayBuffer = null; @@ -342,18 +345,20 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua /** * set Texture of Particle System * @override - * @param {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture - * @param {Boolean} isCallSuper is direct call super method + * @param {cc.Texture2D} texture */ - setTexture:function (texture, isCallSuper) { - if (isCallSuper != null && isCallSuper === true) { - cc.ParticleSystem.prototype.setTexture.call(this, texture); - return; + setTexture:function (texture) { + if(texture.isLoaded()){ + var size = texture.getContentSize(); + this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height)); + } else { + this._textureLoaded = false; + texture.addLoadedEventListener(function(sender){ + this._textureLoaded = true; + var size = sender.getContentSize(); + this.setTextureWithRect(sender, cc.rect(0, 0, size.width, size.height)); + }, this); } - - var size = texture.getContentSize(); - - this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height)); }, /** @@ -497,6 +502,8 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua */ draw:function (ctx) { cc.Assert(!this._batchNode, "draw should not be called when added to a particleBatchNode"); + if(!this._textureLoaded) + return; if (cc.renderContextType === cc.CANVAS) this._drawForCanvas(ctx); diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index d7083774f0..3a98068113 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -331,6 +331,26 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ _flipX:false, //Whether the sprite is flipped horizontally or not. _flipY:false, //Whether the sprite is flipped vertically or not. + _textureLoaded:false, + _loadedEventListeners:null, + + textureLoaded:function(){ + return this._textureLoaded; + }, + + addLoadedEventListener:function(callback, target){ + this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); + }, + + _callLoadedEventCallbacks:function(){ + var locListeners = this._loadedEventListeners; + for(var i = 0, len = locListeners.length; i < len; i++){ + var selCallback = locListeners[i]; + selCallback.eventCallback.call(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. @@ -431,12 +451,27 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ */ initWithSpriteFrame:function (spriteFrame) { cc.Assert(spriteFrame != 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: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.
@@ -539,10 +574,10 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ * @override */ removeAllChildren:function (cleanup) { - var locChildren = this._children; - if (this._batchNode && locChildren != null) { - for (var i = 0; i < locChildren.length; i++) - this._batchNode.removeSpriteFromAtlas(locChildren[i]); + 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); @@ -845,6 +880,8 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ this._offsetPosition = cc.p(0, 0); this._unflippedOffsetPositionFromCenter = cc.p(0, 0); this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; + this._textureLoaded = true; + this._loadedEventListeners = []; if (fileName) { if (typeof(fileName) == "string") { @@ -853,12 +890,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ } else if (typeof(fileName) === "object") { if (fileName instanceof cc.SpriteFrame) { this.initWithSpriteFrame(fileName); - } else if (fileName instanceof cc.SpriteBatchNode) { - if (arguments.length > 1) { - var rect = arguments[1]; - if (rect instanceof cc.Rect) - this.initWithBatchNode(fileName, rect); - } } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { var texture2d = new cc.Texture2D(); texture2d.initWithElement(fileName); @@ -901,6 +932,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // update texture (calls _updateBlendFunc) this.setTexture(null); + this._textureLoaded = true; this._flipX = this._flipY = false; // default transform anchor: center @@ -933,29 +965,11 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ */ initWithFile:function (filename, rect) { cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite"); - var selfPointer = this; var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { filename = cc.FileUtils.getInstance().fullPathForFilename(filename); - this._visible = false; - var loadImg = new Image(); - loadImg.addEventListener("load", function () { - if (!rect) { - rect = cc.rect(0, 0, loadImg.width, loadImg.height); - rect = cc.RECT_PIXELS_TO_POINTS(rect); - } - var texture2d = new cc.Texture2D(); - texture2d.initWithElement(loadImg); - texture2d.handleLoadedTexture(); - selfPointer.initWithTexture(texture2d, rect); - cc.TextureCache.getInstance().cacheImage(filename, loadImg); - selfPointer._visible = true; - }); - loadImg.addEventListener("error", function () { - cc.log("load failure:" + filename); - }); - loadImg.src = filename; - return true; + texture = cc.TextureCache.getInstance().addImage(filename); + return this.initWithTexture(texture, rect); } else { if (!rect) { var size = texture.getContentSize(); @@ -963,7 +977,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ } return this.initWithTexture(texture, rect); } - return false; }, /** @@ -1006,6 +1019,16 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ this._offsetPosition = cc.p(0, 0); this._hasChildren = false; + var locTextureLoaded = texture.isLoaded(); + this._textureLoaded = locTextureLoaded; + + if(!locTextureLoaded){ + this._rectRotated = rotated || false; + this._rect = rect; + texture.addLoadedEventListener(this._textureLoadedCallback, this); + return true; + } + if (!rect) { rect = cc.rect(0, 0, 0, 0); rect.size = texture.getContentSize(); @@ -1021,6 +1044,25 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ return true; }, + _textureLoadedCallback:function(sender){ + this._textureLoaded = true; + var locRect = this._rect; + if (!locRect) { + locRect = cc.rect(0, 0, 0, 0); + locRect.size = sender.getContentSize(); + } + 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(null); + + this._callLoadedEventCallbacks(); + }, + /** * updates the texture rect of the CCSprite in points. * @param {cc.Rect} rect a rect of texture @@ -1142,22 +1184,36 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ 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(), this._rectRotated, sender.getOriginalSize()); + this._callLoadedEventCallbacks(); + },this); + } // update texture before updating texture rect if (pNewTexture != this._texture) this.setTexture(pNewTexture); - // update rect - this._rectRotated = newFrame.isRotated(); - if (this._rectRotated) this._originalTexture = pNewTexture; this.setTextureRect(newFrame.getRect(), this._rectRotated, newFrame.getOriginalSize()); this._colorized = false; - var curColor = this.getColor(); - if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) - this._changeTextureColor(); + if (locTextureLoaded) { + var curColor = this.getColor(); + if (curColor.r !== 255 || curColor.g !== 255 || curColor.b !== 255) + this._changeTextureColor(); + } }, /** @@ -1217,7 +1273,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument"); if (this._texture != texture) { - if(texture&&texture.getHtmlElementObj() instanceof HTMLImageElement){ + if(texture && texture.getHtmlElementObj() instanceof HTMLImageElement){ this._originalTexture = texture; } this._texture = texture; @@ -1238,7 +1294,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (locElement instanceof HTMLCanvasElement && !this._rectRotated) cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect(), locElement); else { - locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, this.getTextureRect()); locTexture = new cc.Texture2D(); locTexture.initWithElement(locElement); @@ -1251,9 +1306,12 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ /** * draw sprite to canvas - * @param {CanvasContext} ctx 2d context of canvas + * @param {CanvasRenderingContext2D} ctx 2d context of canvas */ draw:function (ctx) { + if(!this._textureLoaded) + return; + var context = ctx || cc.renderContext; if (this._isLighterMode) context.globalCompositeOperation = 'lighter'; @@ -1375,6 +1433,25 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ _flipX:false, //Whether the sprite is flipped horizontally or not. _flipY:false, //Whether the sprite is flipped vertically or not. + _textureLoaded:false, + + textureLoaded:function(){ + return this._textureLoaded; + }, + + addLoadedEventListener:function(callback, target){ + this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); + }, + + _callLoadedEventCallbacks:function(){ + var locListeners = this._loadedEventListeners; + for(var i = 0, len = locListeners.length; i < len; i++){ + var selCallback = locListeners[i]; + selCallback.eventCallback.call(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. @@ -1483,12 +1560,23 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ */ initWithSpriteFrame:function (spriteFrame) { cc.Assert(spriteFrame != 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:function(spriteFrame){ + this.setNodeDirty(); + this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); + this._callLoadedEventCallbacks(); + }, + /** * Initializes a sprite with a sprite frame name.
* A cc.SpriteFrame will be fetched from the cc.SpriteFrameCache by name.
@@ -1591,10 +1679,10 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * @override */ removeAllChildren:function (cleanup) { - var locChildren = this._children; - if (this._batchNode && locChildren != null) { - for (var i = 0; i < locChildren.length; i++) - this._batchNode.removeSpriteFromAtlas(locChildren[i]); + 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); @@ -1902,6 +1990,8 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ this._quad = new cc.V3F_C4B_T2F_Quad(); this._quadWebBuffer = cc.renderContext.createBuffer(); this._quadDirty = true; + this._textureLoaded = true; + this._loadedEventListeners = []; if (fileName) { if (typeof(fileName) == "string") { @@ -1910,19 +2000,13 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } else if (typeof(fileName) == "object") { if (fileName instanceof cc.SpriteFrame) { this.initWithSpriteFrame(fileName); - } else if (fileName instanceof cc.SpriteBatchNode) { - if (arguments.length > 1) { - var rect = arguments[1]; - if (rect instanceof cc.Rect) - this.initWithBatchNode(fileName, rect); - } } else if ((fileName instanceof HTMLImageElement) || (fileName instanceof HTMLCanvasElement)) { var texture2d = new cc.Texture2D(); texture2d.initWithElement(fileName); texture2d.handleLoadedTexture(); - this.initWithTexture(texture2d) + this.initWithTexture(texture2d); } else if (fileName instanceof cc.Texture2D) { - this.initWithTexture(fileName) + this.initWithTexture(fileName); } } } @@ -1965,7 +2049,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ // update texture (calls _updateBlendFunc) this.setTexture(null); - + this._textureLoaded = true; this._flipX = this._flipY = false; // default transform anchor: center @@ -2005,39 +2089,18 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ */ initWithFile:function (filename, rect) { cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite"); - var selfPointer = this; - var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { filename = cc.FileUtils.getInstance().fullPathForFilename(filename); - this._visible = false; - var loadImg = new Image(); - loadImg.addEventListener("load", function () { - if (!rect) { - rect = cc.rect(0, 0, loadImg.width, loadImg.height); - } - var texture2d = new cc.Texture2D(); - texture2d.initWithElement(loadImg); - texture2d.handleLoadedTexture(); - selfPointer.initWithTexture(texture2d, rect); - cc.TextureCache.getInstance().cacheImage(filename, loadImg); - selfPointer._visible = true; - }); - loadImg.addEventListener("error", function () { - cc.log("load failure:" + filename); - }); - loadImg.src = filename; - return true; + texture = cc.TextureCache.getInstance().addImage(filename); + return this.initWithTexture(texture, rect); } else { - if (texture) { - if (!rect) { - var size = texture.getContentSize(); - rect = cc.rect(0, 0, size.width, size.height); - } - return this.initWithTexture(texture, rect); + if (!rect) { + var size = texture.getContentSize(); + rect = cc.rect(0, 0, size.width, size.height); } + return this.initWithTexture(texture, rect); } - return false; }, /** @@ -2086,6 +2149,16 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ this._quad.tl.colors = tmpColor; this._quad.tr.colors = tmpColor; + var locTextureLoaded = texture.isLoaded(); + this._textureLoaded = locTextureLoaded; + + if(!locTextureLoaded){ + this._rectRotated = rotated || false; + this._rect = rect; + texture.addLoadedEventListener(this._textureLoadedCallback, this); + return true; + } + if (!rect) { rect = cc.rect(0, 0, 0, 0); rect.size = texture.getContentSize(); @@ -2099,6 +2172,23 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ this._quadDirty = true; return true; }, + + _textureLoadedCallback:function(sender){ + this._textureLoaded = true; + var locRect = this._rect; + if (!locRect) { + locRect = cc.rect(0, 0, 0, 0); + locRect.size = sender.getContentSize(); + } + + 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(null); + this._quadDirty = true; + }, /** * updates the texture rect of the CCSprite in points. * @param {cc.Rect} rect a rect of texture @@ -2316,8 +2406,23 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ */ setDisplayFrame:function (newFrame) { this.setNodeDirty(); - this._unflippedOffsetPositionFromCenter = newFrame.getOffset(); + 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._rectRotated, sender.getOriginalSize()); + this._callLoadedEventCallbacks(); + },this); + } // update texture before updating texture rect if (pNewTexture != this._texture) this.setTexture(pNewTexture); @@ -2507,6 +2612,9 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * draw sprite to canvas */ draw: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"); diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 09aa85ae7f..cf836776dd 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -49,6 +49,8 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ _originalSizeInPixels:null, _texture:null, _textureFilename:"", + _textureLoaded:false, + _eventListeners:null, ctor:function () { this._offset = cc.p(0, 0); @@ -60,9 +62,28 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ this._originalSizeInPixels = cc.size(0, 0); this._textureFilename = ""; this._texture = null; + this._textureLoaded = false; + this._eventListeners = []; }, // attributes + textureLoaded:function(){ + return this._textureLoaded; + }, + + addLoadedEventListener:function(callback, target){ + this._eventListeners.push({eventCallback:callback, eventTarget:target}); + }, + + _callLoadedEventCallbacks:function(){ + var locListeners = this._eventListeners; + for(var i = 0, len = locListeners.length; i < len; i++){ + var selCallback = locListeners[i]; + selCallback.eventCallback.call(selCallback.eventTarget, this); + } + locListeners.length = 0; + }, + /** * @return {cc.Rect} */ @@ -166,7 +187,7 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ /** * get texture of the frame - * @return {cc.Texture2D|HTMLImageElement} + * @return {cc.Texture2D} */ getTexture:function () { if (this._texture) @@ -178,11 +199,41 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ /** * set texture of the frame, the texture is retained - * @param {cc.Texture2D|HTMLImageElement} texture + * @param {cc.Texture2D} texture */ setTexture:function (texture) { if (this._texture != texture) { + var locLoaded = texture.isLoaded(); + this._textureLoaded = locLoaded; this._texture = texture; + if(!locLoaded){ + texture.addLoadedEventListener(function(sender){ + this._textureLoaded = true; + if(this._rotated){ + var tempElement = sender.getHtmlElementObj(); + tempElement = cc.cutRotateImageToCanvas(tempElement, this.getRect()); + var tempTexture = new cc.Texture2D(); + tempTexture.initWithElement(tempElement); + tempTexture.handleLoadedTexture(); + this.setTexture(tempTexture); + + var rect = this.getRect(); + this.setRect(cc.rect(0, 0, rect.width, rect.height)); + } + var locRect = this._rect; + if(locRect.width === 0 && locRect.height === 0){ + var locContentSize = sender.getContentSize(); + this._rect.width = locContentSize.width; + this._rect.height = locContentSize.height; + this._rectInPixels = cc.RECT_POINTS_TO_PIXELS(this._rect); + this._originalSizeInPixels.width = this._rectInPixels.width; + this._originalSizeInPixels.height = this._rectInPixels.height; + this._originalSize.width = locContentSize.width; + this._originalSize.height = locContentSize.height; + } + this._callLoadedEventCallbacks(); + }, this); + } } }, @@ -236,34 +287,20 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ * @return {Boolean} */ initWithTexture:function (texture, rect, rotated, offset, originalSize) { - var argnum = arguments.length; - switch (argnum) { - /** Initializes a cc.SpriteFrame with a texture, rect in points. - It is assumed that the frame was not trimmed. - */ - case 2: - var rectInPixels = cc.RECT_POINTS_TO_PIXELS(rect); - return this.initWithTexture(texture, rectInPixels, false, cc.PointZero(), rectInPixels.size); - break; - - /** Initializes a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. - The originalSize is the size in points of the frame before being trimmed. - */ - case 5: - this._texture = texture; - this._rectInPixels = rect; - this._rect = cc.RECT_PIXELS_TO_POINTS(rect); - this._offsetInPixels = offset; - this._offset = cc.POINT_PIXELS_TO_POINTS(this._offsetInPixels); - this._originalSizeInPixels = originalSize; - this._originalSize = cc.SIZE_PIXELS_TO_POINTS(this._originalSizeInPixels); - this._rotated = rotated; - return true; - break; - default: - throw "Argument must be non-nil "; - break; - } + var rectInPixels = cc.RECT_POINTS_TO_PIXELS(rect); + rotated = rotated || false; + offset = offset || cc.PointZero(); + originalSize = originalSize || rectInPixels.size; + + this.setTexture(texture); + this._rectInPixels = rectInPixels; + this._rect = cc.RECT_PIXELS_TO_POINTS(rectInPixels); + this._offsetInPixels = offset; + this._offset = cc.POINT_PIXELS_TO_POINTS(this._offsetInPixels); + this._originalSizeInPixels = originalSize; + this._originalSize = cc.SIZE_PIXELS_TO_POINTS(this._originalSizeInPixels); + this._rotated = rotated; + return true; }, /** @@ -326,11 +363,11 @@ cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) /** * Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. - * @param {cc.Texture2D|HTMLImageElement} texture + * @param {cc.Texture2D} texture * @param {cc.Rect} rect - * @param {Boolean} rotated - * @param {cc.Point} offset - * @param {cc.Size} originalSize + * @param {Boolean} [rotated=] + * @param {cc.Point} [offset=] + * @param {cc.Size} [originalSize=] * @return {cc.SpriteFrame} * @example * //Create a cc.SpriteFrame with a texture, rect in texture. @@ -340,25 +377,8 @@ cc.SpriteFrame.create = function (filename, rect, rotated, offset, originalSize) * var frame2 = cc.SpriteFrame.createWithTexture(texture, frameRect, rotated, offset, sourceSize); */ cc.SpriteFrame.createWithTexture = function (texture, rect, rotated, offset, originalSize) { - var argnum = arguments.length; var spriteFrame = new cc.SpriteFrame(); - switch (argnum) { - /** Create a cc.SpriteFrame with a texture, rect in points. - It is assumed that the frame was not trimmed. - */ - case 2: - spriteFrame.initWithTexture(texture, rect); - break; - /** Create a cc.SpriteFrame with a texture, rect, rotated, offset and originalSize in pixels. - The originalSize is the size in points of the frame before being trimmed. - */ - case 5: - spriteFrame.initWithTexture(texture, rect, rotated, offset, originalSize); - break; - default: - throw "Argument must be non-nil "; - break; - } + spriteFrame.initWithTexture(texture, rect, rotated, offset, originalSize); return spriteFrame; }; diff --git a/cocos2d/sprite_nodes/CCSpriteFrameCache.js b/cocos2d/sprite_nodes/CCSpriteFrameCache.js index f0dc3faadb..90f7336750 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrameCache.js +++ b/cocos2d/sprite_nodes/CCSpriteFrameCache.js @@ -138,16 +138,18 @@ cc.SpriteFrameCache = cc.Class.extend(/** @lends cc.SpriteFrameCache# */{ if(cc.renderContextType === cc.CANVAS && spriteFrame.isRotated()){ //clip to canvas - var tempElement = spriteFrame.getTexture().getHtmlElementObj(); - tempElement = cc.cutRotateImageToCanvas(tempElement, spriteFrame.getRect()); - var tempTexture = new cc.Texture2D(); - tempTexture.initWithElement(tempElement); - tempTexture.handleLoadedTexture(); - spriteFrame.setTexture(tempTexture); - - var rect = spriteFrame.getRect(); - spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height)); - + var locTexture = spriteFrame.getTexture(); + if(locTexture.isLoaded()){ + var tempElement = spriteFrame.getTexture().getHtmlElementObj(); + tempElement = cc.cutRotateImageToCanvas(tempElement, spriteFrame.getRect()); + var tempTexture = new cc.Texture2D(); + tempTexture.initWithElement(tempElement); + tempTexture.handleLoadedTexture(); + spriteFrame.setTexture(tempTexture); + + var rect = spriteFrame.getRect(); + spriteFrame.setRect(cc.rect(0, 0, rect.width, rect.height)); + } } // add sprite frame diff --git a/cocos2d/textures/CCTexture2D.js b/cocos2d/textures/CCTexture2D.js index a3a93013e9..1033043f5d 100644 --- a/cocos2d/textures/CCTexture2D.js +++ b/cocos2d/textures/CCTexture2D.js @@ -150,6 +150,8 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ _htmlElementObj:null, _webTextureObj:null, + _loadedEventListeners:null, + /*public:*/ ctor:function () { this._pixelsWide = 0; @@ -168,6 +170,7 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ this._isLoaded = false; this._htmlElementObj = null; this._webTextureObj = null; + this._loadedEventListeners = []; }, releaseTexture:function () { @@ -521,6 +524,7 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ this._hasPremultipliedAlpha = false; this._hasMipmaps = false; + this._callLoadedEventCallbacks(); }, /** @@ -903,6 +907,19 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ this._hasPremultipliedAlpha = uiImage.isPremultipliedAlpha(); return true; + }, + + addLoadedEventListener: function (callback, target) { + this._loadedEventListeners.push({eventCallback: callback, eventTarget: target}); + }, + + _callLoadedEventCallbacks: function () { + var locListeners = this._loadedEventListeners; + for (var i = 0, len = locListeners.length; i < len; i++) { + var selCallback = locListeners[i]; + selCallback.eventCallback.call(selCallback.eventTarget, this); + } + locListeners.length = 0; } }); @@ -920,11 +937,14 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ _contentSize:null, _isLoaded:false, _htmlElementObj:null, + + _loadedEventListeners:null, /*public:*/ ctor:function () { this._contentSize = cc.size(0,0); this._isLoaded = false; this._htmlElementObj = null; + this._loadedEventListeners = []; }, /** @@ -975,11 +995,10 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ handleLoadedTexture:function () { this._isLoaded = true; + var locElement = this._htmlElementObj; + this._contentSize = new cc.Size(locElement.width, locElement.height); - var pixelsWide = this._htmlElementObj.width; - var pixelsHigh = this._htmlElementObj.height; - - this._contentSize = new cc.Size(pixelsWide, pixelsHigh); + this._callLoadedEventCallbacks(); }, description:function () { @@ -1096,8 +1115,6 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ return false; }, - - /** * These functions are needed to create mutable textures * @param {Array} data @@ -1112,8 +1129,6 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ return data; }, - - /** Drawing extensions to make it easy to draw basic quads using a CCTexture2D object. These functions require gl.TEXTURE_2D and both gl.VERTEX_ARRAY and gl.TEXTURE_COORD_ARRAY client states to be enabled. @@ -1135,8 +1150,6 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ //support only in WebGl rendering mode }, - - /** * Initializes a texture from a ETC file (note: initWithETCFile does not support on HTML5) * @note Compatible to Cocos2d-x @@ -1229,8 +1242,20 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ bitsPerPixelForFormat:function (format) { //support only in WebGl rendering mode return -1; - } + }, + + addLoadedEventListener:function(callback, target){ + this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); + }, + _callLoadedEventCallbacks:function(){ + var locListeners = this._loadedEventListeners; + for(var i = 0, len = locListeners.length; i < len; i++){ + var selCallback = locListeners[i]; + selCallback.eventCallback.call(selCallback.eventTarget, this); + } + locListeners.length = 0; + } }); cc.Texture2D = cc.Browser.supportWebGL ? cc.Texture2DWebGL : cc.Texture2DCanvas; diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index ae44271464..e59158e110 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -277,12 +277,12 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ cc.Assert(path != null, "TextureCache: path MUST not be null"); path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; - var image; + var image,that; if (texture) { if(texture.isLoaded()){ this._addImageAsyncCallBack(target, selector); }else{ - var that = this; + that = this; image = texture.getHtmlElementObj(); image.addEventListener("load", function () { texture.handleLoadedTexture(); @@ -293,7 +293,7 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ image = new Image(); image.crossOrigin = "Anonymous"; - var that = this; + that = this; image.addEventListener("load", function () { if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/CCBReader/CCNodeLoader.js index 4505a08bd7..8e879cf9d7 100644 --- a/extensions/CCBReader/CCNodeLoader.js +++ b/extensions/CCBReader/CCNodeLoader.js @@ -489,13 +489,9 @@ cc.NodeLoader = cc.Class.extend({ if(spriteSheet.length == 0){ spriteFile = ccbReader.getCCBRootPath() + spriteFile; var texture = cc.TextureCache.getInstance().addImage(spriteFile); - var bounds; - if(texture instanceof cc.Texture2D){ - var locContentSize = texture.getContentSize(); - bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); - }else{ - bounds = cc.RECT_PIXELS_TO_POINTS(cc.RectMake(0, 0, texture.width, texture.height)); - } + + var locContentSize = texture.getContentSize(); + var bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); spriteFrame = cc.SpriteFrame.createWithTexture(texture, bounds); } else { var frameCache = cc.SpriteFrameCache.getInstance(); diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/GUI/CCControlExtension/CCControlButton.js index 4612689f3e..6c41fc1a6c 100644 --- a/extensions/GUI/CCControlExtension/CCControlButton.js +++ b/extensions/GUI/CCControlExtension/CCControlButton.js @@ -226,7 +226,7 @@ cc.ControlButton = cc.Control.extend({ }, setPreferredSize:function (size) { - if (size.width == 0 && size.height == 0) { + if (size.width === 0 && size.height === 0) { this._adjustBackgroundImage = true; } else { this._adjustBackgroundImage = false; @@ -598,12 +598,12 @@ cc.ControlButton = cc.Control.extend({ sprite.setAnchorPoint(cc.p(0.5, 0.5)); this.addChild(sprite); - if (this._preferredSize.width != 0 || this._preferredSize.height != 0) { + if (this._preferredSize.width !== 0 || this._preferredSize.height !== 0) { sprite.setPreferredSize(this._preferredSize); } // If the current state if equal to the given state we update the layout - if (this.getState() == state) { + if (this._state === state) { this.needsLayout(); } }, @@ -621,7 +621,7 @@ cc.ControlButton = cc.Control.extend({ } }); -cc.ControlButton.create = function (label, backgroundSprite) { +cc.ControlButton.create = function(label, backgroundSprite) { var controlButton; if (arguments.length == 0) { controlButton = new cc.ControlButton(); @@ -632,16 +632,14 @@ cc.ControlButton.create = function (label, backgroundSprite) { } else if (arguments.length == 1) { controlButton = new cc.ControlButton(); controlButton.initWithBackgroundSprite(arguments[0]); - return controlButton; } else if (arguments.length == 2) { controlButton = new cc.ControlButton(); controlButton.initWithLabelAndBackgroundSprite(label, backgroundSprite); - return controlButton; } else if (arguments.length == 3) { controlButton = new cc.ControlButton(); controlButton.initWithTitleAndFontNameAndFontSize(arguments[0], arguments[1], arguments[2]); - return controlButton; } + return controlButton; }; diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 78cb10bfed..052216834b 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -319,7 +319,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ }, initWithBatchNode: function (batchNode, rect, rotated, capInsets) { - if (arguments.length == 3) { + if (arguments.length === 3) { capInsets = rotated; rotated = false; } @@ -377,6 +377,16 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ var selTexture = spriteFrame.getTexture(); cc.Assert(selTexture != null, "Texture must be not nil"); + if(!spriteFrame.textureLoaded()){ + spriteFrame.addLoadedEventListener(function(sender){ + // the texture is rotated on Canvas render mode, so isRotated always is false. + var preferredSize = this._preferredSize; + preferredSize = cc.size(preferredSize.width, preferredSize.height); + this.updateWithBatchNode(this._scale9Image, sender.getRect(), cc.Browser.supportWebGL ? sender.isRotated() : false, this._capInsets); + this.setPreferredSize(preferredSize); + this.m_positionsAreDirty = true; + },this); + } var batchNode = cc.SpriteBatchNode.createWithTexture(selTexture, 9); // the texture is rotated on Canvas render mode, so isRotated always is false. return this.initWithBatchNode(batchNode, spriteFrame.getRect(), cc.Browser.supportWebGL ? spriteFrame.isRotated() : false, capInsets); @@ -471,8 +481,11 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ var rectSize = rect.size; this._originalSize.width = rectSize.width; this._originalSize.height = rectSize.height; - this._preferredSize.width = rectSize.width; - this._preferredSize.height = rectSize.height; + var locPreferredSize = this._preferredSize; + if(locPreferredSize.width === 0 && locPreferredSize.height === 0){ + locPreferredSize.width = rectSize.width; + locPreferredSize.height = rectSize.height; + } var locCapInsetsInternal = this._capInsetsInternal; if(!capInsets){ From 6449f2a64959fb6f271dc074ee70bf68821160ad Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 21 Aug 2013 11:27:06 +0800 Subject: [PATCH 054/141] fixed #2531 Asynchronous loading texture for LabelBMFont on Canvas Mode has been implemented --- cocos2d/label_nodes/CCLabelBMFont.js | 54 +++++++++++++++++++++------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index 1d7eb2e581..f570f28364 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -445,6 +445,8 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ _cascadeColorEnabled:false, _cascadeOpacityEnabled:false, + _textureLoaded: false, + _setString:function(newString, needUpdateLabel){ if(!needUpdateLabel){ this._string = newString; @@ -489,10 +491,10 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._reusedChar = []; }, /** - * @param {CanvasContext} ctx + * @param {CanvasRenderingContext2D} ctx */ draw:function (ctx) { - this._super(); + this._super(ctx); //LabelBMFont - Debug draw if (cc.LABELBMFONT_DEBUG_DRAW) { @@ -510,17 +512,19 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ * @param {cc.Color3B} color3 */ setColor:function (color3) { - if ((this._realColor.r == color3.r) && (this._realColor.g == color3.g) && (this._realColor.b == color3.b)) + if (((this._realColor.r == color3.r) && (this._realColor.g == color3.g) && (this._realColor.b == color3.b))) return; this._displayedColor = {r:color3.r, g:color3.g, b:color3.b}; this._realColor = {r:color3.r, g:color3.g, b:color3.b}; - if(this._cascadeColorEnabled){ - var parentColor = cc.white(); - var locParent = this._parent; - if(locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) - parentColor = locParent.getDisplayedColor(); - this.updateDisplayedColor(parentColor); + if(this._textureLoaded){ + if(this._cascadeColorEnabled){ + var parentColor = cc.white(); + var locParent = this._parent; + if(locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) + parentColor = locParent.getDisplayedColor(); + this.updateDisplayedColor(parentColor); + } } }, @@ -681,10 +685,22 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._configuration = newConf; this._fntFile = fntFile; texture = cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName()); + var locIsLoaded = texture.isLoaded(); + this._textureLoaded = locIsLoaded; + if(!locIsLoaded){ + this._textureLoaded = false; + texture.addLoadedEventListener(function(sender){ + this._textureLoaded = true; + //reset the LabelBMFont + this.initWithTexture(texture, theString.length) + this.setString(theString,true); + }, this); + } } else{ texture = new cc.Texture2D(); var image = new Image(); texture.initWithElement(image); + this._textureLoaded = false; } if (this.initWithTexture(texture, theString.length)) { @@ -1131,11 +1147,25 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._fntFile = fntFile; this._configuration = newConf; - this.setTexture(cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName())); - if (cc.renderContextType === cc.CANVAS) { + var texture = cc.TextureCache.getInstance().addImage(this._configuration.getAtlasName()); + var locIsLoaded = texture.isLoaded(); + this._textureLoaded = locIsLoaded; + this.setTexture(texture); + if (cc.renderContextType === cc.CANVAS) this._originalTexture = this.getTexture(); - } this.createFontChars(); + if(!locIsLoaded){ + texture.addLoadedEventListener(function(){ + this._textureLoaded = true; + if(this._cascadeColorEnabled){ + var parentColor = cc.white(); + var locParent = this._parent; + if(locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) + parentColor = locParent.getDisplayedColor(); + this.updateDisplayedColor(parentColor); + } + }, this); + } } }, From 4ca2a4baf41d5ac3782a9570a773cf659f34c073 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 21 Aug 2013 14:56:59 +0800 Subject: [PATCH 055/141] fixed #2531 use direct calling function of parent class instead this._super --- HelloHTML5World/cocos2d.js | 2 +- cocos2d/CCDrawingPrimitives.js | 2 +- cocos2d/CCLoader.js | 2 +- cocos2d/base_nodes/CCAtlasNode.js | 4 +- cocos2d/draw_nodes/CCDrawNode.js | 6 +-- cocos2d/label_nodes/CCLabelAtlas.js | 24 +++++---- cocos2d/label_nodes/CCLabelBMFont.js | 13 ++--- .../CCTransition.js | 50 +++++++++---------- .../CCTransitionPageTurn.js | 4 +- .../CCTransitionProgress.js | 27 ++++------ cocos2d/particle_nodes/CCParticleBatchNode.js | 15 +++--- cocos2d/physics_nodes/CCPhysicsDebugNode.js | 2 +- cocos2d/physics_nodes/CCPhysicsSprite.js | 9 ++-- cocos2d/text_input_node/CCTextFieldTTF.js | 20 +++----- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 2 +- cocos2d/touch_dispatcher/CCTouchHandler.js | 7 +-- 16 files changed, 85 insertions(+), 104 deletions(-) diff --git a/HelloHTML5World/cocos2d.js b/HelloHTML5World/cocos2d.js index fb091f964f..30638e6410 100644 --- a/HelloHTML5World/cocos2d.js +++ b/HelloHTML5World/cocos2d.js @@ -33,7 +33,7 @@ showFPS:true, frameRate:60, loadExtension:false, - renderMode:1, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only) + renderMode:0, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only) tag:'gameCanvas', //the dom element to run cocos2d on engineDir:'../cocos2d/', //SingleEngineFile:'', diff --git a/cocos2d/CCDrawingPrimitives.js b/cocos2d/CCDrawingPrimitives.js index d21fd0d6a1..2851e42c54 100644 --- a/cocos2d/CCDrawingPrimitives.js +++ b/cocos2d/CCDrawingPrimitives.js @@ -608,7 +608,7 @@ cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ if (!ctx instanceof WebGLRenderingContext) throw "Can't initialise DrawingPrimitiveWebGL. context need is WebGLRenderingContext"; - this._super(ctx); + cc.DrawingPrimitive.prototype.ctor.call(this, ctx); this._color = new cc.Color4F(1.0, 1.0, 1.0, 1.0); }, diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index 68c55b566e..bcdad56b23 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -402,7 +402,7 @@ cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{ * Constructor */ ctor: function () { - this._super(); + cc.Scene.prototype.ctor.call(this); this._winSize = cc.Director.getInstance().getWinSize(); }, init:function(){ diff --git a/cocos2d/base_nodes/CCAtlasNode.js b/cocos2d/base_nodes/CCAtlasNode.js index fb3e1d34cb..1c1f4e042f 100644 --- a/cocos2d/base_nodes/CCAtlasNode.js +++ b/cocos2d/base_nodes/CCAtlasNode.js @@ -59,7 +59,7 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ _ignoreContentScaleFactor:false, // This variable is only used for CCLabelAtlas FPS display. So plz don't modify its value. ctor:function () { - this._super(); + cc.NodeRGBA.prototype.ctor.call(this); this._colorUnmodified = cc.white(); this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; this._ignoreContentScaleFactor = false; @@ -294,7 +294,7 @@ cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ _ignoreContentScaleFactor:false, // This variable is only used for CCLabelAtlas FPS display. So plz don't modify its value. ctor:function () { - this._super(); + cc.NodeRGBA.prototype.ctor.call(this); this._colorUnmodified = cc.white(); this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; this._ignoreContentScaleFactor = false; diff --git a/cocos2d/draw_nodes/CCDrawNode.js b/cocos2d/draw_nodes/CCDrawNode.js index 866379fa9e..3626cdfcc1 100644 --- a/cocos2d/draw_nodes/CCDrawNode.js +++ b/cocos2d/draw_nodes/CCDrawNode.js @@ -102,7 +102,7 @@ cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{ // ----common function end ---- ctor:function () { - this._super(); + cc.Node.prototype.ctor.call(this); this._buffer = []; this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); }, @@ -224,13 +224,13 @@ cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{ // ----common function end ---- ctor:function () { - this._super(); + cc.Node.prototype.ctor.call(this); this._buffer = []; this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); }, init:function () { - if (this._super()) { + if (cc.Node.prototype.init.call(this)) { this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR)); this._ensureCapacity(512); this._trianglesWebBuffer = cc.renderContext.createBuffer(); diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index f04bbbfe8b..b12b1888e2 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -88,7 +88,7 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ * @param {cc.Color3B} color3 */ setColor:function (color3) { - this._super(color3); + cc.AtlasNode.prototype.setColor.call(this, color3); this.updateAtlasValues(); }, /** @@ -103,7 +103,7 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ * draw the label */ draw:function () { - this._super(); + cc.AtlasNode.prototype.draw.call(this); if (cc.LABELATLAS_DEBUG_DRAW) { var s = this.getContentSize(); var vertices = [cc.p(0, 0), cc.p(s.width, 0), @@ -162,8 +162,9 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ this._string = label; this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight)); if (this._children) { - for (var i = 0; i < this._children.length; i++) { - var node = this._children[i]; + var locChildren = this._children; + for (var i = 0, len = locChildren.length; i < len; i++) { + var node = locChildren[i]; if (node) node.setVisible(false); } @@ -175,10 +176,11 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ setOpacity:function (opacity) { if (this._opacity != opacity) { - this._super(opacity); - for (var i = 0; i < this._children.length; i++) { - if (this._children[i]) - this._children[i].setOpacity(opacity); + cc.AtlasNode.prototype.setOpacity.call(this, opacity); + var locChildren = this._children; + for (var i = 0, len = locChildren.length; i < len; i++) { + if (locChildren[i]) + locChildren[i].setOpacity(opacity); } } } @@ -248,7 +250,7 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ * @param {cc.Color3B} color3 */ setColor:function (color3) { - this._super(color3); + cc.AtlasNode.prototype.setColor.call(this, color3); this.updateAtlasValues(); }, /** @@ -263,7 +265,7 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ * draw the label */ draw:function () { - this._super(); + cc.AtlasNode.prototype.draw.call(this); if (cc.LABELATLAS_DEBUG_DRAW) { var s = this.getContentSize(); var vertices = [cc.p(0, 0), cc.p(s.width, 0), @@ -364,7 +366,7 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ setOpacity:function (opacity) { if (this._opacity !== opacity) { - this._super(opacity); + cc.AtlasNode.prototype.setOpacity.call(this, opacity); } } }); diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index f570f28364..87ebcdeb1f 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -494,7 +494,7 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ * @param {CanvasRenderingContext2D} ctx */ draw:function (ctx) { - this._super(ctx); + cc.SpriteBatchNode.prototype.draw.call(this, ctx); //LabelBMFont - Debug draw if (cc.LABELBMFONT_DEBUG_DRAW) { @@ -1111,9 +1111,10 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ /** * @param {Number} scale + * @param {Number} [scaleY=null] */ setScale:function (scale, scaleY) { - this._super(scale, scaleY); + cc.Node.prototype.setScale.call(this, scale, scaleY); this.updateLabel(); }, @@ -1121,7 +1122,7 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ * @param {Number} scaleX */ setScaleX:function (scaleX) { - this._super(scaleX); + cc.Node.prototype.setScaleX.call(this,scaleX); this.updateLabel(); }, @@ -1129,7 +1130,7 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ * @param {Number} scaleY */ setScaleY:function (scaleY) { - this._super(scaleY); + cc.Node.prototype.setScaleY.call(this,scaleY); this.updateLabel(); }, @@ -1177,12 +1178,12 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ }, /** - * set the anchorpoint of the label + * set the AnchorPoint of the label * @param {cc.Point} point */ setAnchorPoint:function (point) { if (!cc.pointEqualToPoint(point, this._anchorPoint)) { - this._super(point); + cc.Node.prototype.setAnchorPoint.call(this, point); this.updateLabel(); } }, diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 1ac114cc56..24ea00d9d9 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -102,8 +102,6 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ * stuff gets drawn here */ draw:function () { - this._super(); - if (this._isInSceneOnTop) { this._outScene.visit(); this._inScene.visit(); @@ -117,7 +115,7 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ * custom onEnter */ onEnter:function () { - cc.Scene.prototype.onEnter.call(this); + cc.Node.prototype.onEnter.call(this); // disable events while transitions cc.Director.getInstance().getTouchDispatcher().setDispatchEvents(false); @@ -133,7 +131,7 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ * custom onExit */ onExit:function () { - cc.Scene.prototype.onExit.call(this); + cc.Node.prototype.onExit.call(this); // enable events while transitions cc.Director.getInstance().getTouchDispatcher().setDispatchEvents(true); @@ -149,7 +147,7 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ * custom cleanup */ cleanup:function () { - this._super(); + cc.Node.prototype.cleanup.call(this); if (this._isSendCleanupToScene) this._outScene.cleanup(); @@ -249,7 +247,7 @@ cc.TransitionSceneOriented = cc.TransitionScene.extend(/** @lends cc.TransitionS * @return {Boolean} */ initWithDuration:function (t, scene, orientation) { - if (this._super(t, scene)) { + if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) { this._orientation = orientation; } return true; @@ -290,7 +288,7 @@ cc.TransitionRotoZoom = cc.TransitionScene.extend(/** @lends cc.TransitionRotoZo * @override */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); this._inScene.setScale(0.001); this._outScene.setScale(1.0); @@ -337,7 +335,7 @@ cc.TransitionJumpZoom = cc.TransitionScene.extend(/** @lends cc.TransitionJumpZo * Custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var winSize = cc.Director.getInstance().getWinSize(); this._inScene.setScale(0.5); @@ -383,7 +381,7 @@ cc.TransitionMoveInL = cc.TransitionScene.extend(/** @lends cc.TransitionMoveInL * Custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); this.initScenes(); var action = this.action(); @@ -559,7 +557,7 @@ cc.TransitionSlideInL = cc.TransitionScene.extend(/** @lends cc.TransitionSlideI * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); this.initScenes(); var inA = this.action(); @@ -749,7 +747,7 @@ cc.TransitionShrinkGrow = cc.TransitionScene.extend(/** @lends cc.TransitionShri * Custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); this._inScene.setScale(0.001); this._outScene.setScale(1.0); @@ -804,7 +802,7 @@ cc.TransitionFlipX = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionF * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -874,7 +872,7 @@ cc.TransitionFlipY = cc.TransitionSceneOriented.extend(/** @lends cc.TransitionF * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -943,7 +941,7 @@ cc.TransitionFlipAngular = cc.TransitionSceneOriented.extend(/** @lends cc.Trans * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -1013,7 +1011,7 @@ cc.TransitionZoomFlipX = cc.TransitionSceneOriented.extend(/** @lends cc.Transit * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -1089,7 +1087,7 @@ cc.TransitionZoomFlipY = cc.TransitionSceneOriented.extend(/** @lends cc.Transit * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -1163,7 +1161,7 @@ cc.TransitionZoomFlipAngular = cc.TransitionSceneOriented.extend(/** @lends cc.T * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var inA, outA; this._inScene.setVisible(false); @@ -1236,7 +1234,7 @@ cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{ * Constructor */ ctor:function () { - this._super(); + cc.TransitionScene.prototype.ctor.call(this); this._color = new cc.Color3B() }, @@ -1244,7 +1242,7 @@ cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{ * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var l = cc.LayerColor.create(this._color); this._inScene.setVisible(false); @@ -1265,7 +1263,7 @@ cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{ * custom on exit */ onExit:function () { - this._super(); + cc.TransitionScene.prototype.onExit.call(this); this.removeChildByTag(cc.SCENE_FADE, false); }, @@ -1278,7 +1276,7 @@ cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{ */ initWithDuration:function (t, scene, color) { color = color || cc.black(); - if (this._super(t, scene)) { + if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) { this._color.r = color.r; this._color.g = color.g; this._color.b = color.b; @@ -1315,7 +1313,7 @@ cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCross * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); // create a transparent color layer // in which we are going to add our rendertextures @@ -1378,7 +1376,7 @@ cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCross */ onExit:function () { this.removeChildByTag(cc.SCENE_FADE, false); - this._super(); + cc.TransitionScene.prototype.onExit.call(this); }, /** @@ -1418,7 +1416,7 @@ cc.TransitionTurnOffTiles = cc.TransitionScene.extend(/** @lends cc.TransitionTu * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var winSize = cc.Director.getInstance().getWinSize(); var aspect = winSize.width / winSize.height; var x = 0 | (12 * aspect); @@ -1465,7 +1463,7 @@ cc.TransitionSplitCols = cc.TransitionScene.extend(/** @lends cc.TransitionSplit * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); this._inScene.setVisible(false); var split = this.action(); @@ -1555,7 +1553,7 @@ cc.TransitionFadeTR = cc.TransitionScene.extend(/** @lends cc.TransitionFadeTR# * Custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var winSize = cc.Director.getInstance().getWinSize(); var aspect = winSize.width / winSize.height; diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js index 93e0d6c750..f5c8d2546f 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js @@ -54,7 +54,7 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu // XXX: needed before [super init] this._back = backwards; - if (this._super(t, scene)) { + if (cc.TransitionScene.prototype.initWithDuration(this, t, scene)) { // do something } return true; @@ -75,7 +75,7 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu * custom on enter */ onEnter:function () { - this._super(); + cc.TransitionScene.prototype.onEnter.call(this); var winSize = cc.Director.getInstance().getWinSize(); var x, y; if (winSize.width > winSize.height) { diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js index e4d5b3e276..9d5b6ba404 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js @@ -45,8 +45,7 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre * @override */ onEnter:function () { - this._super(); - + cc.TransitionScene.prototype.onEnter.call(this); this._setupTransition(); // create a transparent color layer @@ -59,21 +58,16 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre texture.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); texture.setAnchorPoint(cc.p(0.5, 0.5)); - if (cc.renderContextType === cc.CANVAS) { - // render outScene to its texturebuffer - texture.clear(); - this._sceneToBeModified.visit(texture.context); - } else { - // render outScene to its texturebuffer - texture.clear(0, 0, 0, 1); - texture.begin(); - this._sceneToBeModified.visit(); - texture.end(); - } + // render outScene to its texturebuffer + texture.clear(0, 0, 0, 1); + texture.begin(); + this._sceneToBeModified.visit(); + texture.end(); + // Since we've passed the outScene to the texture we don't need it. - if (this._sceneToBeModified == this._outScene) { + if (this._sceneToBeModified == this._outScene) this.hideOutShowIn(); - } + // We need the texture in RenderTexture. var pNode = this._progressTimerNodeWithRenderTexture(texture); @@ -86,7 +80,6 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre // add the layer (which contains our two rendertextures) to the scene this.addChild(pNode, 2, cc.SCENE_RADIAL); - }, /** @@ -95,7 +88,7 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre onExit:function () { // remove our layer and release all containing objects this.removeChildByTag(cc.SCENE_RADIAL, true); - this._super(); + cc.TransitionScene.prototype.onExit.call(this); }, _setupTransition:function () { diff --git a/cocos2d/particle_nodes/CCParticleBatchNode.js b/cocos2d/particle_nodes/CCParticleBatchNode.js index 431796d110..00a0aee906 100644 --- a/cocos2d/particle_nodes/CCParticleBatchNode.js +++ b/cocos2d/particle_nodes/CCParticleBatchNode.js @@ -62,7 +62,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ _textureAtlas:null, ctor:function () { - this._super(); + cc.Node.prototype.ctor.call(this); this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; }, @@ -180,7 +180,7 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystemQuads as children"); cc.Assert(this._children.indexOf(child) > -1, "cc.ParticleBatchNode doesn't contain the sprite. Can't remove it"); - this._super(child, cleanup); + cc.Node.prototype.removeChild.call(this, child, cleanup); // remove child helper this._textureAtlas.removeQuadsAtIndex(child.getAtlasIndex(), child.getTotalParticles()); @@ -253,10 +253,11 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ * @param {Boolean} doCleanup */ removeAllChildren:function (doCleanup) { - for (var i = 0; i < this._children.length; i++) { - this._children[i].setBatchNode(null); + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) { + locChildren[i].setBatchNode(null); } - this._super(doCleanup); + cc.Node.prototype.removeAllChildren.call(this, doCleanup); this._textureAtlas.removeAllQuads(); }, @@ -335,10 +336,8 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ // override visit. // Don't call visit on it's children visit:function (ctx) { - if (cc.renderContextType === cc.CANVAS) { - this._super(ctx); + if (cc.renderContextType === cc.CANVAS) return; - } // CAREFUL: // This visit is almost identical to cc.Node#visit diff --git a/cocos2d/physics_nodes/CCPhysicsDebugNode.js b/cocos2d/physics_nodes/CCPhysicsDebugNode.js index f5c3e2de3a..d598ba7732 100644 --- a/cocos2d/physics_nodes/CCPhysicsDebugNode.js +++ b/cocos2d/physics_nodes/CCPhysicsDebugNode.js @@ -136,7 +136,7 @@ cc.PhysicsDebugNode = cc.DrawNode.extend({ this._spacePtr.eachShape(cc.DrawShape.bind(this)); this._spacePtr.eachConstraint(cc.DrawConstraint.bind(this)); - this._super(); + cc.DrawNode.prototype.draw.call(this); this.clear(); } }); diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js index cfee963008..10873ea427 100644 --- a/cocos2d/physics_nodes/CCPhysicsSprite.js +++ b/cocos2d/physics_nodes/CCPhysicsSprite.js @@ -119,9 +119,8 @@ }, setRotation:function (r) { if (this._ignoreBodyRotation) { - this._super(r); - } - else { + cc.Sprite.prototype.setRotation.call(this, r); + } else { this._body.a = -cc.DEGREES_TO_RADIANS(r); //this._syncRotation(); } @@ -255,7 +254,7 @@ /** * Creates a PhysicsSprite with a sprite frame name - * @param {String} spriteFrame name + * @param {String} spriteFrameName * @return {cc.Sprite} * @example * @@ -299,6 +298,4 @@ } return null; }; - - })(); diff --git a/cocos2d/text_input_node/CCTextFieldTTF.js b/cocos2d/text_input_node/CCTextFieldTTF.js index 61f02c6209..52a16a5eb3 100644 --- a/cocos2d/text_input_node/CCTextFieldTTF.js +++ b/cocos2d/text_input_node/CCTextFieldTTF.js @@ -98,7 +98,7 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ ctor:function () { this._ColorSpaceHolder = new cc.Color3B(127, 127, 127); cc.IMEDispatcher.getInstance().addDelegate(this); - this._super(); + cc.LabelTTF.prototype.ctor.call(this); }, /** @@ -176,22 +176,16 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ /** * Input text property * @param {String} text - * @param {Boolean} isCallParent */ - setString:function (text, isCallParent) { + setString:function (text) { text = String(text); - if (isCallParent && isCallParent == true) { - this._super(text); - return; - } - this._inputText = text || ""; // if there is no input text, display placeholder instead if (!this._inputText.length) - this._super(this._placeHolder); + cc.LabelTTF.prototype.setString.call(this, this._placeHolder); else - this._super(this._inputText); + cc.LabelTTF.prototype.setString.call(this,this._inputText); this._charCount = this._inputText.length; }, @@ -229,14 +223,14 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ return; if (this._inputText && this._inputText.length > 0) { - this._super(context); + cc.LabelTTF.prototype.draw.call(this, context); return; } // draw placeholder var color = this.getColor(); this.setColor(this._ColorSpaceHolder); - this._super(context); + cc.LabelTTF.prototype.draw.call(this, context); this.setColor(color); }, @@ -311,7 +305,7 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ // set new input text var sText = this._inputText.substring(0, strLen - deleteLen); - this.setString(sText, false); + this.setString(sText); }, /** diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index 6a54eb99f4..7211b3e37c 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -592,7 +592,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ var zz = this._atlasIndexArray[atlasIndex]; this._tiles[zz] = 0; cc.ArrayRemoveObjectAtIndex(this._atlasIndexArray, atlasIndex); - this._super(sprite, cleanup); + cc.SpriteBatchNode.prototype.removeChild.call(this, sprite, cleanup); }, /** diff --git a/cocos2d/touch_dispatcher/CCTouchHandler.js b/cocos2d/touch_dispatcher/CCTouchHandler.js index a67f2130e3..90f010cceb 100644 --- a/cocos2d/touch_dispatcher/CCTouchHandler.js +++ b/cocos2d/touch_dispatcher/CCTouchHandler.js @@ -121,10 +121,7 @@ cc.StandardTouchHandler = cc.TouchHandler.extend(/** @lends cc.StandardTouchHand * @return {Boolean} */ initWithDelegate:function (delegate, priority) { - if (this._super(delegate, priority)) { - return true; - } - return false; + return cc.TouchHandler.prototype.initWithDelegate.call(this, delegate, priority); } }); @@ -181,7 +178,7 @@ cc.TargetedTouchHandler = cc.TouchHandler.extend(/** @lends cc.TargetedTouchHand * @return {Boolean} */ initWithDelegate:function (delegate, priority, swallow) { - if (this._super(delegate, priority)) { + if (cc.TouchHandler.prototype.initWithDelegate.call(this, delegate, priority)) { this._claimedTouches = []; this._swallowsTouches = swallow; return true; From 64a9d326c50a1d7a3397da18fff168c301463300 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 22 Aug 2013 13:46:58 +0800 Subject: [PATCH 056/141] fixed #2531 Async loading textures for cc.LabelBMFont has been implemented. --- cocos2d/label_nodes/CCLabelBMFont.js | 34 +++++++++++------------ cocos2d/sprite_nodes/CCSprite.js | 33 +++++++++++----------- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 2 +- cocos2d/textures/CCTexture2D.js | 22 ++++++++++++++- 4 files changed, 56 insertions(+), 35 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index 87ebcdeb1f..2e430c64dc 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -461,10 +461,12 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ selNode.setVisible(false); } } - this.createFontChars(); + if(this._textureLoaded){ + this.createFontChars(); - if(needUpdateLabel) - this.updateLabel(); + if(needUpdateLabel) + this.updateLabel(); + } }, /** * Constructor @@ -692,7 +694,7 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ texture.addLoadedEventListener(function(sender){ this._textureLoaded = true; //reset the LabelBMFont - this.initWithTexture(texture, theString.length) + this.initWithTexture(sender, theString.length) this.setString(theString,true); }, this); } @@ -794,14 +796,14 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ rect.y += this._imageOffset.y; var fontChar = this.getChildByTag(i); - var hasSprite = true; + //var hasSprite = true; if (!fontChar) { fontChar = new cc.Sprite(); if ((key === 32) && (locContextType === cc.CANVAS)) { fontChar.initWithTexture(locTexture, cc.RectZero(), false); } else fontChar.initWithTexture(locTexture, rect, false); - + fontChar._newTextureWhenChangeColor = true; this.addChild(fontChar, 0, i); } else { if ((key === 32) && (locContextType === cc.CANVAS)) { @@ -816,10 +818,10 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ // Apply label properties fontChar.setOpacityModifyRGB(this._opacityModifyRGB); // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on - if(cc.Browser.supportWebGL){ + if (cc.Browser.supportWebGL) { fontChar.updateDisplayedColor(this._displayedColor); fontChar.updateDisplayedOpacity(this._displayedOpacity); - }else{ + } else { cc.NodeRGBA.prototype.updateDisplayedColor.call(fontChar, this._displayedColor); cc.NodeRGBA.prototype.updateDisplayedOpacity.call(fontChar, this._displayedOpacity); fontChar.setNodeDirty(); @@ -1154,18 +1156,16 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this.setTexture(texture); if (cc.renderContextType === cc.CANVAS) this._originalTexture = this.getTexture(); - this.createFontChars(); if(!locIsLoaded){ - texture.addLoadedEventListener(function(){ + texture.addLoadedEventListener(function(sender){ this._textureLoaded = true; - if(this._cascadeColorEnabled){ - var parentColor = cc.white(); - var locParent = this._parent; - if(locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) - parentColor = locParent.getDisplayedColor(); - this.updateDisplayedColor(parentColor); - } + this.setTexture(sender); + this.createFontChars(); + this._changeTextureColor(); + this.updateLabel(); }, this); + } else { + this.createFontChars(); } } }, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index c74da2042c..ce9bb97102 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -166,7 +166,7 @@ cc.generateTintImage = function (texture, tintedImgCache, color, rect, renderCan rect = cc.rect(0, 0, texture.width, texture.height); var selColor; - if (color instanceof cc.Color3B) { + 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 { @@ -331,8 +331,9 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ _flipX:false, //Whether the sprite is flipped horizontally or not. _flipY:false, //Whether the sprite is flipped vertically or not. - _textureLoaded:false, - _loadedEventListeners:null, + _textureLoaded: false, + _loadedEventListeners: null, + _newTextureWhenChangeColor: null, //hack property for LabelBMFont textureLoaded:function(){ return this._textureLoaded; @@ -882,6 +883,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; this._textureLoaded = true; this._loadedEventListeners = []; + this._newTextureWhenChangeColor = false; if (fileName) { if (typeof(fileName) == "string") { @@ -1291,15 +1293,15 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (cacheTextureForColor) { this._colorized = true; //generate color texture cache - /*if (locElement instanceof HTMLCanvasElement && !this._rectRotated) + if (locElement instanceof HTMLCanvasElement && !this._rectRotated && !this._newTextureWhenChangeColor) cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect, locElement); - else {*/ + else { locElement = cc.generateTintImage(locElement, cacheTextureForColor, this._displayedColor, locRect); locTexture = new cc.Texture2D(); locTexture.initWithElement(locElement); locTexture.handleLoadedTexture(); this.setTexture(locTexture); - //} + } } } }, @@ -1317,31 +1319,31 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ context.globalCompositeOperation = 'lighter'; context.globalAlpha = this._displayedOpacity / 255; - var locRect = this._rect; - var flipXOffset = 0 | (this._offsetPosition.x), flipYOffset = -this._offsetPosition.y - locRect.height; + var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; + var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; if (this._flipX) { - flipXOffset = -this._offsetPosition.x - locRect.width; + flipXOffset = -locOffsetPosition.x - locRect.width; context.scale(-1, 1); } if (this._flipY) { - flipYOffset = this._offsetPosition.y; + flipYOffset = locOffsetPosition.y; context.scale(1, -1); } - if (this._texture && locRect.width > 0 && locRect.height > 0) { + if (this._texture && locRect.width > 0) { var image = this._texture.getHtmlElementObj(); if (this._colorized) { context.drawImage(image, - 0, 0, locRect.width , locRect.height , + 0, 0, locRect.width, locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); } else { context.drawImage(image, - locRect.x , locRect.y , locRect.width , locRect.height , + locRect.x, locRect.y, locRect.width, locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); } - } else if (this._contentSize.width !== 0) { + } else if (locContentSize.width !== 0) { var curColor = this.getColor(); context.fillStyle = "rgba(" + curColor.r + "," + curColor.g + "," + curColor.b + ",1)"; - context.fillRect(flipXOffset, flipYOffset, this._contentSize.width, this._contentSize.height); + context.fillRect(flipXOffset, flipYOffset, locContentSize.width, locContentSize.height); } if (cc.SPRITE_DEBUG_DRAW === 1) { @@ -2091,7 +2093,6 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite"); var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { - filename = cc.FileUtils.getInstance().fullPathForFilename(filename); texture = cc.TextureCache.getInstance().addImage(filename); return this.initWithTexture(texture, rect); } else { diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index 855a89bbf3..1e7a5d6bb4 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -1273,7 +1273,7 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); // check cc.Sprite is using the same texture id - cc.Assert(child.getTexture()._webTextureObj == this._textureAtlas.getTexture()._webTextureObj, + cc.Assert(child.getTexture() == this._textureAtlas.getTexture(), "SpriteBatchNode.addChild():cc.Sprite is not using the same texture id"); cc.Node.prototype.addChild.call(this, child, zOrder, tag); this.appendChild(child); diff --git a/cocos2d/textures/CCTexture2D.js b/cocos2d/textures/CCTexture2D.js index 1033043f5d..b9f12d0089 100644 --- a/cocos2d/textures/CCTexture2D.js +++ b/cocos2d/textures/CCTexture2D.js @@ -160,7 +160,7 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ this._maxS = 0; this._maxT = 0; this._hasPremultipliedAlpha = false; - this._contentSize = null; + this._contentSize = cc.size(0, 0); this._hasMipmaps = false; this._pVRHaveAlphaPremultiplied = true; @@ -913,6 +913,16 @@ cc.Texture2DWebGL = cc.Class.extend(/** @lends cc.Texture2D# */{ this._loadedEventListeners.push({eventCallback: callback, eventTarget: target}); }, + removeLoadedEventListener:function(target){ + var locListeners = this._loadedEventListeners; + for(var i = 0; i < locListeners.length; i++){ + var selCallback = locListeners[i]; + if(selCallback.eventTarget == target){ + locListeners.splice(i, 1); + } + } + }, + _callLoadedEventCallbacks: function () { var locListeners = this._loadedEventListeners; for (var i = 0, len = locListeners.length; i < len; i++) { @@ -1248,6 +1258,16 @@ cc.Texture2DCanvas = cc.Class.extend(/** @lends cc.Texture2D# */{ this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); }, + removeLoadedEventListener:function(target){ + var locListeners = this._loadedEventListeners; + for(var i = 0; i < locListeners.length; i++){ + var selCallback = locListeners[i]; + if(selCallback.eventTarget == target){ + locListeners.splice(i, 1); + } + } + }, + _callLoadedEventCallbacks:function(){ var locListeners = this._loadedEventListeners; for(var i = 0, len = locListeners.length; i < len; i++){ From aa8a5fa5601c06fee67220443e0e1a176cce1052 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 22 Aug 2013 14:32:01 +0800 Subject: [PATCH 057/141] fixed #1089 fixed a bug of cc.LayerColorCanvas that respecting incorrect opacity passed into init method --- cocos2d/layers_scenes_transitions_nodes/CCLayer.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 19977ec8c3..6b3839212f 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -828,7 +828,9 @@ cc.LayerColorCanvas = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ this._realColor.g = color.g; this._realColor.b = color.b; - this._opacity = color.a; + this._displayedOpacity = color.a; + this._realOpacity = color.a; + this.setContentSize(cc.size(width, height)); this._updateColor(); return true; From 25efe68d9375dca73f55af7bd5179fc062dfe525 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 23 Aug 2013 11:35:08 +0800 Subject: [PATCH 058/141] issue #2506: use direct call parent's function instead this._super for extensions --- cocos2d/base_nodes/CCNode.js | 36 ++------- cocos2d/sprite_nodes/CCSprite.js | 4 +- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 4 +- extensions/CCBReader/CCBAnimationManager.js | 4 +- extensions/CCBReader/CCControlLoader.js | 44 +++++------ extensions/CCBReader/CCSpriteLoader.js | 74 +++++++++---------- extensions/CCEditBox.js | 2 +- .../GUI/CCControlExtension/CCControl.js | 10 +-- .../GUI/CCControlExtension/CCControlButton.js | 8 +- .../GUI/CCControlExtension/CCScale9Sprite.js | 4 +- extensions/GUI/CCScrollView/CCScrollView.js | 4 +- extensions/GUI/CCScrollView/CCTableView.js | 2 +- 12 files changed, 82 insertions(+), 114 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index ea08902136..e9dfe0c8d4 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -1143,19 +1143,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ _insertChild:function (child, z) { this._reorderChildDirty = true; - var __children = this._children; - var a = __children[__children.length - 1]; - if (!a || a.getZOrder() <= z) - __children.push(child); - else { - for (var i = 0; i < __children.length; i++) { - var node = __children[i]; - if (node && (node.getZOrder() > z )) { - this._children = cc.ArrayAppendObjectToIndex(__children, child, i); - break; - } - } - } + this._children.push(child); child._setZOrder(z); }, @@ -1193,9 +1181,9 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ //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 ))) { - tempChild = _children[j]; _children[j + 1] = tempChild; j = j - 1; + tempChild = _children[j]; } _children[j + 1] = tempItem; } @@ -2986,19 +2974,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ _insertChild:function (child, z) { this._reorderChildDirty = true; - var __children = this._children; - var a = __children[__children.length - 1]; - if (!a || a.getZOrder() <= z) - __children.push(child); - else { - for (var i = 0; i < __children.length; i++) { - var node = __children[i]; - if (node && (node.getZOrder() > z )) { - this._children = cc.ArrayAppendObjectToIndex(__children, child, i); - break; - } - } - } + this._children.push(child); child._setZOrder(z); }, @@ -3036,9 +3012,9 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ //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 ))) { - tempChild = _children[j]; _children[j + 1] = tempChild; j = j - 1; + tempChild = _children[j]; } _children[j + 1] = tempItem; } @@ -3544,9 +3520,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ } this.draw(context); for (; i < len; i++) { - child = children[i]; - if (child._zOrder >= 0) - child.visit(context); + children[i].visit(context); } } else this.draw(context); diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index ce9bb97102..f3fdcdbba0 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -523,9 +523,9 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ //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 ))) { - tempChild = locChildren[j]; locChildren[j + 1] = tempChild; j = j - 1; + tempChild = locChildren[j]; } locChildren[j + 1] = tempItem; } @@ -1629,9 +1629,9 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ //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 ))) { - tempChild = locChildren[j]; locChildren[j + 1] = tempChild; j = j - 1; + tempChild = locChildren[j]; } locChildren[j + 1] = tempItem; } diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index 1e7a5d6bb4..92e3a00c66 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -597,9 +597,9 @@ cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# * //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 ))) { - tempChild = locChildren[j]; locChildren[j + 1] = tempChild; j = j - 1; + tempChild = locChildren[j]; } locChildren[j + 1] = tempItem; } @@ -1312,9 +1312,9 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ //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 ))) { - tempChild = childrenArr[j]; childrenArr[j + 1] = tempChild; j = j - 1; + tempChild = childrenArr[j]; } childrenArr[j + 1] = tempItem; } diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/CCBReader/CCBAnimationManager.js index 3005295504..0f67fb02ce 100644 --- a/extensions/CCBReader/CCBAnimationManager.js +++ b/extensions/CCBReader/CCBAnimationManager.js @@ -665,7 +665,7 @@ cc.BuilderRotateTo = cc.ActionInterval.extend({ _diffAngle:0, initWithDuration:function (duration, angle) { - if (this._super(duration)) { + if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { this._dstAngle = angle; return true; } else { @@ -677,7 +677,7 @@ cc.BuilderRotateTo = cc.ActionInterval.extend({ }, startWithTarget:function (node) { - this._super(node); + cc.ActionInterval.prototype.startWithTarget.call(this, node); this._startAngle = this._target.getRotation(); this._diffAngle = this._dstAngle - this._startAngle; } diff --git a/extensions/CCBReader/CCControlLoader.js b/extensions/CCBReader/CCControlLoader.js index 4924cc5379..c1c4a56e31 100644 --- a/extensions/CCBReader/CCControlLoader.js +++ b/extensions/CCBReader/CCControlLoader.js @@ -34,7 +34,7 @@ cc.BuilderFileLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_CCBFILE) { node.setCCBFileNode(ccbFileNode); } else { - this._super(node, parent, propertyName, ccbFileNode, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader); } } }); @@ -54,7 +54,7 @@ cc.ControlLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_CCCONTROL) { node.addTargetWithActionForControlEvents(blockCCControlData.target, blockCCControlData.selCCControlHandler, blockCCControlData.controlEvents); } else { - this._super(node, parent, propertyName, blockCCControlData, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlockCCControl.call(this, node, parent, propertyName, blockCCControlData, ccbReader); } }, onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { @@ -63,7 +63,7 @@ cc.ControlLoader = cc.NodeLoader.extend({ } else if (propertyName == PROPERTY_SELECTED) { node.setSelected(check); } else { - this._super(node, parent, propertyName, check, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); } } }); @@ -96,7 +96,7 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ if (propertyName == PROPERTY_ZOOMONTOUCHDOWN) { node.setZoomOnTouchDown(check); } else { - this._super(node, parent, propertyName, check, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); } }, onHandlePropTypeString:function (node, parent, propertyName, stringValue, ccbReader) { @@ -107,7 +107,7 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ } else if (propertyName == PROPERTY_TITLE_DISABLED) { node.setTitleForState(stringValue, cc.CONTROL_STATE_DISABLED); } else { - this._super(node, parent, propertyName, stringValue, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeString.call(this, node, parent, propertyName, stringValue, ccbReader); } }, onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) { @@ -118,7 +118,7 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ } else if (propertyName == PROPERTY_TITLETTF_DISABLED) { node.setTitleTTFForState(fontTTF, cc.CONTROL_STATE_DISABLED); } else { - this._super(node, parent, propertyName, fontTTF, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader); } }, onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) { @@ -129,21 +129,21 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ } else if (propertyName == PROPERTY_TITLETTFSIZE_DISABLED) { node.setTitleTTFSizeForState(floatScale, cc.CONTROL_STATE_DISABLED); } else { - this._super(node, parent, propertyName, floatScale, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader); } }, onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) { if (propertyName == PROPERTY_LABELANCHORPOINT) { node.setLabelAnchorPoint(point); } else { - this._super(node, parent, propertyName, point, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader); } }, onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) { if (propertyName == PROPERTY_PREFEREDSIZE) { node.setPreferredSize(size); } else { - this._super(node, parent, propertyName, size, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader); } }, onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) { @@ -160,7 +160,7 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ node.setBackgroundSpriteFrameForState(spriteFrame, cc.CONTROL_STATE_DISABLED); } } else { - this._super(node, parent, propertyName, spriteFrame, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader); } }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { @@ -171,7 +171,7 @@ cc.ControlButtonLoader = cc.ControlLoader.extend({ } else if (propertyName == PROPERTY_TITLECOLOR_DISABLED) { node.setTitleColorForState(ccColor3B, cc.CONTROL_STATE_DISABLED); } else { - this._super(node, parent, propertyName, ccColor3B, ccbReader); + cc.ControlLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } } }); @@ -195,7 +195,7 @@ cc.ScrollViewLoader = cc.NodeLoader.extend({ if(propertyName == PROPERTY_CONTENTSIZE){ node.setViewSize(size); }else{ - this._super(node,parent,propertyName.size,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node,parent,propertyName.size,ccbReader); } }, @@ -204,7 +204,7 @@ cc.ScrollViewLoader = cc.NodeLoader.extend({ node.setContainer(ccbFileNode); node.updateInset(); } else { - this._super(node, parent, propertyName, ccbFileNode, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCCBFile.call(this, node, parent, propertyName, ccbFileNode, ccbReader); } }, onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { @@ -213,21 +213,21 @@ cc.ScrollViewLoader = cc.NodeLoader.extend({ } else if (propertyName == PROPERTY_BOUNCES) { node.setBounceable(check); } else { - this._super(node, parent, propertyName, check, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); } }, onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) { if (propertyName == PROPERTY_SCALE) { node.setScale(floatValue); } else { - this._super(node, parent, propertyName, floatValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader); } }, onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) { if (propertyName == PROPERTY_DIRECTION) { node.setDirection(integerLabeled); } else { - this._super(node, parent, propertyName, integerLabeled, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader); } } }); @@ -255,14 +255,14 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ if(propertyName == PROPERTY_COLOR) { node.setColor(ccColor3B); } else { - this._super(node, parent, propertyName, ccColor3B,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B,ccbReader); } }, onHandlePropTypeByte:function(node, parent, propertyName, byteValue,ccbReader){ if(propertyName == PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue,ccbReader); } }, onHandlePropTypeBlendFunc:function(node, parent, propertyName, ccBlendFunc,ccbReader){ @@ -270,14 +270,14 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ // TODO Not exported by CocosBuilder yet! // node.setBlendFunc(ccBlendFunc); } else { - this._super(node, parent, propertyName, ccBlendFunc,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc,ccbReader); } }, onHandlePropTypeSpriteFrame:function(node, parent, propertyName, spriteFrame,ccbReader){ if(propertyName == PROPERTY_SPRITEFRAME) { node.initWithSpriteFrame(spriteFrame); } else { - this._super(node, parent, propertyName, spriteFrame,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame,ccbReader); } }, onHandlePropTypeSize:function(node, parent, propertyName, size,ccbReader){ @@ -286,7 +286,7 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ } else if(propertyName == PROPERTY_PREFEREDSIZE) { node.setPreferredSize(size); } else { - this._super(node, parent, propertyName, size,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size,ccbReader); } }, onHandlePropTypeFloat:function(node, parent, propertyName, floatValue,ccbReader){ @@ -299,7 +299,7 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ } else if(propertyName == PROPERTY_INSETBOTTOM) { node.setInsetBottom(floatValue); } else { - this._super(node, parent, propertyName, floatValue,ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue,ccbReader); } } }); diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 9674be90d0..85e841282f 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -39,28 +39,28 @@ cc.SpriteLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_COLOR) { node.setColor(color3BValue); } else { - this._super(node, parent, propertyName, color3BValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, color3BValue, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { if (propertyName == PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccbBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccbBlendFunc); } else { - this._super(node, parent, propertyName, ccbBlendFunc, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccbBlendFunc, ccbReader); } }, onHandlePropTypeSpriteFrame:function (node, parent, propertyName, ccSpriteFrame, ccbReader) { if (propertyName == PROPERTY_DISPLAYFRAME) { node.setDisplayFrame(ccSpriteFrame); } else { - this._super(node, parent, propertyName, ccSpriteFrame, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, ccSpriteFrame, ccbReader); } }, onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) { @@ -68,7 +68,7 @@ cc.SpriteLoader = cc.NodeLoader.extend({ node.setFlipX(flip[0]); node.setFlipY(flip[1]); } else { - this._super(node, parent, propertyName, flip, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFlip.call(this, node, parent, propertyName, flip, ccbReader); } } }); @@ -106,7 +106,7 @@ cc.LayerLoader = cc.NodeLoader.extend({ // This comes closest: ((CCLayer *)pNode).setKeypadEnabled(pCheck); } } else { - this._super(node, parent, propertyName, check, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); } } }); @@ -125,21 +125,21 @@ cc.LayerColorLoader = cc.LayerLoader.extend({ if (propertyName == PROPERTY_COLOR) { node.setColor(ccColor3B); } else { - this._super(node, parent, propertyName, ccColor3B, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { if (propertyName == PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { - this._super(node, parent, propertyName, ccBlendFunc, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } } }); @@ -164,7 +164,7 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ } else if (propertyName == PROPERTY_ENDCOLOR) { node.setEndColor(ccColor3B); } else { - this._super(node, parent, propertyName, ccColor3B, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { @@ -173,7 +173,7 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ } else if (propertyName == PROPERTY_ENDOPACITY) { node.setEndOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) { @@ -182,14 +182,14 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ // TODO Not passed along the ccbi file. // node.setCompressedInterpolation(true); } else { - this._super(node, parent, propertyName, point, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { - this._super(node, parent, propertyName, ccBlendFunc, ccbReader); + cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } } }); @@ -222,14 +222,14 @@ cc.MenuItemLoader = cc.NodeLoader.extend({ node.setTarget(blockData.selMenuHander, blockData.target); } } else { - this._super(node, parent, propertyName, blockData, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlock.call(this, node, parent, propertyName, blockData, ccbReader); } }, onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { if (propertyName == PROPERTY_ISENABLED) { node.setEnabled(check); } else { - this._super(node, parent, propertyName, check, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); } } }); @@ -257,7 +257,7 @@ cc.MenuItemImageLoader = cc.MenuItemLoader.extend({ node.setDisabledSpriteFrame(spriteFrame); } } else { - this._super(node, parent, propertyName, spriteFrame, ccbReader); + cc.MenuItemLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, spriteFrame, ccbReader); } } }); @@ -281,42 +281,42 @@ cc.LabelTTFLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_COLOR) { node.setColor(ccColor3B); } else { - this._super(node, parent, propertyName, ccColor3B, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { if (propertyName == PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { - this._super(pNode, pParent, propertyName, ccBlendFunc, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) { if (propertyName == PROPERTY_FONTNAME) { node.setFontName(fontTTF); } else { - this._super(node, parent, propertyName, fontTTF, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader); } }, onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) { if (propertyName == PROPERTY_STRING) { node.setString(textValue); } else { - this._super(node, parent, propertyName, textValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader); } }, onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) { if (propertyName == PROPERTY_FONTSIZE) { node.setFontSize(floatScale); } else { - this._super(node, parent, propertyName, floatScale, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader); } }, onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) { @@ -325,14 +325,14 @@ cc.LabelTTFLoader = cc.NodeLoader.extend({ } else if (propertyName == PROPERTY_VERTICALALIGNMENT) { node.setVerticalAlignment(integerLabeled); } else { - this._super(node, parent, propertyName, integerLabeled, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader); } }, onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) { if (propertyName == PROPERTY_DIMENSIONS) { node.setDimensions(size); } else { - this._super(node, parent, propertyName, size, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader); } } }); @@ -352,35 +352,35 @@ cc.LabelBMFontLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_COLOR) { node.setColor(ccColor3B); } else { - this._super(node, parent, propertyName, ccColor3B, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { if (propertyName == PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { - this._super(node, parent, propertyName, byteValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { - this._super(node, parent, propertyName, ccBlendFunc, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeFntFile:function (node, parent, propertyName, fntFile, ccbReader) { if (propertyName == PROPERTY_FNTFILE) { node.setFntFile(fntFile); } else { - this._super(node, parent, propertyName, fntFile, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFntFile.call(this, node, parent, propertyName, fntFile, ccbReader); } }, onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) { if (propertyName == PROPERTY_STRING) { node.setString(textValue); } else { - this._super(node, parent, propertyName, textValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader); } } }); @@ -418,7 +418,7 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ if (propertyName == PROPERTY_EMITERMODE) { node.setEmitterMode(integerLabeled); } else { - this._super(node, parent, propertyName, integerLabeled, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader); } }, onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) { @@ -427,7 +427,7 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ } else if (propertyName == PROPERTY_GRAVITY) { node.setGravity(point); } else { - this._super(node, parent, propertyName, point, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader); } }, onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) { @@ -436,14 +436,14 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ } else if (propertyName == PROPERTY_DURATION) { node.setDuration(floatValue); } else { - this._super(node, parent, propertyName, floatValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader); } }, onHandlePropTypeInteger:function (node, parent, propertyName, integerValue, ccbReader) { if (propertyName == PROPERTY_TOTALPARTICLES) { node.setTotalParticles(integerValue); } else { - this._super(node, parent, propertyName, integerValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeInteger.call(this, node, parent, propertyName, integerValue, ccbReader); } }, onHandlePropTypeFloatVar:function (node, parent, propertyName, floatVar, ccbReader) { @@ -484,7 +484,7 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ node.setRotatePerSecond(floatVar[0]); node.setRotatePerSecondVar(floatVar[1]); } else { - this._super(node, parent, propertyName, floatVar, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeFloatVar.call(this, node, parent, propertyName, floatVar, ccbReader); } }, onHandlePropTypeColor4FVar:function (node, parent, propertyName, ccColor4FVar, ccbReader) { @@ -495,21 +495,21 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ node.setEndColor(ccColor4FVar[0]); node.setEndColorVar(ccColor4FVar[1]); } else { - this._super(node, parent, propertyName, ccColor4FVar, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor4FVar.call(this, node, parent, propertyName, ccColor4FVar, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { if (propertyName == PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { - this._super(node, parent, propertyName, ccBlendFunc, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeTexture:function (node, parent, propertyName, ccTexture2D, ccbReader) { if (propertyName == PROPERTY_TEXTURE) { node.setTexture(ccTexture2D); } else { - this._super(node, parent, propertyName, ccTexture2D, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeTexture.call(this, node, parent, propertyName, ccTexture2D, ccbReader); } } }); diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index 73b94bf9a5..e738d17aba 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -209,7 +209,7 @@ cc.EditBox = cc.ControlButton.extend({ * * Constructor. * */ ctor: function (boxSize) { - this._super(); + cc.ControlButton.prototype.ctor.call(this); this._textColor = cc.WHITE; this._placeholderColor = cc.GRAY; diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/GUI/CCControlExtension/CCControl.js index 79b890e607..c3a7dc14e2 100644 --- a/extensions/GUI/CCControlExtension/CCControl.js +++ b/extensions/GUI/CCControlExtension/CCControl.js @@ -142,13 +142,13 @@ cc.Control = cc.LayerRGBA.extend({ }, ctor:function () { - this._super(); + cc.LayerRGBA.prototype.ctor.call(this); this._dispatchTable = {}; this._color = cc.white(); }, init:function () { - if (this._super()) { + if (cc.LayerRGBA.prototype.init.call(this)) { //this.setTouchEnabled(true); //m_bIsTouchEnabled=true; // Initialise instance variables @@ -169,12 +169,6 @@ cc.Control = cc.LayerRGBA.extend({ return false; }, - onEnter:function () { - this._super(); - }, - onExit:function () { - this._super(); - }, registerWithTouchDispatcher:function () { cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this.getTouchPriority(), true); }, diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/GUI/CCControlExtension/CCControlButton.js index 6c41fc1a6c..79d8ce3038 100644 --- a/extensions/GUI/CCControlExtension/CCControlButton.js +++ b/extensions/GUI/CCControlExtension/CCControlButton.js @@ -48,7 +48,7 @@ cc.ControlButton = cc.Control.extend({ _marginH:0, ctor:function () { - this._super(); + cc.Control.prototype.ctor.call(this); this._preferredSize = new cc.Size(0, 0); this._labelAnchorPoint = new cc.Point(0, 0); @@ -309,11 +309,11 @@ cc.ControlButton = cc.Control.extend({ }, setEnabled:function (enabled) { - this._super(enabled); + cc.Control.prototype.setEnabled.call(this, enabled); this.needsLayout(); }, setSelected:function (enabled) { - this._super(enabled); + cc.Control.prototype.setSelected.call(this, enabled); this.needsLayout(); }, @@ -324,7 +324,7 @@ cc.ControlButton = cc.Control.extend({ else { this._state = cc.CONTROL_STATE_NORMAL; } - this._super(enabled); + cc.Control.prototype.setHighlighted.call(this, enabled); var action = this.getActionByTag(cc.CONTROL_ZOOM_ACTION_TAG); if (action) { this.stopAction(action); diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 052216834b..37d767ad11 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -302,7 +302,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ }, setContentSize: function (size) { - this._super(size); + cc.Node.prototype.setContentSize.call(this, size); this.m_positionsAreDirty = true; }, @@ -311,7 +311,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ this._updatePositions(); this.m_positionsAreDirty = false; } - this._super(); + cc.Node.prototype.visit.call(this); }, init: function () { diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index f222a6d9cb..04ef5034c4 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -601,12 +601,12 @@ cc.ScrollView = cc.Layer.extend({ if (this._container != child) { this._container.addChild(child, zOrder, tag); } else { - this._super(child, zOrder, tag); + cc.Layer.prototype.addChild.call(this, child, zOrder, tag); } }, setTouchEnabled:function (e) { - this._super(e); + cc.Layer.prototype.setTouchEnabled.call(this, e); if (!e) { this._dragging = false; this._touchMoved = false; diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index 0cc114dcd8..d86de079e7 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -120,7 +120,7 @@ cc.TableView = cc.ScrollView.extend({ _oldDirection:null, ctor:function () { - this._super(); + cc.ScrollView.prototype.ctor.call(this); this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE; }, From a861869ce5031f719c7c03506dca88311f88d24d Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Mon, 26 Aug 2013 17:19:09 +0800 Subject: [PATCH 059/141] added js loading image --- cocos2d/platform/jsloader.js | 29 ++++++++++++++++++++++++++--- template/cocos2d.js | 12 ++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index 33ca17c25b..d8546fd53d 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -38,7 +38,7 @@ 'platform/CCMacro.js', 'platform/CCFileUtils.js', 'platform/CCTypes.js', - 'platform/CCAccelerometer.js', + 'platform/CCAccelerometer.js', 'platform/zlib.min.js', 'platform/CCEGLView.js', 'platform/CCImage.js', @@ -248,6 +248,27 @@ } + var loadJsImg = document.getElementById("cocos2d_loadJsImg"); + if(!loadJsImg){ + loadJsImg = new Image(); + loadJsImg.src = "data:image/gif;base64,R0lGODlhEAAQALMNAD8/P7+/vyoqKlVVVX9/fxUVFUBAQGBgYMDAwC8vL5CQkP///wAAAP///wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAANACwAAAAAEAAQAAAEO5DJSau9OOvNex0IMnDIsiCkiW6g6BmKYlBFkhSUEgQKlQCARG6nEBwOgl+QApMdCIRD7YZ5RjlGpCUCACH5BAUAAA0ALAAAAgAOAA4AAAQ6kLGB0JA4M7QW0hrngRllkYyhKAYqKUGguAws0ypLS8JxCLQDgXAIDg+FRKIA6v0SAECCBpXSkstMBAAh+QQFAAANACwAAAAACgAQAAAEOJDJORAac6K1kDSKYmydpASBUl0mqmRfaGTCcQgwcxDEke+9XO2WkxQSiUIuAQAkls0n7JgsWq8RACH5BAUAAA0ALAAAAAAOAA4AAAQ6kMlplDIzTxWC0oxwHALnDQgySAdBHNWFLAvCukc215JIZihVIZEogDIJACBxnCSXTcmwGK1ar1hrBAAh+QQFAAANACwAAAAAEAAKAAAEN5DJKc4RM+tDyNFTkSQF5xmKYmQJACTVpQSBwrpJNteZSGYoFWjIGCAQA2IGsVgglBOmEyoxIiMAIfkEBQAADQAsAgAAAA4ADgAABDmQSVZSKjPPBEDSGucJxyGA1XUQxAFma/tOpDlnhqIYN6MEAUXvF+zldrMBAjHoIRYLhBMqvSmZkggAIfkEBQAADQAsBgAAAAoAEAAABDeQyUmrnSWlYhMASfeFVbZdjHAcgnUQxOHCcqWylKEohqUEAYVkgEAMfkEJYrFA6HhKJsJCNFoiACH5BAUAAA0ALAIAAgAOAA4AAAQ3kMlJq704611SKloCAEk4lln3DQgyUMJxCBKyLAh1EMRR3wiDQmHY9SQslyIQUMRmlmVTIyRaIgA7"; + + var canvasNode = document.getElementById(c.tag); + canvasNode.style.backgroundColor = "black"; + canvasNode.parentNode.appendChild(loadJsImg); + + var canvasStyle = getComputedStyle?getComputedStyle(canvasNode):canvasNode.currentStyle; + loadJsImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - loadJsImg.width)/2 + "px"; + loadJsImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - loadJsImg.height)/2 + "px"; + loadJsImg.style.position = "absolute"; + } + + var updateLoading = function(p){ + if(p>=1) { + loadJsImg.parentNode.removeChild(loadJsImg); + } + } + var loaded = 0; var que = engine.concat(c.appFiles); que.push('main.js'); @@ -263,8 +284,9 @@ f.onload = loadNext; d.body.appendChild(f); //TODO: code for updating progress bar - //p = s / (que.length - 1); } + var p = s / (que.length - 1); + updateLoading(p); }; loadNext(); } @@ -276,7 +298,8 @@ s.onload = function () { loaded++; //TODO: code for updating progress bar - //p = loaded / que.length; + var p = loaded / que.length; + updateLoading(p); }; d.body.appendChild(s); que[i] = s; diff --git a/template/cocos2d.js b/template/cocos2d.js index f657b9d7fc..b0d1b1c9ca 100644 --- a/template/cocos2d.js +++ b/template/cocos2d.js @@ -63,6 +63,18 @@ /*********Delete this section if you have packed all files into one*******/ if (c.SingleEngineFile && !c.engineDir) { s.src = c.SingleEngineFile; + + var loadJsImg = new Image(); + loadJsImg.src = "data:image/gif;base64,R0lGODlhEAAQALMNAD8/P7+/vyoqKlVVVX9/fxUVFUBAQGBgYMDAwC8vL5CQkP///wAAAP///wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFAAANACwAAAAAEAAQAAAEO5DJSau9OOvNex0IMnDIsiCkiW6g6BmKYlBFkhSUEgQKlQCARG6nEBwOgl+QApMdCIRD7YZ5RjlGpCUCACH5BAUAAA0ALAAAAgAOAA4AAAQ6kLGB0JA4M7QW0hrngRllkYyhKAYqKUGguAws0ypLS8JxCLQDgXAIDg+FRKIA6v0SAECCBpXSkstMBAAh+QQFAAANACwAAAAACgAQAAAEOJDJORAac6K1kDSKYmydpASBUl0mqmRfaGTCcQgwcxDEke+9XO2WkxQSiUIuAQAkls0n7JgsWq8RACH5BAUAAA0ALAAAAAAOAA4AAAQ6kMlplDIzTxWC0oxwHALnDQgySAdBHNWFLAvCukc215JIZihVIZEogDIJACBxnCSXTcmwGK1ar1hrBAAh+QQFAAANACwAAAAAEAAKAAAEN5DJKc4RM+tDyNFTkSQF5xmKYmQJACTVpQSBwrpJNteZSGYoFWjIGCAQA2IGsVgglBOmEyoxIiMAIfkEBQAADQAsAgAAAA4ADgAABDmQSVZSKjPPBEDSGucJxyGA1XUQxAFma/tOpDlnhqIYN6MEAUXvF+zldrMBAjHoIRYLhBMqvSmZkggAIfkEBQAADQAsBgAAAAoAEAAABDeQyUmrnSWlYhMASfeFVbZdjHAcgnUQxOHCcqWylKEohqUEAYVkgEAMfkEJYrFA6HhKJsJCNFoiACH5BAUAAA0ALAIAAgAOAA4AAAQ3kMlJq704611SKloCAEk4lln3DQgyUMJxCBKyLAh1EMRR3wiDQmHY9SQslyIQUMRmlmVTIyRaIgA7"; + + var canvasNode = document.getElementById(c.tag); + canvasNode.style.backgroundColor = "black"; + canvasNode.parentNode.appendChild(loadJsImg); + + var canvasStyle = getComputedStyle?getComputedStyle(canvasNode):canvasNode.currentStyle; + loadJsImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - loadJsImg.width)/2 + "px"; + loadJsImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - loadJsImg.height)/2 + "px"; + loadJsImg.style.position = "absolute"; } else if (c.engineDir && !c.SingleEngineFile) { s.src = c.engineDir + 'platform/jsloader.js'; From 76cd18e620f9a626bcff7106685d4ace3fa78af9 Mon Sep 17 00:00:00 2001 From: 06wj <06wj@163.com> Date: Mon, 26 Aug 2013 17:38:36 +0800 Subject: [PATCH 060/141] give loading image a id --- template/cocos2d.js | 1 + 1 file changed, 1 insertion(+) diff --git a/template/cocos2d.js b/template/cocos2d.js index b0d1b1c9ca..47358d580a 100644 --- a/template/cocos2d.js +++ b/template/cocos2d.js @@ -75,6 +75,7 @@ loadJsImg.style.left = canvasNode.offsetLeft + (parseFloat(canvasStyle.width) - loadJsImg.width)/2 + "px"; loadJsImg.style.top = canvasNode.offsetTop + (parseFloat(canvasStyle.height) - loadJsImg.height)/2 + "px"; loadJsImg.style.position = "absolute"; + loadJsImg.id = "cocos2d_loadJsImg"; } else if (c.engineDir && !c.SingleEngineFile) { s.src = c.engineDir + 'platform/jsloader.js'; From 1e0158010103d729eb8fe1f43a2ff8645781654b Mon Sep 17 00:00:00 2001 From: WanderWang Date: Mon, 26 Aug 2013 23:44:09 +0800 Subject: [PATCH 061/141] =?UTF-8?q?=E4=BF=AE=E5=A4=8DBrowserTypes=E6=AD=A3?= =?UTF-8?q?=E5=88=99=E8=A1=A8=E8=BE=BE=E5=BC=8F=E5=8C=B9=E9=85=8D=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E6=97=B6=E7=9A=84=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复BrowserTypes正则表达式匹配失败时的报错 --- cocos2d/platform/miniFramework.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/platform/miniFramework.js b/cocos2d/platform/miniFramework.js index ba8eb80354..dea0805b08 100644 --- a/cocos2d/platform/miniFramework.js +++ b/cocos2d/platform/miniFramework.js @@ -59,7 +59,7 @@ cc.Browser = {}; cc.Browser.isMobile = (cc.Browser.ua.indexOf('mobile') != -1 || cc.Browser.ua.indexOf('android') != -1); cc.Browser.type = (function () { var browserTypes = cc.Browser.ua.match(/micromessenger|qqbrowser|mqqbrowser|ucbrowser|360browser|baidubrowser|maxthon|ie|opera|firefox/) || cc.Browser.ua.match(/chrome|safari/); - if (browserTypes.length > 0) { + if (browserTypes && browserTypes.length > 0) { var el = browserTypes[0]; if (el == 'micromessenger') { return 'wechat'; From d86d249fef223e6ba86cefb9328f90e3261f4ed2 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 27 Aug 2013 09:58:31 +0800 Subject: [PATCH 062/141] fixed #2506: Optimize performance for ContolButton, ScrollView and TableView etc --- cocos2d/CCLoader.js | 2 +- cocos2d/actions/CCAction.js | 2 +- cocos2d/base_nodes/CCNode.js | 2 +- cocos2d/cocoa/CCAffineTransform.js | 45 +- cocos2d/cocoa/CCGeometry.js | 6 + cocos2d/label_nodes/CCLabelAtlas.js | 2 +- .../CCTransition.js | 29 +- .../CCTransitionProgress.js | 14 +- cocos2d/menu_nodes/CCMenu.js | 54 ++- cocos2d/menu_nodes/CCMenuItem.js | 2 +- cocos2d/particle_nodes/CCParticleExamples.js | 22 +- cocos2d/particle_nodes/CCParticleSystem.js | 2 +- cocos2d/sprite_nodes/CCSprite.js | 4 + .../tileMap_parallax_nodes/CCParallaxNode.js | 2 +- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 4 +- extensions/CCBReader/CCBReader.js | 8 +- extensions/CCEditBox.js | 4 +- .../GUI/CCControlExtension/CCControl.js | 142 +++---- .../GUI/CCControlExtension/CCControlButton.js | 400 +++++++++--------- .../CCControlColourPicker.js | 2 +- .../CCControlExtension/CCControlHuePicker.js | 2 +- .../CCControlPotentiometer.js | 2 +- .../CCControlSaturationBrightnessPicker.js | 2 +- .../GUI/CCControlExtension/CCControlSlider.js | 2 +- .../CCControlExtension/CCControlStepper.js | 3 +- .../GUI/CCControlExtension/CCControlSwitch.js | 2 +- .../GUI/CCControlExtension/CCControlUtils.js | 1 - .../GUI/CCControlExtension/CCScale9Sprite.js | 49 +-- extensions/GUI/CCScrollView/CCScrollView.js | 122 +++--- extensions/GUI/CCScrollView/CCSorting.js | 15 +- extensions/GUI/CCScrollView/CCTableView.js | 84 +++- 31 files changed, 544 insertions(+), 488 deletions(-) diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index bcdad56b23..6bfa53e296 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -423,7 +423,7 @@ cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{ // bg this._bgLayer = cc.LayerColor.create(cc.c4(32, 32, 32, 255)); - this._bgLayer.setPosition(cc.p(0, 0)); + this._bgLayer.setPosition(0, 0); this.addChild(this._bgLayer, 0); //loading percent diff --git a/cocos2d/actions/CCAction.js b/cocos2d/actions/CCAction.js index 82890d79b0..34fbec375c 100644 --- a/cocos2d/actions/CCAction.js +++ b/cocos2d/actions/CCAction.js @@ -462,7 +462,7 @@ cc.Follow = cc.Action.extend(/** @lends cc.Follow# */{ this._followedNode = followedNode; this._worldRect = rect; - this._boundarySet = !cc.rectEqualToRect(rect, cc.RectZero()); + this._boundarySet = !cc._rectEqualToZero(rect); this._boundaryFullyCovered = false; diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index e9dfe0c8d4..1c0bd68ebd 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -2758,7 +2758,7 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ */ getBoundingBox:function () { var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); - return cc.RectApplyAffineTransform(rect, this.nodeToParentTransform()); + return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform()); }, /** diff --git a/cocos2d/cocoa/CCAffineTransform.js b/cocos2d/cocoa/CCAffineTransform.js index fbf7f30a9d..2437f5ca18 100644 --- a/cocos2d/cocoa/CCAffineTransform.js +++ b/cocos2d/cocoa/CCAffineTransform.js @@ -76,6 +76,11 @@ cc.PointApplyAffineTransform = function (point, t) { return {x: t.a * point.x + t.c * point.y + t.tx, y: t.b * point.x + t.d * point.y + t.ty}; }; +cc._PointApplyAffineTransform = function (x, y, t) { + return {x: t.a * x + t.c * y + t.tx, + y: t.b * x + t.d * y + t.ty}; +}; + cc.__SizeApplyAffineTransform = function (size, t) { return {width: t.a * size.width + t.c * size.height, height: t.b * size.width + t.d * size.height}; }; @@ -122,10 +127,10 @@ cc.RectApplyAffineTransform = function (rect, anAffineTransform) { var right = cc.rectGetMaxX(rect); var bottom = cc.rectGetMaxY(rect); - var topLeft = cc.PointApplyAffineTransform(cc.p(left, top), anAffineTransform); - var topRight = cc.PointApplyAffineTransform(cc.p(right, top), anAffineTransform); - var bottomLeft = cc.PointApplyAffineTransform(cc.p(left, bottom), anAffineTransform); - var bottomRight = cc.PointApplyAffineTransform(cc.p(right, bottom), anAffineTransform); + var topLeft = cc._PointApplyAffineTransform(left, top, anAffineTransform); + var topRight = cc._PointApplyAffineTransform(right, top, anAffineTransform); + var bottomLeft = cc._PointApplyAffineTransform(left, bottom, anAffineTransform); + var bottomRight = cc._PointApplyAffineTransform(right, bottom, anAffineTransform); var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); @@ -135,6 +140,29 @@ cc.RectApplyAffineTransform = function (rect, anAffineTransform) { return cc.rect(minX, minY, (maxX - minX), (maxY - minY)); }; +cc._RectApplyAffineTransformIn = function(rect, anAffineTransform){ + var top = cc.rectGetMinY(rect); + var left = cc.rectGetMinX(rect); + var right = cc.rectGetMaxX(rect); + var bottom = cc.rectGetMaxY(rect); + + var topLeft = cc._PointApplyAffineTransform(left, top, anAffineTransform); + var topRight = cc._PointApplyAffineTransform(right, top, anAffineTransform); + var bottomLeft = cc._PointApplyAffineTransform(left, bottom, anAffineTransform); + var bottomRight = cc._PointApplyAffineTransform(right, bottom, anAffineTransform); + + var minX = Math.min(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); + var maxX = Math.max(topLeft.x, topRight.x, bottomLeft.x, bottomRight.x); + var minY = Math.min(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); + var maxY = Math.max(topLeft.y, topRight.y, bottomLeft.y, bottomRight.y); + + rect.x = minX; + rect.y = minY; + rect.width = maxX - minX; + rect.height = maxY - minY; + return rect; +}; + /** * @function * @param {cc.AffineTransform} t @@ -144,7 +172,14 @@ cc.RectApplyAffineTransform = function (rect, anAffineTransform) { * Constructor */ cc.AffineTransformTranslate = function (t, tx, ty) { - return {a: t.a, b: t.b, c: t.c, d: t.d, tx: t.tx + t.a * tx + t.c * ty, ty: t.ty + t.b * tx + t.d * ty}; + return { + a: t.a, + b: t.b, + c: t.c, + d: t.d, + tx: t.tx + t.a * tx + t.c * ty, + ty: t.ty + t.b * tx + t.d * ty + }; }; /** diff --git a/cocos2d/cocoa/CCGeometry.js b/cocos2d/cocoa/CCGeometry.js index 4944efb269..6cca20be8a 100644 --- a/cocos2d/cocoa/CCGeometry.js +++ b/cocos2d/cocoa/CCGeometry.js @@ -270,6 +270,12 @@ cc.rectEqualToRect = function (rect1, rect2) { (cc.sizeEqualToSize(rect1.size, rect2.size))); }; +cc._rectEqualToZero = function(rect){ + if(!rect) + return false; + return (rect.x === 0) && (rect.y === 0) && (rect.width === 0) && (rect.height === 0); +}; + /** * @function * @param {cc.Rect} rect1 diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index b12b1888e2..12dd596cdc 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -148,7 +148,7 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ fontChar.setOpacity(this._opacity); } } - fontChar.setPosition(cc.p(i * locItemWidth + locItemWidth / 2, locItemHeight / 2)); + fontChar.setPosition(i * locItemWidth + locItemWidth / 2, locItemHeight / 2); } }, diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 24ea00d9d9..96b5e330c6 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -165,7 +165,7 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ if (this.init()) { this._duration = t; this.setAnchorPoint(cc.p(0, 0)); - this.setPosition(cc.p(0, 0)); + this.setPosition(0, 0); // retain this._inScene = scene; this._outScene = cc.Director.getInstance().getRunningScene(); @@ -190,14 +190,14 @@ cc.TransitionScene = cc.Scene.extend(/** @lends cc.TransitionScene# */{ finish:function () { // clean up this._inScene.setVisible(true); - this._inScene.setPosition(cc.p(0, 0)); + this._inScene.setPosition(0, 0); this._inScene.setScale(1.0); this._inScene.setRotation(0.0); if(cc.renderContextType === cc.WEBGL) this._inScene.getCamera().restore(); this._outScene.setVisible(false); - this._outScene.setPosition(cc.p(0, 0)); + this._outScene.setPosition(0, 0); this._outScene.setScale(1.0); this._outScene.setRotation(0.0); if(cc.renderContextType === cc.WEBGL) @@ -339,7 +339,7 @@ cc.TransitionJumpZoom = cc.TransitionScene.extend(/** @lends cc.TransitionJumpZo var winSize = cc.Director.getInstance().getWinSize(); this._inScene.setScale(0.5); - this._inScene.setPosition(cc.p(winSize.width, 0)); + this._inScene.setPosition(winSize.width, 0); this._inScene.setAnchorPoint(cc.p(0.5, 0.5)); this._outScene.setAnchorPoint(cc.p(0.5, 0.5)); @@ -394,7 +394,7 @@ cc.TransitionMoveInL = cc.TransitionScene.extend(/** @lends cc.TransitionMoveInL * initializes the scenes */ initScenes:function () { - this._inScene.setPosition(cc.p(-cc.Director.getInstance().getWinSize().width, 0)); + this._inScene.setPosition(-cc.Director.getInstance().getWinSize().width, 0); }, /** @@ -437,12 +437,11 @@ cc.TransitionMoveInL.create = function (t, scene) { * @extends cc.TransitionMoveInL */ cc.TransitionMoveInR = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveInR# */{ - /** * Init */ initScenes:function () { - this._inScene.setPosition(cc.p(cc.Director.getInstance().getWinSize().width, 0)); + this._inScene.setPosition(cc.Director.getInstance().getWinSize().width, 0); } }); @@ -474,7 +473,7 @@ cc.TransitionMoveInT = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveI * init */ initScenes:function () { - this._inScene.setPosition(cc.p(0, cc.Director.getInstance().getWinSize().height)); + this._inScene.setPosition(0, cc.Director.getInstance().getWinSize().height); } }); @@ -506,7 +505,7 @@ cc.TransitionMoveInB = cc.TransitionMoveInL.extend(/** @lends cc.TransitionMoveI * init */ initScenes:function () { - this._inScene.setPosition(cc.p(0, -cc.Director.getInstance().getWinSize().height)); + this._inScene.setPosition(0, -cc.Director.getInstance().getWinSize().height); } }); @@ -573,7 +572,7 @@ cc.TransitionSlideInL = cc.TransitionScene.extend(/** @lends cc.TransitionSlideI * initializes the scenes */ initScenes:function () { - this._inScene.setPosition(cc.p(-(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR), 0)); + this._inScene.setPosition(-(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR), 0); }, /** * returns the action that will be performed by the incomming and outgoing scene @@ -622,7 +621,7 @@ cc.TransitionSlideInR = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSli * initializes the scenes */ initScenes:function () { - this._inScene.setPosition(cc.p(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR, 0)); + this._inScene.setPosition(cc.Director.getInstance().getWinSize().width - cc.ADJUST_FACTOR, 0); }, /** * returns the action that will be performed by the incomming and outgoing scene @@ -664,7 +663,7 @@ cc.TransitionSlideInB = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSli * initializes the scenes */ initScenes:function () { - this._inScene.setPosition(cc.p(0, cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR)); + this._inScene.setPosition(0, cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR); }, /** @@ -707,7 +706,7 @@ cc.TransitionSlideInT = cc.TransitionSlideInL.extend(/** @lends cc.TransitionSli * initializes the scenes */ initScenes:function () { - this._inScene.setPosition(cc.p(0, -(cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR))); + this._inScene.setPosition(0, -(cc.Director.getInstance().getWinSize().height - cc.ADJUST_FACTOR)); }, /** @@ -1328,7 +1327,7 @@ cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCross return; inTexture.getSprite().setAnchorPoint(cc.p(0.5, 0.5)); - inTexture.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + inTexture.setPosition(winSize.width / 2, winSize.height / 2); inTexture.setAnchorPoint(cc.p(0.5, 0.5)); // render inScene to its texturebuffer @@ -1339,7 +1338,7 @@ cc.TransitionCrossFade = cc.TransitionScene.extend(/** @lends cc.TransitionCross // create the second render texture for outScene var outTexture = cc.RenderTexture.create(winSize.width, winSize.height); outTexture.getSprite().setAnchorPoint(cc.p(0.5, 0.5)); - outTexture.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + outTexture.setPosition(winSize.width / 2, winSize.height / 2); outTexture.setAnchorPoint(cc.p(0.5, 0.5)); // render outScene to its texturebuffer diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js index 9d5b6ba404..c75fe1c65e 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js @@ -55,7 +55,7 @@ cc.TransitionProgress = cc.TransitionScene.extend(/** @lends cc.TransitionProgre // create the second render texture for outScene var texture = cc.RenderTexture.create(winSize.width, winSize.height); texture.getSprite().setAnchorPoint(cc.p(0.5, 0.5)); - texture.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + texture.setPosition(winSize.width / 2, winSize.height / 2); texture.setAnchorPoint(cc.p(0.5, 0.5)); // render outScene to its texturebuffer @@ -142,7 +142,7 @@ cc.TransitionProgressRadialCCW = cc.TransitionProgress.extend(/** @lends cc.Tran // Return the radial type that we want to use pNode.setReverseDirection(false); pNode.setPercentage(100); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; @@ -184,7 +184,7 @@ cc.TransitionProgressRadialCW = cc.TransitionProgress.extend(/** @lends cc.Trans // Return the radial type that we want to use pNode.setReverseDirection(true); pNode.setPercentage(100); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; @@ -227,7 +227,7 @@ cc.TransitionProgressHorizontal = cc.TransitionProgress.extend(/** @lends cc.Tra pNode.setBarChangeRate(cc.p(1, 0)); pNode.setPercentage(100); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; @@ -269,7 +269,7 @@ cc.TransitionProgressVertical = cc.TransitionProgress.extend(/** @lends cc.Trans pNode.setBarChangeRate(cc.p(0, 1)); pNode.setPercentage(100); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; @@ -310,7 +310,7 @@ cc.TransitionProgressInOut = cc.TransitionProgress.extend(/** @lends cc.Transiti pNode.setBarChangeRate(cc.p(1, 1)); pNode.setPercentage(0); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; @@ -359,7 +359,7 @@ cc.TransitionProgressOutIn = cc.TransitionProgress.extend(/** @lends cc.Transiti pNode.setBarChangeRate(cc.p(1, 1)); pNode.setPercentage(100); - pNode.setPosition(cc.p(size.width / 2, size.height / 2)); + pNode.setPosition(size.width / 2, size.height / 2); pNode.setAnchorPoint(cc.p(0.5, 0.5)); return pNode; diff --git a/cocos2d/menu_nodes/CCMenu.js b/cocos2d/menu_nodes/CCMenu.js index 8f90bd77a9..407df91346 100644 --- a/cocos2d/menu_nodes/CCMenu.js +++ b/cocos2d/menu_nodes/CCMenu.js @@ -154,7 +154,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ this.ignoreAnchorPointForPosition(true); this.setAnchorPoint(cc.p(0.5, 0.5)); this.setContentSize(winSize); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); if (arrayOfItems) { for (var i = 0; i < arrayOfItems.length; i++) @@ -204,7 +204,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var y = height / 2.0; if (this._children && this._children.length > 0) { for (i = 0; i < this._children.length; i++) { - this._children[i].setPosition(cc.p(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2)); + this._children[i].setPosition(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2); y -= this._children[i].getContentSize().height * this._children[i].getScaleY() + padding; } } @@ -232,7 +232,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var x = -width / 2.0; if (this._children && this._children.length > 0) { for (i = 0; i < this._children.length; i++) { - this._children[i].setPosition(cc.p(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2, 0)); + this._children[i].setPosition(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2, 0); x += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding; } } @@ -258,16 +258,17 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var row = 0; var rowHeight = 0; var columnsOccupied = 0; - var rowColumns; - if (this._children && this._children.length > 0) { - for (i = 0; i < this._children.length; i++) { + var rowColumns, tmp, len; + var locChildren = this._children; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) { cc.Assert(row < rows.length, ""); rowColumns = rows[row]; // can not have zero columns on a row cc.Assert(rowColumns, ""); - var tmp = this._children[i].getContentSize().height; + tmp = locChildren[i].getContentSize().height; rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp); ++columnsOccupied; @@ -291,27 +292,24 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var x = 0.0; var y = (height / 2); - if (this._children && this._children.length > 0) { - for (i = 0; i < this._children.length; i++) { - var child = this._children[i]; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) { + var child = locChildren[i]; if (rowColumns == 0) { rowColumns = rows[row]; w = winSize.width / (1 + rowColumns); x = w; } - var tmp = child.getContentSize().height; + tmp = child.getContentSize().height; rowHeight = ((rowHeight >= tmp || isNaN(tmp)) ? rowHeight : tmp); - - child.setPosition(cc.p(x - winSize.width / 2, - y - child.getContentSize().height / 2)); + child.setPosition(x - winSize.width / 2, y - tmp / 2); x += w; ++columnsOccupied; if (columnsOccupied >= rowColumns) { y -= rowHeight + 5; - columnsOccupied = 0; rowColumns = 0; rowHeight = 0; @@ -331,8 +329,8 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ alignItemsInRows:function (/*Multiple arguments*/) { if((arguments.length > 0) && (arguments[arguments.length-1] == null)) cc.log("parameters should not be ending with null in Javascript"); - var columns = []; - for (var i = 0; i < arguments.length; i++) { + var columns = [], i; + for (i = 0; i < arguments.length; i++) { columns.push(arguments[i]); } var columnWidths = []; @@ -343,11 +341,12 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var column = 0; var columnWidth = 0; var rowsOccupied = 0; - var columnRows; + var columnRows, child, len, tmp; - if (this._children && this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; + var locChildren = this._children; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) { + child = locChildren[i]; // check if too many menu items for the amount of rows/columns cc.Assert(column < columns.length, ""); @@ -356,7 +355,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ cc.Assert(columnRows, ""); // columnWidth = fmaxf(columnWidth, [item contentSize].width); - var tmp = child.getContentSize().width; + tmp = child.getContentSize().width; columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp); columnHeight += (child.getContentSize().height + 5); @@ -385,20 +384,19 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var x = -width / 2; var y = 0.0; - if (this._children && this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - var child = this._children[i]; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) { + child = locChildren[i]; if (columnRows == 0) { columnRows = columns[column]; y = columnHeights[column]; } // columnWidth = fmaxf(columnWidth, [item contentSize].width); - var tmp = child.getContentSize().width; + tmp = child.getContentSize().width; columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp); - child.setPosition(cc.p(x + columnWidths[column] / 2, - y - winSize.height / 2)); + child.setPosition(x + columnWidths[column] / 2, y - winSize.height / 2); y -= child.getContentSize().height + 10; ++rowsOccupied; diff --git a/cocos2d/menu_nodes/CCMenuItem.js b/cocos2d/menu_nodes/CCMenuItem.js index ea1ff9fc7a..8985d195ef 100644 --- a/cocos2d/menu_nodes/CCMenuItem.js +++ b/cocos2d/menu_nodes/CCMenuItem.js @@ -1060,7 +1060,7 @@ cc.MenuItemToggle = cc.MenuItem.extend(/** @lends cc.MenuItemToggle# */{ this.addChild(item, 0, cc.CURRENT_ITEM); var s = item.getContentSize(); this.setContentSize(s); - item.setPosition(cc.p(s.width / 2, s.height / 2)); + item.setPosition(s.width / 2, s.height / 2); } }, diff --git a/cocos2d/particle_nodes/CCParticleExamples.js b/cocos2d/particle_nodes/CCParticleExamples.js index 4d33780e8e..27d99061a0 100644 --- a/cocos2d/particle_nodes/CCParticleExamples.js +++ b/cocos2d/particle_nodes/CCParticleExamples.js @@ -71,7 +71,7 @@ cc.ParticleFire = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFire# */{ // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, 60)); + this.setPosition(winSize.width / 2, 60); this._posVar = cc.p(40, 20); // life of particles @@ -171,7 +171,7 @@ cc.ParticleFireworks = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFirewo // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); // angle this._angle = 90; @@ -280,7 +280,7 @@ cc.ParticleSun = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSun# */{ // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this.setPosVar(cc.PointZero()); // life of particles @@ -387,7 +387,7 @@ cc.ParticleGalaxy = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleGalaxy# * // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this._posVar = cc.PointZero(); // life of particles @@ -493,7 +493,7 @@ cc.ParticleFlower = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFlower# * // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this._posVar = cc.PointZero(); // life of particles @@ -601,7 +601,7 @@ cc.ParticleMeteor = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleMeteor# * // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this._posVar = cc.PointZero(); // life of particles @@ -708,7 +708,7 @@ cc.ParticleSpiral = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSpiral# * // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this._posVar = cc.PointZero(); // life of particles @@ -815,7 +815,7 @@ cc.ParticleExplosion = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleExplos // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height / 2)); + this.setPosition(winSize.width / 2, winSize.height / 2); this._posVar = cc.PointZero(); // life of particles @@ -919,7 +919,7 @@ cc.ParticleSmoke = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSmoke# */{ // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, 0)); + this.setPosition(winSize.width / 2, 0); this._posVar = cc.p(20, 0); // life of particles @@ -1022,7 +1022,7 @@ cc.ParticleSnow = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSnow# */{ // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height + 10)); + this.setPosition(winSize.width / 2, winSize.height + 10); this._posVar = cc.p(winSize.width / 2, 0); // angle @@ -1134,7 +1134,7 @@ cc.ParticleRain = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleRain# */{ // emitter position var winSize = cc.Director.getInstance().getWinSize(); - this.setPosition(cc.p(winSize.width / 2, winSize.height)); + this.setPosition(winSize.width / 2, winSize.height); this._posVar = cc.p(winSize.width / 2, 0); // life of particles diff --git a/cocos2d/particle_nodes/CCParticleSystem.js b/cocos2d/particle_nodes/CCParticleSystem.js index 7a2ec5c0b6..05834c754b 100644 --- a/cocos2d/particle_nodes/CCParticleSystem.js +++ b/cocos2d/particle_nodes/CCParticleSystem.js @@ -1340,7 +1340,7 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ // position var x = parseFloat(locValueForKey("sourcePositionx", dictionary)); var y = parseFloat(locValueForKey("sourcePositiony", dictionary)); - this.setPosition(cc.p(x, y)); + this.setPosition(x, y); this._posVar.x = parseFloat(locValueForKey("sourcePositionVariancex", dictionary)); this._posVar.y = parseFloat(locValueForKey("sourcePositionVariancey", dictionary)); diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index f3fdcdbba0..78b022bab7 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1052,6 +1052,8 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ if (!locRect) { locRect = cc.rect(0, 0, 0, 0); locRect.size = sender.getContentSize(); + } else if(cc._rectEqualToZero(locRect)){ + locRect.size = sender.getContentSize(); } this._originalTexture = sender; @@ -2180,6 +2182,8 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ if (!locRect) { locRect = cc.rect(0, 0, 0, 0); locRect.size = sender.getContentSize(); + } else if(cc._rectEqualToZero(locRect)){ + locRect.size = sender.getContentSize(); } this.setTexture(sender); diff --git a/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js b/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js index c5c29f91fa..9d512e30b5 100644 --- a/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js +++ b/cocos2d/tileMap_parallax_nodes/CCParallaxNode.js @@ -202,7 +202,7 @@ cc.ParallaxNode = cc.Node.extend(/** @lends cc.ParallaxNode# */{ var point = locParallaxArray[i]; var x = -pos.x + pos.x * point.getRatio().x + point.getOffset().x; var y = -pos.y + pos.y * point.getRatio().y + point.getOffset().y; - point.getChild().setPosition(cc.p(x, y)); + point.getChild().setPosition(x, y); } this._lastPosition = pos; } diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index 7211b3e37c..b139fad240 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -760,8 +760,8 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) { // put the anchor in the middle for ease of rotation. sprite.setAnchorPoint(cc.p(0.5, 0.5)); - sprite.setPosition(cc.p(this.getPositionAt(pos).x + sprite.getContentSize().height / 2, - this.getPositionAt(pos).y + sprite.getContentSize().width / 2)); + sprite.setPosition(this.getPositionAt(pos).x + sprite.getContentSize().height / 2, + this.getPositionAt(pos).y + sprite.getContentSize().width / 2); var flag = (gid & (cc.TMX_TILE_HORIZONTAL_FLAG | cc.TMX_TILE_VERTICAL_FLAG) >>> 0) >>> 0; // handle the 4 diagonally flipped states. diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index d2fb41301b..d0ceb994e8 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -227,7 +227,7 @@ cc.BuilderReader = cc.Class.extend({ return this.readNodeGraphFromData(data, owner, parentSize, animationManager); }, - readNodeGraphFromData:function (data, owner, parentSize, animationManager) { + readNodeGraphFromData:function (data, owner, parentSize) { this.initWithData(data, owner); this._actionManager.setRootContainerSize(parentSize); this._actionManager.setOwner(owner); @@ -256,12 +256,6 @@ cc.BuilderReader = cc.Class.extend({ } } - // Return action manager by reference - //if (ppAnimationManager) - //{ - // *ppAnimationManager = mActionManager; - //} - return nodeGraph; }, diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index e738d17aba..176181e246 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -412,11 +412,11 @@ cc.EditBox = cc.ControlButton.extend({ */ initWithSizeAndBackgroundSprite: function (size, normal9SpriteBg) { if (this.initWithBackgroundSprite(normal9SpriteBg)) { - this._domInputSprite.setPosition(cc.p(3, 3)); + this._domInputSprite.setPosition(3, 3); this.setZoomOnTouchDown(false); this.setPreferredSize(size); - this.setPosition(cc.p(0, 0)); + this.setPosition(0, 0); this._addTargetWithActionForControlEvent(this, this.touchDownAction, cc.CONTROL_EVENT_TOUCH_UP_INSIDE); return true; } diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/GUI/CCControlExtension/CCControl.js index c3a7dc14e2..14836390d0 100644 --- a/extensions/GUI/CCControlExtension/CCControl.js +++ b/extensions/GUI/CCControlExtension/CCControl.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * Copyright 2011 Yannick Loriot. @@ -69,11 +69,10 @@ cc.Control = cc.LayerRGBA.extend({ this._isOpacityModifyRGB = opacityModifyRGB; var children = this.getChildren(); - for (var i = 0; i < children.length; i++) { + for (var i = 0, len = children.length; i < len; i++) { var selNode = children[i]; - if (selNode && selNode.RGBAProtocol) { + if (selNode && selNode.RGBAProtocol) selNode.setOpacityModifyRGB(opacityModifyRGB); - } } }, @@ -87,7 +86,7 @@ cc.Control = cc.LayerRGBA.extend({ _selected:false, _highlighted:false, - _dispatchTable:{}, + _dispatchTable:null, /** * Tells whether the control is enabled @@ -95,11 +94,7 @@ cc.Control = cc.LayerRGBA.extend({ */ setEnabled:function (enabled) { this._enabled = enabled; - if (this._enabled) { - this._state = cc.CONTROL_STATE_NORMAL; - } else { - this._state = cc.CONTROL_STATE_DISABLED; - } + this._state = enabled ? cc.CONTROL_STATE_NORMAL:cc.CONTROL_STATE_DISABLED; this.needsLayout(); }, @@ -134,9 +129,8 @@ cc.Control = cc.LayerRGBA.extend({ hasVisibleParents:function () { var parent = this.getParent(); for (var c = parent; c != null; c = c.getParent()) { - if (!c.isVisible()) { + if (!c.isVisible()) return false; - } } return true; }, @@ -161,7 +155,7 @@ cc.Control = cc.LayerRGBA.extend({ this._defaultTouchPriority = 1; this.setTouchPriority(1); // Initialise the tables - this._dispatchTable = {}; + //this._dispatchTable = {}; //dispatchTable.autorelease(); // dispatchTable_ = [[NSMutableDictionary alloc] initWithCapacity:1]; return true; @@ -176,17 +170,17 @@ cc.Control = cc.LayerRGBA.extend({ /** * Sends action messages for the given control events. * which action messages are sent. See "CCControlEvent" for bitmask constants. - * @param controlEvents A bitmask whose set flags specify the control events for + * @param {Number} controlEvents A bitmask whose set flags specify the control events for */ sendActionsForControlEvents:function (controlEvents) { // For each control events - for (var i = 0; i < cc.CONTROL_EVENT_TOTAL_NUMBER; i++) { + for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) { // If the given controlEvents bitmask contains the curent event if ((controlEvents & (1 << i))) { // Call invocations // var invocationList = this._dispatchListforControlEvent(1 << i); - for (var j = 0; j < invocationList.length; j++) { + for (var j = 0, inLen = invocationList.length; j < inLen; j++) { invocationList[j].invoke(this); } } @@ -194,69 +188,57 @@ cc.Control = cc.LayerRGBA.extend({ }, /** - * Adds a target and action for a particular event (or events) to an internal - * dispatch table. - * The action message may optionnaly include the sender and the event as - * parameters, in that order. + *

+ * Adds a target and action for a particular event (or events) to an internal
+ * dispatch table.
+ * The action message may optionally include the sender and the event as
+ * parameters, in that order.
* When you call this method, target is not retained. - * - * @param target The target object梩hat is, the object to which the action - * message is sent. It cannot be nil. The target is not retained. - * @param action A selector identifying an action message. It cannot be NULL. - * @param controlEvents A bitmask specifying the control events for which the - * action message is sent. See "CCControlEvent" for bitmask constants. + *

+ * @param {Object} target The target object that is, the object to which the action message is sent. It cannot be nil. The target is not retained. + * @param {function} action A selector identifying an action message. It cannot be NULL. + * @param {Number} controlEvents A bitmask specifying the control events for which the action message is sent. See "CCControlEvent" for bitmask constants. */ addTargetWithActionForControlEvents:function (target, action, controlEvents) { // For each control events - for (var i = 0; i < cc.CONTROL_EVENT_TOTAL_NUMBER; i++) { - // If the given controlEvents bitmask contains the curent event - if ((controlEvents & (1 << i))) { + for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) { + // If the given controlEvents bit mask contains the current event + if ((controlEvents & (1 << i))) this._addTargetWithActionForControlEvent(target, action, 1 << i); - } } }, /** - * Removes a target and action for a particular event (or events) from an - * internal dispatch table. + * Removes a target and action for a particular event (or events) from an internal dispatch table. * - * @param target The target object梩hat is, the object to which the action - * message is sent. Pass nil to remove all targets paired with action and the - * specified control events. - * @param action A selector identifying an action message. Pass NULL to remove - * all action messages paired with target. - * @param controlEvents A bitmask specifying the control events associated with - * target and action. See "CCControlEvent" for bitmask constants. + * @param {Object} target The target object that is, the object to which the action message is sent. Pass nil to remove all targets paired with action and the specified control events. + * @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target. + * @param {Number} controlEvents A bitmask specifying the control events associated with target and action. See "CCControlEvent" for bitmask constants. */ removeTargetWithActionForControlEvents:function (target, action, controlEvents) { // For each control events - for (var i = 0; i < cc.CONTROL_EVENT_TOTAL_NUMBER; i++) { - // If the given controlEvents bitmask contains the curent event - if ((controlEvents & (1 << i))) { + for (var i = 0, len = cc.CONTROL_EVENT_TOTAL_NUMBER; i < len; i++) { + // If the given controlEvents bitmask contains the current event + if ((controlEvents & (1 << i))) this.removeTargetWithActionForControlEvent(target, action, 1 << i); - } } }, /** * Returns a point corresponding to the touh location converted into the * control space coordinates. - * @param touch A CCTouch object that represents a touch. + * @param {cc.Touch} touch A CCTouch object that represents a touch. */ getTouchLocation:function (touch) { var touchLocation = touch.getLocation(); // Get the touch position - touchLocation = this.convertToNodeSpace(touchLocation); // Convert to the node space of this class - - return touchLocation; + return this.convertToNodeSpace(touchLocation); // Convert to the node space of this class }, /** - * Returns a boolean value that indicates whether a touch is inside the bounds - * of the receiver. The given touch must be relative to the world. + * Returns a boolean value that indicates whether a touch is inside the bounds of the receiver. The given touch must be relative to the world. * - * @param touch A CCTouch object that represents a touch. - * - * @return YES whether a touch is inside the receiver抯 rect. + * @param {cc.Touch} touch A cc.Touch object that represents a touch. + * @return {Boolean} YES whether a touch is inside the receiver's rect. */ isTouchInside:function (touch) { var touchLocation = touch.getLocation(); // Get the touch position @@ -265,51 +247,43 @@ cc.Control = cc.LayerRGBA.extend({ }, /** - * Returns an CCInvocation object able to construct messages using a given - * target-action pair. (The invocation may optionnaly include the sender and + *

+ * Returns an cc.Invocation object able to construct messages using a given
+ * target-action pair. (The invocation may optionally include the sender and
* the event as parameters, in that order) + *

+ * @param {Object} target The target object. + * @param {function} action A selector identifying an action message. + * @param {Number} controlEvent A control events for which the action message is sent. See "CCControlEvent" for constants. * - * @param target The target object. - * @param action A selector identifying an action message. - * @param controlEvent A control events for which the action message is sent. - * See "CCControlEvent" for constants. - * - * @return an CCInvocation object able to construct messages using a given - * target-action pair. + * @return {cc.Invocation} an CCInvocation object able to construct messages using a given target-action pair. */ _invocationWithTargetAndActionForControlEvent:function (target, action, controlEvent) { + return null; }, /** - * Returns the CCInvocation list for the given control event. If the list does - * not exist, it'll create an empty array before returning it. - * - * @param controlEvent A control events for which the action message is sent. - * See "CCControlEvent" for constants. + * Returns the cc.Invocation list for the given control event. If the list does not exist, it'll create an empty array before returning it. * - * @return the CCInvocation list for the given control event. + * @param {Number} controlEvent A control events for which the action message is sent. See "CCControlEvent" for constants. + * @return {cc.Invocation} the cc.Invocation list for the given control event. */ _dispatchListforControlEvent:function (controlEvent) { controlEvent = controlEvent.toString(); - if (this._dispatchTable.hasOwnProperty(controlEvent)) - return this._dispatchTable[controlEvent]; - // If the invocation list does not exist for the dispatch table, we create it - - var invocationList = []; - this._dispatchTable[controlEvent] = invocationList; - - return invocationList; + if (!this._dispatchTable.hasOwnProperty(controlEvent)) + this._dispatchTable[controlEvent] = []; + return this._dispatchTable[controlEvent]; }, /** * Adds a target and action for a particular event to an internal dispatch * table. - * The action message may optionnaly include the sender and the event as + * The action message may optionally include the sender and the event as * parameters, in that order. * When you call this method, target is not retained. * - * @param target The target object梩hat is, the object to which the action + * @param target The target object that is, the object to which the action * message is sent. It cannot be nil. The target is not retained. * @param action A selector identifying an action message. It cannot be NULL. * @param controlEvent A control event for which the action message is sent. @@ -325,16 +299,11 @@ cc.Control = cc.LayerRGBA.extend({ }, /** - * Removes a target and action for a particular event from an internal dispatch - * table. + * Removes a target and action for a particular event from an internal dispatch table. * - * @param target The target object梩hat is, the object to which the action - * message is sent. Pass nil to remove all targets paired with action and the - * specified control events. - * @param action A selector identifying an action message. Pass NULL to remove - * all action messages paired with target. - * @param controlEvent A control event for which the action message is sent. - * See "CCControlEvent" for constants. + * @param {Object} target The target object that is, the object to which the action message is sent. Pass nil to remove all targets paired with action and the specified control events. + * @param {function} action A selector identifying an action message. Pass NULL to remove all action messages paired with target. + * @param {Number} controlEvent A control event for which the action message is sent. See "CCControlEvent" for constants. */ removeTargetWithActionForControlEvent:function (target, action, controlEvent) { // Retrieve all invocations for the given control event @@ -367,7 +336,6 @@ cc.Control = cc.LayerRGBA.extend({ * Updates the control layout using its current internal state. */ needsLayout:function () { - } }); diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/GUI/CCControlExtension/CCControlButton.js index 79d8ce3038..ee479f8240 100644 --- a/extensions/GUI/CCControlExtension/CCControlButton.js +++ b/extensions/GUI/CCControlExtension/CCControlButton.js @@ -1,4 +1,4 @@ -/* +/** * CCControlButton.m * * Copyright (c) 2010-2012 cocos2d-x.org @@ -28,16 +28,16 @@ cc.CONTROL_ZOOM_ACTION_TAG = 0xCCCB0001; /** @class CCControlButton Button control for Cocos2D. */ cc.ControlButton = cc.Control.extend({ - _adjustBackgroundImage:false, + _doesAdjustBackgroundImage:false, _zoomOnTouchDown:false, - _preferredSize:new cc.Size(0, 0), - _labelAnchorPoint:new cc.Point(0, 0), - _currentTitle:"", - _currentTitleColor:cc.white(), + _preferredSize: null, + _labelAnchorPoint: null, + _currentTitle: null, + _currentTitleColor: null, _titleLabel:null, _backgroundSprite:null, _opacity:0, - _pushed:false, + _isPushed:false, _titleDispatchTable:null, _titleColorDispatchTable:null, _titleLabelDispatchTable:null, @@ -51,7 +51,7 @@ cc.ControlButton = cc.Control.extend({ cc.Control.prototype.ctor.call(this); this._preferredSize = new cc.Size(0, 0); this._labelAnchorPoint = new cc.Point(0, 0); - + this._currentTitle = ""; this._currentTitleColor = cc.white(); this._titleDispatchTable = {}; this._titleColorDispatchTable = {}; @@ -60,7 +60,7 @@ cc.ControlButton = cc.Control.extend({ }, init:function () { - return this.initWithLabelAndBackgroundSprite(cc.LabelTTF.create("", "Helvetica", 12), cc.Scale9Sprite.create()); + return this.initWithLabelAndBackgroundSprite(cc.LabelTTF.create("", "Arial", 12), cc.Scale9Sprite.create()); }, needsLayout:function () { @@ -68,63 +68,74 @@ cc.ControlButton = cc.Control.extend({ return; } // Hide the background and the label - this._titleLabel.setVisible(false); - this._backgroundSprite.setVisible(false); + if(this._titleLabel) + this._titleLabel.setVisible(false); + if(this._backgroundSprite) + this._backgroundSprite.setVisible(false); // Update anchor of all labels this.setLabelAnchorPoint(this._labelAnchorPoint); // Update the label to match with the current state //CC_SAFE_RELEASE(this._currentTitle) + var locState = this._state; - this._currentTitle = this.getTitleForState(this._state); - this._currentTitleColor = this.getTitleColorForState(this._state); - - this._titleLabel = this.getTitleLabelForState(this._state); + this._currentTitle = this.getTitleForState(locState); + this._currentTitleColor = this.getTitleColorForState(locState); + this._titleLabel = this.getTitleLabelForState(locState); var label = this._titleLabel; if (label && label.setString) label.setString(this._currentTitle); + if (label && label.RGBAProtocol) + label.setColor(this._currentTitleColor); - if (this._titleLabel && this._titleLabel.RGBAProtocol) - this._titleLabel.setColor(this._currentTitleColor); - this._titleLabel.setPosition(cc.p(this.getContentSize().width / 2, this.getContentSize().height / 2)); - + var locContentSize = this.getContentSize(); + if(label) + label.setPosition(locContentSize.width / 2, locContentSize.height / 2); // Update the background sprite - this._backgroundSprite = this.getBackgroundSpriteForState(this._state); - this._backgroundSprite.setPosition(cc.p(this.getContentSize().width / 2, this.getContentSize().height / 2)); + this._backgroundSprite = this.getBackgroundSpriteForState(locState); + var locBackgroundSprite = this._backgroundSprite; + if(locBackgroundSprite) + locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2); // Get the title label size - var titleLabelSize = this._titleLabel.getBoundingBox().size; + var titleLabelSize = label ? label.getBoundingBox().size : cc.size(0, 0); // Adjust the background image if necessary - if (this._adjustBackgroundImage) { + if (this._doesAdjustBackgroundImage) { // Add the margins - this._backgroundSprite.setContentSize(cc.SizeMake(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2)); + if(locBackgroundSprite) + locBackgroundSprite.setContentSize(cc.size(titleLabelSize.width + this._marginH * 2, titleLabelSize.height + this._marginV * 2)); } else { //TODO: should this also have margins if one of the preferred sizes is relaxed? - var preferredSize = this._backgroundSprite.getPreferredSize(); - if (preferredSize.width <= 0) { - preferredSize.width = titleLabelSize.width; + if(locBackgroundSprite){ + var preferredSize = locBackgroundSprite.getPreferredSize(); + preferredSize = cc.size(preferredSize.width, preferredSize.height); + if (preferredSize.width <= 0) + preferredSize.width = titleLabelSize.width; + if (preferredSize.height <= 0) + preferredSize.height = titleLabelSize.height; + + locBackgroundSprite.setContentSize(preferredSize); } - if (preferredSize.height <= 0) { - preferredSize.height = titleLabelSize.height; - } - - this._backgroundSprite.setContentSize(preferredSize); } // Set the content size - var maxRect = cc.ControlUtils.CCRectUnion(this._titleLabel.getBoundingBox(), this._backgroundSprite.getBoundingBox()); - this.setContentSize(cc.SizeMake(maxRect.width, maxRect.height)); - - this._titleLabel.setPosition(cc.p(this.getContentSize().width / 2, this.getContentSize().height / 2)); - this._backgroundSprite.setPosition(cc.p(this.getContentSize().width / 2, this.getContentSize().height / 2)); - - // Make visible the background and the label - this._titleLabel.setVisible(true); - this._backgroundSprite.setVisible(true); + var rectTitle = label? label.getBoundingBox():cc.rect(0,0,0,0); + var rectBackground = locBackgroundSprite? locBackgroundSprite.getBoundingBox():cc.rect(0,0,0,0); + var maxRect = cc.rectUnion(rectTitle, rectBackground); + this.setContentSize(cc.size(maxRect.width, maxRect.height)); + locContentSize = this.getContentSize(); + if(label){ + label.setPosition(locContentSize.width / 2, locContentSize.height / 2); + label.setVisible(true); + } + if(locBackgroundSprite){ + locBackgroundSprite.setPosition(locContentSize.width / 2, locContentSize.height / 2); + locBackgroundSprite.setVisible(true); + } }, initWithLabelAndBackgroundSprite:function (label, backgroundSprite) { @@ -132,15 +143,23 @@ cc.ControlButton = cc.Control.extend({ cc.Assert(label != null, "node must not be nil"); cc.Assert(label != null || label.RGBAProtocol || backgroundSprite != null, ""); - this.setTouchEnabled(true); - this._pushed = false; this._parentInited = true; + + // Initialize the button state tables + this._titleDispatchTable = {}; + this._titleColorDispatchTable = {}; + this._titleLabelDispatchTable = {}; + this._backgroundSpriteDispatchTable = {}; + + this.setTouchEnabled(true); + this._isPushed = false; this._zoomOnTouchDown = true; - this._state = cc.CONTROL_STATE_INITIAL; + this._currentTitle = null; // Adjust the background image by default - this._adjustBackgroundImage = true; + this.setAdjustBackgroundImage(true); + this.setPreferredSize(cc.size(0,0)); // Zooming button by default this._zoomOnTouchDown = true; @@ -153,13 +172,6 @@ cc.ControlButton = cc.Control.extend({ this._titleLabel = label; this._backgroundSprite = backgroundSprite; - - // Initialize the button state tables - this._titleDispatchTable = {}; - this._titleColorDispatchTable = {}; - this._titleLabelDispatchTable = {}; - this._backgroundSpriteDispatchTable = {}; - // Set the default color and opacity this.setColor(cc.c3(255, 255, 255)); this.setOpacity(255); @@ -185,7 +197,6 @@ cc.ControlButton = cc.Control.extend({ // Layout update this.needsLayout(); - return true; }//couldn't init the CCControl else @@ -202,13 +213,16 @@ cc.ControlButton = cc.Control.extend({ return this.initWithLabelAndBackgroundSprite(label, sprite); }, - /** Adjust the background image. YES by default. If the property is set to NO, the - background will use the prefered size of the background image. */ - getAdjustBackgroundImage:function () { - return this._adjustBackgroundImage; + /** + * Adjust the background image. YES by default. If the property is set to NO, the background will use the prefered size of the background image. + * @return {Boolean} + */ + doesAdjustBackgroundImage:function () { + return this._doesAdjustBackgroundImage; }, + setAdjustBackgroundImage:function (adjustBackgroundImage) { - this._adjustBackgroundImage = adjustBackgroundImage; + this._doesAdjustBackgroundImage = adjustBackgroundImage; this.needsLayout(); }, @@ -216,6 +230,7 @@ cc.ControlButton = cc.Control.extend({ getZoomOnTouchDown:function () { return this._zoomOnTouchDown; }, + setZoomOnTouchDown:function (zoomOnTouchDown) { return this._zoomOnTouchDown = zoomOnTouchDown; }, @@ -227,12 +242,12 @@ cc.ControlButton = cc.Control.extend({ setPreferredSize:function (size) { if (size.width === 0 && size.height === 0) { - this._adjustBackgroundImage = true; + this._doesAdjustBackgroundImage = true; } else { - this._adjustBackgroundImage = false; - for (var itemKey in this._backgroundSpriteDispatchTable) { - this._backgroundSpriteDispatchTable[itemKey].setPreferredSize(size); - } + this._doesAdjustBackgroundImage = false; + var locTable = this._backgroundSpriteDispatchTable; + for (var itemKey in locTable) + locTable[itemKey].setPreferredSize(size); } this._preferredSize = size; this.needsLayout(); @@ -243,17 +258,20 @@ cc.ControlButton = cc.Control.extend({ }, setLabelAnchorPoint:function (labelAnchorPoint) { this._labelAnchorPoint = labelAnchorPoint; - - this._titleLabel.setAnchorPoint(labelAnchorPoint); + if(this._titleLabel) + this._titleLabel.setAnchorPoint(labelAnchorPoint); }, - /** The current title that is displayed on the button. */ - getCurrentTitle:function () { + /** + * The current title that is displayed on the button. + * @return {string} + */ + _getCurrentTitle:function () { return this._currentTitle; }, /** The current color used to display the title. */ - getCurrentTitleColor:function () { + _getCurrentTitleColor:function () { return this._currentTitleColor; }, @@ -263,45 +281,51 @@ cc.ControlButton = cc.Control.extend({ }, setOpacity:function (opacity) { - this._opacity = opacity; - + // XXX fixed me if not correct + cc.Control.prototype.setOpacity.call(opacity); + /*this._opacity = opacity; var controlChildren = this.getChildren(); - for (var i = 0; i < controlChildren.length; i++) { - if (controlChildren[i] && controlChildren[i].RGBAProtocol) { - controlChildren[i].setOpacity(opacity); - } - } - for (var itemKey in this._backgroundSpriteDispatchTable) { - this._backgroundSpriteDispatchTable[itemKey].setOpacity(opacity); - } + var selChild = controlChildren[i]; + if (selChild && selChild.RGBAProtocol) + selChild.setOpacity(opacity); + }*/ + var locTable = this._backgroundSpriteDispatchTable; + for (var itemKey in locTable) + locTable[itemKey].setOpacity(opacity); }, setColor:function(color){ cc.Control.prototype.setColor.call(this,color); - for(var key in this._backgroundSpriteDispatchTable){ - this._backgroundSpriteDispatchTable[key].setColor(color); - } + var locTable = this._backgroundSpriteDispatchTable; + for(var key in locTable) + locTable[key].setColor(color); }, getColor:function(){ return this._realColor; }, + /** Flag to know if the button is currently pushed. */ - getIsPushed:function () { - return this._pushed; + isPushed:function () { + return this._isPushed; }, /* Define the button margin for Top/Bottom edge */ - getVerticalMargin:function () { + _getVerticalMargin:function () { return this._marginV; }, /* Define the button margin for Left/Right edge */ - getHorizontalOrigin:function () { + _getHorizontalOrigin:function () { return this._marginH; }, - //set the margins at once (so we only have to do one call of needsLayout) + + /** + * set the margins at once (so we only have to do one call of needsLayout) + * @param {Number} marginH + * @param {Number} marginV + */ setMargins:function (marginH, marginV) { this._marginV = marginV; this._marginH = marginH; @@ -318,17 +342,13 @@ cc.ControlButton = cc.Control.extend({ }, setHighlighted:function (enabled) { - if (enabled == true) { - this._state = cc.CONTROL_STATE_HIGHLIGHTED; - } - else { - this._state = cc.CONTROL_STATE_NORMAL; - } + this._state = enabled?cc.CONTROL_STATE_HIGHLIGHTED:cc.CONTROL_STATE_NORMAL; + cc.Control.prototype.setHighlighted.call(this, enabled); var action = this.getActionByTag(cc.CONTROL_ZOOM_ACTION_TAG); - if (action) { + if (action) this.stopAction(action); - } + this.needsLayout(); if (this._zoomOnTouchDown) { var scaleValue = (this.isHighlighted() && this.isEnabled() && !this.isSelected()) ? 1.1 : 1.0; @@ -339,33 +359,29 @@ cc.ControlButton = cc.Control.extend({ }, onTouchBegan:function (touch, event) { - if (!this.isTouchInside(touch) || !this.isEnabled()|| !this.isVisible()||!this.hasVisibleParents()) { + if (!this.isTouchInside(touch) || !this.isEnabled()|| !this.isVisible()||!this.hasVisibleParents()) return false; - } - this._pushed = true; + this._isPushed = true; this.setHighlighted(true); this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DOWN); return true; }, onTouchMoved:function (touch, event) { - if (!this._enabled || !this._pushed || this._selected) { - if (this._highlighted) { + if (!this._enabled || !this._isPushed || this._selected) { + if (this._highlighted) this.setHighlighted(false); - } return; } var isTouchMoveInside = this.isTouchInside(touch); if (isTouchMoveInside && !this._highlighted) { - this._state = cc.CONTROL_STATE_HIGHLIGHTED; this.setHighlighted(true); this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_ENTER); } else if (isTouchMoveInside && this._highlighted) { this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_INSIDE); } else if (!isTouchMoveInside && this._highlighted) { - this._state = cc.CONTROL_STATE_NORMAL; this.setHighlighted(false); this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_DRAG_EXIT); } else if (!isTouchMoveInside && !this._highlighted) { @@ -373,7 +389,7 @@ cc.ControlButton = cc.Control.extend({ } }, onTouchEnded:function (touch, event) { - this._pushed = false; + this._isPushed = false; this.setHighlighted(false); if (this.isTouchInside(touch)) { @@ -384,7 +400,7 @@ cc.ControlButton = cc.Control.extend({ }, onTouchCancelled:function (touch, event) { - this._pushed = false; + this._isPushed = false; this.setHighlighted(false); this.sendActionsForControlEvents(cc.CONTROL_EVENT_TOUCH_CANCEL); }, @@ -392,127 +408,110 @@ cc.ControlButton = cc.Control.extend({ /** * Returns the title used for a state. * - * @param state The state that uses the title. Possible values are described in - * "CCControlState". - * - * @return The title for the specified state. + * @param {Number} state The state that uses the title. Possible values are described in "CCControlState". + * @return {string} The title for the specified state. */ getTitleForState:function (state) { - if (this._titleDispatchTable) { - if (this._titleDispatchTable[state]) - return this._titleDispatchTable[state]; - return this._titleDispatchTable[cc.CONTROL_STATE_NORMAL]; + var locTable = this._titleDispatchTable; + if (locTable) { + if (locTable[state]) + return locTable[state]; + return locTable[cc.CONTROL_STATE_NORMAL]; } return ""; }, /** - * Sets the title string to use for the specified state. - * If a property is not specified for a state, the default is to use - * the CCButtonStateNormal value. - * - * @param title The title string to use for the specified state. - * @param state The state that uses the specified title. The values are described - * in "CCControlState". + *

+ * Sets the title string to use for the specified state.
+ * If a property is not specified for a state, the default is to use the CCButtonStateNormal value. + *

+ * @param {string} title The title string to use for the specified state. + * @param {Number} state The state that uses the specified title. The values are described in "CCControlState". */ setTitleForState:function (title, state) { - if (title) { - this._titleDispatchTable[state] = title; - } else { - this._titleDispatchTable[state] = ""; - } + this._titleDispatchTable[state] = title || ""; // If the current state if equal to the given state we update the layout - if (this.getState() == state) { + if (this.getState() == state) this.needsLayout(); - } }, /** * Returns the title color used for a state. * - * @param state The state that uses the specified color. The values are described - * in "CCControlState". - * - * @return The color of the title for the specified state. + * @param {Number} state The state that uses the specified color. The values are described in "CCControlState". + * @return {cc.Color3B} The color of the title for the specified state. */ - getTitleColorForState:function (state) { - var returnColor = cc.white(); - do { - var colorObject = this._titleColorDispatchTable[state]; - if (colorObject) { - returnColor = colorObject; - break; - } - colorObject = this._titleColorDispatchTable[cc.CONTROL_STATE_NORMAL]; - if (colorObject) { - returnColor = colorObject; - break; - } - - } while (0); - - return returnColor; + getTitleColorForState: function (state) { + var colorObject = this._titleColorDispatchTable[state]; + if (colorObject) + return colorObject; + colorObject = this._titleColorDispatchTable[cc.CONTROL_STATE_NORMAL]; + if (colorObject) + return colorObject; + return cc.white(); }, /** * Sets the color of the title to use for the specified state. * - * @param color The color of the title to use for the specified state. - * @param state The state that uses the specified color. The values are described - * in "CCControlState". + * @param {cc.Color3B} color The color of the title to use for the specified state. + * @param {Number} state The state that uses the specified color. The values are described in "CCControlState". */ setTitleColorForState:function (color, state) { //ccColor3B* colorValue=&color; this._titleColorDispatchTable[state] = color; // If the current state if equal to the given state we update the layout - if (this.getState() == state) { + if (this.getState() == state) this.needsLayout(); - } }, /** * Returns the title label used for a state. * - * @param state The state that uses the title label. Possible values are described - * in "CCControlState". + * @param state The state that uses the title label. Possible values are described in "CCControlState". + * @return {cc.Node} the title label used for a state. */ getTitleLabelForState:function (state) { - if (this._titleLabelDispatchTable.hasOwnProperty(state) && this._titleLabelDispatchTable[state]) { - return this._titleLabelDispatchTable[state]; - } - return this._titleLabelDispatchTable[cc.CONTROL_STATE_NORMAL]; + var locTable = this._titleLabelDispatchTable; + if (locTable.hasOwnProperty(state) && locTable[state]) + return locTable[state]; + + return locTable[cc.CONTROL_STATE_NORMAL]; }, /** - * Sets the title label to use for the specified state. - * If a property is not specified for a state, the default is to use - * the CCButtonStateNormal value. + *

Sets the title label to use for the specified state.
+ * If a property is not specified for a state, the default is to use the CCButtonStateNormal value.

* - * @param titleLabel The title label to use for the specified state. - * @param state The state that uses the specified title. The values are described - * in "CCControlState". + * @param {cc.Node} titleLabel The title label to use for the specified state. + * @param {Number} state The state that uses the specified title. The values are described in "CCControlState". */ setTitleLabelForState:function (titleLabel, state) { - if (this._titleLabelDispatchTable.hasOwnProperty(state)) { - var previousLabel = this._titleLabelDispatchTable[state]; - if (previousLabel) { + var locTable = this._titleLabelDispatchTable; + if (locTable.hasOwnProperty(state)) { + var previousLabel = locTable[state]; + if (previousLabel) this.removeChild(previousLabel, true); - } } - this._titleLabelDispatchTable[state] = titleLabel; + locTable[state] = titleLabel; titleLabel.setVisible(false); titleLabel.setAnchorPoint(cc.p(0.5, 0.5)); this.addChild(titleLabel, 1); // If the current state if equal to the given state we update the layout - if (this.getState() == state) { + if (this.getState() == state) this.needsLayout(); - } }, + /** + * Sets the title TTF filename to use for the specified state. + * @param {string} fntFile + * @param {Number} state + */ setTitleTTFForState:function (fntFile, state) { var title = this.getTitleForState(state); if (!title) @@ -520,6 +519,11 @@ cc.ControlButton = cc.Control.extend({ this.setTitleLabelForState(cc.LabelTTF.create(title, fntFile, 12), state); }, + /** + * return the title TTF filename to use for the specified state. + * @param {Number} state + * @returns {string} + */ getTitleTTFForState:function (state) { var labelTTF = this.getTitleLabelForState(state); if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) { @@ -529,6 +533,10 @@ cc.ControlButton = cc.Control.extend({ } }, + /** + * @param {Number} size + * @param {Number} state + */ setTitleTTFSizeForState:function (size, state) { var labelTTF = this.getTitleLabelForState(state); if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) { @@ -536,6 +544,11 @@ cc.ControlButton = cc.Control.extend({ } }, + /** + * return the font size of LabelTTF to use for the specified state + * @param {Number} state + * @returns {Number} + */ getTitleTTFSizeForState:function (state) { var labelTTF = this.getTitleLabelForState(state); if ((labelTTF != null) && (labelTTF instanceof cc.LabelTTF)) { @@ -545,10 +558,9 @@ cc.ControlButton = cc.Control.extend({ }, /** - * Sets the font of the label, changes the label to a CCLabelBMFont if neccessary. - * @param fntFile The name of the font to change to - * @param state The state that uses the specified fntFile. The values are described - * in "CCControlState". + * Sets the font of the label, changes the label to a CCLabelBMFont if necessary. + * @param {string} fntFile The name of the font to change to + * @param {Number} state The state that uses the specified fntFile. The values are described in "CCControlState". */ setTitleBMFontForState:function (fntFile, state) { var title = this.getTitleForState(state); @@ -568,52 +580,50 @@ cc.ControlButton = cc.Control.extend({ /** * Returns the background sprite used for a state. * - * @param state The state that uses the background sprite. Possible values are - * described in "CCControlState". + * @param {Number} state The state that uses the background sprite. Possible values are described in "CCControlState". */ getBackgroundSpriteForState:function (state) { - if (this._backgroundSpriteDispatchTable.hasOwnProperty(state) && this._backgroundSpriteDispatchTable[state]) { - return this._backgroundSpriteDispatchTable[state]; + var locTable = this._backgroundSpriteDispatchTable; + if (locTable.hasOwnProperty(state) && locTable[state]) { + return locTable[state]; } - return this._backgroundSpriteDispatchTable[cc.CONTROL_STATE_NORMAL]; + return locTable[cc.CONTROL_STATE_NORMAL]; }, /** * Sets the background sprite to use for the specified button state. * - * @param sprite The background sprite to use for the specified state. - * @param state The state that uses the specified image. The values are described - * in "CCControlState". + * @param {Scale9Sprite} sprite The background sprite to use for the specified state. + * @param {Number} state The state that uses the specified image. The values are described in "CCControlState". */ setBackgroundSpriteForState:function (sprite, state) { - if (this._backgroundSpriteDispatchTable.hasOwnProperty(state)) { - var previousSprite = this._backgroundSpriteDispatchTable[state]; - if (previousSprite) { + var locTable = this._backgroundSpriteDispatchTable; + if (locTable.hasOwnProperty(state)) { + var previousSprite = locTable[state]; + if (previousSprite) this.removeChild(previousSprite, true); - } } - this._backgroundSpriteDispatchTable[state] = sprite; + locTable[state] = sprite; sprite.setVisible(false); sprite.setAnchorPoint(cc.p(0.5, 0.5)); this.addChild(sprite); - if (this._preferredSize.width !== 0 || this._preferredSize.height !== 0) { - sprite.setPreferredSize(this._preferredSize); + var locPreferredSize = this._preferredSize; + if (locPreferredSize.width !== 0 || locPreferredSize.height !== 0) { + sprite.setPreferredSize(locPreferredSize); } // If the current state if equal to the given state we update the layout - if (this._state === state) { + if (this._state === state) this.needsLayout(); - } }, /** * Sets the background spriteFrame to use for the specified button state. * - * @param spriteFrame The background spriteFrame to use for the specified state. - * @param state The state that uses the specified image. The values are described - * in "CCControlState". + * @param {SpriteFrame} spriteFrame The background spriteFrame to use for the specified state. + * @param {Number} state The state that uses the specified image. The values are described in "CCControlState". */ setBackgroundSpriteFrameForState:function (spriteFrame, state) { var sprite = cc.Scale9Sprite.createWithSpriteFrame(spriteFrame); diff --git a/extensions/GUI/CCControlExtension/CCControlColourPicker.js b/extensions/GUI/CCControlExtension/CCControlColourPicker.js index d6cf2706f7..a456f5eb71 100644 --- a/extensions/GUI/CCControlExtension/CCControlColourPicker.js +++ b/extensions/GUI/CCControlExtension/CCControlColourPicker.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlHuePicker.js b/extensions/GUI/CCControlExtension/CCControlHuePicker.js index e9a34159c8..10952b4370 100644 --- a/extensions/GUI/CCControlExtension/CCControlHuePicker.js +++ b/extensions/GUI/CCControlExtension/CCControlHuePicker.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlPotentiometer.js b/extensions/GUI/CCControlExtension/CCControlPotentiometer.js index 693cd9646d..a7245ef9ec 100644 --- a/extensions/GUI/CCControlExtension/CCControlPotentiometer.js +++ b/extensions/GUI/CCControlExtension/CCControlPotentiometer.js @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2012 cocos2d-x.org * http://www.cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js b/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js index 66e985338a..7957a55e83 100644 --- a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js +++ b/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlSlider.js b/extensions/GUI/CCControlExtension/CCControlSlider.js index 2b3e9bb107..bf93540ff3 100644 --- a/extensions/GUI/CCControlExtension/CCControlSlider.js +++ b/extensions/GUI/CCControlExtension/CCControlSlider.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlStepper.js b/extensions/GUI/CCControlExtension/CCControlStepper.js index 4a16c0eae7..e0985fe77b 100644 --- a/extensions/GUI/CCControlExtension/CCControlStepper.js +++ b/extensions/GUI/CCControlExtension/CCControlStepper.js @@ -1,4 +1,4 @@ -/* +/** * Copyright (c) 2012 cocos2d-x.org * http://www.cocos2d-x.org * @@ -55,6 +55,7 @@ cc.ControlStepper = cc.Control.extend({ _touchedPart:cc.CONTROL_STEPPER_PARTNONE, _autorepeatCount:0, ctor:function () { + cc.Control.prototype.ctor.call(this); this._minusSprite = null; this._plusSprite = null; this._minusLabel = null; diff --git a/extensions/GUI/CCControlExtension/CCControlSwitch.js b/extensions/GUI/CCControlExtension/CCControlSwitch.js index d551196e1e..292a4a93c2 100644 --- a/extensions/GUI/CCControlExtension/CCControlSwitch.js +++ b/extensions/GUI/CCControlExtension/CCControlSwitch.js @@ -1,4 +1,4 @@ -/* +/** * * Copyright (c) 2010-2012 cocos2d-x.org * diff --git a/extensions/GUI/CCControlExtension/CCControlUtils.js b/extensions/GUI/CCControlExtension/CCControlUtils.js index 3acd0e3483..c31fdf1db6 100644 --- a/extensions/GUI/CCControlExtension/CCControlUtils.js +++ b/extensions/GUI/CCControlExtension/CCControlUtils.js @@ -153,7 +153,6 @@ cc.ControlUtils.RGBfromHSV = function(hsvValue){ out.g = p; out.b = hsvValue.v; break; - case 5: default: out.r = hsvValue.v; out.g = p; diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 37d767ad11..352fc6d010 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -87,7 +87,6 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) { insets = cc.RectZero(); } else { - insets = this._spriteFrameRotated ? cc.RectMake(locInsetBottom, locInsetLeft, locSpriteRect.width - locInsetRight - locInsetLeft, locSpriteRect.height - locInsetTop - locInsetBottom) : @@ -439,9 +438,8 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ this._opacityModifyRGB = value; var scaleChildren = this._scale9Image.getChildren(); if (scaleChildren) { - for (var i = 0; i < scaleChildren.length; i++) { - scaleChildren[i].setOpacityModifyRGB(this._opacityModifyRGB); - } + for (var i = 0, len = scaleChildren.length; i < len; i++) + scaleChildren[i].setOpacityModifyRGB(value); } }, @@ -468,12 +466,11 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ this._capInsets = capInsets; var selTexture = locScale9Image.getTexture(); - var rectZero = cc.RectZero(); // If there is no given rect - if (cc.rectEqualToRect(rect, rectZero)) { + if (cc._rectEqualToZero(rect)) { // Get the texture size as original var textureSize = selTexture.getContentSize(); - rect = cc.RectMake(0, 0, textureSize.width, textureSize.height); + rect = cc.rect(0, 0, textureSize.width, textureSize.height); } // Set the given rect's size as original size @@ -498,7 +495,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ var h = rectSize.height; // If there is no specified center region - if (cc.rectEqualToRect(locCapInsetsInternal, rectZero)) { + if (cc._rectEqualToZero(locCapInsetsInternal)) { // CCLog("... cap insets not specified : using default cap insets ..."); locCapInsetsInternal.x = w / 3; locCapInsetsInternal.y = h / 3; @@ -520,15 +517,15 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ var y = 0.0; // top left - var lefttopbounds = cc.RectMake(x, y, left_w, top_h); + var lefttopbounds = cc.rect(x, y, left_w, top_h); // top center x += left_w; - var centertopbounds = cc.RectMake(x, y, center_w, top_h); + var centertopbounds = cc.rect(x, y, center_w, top_h); // top right x += center_w; - var righttopbounds = cc.RectMake(x, y, right_w, top_h); + var righttopbounds = cc.rect(x, y, right_w, top_h); // ... center row x = 0.0; @@ -536,15 +533,15 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ // center left y += top_h; - var leftcenterbounds = cc.RectMake(x, y, left_w, center_h); + var leftcenterbounds = cc.rect(x, y, left_w, center_h); // center center x += left_w; - var centerbounds = cc.RectMake(x, y, center_w, center_h); + var centerbounds = cc.rect(x, y, center_w, center_h); // center right x += center_w; - var rightcenterbounds = cc.RectMake(x, y, right_w, center_h); + var rightcenterbounds = cc.rect(x, y, right_w, center_h); // ... bottom row x = 0.0; @@ -553,30 +550,30 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ y += center_h; // bottom left - var leftbottombounds = cc.RectMake(x, y, left_w, bottom_h); + var leftbottombounds = cc.rect(x, y, left_w, bottom_h); // bottom center x += left_w; - var centerbottombounds = cc.RectMake(x, y, center_w, bottom_h); + var centerbottombounds = cc.rect(x, y, center_w, bottom_h); // bottom right x += center_w; - var rightbottombounds = cc.RectMake(x, y, right_w, bottom_h); + var rightbottombounds = cc.rect(x, y, right_w, bottom_h); var t = cc.AffineTransformMakeIdentity(); if (!rotated) { // CCLog("!rotated"); t = cc.AffineTransformTranslate(t, rect.x, rect.y); - centerbounds = cc.RectApplyAffineTransform(centerbounds, t); - rightbottombounds = cc.RectApplyAffineTransform(rightbottombounds, t); - leftbottombounds = cc.RectApplyAffineTransform(leftbottombounds, t); - righttopbounds = cc.RectApplyAffineTransform(righttopbounds, t); - lefttopbounds = cc.RectApplyAffineTransform(lefttopbounds, t); - rightcenterbounds = cc.RectApplyAffineTransform(rightcenterbounds, t); - leftcenterbounds = cc.RectApplyAffineTransform(leftcenterbounds, t); - centerbottombounds = cc.RectApplyAffineTransform(centerbottombounds, t); - centertopbounds = cc.RectApplyAffineTransform(centertopbounds, t); + cc._RectApplyAffineTransformIn(centerbounds, t); + cc._RectApplyAffineTransformIn(rightbottombounds, t); + cc._RectApplyAffineTransformIn(leftbottombounds, t); + cc._RectApplyAffineTransformIn(righttopbounds, t); + cc._RectApplyAffineTransformIn(lefttopbounds, t); + cc._RectApplyAffineTransformIn(rightcenterbounds, t); + cc._RectApplyAffineTransformIn(leftcenterbounds, t); + cc._RectApplyAffineTransformIn(centerbottombounds, t); + cc._RectApplyAffineTransformIn(centertopbounds, t); // Centre this._centre = new cc.Sprite(); diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index 04ef5034c4..2d2180a775 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -38,7 +38,8 @@ var INSET_RATIO = 0.2; var MOVE_INCH = 7.0/160.0; cc.convertDistanceFromPointToInch = function(pointDis){ - var factor = (cc.EGLView.getInstance().getScaleX() + cc.EGLView.getInstance().getScaleY())/2; + var eglViewer = cc.EGLView.getInstance(); + var factor = (eglViewer.getScaleX() + eglViewer.getScaleY())/2; return (pointDis * factor) / 160; // CCDevice::getDPI() default value }; @@ -104,7 +105,7 @@ cc.ScrollView = cc.Layer.extend({ }, /** - * Returns a scroll view object + * initialized whether success or fail * @param {cc.Size} size * @param {cc.Node} container * @return {Boolean} @@ -146,24 +147,25 @@ cc.ScrollView = cc.Layer.extend({ * @param {cc.Point} offset new offset * @param {Number} [animated=] If YES, the view scrolls to the new offset */ - setContentOffset:function (offset, animated) { + setContentOffset: function (offset, animated) { if (animated) { //animate scrolling this.setContentOffsetInDuration(offset, BOUNCE_DURATION); - } else { //set the container position directly - if (!this._bounceable) { - var minOffset = this.minContainerOffset(); - var maxOffset = this.maxContainerOffset(); + return; + } + if (!this._bounceable) { + var minOffset = this.minContainerOffset(); + var maxOffset = this.maxContainerOffset(); - offset.x = Math.max(minOffset.x, Math.min(maxOffset.x, offset.x)); - offset.y = Math.max(minOffset.y, Math.min(maxOffset.y, offset.y)); - } + offset.x = Math.max(minOffset.x, Math.min(maxOffset.x, offset.x)); + offset.y = Math.max(minOffset.y, Math.min(maxOffset.y, offset.y)); + } - this._container.setPosition(offset); - var locDelegate = this._delegate; - if (locDelegate != null && locDelegate.scrollViewDidScroll) { - locDelegate.scrollViewDidScroll(this); - } + this._container.setPosition(offset); + var locDelegate = this._delegate; + if (locDelegate != null && locDelegate.scrollViewDidScroll) { + locDelegate.scrollViewDidScroll(this); } + }, getContentOffset:function () { @@ -188,36 +190,34 @@ cc.ScrollView = cc.Layer.extend({ * Sets a new scale and does that for a predefined duration. * * @param {Number} scale a new scale vale - * @param {Boolean} animated if YES, scaling is animated + * @param {Boolean} [animated=null] if YES, scaling is animated */ - setZoomScale:function (scale, animated) { - if (arguments.length === 1) { - var locContainer = this._container; - if (locContainer.getScale() != scale) { - var oldCenter, newCenter; - var center; - - if (this._touchLength == 0.0) { - center = cc.p(this._viewSize.width * 0.5, this._viewSize.height * 0.5); - center = this.convertToWorldSpace(center); - } else - center = this._touchPoint; - - oldCenter = locContainer.convertToNodeSpace(center); - locContainer.setScale(Math.max(this._minScale, Math.min(this._maxScale, scale))); - newCenter = locContainer.convertToWorldSpace(oldCenter); - - var offset = cc.pSub(center, newCenter); - if (this._delegate != null) { - this._delegate.scrollViewDidZoom(this); - } - this.setContentOffset(cc.pAdd(locContainer.getPosition(), offset)); - } - } else if (arguments.length === 2) { - if (animated) - this.setZoomScaleInDuration(scale, BOUNCE_DURATION); - else - this.setZoomScale(scale); + setZoomScale: function (scale, animated) { + if (animated) { + this.setZoomScaleInDuration(scale, BOUNCE_DURATION); + return; + } + + var locContainer = this._container; + if (locContainer.getScale() != scale) { + var oldCenter, newCenter; + var center; + + if (this._touchLength == 0.0) { + var locViewSize = this._viewSize; + center = cc.p(locViewSize.width * 0.5, locViewSize.height * 0.5); + center = this.convertToWorldSpace(center); + } else + center = this._touchPoint; + + oldCenter = locContainer.convertToNodeSpace(center); + locContainer.setScale(Math.max(this._minScale, Math.min(this._maxScale, scale))); + newCenter = locContainer.convertToWorldSpace(oldCenter); + + var offset = cc.pSub(center, newCenter); + if (this._delegate != null) + this._delegate.scrollViewDidZoom(this); + this.setContentOffset(cc.pAdd(locContainer.getPosition(), offset)); } }, @@ -233,8 +233,9 @@ cc.ScrollView = cc.Layer.extend({ */ setZoomScaleInDuration:function (s, dt) { if (dt > 0) { - if (this._container.getScale() != s) { - var scaleAction = cc.ActionTween.create(dt, "zoomScale", this._container.getScale(), s); + var locScale = this._container.getScale(); + if (locScale != s) { + var scaleAction = cc.ActionTween.create(dt, "zoomScale", locScale, s); this.runAction(scaleAction); } } else { @@ -244,15 +245,18 @@ cc.ScrollView = cc.Layer.extend({ /** * Returns the current container's minimum offset. You may want this while you animate scrolling by yourself + * @return {cc.Point} Returns the current container's minimum offset. */ minContainerOffset:function () { - var locContentSize = this._container.getContentSize(); - return cc.p(this._viewSize.width - locContentSize.width * this._container.getScaleX(), - this._viewSize.height - locContentSize.height * this._container.getScaleY()); + var locContainer = this._container; + var locContentSize = locContainer.getContentSize(), locViewSize = this._viewSize; + return cc.p(locViewSize.width - locContentSize.width * locContainer.getScaleX(), + locViewSize.height - locContentSize.height * locContainer.getScaleY()); }, /** * Returns the current container's maximum offset. You may want this while you animate scrolling by yourself + * @return {cc.Point} Returns the current container's maximum offset. */ maxContainerOffset:function () { return cc.p(0.0, 0.0); @@ -289,7 +293,7 @@ cc.ScrollView = cc.Layer.extend({ */ resume:function (sender) { var selChildren = this._container.getChildren(); - for (var i = 0; i < selChildren.length; i++) { + for (var i = 0, len = selChildren.length; i < len; i++) { selChildren[i].resumeSchedulerAndActions(); } @@ -338,10 +342,10 @@ cc.ScrollView = cc.Layer.extend({ this.removeAllChildren(true); this._container = container; - this._container.ignoreAnchorPointForPosition(false); - this._container.setAnchorPoint(cc.p(0.0, 0.0)); + container.ignoreAnchorPointForPosition(false); + container.setAnchorPoint(cc.p(0.0, 0.0)); - this.addChild(this._container); + this.addChild(container); this.setViewSize(this._viewSize); }, @@ -414,10 +418,10 @@ cc.ScrollView = cc.Layer.extend({ var newPoint = this.convertTouchToNodeSpace(touch); var moveDistance = cc.pSub(newPoint, this._touchPoint); - var dis = 0.0; - if (this._direction === cc.SCROLLVIEW_DIRECTION_VERTICAL) + var dis = 0.0, locDirection = this._direction; + if (locDirection === cc.SCROLLVIEW_DIRECTION_VERTICAL) dis = moveDistance.y; - else if (this._direction === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) + else if (locDirection === cc.SCROLLVIEW_DIRECTION_HORIZONTAL) dis = moveDistance.x; else dis = Math.sqrt(moveDistance.x * moveDistance.x + moveDistance.y * moveDistance.y); @@ -436,7 +440,7 @@ cc.ScrollView = cc.Layer.extend({ this._touchMoved = true; if (cc.rectContainsPoint(frame, this.convertToWorldSpace(newPoint))) { - switch (this._direction) { + switch (locDirection) { case cc.SCROLLVIEW_DIRECTION_VERTICAL: moveDistance.x = 0.0; break; @@ -680,7 +684,8 @@ cc.ScrollView = cc.Layer.extend({ newX = Math.max(newX, minInset.x); var newY = Math.min(this._container.getPosition().y, maxInset.y); newY = Math.max(newY, minInset.y);*/ - oldPosition = this._container.getPosition(); + oldPosition.x = this._container.getPositionX(); + oldPosition.y = this._container.getPositionY(); var newX = oldPosition.x; var newY = oldPosition.y; @@ -767,7 +772,6 @@ cc.ScrollView = cc.Layer.extend({ //clip EGLViewer.setScissorInPoints(frame.x, frame.y, frame.width, frame.height); } - } } }, diff --git a/extensions/GUI/CCScrollView/CCSorting.js b/extensions/GUI/CCScrollView/CCSorting.js index ede6e0811c..205cfa8fe0 100644 --- a/extensions/GUI/CCScrollView/CCSorting.js +++ b/extensions/GUI/CCScrollView/CCSorting.js @@ -52,7 +52,7 @@ var _compareObject = function (val1, val2) { }; cc.ArrayForObjectSorting = cc.Class.extend({ - _saveObjectArr:[], + _saveObjectArr:null, ctor:function () { this._saveObjectArr = []; @@ -128,9 +128,8 @@ cc.ArrayForObjectSorting = cc.Class.extend({ var idx = this.indexOfSortedObject(foundObj); if (idx < this.count() && idx != cc.INVALID_INDEX) { foundObj = this.objectAtIndex(idx); - if (foundObj.getObjectID() != tag) { + if (foundObj.getObjectID() != tag) foundObj = null; - } } return foundObj; }, @@ -167,8 +166,9 @@ cc.ArrayForObjectSorting = cc.Class.extend({ var uPrevObjectID = 0; var uOfSortObjectID = idxObj.getObjectID(); - for (var i = 0; i < this._saveObjectArr.length; i++) { - var pSortableObj = this._saveObjectArr[i]; + var locObjectArr = this._saveObjectArr; + for (var i = 0; i < locObjectArr.length; i++) { + var pSortableObj = locObjectArr[i]; var curObjectID = pSortableObj.getObjectID(); if ((uOfSortObjectID == curObjectID) || (uOfSortObjectID >= uPrevObjectID && uOfSortObjectID < curObjectID)) { @@ -189,9 +189,10 @@ cc.ArrayForObjectSorting = cc.Class.extend({ }, lastObject:function () { - if (this._saveObjectArr.length == 0) + var locObjectArr = this._saveObjectArr; + if (locObjectArr.length == 0) return null; - return this._saveObjectArr[this._saveObjectArr.length - 1]; + return locObjectArr[locObjectArr.length - 1]; }, objectAtIndex:function (idx) { diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index d86de079e7..67003ebe76 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -64,10 +64,42 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({ /** * Delegate to respond touch event * - * @param table table contains the given cell - * @param cell cell that is touched + * @param {cc.TableView} table table contains the given cell + * @param {cc.TableViewCell} cell cell that is touched */ tableCellTouched:function (table, cell) { + }, + + /** + * Delegate to respond a table cell press event. + * + * @param {cc.TableView} table table contains the given cell + * @param {cc.TableViewCell} cell cell that is pressed + */ + tableCellHighlight:function(table, cell){ + }, + + /** + * Delegate to respond a table cell release event + * + * @param {cc.TableView} table table contains the given cell + * @param {cc.TableViewCell} cell cell that is pressed + */ + tableCellUnhighlight:function(table, cell){ + + }, + + /** + *

+ * Delegate called when the cell is about to be recycled. Immediately
+ * after this call the cell will be removed from the scene graph and
+ * recycled. + *

+ * @param table table contains the given cell + * @param cell cell that is pressed + */ + tableCellWillRecycle:function(table, cell){ + } }); @@ -75,30 +107,39 @@ cc.TableViewDelegate = cc.ScrollViewDelegate.extend({ * Data source that governs table backend data. */ cc.TableViewDataSource = cc.Class.extend({ + /** + * cell size for a given index + * @param {cc.TableView} table table to hold the instances of Class + * @param {Number} idx the index of a cell to get a size + * @return {cc.Size} size of a cell at given index + */ + tableCellSizeForIndex:function(table, idx){ + return this.cellSizeForTable(table); + }, /** * cell height for a given table. * - * @param table table to hold the instances of Class - * @return cell size + * @param {cc.TableView} table table to hold the instances of Class + * @return {cc.Size} cell size */ cellSizeForTable:function (table) { - return 0; + return cc.SIZE_ZERO; }, /** * a cell instance at a given index - * + * @param {cc.TableView} table table to hold the instances of Class * @param idx index to search for a cell - * @return cell found at idx + * @return {cc.TableView} cell found at idx */ tableCellAtIndex:function (table, idx) { - return 0; + return null; }, /** * Returns number of cells in a given table view. - * - * @return number of cells + * @param {cc.TableView} table table to hold the instances of Class + * @return {Number} number of cells */ numberOfCellsInTableView:function (table) { return 0; @@ -140,11 +181,12 @@ cc.TableView = cc.ScrollView.extend({ }, _indexFromOffset:function (offset) { - var maxIdx = this._dataSource.numberOfCellsInTableView(this) - 1; + var locDataSource = this._dataSource; + var maxIdx = locDataSource.numberOfCellsInTableView(this) - 1; var offset1 = new cc.Point(offset.x, offset.y); - var cellSize = this._dataSource.cellSizeForTable(this); + var cellSize = locDataSource.cellSizeForTable(this); if (this._vOrdering == cc.TABLEVIEW_FILL_TOPDOWN) { offset1.y = this.getContainer().getContentSize().height - offset.y - cellSize.height; } @@ -377,23 +419,21 @@ cc.TableView = cc.ScrollView.extend({ */ reloadData:function () { this._oldDirection = cc.SCROLLVIEW_DIRECTION_NONE; - var locCellsUsed = this._cellsUsed; + var locCellsUsed = this._cellsUsed, locCellsFreed = this._cellsFreed, locContainer = this.getContainer(); for (var i = 0; i < locCellsUsed.count(); i++) { var cell = locCellsUsed.objectAtIndex(i); - this._cellsFreed.addObject(cell); + locCellsFreed.addObject(cell); cell.reset(); - if (cell.getParent() == this.getContainer()) { - this.getContainer().removeChild(cell, true); - } + if (cell.getParent() == locContainer) + locContainer.removeChild(cell, true); } this._indices = new cc.Set(); this._cellsUsed = new cc.ArrayForObjectSorting(); this._updateContentSize(); - if (this._dataSource.numberOfCellsInTableView(this) > 0) { + if (this._dataSource.numberOfCellsInTableView(this) > 0) this.scrollViewDidScroll(this); - } }, /** @@ -479,8 +519,9 @@ cc.TableView = cc.ScrollView.extend({ } } + var locIndices = this._indices; for (var i = startIdx; i <= endIdx; i++) { - if (this._indices.containsObject(i)) + if (locIndices.containsObject(i)) continue; this.updateCellAtIndex(i); } @@ -502,9 +543,8 @@ cc.TableView = cc.ScrollView.extend({ var index = 0 | this._indexFromOffset(point); var cell = this._cellWithIndex(index); - if (cell) { + if (cell) this._tableViewDelegate.tableCellTouched(this, cell); - } } cc.ScrollView.prototype.onTouchEnded.call(this, touch, event); } From a1f75f0ff577ea8a539a6f532f63c4d5be04aed4 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 27 Aug 2013 11:38:45 +0800 Subject: [PATCH 063/141] fixed #2723: Function prototype have not method of bind in iphone safari. --- cocos2d/platform/CCClass.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cocos2d/platform/CCClass.js b/cocos2d/platform/CCClass.js index 6f96df7edb..cfe9295024 100644 --- a/cocos2d/platform/CCClass.js +++ b/cocos2d/platform/CCClass.js @@ -199,6 +199,15 @@ ClassManager.getNewID=function(){ }; return Class; }; + + Function.prototype.bind = Function.prototype.bind || function (bind) { + var self = this; + return function () { + var args = Array.prototype.slice.call(arguments); + return self.apply(bind || null, args); + }; + }; + })(); // @@ -259,3 +268,4 @@ cc.concatObjectProperties = function(dstObject, srcObject){ } return dstObject; }; + From 27f140a13bcd2c4920b3491ea400f51a553b2769 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 27 Aug 2013 11:39:52 +0800 Subject: [PATCH 064/141] fixed #2723: Append a div child to body bottom,and tag to it. --- cocos2d/platform/CCApplication.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js index 6fbc4adb15..5ccf92c4bb 100644 --- a/cocos2d/platform/CCApplication.js +++ b/cocos2d/platform/CCApplication.js @@ -235,8 +235,10 @@ cc.setup = function (el, width, height) { } }, true); */ - if(cc.Browser.isMobile) + if(cc.Browser.isMobile){ cc._addUserSelectStatus(); + cc._addBottomTag(); + } var hidden, visibilityChange; if (typeof document.hidden !== "undefined") { @@ -276,6 +278,14 @@ cc._addUserSelectStatus = function(){ +"-webkit-tap-highlight-color:rgba(0,0,0,0);}"; }; +cc._addBottomTag = function () { + var bottom = document.createElement("div"); + bottom.id = "bottom"; + bottom.style.border = bottom.style.margin = bottom.style.padding = bottom.style.height = bottom.style.lineHeight = bottom.style.fontSize = "0px"; + document.body.appendChild(bottom); + window.location.href="#bottom"; +}; + cc._isContextMenuEnable = false; /** * enable/disable contextMenu for Canvas From 2bf91e529c4cb84fd30764c3b203578ec7ed69d4 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 27 Aug 2013 11:41:07 +0800 Subject: [PATCH 065/141] fixed #2723: Hide url address bar for mobile browser,it can work in iphone safari and android default browser . --- cocos2d/platform/CCEGLView.js | 43 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/cocos2d/platform/CCEGLView.js b/cocos2d/platform/CCEGLView.js index eb3d974ef3..c551ced119 100644 --- a/cocos2d/platform/CCEGLView.js +++ b/cocos2d/platform/CCEGLView.js @@ -88,29 +88,50 @@ cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{ ctor:function () { this._ele = (cc.container.parentNode === document.body) ? document.documentElement : cc.container.parentNode; this._viewName = "Cocos2dHTML5"; - this._screenSize = cc.size(this._ele.clientWidth, this._ele.clientHeight); + this._designResolutionSize = cc.SizeZero(); this._viewPortRect = cc.RectZero(); this._delegate = cc.Director.getInstance().getTouchDispatcher(); this._contentTranslateLeftTop = {left:0, top:0}; + this._screenSize = cc.SizeZero(); this._hDC = cc.canvas; this._hRC = cc.renderContext; + this._initScreenSize(); }, /** * init */ initialize:function () { + this._scrollToBottom(); this._initialize = true; - this._adjustSize(); - var adjustSize = this._adjustSize.bind(this); window.addEventListener('resize', adjustSize, false); + if(cc.Browser.isMobile){ + setTimeout(adjustSize,300); + }else{ + this._adjustSize(); + } + }, + + _scrollToBottom:function(){ + if(cc.Browser.isMobile){ + cc.canvas.height = this._ele.clientHeight+500; + window.location.href="#bottom"; + } }, + _initScreenSize:function(){ + this._screenSize.width = this._ele.clientWidth; + this._screenSize.height = this._ele.clientHeight; + if(navigator.userAgent.match(/iPhone/i)){ + this._screenSize.height +=(this._screenSize.width/320)*60; + } + }, _adjustSize:function () { - this._screenSize = cc.size(this._ele.clientWidth, this._ele.clientHeight); + this._scrollToBottom(); + this._initScreenSize(); cc.canvas.width = this._screenSize.width; cc.canvas.height = this._screenSize.height; @@ -269,19 +290,23 @@ cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{ setDesignResolutionSize:function (width, height, resolutionPolicy) { cc.Assert(resolutionPolicy !== cc.RESOLUTION_POLICY.UNKNOWN, "should set resolutionPolicy"); - if (!this._initialize) { - this.initialize(); - } - if (width == 0 || height == 0) return; - if ((width != null) && (height != null)) + if ((width != null) && (height != null)){ this._designResolutionSize = cc.size(width, height); + } if (resolutionPolicy != null) this._resolutionPolicy = resolutionPolicy; + if (!this._initialize) { + this.initialize(); + return; + } + + + this._scaleX = this._screenSize.width / this._designResolutionSize.width; this._scaleY = this._screenSize.height / this._designResolutionSize.height; From ed7dc5257607ce7e749b9213f236a5c15d2338a0 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 27 Aug 2013 15:45:14 +0800 Subject: [PATCH 066/141] fixed #2725: Implement unloadPlist function of cc.SAXParser --- cocos2d/platform/CCSAXParser.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cocos2d/platform/CCSAXParser.js b/cocos2d/platform/CCSAXParser.js index 9654aef41e..58f729bd32 100644 --- a/cocos2d/platform/CCSAXParser.js +++ b/cocos2d/platform/CCSAXParser.js @@ -200,6 +200,15 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ cc.Assert("cocos2d:Your browser does not support XMLHTTP."); }, + /** + * Unload the preloaded plist from xmlList + * @param {String} filePath + */ + unloadPlist:function(filePath){ + if (this._xmlDict.hasOwnProperty(filePath)) + delete this._xmlDict[filePath]; + }, + /** * get filename from filepath * @param {String} filePath From b6370ebdaf5cbbc0342dc664b8002feadad41ada Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 27 Aug 2013 15:53:08 +0800 Subject: [PATCH 067/141] issue #1088: add onResLoadingErr for preload file --- cocos2d/platform/CCFileUtils.js | 69 ++++++++++++++++----------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/cocos2d/platform/CCFileUtils.js b/cocos2d/platform/CCFileUtils.js index ad90b6d610..4d1ba82d65 100644 --- a/cocos2d/platform/CCFileUtils.js +++ b/cocos2d/platform/CCFileUtils.js @@ -192,6 +192,8 @@ cc.FileUtils = cc.Class.extend({ var fileContents = cc._convertResponseBodyToText(xhr["responseBody"]); if (fileContents) selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents); + } else { + cc.Loader.getInstance().onResLoadingErr(fileUrl); } cc.Loader.getInstance().onResLoaded(); } @@ -199,11 +201,17 @@ cc.FileUtils = cc.Class.extend({ } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=x-user-defined"); - xhr.onload = function (e) { - var arrayStr = xhr.responseText; - if (arrayStr) { + + xhr.onreadystatechange = function (event) { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + var fileContents = xhr.responseText; + if (fileContents) + selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(fileContents); + } else { + cc.Loader.getInstance().onResLoadingErr(fileUrl); + } cc.Loader.getInstance().onResLoaded(); - selfPointer._fileDataCache[fileUrl] = selfPointer._stringConvertToArray(arrayStr); } }; } @@ -263,55 +271,44 @@ cc.FileUtils = cc.Class.extend({ if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { // IE-specific logic here xhr.setRequestHeader("Accept-Charset", "utf-8"); - xhr.onreadystatechange = function (event) { - if (xhr.readyState == 4) { - if (xhr.status == 200) { - var fileContents = xhr.responseText; - if (fileContents) - selfPointer._textFileCache[fileUrl] = fileContents; - } - cc.Loader.getInstance().onResLoaded(); - } - }; } else { if (xhr.overrideMimeType) xhr.overrideMimeType("text\/plain; charset=utf-8"); - xhr.onload = function (e) { - if (xhr.responseText) { - cc.Loader.getInstance().onResLoaded(); - selfPointer._textFileCache[fileUrl] = xhr.responseText; - } - }; } + xhr.onreadystatechange = function (event) { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + var fileContents = xhr.responseText; + if (fileContents) + selfPointer._textFileCache[fileUrl] = fileContents; + } else { + cc.Loader.getInstance().onResLoadingErr(fileUrl); + } + cc.Loader.getInstance().onResLoaded(); + } + }; xhr.send(null); }, _loadTextFileData:function (fileUrl) { var req = this._getXMLHttpRequest(); req.open('GET', fileUrl, false); - var arrayInfo = null; + var fileContents = null; if (/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) { req.setRequestHeader("Accept-Charset", "utf-8"); - req.send(null); - if (req.status != 200) - return null; - - var fileContents = req.responseText; - if (fileContents) { - arrayInfo = fileContents; - this._textFileCache[fileUrl] = fileContents; - } } else { if (req.overrideMimeType) req.overrideMimeType('text\/plain; charset=utf-8'); - req.send(null); - if (req.status != 200) - return null; + } + req.send(null); + if (req.status != 200) + return null; - arrayInfo = req.responseText; - this._textFileCache[fileUrl] = arrayInfo; + fileContents = req.responseText; + if (fileContents) { + this._textFileCache[fileUrl] = fileContents; } - return arrayInfo; + return fileContents; }, /** From f4de13c0b82ce84f717b6e147c25ae21e58790d6 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 29 Aug 2013 11:29:39 +0800 Subject: [PATCH 068/141] closed #2741: Modify LabelTTF's rendering from direct draw to pre-render --- cocos2d/CCDirector.js | 2 +- cocos2d/base_nodes/CCNode.js | 3 +- cocos2d/label_nodes/CCLabelTTF.js | 462 +++++++++++++--------- cocos2d/support/CCNotificationCenter.js | 1 - cocos2d/text_input_node/CCTextFieldTTF.js | 6 +- 5 files changed, 278 insertions(+), 196 deletions(-) diff --git a/cocos2d/CCDirector.js b/cocos2d/CCDirector.js index 9b7a3dcc44..3e727378df 100644 --- a/cocos2d/CCDirector.js +++ b/cocos2d/CCDirector.js @@ -770,6 +770,7 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ setOpenGLView:function (openGLView) { // set size this._winSizeInPoints = cc.size(cc.canvas.width, cc.canvas.height); //this._openGLView.getDesignResolutionSize(); + this._openGLView = openGLView || cc.EGLView.getInstance(); if (cc.renderContextType === cc.CANVAS) return; @@ -785,7 +786,6 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ //if (this._openGLView != openGLView) { // because EAGLView is not kind of CCObject - this._openGLView = openGLView || cc.EGLView.getInstance(); this._createStatsLabel(); diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 1c0bd68ebd..b1d6a76239 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -3762,7 +3762,8 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ }, getColor:function(){ - return this._realColor; + var locRealColor = this._realColor; + return new cc.Color3B(locRealColor.r, locRealColor.g, locRealColor.b); }, getDisplayedColor:function(){ diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index b642548e9b..c237a95c7e 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -38,7 +38,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ _dimensions:null, _hAlignment:cc.TEXT_ALIGNMENT_CENTER, _vAlignment:cc.VERTICAL_TEXT_ALIGNMENT_TOP, - _fontName:"Arial", + _fontName: null, _fontSize:0.0, _string:"", _isMultiLine:false, @@ -60,13 +60,21 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ // font tint _textFillColor:null, + _strokeShadowOffsetX:0, + _strokeShadowOffsetY:0, + _originalPosition:null, + _needUpdateTexture:false, + + _labelCanvas:null, + _labelContext:null, + /** * Constructor */ ctor:function () { cc.Sprite.prototype.ctor.call(this); this._dimensions = cc.SizeZero(); - this._hAlignment = cc.TEXT_ALIGNMENT_CENTER; + this._hAlignment = cc.TEXT_ALIGNMENT_LEFT; this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; this._opacityModifyRGB = false; this._fontStyleStr = ""; @@ -85,11 +93,16 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._strokeColorStr = ""; this._textFillColor = cc.white(); + this._strokeShadowOffsetX = 0; + this._strokeShadowOffsetY = 0; + this._originalPosition = cc.PointZero(); + this._needUpdateTexture = false; + this._setColorStyleStr(); }, init:function () { - return this.initWithString([" ", this._fontName, this._fontSize]); + return this.initWithString(" ", this._fontName, this._fontSize); }, /** * Prints out a description of this class @@ -103,16 +116,21 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this.setFontFillColor(color3, true); }, + getColor:function(){ + return this._textFillColor; + }, + setOpacity:function (opacity) { if (this._opacity === opacity) return; cc.Sprite.prototype.setOpacity.call(this, opacity); this._setColorStyleStr(); + this._needUpdateTexture = true; }, _setColorStyleStr:function () { var locFillColor = this._textFillColor; - this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._realOpacity / 255 + ")"; + this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")"; }, /** @@ -165,46 +183,36 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ /** * initializes the cc.LabelTTF with a font name, alignment, dimension and font size - * @param {String} initialize string + * @param {String} label string * @param {String} fontName * @param {Number} fontSize - * @param {cc.Size} dimensions - * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment + * @param {cc.Size} [dimensions=] + * @param {Number} [hAlignment=] + * @param {Number} [vAlignment=] * @return {Boolean} return false on error */ - initWithString:function (arg) { - var strInfo = arg[0] + "", fontName, fontSize, dimensions, hAlignment, vAlignment; + initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { + var strInfo = label + ""; cc.Assert(strInfo != null, "cc.LabelTTF.initWithString() label is null"); - if (arg.length == 6) { - fontName = arg[1]; - fontSize = arg[2]; - dimensions = arg[3]; - hAlignment = arg[4]; - vAlignment = arg[5]; - } else if (arg.length == 5) { - fontName = arg[1]; - fontSize = arg[2]; - dimensions = arg[3]; - hAlignment = arg[4]; - vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; - } else { - fontName = arg[1] || "Arial"; - fontSize = arg[2] || 16; - dimensions = cc.size(0, arg[2]); - hAlignment = cc.TEXT_ALIGNMENT_LEFT; - vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM; - } + + fontSize = fontSize || 16; + dimensions = dimensions || cc.size(0, fontSize); + hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT; + vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP; if (cc.Sprite.prototype.init.call(this)) { this._opacityModifyRGB = false; this._dimensions = cc.size(dimensions.width, dimensions.height); - this._fontName = fontName; + this._fontName = fontName || "Arial"; this._hAlignment = hAlignment; this._vAlignment = vAlignment; this._fontSize = fontSize * cc.CONTENT_SCALE_FACTOR(); this._fontStyleStr = this._fontSize + "px '" + fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize); this.setString(strInfo); + this._setColorStyleStr(); + this._updateTexture(); + this._needUpdateTexture = false; return true; } @@ -212,6 +220,169 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ }, /// ---- common properties end ---- + _getLabelContext:function () { + if (this._labelContext) + return this._labelContext; + + if (!this._labelCanvas) { + var locCanvas = document.createElement("canvas"); + var labelTexture = new cc.Texture2D(); + labelTexture.initWithElement(locCanvas); + this.setTexture(labelTexture); + this._labelCanvas = locCanvas; + } + this._labelContext = this._labelCanvas.getContext("2d"); + return this._labelContext; + }, + + _updateTexture:function () { + var locContext = this._getLabelContext(); + var locContentSize = this._contentSize; + + if(this._string.length === 0){ + this._labelCanvas.width = 1; + this._labelCanvas.height = locContentSize.height; + this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height)); + return true; + } + + //set size for labelCanvas + locContext.font = this._fontStyleStr; + this._updateTTF(); + var width = locContentSize.width, height = locContentSize.height; + this._labelCanvas.width = width; + this._labelCanvas.height = height; + + //draw text to labelCanvas + this._drawTTFInCanvas(locContext); + this._texture.handleLoadedTexture(); + + this.setTextureRect(cc.rect(0, 0, width, height)); + return true; + }, + + _drawTTFInCanvas: function (context) { + if (!context) + return; + + var locContentSizeHeight = this._contentSize.height, locVAlignment = this._vAlignment, locHAlignment = this._hAlignment, + locFontHeight = this._fontClientHeight; + + context.setTransform(1, 0, 0, 1, 0, locContentSizeHeight); + //this is fillText for canvas + if (context.font != this._fontStyleStr) + context.font = this._fontStyleStr; + context.fillStyle = this._colorStyleStr; + + //stroke style setup + var locStrokeEnabled = this._strokeEnabled; + if (locStrokeEnabled) { + context.lineWidth = this._strokeSize; + context.strokeStyle = this._strokeColorStr; + } + + var isNegForOffsetX = false, isNegForOffsetY = false; + //shadow style setup + if (this._shadowEnabled) { + var locShadowOffset = this._shadowOffset; + context.shadowColor = "rgba(128,128,128,1)"; + isNegForOffsetX = locShadowOffset.width < 0; + isNegForOffsetY = locShadowOffset.height < 0; + context.shadowOffsetX = locShadowOffset.width; + context.shadowOffsetY = -locShadowOffset.height; + context.shadowBlur = this._shadowBlur; + } + + context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment]; + context.textAlign = cc.LabelTTF._textAlign[locHAlignment]; + + var xOffset = 0, locStrokeShadowOffsetX = this._strokeShadowOffsetX, locStrokeShadowOffsetY = this._strokeShadowOffsetY; + var yOffset = 0; + var locContentWidth = this._contentSize.width - locStrokeShadowOffsetX; + if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT) + xOffset = isNegForOffsetX ? locContentWidth + locStrokeShadowOffsetX : locContentWidth; + else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER) + xOffset = isNegForOffsetX ? locContentWidth / 2 + locStrokeShadowOffsetX : locContentWidth / 2; + else + xOffset = isNegForOffsetX ? locStrokeShadowOffsetX : 0; + if (this._isMultiLine) { + var locStrLen = this._strings.length; + if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM){ + yOffset = locFontHeight + locContentSizeHeight - locFontHeight * locStrLen; + if(isNegForOffsetY) + yOffset -= locStrokeShadowOffsetY; + } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER){ + yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * locStrLen) / 2; + if(isNegForOffsetY) + yOffset -= locStrokeShadowOffsetY; + } else{ + if(isNegForOffsetY) + yOffset -= locStrokeShadowOffsetY/2; + else + yOffset += locStrokeShadowOffsetY/2; + } + + for (var i = 0; i < locStrLen; i++) { + var line = this._strings[i]; + var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset; + if (locStrokeEnabled) + context.strokeText(line, xOffset, tmpOffsetY); + context.fillText(line, xOffset, tmpOffsetY); + } + } else { + if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) { + yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY : 0; + if (locStrokeEnabled) + context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); + } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) { + yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY/2 -locContentSizeHeight : - locContentSizeHeight + locStrokeShadowOffsetY/2; + if (locStrokeEnabled) + context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); + } else { + yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY -locContentSizeHeight / 2 : - locContentSizeHeight / 2; + if (locStrokeEnabled) + context.strokeText(this._string, xOffset, yOffset); + context.fillText(this._string, xOffset, yOffset); + } + } + }, + + visit:function(){ + if(!this._string || this._string == "") + return; + + if(this._needUpdateTexture ){ + this._needUpdateTexture = false; + this._updateTexture(); + } + cc.Sprite.prototype.visit.call(this); + }, + + setPosition:function(posX, posY){ + if (arguments.length == 2) + this._originalPosition = cc.p(posX, posY); + else + this._originalPosition = cc.p(posX.x, posX.y); + + //get real position + var locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0; + if(this._strokeEnabled) + locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2; + if(this._shadowEnabled){ + var locOffsetSize = this._shadowOffset; + locStrokeShadowOffsetX += locOffsetSize.width> 0?0:locOffsetSize.width; + locStrokeShadowOffsetY += locOffsetSize.height>0?0:locOffsetSize.height; + } + var realPosition = cc.p(this._originalPosition.x + locStrokeShadowOffsetX, this._originalPosition.y + locStrokeShadowOffsetY); + cc.Sprite.prototype.setPosition.call(this, realPosition); + }, + + getPosition:function(){ + return cc.p(this._originalPosition.x, this._originalPosition.y); + }, + /** * initializes the CCLabelTTF with a font name, alignment, dimension and font size * @param {String} text @@ -270,6 +441,8 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ if (this._shadowBlur != shadowBlur) this._shadowBlur = shadowBlur; + + this._needUpdateTexture = true; }, /** @@ -279,6 +452,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ disableShadow:function(mustUpdateTexture){ if (this._shadowEnabled) { this._shadowEnabled = false; + this._needUpdateTexture = true; } }, @@ -299,7 +473,9 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ } if (this._strokeSize!== strokeSize) - this._strokeSize = strokeSize; + this._strokeSize = strokeSize || 0; + + this._needUpdateTexture = true; }, /** @@ -309,6 +485,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ disableStroke:function(mustUpdateTexture){ if (this._strokeEnabled){ this._strokeEnabled = false; + this._needUpdateTexture = true; } }, @@ -322,6 +499,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b){ this._textFillColor = tintColor; this._setColorStyleStr(); + this._needUpdateTexture = true; } }, @@ -346,6 +524,9 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ // fill color this.setFontFillColor(textDefinition.fontFillColor, false); + + if (mustUpdateTexture) + this._updateTexture(); }, _prepareTextDefinition:function(adjustForResolution){ @@ -400,8 +581,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._string = text + ""; // Force update - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, @@ -414,8 +594,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._hAlignment = alignment; // Force update - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, @@ -428,8 +607,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._vAlignment = verticalAlignment; // Force update - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, @@ -442,8 +620,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._dimensions = dim; // Force udpate - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, @@ -457,8 +634,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); // Force update - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, @@ -467,29 +643,25 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ * @param {String} fontName */ setFontName:function (fontName) { - if (this._fontName != fontName) { - this._fontName = new String(fontName); + if (this._fontName != fontName ) { + this._fontName = fontName; this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); // Force update - if (this._string.length > 0) - this._updateTTF(); + this._needUpdateTexture = true; } }, _updateTTF:function () { - var context = cc.renderContext; - if (context.font != this._fontStyleStr) - context.font = this._fontStyleStr; - // we need to find out if the label needs multiline, if its automatic new line or specified newline - var stringWidth = context.measureText(this._string).width; - var locDimensionsWidth = this._dimensions.width; - if (this._string.indexOf('\n') !== -1 || (locDimensionsWidth !== 0 && stringWidth > locDimensionsWidth && this._string.indexOf(" ") !== -1)) { + var locDimensionsWidth = this._dimensions.width, locLabelContext = this._labelContext; + + var stringWidth = locLabelContext.measureText(this._string).width; + if(this._string.indexOf('\n') !== -1 || (locDimensionsWidth !== 0 && stringWidth > locDimensionsWidth && this._string.indexOf(" ") !== -1)) { var strings = this._strings = this._string.split('\n'); var lineWidths = this._lineWidths = []; for (var i = 0; i < strings.length; i++) { if (strings[i].indexOf(" ") !== -1 && locDimensionsWidth > 0) { - var percent = locDimensionsWidth / context.measureText(this._strings[i]).width; + var percent = locDimensionsWidth / locLabelContext.measureText(this._strings[i]).width; var startSearch = 0 | (percent * strings[i].length + 1); var cutoff = startSearch; var tempLineWidth = 0; @@ -497,7 +669,7 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ do { cutoff = strings[i].lastIndexOf(" ", cutoff - 1); var str = strings[i].substring(0, cutoff); - tempLineWidth = context.measureText(str).width; + tempLineWidth = locLabelContext.measureText(str).width; if (cutoff === -1) { cutoff = strings[i].indexOf(" ", startSearch); break; @@ -508,122 +680,46 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ strings[i] = str; } } - lineWidths[i] = tempLineWidth || context.measureText(strings[i]).width; + lineWidths[i] = tempLineWidth || locLabelContext.measureText(strings[i]).width; } this._isMultiLine = true; } else this._isMultiLine = false; - // we will need to change contentSize to cater this - //if dimension is not set, set contentSize according to actual size + var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0; + if(this._strokeEnabled) + locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2; + if(this._shadowEnabled){ + var locOffsetSize = this._shadowOffset; + locStrokeShadowOffsetX += Math.abs(locOffsetSize.width); + locStrokeShadowOffsetY += Math.abs(locOffsetSize.height); + } + + //get offset for stroke and shadow if (locDimensionsWidth === 0) { if (this._isMultiLine) - this.setContentSize(cc.size(Math.max.apply(Math, this._lineWidths), this._fontClientHeight * this._strings.length)); + locSize = cc.size(Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); else - this.setContentSize(cc.size(stringWidth, this._fontClientHeight)); + locSize = cc.size(stringWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); } else { - if(this._dimensions.height === 0) { + if(this._dimensions.height === 0){ if (this._isMultiLine) - this.setContentSize(cc.size(locDimensionsWidth, this._fontClientHeight * this._strings.length)); + locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); else - this.setContentSize(cc.size(locDimensionsWidth, this._fontClientHeight)); + locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); } else { //dimension is already set, contentSize must be same as dimension - this.setContentSize(cc.size(locDimensionsWidth, this._dimensions.height)); + locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._dimensions.height + locStrokeShadowOffsetY); } } + this.setContentSize(locSize); + this._strokeShadowOffsetX = locStrokeShadowOffsetX; + this._strokeShadowOffsetY = locStrokeShadowOffsetY; + this._anchorPointInPoints.x = this._contentSize.width * this._anchorPoint.x; this._anchorPointInPoints.y = this._contentSize.height * this._anchorPoint.y; - }, - /** - * renders the label - * @param {CanvasRenderingContext2D|Null} ctx - */ - draw:function (ctx) { - if(!this._string || this._string == "") - return; - var context = ctx || cc.renderContext; - if (this._flipX) - context.scale(-1, 1); - if (this._flipY) - context.scale(1, -1); - - //this is fillText for canvas - context.fillStyle = this._colorStyleStr; - - if (context.font != this._fontStyleStr) - context.font = this._fontStyleStr; - - //stroke style setup - var locStrokeEnabled = this._strokeEnabled; - if(locStrokeEnabled){ - context.lineWidth = this._strokeSize * 2; - context.strokeStyle = this._strokeColorStr; - } - - //shadow style setup - if(this._shadowEnabled){ - var locShadowOffset = this._shadowOffset; - context.shadowColor = "rgba(128,128,128,1)"; - context.shadowOffsetX = locShadowOffset.width; - context.shadowOffsetY = -locShadowOffset.height; - context.shadowBlur = this._shadowBlur; - } - - var locVAlignment = this._vAlignment, locHAlignment = this._hAlignment, - locContentSizeWidth = this._contentSize.width, locContentSizeHeight = this._contentSize.height; - var locFontHeight = this._fontClientHeight; - - context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment]; - context.textAlign = cc.LabelTTF._textAlign[locHAlignment]; - var xoffset = 0; - if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT) - xoffset = locContentSizeWidth; - else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER) - xoffset = locContentSizeWidth / 2; - if (this._isMultiLine) { - var locStrings = this._strings; - var yOffset = 0, strLen = this._strings.length; - if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) - yOffset = locFontHeight + locContentSizeHeight - locFontHeight * strLen; - else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER) - yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * strLen) / 2; - - var tmpLineStr = null, tmpYOffset = null; - for (var i = 0; i < strLen; i++) { - tmpLineStr = locStrings[i]; - tmpYOffset = -locContentSizeHeight + (locFontHeight * i) + yOffset; - if(locStrokeEnabled) - context.strokeText(tmpLineStr, xoffset, tmpYOffset); - context.fillText(tmpLineStr, xoffset, tmpYOffset); - } - } else { - if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM){ - if(locStrokeEnabled) - context.strokeText(this._string, xoffset, 0); - context.fillText(this._string, xoffset, 0); - }else if(locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP){ - if(locStrokeEnabled) - context.strokeText(this._string, xoffset, -locContentSizeHeight); - context.fillText(this._string, xoffset, -locContentSizeHeight); - }else{ - if(locStrokeEnabled) - context.strokeText(this._string, xoffset, -locContentSizeHeight/2); - context.fillText(this._string, xoffset, -locContentSizeHeight/2); - } - } - - if (cc.SPRITE_DEBUG_DRAW === 1) { - context.fillStyle = "rgba(255,0,0,0.2)"; - context.lineWidth = 1; - context.shadowColor = ""; - context.shadowOffsetX = 0; - context.shadowOffsetY = 0; - context.shadowBlur = 0; - context.fillRect(this._offsetPosition.x, this._offsetPosition.y, locContentSizeWidth, -locContentSizeHeight); - } - cc.INCREMENT_GL_DRAWS(1); + this.setPosition(this._originalPosition); } }); @@ -666,6 +762,9 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ _strokeShadowOffsetX:0, _strokeShadowOffsetY:0, _originalPosition:null, + _needUpdateTexture:false, + _labelCanvas:null, + _labelContext:null, /** * Constructor @@ -699,12 +798,13 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ this._strokeShadowOffsetX = 0; this._strokeShadowOffsetY = 0; this._originalPosition = cc.PointZero(); + this._needUpdateTexture = false; this._setColorStyleStr(); }, init:function () { - return this.initWithString([" ", this._fontName, this._fontSize]); + return this.initWithString(" ", this._fontName, this._fontSize); }, /** * Prints out a description of this class @@ -714,15 +814,9 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ return ""; }, - setOpacity:function (opacity) { - if (this._opacity === opacity) - return; - cc.Sprite.prototype.setOpacity.call(this, opacity); - this._setColorStyleStr(); - }, - _setColorStyleStr:function () { - this._colorStyleStr = "rgba(" + this._color.r + "," + this._color.g + "," + this._color.b + ", " + this._opacity / 255 + ")"; + var locFillColor = this._textFillColor; + this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")"; }, /** @@ -775,40 +869,27 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ /** * initializes the cc.LabelTTF with a font name, alignment, dimension and font size - * @param {String} initialize string + * @param {String} label string * @param {String} fontName * @param {Number} fontSize * @param {cc.Size} dimensions - * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment + * @param {Number} hAlignment + * @param {Number} vAlignment * @return {Boolean} return false on error */ - initWithString:function (arg) { - var strInfo = (arg[0] == undefined ) ? " " : arg[0] + "", fontName, fontSize, dimensions, hAlignment, vAlignment; + initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { + var strInfo = label + ""; cc.Assert(strInfo != null, "cc.LabelTTF.initWithString() label is null"); - if (arg.length == 6) { - fontName = arg[1]; - fontSize = arg[2]; - dimensions = arg[3]; - hAlignment = arg[4]; - vAlignment = arg[5]; - } else if (arg.length == 5) { - fontName = arg[1]; - fontSize = arg[2]; - dimensions = arg[3]; - hAlignment = arg[4]; - vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; - } else { - fontName = arg[1] || "Arial"; - fontSize = arg[2] || 16; - dimensions = cc.size(0, arg[2]); - hAlignment = cc.TEXT_ALIGNMENT_LEFT; - vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM; - } + + fontSize = fontSize || 16; + dimensions = dimensions || cc.size(0, fontSize); + hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT; + vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP; if (cc.Sprite.prototype.init.call(this)) { this._opacityModifyRGB = false; this._dimensions = cc.size(dimensions.width, dimensions.height); - this._fontName = fontName; + this._fontName = fontName || "Arial"; this._hAlignment = hAlignment; this._vAlignment = vAlignment; this._fontSize = fontSize * cc.CONTENT_SCALE_FACTOR(); @@ -873,7 +954,6 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ if (false === this._shadowEnabled) this._shadowEnabled = true; - if(this._shadowOffset){ if ((this._shadowOffset.width != shadowOffset.width) || (this._shadowOffset.height != shadowOffset.height)) { this._shadowOffset.width = shadowOffset.width; @@ -1113,7 +1193,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ //this is fillText for canvas if (context.font != this._fontStyleStr) context.font = this._fontStyleStr; - context.fillStyle = this._fillColorStr; + context.fillStyle = "rgba(255,255,255,1)"; //stroke style setup var locStrokeEnabled = this._strokeEnabled; @@ -1323,7 +1403,6 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ return true; }, - _needUpdateTexture:false, visit:function(){ if(this._needUpdateTexture ){ this._needUpdateTexture = false; @@ -1403,16 +1482,17 @@ cc.LabelTTF._textBaseline = ["top", "middle", "bottom"]; * @param {String} label * @param {String} fontName * @param {Number} fontSize - * @param {cc.Size} dimensions - * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment + * @param {cc.Size} [dimensions=cc.SIZE_ZERO] + * @param {Number} [hAlignment] + * @param {Number} [vAlignment=cc.VERTICAL_TEXT_ALIGNMENT_TOP] * @return {cc.LabelTTF|Null} * @example * // Example * var myLabel = cc.LabelTTF.create('label text', 'Times New Roman', 32, cc.size(32,16), cc.TEXT_ALIGNMENT_LEFT); */ -cc.LabelTTF.create = function (/* Multi arguments */) { +cc.LabelTTF.create = function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { var ret = new cc.LabelTTF(); - if (ret.initWithString(arguments)) + if (ret.initWithString(label, fontName, fontSize, dimensions, hAlignment, vAlignment)) return ret; return null; }; diff --git a/cocos2d/support/CCNotificationCenter.js b/cocos2d/support/CCNotificationCenter.js index 84a283aa41..60188057bf 100644 --- a/cocos2d/support/CCNotificationCenter.js +++ b/cocos2d/support/CCNotificationCenter.js @@ -126,7 +126,6 @@ cc.NotificationCenter.getInstance = function() { }; cc.NotificationObserver = cc.Class.extend({ - /** * @param {cc.Class} target * @param {String} selector diff --git a/cocos2d/text_input_node/CCTextFieldTTF.js b/cocos2d/text_input_node/CCTextFieldTTF.js index 52a16a5eb3..67f69be2db 100644 --- a/cocos2d/text_input_node/CCTextFieldTTF.js +++ b/cocos2d/text_input_node/CCTextFieldTTF.js @@ -157,7 +157,7 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ if (placeholder) { this._placeHolder = placeholder; } - return this.initWithString(this._placeHolder, dimensions, alignment, fontName, fontSize); + return this.initWithString(this._placeHolder,fontName, fontSize, dimensions, alignment); break; case 3: if (placeholder) { @@ -230,6 +230,8 @@ cc.TextFieldTTF = cc.LabelTTF.extend(/** @lends cc.TextFieldTTF# */{ // draw placeholder var color = this.getColor(); this.setColor(this._ColorSpaceHolder); + if(cc.renderContextType === cc.CANVAS) + this._updateTexture(); cc.LabelTTF.prototype.draw.call(this, context); this.setColor(color); }, @@ -400,7 +402,7 @@ cc.TextFieldTTF.create = function (placeholder, dimensions, alignment, fontName, ret = new cc.TextFieldTTF(); fontName = arguments[1]; fontSize = arguments[2]; - if (ret && ret.initWithString(["", fontName, fontSize])) { + if (ret && ret.initWithString("", fontName, fontSize)) { if (placeholder) ret.setPlaceHolder(placeholder); return ret; From ec76afe15ada206f57abc7ba7958e87e26d717af Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 29 Aug 2013 17:06:18 +0800 Subject: [PATCH 069/141] Closed 2741: Solved the problem that LabelTTF didn't work on mobile browser. --- cocos2d/label_nodes/CCLabelTTF.js | 10 +++++----- cocos2d/sprite_nodes/CCSprite.js | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index c237a95c7e..fd41ecccef 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -698,18 +698,18 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ //get offset for stroke and shadow if (locDimensionsWidth === 0) { if (this._isMultiLine) - locSize = cc.size(Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); + locSize = cc.size(0 | (Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); else - locSize = cc.size(stringWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); + locSize = cc.size(0 | (stringWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); } else { if(this._dimensions.height === 0){ if (this._isMultiLine) - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); else - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); } else { //dimension is already set, contentSize must be same as dimension - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._dimensions.height + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY)); } } this.setContentSize(locSize); diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 78b022bab7..8f14031cd3 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1335,12 +1335,16 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ var image = this._texture.getHtmlElementObj(); if (this._colorized) { context.drawImage(image, - 0, 0, locRect.width, locRect.height, + 0, 0, 0 | locRect.width, 0 | locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); } else { + try{ context.drawImage(image, - locRect.x, locRect.y, locRect.width, locRect.height, + 0 | locRect.x, 0 | locRect.y, 0 | locRect.width, 0 | locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); + }catch(ex){ + console.log(ex); + } } } else if (locContentSize.width !== 0) { var curColor = this.getColor(); From f518e85c25a1478fffeeeaa368039949980da7b2 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 29 Aug 2013 17:08:26 +0800 Subject: [PATCH 070/141] Closed #2741: remove the debug codes. --- cocos2d/sprite_nodes/CCSprite.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 8f14031cd3..15b7a80359 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1338,13 +1338,9 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ 0, 0, 0 | locRect.width, 0 | locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); } else { - try{ context.drawImage(image, 0 | locRect.x, 0 | locRect.y, 0 | locRect.width, 0 | locRect.height, flipXOffset, flipYOffset, locRect.width, locRect.height); - }catch(ex){ - console.log(ex); - } } } else if (locContentSize.width !== 0) { var curColor = this.getColor(); From e45d057d328204191eedae68f915d2158865be28 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 29 Aug 2013 17:53:19 +0800 Subject: [PATCH 071/141] Closed #2741: fixed a bug of SpriteCanvas that loading texture doesn't work when calling initWithFile --- cocos2d/sprite_nodes/CCSprite.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 15b7a80359..2903ae8c78 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -969,7 +969,6 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite"); var texture = cc.TextureCache.getInstance().textureForKey(filename); if (!texture) { - filename = cc.FileUtils.getInstance().fullPathForFilename(filename); texture = cc.TextureCache.getInstance().addImage(filename); return this.initWithTexture(texture, rect); } else { From 1372e0df5ffff2a4db4a15f82c42d1c413f3ff65 Mon Sep 17 00:00:00 2001 From: SmallJun <536762164@qq.com> Date: Fri, 30 Aug 2013 17:54:28 +0800 Subject: [PATCH 072/141] fixed #2754: Fixed the bug that _getResType error when the url of res is like "a.png?arg=value". --- cocos2d/CCLoader.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index 6bfa53e296..a5a806c2f1 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -241,6 +241,10 @@ cc.Loader = cc.Class.extend(/** @lends cc.Loader# */{ } else { var src = resInfo.src; var ext = src.substring(src.lastIndexOf(".") + 1, src.length); + + var index = ext.indexOf("?"); + if(index > 0) ext = ext.substring(0, index); + for (var resType in cc.RESOURCE_TYPE) { if (cc.RESOURCE_TYPE[resType].indexOf(ext) != -1) { return resType; From 78f08915b580c26a8c4dad0751e9af539d037cb0 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Sun, 1 Sep 2013 12:41:28 +0800 Subject: [PATCH 073/141] fixed #2760 : removeEventListener bug --- CocosDenshion/SimpleAudioEngine.js | 1 + HelloHTML5World/cocos2d.js | 1 + cocos2d/CCDirector.js | 1 + cocos2d/CCLoader.js | 1 + cocos2d/platform/jsloader.js | 33 +++++++++--------- cocos2d/textures/CCTextureCache.js | 34 +++++++++++++++++-- .../PluginX/samples/HelloSocial/cocos2d.js | 1 + template/cocos2d.js | 1 + 8 files changed, 54 insertions(+), 19 deletions(-) diff --git a/CocosDenshion/SimpleAudioEngine.js b/CocosDenshion/SimpleAudioEngine.js index 6a1b0c664f..6f399baec3 100644 --- a/CocosDenshion/SimpleAudioEngine.js +++ b/CocosDenshion/SimpleAudioEngine.js @@ -177,6 +177,7 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ sfxCache.audio.addEventListener('canplaythrough', function (e) { cc.Loader.getInstance().onResLoaded(); this.removeEventListener('canplaythrough', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }, false); sfxCache.audio.addEventListener("error", function (e) { diff --git a/HelloHTML5World/cocos2d.js b/HelloHTML5World/cocos2d.js index 30638e6410..c4c6cd9cbb 100644 --- a/HelloHTML5World/cocos2d.js +++ b/HelloHTML5World/cocos2d.js @@ -58,6 +58,7 @@ } window.addEventListener('DOMContentLoaded', function () { + this.removeEventListener('DOMContentLoaded', arguments.callee, false); //first load engine file if specified var s = d.createElement('script'); /*********Delete this section if you have packed all files into one*******/ diff --git a/cocos2d/CCDirector.js b/cocos2d/CCDirector.js index 3e727378df..d3d6ecdb72 100644 --- a/cocos2d/CCDirector.js +++ b/cocos2d/CCDirector.js @@ -1273,6 +1273,7 @@ cc.defaultFPS = 60; cc.Director._fpsImage = new Image(); cc.Director._fpsImage.addEventListener("load", function () { cc.Director._fpsImageLoaded = true; + this.removeEventListener('load', arguments.callee, false); }); cc.Director._fpsImage.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAAgCAYAAAD9qabkAAAKQ2lDQ1BJQ0MgcHJvZmlsZQAAeNqdU3dYk/cWPt/3ZQ9WQtjwsZdsgQAiI6wIyBBZohCSAGGEEBJAxYWIClYUFRGcSFXEgtUKSJ2I4qAouGdBiohai1VcOO4f3Ke1fXrv7e371/u855zn/M55zw+AERImkeaiagA5UoU8Otgfj09IxMm9gAIVSOAEIBDmy8JnBcUAAPADeXh+dLA//AGvbwACAHDVLiQSx+H/g7pQJlcAIJEA4CIS5wsBkFIAyC5UyBQAyBgAsFOzZAoAlAAAbHl8QiIAqg0A7PRJPgUA2KmT3BcA2KIcqQgAjQEAmShHJAJAuwBgVYFSLALAwgCgrEAiLgTArgGAWbYyRwKAvQUAdo5YkA9AYACAmUIszAAgOAIAQx4TzQMgTAOgMNK/4KlfcIW4SAEAwMuVzZdL0jMUuJXQGnfy8ODiIeLCbLFCYRcpEGYJ5CKcl5sjE0jnA0zODAAAGvnRwf44P5Dn5uTh5mbnbO/0xaL+a/BvIj4h8d/+vIwCBAAQTs/v2l/l5dYDcMcBsHW/a6lbANpWAGjf+V0z2wmgWgrQevmLeTj8QB6eoVDIPB0cCgsL7SViob0w44s+/zPhb+CLfvb8QB7+23rwAHGaQJmtwKOD/XFhbnauUo7nywRCMW735yP+x4V//Y4p0eI0sVwsFYrxWIm4UCJNx3m5UpFEIcmV4hLpfzLxH5b9CZN3DQCshk/ATrYHtctswH7uAQKLDljSdgBAfvMtjBoLkQAQZzQyefcAAJO/+Y9AKwEAzZek4wAAvOgYXKiUF0zGCAAARKCBKrBBBwzBFKzADpzBHbzAFwJhBkRADCTAPBBCBuSAHAqhGJZBGVTAOtgEtbADGqARmuEQtMExOA3n4BJcgetwFwZgGJ7CGLyGCQRByAgTYSE6iBFijtgizggXmY4EImFINJKApCDpiBRRIsXIcqQCqUJqkV1II/ItchQ5jVxA+pDbyCAyivyKvEcxlIGyUQPUAnVAuagfGorGoHPRdDQPXYCWomvRGrQePYC2oqfRS+h1dAB9io5jgNExDmaM2WFcjIdFYIlYGibHFmPlWDVWjzVjHVg3dhUbwJ5h7wgkAouAE+wIXoQQwmyCkJBHWExYQ6gl7CO0EroIVwmDhDHCJyKTqE+0JXoS+cR4YjqxkFhGrCbuIR4hniVeJw4TX5NIJA7JkuROCiElkDJJC0lrSNtILaRTpD7SEGmcTCbrkG3J3uQIsoCsIJeRt5APkE+S+8nD5LcUOsWI4kwJoiRSpJQSSjVlP+UEpZ8yQpmgqlHNqZ7UCKqIOp9aSW2gdlAvU4epEzR1miXNmxZDy6Qto9XQmmlnafdoL+l0ugndgx5Fl9CX0mvoB+nn6YP0dwwNhg2Dx0hiKBlrGXsZpxi3GS+ZTKYF05eZyFQw1zIbmWeYD5hvVVgq9ip8FZHKEpU6lVaVfpXnqlRVc1U/1XmqC1SrVQ+rXlZ9pkZVs1DjqQnUFqvVqR1Vu6k2rs5Sd1KPUM9RX6O+X/2C+mMNsoaFRqCGSKNUY7fGGY0hFsYyZfFYQtZyVgPrLGuYTWJbsvnsTHYF+xt2L3tMU0NzqmasZpFmneZxzQEOxrHg8DnZnErOIc4NznstAy0/LbHWaq1mrX6tN9p62r7aYu1y7Rbt69rvdXCdQJ0snfU6bTr3dQm6NrpRuoW623XP6j7TY+t56Qn1yvUO6d3RR/Vt9KP1F+rv1u/RHzcwNAg2kBlsMThj8MyQY+hrmGm40fCE4agRy2i6kcRoo9FJoye4Ju6HZ+M1eBc+ZqxvHGKsNN5l3Gs8YWJpMtukxKTF5L4pzZRrmma60bTTdMzMyCzcrNisyeyOOdWca55hvtm82/yNhaVFnMVKizaLx5balnzLBZZNlvesmFY+VnlW9VbXrEnWXOss623WV2xQG1ebDJs6m8u2qK2brcR2m23fFOIUjynSKfVTbtox7PzsCuya7AbtOfZh9iX2bfbPHcwcEh3WO3Q7fHJ0dcx2bHC866ThNMOpxKnD6VdnG2ehc53zNRemS5DLEpd2lxdTbaeKp26fesuV5RruutK10/Wjm7ub3K3ZbdTdzD3Ffav7TS6bG8ldwz3vQfTw91jicczjnaebp8LzkOcvXnZeWV77vR5Ps5wmntYwbcjbxFvgvct7YDo+PWX6zukDPsY+Ap96n4e+pr4i3z2+I37Wfpl+B/ye+zv6y/2P+L/hefIW8U4FYAHBAeUBvYEagbMDawMfBJkEpQc1BY0FuwYvDD4VQgwJDVkfcpNvwBfyG/ljM9xnLJrRFcoInRVaG/owzCZMHtYRjobPCN8Qfm+m+UzpzLYIiOBHbIi4H2kZmRf5fRQpKjKqLupRtFN0cXT3LNas5Fn7Z72O8Y+pjLk722q2cnZnrGpsUmxj7Ju4gLiquIF4h/hF8ZcSdBMkCe2J5MTYxD2J43MC52yaM5zkmlSWdGOu5dyiuRfm6c7Lnnc8WTVZkHw4hZgSl7I/5YMgQlAvGE/lp25NHRPyhJuFT0W+oo2iUbG3uEo8kuadVpX2ON07fUP6aIZPRnXGMwlPUit5kRmSuSPzTVZE1t6sz9lx2S05lJyUnKNSDWmWtCvXMLcot09mKyuTDeR55m3KG5OHyvfkI/lz89sVbIVM0aO0Uq5QDhZML6greFsYW3i4SL1IWtQz32b+6vkjC4IWfL2QsFC4sLPYuHhZ8eAiv0W7FiOLUxd3LjFdUrpkeGnw0n3LaMuylv1Q4lhSVfJqedzyjlKD0qWlQyuCVzSVqZTJy26u9Fq5YxVhlWRV72qX1VtWfyoXlV+scKyorviwRrjm4ldOX9V89Xlt2treSrfK7etI66Trbqz3Wb+vSr1qQdXQhvANrRvxjeUbX21K3nShemr1js20zcrNAzVhNe1bzLas2/KhNqP2ep1/XctW/a2rt77ZJtrWv913e/MOgx0VO97vlOy8tSt4V2u9RX31btLugt2PGmIbur/mft24R3dPxZ6Pe6V7B/ZF7+tqdG9s3K+/v7IJbVI2jR5IOnDlm4Bv2pvtmne1cFoqDsJB5cEn36Z8e+NQ6KHOw9zDzd+Zf7f1COtIeSvSOr91rC2jbaA9ob3v6IyjnR1eHUe+t/9+7zHjY3XHNY9XnqCdKD3x+eSCk+OnZKeenU4/PdSZ3Hn3TPyZa11RXb1nQ8+ePxd07ky3X/fJ897nj13wvHD0Ivdi2yW3S609rj1HfnD94UivW2/rZffL7Vc8rnT0Tes70e/Tf/pqwNVz1/jXLl2feb3vxuwbt24m3Ry4Jbr1+Hb27Rd3Cu5M3F16j3iv/L7a/eoH+g/qf7T+sWXAbeD4YMBgz8NZD+8OCYee/pT/04fh0kfMR9UjRiONj50fHxsNGr3yZM6T4aeypxPPyn5W/3nrc6vn3/3i+0vPWPzY8Av5i8+/rnmp83Lvq6mvOscjxx+8znk98ab8rc7bfe+477rfx70fmSj8QP5Q89H6Y8en0E/3Pud8/vwv94Tz+4A5JREAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfcAgcQLxxUBNp/AAAQZ0lEQVR42u2be3QVVZbGv1N17829eRLyIKAEOiISEtPhJTJAYuyBDmhWjAEx4iAGBhxA4wABbVAMWUAeykMCM+HRTcBRWkNH2l5moS0LCCrQTkYeQWBQSCAIgYRXEpKbW/XNH5zS4noR7faPEeu31l0h4dSpvc+t/Z199jkFWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhY/H9D/MR9qfKnLj/00U71aqfJn9+HCkCR/Wk36ddsgyJ/1wF4fkDfqqm9/gPsUeTnVr6a2xlQfnxdI7zs0W7irzD17Ytb2WT7EeNv/r4ox1O3Quf2QP2pgt9utwfout4FQE8AVBSlnaRmfvAURQkg2RlAbwB9AThlW5L0GaiKojhJhgOIBqDa7XaPrusdPtr5kQwF0BVAAoBIABRCKDd5aFUhRDAAw57eAOwAhKIoupft3zoqhB1AqLwuHIBut9uFt02qqvqRDJR2dAEQJj/BAOjn56dqmma+xiaECAEQAWAggLsB6A6HQ2iaZggBhBAqgEAAnQB0kzaEmT4hAITT6VQ8Ho/HJAKKECJQtr8LwD1y/A1/vcdfEUIEyfZ9AcQbYvZ942Px88L2UwlJR0dH0EMPPbRj5syZPUeNGrXR7Xb/641xIwJ1XY9NSUlZm52dfW+XLl1w8uRJzJ8//+OGhoYJqqqe1TSt1Wsm9NN1PSIqKmr12rVrR5WUlHy1bdu2AQCumWc3IYRD1/UwVVXnFRQUTIuNjUVzczN2797dWFJSkq8oymZd15sAGAEnFEUJ1nX9nzIzM1dnZmZGh4SE4OTJk5g5c+Zf29vbp9pstrMej6fVOyhIhgAYU1hY+B+hoaGoqKg4XVlZea+XTULTNFdCQsLGiRMnPuR2u3UhBOV9eeDAAWXTpk095DUe6WsoyRE5OTlr0tLSAux2O/bs2cO5c+e+pijKUpIXSHaQVAGkvPLKK++6XK4OksJLCFlXV2cvKSlJBFAjhU+x2WwhHo9nUHp6+urMzMy7wsLCUF9fjxdffPHjxsbGiTab7WuPx9NiEutOuq4PyMjI+M+srKyYqKgoHD58GDNmzNjq8XhyVFU9b/q+LH7hBAEYu3PnTlZVVRFAGgCX6f/tAHoOHDjwa0p27txp/JO9e/f+QM7cipw9nfL3kQBKt2zZQpJ87rnn6mQmoHilw2EACs+cOUOSrK+vZ1NTE0nyo48+IoBpxswoBcMJ4Ndjx471kOTFixe5d+9ekqTH42H//v13A4jyzpAURfEH0H/OnDnthu1z5sw558MmFUCPWbNmnaMP3nrrLZoyDmP8Hl68eDFJ8siRI9/Yc+zYMQKYKdtAztrTrl27xptRXV1NAKMAOAyBBBA/Y8aMdpLs6Ojgxx9//E37+++//29yvFXppwvAwMcee8xjtDHsuXLlCqOjo//ia3wsfpkoALqFhoZuIckJEyackimm3dQmEMDUmpoakmRISMhhAHOHDx/eQJIbN24kgKEyMAHAFRMTs2XXrl1saWkhSZ0kp0+ffhrAr3wEW/S8efOukORLL72kA1gKYMPWrVtJkk899dRJAHeYrgsEsIQkjx8/TgDvAPjd448/3kaSb7zxBmUa7vC6z53BwcFbSHL9+vU6Sc6aNes8gF5ewWAH0PfVV18lSQL4DMBGIcQ6AKtcLleBFC2jXtFt8ODBe0iyoqKCAJYByC8qKmJDQwOzsrK+MAmqo1OnTveHhoa+GRkZ+XZkZOSWiIiIvzgcjk9mzpypkWRmZuZpmbYbGV4AgPnNzc1sa2sjgN0A5iQmJtaSZHl5OQHcb/K3s81mW0uSTU1NBFAFYFbfvn1Pk+Tbb79NAA8IIVzW42/hByA+Pz/fLR/2ZXIda05NI/z9/TeR5J49ewhgqlxTrtI0jY2NjQQw3zTLuWJiYjaUlJToS5Ys6fjkk080kwDEeAmADcA9GzZsIElGRUW9CyAWwLApU6Y0kOSKFSsog9QICGdERMTGsrIyZmVlEcC9AB4IDw/fTpLbtm0jgN94CUAnAJmVlZVcs2aNZ/LkyRdJcvbs2b4EwAkgZfPmzTxw4AABFAN4BkC6vFeUSewcAO5duXIlSTIhIaEawGMAxgKYAmAGgCS73e5vrKVk/yGythANYEhCQsIhkly+fDkBpKqqGmL6DgIALDKN/3yZpVWQZGVlJQE8aPI3KiMjo5okV61aRQAjAPQBMPfIkSN0u90EUCBtsPiFEwpgbn19PdetW2fM5N4zQ9ekpKQqkty0aRMBpMjiWM6JEydIkoqirJUFJ6iq6pAPVy8A6cZMehMBUACEuVyuFwG8HBwcPEIWx367ZMkSjSQXLVrUJouTRorrkAHdA8BdQogsAOsKCwtJkmPGjDkvMw2bDDo/ADEjRoz4XylyFbm5uY0mAbjLyyZ/AOOrq6tZVlbWsWDBgo69e/eyoqKCgwcPPg4gSQaoIRbp27dvN7KF+tLSUr28vJwFBQXtMpvpYRIM7+wrAkDeqVOnePbsWQIoNKfzpiXPg8uXLydJJicnNwF4f+nSpW6STEtLq5fjYwhk1wkTJtSQ5Ouvv04AqTKj+N2xY8dIkgEBAW/Ie1v8wncRegwZMmQvSfbr12+3Ua33WqPfOWbMmP0kWVpaSgCDZAqcfejQIWNZsEGKgvnh9gfQb9myZd8nAEJVVZtMkUNk8CcNHTq0liR1XWdYWNhmH1mJIme80OnTp18x1rp5eXkEsNJms92Fb7e/IgEsvHz5Mp999tkmAI/l5uZeMC0B7vEqqAYAyL106RJJsra2lpWVld+sucePH38ZQG+5NncBeOrgwYMkqbe3t/Po0aOsra011wAWyl0H7x0JJ4DE+fPnu0kyPT29DsDdUrBuyNKEEAkAdpw/f/6GeoEM8GUmfwEgPCIiopwkGxsbabPZPgOw6L777vvm4p49e26VGYjFLxUhhD+ApLKyMp44ccIoVnXybgbgzkcfffRzklyzZg0BDJYCMMmoCwQFBXkLgLGWvvcWAgBToSsKwNPTp09vMR7UuLi4rwH0lgU8c/Db5ezbeeTIkRWzZ8++aMxu+fn5BPCADBwHgP4LFy701NXVEUAJgAnPP/98kyxMNgHo53A4zH77BQQETMvPz7+Um5vbBuAlAFMSExPPmdbVL0qh8Acw8fDhw5SCchVAEYAVb775JknyhRdeaJYztHfxMwLAaqNwCGC2FArv8x0hAHKNLGPKlCme5OTk/Zs3bzb7O0wKiiG8KXl5ed8IxenTp0mSR48e1UmyW7duWywBuD2xyQcgFECgoih+8H1gyJgZV5Lkyy+/3CbTRIePtl2HDBmyw1QBHyGDdXZdXR1JUghRKkXBjOMHCoBdpr0L3nvvPZLkF198wejo6O0A4lVVDTb74HQ6AwD8Wq7Jh8rgGgDgQ13XjVR8qaxJuADMbmlpYXl5uV5UVNRWUFDgfv/993Vj/ZydnU1c37eHXML4S3viAcQqitJD2l104cIFY8lTKsXSBWBMVVWVcd9yed2A1NTUQ6Zl00CvLMMOoHdubm6zFIlWOf5+PsY/Kj09vdrU11QAwwGsv3jxIk21m2DZr10I0RXAuAcffPBgaWkpV69eTYfDcdiwUxY0w6xw+flX8L1xApjevXv3lREREaW6rofB93aPDUDQpEmTMgHgtddeqwBwEd/utZvpqK6uPgEAcXFxkA94NwB9unfvjrNnz4LklwDcf08iIqv66Zs2bXrl4YcfxooVKxAbG7uqrq5uAYA2TdOEqqpGYIi2tjbl6aeffu/YsWPv5uTk7JaC1wHg4Pnz542MwoVvTx+21dbWYvjw4WLixIl+2dnZ9lGjRgmSTE1NRUpKCkwFTGiaxtTU1OXTpk3707Bhw/6g67pDipnT4biuj7qut+Lbk3Vf1tTUXI9qu91Pjq1QFEUBgJaWFgBo8yGOQ8eNGxcAAOvXr/8QwBUfYygAKL169eoCABcuXACAWtn2hOGv0+kMNO1KiPDw8F4A4rZv3/7R1KlTR0+bNu1ht9u9r1+/fqitrQXJgwDarRC6/QjPzs4+QJIffPCB9/aQmSAA43ft2mW0e1QGoi8CAPyLsZccExNTC2BlRkbGRdOyYJCP2csBIN6UAZzCd7cBbQCijYp/dXU1ExMTz6SmptaMHj36f9LS0vYlJCRsl6mxIWSdu3fv/g5J7t+/nwC2AShMTk6+SJKff/45AWRLYbD7+fndAeDf5BJnLoCCyZMnt5JkdnZ2C4B/F0KEm1Pu+Pj4rST55ZdfEsBWAK+mpaVdMo3raDn7KwDuSEpK+m+S3LBhAwG8DuCtHTt2UBbpjgC408vvcFVV15HkuXPnjMp+p5uMf0RcXNyHJNnQ0EBVVfcCWBQXF3fG+Jv0yxABPwB5LS0tRmFxN4BlTzzxxGWSXLx4sS5F3GGFy+1Hp5SUlJq6ujoWFxdTpsZ2H+0iIyMj/0iSWVlZX5mr5jfJFroPGzasxlhTnjp1iiTZ3NxMl8tlrCd9pfa9SkpKSJI5OTmnZOageLUZZqxvfVFWVkZcPwdgNwnSCKPqb17jkmR8fPzfZMDZ5CRsFBmNI7h95s2b1yhT7/MAYmStwCx4vy0uLqa3v5qmEcCfvSr1QQAeXb16NY3Cm3HQ55133iGAp+SxZTNhKSkpfzUddkrFjYevzAQCeGjp0qXfsYckY2NjTwD4leGDLCL2HTdunNtoY+zWSHFcIHdsFCtcfuZ1vO9Eqs3m7/F47sb1k2qX/f3997W2tl7BjWfpBYDOzzzzzIVJkyZh0KBBCwEsB3AJvl9AETabLcDj8dwRFRW1ctasWb8JCgpSzp07d62wsPC/Wltb8xRFadR1/ZqPXYbgAQMGbI2Pjw/+6quv9ldVVT0r01ezuPRJSUn5Y9euXXVd11WzDaqq6kePHm3+7LPPRgO4KlNuxWazhXo8nuTk5OSXMjIyEl0uFxoaGtqKior+dPXq1VdUVT0jj7r68ieoT58+vx8yZMjdx48fP1JVVTVF9m20VW02WyfZf97YsWPjXS4X6urqWvPy8jYCWCyEuEDS8FdVFKWzruv//OSTTy5OTk7uqWkaPv3007qysrJ8RVH+LI8ym8/rB3Tu3HnRI488knLo0KG2ffv2ZQI4C98vP6mqqoZqmpaclpa2cOTIkX39/f3R0NDQUVxc/G5TU9PLqqrWa5rWLH1QVFUN0TStX1JSUvH48eP7BwYG4uDBg1cKCgpeBbBe2u+2Qug2EwD5N5sMPuNtMe8XP4TT6Qxoa2sbIGeXvUKIK7d4IISiKC5d1wPljOfA9bPwzYqiXNV13dd6Uqiq6qdpml2mpe02m63d4/G4vcTF5fF47LJf71nJA6BZVVW3pmntuPHlmAD5wk6Q9NnbHp9vHaqq6tA0zU/64PZhk1FfCZB9G/23ALiqKEqzD39tpvbGUqoFwFUhRLP3yzpCCDtJpxyXDulfG27+pqRR3DXsUWVd4Yq0x/taVQjhIhksC8L+ABpM9ljBf5sKwI8pIBr75L5E4vvu+UNeG/a+hv+AL7yFH8qPtOfHjtOP6V/Bja8D6z/B2Nys/1u9Xv33tLf4GfF/LC4GCJwByWIAAAAASUVORK5CYII="; diff --git a/cocos2d/CCLoader.js b/cocos2d/CCLoader.js index 6bfa53e296..6e62d676a1 100644 --- a/cocos2d/CCLoader.js +++ b/cocos2d/CCLoader.js @@ -416,6 +416,7 @@ cc.LoaderScene = cc.Scene.extend(/** @lends cc.LoaderScene# */{ var _this = this; this._logoTexture.addEventListener("load", function () { _this._initStage(centerPos); + this.removeEventListener('load', arguments.callee, false); }); this._logoTexture.src = "data:image/jpeg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAAlAAD/4QMpaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjAtYzA2MCA2MS4xMzQ3NzcsIDIwMTAvMDIvMTItMTc6MzI6MDAgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjM4MDBEMDY2QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjM4MDBEMDY1QTU1MjExRTFBQTAzQjEzMUNFNzMxRkQwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzUgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU2RTk0OEM4OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU2RTk0OEM5OERCNDExRTE5NEUyRkE3M0M3QkE1NTlEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+/+4ADkFkb2JlAGTAAAAAAf/bAIQADQkJCQoJDQoKDRMMCwwTFhENDREW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"; this._logoTexture.width = 160; diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index d8546fd53d..df804a8cd5 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -267,26 +267,28 @@ if(p>=1) { loadJsImg.parentNode.removeChild(loadJsImg); } - } + }; var loaded = 0; var que = engine.concat(c.appFiles); que.push('main.js'); + if (navigator.userAgent.indexOf("Trident/5") > -1) { //ie9 - this.serial = -1; + var i = -1; var loadNext = function () { - var s = this.serial + 1; - if (s < que.length) { + i++; + if (i < que.length) { var f = d.createElement('script'); - f.src = que[s]; - f.serial = s; - f.onload = loadNext; + f.src = que[i]; + f.addEventListener('load',function(){ + loadNext(); + updateLoading(loaded / que.length); + this.removeEventListener('load', arguments.callee, false); + },false); d.body.appendChild(f); - //TODO: code for updating progress bar } - var p = s / (que.length - 1); - updateLoading(p); + updateLoading(i / (que.length - 1)); }; loadNext(); } @@ -295,15 +297,12 @@ var s = d.createElement('script'); s.async = false; s.src = f; - s.onload = function () { + s.addEventListener('load',function(){ loaded++; - //TODO: code for updating progress bar - var p = loaded / que.length; - updateLoading(p); - }; + updateLoading(loaded / que.length); + this.removeEventListener('load', arguments.callee, false); + },false); d.body.appendChild(s); - que[i] = s; - }); } })(); diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index e59158e110..f1abdbaaaa 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -43,9 +43,10 @@ cc.loadImage = function (imageUrl) { } var image = new Image(); image.src = imageUrl; - image.onLoad = function (e) { + image.addEventListener('load',function(){ cc.TextureCache.getInstance().cacheImage(imageUrl, image); - }; + this.removeEventListener('load', arguments.callee, false); + },false); }; /** @@ -287,6 +288,7 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ image.addEventListener("load", function () { texture.handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); + this.removeEventListener('load', arguments.callee, false); }); } } else { @@ -298,12 +300,16 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); + this.removeEventListener('load', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }); image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; + + this.removeEventListener('error', arguments.callee, false); }); image.src = path; var texture2d = new cc.Texture2D(); @@ -340,6 +346,7 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ image.addEventListener("load", function () { texture.handleLoadedTexture(); cc.Loader.getInstance().onResLoaded(); + this.removeEventListener('load', arguments.callee, false); }); } } else { @@ -351,12 +358,16 @@ cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ cc.Loader.getInstance().onResLoaded(); if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); + this.removeEventListener('load', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }); image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; + + this.removeEventListener('error', arguments.callee, false); }); image.src = path; var texture2d = new cc.Texture2D(); @@ -698,6 +709,8 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ image.addEventListener("load", function () { texture.handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); + + this.removeEventListener('load', arguments.callee, false); }); } } else { @@ -709,12 +722,17 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); + + this.removeEventListener('load', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }); image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; + + this.removeEventListener('error', arguments.callee, false); }); image.src = path; var texture2d = new cc.Texture2D(); @@ -732,10 +750,15 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Loader.getInstance().onResLoaded(); that._loadedTexturesBefore[path] = texture; delete that._loadingTexturesBefore[path]; + + this.removeEventListener('load', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }); texture.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); delete that._loadingTexturesBefore[path]; + + this.removeEventListener('error', arguments.callee, false); }); texture.src = path; this._loadingTexturesBefore[path] = texture; @@ -770,6 +793,8 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ image.addEventListener("load", function () { texture.handleLoadedTexture(); cc.Loader.getInstance().onResLoaded(); + + this.removeEventListener('load', arguments.callee, false); }); } } else { @@ -781,12 +806,17 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Loader.getInstance().onResLoaded(); if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); + + this.removeEventListener('load', arguments.callee, false); + this.removeEventListener('error', arguments.callee, false); }); image.addEventListener("error", function () { cc.Loader.getInstance().onResLoadingErr(path); //remove from cache if (that._textures.hasOwnProperty(path)) delete that._textures[path]; + + this.removeEventListener('error', arguments.callee, false); }); image.src = path; diff --git a/extensions/PluginX/samples/HelloSocial/cocos2d.js b/extensions/PluginX/samples/HelloSocial/cocos2d.js index f3f3a40733..851a010f79 100644 --- a/extensions/PluginX/samples/HelloSocial/cocos2d.js +++ b/extensions/PluginX/samples/HelloSocial/cocos2d.js @@ -60,6 +60,7 @@ window.addEventListener('DOMContentLoaded', function () { + this.removeEventListener('DOMContentLoaded', arguments.callee, false); //first load engine file if specified var s = d.createElement('script'); /*********Delete this section if you have packed all files into one*******/ diff --git a/template/cocos2d.js b/template/cocos2d.js index 47358d580a..26f3954ca6 100644 --- a/template/cocos2d.js +++ b/template/cocos2d.js @@ -58,6 +58,7 @@ window.addEventListener('DOMContentLoaded', function () { + this.removeEventListener('DOMContentLoaded', arguments.callee, false); //first load engine file if specified var s = d.createElement('script'); /*********Delete this section if you have packed all files into one*******/ From 70590f9f230759cf185c157d045e3e0859d22441 Mon Sep 17 00:00:00 2001 From: guozhuc Date: Mon, 2 Sep 2013 16:47:45 +0800 Subject: [PATCH 074/141] fix for simple audio enginee loading and playing error on browser that doesn't support audio tag --- CocosDenshion/SimpleAudioEngine.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CocosDenshion/SimpleAudioEngine.js b/CocosDenshion/SimpleAudioEngine.js index 6a1b0c664f..b87f2ba4bd 100644 --- a/CocosDenshion/SimpleAudioEngine.js +++ b/CocosDenshion/SimpleAudioEngine.js @@ -195,8 +195,9 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ cc.Loader.getInstance().onResLoaded(); } } - - //cc.Loader.getInstance().onResLoaded(); + else { + cc.Loader.getInstance().onResLoaded(); + } }, /** @@ -208,6 +209,9 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * cc.AudioEngine.getInstance().playMusic(path, false); */ playMusic:function (path, loop) { + if (!this._soundEnable) + return; + var keyname = this._getPathWithoutExt(path); var extName = this._getExtFromFullPath(path); var au; @@ -370,6 +374,9 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * var soundId = cc.AudioEngine.getInstance().playEffect(path); */ playEffect:function (path, loop) { + if (!this._soundEnable) + return; + var keyname = this._getPathWithoutExt(path), actExt; if (this._soundList.hasOwnProperty(keyname)) { actExt = this._soundList[keyname].ext; From dd8e32b696a5f0d8831228534d52a5a234a1aa45 Mon Sep 17 00:00:00 2001 From: WanderWang Date: Mon, 2 Sep 2013 20:39:15 +0800 Subject: [PATCH 075/141] Update CCLabelTTF.js add param context to method visit() --- cocos2d/label_nodes/CCLabelTTF.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index fd41ecccef..66e8b83353 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -349,15 +349,15 @@ cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ } }, - visit:function(){ + visit:function(ctx){ if(!this._string || this._string == "") return; - if(this._needUpdateTexture ){ this._needUpdateTexture = false; this._updateTexture(); } - cc.Sprite.prototype.visit.call(this); + var context = ctx || cc.renderContext; + cc.Sprite.prototype.visit.call(this,context); }, setPosition:function(posX, posY){ From 27cfe60ad0de21656828da196b76d284f873e982 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 3 Sep 2013 10:56:20 +0800 Subject: [PATCH 076/141] Closed #2514: Migrate CCBReader to Cocos2d-x v2.1.4 --- cocos2d/base_nodes/CCNode.js | 7 - cocos2d/platform/CCTypes.js | 215 ++++++++++-------- extensions/CCBReader/CCBAnimationManager.js | 93 +++++--- extensions/CCBReader/CCBReader.js | 182 ++++++++------- extensions/CCBReader/CCBReaderUtil.js | 8 +- .../CCBReader/CCBRelativePositioning.js | 39 +++- extensions/CCBReader/CCBSequence.js | 1 - extensions/CCBReader/CCNodeLoader.js | 46 ++-- extensions/CCBReader/CCSpriteLoader.js | 123 +++++----- 9 files changed, 395 insertions(+), 319 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index b1d6a76239..040ae3bc6f 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -3715,13 +3715,6 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ this._cascadeOpacityEnabled = false; }, - init:function(){ - if(cc.Node.prototype.init.call(this)){ - return true; - } - return false; - }, - getOpacity:function(){ return this._realOpacity; }, diff --git a/cocos2d/platform/CCTypes.js b/cocos2d/platform/CCTypes.js index 05b2e22836..8658a80a4e 100644 --- a/cocos2d/platform/CCTypes.js +++ b/cocos2d/platform/CCTypes.js @@ -458,7 +458,6 @@ cc.Quad2 = function (tl1, tr1, bl1, br1) { * @param {cc.Vertex3F} tr1 */ cc.Quad3 = function (bl1, br1, tl1, tr1) { - //TODO need redefine by ArrayBuffer this.bl = bl1 || new cc.Vertex3F(0, 0, 0); this.br = br1 || new cc.Vertex3F(0, 0, 0); this.tl = tl1 || new cc.Vertex3F(0, 0, 0); @@ -608,7 +607,7 @@ cc.V3F_C4B_T2F_QuadZero = function () { cc.V3F_C4B_T2F_QuadCopy = function (sourceQuad) { if (!sourceQuad) return cc.V3F_C4B_T2F_QuadZero(); - + var tl = sourceQuad.tl, bl = sourceQuad.bl, tr = sourceQuad.tr, br = sourceQuad.br; return new cc.V3F_C4B_T2F_Quad( new cc.V3F_C4B_T2F(new cc.Vertex3F(sourceQuad.tl.vertices.x, sourceQuad.tl.vertices.y, sourceQuad.tl.vertices.z), new cc.Color4B(sourceQuad.tl.colors.r, sourceQuad.tl.colors.g, sourceQuad.tl.colors.b, sourceQuad.tl.colors.a), @@ -718,10 +717,11 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Color4B.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._rU8 = new Uint8Array(this._arrayBuffer, this._offset, 1); - this._gU8 = new Uint8Array(this._arrayBuffer, this._offset + Uint8Array.BYTES_PER_ELEMENT, 1); - this._bU8 = new Uint8Array(this._arrayBuffer, this._offset + Uint8Array.BYTES_PER_ELEMENT * 2, 1); - this._aU8 = new Uint8Array(this._arrayBuffer, this._offset + Uint8Array.BYTES_PER_ELEMENT * 3, 1); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = Uint8Array.BYTES_PER_ELEMENT; + this._rU8 = new Uint8Array(locArrayBuffer, locOffset, 1); + this._gU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen, 1); + this._bU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen * 2, 1); + this._aU8 = new Uint8Array(locArrayBuffer, locOffset + locElementLen * 3, 1); this._rU8[0] = r || 0; this._gU8[0] = g || 0; @@ -769,17 +769,18 @@ if(cc.Browser.supportWebGL){ }); //redefine cc.Color4F - cc.Color4F = function(r,g,b,a, arrayBuffer, offset){ + cc.Color4F = function (r, g, b, a, arrayBuffer, offset) { this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Color4F.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._rF32 = new Float32Array(this._arrayBuffer,this._offset, 1); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = Float32Array.BYTES_PER_ELEMENT; + this._rF32 = new Float32Array(locArrayBuffer, locOffset, 1); this._rF32[0] = r || 0; - this._gF32 = new Float32Array(this._arrayBuffer,this._offset + Float32Array.BYTES_PER_ELEMENT, 1); + this._gF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen, 1); this._gF32[0] = g || 0; - this._bF32 = new Float32Array(this._arrayBuffer,this._offset + Float32Array.BYTES_PER_ELEMENT * 2, 1); + this._bF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen * 2, 1); this._bF32[0] = b || 0; - this._aF32 = new Float32Array(this._arrayBuffer,this._offset + Float32Array.BYTES_PER_ELEMENT * 3, 1); + this._aF32 = new Float32Array(locArrayBuffer, locOffset + locElementLen * 3, 1); this._aF32[0] = a || 0; }; cc.Color4F.BYTES_PER_ELEMENT = 16; @@ -859,11 +860,12 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Vertex3F.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._xF32 = new Float32Array(this._arrayBuffer, this._offset, 1); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset; + this._xF32 = new Float32Array(locArrayBuffer, locOffset, 1); this._xF32[0] = x || 0; - this._yF32 = new Float32Array(this._arrayBuffer, this._offset + Float32Array.BYTES_PER_ELEMENT, 1); + this._yF32 = new Float32Array(locArrayBuffer, locOffset + Float32Array.BYTES_PER_ELEMENT, 1); this._yF32[0] = y || 0; - this._zF32 = new Float32Array(this._arrayBuffer, this._offset + Float32Array.BYTES_PER_ELEMENT * 2, 1); + this._zF32 = new Float32Array(locArrayBuffer, locOffset + Float32Array.BYTES_PER_ELEMENT * 2, 1); this._zF32[0] = z || 0; }; cc.Vertex3F.BYTES_PER_ELEMENT = 12; @@ -934,13 +936,11 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.Quad2.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._tl = tl ? new cc.Vertex2F(tl.x, tl.y, this._arrayBuffer, 0) : new cc.Vertex2F(0, 0, this._arrayBuffer, 0); - this._tr = tr ? new cc.Vertex2F(tr.x, tr.y, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT) : - new cc.Vertex2F(0, 0, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT); - this._bl = bl ? new cc.Vertex2F(bl.x, bl.y, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT * 2) : - new cc.Vertex2F(0, 0, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT * 2); - this._br = br ? new cc.Vertex2F(br.x, br.y, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT * 3) : - new cc.Vertex2F(0, 0, this._arrayBuffer, cc.Vertex2F.BYTES_PER_ELEMENT * 3); + var locArrayBuffer = this._arrayBuffer, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT; + this._tl = tl ? new cc.Vertex2F(tl.x, tl.y, locArrayBuffer, 0) : new cc.Vertex2F(0, 0, locArrayBuffer, 0); + this._tr = tr ? new cc.Vertex2F(tr.x, tr.y, locArrayBuffer, locElementLen) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen); + this._bl = bl ? new cc.Vertex2F(bl.x, bl.y, locArrayBuffer, locElementLen * 2) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen * 2); + this._br = br ? new cc.Vertex2F(br.x, br.y, locArrayBuffer, locElementLen * 3) : new cc.Vertex2F(0, 0, locArrayBuffer, locElementLen * 3); }; cc.Quad2.BYTES_PER_ELEMENT = 32; Object.defineProperties(cc.Quad2.prototype, { @@ -991,12 +991,13 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._vertices = vertices ? new cc.Vertex3F(vertices.x, vertices.y, vertices.z, this._arrayBuffer, this._offset) : - new cc.Vertex3F(0, 0, 0, this._arrayBuffer, this._offset); - this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, this._arrayBuffer, this._offset + cc.Vertex3F.BYTES_PER_ELEMENT) : - new cc.Color4B(0, 0, 0, 0, this._arrayBuffer, this._offset + cc.Vertex3F.BYTES_PER_ELEMENT); - this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, this._arrayBuffer, this._offset + cc.Vertex3F.BYTES_PER_ELEMENT + cc.Color4B.BYTES_PER_ELEMENT) : - new cc.Tex2F(0, 0, this._arrayBuffer, this._offset + cc.Vertex3F.BYTES_PER_ELEMENT + cc.Color4B.BYTES_PER_ELEMENT); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex3F.BYTES_PER_ELEMENT; + this._vertices = vertices ? new cc.Vertex3F(vertices.x, vertices.y, vertices.z, locArrayBuffer, locOffset) : + new cc.Vertex3F(0, 0, 0, locArrayBuffer, locOffset); + this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset + locElementLen) : + new cc.Color4B(0, 0, 0, 0, locArrayBuffer, locOffset + locElementLen); + this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT) : + new cc.Tex2F(0, 0, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT); }; cc.V3F_C4B_T2F.BYTES_PER_ELEMENT = 24; Object.defineProperties(cc.V3F_C4B_T2F.prototype, { @@ -1005,9 +1006,10 @@ if(cc.Browser.supportWebGL){ return this._vertices; }, set: function (verticesValue) { - this._vertices.x = verticesValue.x; - this._vertices.y = verticesValue.y; - this._vertices.z = verticesValue.z; + var locVertices = this._vertices; + locVertices.x = verticesValue.x; + locVertices.y = verticesValue.y; + locVertices.z = verticesValue.z; }, enumerable: true }, @@ -1016,10 +1018,11 @@ if(cc.Browser.supportWebGL){ return this._colors; }, set: function (colorValue) { - this._colors.r = colorValue.r; - this._colors.g = colorValue.g; - this._colors.b = colorValue.b; - this._colors.a = colorValue.a; + var locColors = this._colors; + locColors.r = colorValue.r; + locColors.g = colorValue.g; + locColors.b = colorValue.b; + locColors.a = colorValue.a; }, enumerable: true }, @@ -1040,14 +1043,15 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._tl = tl ? new cc.V3F_C4B_T2F(tl.vertices, tl.colors, tl.texCoords, this._arrayBuffer, this._offset) : - new cc.V3F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset); - this._bl = bl ? new cc.V3F_C4B_T2F(bl.vertices, bl.colors, bl.texCoords, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT) : - new cc.V3F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT); - this._tr = tr ? new cc.V3F_C4B_T2F(tr.vertices, tr.colors, tr.texCoords, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT * 2) : - new cc.V3F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT * 2); - this._br = br ? new cc.V3F_C4B_T2F(br.vertices, br.colors, br.texCoords, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT * 3) : - new cc.V3F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset + cc.V3F_C4B_T2F.BYTES_PER_ELEMENT * 3); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V3F_C4B_T2F.BYTES_PER_ELEMENT; + this._tl = tl ? new cc.V3F_C4B_T2F(tl.vertices, tl.colors, tl.texCoords, locArrayBuffer, locOffset) : + new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset); + this._bl = bl ? new cc.V3F_C4B_T2F(bl.vertices, bl.colors, bl.texCoords, locArrayBuffer, locOffset + locElementLen) : + new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen); + this._tr = tr ? new cc.V3F_C4B_T2F(tr.vertices, tr.colors, tr.texCoords, locArrayBuffer, locOffset + locElementLen * 2) : + new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 2); + this._br = br ? new cc.V3F_C4B_T2F(br.vertices, br.colors, br.texCoords, locArrayBuffer, locOffset + locElementLen * 3) : + new cc.V3F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 3); }; cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT = 96; Object.defineProperties(cc.V3F_C4B_T2F_Quad.prototype, { @@ -1056,9 +1060,10 @@ if(cc.Browser.supportWebGL){ return this._tl; }, set: function (tlValue) { - this._tl.vertices = tlValue.vertices; - this._tl.colors = tlValue.colors; - this._tl.texCoords = tlValue.texCoords; + var locTl = this._tl; + locTl.vertices = tlValue.vertices; + locTl.colors = tlValue.colors; + locTl.texCoords = tlValue.texCoords; }, enumerable: true }, @@ -1067,9 +1072,10 @@ if(cc.Browser.supportWebGL){ return this._bl; }, set: function (blValue) { - this._bl.vertices = blValue.vertices; - this._bl.colors = blValue.colors; - this._bl.texCoords = blValue.texCoords; + var locBl = this._bl; + locBl.vertices = blValue.vertices; + locBl.colors = blValue.colors; + locBl.texCoords = blValue.texCoords; }, enumerable: true }, @@ -1078,9 +1084,10 @@ if(cc.Browser.supportWebGL){ return this._tr; }, set: function (trValue) { - this._tr.vertices = trValue.vertices; - this._tr.colors = trValue.colors; - this._tr.texCoords = trValue.texCoords; + var locTr = this._tr; + locTr.vertices = trValue.vertices; + locTr.colors = trValue.colors; + locTr.texCoords = trValue.texCoords; }, enumerable: true }, @@ -1089,9 +1096,10 @@ if(cc.Browser.supportWebGL){ return this._br; }, set: function (brValue) { - this._br.vertices = brValue.vertices; - this._br.colors = brValue.colors; - this._br.texCoords = brValue.texCoords; + var locBr = this._br; + locBr.vertices = brValue.vertices; + locBr.colors = brValue.colors; + locBr.texCoords = brValue.texCoords; }, enumerable: true }, @@ -1111,19 +1119,20 @@ if(cc.Browser.supportWebGL){ return cc.V3F_C4B_T2F_QuadZero(); //return new cc.V3F_C4B_T2F_Quad(sourceQuad,tl,sourceQuad,bl,sourceQuad.tr,sourceQuad.br,null,0); + var srcTL = sourceQuad.tl, srcBL = sourceQuad.bl, srcTR = sourceQuad.tr, srcBR = sourceQuad.br; return { - tl: {vertices: {x: sourceQuad.tl.vertices.x, y: sourceQuad.tl.vertices.y, z: sourceQuad.tl.vertices.z}, - colors: {r: sourceQuad.tl.colors.r, g: sourceQuad.tl.colors.g, b: sourceQuad.tl.colors.b, a: sourceQuad.tl.colors.a}, - texCoords: {u: sourceQuad.tl.texCoords.u, v: sourceQuad.tl.texCoords.v}}, - bl: {vertices: {x: sourceQuad.bl.vertices.x, y: sourceQuad.bl.vertices.y, z: sourceQuad.bl.vertices.z}, - colors: {r: sourceQuad.bl.colors.r, g: sourceQuad.bl.colors.g, b: sourceQuad.bl.colors.b, a: sourceQuad.bl.colors.a}, - texCoords: {u: sourceQuad.bl.texCoords.u, v: sourceQuad.bl.texCoords.v}}, - tr: {vertices: {x: sourceQuad.tr.vertices.x, y: sourceQuad.tr.vertices.y, z: sourceQuad.tr.vertices.z}, - colors: {r: sourceQuad.tr.colors.r, g: sourceQuad.tr.colors.g, b: sourceQuad.tr.colors.b, a: sourceQuad.tr.colors.a}, - texCoords: {u: sourceQuad.tr.texCoords.u, v: sourceQuad.tr.texCoords.v}}, - br: {vertices: {x: sourceQuad.br.vertices.x, y: sourceQuad.br.vertices.y, z: sourceQuad.br.vertices.z}, - colors: {r: sourceQuad.br.colors.r, g: sourceQuad.br.colors.g, b: sourceQuad.br.colors.b, a: sourceQuad.br.colors.a}, - texCoords: {u: sourceQuad.br.texCoords.u, v: sourceQuad.br.texCoords.v}} + tl: {vertices: {x: srcTL.vertices.x, y: srcTL.vertices.y, z: srcTL.vertices.z}, + colors: {r: srcTL.colors.r, g: srcTL.colors.g, b: srcTL.colors.b, a: srcTL.colors.a}, + texCoords: {u: srcTL.texCoords.u, v: srcTL.texCoords.v}}, + bl: {vertices: {x: srcBL.vertices.x, y: srcBL.vertices.y, z: srcBL.vertices.z}, + colors: {r: srcBL.colors.r, g: srcBL.colors.g, b: srcBL.colors.b, a: srcBL.colors.a}, + texCoords: {u: srcBL.texCoords.u, v: srcBL.texCoords.v}}, + tr: {vertices: {x: srcTR.vertices.x, y: srcTR.vertices.y, z: srcTR.vertices.z}, + colors: {r: srcTR.colors.r, g: srcTR.colors.g, b: srcTR.colors.b, a: srcTR.colors.a}, + texCoords: {u: srcTR.texCoords.u, v: srcTR.texCoords.v}}, + br: {vertices: {x: srcBR.vertices.x, y: srcBR.vertices.y, z: srcBR.vertices.z}, + colors: {r: srcBR.colors.r, g: srcBR.colors.g, b: srcBR.colors.b, a: srcBR.colors.a}, + texCoords: {u: srcBR.texCoords.u, v: srcBR.texCoords.v}} }; }; @@ -1132,12 +1141,13 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._vertices = vertices ? new cc.Vertex2F(vertices.x, vertices.y, this._arrayBuffer, this._offset) : - new cc.Vertex2F(0, 0, this._arrayBuffer, this._offset); - this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, this._arrayBuffer, this._offset + cc.Vertex2F.BYTES_PER_ELEMENT) : - new cc.Color4B(0, 0, 0, 0, this._arrayBuffer, this._offset + cc.Vertex2F.BYTES_PER_ELEMENT); - this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, this._arrayBuffer, this._offset + cc.Vertex2F.BYTES_PER_ELEMENT + cc.Color4B.BYTES_PER_ELEMENT) : - new cc.Tex2F(0, 0, this._arrayBuffer, this._offset + cc.Vertex2F.BYTES_PER_ELEMENT + cc.Color4B.BYTES_PER_ELEMENT); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.Vertex2F.BYTES_PER_ELEMENT; + this._vertices = vertices ? new cc.Vertex2F(vertices.x, vertices.y, locArrayBuffer, locOffset) : + new cc.Vertex2F(0, 0, locArrayBuffer, locOffset); + this._colors = colors ? new cc.Color4B(colors.r, colors.g, colors.b, colors.a, locArrayBuffer, locOffset + locElementLen) : + new cc.Color4B(0, 0, 0, 0, locArrayBuffer, locOffset + locElementLen); + this._texCoords = texCoords ? new cc.Tex2F(texCoords.u, texCoords.v, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT) : + new cc.Tex2F(0, 0, locArrayBuffer, locOffset + locElementLen + cc.Color4B.BYTES_PER_ELEMENT); }; cc.V2F_C4B_T2F.BYTES_PER_ELEMENT = 20; Object.defineProperties(cc.V2F_C4B_T2F.prototype, { @@ -1156,10 +1166,11 @@ if(cc.Browser.supportWebGL){ return this._colors; }, set: function (colorValue) { - this._colors.r = colorValue.r; - this._colors.g = colorValue.g; - this._colors.b = colorValue.b; - this._colors.a = colorValue.a; + var locColors = this._colors; + locColors.r = colorValue.r; + locColors.g = colorValue.g; + locColors.b = colorValue.b; + locColors.a = colorValue.a; }, enumerable: true }, @@ -1180,12 +1191,13 @@ if(cc.Browser.supportWebGL){ this._arrayBuffer = arrayBuffer || new ArrayBuffer(cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT); this._offset = offset || 0; - this._a = a ? new cc.V2F_C4B_T2F(a.vertices, a.colors, a.texCoords, this._arrayBuffer, this._offset) : - new cc.V2F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset); - this._b = b ? new cc.V2F_C4B_T2F(b.vertices, b.colors, b.texCoords, this._arrayBuffer, this._offset + cc.V2F_C4B_T2F.BYTES_PER_ELEMENT) : - new cc.V2F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset + cc.V2F_C4B_T2F.BYTES_PER_ELEMENT); - this._c = c ? new cc.V2F_C4B_T2F(c.vertices, c.colors, c.texCoords, this._arrayBuffer, this._offset + cc.V2F_C4B_T2F.BYTES_PER_ELEMENT * 2) : - new cc.V2F_C4B_T2F(null, null, null, this._arrayBuffer, this._offset + cc.V2F_C4B_T2F.BYTES_PER_ELEMENT * 2); + var locArrayBuffer = this._arrayBuffer, locOffset = this._offset, locElementLen = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT; + this._a = a ? new cc.V2F_C4B_T2F(a.vertices, a.colors, a.texCoords, locArrayBuffer, locOffset) : + new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset); + this._b = b ? new cc.V2F_C4B_T2F(b.vertices, b.colors, b.texCoords, locArrayBuffer, locOffset + locElementLen) : + new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen); + this._c = c ? new cc.V2F_C4B_T2F(c.vertices, c.colors, c.texCoords, locArrayBuffer, locOffset + locElementLen * 2) : + new cc.V2F_C4B_T2F(null, null, null, locArrayBuffer, locOffset + locElementLen * 2); }; cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT = 60; Object.defineProperties(cc.V2F_C4B_T2F_Triangle.prototype, { @@ -1194,9 +1206,10 @@ if(cc.Browser.supportWebGL){ return this._a; }, set: function (aValue) { - this._a.vertices = aValue.vertices; - this._a.colors = aValue.colors; - this._a.texCoords = aValue.texCoords; + var locA = this._a; + locA.vertices = aValue.vertices; + locA.colors = aValue.colors; + locA.texCoords = aValue.texCoords; }, enumerable: true }, @@ -1205,9 +1218,10 @@ if(cc.Browser.supportWebGL){ return this._b; }, set: function (bValue) { - this._b.vertices = bValue.vertices; - this._b.colors = bValue.colors; - this._b.texCoords = bValue.texCoords; + var locB = this._b; + locB.vertices = bValue.vertices; + locB.colors = bValue.colors; + locB.texCoords = bValue.texCoords; }, enumerable: true }, @@ -1216,9 +1230,10 @@ if(cc.Browser.supportWebGL){ return this._c; }, set: function (cValue) { - this._c.vertices = cValue.vertices; - this._c.colors = cValue.colors; - this._c.texCoords = cValue.texCoords; + var locC = this._c; + locC.vertices = cValue.vertices; + locC.colors = cValue.colors; + locC.texCoords = cValue.texCoords; }, enumerable: true } @@ -1311,8 +1326,9 @@ cc._Dictionary = cc.Class.extend({ if (key == null) return null; - for (var keyId in this._keyMapTb) { - if (this._keyMapTb[keyId] === key) + var locKeyMapTb = this._keyMapTb; + for (var keyId in locKeyMapTb) { + if (locKeyMapTb[keyId] === key) return this._valueMapTb[keyId]; } return null; @@ -1326,10 +1342,11 @@ cc._Dictionary = cc.Class.extend({ if (key == null) return; - for (var keyId in this._keyMapTb) { - if (this._keyMapTb[keyId] === key) { + var locKeyMapTb = this._keyMapTb; + for (var keyId in locKeyMapTb) { + if (locKeyMapTb[keyId] === key) { delete this._valueMapTb[keyId]; - delete this._keyMapTb[keyId]; + delete locKeyMapTb[keyId]; return; } } @@ -1344,9 +1361,9 @@ cc._Dictionary = cc.Class.extend({ }, allKeys: function () { - var keyArr = []; - for (var key in this._keyMapTb) - keyArr.push(this._keyMapTb[key]); + var keyArr = [], locKeyMapTb = this._keyMapTb; + for (var key in locKeyMapTb) + keyArr.push(locKeyMapTb[key]); return keyArr; }, diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/CCBReader/CCBAnimationManager.js index 0f67fb02ce..82867a3528 100644 --- a/extensions/CCBReader/CCBAnimationManager.js +++ b/extensions/CCBReader/CCBAnimationManager.js @@ -177,7 +177,9 @@ cc.BuilderAnimationManager = cc.Class.extend({ }, getRunningSequenceName:function () { - return this._runningSequence.getName(); + if(this._runningSequence) + return this._runningSequence.getName(); + return null; }, getContainerSize:function (node) { @@ -201,17 +203,19 @@ cc.BuilderAnimationManager = cc.Class.extend({ moveAnimationsFromNode:function(fromNode,toNode){ // Move base values - var baseValue = this._baseValues.objectForKey(fromNode); + var locBaseValues = this._baseValues; + var baseValue = locBaseValues.objectForKey(fromNode); if(baseValue != null) { - this._baseValues.setObject(baseValue, toNode); - this._baseValues.removeObjectForKey(fromNode); + locBaseValues.setObject(baseValue, toNode); + locBaseValues.removeObjectForKey(fromNode); } // Move seqs - var seqs = this._nodeSequences.objectForKey(fromNode); + var locNodeSequences = this._nodeSequences; + var seqs = locNodeSequences.objectForKey(fromNode); if(seqs != null) { - this._nodeSequences.setObject(seqs, toNode); - this._nodeSequences.removeObjectForKey(fromNode); + locNodeSequences.setObject(seqs, toNode); + locNodeSequences.removeObjectForKey(fromNode); } }, @@ -296,24 +300,24 @@ cc.BuilderAnimationManager = cc.Class.extend({ return cc.Sequence.create(actions); }, + runAnimationsForSequenceNamed:function(name){ - this.runAnimations(name); + this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), 0); }, - runAnimations:function (name, tweenDuration) { + runAnimationsForSequenceNamedTweenDuration:function(name, tweenDuration){ + this.runAnimationsForSequenceIdTweenDuration(this._getSequenceId(name), tweenDuration); + }, + + runAnimationsForSequenceIdTweenDuration:function(nSeqId, tweenDuration){ tweenDuration = tweenDuration || 0; - var nSeqId; - if(typeof(name) === "string") - nSeqId = this._getSequenceId(name); - else - nSeqId = name; cc.Assert(nSeqId != -1, "Sequence id couldn't be found"); this._rootNode.stopAllActions(); var allKeys = this._nodeSequences.allKeys(); - for(var i = 0 ; i< allKeys.length;i++){ + for(var i = 0,len = allKeys.length ; i< len;i++){ var node = allKeys[i]; node.stopAllActions(); @@ -353,10 +357,11 @@ cc.BuilderAnimationManager = cc.Class.extend({ cc.CallFunc.create(this._sequenceCompleted,this)); this._rootNode.runAction(completeAction); - // Playback callbacks and sounds + // Playback callbacks and sounds + var action; if (seq.getCallbackChannel()) { // Build sound actions for channel - var action = this.getActionForCallbackChannel(seq.getCallbackChannel()); + action = this.getActionForCallbackChannel(seq.getCallbackChannel()); if (action) { this._rootNode.runAction(action); } @@ -364,15 +369,26 @@ cc.BuilderAnimationManager = cc.Class.extend({ if (seq.getSoundChannel()) { // Build sound actions for channel - var action = this.getActionForSoundChannel(seq.getSoundChannel()); + action = this.getActionForSoundChannel(seq.getSoundChannel()); if (action) { this._rootNode.runAction(action); } } - // Set the running scene + // Set the running scene this._runningSequence = this._getSequence(nSeqId); }, + runAnimations:function (name, tweenDuration) { + tweenDuration = tweenDuration || 0; + var nSeqId; + if(typeof(name) === "string") + nSeqId = this._getSequenceId(name); + else + nSeqId = name; + + this.runAnimationsForSequenceIdTweenDuration(nSeqId, tweenDuration); + }, + setAnimationCompletedCallback:function(target,callbackFunc){ this._target = target; this._animationCompleteCallbackFunc = callbackFunc; @@ -384,6 +400,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ setCallFunc:function(callFunc, callbackNamed) { this._keyframeCallFuncs[callbackNamed] = callFunc; }, + debug:function () { }, @@ -396,9 +413,10 @@ cc.BuilderAnimationManager = cc.Class.extend({ _getSequenceId:function (sequenceName) { var element = null; - for (var i = 0; i < this._sequences.length; i++) { - element = this._sequences[i]; - if (element && element.getName() == sequenceName) + var locSequences = this._sequences; + for (var i = 0, len = locSequences.length; i < len; i++) { + element = locSequences[i]; + if (element && element.getName() === sequenceName) return element.getSequenceId(); } return -1; @@ -406,8 +424,9 @@ cc.BuilderAnimationManager = cc.Class.extend({ _getSequence:function (sequenceId) { var element = null; - for (var i = 0; i < this._sequences.length; i++) { - element = this._sequences[i]; + var locSequences = this._sequences; + for (var i = 0, len = locSequences.length; i < len; i++) { + element = locSequences[i]; if (element && element.getSequenceId() === sequenceId) return element; } @@ -449,7 +468,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ var containerSize = this.getContainerSize(node.getParent()); - var absPos = cc.getAbsolutePosition(cc.p(x,y), type,containerSize,propName); + var absPos = cc._getAbsolutePosition(x,y, type,containerSize,propName); return cc.MoveTo.create(duration,absPos); } else if( propName === "scale"){ @@ -461,8 +480,13 @@ cc.BuilderAnimationManager = cc.Class.extend({ x = getValueArr[0]; y = getValueArr[1]; - if(type == CCB_SCALETYPE_MULTIPLY_RESOLUTION) - var resolutionScale = cc.BuilderReader.getResolutionScale(); + if(type === CCB_SCALETYPE_MULTIPLY_RESOLUTION){ + //TODO need to test + var resolutionScale = cc.BuilderReader.getResolutionScale(); + x *= resolutionScale; + y *= resolutionScale; + } + return cc.ScaleTo.create(duration,x,y); } else if( propName === "skew") { //get relative position @@ -496,7 +520,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ x = value[0]; y = value[1]; - node.setPosition(cc.getAbsolutePosition(cc.p(x,y),nType, this.getContainerSize(node.getParent()),propName)); + node.setPosition(cc._getAbsolutePosition(x,y,nType, this.getContainerSize(node.getParent()),propName)); }else if(propName === "scale"){ getArr = this._getBaseValue(node,propName); nType = getArr[2]; @@ -506,8 +530,6 @@ cc.BuilderAnimationManager = cc.Class.extend({ cc.setRelativeScale(node,x,y,nType,propName); } else if( propName === "skew") { - getArr = this._getBaseValue(node,propName); - nType = getArr[2]; x = value[0]; y = value[1]; node.setSkewX(x); @@ -537,7 +559,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ _setFirstFrame:function (node, seqProp, tweenDuration) { var keyframes = seqProp.getKeyframes(); - if (keyframes.length == 0) { + if (keyframes.length === 0) { // Use base value (no animation) var baseValue = this._getBaseValue(node, seqProp.getName()); cc.Assert(baseValue, "No baseValue found for property"); @@ -615,18 +637,19 @@ cc.BuilderAnimationManager = cc.Class.extend({ }, _sequenceCompleted:function () { - if(this._lastCompletedSequenceName != this._runningSequence.getName()){ - this._lastCompletedSequenceName = this._runningSequence.getName(); + var locRunningSequence = this._runningSequence; + if(this._lastCompletedSequenceName != locRunningSequence.getName()){ + this._lastCompletedSequenceName = locRunningSequence.getName(); } if (this._delegate) - this._delegate.completedAnimationSequenceNamed(this._runningSequence.getName()); + this._delegate.completedAnimationSequenceNamed(locRunningSequence.getName()); if(this._target && this._animationCompleteCallbackFunc){ this._animationCompleteCallbackFunc.call(this._target); } - var nextSeqId = this._runningSequence.getChainedSequenceId(); + var nextSeqId = locRunningSequence.getChainedSequenceId(); this._runningSequence = null; if (nextSeqId != -1) diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index d0ceb994e8..142da066c3 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -152,7 +152,7 @@ cc.BuilderReader = cc.Class.extend({ _ownerCallbackNames:null, _ownerCallbackNodes:null, - _hasScriptingOwner:false, + _readNodeGraphFromData:false, ctor:function (ccNodeLoaderLibrary, ccbMemberVariableAssigner, ccbSelectorResolver, ccNodeLoaderListener) { this._stringCache = []; @@ -220,17 +220,18 @@ cc.BuilderReader = cc.Class.extend({ animationManager = parentSize; parentSize = cc.Director.getInstance().getWinSize(); } - - var path = cc.FileUtils.getInstance().fullPathFromRelativePath(ccbFileName); - var data = cc.FileUtils.getInstance().getByteArrayFromFile(path); + var fileUtils = cc.FileUtils.getInstance(); + var path = fileUtils.fullPathFromRelativePath(ccbFileName); + var data = fileUtils.getByteArrayFromFile(path); return this.readNodeGraphFromData(data, owner, parentSize, animationManager); }, readNodeGraphFromData:function (data, owner, parentSize) { this.initWithData(data, owner); - this._actionManager.setRootContainerSize(parentSize); - this._actionManager.setOwner(owner); + var locActionManager = this._actionManager; + locActionManager.setRootContainerSize(parentSize); + locActionManager.setOwner(owner); this._ownerOutletNames = []; this._ownerOutletNodes = []; @@ -240,20 +241,24 @@ cc.BuilderReader = cc.Class.extend({ var nodeGraph = this.readFileWithCleanUp(true); - if (nodeGraph && this._actionManager.getAutoPlaySequenceId() != -1) { + if (nodeGraph && locActionManager.getAutoPlaySequenceId() != -1) { //auto play animations - this._actionManager.runAnimations(this._actionManager.getAutoPlaySequenceId(), 0); + locActionManager.runAnimations(locActionManager.getAutoPlaySequenceId(), 0); } if (this._jsControlled) { - this._nodesWithAnimationManagers = []; - this._animationManagerForNodes = []; + var locNodes = []; + var locAnimations = []; - var getAllKeys = this._animationManagers.allKeys(); + var locAnimationManager = this._animationManagers; + var getAllKeys = locAnimationManager.allKeys(); for (var i = 0; i < getAllKeys.length; i++) { - this._nodesWithAnimationManagers.push(getAllKeys[i]); - this._animationManagerForNodes.push(this._animationManagers.objectForKey(getAllKeys[i])); + locNodes.push(getAllKeys[i]); + locAnimations.push(locAnimationManager.objectForKey(getAllKeys[i])); } + + this._nodesWithAnimationManagers = locNodes; + this._animationManagerForNodes = locAnimations; } return nodeGraph; @@ -500,10 +505,21 @@ cc.BuilderReader = cc.Class.extend({ return node; }, + addOwnerOutletName: function(name){ + this._ownerOutletNames.push(name); + }, + + addOwnerOutletNode: function(node){ + if(node == null) + return; + + this._ownerOutletNodes.push(node); + }, + _cleanUpNodeGraph:function (node) { node.setUserObject(null); var getChildren = node.getChildren(); - for (var i = 0; i < getChildren.length; i++) { + for (var i = 0, len = getChildren.length; i < len; i++) { this._cleanUpNodeGraph(getChildren[i]); } }, @@ -515,9 +531,8 @@ cc.BuilderReader = cc.Class.extend({ return true; var channel = new cc.BuilderSequenceProperty(); - - for (var i = 0; i < numKeyframes; i++) - { + var locJsControlled = this._jsControlled, locActionManager = this._actionManager, locKeyframes = channel.getKeyframes(); + for (var i = 0; i < numKeyframes; i++) { var time = this.readFloat(); var callbackName = this.readCachedString(); var callbackType = this.readInt(false); @@ -528,10 +543,10 @@ cc.BuilderReader = cc.Class.extend({ keyframe.setTime(time); keyframe.setValue(value); - if(this._jsControlled) { - this._actionManager.getKeyframeCallbacks().push(callbackType+":"+callbackName); - } - channel.getKeyframes().push(keyframe); + if(locJsControlled) + locActionManager.getKeyframeCallbacks().push(callbackType+":"+callbackName); + + locKeyframes.push(keyframe); } // Assign to sequence @@ -543,12 +558,12 @@ cc.BuilderReader = cc.Class.extend({ _readSoundKeyframesForSeq:function(seq) { var numKeyframes = this.readInt(false); - if (!numKeyframes) return true; + if (!numKeyframes) + return true; var channel = new cc.BuilderSequenceProperty(); - - for (var i = 0; i < numKeyframes; i++) - { + var locKeyframes = channel.getKeyframes(); + for (var i = 0; i < numKeyframes; i++) { var time = this.readFloat(); var soundFile = this.readCachedString(); var pitch = this.readFloat(); @@ -560,12 +575,11 @@ cc.BuilderReader = cc.Class.extend({ keyframe.setTime(time); keyframe.setValue(value); - channel.getKeyframes().push(keyframe); + locKeyframes.push(keyframe); } // Assign to sequence seq.setSoundChannel(channel); - return true; }, _readSequences:function () { @@ -628,7 +642,8 @@ cc.BuilderReader = cc.Class.extend({ if (spriteSheet == "") { spriteFile = this._ccbRootPath + spriteFile; var texture = cc.TextureCache.getInstance().addImage(spriteFile); - var bounds = cc.RectMake(0, 0, texture.getContentSize().width, texture.getContentSize().height); + var locContentSize = texture.getContentSize(); + var bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); value = cc.SpriteFrame.createWithTexture(texture, bounds); } else { spriteSheet = this._ccbRootPath + spriteSheet; @@ -675,24 +690,21 @@ cc.BuilderReader = cc.Class.extend({ _readStringFromBytes:function (startIndex, strLen, reverse) { reverse = reverse || false; var strValue = ""; - var i; + var i, locData = this._data, locCurrentByte = this._currentByte; if (reverse) { - for (i = strLen - 1; i >= 0; i--) { - strValue += String.fromCharCode(this._data[this._currentByte + i]); - } + for (i = strLen - 1; i >= 0; i--) + strValue += String.fromCharCode(locData[locCurrentByte + i]); } else { - for (i = 0; i < strLen; i++) { - strValue += String.fromCharCode(this._data[this._currentByte + i]); - } + for (i = 0; i < strLen; i++) + strValue += String.fromCharCode(locData[locCurrentByte + i]); } return strValue; }, _readStringCache:function () { var numStrings = this.readInt(false); - for (var i = 0; i < numStrings; i++) { + for (var i = 0; i < numStrings; i++) this._readStringCacheEntry(); - } return true; }, @@ -702,9 +714,9 @@ cc.BuilderReader = cc.Class.extend({ var numBytes = b0 << 8 | b1; - var str = ""; + var str = "", locData = this._data, locCurrentByte = this._currentByte; for (var i = 0; i < numBytes; i++) { - var hexChar = this._data[this._currentByte + i].toString("16").toUpperCase(); + var hexChar = locData[locCurrentByte + i].toString("16").toUpperCase(); hexChar = hexChar.length > 1 ? hexChar : "0" + hexChar; str += "%" + hexChar; } @@ -718,8 +730,8 @@ cc.BuilderReader = cc.Class.extend({ /* Read class name. */ var className = this.readCachedString(); - var jsControlledName; - if (this._jsControlled) + var jsControlledName, locJsControlled = this._jsControlled, locActionManager = this._actionManager; + if (locJsControlled) jsControlledName = this.readCachedString(); var memberVarAssignmentType = this.readInt(false); @@ -737,19 +749,18 @@ cc.BuilderReader = cc.Class.extend({ var node = ccNodeLoader.loadCCNode(parent, this); //set root node - if (!this._actionManager.getRootNode()) - this._actionManager.setRootNode(node); + if (!locActionManager.getRootNode()) + locActionManager.setRootNode(node); - if (this._jsControlled && node == this._actionManager.getRootNode()) { - this._actionManager.setDocumentControllerName(jsControlledName); + if (locJsControlled && node == locActionManager.getRootNode()) { + locActionManager.setDocumentControllerName(jsControlledName); } - //read animated properties var seqs = new cc._Dictionary(); this._animatedProps = []; - var i; + var i, locAnimatedProps = this._animatedProps; var numSequence = this.readInt(false); for (i = 0; i < numSequence; ++i) { var seqId = this.readInt(false); @@ -762,12 +773,12 @@ cc.BuilderReader = cc.Class.extend({ seqProp.setName(this.readCachedString()); seqProp.setType(this.readInt(false)); - this._animatedProps.push(seqProp.getName()); + locAnimatedProps.push(seqProp.getName()); var numKeyframes = this.readInt(false); - + var locKeyframes = seqProp.getKeyframes(); for (var k = 0; k < numKeyframes; ++k) { var keyFrame = this.readKeyframe(seqProp.getType()); - seqProp.getKeyframes().push(keyFrame); + locKeyframes.push(keyFrame); } seqNodeProps.setObject(seqProp, seqProp.getName()); } @@ -775,31 +786,33 @@ cc.BuilderReader = cc.Class.extend({ } if (seqs.count() > 0) - this._actionManager.addNode(node, seqs); + locActionManager.addNode(node, seqs); //read properties ccNodeLoader.parseProperties(node, parent, this); //handle sub ccb files(remove middle node) - if (node instanceof cc.BuilderFile) { + var isCCBFileNode = node instanceof cc.BuilderFile; + if (isCCBFileNode) { var embeddedNode = node.getCCBFileNode(); embeddedNode.setPosition(node.getPosition()); embeddedNode.setRotation(node.getRotation()); - embeddedNode.setScale(node.getScale()); + embeddedNode.setScaleX(node.getScaleX()); + embeddedNode.setScaleY(node.getScaleY()); embeddedNode.setTag(node.getTag()); embeddedNode.setVisible(true); - embeddedNode.ignoreAnchorPointForPosition(node.isIgnoreAnchorPointForPosition()); + //embeddedNode.ignoreAnchorPointForPosition(node.isIgnoreAnchorPointForPosition()); + locActionManager.moveAnimationsFromNode(node, embeddedNode); node.setCCBFileNode(null); node = embeddedNode; } - + var target = null, locMemberAssigner = null; if (memberVarAssignmentType != CCB_TARGETTYPE_NONE) { - if (!this._jsControlled) { - var target = null; - if (memberVarAssignmentType == CCB_TARGETTYPE_DOCUMENTROOT) { - target = this._actionManager.getRootNode(); - } else if (memberVarAssignmentType == CCB_TARGETTYPE_OWNER) { + if (!locJsControlled) { + if (memberVarAssignmentType === CCB_TARGETTYPE_DOCUMENTROOT) { + target = locActionManager.getRootNode(); + } else if (memberVarAssignmentType === CCB_TARGETTYPE_OWNER) { target = this._owner; } @@ -809,15 +822,15 @@ cc.BuilderReader = cc.Class.extend({ if (target != null && (target.onAssignCCBMemberVariable)) { assigned = target.onAssignCCBMemberVariable(target, memberVarAssignmentName, node); } - - if (!assigned && this._ccbMemberVariableAssigner != null && this._ccbMemberVariableAssigner.onAssignCCBMemberVariable) { - this._ccbMemberVariableAssigner.onAssignCCBMemberVariable(target, memberVarAssignmentName, node); + locMemberAssigner = this._ccbMemberVariableAssigner; + if (!assigned && locMemberAssigner != null && locMemberAssigner.onAssignCCBMemberVariable) { + locMemberAssigner.onAssignCCBMemberVariable(target, memberVarAssignmentName, node); } } } else { if (memberVarAssignmentType == CCB_TARGETTYPE_DOCUMENTROOT) { - this._actionManager.addDocumentOutletName(memberVarAssignmentName); - this._actionManager.addDocumentOutletNode(node); + locActionManager.addDocumentOutletName(memberVarAssignmentName); + locActionManager.addDocumentOutletNode(node); } else { this._ownerOutletNames.push(memberVarAssignmentName); this._ownerOutletNodes.push(node); @@ -828,18 +841,17 @@ cc.BuilderReader = cc.Class.extend({ // Assign custom properties. if (ccNodeLoader.getCustomProperties().length > 0) { var customAssigned = false; - - if(!this._jsControlled) { - var target = node; + if(!locJsControlled) { + target = node; if(target != null && target.onAssignCCBCustomProperty != null) { var customProperties = ccNodeLoader.getCustomProperties(); var customPropKeys = customProperties.allKeys(); for(i = 0;i < customPropKeys.length;i++){ var customPropValue = customProperties.objectForKey(customPropKeys[i]); customAssigned = target.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue); - - if(!customAssigned && (this._ccbMemberVariableAssigner != null) && (this._ccbMemberVariableAssigner.onAssignCCBCustomProperty != null)) - customAssigned = this._ccbMemberVariableAssigner.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue); + locMemberAssigner = this._ccbMemberVariableAssigner; + if(!customAssigned && (locMemberAssigner != null) && (locMemberAssigner.onAssignCCBCustomProperty != null)) + customAssigned = locMemberAssigner.onAssignCCBCustomProperty(target, customPropKeys[i], customPropValue); } } } @@ -854,11 +866,15 @@ cc.BuilderReader = cc.Class.extend({ node.addChild(child); } - // Call onNodeLoaded - if (node != null && node.onNodeLoaded) { - node.onNodeLoaded(node, ccNodeLoader); - } else if (this._ccNodeLoaderListener != null) { - this._ccNodeLoaderListener.onNodeLoaded(node, ccNodeLoader); + // FIX ISSUE #1860: "onNodeLoaded will be called twice if ccb was added as a CCBFile". + // If it's a sub-ccb node, skip notification to CCNodeLoaderListener since it will be + // notified at LINE #734: CCNode * child = this->readNodeGraph(node); + if (!isCCBFileNode) { + // Call onNodeLoaded + if (node != null && node.onNodeLoaded) + node.onNodeLoaded(node, ccNodeLoader); + else if (this._ccNodeLoaderListener != null) + this._ccNodeLoaderListener.onNodeLoaded(node, ccNodeLoader); } return node; @@ -951,14 +967,21 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { var animationManager = animationManagersForNodes[i]; var j; - innerNode.animationManager = animationManager; var documentControllerName = animationManager.getDocumentControllerName(); if (!documentControllerName) continue; // Create a document controller - var controller = new _ccbGlobalContext[documentControllerName](); + var controller; + if(documentControllerName.indexOf(".") > -1){ + var controllerNameArr = documentControllerName.split("."); + controller = _ccbGlobalContext[controllerNameArr[0]]; + for(var ni = 1, niLen = controllerNameArr.length - 1; ni < niLen; ni++) + controller = controller[controllerNameArr[ni]]; + controller = new controller[controllerNameArr[controllerNameArr.length - 1]](); + }else + controller = new _ccbGlobalContext[documentControllerName](); controller.controllerName = documentControllerName; innerNode.controller = controller; @@ -988,9 +1011,8 @@ cc.BuilderReader.load = function (ccbFilePath, owner, parentSize, ccbRootPath) { controller[outletName] = outletNode; } - if (controller.onDidLoadFromCCB && typeof(controller.onDidLoadFromCCB) == "function") { + if (controller.onDidLoadFromCCB && typeof(controller.onDidLoadFromCCB) == "function") controller.onDidLoadFromCCB(); - } // Setup timeline callbacks var keyframeCallbacks = animationManager.getKeyframeCallbacks(); diff --git a/extensions/CCBReader/CCBReaderUtil.js b/extensions/CCBReader/CCBReaderUtil.js index b8c63196d6..ec327c8533 100644 --- a/extensions/CCBReader/CCBReaderUtil.js +++ b/extensions/CCBReader/CCBReaderUtil.js @@ -45,9 +45,9 @@ cc.BuilderMemberVariableAssigner = cc.Class.extend({ * @param {Object} target The custom class * @param {string} memberVariableName The name of the member variable. * @param {cc.Node} node The member variable. - * @return Whether the assignment was successful. + * @return {Boolean} Whether the assignment was successful. */ - onAssignCCBMemberVariable:function(target,memberVariableName, node){}, + onAssignCCBMemberVariable:function(target,memberVariableName, node){ return false;}, /** * The callback function of assigning custom properties. @@ -55,7 +55,7 @@ cc.BuilderMemberVariableAssigner = cc.Class.extend({ * @param {Object} target The custom class. * @param {string} memberVariableName The name of the member variable. * @param {*} value The value of the property. - * @return Whether the assignment was successful. + * @return {Boolean} Whether the assignment was successful. */ - onAssignCCBCustomProperty:function(target, memberVariableName, value){} + onAssignCCBCustomProperty:function(target, memberVariableName, value){ return false; } }); diff --git a/extensions/CCBReader/CCBRelativePositioning.js b/extensions/CCBReader/CCBRelativePositioning.js index 67948ff407..c23351eadd 100644 --- a/extensions/CCBReader/CCBRelativePositioning.js +++ b/extensions/CCBReader/CCBRelativePositioning.js @@ -26,21 +26,21 @@ cc.getAbsolutePosition = function(pt, type, containerSize, propName){ var absPt = cc.p(0,0); - if(type == CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT) + if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT) absPt = pt; - else if(type == CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){ + else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){ absPt.x = pt.x; absPt.y = containerSize.height - pt.y; - } else if(type == CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){ + } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){ absPt.x = containerSize.width - pt.x; absPt.y = containerSize.height - pt.y; - } else if (type == CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) { + } else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) { absPt.x = containerSize.width - pt.x; absPt.y = pt.y; - } else if (type == CCB_POSITIONTYPE_PERCENT) { + } else if (type === CCB_POSITIONTYPE_PERCENT) { absPt.x = (containerSize.width * pt.x / 100.0); absPt.y = (containerSize.height * pt.y / 100.0); - } else if (type == CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) { + } else if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) { var resolutionScale = cc.BuilderReader.getResolutionScale(); absPt.x = pt.x * resolutionScale; absPt.y = pt.y * resolutionScale; @@ -49,10 +49,35 @@ cc.getAbsolutePosition = function(pt, type, containerSize, propName){ return absPt; }; +cc._getAbsolutePosition = function(x, y, type, containerSize, propName){ + var absPt = cc.p(0,0); + if(type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_LEFT){ + absPt.x = x; + absPt.y = y; + } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_LEFT){ + absPt.x = x; + absPt.y = containerSize.height - y; + } else if(type === CCB_POSITIONTYPE_RELATIVE_TOP_RIGHT){ + absPt.x = containerSize.width - x; + absPt.y = containerSize.height - y; + } else if (type === CCB_POSITIONTYPE_RELATIVE_BOTTOM_RIGHT) { + absPt.x = containerSize.width - x; + absPt.y = y; + } else if (type === CCB_POSITIONTYPE_PERCENT) { + absPt.x = (containerSize.width * x / 100.0); + absPt.y = (containerSize.height * y / 100.0); + } else if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) { + var resolutionScale = cc.BuilderReader.getResolutionScale(); + absPt.x = x * resolutionScale; + absPt.y = y * resolutionScale; + } + return absPt; +}; + cc.setRelativeScale = function(node,scaleX, scaleY, type, propName){ cc.Assert(node, "pNode should not be null"); - if (type == CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) { + if (type === CCB_POSITIONTYPE_MULTIPLY_RESOLUTION) { var resolutionScale = cc.BuilderReader.getResolutionScale(); scaleX *= resolutionScale; diff --git a/extensions/CCBReader/CCBSequence.js b/extensions/CCBReader/CCBSequence.js index 4980801bf1..b991c48e4b 100644 --- a/extensions/CCBReader/CCBSequence.js +++ b/extensions/CCBReader/CCBSequence.js @@ -77,7 +77,6 @@ cc.BuilderSequence = cc.Class.extend({ setSoundChannel:function(channel) { this._soundChannel = channel; } - }); cc.BuilderSequenceProperty = cc.Class.extend({ diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/CCBReader/CCNodeLoader.js index 8e879cf9d7..d13df20fe2 100644 --- a/extensions/CCBReader/CCNodeLoader.js +++ b/extensions/CCBReader/CCNodeLoader.js @@ -82,7 +82,7 @@ cc.NodeLoader = cc.Class.extend({ var setProp = false; var platform = ccbReader.readByte(); - if ((platform == CCB_PLATFORM_ALL) ||(platform == CCB_PLATFORM_IOS) ||(platform == CCB_PLATFORM_MAC) ) + if ((platform === CCB_PLATFORM_ALL) ||(platform === CCB_PLATFORM_IOS) ||(platform === CCB_PLATFORM_MAC) ) setProp = true; //forward properties for sub ccb files @@ -106,49 +106,43 @@ cc.NodeLoader = cc.Class.extend({ case CCB_PROPTYPE_POSITION: { var position = this.parsePropTypePosition(node, parent, ccbReader, propertyName); - if (setProp) { + if (setProp) this.onHandlePropTypePosition(node, parent, propertyName, position, ccbReader); - } break; } case CCB_PROPTYPE_POINT: { var point = this.parsePropTypePoint(node, parent, ccbReader); - if (setProp) { + if (setProp) this.onHandlePropTypePoint(node, parent, propertyName, point, ccbReader); - } break; } case CCB_PROPTYPE_POINTLOCK: { var pointLock = this.parsePropTypePointLock(node, parent, ccbReader); - if (setProp) { + if (setProp) this.onHandlePropTypePointLock(node, parent, propertyName, pointLock, ccbReader); - } break; } case CCB_PROPTYPE_SIZE: { var size = this.parsePropTypeSize(node, parent, ccbReader); - if (setProp) { + if (setProp) this.onHandlePropTypeSize(node, parent, propertyName, size, ccbReader); - } break; } case CCB_PROPTYPE_SCALELOCK: { var scaleLock = this.parsePropTypeScaleLock(node, parent, ccbReader, propertyName); - if (setProp) { + if (setProp) this.onHandlePropTypeScaleLock(node, parent, propertyName, scaleLock, ccbReader); - } break; } case CCB_PROPTYPE_FLOATXY: { var xy = this.parsePropTypeFloatXY(node, parent, ccbReader); - if (setProp) { + if (setProp) this.onHandlePropTypeFloatXY(node, parent, propertyName, xy, ccbReader); - } break; } @@ -350,7 +344,7 @@ cc.NodeLoader = cc.Class.extend({ var type = ccbReader.readInt(false); var containerSize = ccbReader.getAnimationManager().getContainerSize(parent); - var pt = cc.getAbsolutePosition(cc.p(x,y),type,containerSize,propertyName); + var pt = cc._getAbsolutePosition(x,y,type,containerSize,propertyName); node.setPosition(cc.getAbsolutePosition(pt,type,containerSize,propertyName)); //different to -x node.setPosition(pt); if(ccbReader.getAnimatedProperties().indexOf(propertyName) > -1){ @@ -620,12 +614,12 @@ cc.NodeLoader = cc.Class.extend({ var selectorName = ccbReader.readCachedString(); var selectorTarget = ccbReader.readInt(false); - if (selectorTarget != CCB_TARGETTYPE_NONE) { + if (selectorTarget !== CCB_TARGETTYPE_NONE) { var target = null; if(!ccbReader.isJSControlled()) { - if (selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT) { + if (selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT) { target = ccbReader.getAnimationManager().getRootNode(); - } else if (selectorTarget == CCB_TARGETTYPE_OWNER) { + } else if (selectorTarget === CCB_TARGETTYPE_OWNER) { target = ccbReader.getOwner(); } @@ -634,14 +628,13 @@ cc.NodeLoader = cc.Class.extend({ var selMenuHandler = 0; //var targetAsCCBSelectorResolver = target; - if (target != null && target.onResolveCCBCCMenuItemSelector) { + if (target != null && target.onResolveCCBCCMenuItemSelector) selMenuHandler = target.onResolveCCBCCMenuItemSelector(target, selectorName); - } + if (selMenuHandler == 0) { var ccbSelectorResolver = ccbReader.getCCBSelectorResolver(); - if (ccbSelectorResolver != null) { + if (ccbSelectorResolver != null) selMenuHandler = ccbSelectorResolver.onResolveCCBCCMenuItemSelector(target, selectorName); - } } if (selMenuHandler == 0) { @@ -656,7 +649,7 @@ cc.NodeLoader = cc.Class.extend({ cc.log("Unexpected NULL target for selector."); } } else { - if(selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT){ + if(selectorTarget === CCB_TARGETTYPE_DOCUMENTROOT){ ccbReader.addDocumentCallbackNode(node); ccbReader.addDocumentCallbackName(selectorName); ccbReader.addDocumentCallbackControlEvents(0); @@ -674,7 +667,7 @@ cc.NodeLoader = cc.Class.extend({ var selectorTarget = ccbReader.readInt(false); var controlEvents = ccbReader.readInt(false); - if (selectorTarget != CCB_TARGETTYPE_NONE) { + if (selectorTarget !== CCB_TARGETTYPE_NONE) { if(!ccbReader.isJSControlled()){ var target = null; if (selectorTarget == CCB_TARGETTYPE_DOCUMENTROOT) { @@ -730,11 +723,12 @@ cc.NodeLoader = cc.Class.extend({ ccbFileName = ccbFileWithoutPathExtension + ".ccbi"; //load sub file - var path = cc.FileUtils.getInstance().fullPathFromRelativePath(ccbFileName); + var fileUtils = cc.FileUtils.getInstance(); + var path = fileUtils.fullPathFromRelativePath(ccbFileName); var myCCBReader = new cc.BuilderReader(ccbReader); var size ; - var bytes = cc.FileUtils.getInstance().getByteArrayFromFile(path,"rb", size); + var bytes = fileUtils.getByteArrayFromFile(path,"rb", size); myCCBReader.initWithData(bytes,ccbReader.getOwner()); myCCBReader.getAnimationManager().setRootContainerSize(parent.getContentSize()); @@ -844,7 +838,7 @@ cc.NodeLoader = cc.Class.extend({ onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { if (propertyName === PROPERTY_VISIBLE) { node.setVisible(check); - } else if (propertyName == PROPERTY_IGNOREANCHORPOINTFORPOSITION) { + } else if (propertyName === PROPERTY_IGNOREANCHORPOINTFORPOSITION) { node.ignoreAnchorPointForPosition(check); } else { ASSERT_FAIL_UNEXPECTED_PROPERTY(propertyName); diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 85e841282f..cd08b83ad5 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -36,35 +36,38 @@ cc.SpriteLoader = cc.NodeLoader.extend({ }, onHandlePropTypeColor3:function (node, parent, propertyName, color3BValue, ccbReader) { - if (propertyName == PROPERTY_COLOR) { + if (propertyName === PROPERTY_COLOR) { node.setColor(color3BValue); } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, color3BValue, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { - if (propertyName == PROPERTY_OPACITY) { + if (propertyName === PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccbBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccbBlendFunc); } else { cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccbBlendFunc, ccbReader); } }, onHandlePropTypeSpriteFrame:function (node, parent, propertyName, ccSpriteFrame, ccbReader) { - if (propertyName == PROPERTY_DISPLAYFRAME) { - node.setDisplayFrame(ccSpriteFrame); + if (propertyName === PROPERTY_DISPLAYFRAME) { + if(ccSpriteFrame) + node.setDisplayFrame(ccSpriteFrame); + else + cc.log("ERROR: SpriteFrame is null"); } else { cc.NodeLoader.prototype.onHandlePropTypeSpriteFrame.call(this, node, parent, propertyName, ccSpriteFrame, ccbReader); } }, onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) { - if (propertyName == PROPERTY_FLIP) { + if (propertyName === PROPERTY_FLIP) { node.setFlipX(flip[0]); node.setFlipY(flip[1]); } else { @@ -91,15 +94,15 @@ cc.LayerLoader = cc.NodeLoader.extend({ return cc.Layer.create(); }, onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { - if (propertyName == PROPERTY_TOUCH_ENABLED || propertyName == PROPERTY_IS_TOUCH_ENABLED) { + if (propertyName === PROPERTY_TOUCH_ENABLED || propertyName === PROPERTY_IS_TOUCH_ENABLED) { node.setTouchEnabled(check); - } else if (propertyName == PROPERTY_ACCELEROMETER_ENABLED || propertyName == PROPERTY_IS_ACCELEROMETER_ENABLED) { + } else if (propertyName === PROPERTY_ACCELEROMETER_ENABLED || propertyName === PROPERTY_IS_ACCELEROMETER_ENABLED) { node.setAccelerometerEnabled(check); - } else if (propertyName == PROPERTY_MOUSE_ENABLED || propertyName == PROPERTY_IS_MOUSE_ENABLED ) { + } else if (propertyName === PROPERTY_MOUSE_ENABLED || propertyName === PROPERTY_IS_MOUSE_ENABLED ) { node.setMouseEnabled(check); - } else if (propertyName == PROPERTY_KEYBOARD_ENABLED || propertyName == PROPERTY_IS_KEYBOARD_ENABLED) { + } else if (propertyName === PROPERTY_KEYBOARD_ENABLED || propertyName === PROPERTY_IS_KEYBOARD_ENABLED) { // TODO XXX - if(node.setKeyboardEnabled && sys.platform == "browser") { + if(node.setKeyboardEnabled && sys.platform === "browser") { node.setKeyboardEnabled(check); } else { cc.log("The property '" + PROPERTY_IS_KEYBOARD_ENABLED + "' is not supported!"); @@ -122,21 +125,21 @@ cc.LayerColorLoader = cc.LayerLoader.extend({ }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { - if (propertyName == PROPERTY_COLOR) { + if (propertyName === PROPERTY_COLOR) { node.setColor(ccColor3B); } else { cc.LayerLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { - if (propertyName == PROPERTY_OPACITY) { + if (propertyName === PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); @@ -159,7 +162,7 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ return cc.LayerGradient.create(); }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { - if (propertyName == PROPERTY_STARTCOLOR) { + if (propertyName === PROPERTY_STARTCOLOR) { node.setStartColor(ccColor3B); } else if (propertyName == PROPERTY_ENDCOLOR) { node.setEndColor(ccColor3B); @@ -168,16 +171,16 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { - if (propertyName == PROPERTY_STARTOPACITY) { + if (propertyName === PROPERTY_STARTOPACITY) { node.setStartOpacity(byteValue); - } else if (propertyName == PROPERTY_ENDOPACITY) { + } else if (propertyName === PROPERTY_ENDOPACITY) { node.setEndOpacity(byteValue); } else { cc.LayerLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) { - if (propertyName == PROPERTY_VECTOR) { + if (propertyName === PROPERTY_VECTOR) { node.setVector(point); // TODO Not passed along the ccbi file. // node.setCompressedInterpolation(true); @@ -186,7 +189,7 @@ cc.LayerGradientLoader = cc.LayerLoader.extend({ } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { cc.LayerLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); @@ -217,7 +220,7 @@ cc.MenuItemLoader = cc.NodeLoader.extend({ }, onHandlePropTypeBlock:function (node, parent, propertyName, blockData, ccbReader) { - if (propertyName == PROPERTY_BLOCK) { + if (propertyName === PROPERTY_BLOCK) { if (null != blockData) { // Add this condition to allow CCMenuItemImage without target/selector predefined node.setTarget(blockData.selMenuHander, blockData.target); } @@ -226,7 +229,7 @@ cc.MenuItemLoader = cc.NodeLoader.extend({ } }, onHandlePropTypeCheck:function (node, parent, propertyName, check, ccbReader) { - if (propertyName == PROPERTY_ISENABLED) { + if (propertyName === PROPERTY_ISENABLED) { node.setEnabled(check); } else { cc.NodeLoader.prototype.onHandlePropTypeCheck.call(this, node, parent, propertyName, check, ccbReader); @@ -244,15 +247,15 @@ cc.MenuItemImageLoader = cc.MenuItemLoader.extend({ }, onHandlePropTypeSpriteFrame:function (node, parent, propertyName, spriteFrame, ccbReader) { - if (propertyName == PROPERTY_NORMALDISPLAYFRAME) { + if (propertyName === PROPERTY_NORMALDISPLAYFRAME) { if (spriteFrame != null) { node.setNormalSpriteFrame(spriteFrame); } - } else if (propertyName == PROPERTY_SELECTEDDISPLAYFRAME) { + } else if (propertyName === PROPERTY_SELECTEDDISPLAYFRAME) { if (spriteFrame != null) { node.setSelectedSpriteFrame(spriteFrame); } - } else if (propertyName == PROPERTY_DISABLEDDISPLAYFRAME) { + } else if (propertyName === PROPERTY_DISABLEDDISPLAYFRAME) { if (spriteFrame != null) { node.setDisabledSpriteFrame(spriteFrame); } @@ -278,58 +281,58 @@ cc.LabelTTFLoader = cc.NodeLoader.extend({ return cc.LabelTTF.create(); }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { - if (propertyName == PROPERTY_COLOR) { + if (propertyName === PROPERTY_COLOR) { node.setColor(ccColor3B); } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { - if (propertyName == PROPERTY_OPACITY) { + if (propertyName === PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeFontTTF:function (node, parent, propertyName, fontTTF, ccbReader) { - if (propertyName == PROPERTY_FONTNAME) { + if (propertyName === PROPERTY_FONTNAME) { node.setFontName(fontTTF); } else { cc.NodeLoader.prototype.onHandlePropTypeFontTTF.call(this, node, parent, propertyName, fontTTF, ccbReader); } }, onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) { - if (propertyName == PROPERTY_STRING) { + if (propertyName === PROPERTY_STRING) { node.setString(textValue); } else { cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader); } }, onHandlePropTypeFloatScale:function (node, parent, propertyName, floatScale, ccbReader) { - if (propertyName == PROPERTY_FONTSIZE) { + if (propertyName === PROPERTY_FONTSIZE) { node.setFontSize(floatScale); } else { cc.NodeLoader.prototype.onHandlePropTypeFloatScale.call(this, node, parent, propertyName, floatScale, ccbReader); } }, onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) { - if (propertyName == PROPERTY_HORIZONTALALIGNMENT) { + if (propertyName === PROPERTY_HORIZONTALALIGNMENT) { node.setHorizontalAlignment(integerLabeled); - } else if (propertyName == PROPERTY_VERTICALALIGNMENT) { + } else if (propertyName === PROPERTY_VERTICALALIGNMENT) { node.setVerticalAlignment(integerLabeled); } else { cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader); } }, onHandlePropTypeSize:function (node, parent, propertyName, size, ccbReader) { - if (propertyName == PROPERTY_DIMENSIONS) { + if (propertyName === PROPERTY_DIMENSIONS) { node.setDimensions(size); } else { cc.NodeLoader.prototype.onHandlePropTypeSize.call(this, node, parent, propertyName, size, ccbReader); @@ -349,35 +352,35 @@ cc.LabelBMFontLoader = cc.NodeLoader.extend({ }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { - if (propertyName == PROPERTY_COLOR) { + if (propertyName === PROPERTY_COLOR) { node.setColor(ccColor3B); } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { - if (propertyName == PROPERTY_OPACITY) { + if (propertyName === PROPERTY_OPACITY) { node.setOpacity(byteValue); } else { cc.NodeLoader.prototype.onHandlePropTypeByte.call(this, node, parent, propertyName, byteValue, ccbReader); } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeFntFile:function (node, parent, propertyName, fntFile, ccbReader) { - if (propertyName == PROPERTY_FNTFILE) { + if (propertyName === PROPERTY_FNTFILE) { node.setFntFile(fntFile); } else { cc.NodeLoader.prototype.onHandlePropTypeFntFile.call(this, node, parent, propertyName, fntFile, ccbReader); } }, onHandlePropTypeText:function (node, parent, propertyName, textValue, ccbReader) { - if (propertyName == PROPERTY_STRING) { + if (propertyName === PROPERTY_STRING) { node.setString(textValue); } else { cc.NodeLoader.prototype.onHandlePropTypeText.call(this, node, parent, propertyName, textValue, ccbReader); @@ -415,72 +418,72 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ }, onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) { - if (propertyName == PROPERTY_EMITERMODE) { + if (propertyName === PROPERTY_EMITERMODE) { node.setEmitterMode(integerLabeled); } else { cc.NodeLoader.prototype.onHandlePropTypeIntegerLabeled.call(this, node, parent, propertyName, integerLabeled, ccbReader); } }, onHandlePropTypePoint:function (node, parent, propertyName, point, ccbReader) { - if (propertyName == PROPERTY_POSVAR) { + if (propertyName === PROPERTY_POSVAR) { node.setPosVar(point); - } else if (propertyName == PROPERTY_GRAVITY) { + } else if (propertyName === PROPERTY_GRAVITY) { node.setGravity(point); } else { cc.NodeLoader.prototype.onHandlePropTypePoint.call(this, node, parent, propertyName, point, ccbReader); } }, onHandlePropTypeFloat:function (node, parent, propertyName, floatValue, ccbReader) { - if (propertyName == PROPERTY_EMISSIONRATE) { + if (propertyName === PROPERTY_EMISSIONRATE) { node.setEmissionRate(floatValue); - } else if (propertyName == PROPERTY_DURATION) { + } else if (propertyName === PROPERTY_DURATION) { node.setDuration(floatValue); } else { cc.NodeLoader.prototype.onHandlePropTypeFloat.call(this, node, parent, propertyName, floatValue, ccbReader); } }, onHandlePropTypeInteger:function (node, parent, propertyName, integerValue, ccbReader) { - if (propertyName == PROPERTY_TOTALPARTICLES) { + if (propertyName === PROPERTY_TOTALPARTICLES) { node.setTotalParticles(integerValue); } else { cc.NodeLoader.prototype.onHandlePropTypeInteger.call(this, node, parent, propertyName, integerValue, ccbReader); } }, onHandlePropTypeFloatVar:function (node, parent, propertyName, floatVar, ccbReader) { - if (propertyName == PROPERTY_LIFE) { + if (propertyName === PROPERTY_LIFE) { node.setLife(floatVar[0]); node.setLifeVar(floatVar[1]); - } else if (propertyName == PROPERTY_STARTSIZE) { + } else if (propertyName === PROPERTY_STARTSIZE) { node.setStartSize(floatVar[0]); node.setStartSizeVar(floatVar[1]); - } else if (propertyName == PROPERTY_ENDSIZE) { + } else if (propertyName === PROPERTY_ENDSIZE) { node.setEndSize(floatVar[0]); node.setEndSizeVar(floatVar[1]); - } else if (propertyName == PROPERTY_STARTSPIN) { + } else if (propertyName === PROPERTY_STARTSPIN) { node.setStartSpin(floatVar[0]); node.setStartSpinVar(floatVar[1]); - } else if (propertyName == PROPERTY_ENDSPIN) { + } else if (propertyName === PROPERTY_ENDSPIN) { node.setEndSpin(floatVar[0]); node.setEndSpinVar(floatVar[1]); - } else if (propertyName == PROPERTY_ANGLE) { + } else if (propertyName === PROPERTY_ANGLE) { node.setAngle(floatVar[0]); node.setAngleVar(floatVar[1]); - } else if (propertyName == PROPERTY_SPEED) { + } else if (propertyName === PROPERTY_SPEED) { node.setSpeed(floatVar[0]); node.setSpeedVar(floatVar[1]); - } else if (propertyName == PROPERTY_TANGENTIALACCEL) { + } else if (propertyName === PROPERTY_TANGENTIALACCEL) { node.setTangentialAccel(floatVar[0]); node.setTangentialAccelVar(floatVar[1]); - } else if (propertyName == PROPERTY_RADIALACCEL) { + } else if (propertyName === PROPERTY_RADIALACCEL) { node.setRadialAccel(floatVar[0]); node.setRadialAccelVar(floatVar[1]); - } else if (propertyName == PROPERTY_STARTRADIUS) { + } else if (propertyName === PROPERTY_STARTRADIUS) { node.setStartRadius(floatVar[0]); node.setStartRadiusVar(floatVar[1]); - } else if (propertyName == PROPERTY_ENDRADIUS) { + } else if (propertyName === PROPERTY_ENDRADIUS) { node.setEndRadius(floatVar[0]); node.setEndRadiusVar(floatVar[1]); - } else if (propertyName == PROPERTY_ROTATEPERSECOND) { + } else if (propertyName === PROPERTY_ROTATEPERSECOND) { node.setRotatePerSecond(floatVar[0]); node.setRotatePerSecondVar(floatVar[1]); } else { @@ -488,10 +491,10 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ } }, onHandlePropTypeColor4FVar:function (node, parent, propertyName, ccColor4FVar, ccbReader) { - if (propertyName == PROPERTY_STARTCOLOR) { + if (propertyName === PROPERTY_STARTCOLOR) { node.setStartColor(ccColor4FVar[0]); node.setStartColorVar(ccColor4FVar[1]); - } else if (propertyName == PROPERTY_ENDCOLOR) { + } else if (propertyName === PROPERTY_ENDCOLOR) { node.setEndColor(ccColor4FVar[0]); node.setEndColorVar(ccColor4FVar[1]); } else { @@ -499,14 +502,14 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ } }, onHandlePropTypeBlendFunc:function (node, parent, propertyName, ccBlendFunc, ccbReader) { - if (propertyName == PROPERTY_BLENDFUNC) { + if (propertyName === PROPERTY_BLENDFUNC) { node.setBlendFunc(ccBlendFunc); } else { cc.NodeLoader.prototype.onHandlePropTypeBlendFunc.call(this, node, parent, propertyName, ccBlendFunc, ccbReader); } }, onHandlePropTypeTexture:function (node, parent, propertyName, ccTexture2D, ccbReader) { - if (propertyName == PROPERTY_TEXTURE) { + if (propertyName === PROPERTY_TEXTURE) { node.setTexture(ccTexture2D); } else { cc.NodeLoader.prototype.onHandlePropTypeTexture.call(this, node, parent, propertyName, ccTexture2D, ccbReader); From 2bf826fcb9f5f6af151805253bc96d6a9eaa384a Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 3 Sep 2013 14:32:03 +0800 Subject: [PATCH 077/141] Closed #2762: Refactor CCSimpleAudioEngine.js for code maintainability --- CocosDenshion/SimpleAudioEngine.js | 238 ++++++++++++++--------------- 1 file changed, 114 insertions(+), 124 deletions(-) diff --git a/CocosDenshion/SimpleAudioEngine.js b/CocosDenshion/SimpleAudioEngine.js index 0cafb66c9c..76acc46b61 100644 --- a/CocosDenshion/SimpleAudioEngine.js +++ b/CocosDenshion/SimpleAudioEngine.js @@ -69,16 +69,16 @@ cc.AudioEngine = cc.Class.extend(/** @lends cc.AudioEngine# */{ /** * Helper function for cutting out the extension from the path * @param {String} fullpath + * @return {String|null} path without ext name * @protected */ _getPathWithoutExt: function (fullpath) { if (typeof(fullpath) != "string") { - return; + return null; } var endPos = fullpath.lastIndexOf("."); - if (endPos != -1) { + if (endPos !== -1) return fullpath.substring(0, endPos); - } return fullpath; }, @@ -89,7 +89,7 @@ cc.AudioEngine = cc.Class.extend(/** @lends cc.AudioEngine# */{ */ _getExtFromFullPath: function (fullpath) { var startPos = fullpath.lastIndexOf("."); - if (startPos != -1) { + if (startPos !== -1) { return fullpath.substring(startPos + 1, fullpath.length); } return -1; @@ -113,21 +113,15 @@ cc.SimpleSFX = function (audio, ext) { * @extends cc.AudioEngine */ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */{ - _supportedFormat:[], - _soundEnable:false, + _supportedFormat:null, _effectList:{}, _soundList:{}, _playingMusic:null, _effectsVolume:1, _maxAudioInstance:10, + _capabilities:null, + _soundSupported:false, _canPlay:true, - _capabilities:{ - mp3:false, - ogg:false, - wav:false, - mp4:false, - m4a:false - }, /** * Constructor @@ -136,12 +130,17 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ cc.AudioEngine.prototype.ctor.call(this); this._supportedFormat = []; - this._checkCanPlay(this._capabilities); + this._effectList = {}; + this._soundList = {}; + + this._capabilities = { mp3: false, ogg: false, wav: false, mp4: false, m4a: false}; + var locCapabilities = this._capabilities; + this._checkCanPlay(locCapabilities); // enable sound if any of the audio format is supported - this._soundEnable = this._capabilities.mp3 || this._capabilities.mp4 - || this._capabilities.m4a || this._capabilities.ogg - || this._capabilities.wav; + this._soundSupported = locCapabilities.mp3 || locCapabilities.mp4 + || locCapabilities.m4a || locCapabilities.ogg + || locCapabilities.wav; var ua = navigator.userAgent; if(/Mobile/.test(ua) && (/iPhone OS/.test(ua)||/iPad/.test(ua)||/Firefox/.test(ua)) || /MSIE/.test(ua)){ @@ -156,7 +155,7 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ init:function () { // detect the prefered audio format this._getSupportedAudioFormat(); - return this._soundEnable; + return this._soundSupported; }, /** @@ -165,7 +164,7 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * @param {String} path The path of the music file with filename extension. */ preloadSound:function (path) { - if (this._soundEnable) { + if (this._soundSupported) { var extName = this._getExtFromFullPath(path); var keyname = this._getPathWithoutExt(path); if (this.isFormatSupported(extName) && !this._soundList.hasOwnProperty(keyname)) { @@ -174,31 +173,26 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ sfxCache.ext = extName; sfxCache.audio = new Audio(path); sfxCache.audio.preload = 'auto'; - sfxCache.audio.addEventListener('canplaythrough', function (e) { + var soundPreloadCanplayHandler = function (e) { cc.Loader.getInstance().onResLoaded(); - this.removeEventListener('canplaythrough', arguments.callee, false); - this.removeEventListener('error', arguments.callee, false); - }, false); - - sfxCache.audio.addEventListener("error", function (e) { + this.removeEventListener('canplaythrough', soundPreloadCanplayHandler, false); + this.removeEventListener('error', soundPreloadErrorHandler, false); + }; + var soundPreloadErrorHandler = function (e) { cc.Loader.getInstance().onResLoadingErr(e.srcElement.src); - this.removeEventListener('error', arguments.callee, false); - }, false); + this.removeEventListener('canplaythrough', soundPreloadCanplayHandler, false); + this.removeEventListener('error', soundPreloadErrorHandler, false); + }; + sfxCache.audio.addEventListener('canplaythrough', soundPreloadCanplayHandler, false); + sfxCache.audio.addEventListener("error", soundPreloadErrorHandler, false); this._soundList[keyname] = sfxCache; sfxCache.audio.load(); - } - else{ - cc.Loader.getInstance().onResLoaded(); + return; } } - else { - cc.Loader.getInstance().onResLoaded(); - } - } - else { - cc.Loader.getInstance().onResLoaded(); } + cc.Loader.getInstance().onResLoaded(); }, /** @@ -210,27 +204,27 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * cc.AudioEngine.getInstance().playMusic(path, false); */ playMusic:function (path, loop) { - if (!this._soundEnable) + if (!this._soundSupported) return; var keyname = this._getPathWithoutExt(path); var extName = this._getExtFromFullPath(path); var au; - if (this._soundList.hasOwnProperty(this._playingMusic)) { - this._soundList[this._playingMusic].audio.pause(); + var locSoundList = this._soundList; + if (locSoundList.hasOwnProperty(this._playingMusic)) { + locSoundList[this._playingMusic].audio.pause(); } this._playingMusic = keyname; - if (this._soundList.hasOwnProperty(this._playingMusic)) { - au = this._soundList[this._playingMusic].audio; - } - else { + if (locSoundList.hasOwnProperty(this._playingMusic)) { + au = locSoundList[this._playingMusic].audio; + } else { var sfxCache = new cc.SimpleSFX(); sfxCache.ext = extName; au = sfxCache.audio = new Audio(path); sfxCache.audio.preload = 'auto'; - this._soundList[keyname] = sfxCache; + locSoundList[keyname] = sfxCache; sfxCache.audio.load(); } @@ -254,12 +248,13 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * cc.AudioEngine.getInstance().stopMusic(); */ stopMusic:function (releaseData) { - if (this._soundList.hasOwnProperty(this._playingMusic)) { - var au = this._soundList[this._playingMusic].audio; + var locSoundList = this._soundList, locPlayingMusic = this._playingMusic; + if (locSoundList.hasOwnProperty(locPlayingMusic)) { + var au = locSoundList[locPlayingMusic].audio; au.pause(); au.currentTime = au.duration; if (releaseData) { - delete this._soundList[this._playingMusic]; + delete locSoundList[locPlayingMusic]; } cc.AudioEngine.isMusicPlaying = false; } @@ -340,11 +335,9 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ var music = this._soundList[this._playingMusic].audio; if (volume > 1) { music.volume = 1; - } - else if (volume < 0) { + } else if (volume < 0) { music.volume = 0; - } - else { + } else { music.volume = volume; } } @@ -370,19 +363,19 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * Play sound effect. * @param {String} path The path of the sound effect with filename extension. * @param {Boolean} loop Whether to loop the effect playing, default value is false + * @return {Number|null} the audio id * @example * //example * var soundId = cc.AudioEngine.getInstance().playEffect(path); */ - playEffect:function (path, loop) { - if (!this._soundEnable) - return; + playEffect: function (path, loop) { + if (!this._soundSupported) + return null; var keyname = this._getPathWithoutExt(path), actExt; if (this._soundList.hasOwnProperty(keyname)) { actExt = this._soundList[keyname].ext; - } - else { + } else { actExt = this._getExtFromFullPath(path); } @@ -393,9 +386,8 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ if (reclaim[i].ended) { au = reclaim[i]; au.currentTime = 0; - if (window.chrome){ + if (window.chrome) au.load(); - } break; } } @@ -411,13 +403,11 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ reclaim.push(au); } - if (loop) { + if (loop) au.loop = loop; - } au.play(); var audioID = this._audioID++; this._audioIDList[audioID] = au; - return audioID; }, @@ -440,19 +430,16 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * cc.AudioEngine.getInstance().setEffectsVolume(0.5); */ setEffectsVolume:function (volume) { - if (volume > 1) { + if (volume > 1) this._effectsVolume = 1; - } - else if (volume < 0) { + else if (volume < 0) this._effectsVolume = 0; - } - else { + else this._effectsVolume = volume; - } - var tmpArr, au; - for (var i in this._effectList) { - tmpArr = this._effectList[i]; + var tmpArr, au, locEffectList = this._effectList; + for (var i in locEffectList) { + tmpArr = locEffectList[i]; if (tmpArr.length > 0) { for (var j = 0; j < tmpArr.length; j++) { au = tmpArr[j]; @@ -488,13 +475,13 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ */ pauseAllEffects:function () { var tmpArr, au; - for (var i in this._effectList) { - tmpArr = this._effectList[i]; + var locEffectList = this._effectList; + for (var i in locEffectList) { + tmpArr = locEffectList[i]; for (var j = 0; j < tmpArr.length; j++) { au = tmpArr[j]; - if (!au.ended) { + if (!au.ended) au.pause(); - } } } }, @@ -511,9 +498,8 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ if (this._audioIDList.hasOwnProperty(audioID)) { var au = this._audioIDList[audioID]; - if (!au.ended) { + if (!au.ended) au.play(); - } } }, @@ -525,14 +511,14 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ */ resumeAllEffects:function () { var tmpArr, au; - for (var i in this._effectList) { - tmpArr = this._effectList[i]; + var locEffectList = this._effectList; + for (var i in locEffectList) { + tmpArr = locEffectList[i]; if (tmpArr.length > 0) { for (var j = 0; j < tmpArr.length; j++) { au = tmpArr[j]; - if (!au.ended) { + if (!au.ended) au.play(); - } } } } @@ -564,9 +550,9 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * cc.AudioEngine.getInstance().stopAllEffects(); */ stopAllEffects:function () { - var tmpArr, au; - for (var i in this._effectList) { - tmpArr = this._effectList[i]; + var tmpArr, au, locEffectList = this._effectList; + for (var i in locEffectList) { + tmpArr = locEffectList[i]; for (var j = 0; j < tmpArr.length; j++) { au = tmpArr[j]; if (!au.ended) { @@ -591,24 +577,24 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ delete this._effectList[keyname]; } - var au,pathName; - for (var k in this._audioIDList) { - au = this._audioIDList[k]; + var au, pathName, locAudioIDList = this._audioIDList; + for (var k in locAudioIDList) { + au = locAudioIDList[k]; pathName = this._getPathWithoutExt(au.src); if(pathName.indexOf(keyname) > -1){ this.stopEffect(k); - delete this._audioIDList[k]; + delete locAudioIDList[k]; } } }, _getEffectList:function (elt) { - if (this._effectList.hasOwnProperty(elt)) { - return this._effectList[elt]; - } - else { - this._effectList[elt] = []; - return this._effectList[elt]; + var locEffectList = this._effectList; + if (locEffectList.hasOwnProperty(elt)) { + return locEffectList[elt]; + } else { + locEffectList[elt] = []; + return locEffectList[elt]; } }, @@ -617,20 +603,19 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ * @param {String} ext * @returns {Boolean} */ - isFormatSupported:function (ext) { - var tmpExt; - for (var i = 0; i < this._supportedFormat.length; i++) { - tmpExt = this._supportedFormat[i]; - if (tmpExt == ext) { + isFormatSupported: function (ext) { + var tmpExt, locSupportedFormat = this._supportedFormat; + for (var i = 0; i < locSupportedFormat.length; i++) { + tmpExt = locSupportedFormat[i]; + if (tmpExt == ext) return true; - } } return false; }, _getSupportedAudioFormat:function () { // check for sound support by the browser - if (!this._soundEnable) { + if (!this._soundSupported) { return; } @@ -675,11 +660,11 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ // the Web Audio Context _ctx: null, // may be: mp3, ogg, wav, mp4, m4a - _supportedFormat: [], + _supportedFormat: null, // if sound is not enabled, this engine's init() will return false - _soundEnable: false, + _soundSupported: false, // containing all binary buffers of loaded audio resources - _audioData: {}, + _audioData: null, /* * Issue: When loading two resources with different suffixes asynchronously, the second one might start loading * when the first one is already loading! @@ -687,13 +672,13 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ * exception "DOM exception 12", it should be a bug of the browser. * So just add something to mark some audios as LOADING so as to avoid duplication. */ - _audiosLoading: {}, + _audiosLoading: null, // the music being played, cc.WebAudioSFX, when null, no music is being played; when not null, it may be playing or paused _music: null, // the volume applied to the music _musicVolume: 1, // the effects being played: { key => [cc.WebAudioSFX] }, many effects of the same resource may be played simultaneously - _effects: {}, + _effects: null, // the volume applied to all effects _effectsVolume: 1, @@ -713,6 +698,10 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ */ ctor: function() { cc.AudioEngine.prototype.ctor.call(this); + this._supportedFormat = []; + this._audioData = {}; + this._audiosLoading = {}; + this._effects = {}; }, /** @@ -730,16 +719,14 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ var capabilities = {}; this._checkCanPlay(capabilities); - var formats = ['ogg', 'mp3', 'wav', 'mp4', 'm4a']; + var formats = ['ogg', 'mp3', 'wav', 'mp4', 'm4a'], locSupportedFormat = this._supportedFormat; for (var idx in formats) { var name = formats[idx]; - if (capabilities[name]) { - this._supportedFormat.push(name); - } + if (capabilities[name]) + locSupportedFormat.push(name); } - this._soundEnable = this._supportedFormat.length > 0; - - return this._soundEnable; + this._soundSupported = locSupportedFormat.length > 0; + return this._soundSupported; }, /** @@ -748,10 +735,10 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ * @returns {Boolean} */ isFormatSupported: function(ext) { - for (var idx in this._supportedFormat) { - if (ext === this._supportedFormat[idx]) { + var locSupportedFormat = this._supportedFormat; + for (var idx in locSupportedFormat) { + if (ext === locSupportedFormat[idx]) return true; - } } return false; }, @@ -785,7 +772,7 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ * @param {String} path The path of the music file with filename extension. */ preloadSound: function(path) { - if (!this._soundEnable) { + if (!this._soundSupported) { return; } @@ -1146,11 +1133,12 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ if (keyName in this._audioData) { // the resource has been loaded, just play it - if (!(keyName in this._effects)) { - this._effects[keyName] = []; + var locEffects = this._effects; + if (!(keyName in locEffects)) { + locEffects[keyName] = []; } // a list of sound objects from the same resource - var effectList = this._effects[keyName]; + var effectList = locEffects[keyName]; for (var idx in effectList) { var sfxCache = effectList[idx]; if (!this._isSoundPlaying(sfxCache) && !this._isSoundPaused(sfxCache)) { @@ -1217,8 +1205,9 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ } this._effectsVolume = volume; - for (var key in this._effects) { - var effectList = this._effects[key]; + var locEffects = this._effects; + for (var key in locEffects) { + var effectList = locEffects[key]; for (var idx in effectList) { this._setSoundVolume(effectList[idx], volume); } @@ -1336,8 +1325,9 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ * cc.AudioEngine.getInstance().stopAllEffects(); */ stopAllEffects: function() { - for (var key in this._effects) { - var effectList = this._effects[key]; + var locEffects = this._effects; + for (var key in locEffects) { + var effectList = locEffects[key]; for (var idx in effectList) { this._endSound(effectList[idx]); } @@ -1347,7 +1337,7 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ * If I reassign a new {} to it, that will be appear in the instance. * In other words, the dict in prototype won't release its children. */ - delete this._effects[key]; + delete locEffects[key]; } }, From b7395319a6de84a098183404a5772da3facfc180 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 3 Sep 2013 15:13:16 +0800 Subject: [PATCH 078/141] fixed #880 add msPointerEnabled support --- cocos2d/platform/Sys.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/platform/Sys.js b/cocos2d/platform/Sys.js index 285a7dfc63..e3bc7431de 100644 --- a/cocos2d/platform/Sys.js +++ b/cocos2d/platform/Sys.js @@ -51,7 +51,7 @@ Object.defineProperties(sys, if(cc.Browser.supportWebGL) capabilities["opengl"] = true; - if( 'ontouchstart' in document.documentElement ) + if( 'ontouchstart' in document.documentElement || window.navigator.msPointerEnabled) capabilities["touches"] = true; else if( 'onmouseup' in document.documentElement ) From 832f5f14143dd31f9f4e6e37dad9940dc8586d5a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 3 Sep 2013 15:32:17 +0800 Subject: [PATCH 079/141] Closed #2748: Fix a bug of cc.Sprite that its children also follow fliped when it fliped --- cocos2d/sprite_nodes/CCSprite.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 78b022bab7..a838b2b47b 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1323,14 +1323,19 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ context.globalAlpha = this._displayedOpacity / 255; var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - if (this._flipX) { - flipXOffset = -locOffsetPosition.x - locRect.width; - context.scale(-1, 1); - } - if (this._flipY) { - flipYOffset = locOffsetPosition.y; - context.scale(1, -1); + + if (this._flipX || this._flipY) { + context.save(); + if (this._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (this._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); + } } + if (this._texture && locRect.width > 0) { var image = this._texture.getHtmlElementObj(); if (this._colorized) { @@ -1364,6 +1369,10 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; cc.drawingUtil.drawPoly(vertices2, 4, true); } + + if (this._flipX || this._flipY) + context.restore(); + cc.g_NumberOfDraws++; } }); From a1c8d296169f7b609de10ed3552400f38ee0156e Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 3 Sep 2013 15:41:41 +0800 Subject: [PATCH 080/141] Closed #2748: Fixed a bug of LabelAtlasCanvas, that _opacity is wrong used. --- cocos2d/label_nodes/CCLabelAtlas.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index 12dd596cdc..733e334b01 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -145,7 +145,7 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ fontChar.initWithTexture(texture, rect); // restore to default in case they were modified fontChar.setVisible(true); - fontChar.setOpacity(this._opacity); + fontChar.setOpacity(this._displayedOpacity); } } fontChar.setPosition(i * locItemWidth + locItemWidth / 2, locItemHeight / 2); @@ -175,7 +175,7 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ }, setOpacity:function (opacity) { - if (this._opacity != opacity) { + if (this._displayedOpacity != opacity) { cc.AtlasNode.prototype.setOpacity.call(this, opacity); var locChildren = this._children; for (var i = 0, len = locChildren.length; i < len; i++) { @@ -365,7 +365,7 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ }, setOpacity:function (opacity) { - if (this._opacity !== opacity) { + if (this._displayedOpacity !== opacity) { cc.AtlasNode.prototype.setOpacity.call(this, opacity); } } From 3d5bbe68d8a687b955b9b3c9a805bd60d7f4fd69 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Tue, 3 Sep 2013 15:45:37 +0800 Subject: [PATCH 081/141] fixed #2763:fixed ccb parser bug --- cocos2d/platform/CCSAXParser.js | 94 +++++++++---------- extensions/CCBReader/CCBAnimationManager.js | 5 +- extensions/CCBReader/CCControlLoader.js | 4 +- extensions/CCBReader/CCSpriteLoader.js | 12 ++- extensions/CCEditBox.js | 1 - .../GUI/CCControlExtension/CCControlButton.js | 1 - .../GUI/CCControlExtension/CCScale9Sprite.js | 4 +- 7 files changed, 66 insertions(+), 55 deletions(-) diff --git a/cocos2d/platform/CCSAXParser.js b/cocos2d/platform/CCSAXParser.js index 58f729bd32..19392b9158 100644 --- a/cocos2d/platform/CCSAXParser.js +++ b/cocos2d/platform/CCSAXParser.js @@ -30,14 +30,20 @@ * @extends cc.Class */ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ - xmlDoc:null, - parser:null, - _xmlDict:null, - plist:null, + xmlDoc: null, + _parser: null, + _xmlDict: null, + _isSupportDOMParser: null, - ctor:function () { + ctor: function () { this._xmlDict = {}; - this.plist = {}; + + if (window.DOMParser) { + this._isSupportDOMParser = true; + this._parser = new DOMParser(); + } else { + this._isSupportDOMParser = false; + } }, /** @@ -45,22 +51,13 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @param {String} textxml plist xml contents * @return {Array} plist object array */ - parse:function (textxml) { + parse: function (textxml) { var path = textxml; textxml = this.getList(textxml); - // get a reference to the requested corresponding xml file - if (window.DOMParser) { - this.parser = new DOMParser(); - this.xmlDoc = this.parser.parseFromString(textxml, "text/xml"); - } else {// Internet Explorer (untested!) - this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - this.xmlDoc.async = "false"; - this.xmlDoc.loadXML(textxml); - } - if (this.xmlDoc == null) - cc.log("cocos2d:xml " + this.xmlDoc + " not found!"); - var plist = this.xmlDoc.documentElement; + var xmlDoc = this._parserXML(textxml, path); + + var plist = xmlDoc.documentElement; if (plist.tagName != 'plist') throw "cocos2d: " + path + " is not a plist file"; @@ -71,8 +68,9 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ if (node.nodeType == 1) break } - this.plist = this._parseNode(node); - return this.plist; + xmlDoc = null; + + return this._parseNode(node); }, /** @@ -80,26 +78,32 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @param {String} textxml tilemap xml content * @return {Document} xml document */ - tmxParse:function (textxml, isXMLString) { - if((isXMLString == null) || (isXMLString === false)) + tmxParse: function (textxml, isXMLString) { + if ((isXMLString == null) || (isXMLString === false)) textxml = this.getList(textxml); + return this._parserXML(textxml); + }, + + _parserXML: function (textxml, path) { // get a reference to the requested corresponding xml file - if (window.DOMParser) { - this.parser = new DOMParser(); - this.xmlDoc = this.parser.parseFromString(textxml, "text/xml"); - } else { // Internet Explorer (untested!) - this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); - this.xmlDoc.async = "false"; - this.xmlDoc.loadXML(textxml); + var xmlDoc; + if (this._isSupportDOMParser) { + xmlDoc = this._parser.parseFromString(textxml, "text/xml"); + } else { + // Internet Explorer (untested!) + xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async = "false"; + xmlDoc.loadXML(textxml); } - if (this.xmlDoc == null) - cc.log("cocos2d:xml " + this.xmlDoc + " not found!"); - return this.xmlDoc; + if (xmlDoc == null) + cc.log("cocos2d:xml " + path + " not found!"); + + return xmlDoc; }, - _parseNode:function (node) { + _parseNode: function (node) { var data = null; switch (node.tagName) { case 'dict': @@ -135,7 +139,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ return data; }, - _parseArray:function (node) { + _parseArray: function (node) { var data = []; for (var i = 0, len = node.childNodes.length; i < len; i++) { var child = node.childNodes[i]; @@ -146,7 +150,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ return data; }, - _parseDict:function (node) { + _parseDict: function (node) { var data = {}; var key = null; @@ -168,19 +172,15 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * Preload plist file * @param {String} filePath */ - preloadPlist:function (filePath) { + preloadPlist: function (filePath) { filePath = cc.FileUtils.getInstance().fullPathForFilename(filePath); if (window.XMLHttpRequest) { - // for IE7+, Firefox, Chrome, Opera, Safari brower var xmlhttp = new XMLHttpRequest(); - // is xml file? if (xmlhttp.overrideMimeType) xmlhttp.overrideMimeType('text/xml'); - } else { - // for IE6, IE5 brower - xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } + if (xmlhttp != null) { var that = this; xmlhttp.onreadystatechange = function () { @@ -204,7 +204,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * Unload the preloaded plist from xmlList * @param {String} filePath */ - unloadPlist:function(filePath){ + unloadPlist: function (filePath) { if (this._xmlDict.hasOwnProperty(filePath)) delete this._xmlDict[filePath]; }, @@ -214,7 +214,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @param {String} filePath * @return {String} */ - getName:function (filePath) { + getName: function (filePath) { var startPos = filePath.lastIndexOf("/", filePath.length) + 1; var endPos = filePath.lastIndexOf(".", filePath.length); return filePath.substring(startPos, endPos); @@ -225,7 +225,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @param {String} filePath * @return {String} */ - getExt:function (filePath) { + getExt: function (filePath) { var startPos = filePath.lastIndexOf(".", filePath.length) + 1; return filePath.substring(startPos, filePath.length); }, @@ -235,7 +235,7 @@ cc.SAXParser = cc.Class.extend(/** @lends cc.SAXParser# */{ * @param {String} key * @return {String} xml content */ - getList:function (key) { + getList: function (key) { if (this._xmlDict != null) { return this._xmlDict[key]; } @@ -255,4 +255,4 @@ cc.SAXParser.getInstance = function () { return this._instance; }; -cc.SAXParser._instance = null; +cc.SAXParser._instance = null; \ No newline at end of file diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/CCBReader/CCBAnimationManager.js index 0f67fb02ce..c730a5c984 100644 --- a/extensions/CCBReader/CCBAnimationManager.js +++ b/extensions/CCBReader/CCBAnimationManager.js @@ -522,7 +522,10 @@ cc.BuilderAnimationManager = cc.Class.extend({ } else if(propName === "displayFrame"){ node.setDisplayFrame(value); } else if(propName === "color"){ - node.setColor(value.getColor()); + var ccColor3B = value.getColor(); + if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + node.setColor(ccColor3B); + } } else if( propName === "visible"){ value = value || false; node.setVisible(value); diff --git a/extensions/CCBReader/CCControlLoader.js b/extensions/CCBReader/CCControlLoader.js index c1c4a56e31..8f39c18974 100644 --- a/extensions/CCBReader/CCControlLoader.js +++ b/extensions/CCBReader/CCControlLoader.js @@ -253,7 +253,9 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ onHandlePropTypeColor3:function(node, parent, propertyName, ccColor3B,ccbReader){ if(propertyName == PROPERTY_COLOR) { - node.setColor(ccColor3B); + if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + node.setColor(ccColor3B); + } } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B,ccbReader); } diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 85e841282f..1bf82fe10e 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -37,7 +37,9 @@ cc.SpriteLoader = cc.NodeLoader.extend({ onHandlePropTypeColor3:function (node, parent, propertyName, color3BValue, ccbReader) { if (propertyName == PROPERTY_COLOR) { - node.setColor(color3BValue); + if(!(color3BValue.r == 255 && color3BValue.g == 255 && color3BValue.b == 255)){ + node.setColor(color3BValue); + } } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, color3BValue, ccbReader); } @@ -279,7 +281,9 @@ cc.LabelTTFLoader = cc.NodeLoader.extend({ }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { if (propertyName == PROPERTY_COLOR) { - node.setColor(ccColor3B); + if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + node.setColor(ccColor3B); + } } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } @@ -350,7 +354,9 @@ cc.LabelBMFontLoader = cc.NodeLoader.extend({ onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { if (propertyName == PROPERTY_COLOR) { - node.setColor(ccColor3B); + if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + node.setColor(ccColor3B); + } } else { cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index 176181e246..1bb6a3ba3c 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -215,7 +215,6 @@ cc.EditBox = cc.ControlButton.extend({ this._placeholderColor = cc.GRAY; this.setContentSize(boxSize); this._domInputSprite = new cc.Sprite(); - this._domInputSprite.setColor(cc.BLUE); this._domInputSprite.draw = function(){ }; //redefine draw function this.addChild(this._domInputSprite); var selfPointer = this; diff --git a/extensions/GUI/CCControlExtension/CCControlButton.js b/extensions/GUI/CCControlExtension/CCControlButton.js index ee479f8240..e57fcf0ec4 100644 --- a/extensions/GUI/CCControlExtension/CCControlButton.js +++ b/extensions/GUI/CCControlExtension/CCControlButton.js @@ -173,7 +173,6 @@ cc.ControlButton = cc.Control.extend({ this._backgroundSprite = backgroundSprite; // Set the default color and opacity - this.setColor(cc.c3(255, 255, 255)); this.setOpacity(255); this.setOpacityModifyRGB(true); diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 352fc6d010..cb5559834b 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -726,7 +726,9 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ if (this._spritesGenerated) { // Restore color and opacity this.setOpacity(opacity); - this.setColor(color); + if(!(color.r == 255 && color.g == 255 && color.b == 255)){ + this.setColor(color); + } } this._spritesGenerated = true; return true; From 64637fbf910cfc31b41476c5fd48fdbd0291bc28 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 3 Sep 2013 15:49:00 +0800 Subject: [PATCH 082/141] Closed #2748: Fixed a bug of cc.ProgressTimerCanvas that it is error display when it flip. --- cocos2d/misc_nodes/CCProgressTimer.js | 210 ++++++++++++++------------ 1 file changed, 110 insertions(+), 100 deletions(-) diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index 2d14f6ef45..57d78673e8 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -166,13 +166,11 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * /// ---- common properties end ---- _origin:null, - _originSize:null, - _drawSize:null, - _drawPosition:null, _startAngle:270, _endAngle:270, _radius:0, - + _counterClockWise:false, + _barRect:null, ctor:function () { cc.NodeRGBA.prototype.ctor.call(this); @@ -185,12 +183,11 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * this._sprite = null; this._origin = cc.PointZero(); - this._originSize = cc.SizeZero(); - this._drawSize = cc.SizeZero(); - this._drawPosition = cc.PointZero(); this._startAngle = 270; this._endAngle = 270; this._radius = 0; + this._counterClockWise = false; + this._barRect = cc.RectZero(); }, /** @@ -288,127 +285,140 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * */ draw:function (ctx) { var context = ctx || cc.renderContext; - var locSprite = this._sprite; - context.globalAlpha = locSprite._opacity / 255; - var centerPoint, mpX = 0, mpY = 0; - var spriteContentSize = locSprite._contentSize; - var spriteAnchorPoint = locSprite._anchorPointInPoints; - if (locSprite._flipX) { - centerPoint = cc.p(spriteContentSize.width * 0.5, spriteContentSize.height * 0.5); - mpX = 0 | (centerPoint.x - spriteAnchorPoint.x); - context.translate(mpX, 0); - context.scale(-1, 1); - } - if (locSprite._flipY) { - centerPoint = cc.p(spriteContentSize.width * 0.5, spriteContentSize.height * 0.5); - mpY = -(0 | (centerPoint.y - spriteAnchorPoint.y)); - context.translate(0, mpY); - context.scale(1, -1); + var locSprite = this._sprite; + context.globalAlpha = locSprite._displayedOpacity / 255; + var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition; + var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; + + if (locSprite._flipX || locSprite._flipY) { + context.save(); + if (locSprite._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (locSprite._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); + } } - context.translate(spriteAnchorPoint.x, -spriteAnchorPoint.y); - var pos; - var offsetPixels = locSprite._offsetPosition, locSpriteTexture = locSprite._texture, locSpriteRect = locSprite._rect; - var locOrigin = this._origin; - var locElement = locSpriteTexture.getHtmlElementObj(); + //clip if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { - pos = cc.p(( -spriteAnchorPoint.x + offsetPixels.x + this._drawPosition.x), - ( -spriteAnchorPoint.y + offsetPixels.y + this._drawPosition.y)); - var locOriginSize = this._originSize; - if (locElement instanceof HTMLImageElement) { - if ((locOriginSize.width != 0) && (locOriginSize.height != 0)) { - context.drawImage(locElement, - locSpriteRect.x + locOrigin.x, locSpriteRect.y + locOrigin.y, - locOriginSize.width, locOriginSize.height, - pos.x, -(pos.y + this._drawSize.height), - locOriginSize.width, locOriginSize.height); - } - } else if (locElement instanceof HTMLCanvasElement) { - if ((locOriginSize.width != 0) && (locOriginSize.height != 0)) { - context.drawImage(locElement, - locOrigin.x, locOrigin.y, - locOriginSize.width, locOriginSize.height, - pos.x, -(pos.y + this._drawSize.height), - locOriginSize.width, locOriginSize.height); - } - } - } else { + var locBarRect = this._barRect; context.beginPath(); - context.arc(locOrigin.x, locOrigin.y, this._radius, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, false); + context.rect(locBarRect.x,locBarRect.y,locBarRect.width,locBarRect.height); + context.clip(); + context.closePath(); + }else if(this._type == cc.PROGRESS_TIMER_TYPE_RADIAL){ + var locOrigin = this._origin; + context.beginPath(); + context.arc(locOrigin.x, locOrigin.y, this._radius, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, this._counterClockWise); context.lineTo(locOrigin.x, locOrigin.y); context.clip(); context.closePath(); + } - pos = cc.p(0 | ( -spriteAnchorPoint.x + offsetPixels.x), - 0 | ( -spriteAnchorPoint.y + offsetPixels.y)); - - if (locElement instanceof HTMLImageElement) { - context.drawImage(locElement, - locSpriteRect.x, locSpriteRect.y, - locSpriteRect.width, locSpriteRect.height, - pos.x, -(pos.y + locSpriteRect.height), - locSpriteRect.width, locSpriteRect.height); - } else if (locElement instanceof HTMLCanvasElement) { - context.drawImage(locElement, - 0, 0, - locSpriteRect.width, locSpriteRect.height, - pos.x, -(pos.y + locSpriteRect.height), - locSpriteRect.width, locSpriteRect.height); + //draw sprite + if (locSprite._texture && locRect.width > 0) { + var image = locSprite._texture.getHtmlElementObj(); + if (locSprite._colorized) { + context.drawImage(image, + 0, 0, locRect.width, locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.height); + } else { + context.drawImage(image, + locRect.x, locRect.y, locRect.width, locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.height); } } + + if (locSprite._flipX || locSprite._flipY) + context.restore(); + cc.INCREMENT_GL_DRAWS(1); }, _updateProgress:function () { - var size = this._sprite.getContentSize(); - var textureSize = this._sprite.getTextureRect().size; + var locSprite = this._sprite; + var spriteSize = locSprite.getContentSize(); var locMidPoint = this._midPoint; + if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { - this._origin = cc.p(-(size.width * (0.5 - locMidPoint.x)), -(size.height * (locMidPoint.y - 0.5))); - this._radius = Math.round(Math.sqrt(size.width * size.width + size.height * size.height)); + this._radius = Math.round(Math.sqrt(spriteSize.width * spriteSize.width + spriteSize.height * spriteSize.height)); + var locStartAngle = 270; + var locEndAngle = 270; + var locCounterClockWise = false; + var locOrigin = this._origin; + + locOrigin.x = spriteSize.width * locMidPoint.x; + locOrigin.y = -spriteSize.height * locMidPoint.y; + if (this._reverseDirection) { - this._startAngle = 270 - 3.6 * this._percentage; + locStartAngle = 270 - 3.6 * this._percentage; } else { - this._endAngle = 270 + 3.6 * this._percentage; + locEndAngle = 270 + 3.6 * this._percentage; } - } else { - this._origin = cc.p(0, 0); - this._drawPosition = cc.p(0, 0); - var locBarChangeRate = this._barChangeRate; - var percentageF = this._percentage / 100; - var startPoint = cc.p(size.width * locMidPoint.x, size.height * locMidPoint.y); - var startPointTx = cc.p(textureSize.width * locMidPoint.x, textureSize.height * locMidPoint.y); - - var drawedSize = cc.size((size.width * (1 - locBarChangeRate.x)), (size.height * (1 - locBarChangeRate.y))); - var drawingSize = cc.size((size.width - drawedSize.width) * percentageF, (size.height - drawedSize.height) * percentageF); - this._drawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); + if (locSprite._flipX) { + locOrigin.x -= spriteSize.width * (this._midPoint.x * 2); + locStartAngle= -locStartAngle; + locEndAngle= -locEndAngle; + locStartAngle -= 180; + locEndAngle -= 180; + locCounterClockWise = !locCounterClockWise; + } + if (locSprite._flipY) { + locOrigin.y+=spriteSize.height*(this._midPoint.y*2); + locCounterClockWise = !locCounterClockWise; + locStartAngle= -locStartAngle; + locEndAngle= -locEndAngle; + } - var txDrawedSize = cc.size((textureSize.width * (1 - locBarChangeRate.x)), (textureSize.height * (1 - locBarChangeRate.y))); - var txDrawingSize = cc.size((textureSize.width - txDrawedSize.width) * percentageF, (textureSize.height - txDrawedSize.height) * percentageF); - this._originSize = cc.size(txDrawedSize.width + txDrawingSize.width, txDrawedSize.height + txDrawingSize.height); + this._startAngle = locStartAngle; + this._endAngle = locEndAngle; + this._counterClockWise = locCounterClockWise; - var needToLeft = startPoint.x * percentageF; - var needToLeftTx = startPointTx.x * percentageF; + } else { + var locBarChangeRate = this._barChangeRate; + var percentageF = this._percentage / 100; + var locBarRect = this._barRect; + + var drawedSize = cc.size((spriteSize.width * (1 - locBarChangeRate.x)), (spriteSize.height * (1 - locBarChangeRate.y))); + var drawingSize = cc.size((spriteSize.width - drawedSize.width) * percentageF, (spriteSize.height - drawedSize.height) * percentageF); + var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); + + var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y); + var needToLeft = startPoint.x - currentDrawSize.width / 2; + var needToTop = startPoint.y - currentDrawSize.height / 2; + + //left pos + locBarRect.x = 0; + var flipXNeed = 1; + if (locSprite._flipX) { + locBarRect.x -= currentDrawSize.width; + flipXNeed = -1; + } - if (size.width == this._drawSize.width) { - this._origin.x = 0; - this._drawPosition.x = 0; - } else { - this._origin.x = (startPointTx.x - needToLeftTx); - this._drawPosition.x = (startPoint.x - needToLeft); + if (needToLeft > 0) { + locBarRect.x += needToLeft * flipXNeed; } - var needToTop = (textureSize.height - startPointTx.y) * percentageF; + //right pos + locBarRect.y = 0; + var flipYNeed = 1; + if (locSprite._flipY) { + locBarRect.y += currentDrawSize.height; + flipYNeed = -1; + } - if (size.height == this._drawSize.height) { - this._origin.y = 0; - this._drawPosition.y = 0; - } else { - this._origin.y = (textureSize.height - startPointTx.y - needToTop); - this._drawPosition.y = (startPoint.y - (startPoint.y * percentageF)); + if (needToTop > 0) { + locBarRect.y -= needToTop * flipYNeed; } + + //clip width and clip height + locBarRect.width = currentDrawSize.width; + locBarRect.height = -currentDrawSize.height; } } }); From b03882025cc8420811fe306f7539f2cdce041f86 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Tue, 3 Sep 2013 16:10:07 +0800 Subject: [PATCH 083/141] fixed #2763:fixed ccb parser bug --- extensions/CCBReader/CCBAnimationManager.js | 2 +- extensions/CCBReader/CCControlLoader.js | 2 +- extensions/CCBReader/CCSpriteLoader.js | 12 ++++++------ extensions/GUI/CCControlExtension/CCScale9Sprite.js | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/extensions/CCBReader/CCBAnimationManager.js b/extensions/CCBReader/CCBAnimationManager.js index c730a5c984..6d1effdea1 100644 --- a/extensions/CCBReader/CCBAnimationManager.js +++ b/extensions/CCBReader/CCBAnimationManager.js @@ -523,7 +523,7 @@ cc.BuilderAnimationManager = cc.Class.extend({ node.setDisplayFrame(value); } else if(propName === "color"){ var ccColor3B = value.getColor(); - if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){ node.setColor(ccColor3B); } } else if( propName === "visible"){ diff --git a/extensions/CCBReader/CCControlLoader.js b/extensions/CCBReader/CCControlLoader.js index 8f39c18974..3b3cd8283d 100644 --- a/extensions/CCBReader/CCControlLoader.js +++ b/extensions/CCBReader/CCControlLoader.js @@ -253,7 +253,7 @@ cc.Scale9SpriteLoader = cc.NodeLoader.extend({ onHandlePropTypeColor3:function(node, parent, propertyName, ccColor3B,ccbReader){ if(propertyName == PROPERTY_COLOR) { - if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){ node.setColor(ccColor3B); } } else { diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 1bf82fe10e..08ad71d13c 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -35,13 +35,13 @@ cc.SpriteLoader = cc.NodeLoader.extend({ return cc.Sprite.create(); }, - onHandlePropTypeColor3:function (node, parent, propertyName, color3BValue, ccbReader) { + onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { if (propertyName == PROPERTY_COLOR) { - if(!(color3BValue.r == 255 && color3BValue.g == 255 && color3BValue.b == 255)){ - node.setColor(color3BValue); + if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){ + node.setColor(ccColor3B); } } else { - cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, color3BValue, ccbReader); + cc.NodeLoader.prototype.onHandlePropTypeColor3.call(this, node, parent, propertyName, ccColor3B, ccbReader); } }, onHandlePropTypeByte:function (node, parent, propertyName, byteValue, ccbReader) { @@ -281,7 +281,7 @@ cc.LabelTTFLoader = cc.NodeLoader.extend({ }, onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { if (propertyName == PROPERTY_COLOR) { - if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){ node.setColor(ccColor3B); } } else { @@ -354,7 +354,7 @@ cc.LabelBMFontLoader = cc.NodeLoader.extend({ onHandlePropTypeColor3:function (node, parent, propertyName, ccColor3B, ccbReader) { if (propertyName == PROPERTY_COLOR) { - if(!(ccColor3B.r == 255 && ccColor3B.g == 255 && ccColor3B.b == 255)){ + if(ccColor3B.r !== 255 || ccColor3B.g !== 255 || ccColor3B.b !== 255){ node.setColor(ccColor3B); } } else { diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index cb5559834b..5dc3b2ed72 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -726,7 +726,7 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ if (this._spritesGenerated) { // Restore color and opacity this.setOpacity(opacity); - if(!(color.r == 255 && color.g == 255 && color.b == 255)){ + if(color.r !== 255 || color.g !== 255 || color.b !== 255){ this.setColor(color); } } From 56b9b7ee15826d01830950d19c09b8cacd6c6372 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 3 Sep 2013 16:35:19 +0800 Subject: [PATCH 084/141] closed #2748: clipping region also must use save and restore --- cocos2d/misc_nodes/CCProgressTimer.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index 57d78673e8..c8722c85cf 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -291,16 +291,14 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition; var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - if (locSprite._flipX || locSprite._flipY) { - context.save(); - if (locSprite._flipX) { - flipXOffset = -locOffsetPosition.x - locRect.width; - context.scale(-1, 1); - } - if (locSprite._flipY) { - flipYOffset = locOffsetPosition.y; - context.scale(1, -1); - } + context.save(); + if (locSprite._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (locSprite._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); } //clip @@ -333,9 +331,7 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * } } - if (locSprite._flipX || locSprite._flipY) - context.restore(); - + context.restore(); cc.INCREMENT_GL_DRAWS(1); }, From 97508b054efcdbde97fba6f8e49f19998ef0691c Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Thu, 5 Sep 2013 13:56:46 +0800 Subject: [PATCH 085/141] Issue #2226: Improve Sprite, Node, LabelTTF class define for maintainability and performance --- cocos2d/CCDirector.js | 57 +- cocos2d/CCDrawingPrimitives.js | 36 +- cocos2d/base_nodes/CCAtlasNode.js | 352 ++--- cocos2d/base_nodes/CCNode.js | 1989 +++------------------------ cocos2d/label_nodes/CCLabelAtlas.js | 3 +- cocos2d/label_nodes/CCLabelTTF.js | 898 ++---------- cocos2d/platform/CCApplication.js | 8 - cocos2d/platform/CCClass.js | 26 +- cocos2d/sprite_nodes/CCSprite.js | 1919 +++++++++----------------- 9 files changed, 1162 insertions(+), 4126 deletions(-) diff --git a/cocos2d/CCDirector.js b/cocos2d/CCDirector.js index d3d6ecdb72..399213422e 100644 --- a/cocos2d/CCDirector.js +++ b/cocos2d/CCDirector.js @@ -282,7 +282,7 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ * converts a UIKit coordinate to an OpenGL coordinate
* Useful to convert (multi) touches coordinates to the current layout (portrait or landscape) *

- * @param {cc.Point} point + * @param {cc.Point} uiPoint * @return {cc.Point} */ convertToGL:function (uiPoint) { @@ -326,7 +326,9 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ /** * Draw the scene. This method is called every frame. Don't call it manually. */ - drawScene:function () { + drawScene: null, + + _drawSceneForCanvas: function () { // calculate "global" dt this.calculateDeltaTime(); @@ -334,23 +336,6 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ if (!this._paused) this._scheduler.update(this._deltaTime); - if (cc.renderContextType === cc.CANVAS) - this._drawSceneForCanvas(); - else - this._drawSceneForWebGL(); - - this._totalFrames++; - - // swap buffers - /* if (this._openGLView) { - this._openGLView.swapBuffers(); - }*/ - - if (this._displayStats) - this._calculateMPF(); - }, - - _drawSceneForCanvas:function () { cc.renderContext.clearRect(0, 0, cc.canvas.width, -cc.canvas.height); /* to avoid flickr, nextScene MUST be here: after tick and before draw. @@ -368,9 +353,21 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ if (this._displayStats) this._showStats(); + + this._totalFrames++; + + if (this._displayStats) + this._calculateMPF(); }, - _drawSceneForWebGL:function () { + _drawSceneForWebGL: function () { + // calculate "global" dt + this.calculateDeltaTime(); + + //tick before glClear: issue #533 + if (!this._paused) + this._scheduler.update(this._deltaTime); + var gl = cc.renderContext; gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); @@ -393,6 +390,11 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ this._showStats(); cc.kmGLPopMatrix(); + + this._totalFrames++; + + if (this._displayStats) + this._calculateMPF(); }, /** @@ -1089,12 +1091,7 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ this._mouseDispatcher = mouseDispatcher; }, - _createStatsLabel:function () { - if(cc.renderContextType === cc.CANVAS) - this._createStatsLabelForCanvas(); - else - this._createStatsLabelForWebGL(); - }, + _createStatsLabel: null, _createStatsLabelForWebGL:function(){ if((cc.Director._fpsImageLoaded == null) || (cc.Director._fpsImageLoaded == false)) @@ -1171,6 +1168,14 @@ cc.Director = cc.Class.extend(/** @lends cc.Director# */{ } }); +if (cc.Browser.supportWebGL) { + cc.Director.prototype.drawScene = cc.Director.prototype._drawSceneForWebGL; + cc.Director.prototype._createStatsLabel = cc.Director.prototype._createStatsLabelForWebGL; +} else { + cc.Director.prototype.drawScene = cc.Director.prototype._drawSceneForCanvas; + cc.Director.prototype._createStatsLabel = cc.Director.prototype._createStatsLabelForCanvas; +} + /*************************************************** * implementation of DisplayLinkDirector **************************************************/ diff --git a/cocos2d/CCDrawingPrimitives.js b/cocos2d/CCDrawingPrimitives.js index 2851e42c54..d6f86e2f3e 100644 --- a/cocos2d/CCDrawingPrimitives.js +++ b/cocos2d/CCDrawingPrimitives.js @@ -55,7 +55,7 @@ cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{ /** * returns render context of drawing primitive - * @return {CanvasContext} + * @return {CanvasRenderingContext2D} */ getRenderContext:function () { return this._renderContext; @@ -63,7 +63,7 @@ cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{ /** * Constructor - * @param {CanvasContext} renderContext + * @param {CanvasRenderingContext2D} renderContext */ ctor:function (renderContext) { this._renderContext = renderContext; @@ -172,7 +172,7 @@ cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{ /** * draw a catmull rom line - * @param {cc.PointArray} points + * @param {Array} points * @param {Number} segments */ drawCatmullRom:function (points, segments) { @@ -181,7 +181,7 @@ cc.DrawingPrimitive = cc.Class.extend(/** @lends cc.DrawingPrimitive# */{ /** * draw a cardinal spline path - * @param {cc.PointArray} config + * @param {Array} config * @param {Number} tension * @param {Number} segments */ @@ -200,6 +200,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim * draws a point given x and y coordinate measured in points * @override * @param {cc.Point} point + * @param {Number} size */ drawPoint:function (point, size) { if (!size) { @@ -217,6 +218,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim * @override * @param {Array} points point of array * @param {Number} numberOfPoints + * @param {Number} size */ drawPoints:function (points, numberOfPoints, size) { if (points == null) { @@ -397,7 +399,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * draw a CatmullRom curve * @override - * @param {cc.PointArray} points + * @param {Array} points * @param {Number} segments */ drawCatmullRom:function (points, segments) { @@ -407,7 +409,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * draw a cardinal spline path * @override - * @param {cc.PointArray} config + * @param {Array} config * @param {Number} tension * @param {Number} segments */ @@ -473,7 +475,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * draw a star - * @param {CanvasContext} ctx canvas context + * @param {CanvasRenderingContext2D} ctx canvas context * @param {Number} radius * @param {cc.Color3B|cc.Color4B|cc.Color4F} color */ @@ -513,7 +515,7 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * draw a color ball - * @param {CanvasContext} ctx canvas context + * @param {CanvasRenderingContext2D} ctx canvas context * @param {Number} radius * @param {cc.Color3B|cc.Color4B|cc.Color4F} color */ @@ -551,8 +553,8 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * set the drawing color with 4 unsigned bytes * @param {Number} r red value (0 to 255) - * @param {Number} r green value (0 to 255) - * @param {Number} r blue value (0 to 255) + * @param {Number} g green value (0 to 255) + * @param {Number} b blue value (0 to 255) * @param {Number} a Alpha value (0 to 255) */ setDrawColor4B:function (r, g, b, a) { @@ -563,8 +565,8 @@ cc.DrawingPrimitiveCanvas = cc.DrawingPrimitive.extend(/** @lends cc.DrawingPrim /** * set the drawing color with 4 floats * @param {Number} r red value (0 to 1) - * @param {Number} r green value (0 to 1) - * @param {Number} r blue value (0 to 1) + * @param {Number} g green value (0 to 1) + * @param {Number} b blue value (0 to 1) * @param {Number} a Alpha value (0 to 1) */ setDrawColor4F:function (r, g, b, a) { @@ -751,7 +753,7 @@ cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ }, /** - * draws a poligon given a pointer to cc.Point coordiantes and the number of vertices measured in points. + * draws a polygon given a pointer to cc.Point coordiantes and the number of vertices measured in points. * @param {Array} vertices a pointer to cc.Point coordiantes * @param {Number} numOfVertices the number of vertices measured in points * @param {Boolean} closePolygon The polygon can be closed or open @@ -994,8 +996,8 @@ cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ /** * set the drawing color with 4 unsigned bytes * @param {Number} r red value (0 to 255) - * @param {Number} r green value (0 to 255) - * @param {Number} r blue value (0 to 255) + * @param {Number} g green value (0 to 255) + * @param {Number} b blue value (0 to 255) * @param {Number} a Alpha value (0 to 255) */ setDrawColor4B:function (r, g, b, a) { @@ -1008,8 +1010,8 @@ cc.DrawingPrimitiveWebGL = cc.DrawingPrimitive.extend({ /** * set the drawing color with 4 floats * @param {Number} r red value (0 to 1) - * @param {Number} r green value (0 to 1) - * @param {Number} r blue value (0 to 1) + * @param {Number} g green value (0 to 1) + * @param {Number} b blue value (0 to 1) * @param {Number} a Alpha value (0 to 1) */ setDrawColor4F:function (r, g, b, a) { diff --git a/cocos2d/base_nodes/CCAtlasNode.js b/cocos2d/base_nodes/CCAtlasNode.js index 1c1f4e042f..d122b3218a 100644 --- a/cocos2d/base_nodes/CCAtlasNode.js +++ b/cocos2d/base_nodes/CCAtlasNode.js @@ -25,7 +25,7 @@ ****************************************************************************/ /**

cc.AtlasNode is a subclass of cc.Node that implements the cc.RGBAProtocol and
- * cc.TextureProtocol protocol (Canvas implement)

+ * cc.TextureProtocol protocol

* *

It knows how to render a TextureAtlas object.
* If you are going to render a TextureAtlas consider subclassing cc.AtlasNode (or a subclass of cc.AtlasNode)

@@ -35,8 +35,7 @@ * @class * @extends cc.NodeRGBA */ -cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ - /// ---- common properties start ---- +cc.AtlasNode = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ RGBAProtocol:true, //! chars per row _itemsPerRow:0, @@ -144,10 +143,12 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ this._quadsToDraw = quadsToDraw; }, - /// ---- common properties end ---- _textureForCanvas:null, _originalTexture:null, + _uniformColor:null, + _colorF32Array:null, + /** initializes an cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render * @param {String} tile * @param {Number} tileWidth @@ -163,13 +164,15 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ /** * initializes an CCAtlasNode with a texture the width and height of each item measured in points and the quantity of items to render - * @param {HTMLImageElement|HTMLCanvasElement} texture + * @param {cc.Texture2D} texture * @param {Number} tileWidth * @param {Number} tileHeight * @param {Number} itemsToRender - * @returen {Boolean} + * @return {Boolean} */ - initWithTexture:function(texture, tileWidth, tileHeight, itemsToRender){ + initWithTexture:null, + + _initWithTextureForCanvas:function(texture, tileWidth, tileHeight, itemsToRender){ this._itemWidth = tileWidth; this._itemHeight = tileHeight; @@ -186,224 +189,7 @@ cc.AtlasNodeCanvas = cc.NodeRGBA.extend(/** @lends cc.AtlasNode# */{ return true; }, - /** - * @param {cc.Color3B} color3 - */ - setColor:function (color3) { - if ((this._realColor.r == color3.r) && (this._realColor.g == color3.g) && (this._realColor.b == color3.b)) - return; - var temp = new cc.Color3B(color3.r,color3.g,color3.b); - this._colorUnmodified = color3; - - if (this._opacityModifyRGB) { - temp.r = temp.r * this._displayedOpacity / 255; - temp.g = temp.g * this._displayedOpacity / 255; - temp.b = temp.b * this._displayedOpacity / 255; - } - cc.NodeRGBA.prototype.setColor.call(this, color3); - - if (this.getTexture()) { - var element = this._originalTexture.getHtmlElementObj(); - if(!element) - return; - var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); - if (cacheTextureForColor) { - var textureRect = cc.rect(0, 0, element.width, element.height); - element = cc.generateTintImage(element, cacheTextureForColor, this._realColor, textureRect); - var locTexture = new cc.Texture2D(); - locTexture.initWithElement(element); - locTexture.handleLoadedTexture(); - this.setTexture(locTexture); - } - } - }, - - /** - * @param {Number} opacity - */ - setOpacity:function (opacity) { - cc.NodeRGBA.prototype.setOpacity.call(this, opacity); - - // special opacity for premultiplied textures - if (this._opacityModifyRGB) { - this.setColor(this._colorUnmodified); - } - }, - - // cc.Texture protocol - /** - * returns the used texture - * @return {cc.Texture2D} - */ - getTexture:function () { - return this._textureForCanvas; - }, - - /** sets a new texture. it will be retained - * @param {cc.Texture2D} texture - */ - setTexture:function (texture) { - this._textureForCanvas = texture; - }, - - _calculateMaxItems:function () { - var selTexture = this.getTexture(); - var size = selTexture.getContentSize(); - - this._itemsPerColumn = 0 | (size.height / this._itemHeight); - this._itemsPerRow = 0 | (size.width / this._itemWidth); - }, - - _setIgnoreContentScaleFactor:function(ignoreContentScaleFactor){ - this._ignoreContentScaleFactor = ignoreContentScaleFactor; - } -}); - -/**

cc.AtlasNode is a subclass of cc.Node that implements the cc.RGBAProtocol and
- * cc.TextureProtocol protocol (WebGL implement)

- * - *

It knows how to render a TextureAtlas object.
- * If you are going to render a TextureAtlas consider subclassing cc.AtlasNode (or a subclass of cc.AtlasNode)

- * - *

All features from cc.Node are valid, plus the following features:
- * - opacity and RGB colors

- * @class - * @extends cc.Node - */ -cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ - /// ---- common properties start ---- - RGBAProtocol:true, - //! chars per row - _itemsPerRow:0, - //! chars per column - _itemsPerColumn:0, - //! width of each char - _itemWidth:0, - //! height of each char - _itemHeight:0, - - _colorUnmodified:null, - _textureAtlas:null, - - // protocol variables - _opacityModifyRGB:false, - _blendFunc:null, - - // quads to draw - _quadsToDraw:0, - _ignoreContentScaleFactor:false, // This variable is only used for CCLabelAtlas FPS display. So plz don't modify its value. - - ctor:function () { - cc.NodeRGBA.prototype.ctor.call(this); - this._colorUnmodified = cc.white(); - this._blendFunc = {src:cc.BLEND_SRC, dst:cc.BLEND_DST}; - this._ignoreContentScaleFactor = false; - }, - - /** updates the Atlas (indexed vertex array). - * Shall be overridden in subclasses - */ - updateAtlasValues:function () { - cc.Assert(false, "cc.AtlasNode:Abstract updateAtlasValue not overridden"); - }, - - /** cc.AtlasNode - RGBA protocol - * @return {cc.Color3B} - */ - getColor:function () { - if (this._opacityModifyRGB) - return this._colorUnmodified; - return cc.NodeRGBA.prototype.getColor.call(this); - }, - - /** - * @param {Boolean} value - */ - setOpacityModifyRGB:function (value) { - var oldColor = this.getColor(); - this._opacityModifyRGB = value; - this.setColor(oldColor); - }, - - /** - * @return {Boolean} - */ - isOpacityModifyRGB:function () { - return this._opacityModifyRGB; - }, - - /** cc.AtlasNode - CocosNodeTexture protocol - * @return {cc.BlendFunc} - */ - getBlendFunc:function () { - return this._blendFunc; - }, - - /** - * BlendFunc setter - * @param {Number | cc.BlendFunc} src - * @param {Number} dst - */ - setBlendFunc:function (src, dst) { - if (arguments.length == 1) - this._blendFunc = src; - else - this._blendFunc = {src:src, dst:dst}; - }, - - /** - * @param {cc.TextureAtlas} value - */ - setTextureAtlas:function (value) { - this._textureAtlas = value; - }, - - /** - * @return {cc.TextureAtlas} - */ - getTextureAtlas:function () { - return this._textureAtlas; - }, - - /** - * @return {Number} - */ - getQuadsToDraw:function () { - return this._quadsToDraw; - }, - - /** - * @param {Number} quadsToDraw - */ - setQuadsToDraw:function (quadsToDraw) { - this._quadsToDraw = quadsToDraw; - }, - /// ---- common properties end ---- - - _uniformColor:null, - - /** initializes an cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render - * @param {String} tile - * @param {Number} tileWidth - * @param {Number} tileHeight - * @param {Number} itemsToRender - * @return {Boolean} - */ - initWithTileFile:function (tile, tileWidth, tileHeight, itemsToRender) { - cc.Assert(tile != null, "title should not be null"); - var texture = cc.TextureCache.getInstance().addImage(tile); - return this.initWithTexture(texture, tileWidth, tileHeight, itemsToRender); - }, - - /** - * initializes an CCAtlasNode with a texture the width and height of each item measured in points and the quantity of items to render - * @param {cc.Texture2D} texture - * @param {Number} tileWidth - * @param {Number} tileHeight - * @param {Number} itemsToRender - * @returen {Boolean} - */ - initWithTexture:function(texture, tileWidth, tileHeight, itemsToRender){ + _initWithTextureForWebGL:function(texture, tileWidth, tileHeight, itemsToRender){ this._itemWidth = tileWidth; this._itemHeight = tileHeight; this._colorUnmodified = cc.WHITE; @@ -433,10 +219,12 @@ cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ return true; }, + draw:null, + /** * @param {WebGLRenderingContext} ctx renderContext */ - draw:function (ctx) { + _drawForWebGL:function (ctx) { var context = ctx || cc.renderContext; cc.NODE_DRAW_SETUP(this); cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); @@ -447,31 +235,76 @@ cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ /** * @param {cc.Color3B} color3 */ - setColor:function (color3) { - var temp = cc.Color3B(color3.r,color3.g,color3.b); + setColor:null, + + _setColorForCanvas:function (color3) { + var locRealColor = this._realColor; + if ((locRealColor.r == color3.r) && (locRealColor.g == color3.g) && (locRealColor.b == color3.b)) + return; + var temp = new cc.Color3B(color3.r,color3.g,color3.b); this._colorUnmodified = color3; if (this._opacityModifyRGB) { - temp.r = temp.r * this._displayedOpacity / 255; - temp.g = temp.g * this._displayedOpacity / 255; - temp.b = temp.b * this._displayedOpacity / 255; + var locDisplayedOpacity = this._displayedOpacity; + temp.r = temp.r * locDisplayedOpacity / 255; + temp.g = temp.g * locDisplayedOpacity / 255; + temp.b = temp.b * locDisplayedOpacity / 255; } cc.NodeRGBA.prototype.setColor.call(this, color3); - this._colorF32Array = new Float32Array([this._displayedColor.r / 255.0, this._displayedColor.g / 255.0, - this._displayedColor.b / 255.0, this._displayedOpacity / 255.0]); + + if (this.getTexture()) { + var element = this._originalTexture.getHtmlElementObj(); + if(!element) + return; + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); + if (cacheTextureForColor) { + var textureRect = cc.rect(0, 0, element.width, element.height); + element = cc.generateTintImage(element, cacheTextureForColor, this._realColor, textureRect); + var locTexture = new cc.Texture2D(); + locTexture.initWithElement(element); + locTexture.handleLoadedTexture(); + this.setTexture(locTexture); + } + } + }, + + _setColorForWebGL:function (color3) { + var temp = cc.Color3B(color3.r,color3.g,color3.b); + this._colorUnmodified = color3; + var locDisplayedOpacity = this._displayedOpacity; + if (this._opacityModifyRGB) { + temp.r = temp.r * locDisplayedOpacity / 255; + temp.g = temp.g * locDisplayedOpacity / 255; + temp.b = temp.b * locDisplayedOpacity / 255; + } + cc.NodeRGBA.prototype.setColor.call(this, color3); + var locDisplayedColor = this._displayedColor; + this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, + locDisplayedColor.b / 255.0, locDisplayedOpacity / 255.0]); }, /** * @param {Number} opacity */ - setOpacity:function (opacity) { + setOpacity: null, + + _setOpacityForCanvas: function (opacity) { + cc.NodeRGBA.prototype.setOpacity.call(this, opacity); + // special opacity for premultiplied textures + if (this._opacityModifyRGB) { + this.setColor(this._colorUnmodified); + } + }, + + _setOpacityForWebGL: function (opacity) { cc.NodeRGBA.prototype.setOpacity.call(this, opacity); // special opacity for premultiplied textures if (this._opacityModifyRGB) { this.setColor(this._colorUnmodified); } else { var locDisplayedColor = this._displayedColor; - this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, locDisplayedColor.b / 255.0, this._displayedOpacity / 255.0]); + this._colorF32Array = new Float32Array([locDisplayedColor.r / 255.0, locDisplayedColor.g / 255.0, + locDisplayedColor.b / 255.0, this._displayedOpacity / 255.0]); } }, @@ -480,25 +313,46 @@ cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ * returns the used texture * @return {cc.Texture2D} */ - getTexture:function () { + getTexture: null, + + _getTextureForCanvas: function () { + return this._textureForCanvas; + }, + + _getTextureForWebGL: function () { return this._textureAtlas.getTexture(); }, /** sets a new texture. it will be retained * @param {cc.Texture2D} texture */ - setTexture:function (texture) { + setTexture: null, + + _setTextureForCanvas: function (texture) { + this._textureForCanvas = texture; + }, + + _setTextureForWebGL: function (texture) { this._textureAtlas.setTexture(texture); this._updateBlendFunc(); this._updateOpacityModifyRGB(); }, - _calculateMaxItems:function () { + _calculateMaxItems:null, + + _calculateMaxItemsForCanvas:function () { + var selTexture = this.getTexture(); + var size = selTexture.getContentSize(); + + this._itemsPerColumn = 0 | (size.height / this._itemHeight); + this._itemsPerRow = 0 | (size.width / this._itemWidth); + }, + + _calculateMaxItemsForWebGL:function () { var selTexture = this.getTexture(); var size = selTexture.getContentSize(); - if(this._ignoreContentScaleFactor){ + if(this._ignoreContentScaleFactor) size = selTexture.getContentSizeInPixels(); - } this._itemsPerColumn = 0 | (size.height / this._itemHeight); this._itemsPerRow = 0 | (size.width / this._itemWidth); @@ -520,7 +374,23 @@ cc.AtlasNodeWebGL = cc.NodeRGBA.extend({ } }); -cc.AtlasNode = cc.Browser.supportWebGL ? cc.AtlasNodeWebGL : cc.AtlasNodeCanvas; +if(cc.Browser.supportWebGL){ + cc.AtlasNode.prototype.initWithTexture = cc.AtlasNode.prototype._initWithTextureForWebGL; + cc.AtlasNode.prototype.draw = cc.AtlasNode.prototype._drawForWebGL; + cc.AtlasNode.prototype.setColor = cc.AtlasNode.prototype._setColorForWebGL; + cc.AtlasNode.prototype.setOpacity = cc.AtlasNode.prototype._setOpacityForWebGL; + cc.AtlasNode.prototype.getTexture = cc.AtlasNode.prototype._getTextureForWebGL; + cc.AtlasNode.prototype.setTexture = cc.AtlasNode.prototype._setTextureForWebGL; + cc.AtlasNode.prototype._calculateMaxItems = cc.AtlasNode.prototype._calculateMaxItemsForWebGL; +} else { + cc.AtlasNode.prototype.initWithTexture = cc.AtlasNode.prototype._initWithTextureForCanvas; + cc.AtlasNode.prototype.draw = cc.Node.prototype.draw; + cc.AtlasNode.prototype.setColor = cc.AtlasNode.prototype._setColorForCanvas; + cc.AtlasNode.prototype.setOpacity = cc.AtlasNode.prototype._setOpacityForCanvas; + cc.AtlasNode.prototype.getTexture = cc.AtlasNode.prototype._getTextureForCanvas; + cc.AtlasNode.prototype.setTexture = cc.AtlasNode.prototype._setTextureForCanvas; + cc.AtlasNode.prototype._calculateMaxItems = cc.AtlasNode.prototype._calculateMaxItemsForCanvas; +} /** creates a cc.AtlasNode with an Atlas file the width and height of each item and the quantity of items to render * @param {String} tile diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 040ae3bc6f..12f2062c8d 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -47,9 +47,8 @@ cc.NODE_ON_EXIT = null; */ cc.s_globalOrderOfArrival = 1; - /**

cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.
- The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu. (WebGL implement)

+ The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu.

The main features of a cc.Node are:
- They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc)
@@ -67,8 +66,6 @@ cc.s_globalOrderOfArrival = 1; - position
- scale (x, y)
- rotation (in degrees, clockwise)
- - cc.Camera (an interface to gluLookAt )
- - cc.GridBase (to do mesh transformations)
- anchor point
- size
- visible
@@ -89,7 +86,6 @@ cc.s_globalOrderOfArrival = 1; -# The node will be translated (position)
-# The node will be rotated (rotation)
-# The node will be scaled (scale)
- -# The node will be moved according to the camera values (camera)

Order in transformations with grid enabled
-# The node will be translated (position)
@@ -98,9 +94,6 @@ cc.s_globalOrderOfArrival = 1; -# The grid will capture the screen
-# The node will be moved according to the camera values (camera)
-# The grid will render the captured screen

- -

Camera:
- - Each node has a camera. By default it points to the center of the cc.Node.

* @class * @extends cc.Class * @example @@ -109,8 +102,7 @@ cc.s_globalOrderOfArrival = 1; * cc.Sprite.initWithImage = function(){ * }; */ -cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ - /// ---- common properties start ---- +cc.Node = cc.Class.extend(/** @lends cc.Node# */{ _zOrder:0, _vertexZ:0.0, @@ -157,8 +149,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ _componentContainer:null, _isTransitionFinished:false, - _rotationRadiansX: 0, - _rotationRadiansY: 0, + _rotationRadiansX:0, + _rotationRadiansY:0, _initNode:function () { this._anchorPoint = cc.p(0, 0); @@ -255,7 +247,15 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** * set the dirty node */ - setNodeDirty:function () { + setNodeDirty:null, + + _setNodeDirtyForCanvas:function () { + this._setNodeDirtyForCache(); + if(this._transformDirty === false) + this._transformDirty = this._inverseDirty = true; + }, + + _setNodeDirtyForWebGL:function () { if(this._transformDirty === false) this._transformDirty = this._inverseDirty = true; }, @@ -400,11 +400,10 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ *

* @param {Number} newRotation The rotation of the node in degrees. */ - setRotation: function (newRotation) { + setRotation:function (newRotation) { this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationX * (Math.PI / 180); - this._rotationRadiansY = this._rotationY * (Math.PI / 180); - + this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); + this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, @@ -429,7 +428,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setRotationX:function (rotationX) { this._rotationX = rotationX; - this._rotationRadiansX = this._rotationX * (Math.PI / 180); + this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, @@ -453,7 +452,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setRotationY:function (rotationY) { this._rotationY = rotationY; - this._rotationRadiansY = this._rotationY * (Math.PI / 180); + this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); this.setNodeDirty(); }, @@ -478,8 +477,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ }, /** - * Gets the scale factor of the node, when X and Y have the same scale factor. - * @warning Assert when m_fScaleX != m_fScaleY. + * Returns the scale factor on X axis of this node * @return {Number} The scale factor on X axis. */ getScaleX:function () { @@ -499,8 +497,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ }, /** - * scaleY getter - * @return {Number} + * Returns the scale factor on Y axis of this node + * @return {Number} The scale factor on Y axis. */ getScaleY:function () { return this._scaleY; @@ -546,7 +544,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** *

Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner.

* @const - * @return {cc.Point} + * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates */ getPosition:function () { return cc.p(this._position.x, this._position.y); @@ -631,7 +629,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * But you can use values higher than (1,1) and lower than (0,0) too.
* The default anchorPoint is (0.5,0.5), so it starts in the center of the node.

* @const - * @return {cc.Point} The anchor point of node. + * @return {cc.Point} The anchor point of node. */ getAnchorPoint:function () { return cc.p(this._anchorPoint.x, this._anchorPoint.y); @@ -927,7 +925,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ getBoundingBox:function () { var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); - return cc.RectApplyAffineTransform(rect, this.nodeToParentTransform()); + return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform()); }, /** @@ -942,7 +940,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup); }, - /** Node description + /** + * Gets the description string. It makes debugging easier. * @return {String} */ description:function () { @@ -1023,7 +1022,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * Removes this node itself from its parent node.
* If the node orphan, then nothing happens. * @deprecated - * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. + * @param {Boolean} cleanup true if all actions and callbacks on this node should be removed, false otherwise. */ removeFromParentAndCleanup:function (cleanup) { cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead"); @@ -1037,7 +1036,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * to override this method

* * @param {cc.Node} child The child node which will be removed. - * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. + * @param {Boolean|null} [cleanup=null] true if all running actions and callbacks on the child node will be cleanup, false otherwise. */ removeChild:function (child, cleanup) { // explicit nil handling @@ -1046,9 +1045,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ if (cleanup == null) cleanup = true; - if (this._children.indexOf(child) > -1) { + if (this._children.indexOf(child) > -1) this._detachChild(child, cleanup); - } this.setNodeDirty(); }, @@ -1073,7 +1071,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. * @deprecated - * @param {Boolean | null} cleanup + * @param {Boolean | null } cleanup */ removeAllChildrenWithCleanup:function (cleanup) { cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead"); @@ -1149,8 +1147,8 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** Reorders a child according to a new z value.
* The child MUST be already added. - * @param {cc.Node} child - * @param {Number} zOrder + * @param {cc.Node} child An already added child node. It MUST be already added. + * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) */ reorderChild:function (child, zOrder) { cc.Assert(child != null, "Child must be non-nil"); @@ -1371,7 +1369,7 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * Schedules a custom selector.
* If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. * - * @param {function} callback_fn + * @param {function} callback_fn A function wrapped as a selector * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead. * @param {Number} repeat The selector will be excuted (repeat + 1) times, you can use kCCRepeatForever for tick infinitely. * @param {Number} delay The amount of time that the first tick will wait before execution. @@ -1653,7 +1651,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ removeAllComponents:function(){ this._componentContainer.removeAll(); }, - /// ---- common properties end ---- _transform4x4:null, _stackMatrix:null, @@ -1661,8 +1658,19 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ _camera:null, _grid:null, - ctor:function () { + /** + * Constructor + */ + ctor: null, + + _ctorForCanvas: function () { + this._initNode(); + }, + + _ctorForWebGL: function () { this._initNode(); + + //WebGL var mat4 = new cc.kmMat4(); mat4.mat[2] = mat4.mat[3] = mat4.mat[6] = mat4.mat[7] = mat4.mat[8] = mat4.mat[9] = mat4.mat[11] = mat4.mat[14] = 0.0; mat4.mat[10] = mat4.mat[15] = 1.0; @@ -1673,8 +1681,43 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** * recursive method that visit its children and draw them + * @param {CanvasRenderingContext2D|WebGLRenderingContext} ctx */ - visit: function () { + visit:null, + + _visitForCanvas:function (ctx) { + // quick return if not visible + if (!this._visible) + return; + + //visit for canvas + var context = ctx || cc.renderContext, i; + var children = this._children,child; + context.save(); + this.transform(context); + var len = children.length; + if (len > 0) { + this.sortAllChildren(); + // draw children zOrder < 0 + for (i = 0; i < len; i++) { + child = children[i]; + if (child._zOrder < 0) + child.visit(context); + else + break; + } + this.draw(context); + for (; i < len; i++) { + children[i].visit(context); + } + } else + this.draw(context); + + this._orderOfArrival = 0; + context.restore(); + }, + + _visitForWebGL: function(){ // quick return if not visible if (!this._visible) return; @@ -1725,7 +1768,16 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ /** * Performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes. */ - transform:function () { + transform:null, + + _transformForCanvas: function (ctx) { + // transform for canvas + var context = ctx || cc.renderContext; + var t = this.nodeToParentTransform(); + context.transform(t.a, t.b, t.c, t.d, t.tx, -t.ty); + }, + + _transformForWebGL: function () { //optimize performance for javascript var t4x4 = this._transform4x4, topMat4 = cc.current_stack.top; @@ -1765,7 +1817,87 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ * The matrix is in Pixels. * @return {cc.AffineTransform} */ - nodeToParentTransform:function () { + nodeToParentTransform: null, + + _nodeToParentTransformForCanvas:function () { + if (!this._transform) + this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0}; + if (this._transformDirty) { + var t = this._transform;// quick reference + // base position + t.tx = this._position.x; + t.ty = this._position.y; + + // rotation Cos and Sin + var Cos = 1, Sin = 0; + if (this._rotationX) { + Cos = Math.cos(this._rotationRadiansX); + Sin = Math.sin(this._rotationRadiansX); + } + + // base abcd + t.a = t.d = Cos; + t.c = -Sin; + t.b = Sin; + + var lScaleX = this._scaleX, lScaleY = this._scaleY; + var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y; + + // Firefox on Vista and XP crashes + // GPU thread in case of scale(0.0, 0.0) + var sx = (lScaleX < 0.000001 && lScaleX > -0.000001)? 0.000001 : lScaleX, + sy = (lScaleY < 0.000001 && lScaleY > -0.000001)? 0.000001 : lScaleY; + + // skew + if (this._skewX || this._skewY) { + // offset the anchorpoint + var skx = Math.tan(-this._skewX * Math.PI / 180); + var sky = Math.tan(-this._skewY * Math.PI / 180); + var xx = appY * skx * sx; + var yy = appX * sky * sy; + t.a = Cos + -Sin * sky; + t.c = Cos * skx + -Sin; + t.b = Sin + Cos * sky; + t.d = Sin * skx + Cos; + t.tx += Cos * xx + -Sin * yy; + t.ty += Sin * xx + Cos * yy; + } + + // scale + if (lScaleX !== 1 || lScaleY !== 1) { + t.a *= sx; + t.b *= sx; + t.c *= sy; + t.d *= sy; + } + + // adjust anchorPoint + t.tx += Cos * -appX * sx + -Sin * appY * sy; + t.ty -= Sin * -appX * sx + Cos * appY * sy; + + // if ignore anchorPoint + if (this._ignoreAnchorPointForPosition) { + t.tx += appX + t.ty += appY; + } + + if (this._additionalTransformDirty) { + this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform); + //Because the cartesian coordination is inverted in html5 canvas, these needs to be inverted as well + this._transform.b *= -1; + this._transform.c *= -1; + + this._additionalTransformDirty = false; + } + + t.tx = t.tx | 0; + t.ty = t.ty | 0; + this._transformDirty = false; + } + return this._transform; + }, + + _nodeToParentTransformForWebGL:function () { if (this._transformDirty) { // Translate values var x = this._position.x; @@ -1824,6 +1956,13 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ return this._transform; }, + _setNodeDirtyForCache:function () { + this._cacheDirty = true; + if (this._parent) { + this._parent._setNodeDirtyForCache(); + } + }, + /** * Returns a camera object that lets you move the node using a gluLookAt * @return {cc.Camera} A CCCamera object that lets you move the node using a gluLookAt @@ -1892,1749 +2031,6 @@ cc.NodeWebGL = cc.Class.extend(/** @lends cc.NodeWebGL# */{ */ setGLServerState:function (state) { this._glServerState = state; - } -}); - -/**

cc.Node is the main element. Anything thats gets drawn or contains things that get drawn is a cc.Node.
- The most popular cc.Nodes are: cc.Scene, cc.Layer, cc.Sprite, cc.Menu. (Canvas implement)

- -

The main features of a cc.Node are:
- - They can contain other cc.Node nodes (addChild, getChildByTag, removeChild, etc)
- - They can schedule periodic callback (schedule, unschedule, etc)
- - They can execute actions (runAction, stopAction, etc)

- -

Some cc.Node nodes provide extra functionality for them or their children.

- -

Subclassing a cc.Node usually means (one/all) of:
- - overriding init to initialize resources and schedule callbacks
- - create callbacks to handle the advancement of time
- - overriding draw to render the node

- -

Features of cc.Node:
- - position
- - scale (x, y)
- - rotation (in degrees, clockwise)
- - anchor point
- - size
- - visible
- - z-order
- - openGL z position

- -

Default values:
- - rotation: 0
- - position: (x=0,y=0)
- - scale: (x=1,y=1)
- - contentSize: (x=0,y=0)
- - anchorPoint: (x=0,y=0)

- -

Limitations:
- - A cc.Node is a "void" object. It doesn't have a texture

- -

Order in transformations with grid disabled
- -# The node will be translated (position)
- -# The node will be rotated (rotation)
- -# The node will be scaled (scale)
- -

Order in transformations with grid enabled
- -# The node will be translated (position)
- -# The node will be rotated (rotation)
- -# The node will be scaled (scale)
- -# The grid will capture the screen
- -# The node will be moved according to the camera values (camera)
- -# The grid will render the captured screen

- * @class - * @extends cc.Class - * @example - * // example - * cc.Sprite = cc.Node.extend({}); - * cc.Sprite.initWithImage = function(){ - * }; - */ -cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ - /// ---- common properties start ---- - _zOrder:0, - _vertexZ:0.0, - - _rotationX:0, - _rotationY:0.0, - _scaleX:1.0, - _scaleY:1.0, - _position:null, - _skewX:0.0, - _skewY:0.0, - // children (lazy allocs), - _children:null, - // lazy alloc, - _visible:true, - _anchorPoint:null, - _anchorPointInPoints:null, - _contentSize:null, - _running:false, - _parent:null, - // "whole screen" objects. like Scenes and Layers, should set _ignoreAnchorPointForPosition to true - _ignoreAnchorPointForPosition:false, - _tag:cc.NODE_TAG_INVALID, - // userData is always inited as nil - _userData:null, - _userObject:null, - _transformDirty:true, - _inverseDirty:true, - _cacheDirty:true, - _transformGLDirty:null, - _transform:null, - _inverse:null, - - //since 2.0 api - _reorderChildDirty:false, - _shaderProgram:null, - _orderOfArrival:0, - - _actionManager:null, - _scheduler:null, - - _initializedNode:false, - _additionalTransformDirty:false, - _additionalTransform:null, - _componentContainer:null, - _isTransitionFinished:false, - - _rotationRadiansX:0, - _rotationRadiansY:0, - - _initNode:function () { - this._anchorPoint = cc.p(0, 0); - this._anchorPointInPoints = cc.p(0, 0); - this._contentSize = cc.size(0, 0); - this._position = cc.p(0, 0); - this._children = []; - - var director = cc.Director.getInstance(); - this._actionManager = director.getActionManager(); - this._scheduler = director.getScheduler(); - this._initializedNode = true; - this._additionalTransform = cc.AffineTransformMakeIdentity(); - this._componentContainer = new cc.ComponentContainer(this); - }, - - /** - * Initializes the instance of cc.Node - * @returns {boolean} Whether the initialization was successful. - */ - init:function () { - if (this._initializedNode === false) - this._initNode(); - return true; - }, - - /** - * @param {Array} array - * @param {cc.Node.StateCallbackType} callbackType - * @private - */ - _arrayMakeObjectsPerformSelector:function (array, callbackType) { - if (!array || array.length === 0) - return; - - var i, len = array.length,node; - var nodeCallbackType = cc.Node.StateCallbackType; - switch (callbackType) { - case nodeCallbackType.onEnter: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.onEnter(); - } - break; - case nodeCallbackType.onExit: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.onExit(); - } - break; - case nodeCallbackType.onEnterTransitionDidFinish: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.onEnterTransitionDidFinish(); - } - break; - case nodeCallbackType.cleanup: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.cleanup(); - } - break; - case nodeCallbackType.updateTransform: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.updateTransform(); - } - break; - case nodeCallbackType.onExitTransitionDidStart: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.onExitTransitionDidStart(); - } - break; - case nodeCallbackType.sortAllChildren: - for (i = 0; i < len; i++) { - node = array[i]; - if (node) - node.sortAllChildren(); - } - break; - default : - throw "Unknown callback function"; - break; - } - }, - - /** - *

get the skew degrees in X
- * The X skew angle of the node in degrees.
- * This angle describes the shear distortion in the X direction.
- * Thus, it is the angle between the Y axis and the left edge of the shape
- * The default skewX angle is 0. Positive values distort the node in a CW direction.
- *

- * @return {Number} The X skew angle of the node in degrees. - */ - getSkewX:function () { - return this._skewX; - }, - - /** - *

- * Changes the X skew angle of the node in degrees.
- *
- * This angle describes the shear distortion in the X direction.
- * Thus, it is the angle between the Y axis and the left edge of the shape
- * The default skewX angle is 0. Positive values distort the node in a CW direction. - *

- * @param {Number} newSkewX The X skew angle of the node in degrees. - */ - setSkewX:function (newSkewX) { - this._skewX = newSkewX; - this.setNodeDirty(); - }, - - /** - *

get the skew degrees in Y
- * The Y skew angle of the node in degrees.
- * This angle describes the shear distortion in the Y direction.
- * Thus, it is the angle between the X axis and the bottom edge of the shape
- * The default skewY angle is 0. Positive values distort the node in a CCW direction.
- *

- * @return {Number} The Y skew angle of the node in degrees. - */ - getSkewY:function () { - return this._skewY; - }, - - /** - *

- * Changes the Y skew angle of the node in degrees. - * - * This angle describes the shear distortion in the Y direction. - * Thus, it is the angle between the X axis and the bottom edge of the shape - * The default skewY angle is 0. Positive values distort the node in a CCW direction. - *

- * @param {Number} newSkewY The Y skew angle of the node in degrees. - */ - setSkewY:function (newSkewY) { - this._skewY = newSkewY; - this.setNodeDirty(); - }, - - /** - * zOrder getter - * @return {Number} - */ - getZOrder:function () { - return this._zOrder; - }, - - /** - *

- * Sets the z order which stands for the drawing order
- *
- * This is an internal method. Don't call it outside the framework.
- * The difference between setZOrder(int) and _setOrder(int) is:
- * - _setZOrder(int) is a pure setter for m_nZOrder memeber variable
- * - setZOrder(int) firstly changes m_nZOrder, then recorder this node in its parent's chilren array. - *

- * @param {Number} z - * @private - */ - _setZOrder:function (z) { - this._zOrder = z; - }, - - /** - *

- * Sets the Z order which stands for the drawing order, and reorder this node in its parent's children array.
- *
- * The Z order of node is relative to its "brothers": children of the same parent.
- * It's nothing to do with OpenGL's z vertex. This one only affects the draw order of nodes in cocos2d.
- * The larger number it is, the later this node will be drawn in each message loop.
- * Please refer to setVertexZ(float) for the difference. - *

- * @param {Number} z Z order of this node. - */ - setZOrder:function (z) { - this._setZOrder(z); - if (this._parent) - this._parent.reorderChild(this, z); - }, - - /** - * Gets WebGL Z vertex of this node. - * @return {Number} WebGL Z vertex of this node - */ - getVertexZ:function () { - return this._vertexZ; - }, - - /** - *

- * Sets the real WebGL Z vertex.
- *
- * Differences between openGL Z vertex and cocos2d Z order:
- * - OpenGL Z modifies the Z vertex, and not the Z order in the relation between parent-children
- * - OpenGL Z might require to set 2D projection
- * - cocos2d Z order works OK if all the nodes uses the same openGL Z vertex. eg: vertexZ = 0
- *
- * @warning Use it at your own risk since it might break the cocos2d parent-children z order - *

- * @param {Number} Var - */ - setVertexZ:function (Var) { - this._vertexZ = Var; - }, - - /** - * The rotation (angle) of the node in degrees. 0 is the default rotation angle. Positive values rotate node CW. - * @return {Number} The rotation of the node in degrees. - */ - getRotation:function () { - cc.Assert(this._rotationX == this._rotationY, "CCNode#rotation. RotationX != RotationY. Don't know which one to return"); - return this._rotationX; - }, - - /** - *

- * Sets the rotation (angle) of the node in degrees.
- *
- * 0 is the default rotation angle.
- * Positive values rotate node clockwise, and negative values for anti-clockwise. - *

- * @param {Number} newRotation The rotation of the node in degrees. - */ - setRotation:function (newRotation) { - this._rotationX = this._rotationY = newRotation; - this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); - this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); - - this.setNodeDirty(); - }, - - /** - * The rotation (angle) of the node in degrees. 0 is the default rotation angle.
- * Positive values rotate node CW. It only modifies the X rotation performing a horizontal rotational skew . - * (support only in WebGl rendering mode) - * @return {Number} The X rotation in degrees. - */ - getRotationX:function () { - return this._rotationX; - }, - - /** - *

- * Sets the X rotation (angle) of the node in degrees which performs a horizontal rotational skew.
- *
- * 0 is the default rotation angle.
- * Positive values rotate node clockwise, and negative values for anti-clockwise. - *

- * @param {Number} rotationX The X rotation in degrees which performs a horizontal rotational skew. - */ - setRotationX:function (rotationX) { - this._rotationX = rotationX; - this._rotationRadiansX = this._rotationX * 0.017453292519943295; //(Math.PI / 180); - this.setNodeDirty(); - }, - - /** - * The rotation (angle) of the node in degrees. 0 is the default rotation angle.
- * Positive values rotate node CW. It only modifies the Y rotation performing a vertical rotational skew . - * @return {Number} The Y rotation in degrees. - */ - getRotationY:function () { - return this._rotationY; - }, - - /** - *

- * Sets the Y rotation (angle) of the node in degrees which performs a vertical rotational skew.
- *
- * 0 is the default rotation angle.
- * Positive values rotate node clockwise, and negative values for anti-clockwise. - *

- * @param rotationY The Y rotation in degrees. - */ - setRotationY:function (rotationY) { - this._rotationY = rotationY; - this._rotationRadiansY = this._rotationY * 0.017453292519943295; //(Math.PI / 180); - this.setNodeDirty(); - }, - - /** Get the scale factor of the node. - * @warning: Assert when _scaleX != _scaleY. - * @return {Number} - */ - getScale:function () { - cc.Assert(this._scaleX == this._scaleY, "cc.Node#scale. ScaleX != ScaleY. Don't know which one to return"); - return this._scaleX; - }, - - /** - * The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. - * @param {Number} scale or scaleX value - * @param {Number} scaleY - */ - setScale:function (scale, scaleY) { - this._scaleX = scale; - this._scaleY = scaleY === undefined ? scale : scaleY; - this.setNodeDirty(); - }, - - /** - * Returns the scale factor on X axis of this node - * @return {Number} The scale factor on X axis. - */ - getScaleX:function () { - return this._scaleX; - }, - - /** - *

- * Changes the scale factor on X axis of this node
- * The deafult value is 1.0 if you haven't changed it before - *

- * @param {Number} newScaleX The scale factor on X axis. - */ - setScaleX:function (newScaleX) { - this._scaleX = newScaleX; - this.setNodeDirty(); - }, - - /** - * Returns the scale factor on Y axis of this node - * @return {Number} The scale factor on Y axis. - */ - getScaleY:function () { - return this._scaleY; - }, - - /** - *

- * Changes the scale factor on Y axis of this node
- * The Default value is 1.0 if you haven't changed it before. - *

- * @param {Number} newScaleY The scale factor on Y axis. - */ - setScaleY:function (newScaleY) { - this._scaleY = newScaleY; - this.setNodeDirty(); - }, - - /** - *

- * Changes the position (x,y) of the node in OpenGL coordinates - * Usually we use ccp(x,y) to compose CCPoint object. - * The original point (0,0) is at the left-bottom corner of screen. - * and Passing two numbers (x,y) is much efficient than passing CCPoint object. - *

- * @param {cc.Point|Number} newPosOrxValue The position (x,y) of the node in coordinates or X coordinate for position - * @param {Number} yValue Y coordinate for position - * @example - * var size = cc.Director.getInstance().getWinSize(); - * node.setPosition( cc.p(size.width/2, size.height/2) ) - */ - setPosition:function (newPosOrxValue, yValue) { - var locPosition = this._position; - if (arguments.length == 2) { - locPosition.x = newPosOrxValue; - locPosition.y = yValue; - } else if (arguments.length == 1) { - locPosition.x = newPosOrxValue.x; - locPosition.y = newPosOrxValue.y; - } - this.setNodeDirty(); - }, - - /** - *

Position (x,y) of the node in OpenGL coordinates. (0,0) is the left-bottom corner.

- * @const - * @return {cc.Point} The position (x,y) of the node in OpenGL coordinates - */ - getPosition:function () { - return cc.p(this._position.x, this._position.y); - }, - - /** - * @return {Number} - */ - getPositionX:function () { - return this._position.x; - }, - - /** - * @param {Number} x - */ - setPositionX:function (x) { - this._position.x = x; - this.setNodeDirty(); - }, - - /** - * @return {Number} - */ - getPositionY:function () { - return this._position.y; - }, - - /** - * @param {Number} y - */ - setPositionY:function (y) { - this._position.y = y; - this.setNodeDirty(); - }, - - /** - * Get the amount of children. - * @return {Number} The amount of children. - */ - getChildrenCount:function () { - return this._children.length; - }, - - /** - * Return an array of children
- * Composing a "tree" structure is a very important feature of CCNode - * @return {Array} An array of children - * @example - * //This sample code traverses all children nodes, and set theie position to (0,0) - * var allChildren = parent.getChildren(); - * for(var i = 0; i< allChildren.length; i++) { - * allChildren[i].setPosition(0,0); - * } - */ - getChildren:function () { - return this._children; - }, - - /** - * Determines if the node is visible - * @see setVisible(bool) - * @return {Boolean} true if the node is visible, false if the node is hidden. - */ - isVisible:function () { - return this._visible; - }, - - /** - * Sets whether the node is visible
- * The default value is true, a node is default to visible - * @param {Boolean} Var true if the node is visible, false if the node is hidden. - */ - setVisible:function (Var) { - this._visible = Var; - this.setNodeDirty(); - }, - - /** - *

anchorPoint is the point around which all transformations and positioning manipulations take place.
- * It's like a pin in the node where it is "attached" to its parent.
- * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
- * But you can use values higher than (1,1) and lower than (0,0) too.
- * The default anchorPoint is (0.5,0.5), so it starts in the center of the node.

- * @const - * @return {cc.Point} The anchor point of node. - */ - getAnchorPoint:function () { - return cc.p(this._anchorPoint.x, this._anchorPoint.y); - }, - - /** - *

- * Sets the anchor point in percent.
- *
- * anchorPoint is the point around which all transformations and positioning manipulations take place.
- * It's like a pin in the node where it is "attached" to its parent.
- * The anchorPoint is normalized, like a percentage. (0,0) means the bottom-left corner and (1,1) means the top-right corner.
- * But you can use values higher than (1,1) and lower than (0,0) too.
- * The default anchorPoint is (0.5,0.5), so it starts in the center of the node. - *

- * @param {cc.Point} point The anchor point of node. - */ - setAnchorPoint:function (point) { - var locAnchorPoint = this._anchorPoint; - if (!cc.pointEqualToPoint(point, locAnchorPoint)) { - locAnchorPoint.x = point.x; - locAnchorPoint.y = point.y; - var locAPP = this._anchorPointInPoints, locSize = this._contentSize; - locAPP.x = locSize.width * point.x; - locAPP.y = locSize.height * point.y; - this.setNodeDirty(); - } - }, - - /** - * The anchorPoint in absolute pixels.
- * you can only read it. If you wish to modify it, use anchorPoint instead - * @see getAnchorPoint() - * @const - * @return {cc.Point} The anchor point in absolute pixels. - */ - getAnchorPointInPoints:function () { - return cc.p(this._anchorPointInPoints.x, this._anchorPointInPoints.y); - }, - - /** - *

The untransformed size of the node.
- * The contentSize remains the same no matter the node is scaled or rotated.
- * All nodes has a size. Layer and Scene has the same size of the screen.

- * @const - * @return {cc.Size} The untransformed size of the node. - */ - getContentSize:function () { - return cc.size(this._contentSize.width, this._contentSize.height); - }, - - /** - *

- * Sets the untransformed size of the node.
- *
- * The contentSize remains the same no matter the node is scaled or rotated.
- * All nodes has a size. Layer and Scene has the same size of the screen. - *

- * @param {cc.Size} size The untransformed size of the node. - */ - setContentSize:function (size) { - var locContentSize = this._contentSize; - if (!cc.sizeEqualToSize(size, locContentSize)) { - locContentSize.width = size.width; - locContentSize.height = size.height; - var locAPP = this._anchorPointInPoints, locAnchorPoint = this._anchorPoint; - locAPP.x = locContentSize.width * locAnchorPoint.x; - locAPP.y = locContentSize.height * locAnchorPoint.y; - this.setNodeDirty(); - } - }, - - /** - *

- * Returns whether or not the node accepts event callbacks.
- * Running means the node accept event callbacks like onEnter(), onExit(), update() - *

- * @return {Boolean} Whether or not the node is running. - */ - isRunning:function () { - return this._running; - }, - - /** - * Returns a pointer to the parent node - * @return {cc.Node} A pointer to the parnet node - */ - getParent:function () { - return this._parent; - }, - - /** - * Sets the parent node - * @param {cc.Node} Var A pointer to the parnet node - */ - setParent:function (Var) { - this._parent = Var; - }, - - /** - * Gets whether the anchor point will be (0,0) when you position this node. - * @see ignoreAnchorPointForPosition(bool) - * @return {Boolean} true if the anchor point will be (0,0) when you position this node. - */ - isIgnoreAnchorPointForPosition:function () { - return this._ignoreAnchorPointForPosition; - }, - - /** - *

- * Sets whether the anchor point will be (0,0) when you position this node.
- *
- * This is an internal method, only used by CCLayer and CCScene. Don't call it outside framework.
- * The default value is false, while in CCLayer and CCScene are true - *

- * @param {Boolean} newValue true if anchor point will be (0,0) when you position this node - */ - ignoreAnchorPointForPosition:function (newValue) { - if (newValue != this._ignoreAnchorPointForPosition) { - this._ignoreAnchorPointForPosition = newValue; - this.setNodeDirty(); - } - }, - - /** - * Returns a tag that is used to identify the node easily. - * - * @return {Number} A interger that identifies the node. - * @example - * //You can set tags to node then identify them easily. - * // set tags - * node1.setTag(TAG_PLAYER); - * node2.setTag(TAG_MONSTER); - * node3.setTag(TAG_BOSS); - * parent.addChild(node1); - * parent.addChild(node2); - * parent.addChild(node3); - * // identify by tags - * var allChildren = parent.getChildren(); - * for(var i = 0; i < allChildren.length; i++){ - * switch(node.getTag()) { - * case TAG_PLAYER: - * break; - * case TAG_MONSTER: - * break; - * case TAG_BOSS: - * break; - * } - * } - */ - getTag:function () { - return this._tag; - }, - - /** - * Changes the tag that is used to identify the node easily.
- * Please refer to getTag for the sample code. - * @param {Number} Var A interger that indentifies the node. - */ - setTag:function (Var) { - this._tag = Var; - }, - - /** - *

- * Returns a custom user data pointer
- * You can set everything in UserData pointer, a data block, a structure or an object. - *

- * @return {object} A custom user data pointer - */ - getUserData:function () { - return this._userData; - }, - - /** - *

- * Sets a custom user data pointer
- * You can set everything in UserData pointer, a data block, a structure or an object, etc. - *

- * @warning Don't forget to relfease the memroy manually,especially before you change this data pointer, and before this node is autoreleased. - * @param {object} Var A custom user data - */ - setUserData:function (Var) { - this._userData = Var; - }, - - /** - * Returns a user assigned CCObject.
- * Similar to userData, but instead of holding a void* it holds an id - * @return {object} A user assigned CCObject - */ - getUserObject:function () { - return this._userObject; - }, - - /** - *

- * Returns a user assigned CCObject
- * Similar to UserData, but instead of holding a void* it holds an object.
- * The UserObject will be retained once in this method, and the previous UserObject (if existed) will be relese.
- * The UserObject will be released in CCNode's destructure. - *

- * @param {object} newValue A user assigned CCObject - */ - setUserObject:function (newValue) { - if (this._userObject != newValue) { - this._userObject = newValue; - } - }, - - - /** - * Returns the arrival order, indecates which children is added previously. - * @return {Number} The arrival order. - */ - getOrderOfArrival:function () { - return this._orderOfArrival; - }, - - /** - *

- * Sets the arrival order when this node has a same ZOrder with other children.
- *
- * A node which called addChild subsequently will take a larger arrival order,
- * If two children have the same Z order, the child with larger arrival order will be drawn later. - *

- * @warning This method is used internally for zOrder sorting, don't change this manually - * @param {Number} Var The arrival order. - */ - setOrderOfArrival:function (Var) { - this._orderOfArrival = Var; - }, - - /** - *

Gets the CCActionManager object that is used by all actions.
- * (IMPORTANT: If you set a new cc.ActionManager, then previously created actions are going to be removed.)

- * @see setActionManager() - * @return {cc.ActionManager} A CCActionManager object. - */ - getActionManager:function () { - if (!this._actionManager) { - this._actionManager = cc.Director.getInstance().getActionManager(); - } - return this._actionManager; - }, - - /** - *

Sets the cc.ActionManager object that is used by all actions.

- * @warning If you set a new CCActionManager, then previously created actions will be removed. - * @param {cc.ActionManager} actionManager A CCActionManager object that is used by all actions. - */ - setActionManager:function (actionManager) { - if (this._actionManager != actionManager) { - this.stopAllActions(); - this._actionManager = actionManager; - } - }, - - /** - *

- * cc.Scheduler used to schedule all "updates" and timers.
- * IMPORTANT: If you set a new cc.Scheduler, then previously created timers/update are going to be removed. - *

- * @return {cc.Scheduler} A CCScheduler object. - */ - getScheduler:function () { - if (!this._scheduler) { - this._scheduler = cc.Director.getInstance().getScheduler(); - } - return this._scheduler; - }, - - /** - *

- * Sets a CCScheduler object that is used to schedule all "updates" and timers.
- *

- * @warning If you set a new CCScheduler, then previously created timers/update are going to be removed. - * @param scheduler A cc.Shdeduler object that is used to schedule all "update" and timers. - */ - setScheduler:function (scheduler) { - if (this._scheduler != scheduler) { - this.unscheduleAllCallbacks(); - this._scheduler = scheduler; - } - }, - - /** - * Returns a "local" axis aligned bounding box of the node.
- * The returned box is relative only to its parent. - * @note This method returns a temporaty variable, so it can't returns const CCRect& - * @return {cc.Rect} - */ - getBoundingBox:function () { - var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); - return cc._RectApplyAffineTransformIn(rect, this.nodeToParentTransform()); - }, - - /** - * Stops all running actions and schedulers - */ - cleanup:function () { - // actions - this.stopAllActions(); - this.unscheduleAllCallbacks(); - - // timers - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.cleanup); - }, - - /** - * Gets the description string. It makes debugging easier. - * @return {String} - */ - description:function () { - return ""; - }, - - // composition: GET - /** - * Gets a child from the container given its tag - * @param {Number} aTag An identifier to find the child node. - * @return {cc.Node} a CCNode object whose tag equals to the input parameter - */ - getChildByTag:function (aTag) { - //cc.Assert(aTag != cc.NODE_TAG_INVALID, "Invalid tag"); - var __children = this._children; - if (__children != null) { - for (var i = 0; i < __children.length; i++) { - var node = __children[i]; - if (node && node._tag == aTag) - return node; - } - } - //throw "not found"; - return null; - }, - // composition: ADD - - /**

"add" logic MUST only be on this method

- * - *

If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.

- * - * @param {cc.Node} child A child node - * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) - * @param {Number} tag A interger to identify the node easily. Please refer to setTag(int) - */ - addChild:function (child, zOrder, tag) { - if (child === this) { - console.warn('cc.Node.addChild: An Node can\'t be added as a child of itself.'); - return; - } - - cc.Assert(child != null, "Argument must be non-nil"); - if (child._parent !== null) { - cc.Assert(child._parent === null, "child already added. It can't be added again"); - return; - } - - var tmpzOrder = (zOrder != null) ? zOrder : child._zOrder; - child._tag = (tag != null) ? tag : child._tag; - this._insertChild(child, tmpzOrder); - child._parent = this; - - if (this._running) { - child.onEnter(); - // prevent onEnterTransitionDidFinish to be called twice when a node is added in onEnter - if(this._isTransitionFinished) - child.onEnterTransitionDidFinish(); - } - }, - - // composition: REMOVE - /** - * Remove itself from its parent node. If cleanup is true, then also remove all actions and callbacks.
- * If the cleanup parameter is not passed, it will force a cleanup.
- * If the node orphan, then nothing happens. - * @param {Boolean} cleanup - * @see removeFromParentAndCleanup(bool) - */ - removeFromParent:function (cleanup) { - if (this._parent) { - if (cleanup == null) - cleanup = true; - this._parent.removeChild(this, cleanup); - } - }, - - /** - * Remove itself from its parent node. - * @deprecated - * @param {Boolean} cleanup - */ - removeFromParentAndCleanup:function (cleanup) { - cc.log("removeFromParentAndCleanup is deprecated. Use removeFromParent instead"); - this.removeFromParent(cleanup); - }, - - /**

Removes a child from the container. It will also cleanup all running actions depending on the cleanup parameter.

- * If the cleanup parameter is not passed, it will force a cleanup.
- *

"remove" logic MUST only be on this method
- * If a class wants to extend the 'removeChild' behavior it only needs
- * to override this method

- * - * @param {cc.Node} child The child node which will be removed. - * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. - */ - removeChild:function (child, cleanup) { - // explicit nil handling - if (this._children.length === 0) - return; - - if (cleanup == null) - cleanup = true; - if (this._children.indexOf(child) > -1) { - this._detachChild(child, cleanup); - } - - this.setNodeDirty(); - }, - - /** - * Removes a child from the container by tag value. It will also cleanup all running actions depending on the cleanup parameter. - * If the cleanup parameter is not passed, it will force a cleanup.
- * @param {Number} tag An integer number that identifies a child node - * @param {Boolean} cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. - * @see removeChildByTag(int, bool) - */ - removeChildByTag:function (tag, cleanup) { - cc.Assert(tag != cc.NODE_TAG_INVALID, "Invalid tag"); - - var child = this.getChildByTag(tag); - if (child == null) - cc.log("cocos2d: removeChildByTag: child not found!"); - else - this.removeChild(child, cleanup); - }, - - /** - * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter. - * @deprecated - * @param {Boolean | null } cleanup - */ - removeAllChildrenWithCleanup:function (cleanup) { - cc.log("removeAllChildrenWithCleanup is deprecated. Use removeAllChildren instead"); - this.removeAllChildren(cleanup); - }, - - /** - * Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
- * If the cleanup parameter is not passed, it will force a cleanup.
- * @param {Boolean | null } cleanup true if all running actions on all children nodes should be cleanup, false oterwise. - */ - removeAllChildren:function (cleanup) { - // not using detachChild improves speed here - var __children = this._children; - if (__children != null) { - if (cleanup == null) - cleanup = true; - for (var i = 0; i < __children.length; i++) { - var node = __children[i]; - if (node) { - // IMPORTANT: - // -1st do onExit - // -2nd cleanup - if (this._running) { - node.onExitTransitionDidStart(); - node.onExit(); - } - if (cleanup) - node.cleanup(); - // set parent nil at the end - node.setParent(null); - } - } - this._children.length = 0; - } - }, - - /** - * @param {cc.Node} child - * @param {Boolean} doCleanup - * @private - */ - _detachChild:function (child, doCleanup) { - // IMPORTANT: - // -1st do onExit - // -2nd cleanup - if (this._running) { - child.onExitTransitionDidStart(); - child.onExit(); - } - - // If you don't do cleanup, the child's actions will not get removed and the - // its scheduledSelectors_ dict will not get released! - if (doCleanup) - child.cleanup(); - - // set parent nil at the end - child._parent = null; - - cc.ArrayRemoveObject(this._children, child); - }, - - /** helper used by reorderChild & add - * @param {cc.Node} child - * @param {Number} z - * @private - */ - _insertChild:function (child, z) { - this._reorderChildDirty = true; - this._children.push(child); - child._setZOrder(z); - }, - - /** Reorders a child according to a new z value.
- * The child MUST be already added. - * @param {cc.Node} child An already added child node. It MUST be already added. - * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) - */ - reorderChild:function (child, zOrder) { - cc.Assert(child != null, "Child must be non-nil"); - this._reorderChildDirty = true; - child.setOrderOfArrival(cc.s_globalOrderOfArrival++); - child._setZOrder(zOrder); - this.setNodeDirty(); - }, - - /** - *

- * Sorts the children array once before drawing, instead of every time when a child is added or reordered.
- * This appraoch can improves the performance massively. - *

- * @note Don't call this manually unless a child added needs to be removed in the same frame - */ - sortAllChildren:function () { - if (this._reorderChildDirty) { - var _children = this._children; - var i, j, length = _children.length,tempChild; - - // insertion sort - for (i = 0; i < length; i++) { - var tempItem = _children[i]; - j = i - 1; - tempChild = _children[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 ))) { - _children[j + 1] = tempChild; - j = j - 1; - tempChild = _children[j]; - } - _children[j + 1] = tempItem; - } - - //don't need to check children recursively, that's done in visit of each child - this._reorderChildDirty = false; - } - }, - - // draw - /**

Override this method to draw your own node.
- * The following GL states will be enabled by default:
- - glEnableClientState(GL_VERTEX_ARRAY);
- - glEnableClientState(GL_COLOR_ARRAY);
- - glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- - glEnable(GL_TEXTURE_2D);

- -

AND YOU SHOULD NOT DISABLE THEM AFTER DRAWING YOUR NODE

- -

But if you enable any other GL state, you should disable it after drawing your node.

- * @param {CanvasContext} ctx - */ - draw:function (ctx) { - //cc.Assert(0); - // override me - // Only use- this function to draw your staff. - // DON'T draw your stuff outside this method - }, - - /** performs OpenGL view-matrix transformation of it's ancestors.
- * Generally the ancestors are already transformed, but in certain cases (eg: attaching a FBO)
- * it's necessary to transform the ancestors again. - */ - transformAncestors:function () { - if (this._parent != null) { - this._parent.transformAncestors(); - this._parent.transform(); - } - }, - - //scene managment - /** - *

- * Event callback that is invoked every time when CCNode enters the 'stage'.
- * If the CCNode enters the 'stage' with a transition, this event is called when the transition starts.
- * During onEnter you can't access a "sister/brother" node.
- * If you override onEnter, you shall call its parent's one, e.g., CCNode::onEnter(). - *

- */ - onEnter:function () { - this._isTransitionFinished = false; - this._running = true;//should be running before resumeSchedule - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnter); - this.resumeSchedulerAndActions(); - }, - - /** - *

- * Event callback that is invoked when the CCNode enters in the 'stage'.
- * If the CCNode enters the 'stage' with a transition, this event is called when the transition finishes.
- * If you override onEnterTransitionDidFinish, you shall call its parent's one, e.g. CCNode::onEnterTransitionDidFinish() - *

- */ - onEnterTransitionDidFinish:function () { - this._isTransitionFinished = true; - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onEnterTransitionDidFinish); - }, - - /** - *

callback that is called every time the cc.Node leaves the 'stage'.
- * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition starts.

- */ - onExitTransitionDidStart:function () { - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExitTransitionDidStart); - }, - - /** - *

- * callback that is called every time the cc.Node leaves the 'stage'.
- * If the cc.Node leaves the 'stage' with a transition, this callback is called when the transition finishes.
- * During onExit you can't access a sibling node.
- * If you override onExit, you shall call its parent's one, e.g., CCNode::onExit(). - *

- */ - onExit:function () { - this._running = false; - this.pauseSchedulerAndActions(); - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.onExit); - this._componentContainer.removeAll(); - }, - - // actions - /** - * Executes an action, and returns the action that is executed.
- * The node becomes the action's target. Refer to CCAction::getTarget() - * @warning Starting from v0.8 actions don't retain their target anymore. - * @param {cc.Action} action - * @return {cc.Action} An Action pointer - */ - runAction:function (action) { - cc.Assert(action != null, "Argument must be non-nil"); - this.getActionManager().addAction(action, this, !this._running); - return action; - }, - - /** - * Stops and removes all actions from the running action list . - */ - stopAllActions:function () { - this.getActionManager().removeAllActionsFromTarget(this); - }, - - /** - * Stops and removes an action from the running action list. - * @param {cc.Action} action An action object to be removed. - */ - stopAction:function (action) { - this.getActionManager().removeAction(action); - }, - - /** - * Removes an action from the running action list by its tag. - * @param {Number} tag A tag that indicates the action to be removed. - */ - stopActionByTag:function (tag) { - cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag"); - this.getActionManager().removeActionByTag(tag, this); - }, - - /** - * Gets an action from the running action list by its tag. - * @see setTag(int), getTag(). - * @param {Number} tag - * @return {cc.Action} The action object with the given tag. - */ - getActionByTag:function (tag) { - cc.Assert(tag != cc.ACTION_TAG_INVALID, "Invalid tag"); - return this.getActionManager().getActionByTag(tag, this); - }, - - /** Returns the numbers of actions that are running plus the ones that are schedule to run (actions in actionsToAdd and actions arrays).
- * Composable actions are counted as 1 action. Example:
- * If you are running 1 Sequence of 7 actions, it will return 1.
- * If you are running 7 Sequences of 2 actions, it will return 7. - * @return {Number} The number of actions that are running plus the ones that are schedule to run - */ - numberOfRunningActions:function () { - return this.getActionManager().numberOfRunningActionsInTarget(this); - }, - - // cc.Node - Callbacks - // timers - /** - * schedules the "update" method.
- * It will use the order number 0. This method will be called every frame.
- * Scheduled methods with a lower order value will be called before the ones that have a higher order value.
- * Only one "update" method could be scheduled per node. - */ - scheduleUpdate:function () { - this.scheduleUpdateWithPriority(0); - }, - - /** - *

- * schedules the "update" callback function with a custom priority. - * This callback function will be called every frame.
- * Scheduled callback functions with a lower priority will be called before the ones that have a higher value.
- * Only one "update" callback function could be scheduled per node (You can't have 2 'update' callback functions).
- *

- * @param {Number} priority - */ - scheduleUpdateWithPriority:function (priority) { - this.getScheduler().scheduleUpdateForTarget(this, priority, !this._running); - }, - - /** - * unschedules the "update" method. - * @see scheduleUpdate(); - */ - unscheduleUpdate:function () { - this.getScheduler().unscheduleUpdateForTarget(this); - }, - - /** - * Schedules a custom selector.
- * If the selector is already scheduled, then the interval parameter will be updated without scheduling it again. - * - * @param {function} callback_fn A function wrapped as a selector - * @param {Number} interval Tick interval in seconds. 0 means tick every frame. If interval = 0, it's recommended to use scheduleUpdate() instead. - * @param {Number} repeat The selector will be excuted (repeat + 1) times, you can use kCCRepeatForever for tick infinitely. - * @param {Number} delay The amount of time that the first tick will wait before execution. - */ - schedule:function (callback_fn, interval, repeat, delay) { - interval = interval || 0; - - cc.Assert(callback_fn, "Argument must be non-nil"); - cc.Assert(interval >= 0, "Argument must be positive"); - - repeat = (repeat == null) ? cc.REPEAT_FOREVER : repeat; - delay = delay || 0; - - this.getScheduler().scheduleCallbackForTarget(this, callback_fn, interval, repeat, delay, !this._running); - }, - - /** - * Schedules a callback function that runs only once, with a delay of 0 or larger - * @see schedule(SEL_SCHEDULE, float, unsigned int, float) - * @param {function} callback_fn A function wrapped as a selector - * @param {Number} delay The amount of time that the first tick will wait before execution. - */ - scheduleOnce:function (callback_fn, delay) { - this.schedule(callback_fn, 0.0, 0, delay); - }, - - /** - * unschedules a custom callback function. - * @see schedule(SEL_SCHEDULE, float, unsigned int, float) - * @param {function} callback_fn A function wrapped as a selector - */ - unschedule:function (callback_fn) { - // explicit nil handling - if (!callback_fn) - return; - - this.getScheduler().unscheduleCallbackForTarget(this, callback_fn); - }, - - /** - * unschedule all scheduled callback functions: custom callback functions, and the 'update' callback function.
- * Actions are not affected by this method. - */ - unscheduleAllCallbacks:function () { - this.getScheduler().unscheduleAllCallbacksForTarget(this); - }, - - /** - * Resumes all scheduled selectors and actions.
- * This method is called internally by onEnter - */ - resumeSchedulerAndActions:function () { - this.getScheduler().resumeTarget(this); - this.getActionManager().resumeTarget(this); - }, - - /** - * Pauses all scheduled selectors and actions.
- * This method is called internally by onExit - */ - pauseSchedulerAndActions:function () { - this.getScheduler().pauseTarget(this); - this.getActionManager().pauseTarget(this); - }, - - /** - *

Sets the additional transform.
- * The additional transform will be concatenated at the end of nodeToParentTransform.
- * It could be used to simulate `parent-child` relationship between two nodes (e.g. one is in BatchNode, another isn't).
- *

- * @example - * // create a batchNode - * var batch= cc.SpriteBatchNode.create("Icon-114.png"); - * this.addChild(batch); - * - * // create two sprites, spriteA will be added to batchNode, they are using different textures. - * var spriteA = cc.Sprite.createWithTexture(batch->getTexture()); - * var spriteB = cc.Sprite.create("Icon-72.png"); - * - * batch.addChild(spriteA); - * - * // We can't make spriteB as spriteA's child since they use different textures. So just add it to layer. - * // But we want to simulate `parent-child` relationship for these two node. - * this.addChild(spriteB); - * - * //position - * spriteA.setPosition(ccp(200, 200)); - * - * // Gets the spriteA's transform. - * var t = spriteA.nodeToParentTransform(); - * - * // Sets the additional transform to spriteB, spriteB's postion will based on its pseudo parent i.e. spriteA. - * spriteB.setAdditionalTransform(t); - * - * //scale - * spriteA.setScale(2); - * - * // Gets the spriteA's transform. - * t = spriteA.nodeToParentTransform(); - * - * // Sets the additional transform to spriteB, spriteB's scale will based on its pseudo parent i.e. spriteA. - * spriteB.setAdditionalTransform(t); - * - * //rotation - * spriteA.setRotation(20); - * - * // Gets the spriteA's transform. - * t = spriteA.nodeToParentTransform(); - * - * // Sets the additional transform to spriteB, spriteB's rotation will based on its pseudo parent i.e. spriteA. - * spriteB.setAdditionalTransform(t); - */ - setAdditionalTransform:function (additionalTransform) { - this._additionalTransform = additionalTransform; - this._transformDirty = true; - this._additionalTransformDirty = true; - }, - - /** - * Returns the matrix that transform parent's space coordinates to the node's (local) space coordinates.
- * The matrix is in Pixels. - * @return {cc.AffineTransform} - */ - parentToNodeTransform:function () { - if (this._inverseDirty) { - this._inverse = cc.AffineTransformInvert(this.nodeToParentTransform()); - this._inverseDirty = false; - } - return this._inverse; - }, - - /** - * Retrusn the world affine transform matrix. The matrix is in Pixels. - * @return {cc.AffineTransform} - */ - nodeToWorldTransform:function () { - var t = this.nodeToParentTransform(); - for (var p = this._parent; p != null; p = p.getParent()) - t = cc.AffineTransformConcat(t, p.nodeToParentTransform()); - return t; - }, - - /** - * Returns the inverse world affine transform matrix. The matrix is in Pixels. - * @return {cc.AffineTransform} - */ - worldToNodeTransform:function () { - return cc.AffineTransformInvert(this.nodeToWorldTransform()); - }, - - /** - * Converts a Point to node (local) space coordinates. The result is in Points. - * @param {cc.Point} worldPoint - * @return {cc.Point} - */ - convertToNodeSpace:function (worldPoint) { - return cc.PointApplyAffineTransform(worldPoint, this.worldToNodeTransform()); - }, - - /** - * Converts a Point to world space coordinates. The result is in Points. - * @param {cc.Point} nodePoint - * @return {cc.Point} - */ - convertToWorldSpace:function (nodePoint) { - return cc.PointApplyAffineTransform(nodePoint, this.nodeToWorldTransform()); - }, - - /** - * Converts a Point to node (local) space coordinates. The result is in Points.
- * treating the returned/received node point as anchor relative. - * @param {cc.Point} worldPoint - * @return {cc.Point} - */ - convertToNodeSpaceAR:function (worldPoint) { - return cc.pSub(this.convertToNodeSpace(worldPoint), this._anchorPointInPoints); - }, - - /** - * Converts a local Point to world space coordinates.The result is in Points.
- * treating the returned/received node point as anchor relative. - * @param {cc.Point} nodePoint - * @return {cc.Point} - */ - convertToWorldSpaceAR:function (nodePoint) { - var pt = cc.pAdd(nodePoint, this._anchorPointInPoints); - return this.convertToWorldSpace(pt); - }, - - _convertToWindowSpace:function (nodePoint) { - var worldPoint = this.convertToWorldSpace(nodePoint); - return cc.Director.getInstance().convertToUI(worldPoint); - }, - - /** convenience methods which take a cc.Touch instead of cc.Point - * @param {cc.Touch} touch - * @return {cc.Point} - */ - convertTouchToNodeSpace:function (touch) { - var point = touch.getLocation(); - //TODO This point needn't convert to GL in HTML5 - //point = cc.Director.getInstance().convertToGL(point); - return this.convertToNodeSpace(point); - }, - - /** - * converts a cc.Touch (world coordinates) into a local coordiante. This method is AR (Anchor Relative). - * @param {cc.Touch}touch - * @return {cc.Point} - */ - convertTouchToNodeSpaceAR:function (touch) { - var point = touch.getLocation(); - point = cc.Director.getInstance().convertToGL(point); - return this.convertToNodeSpaceAR(point); - }, - - /** - * Update will be called automatically every frame if "scheduleUpdate" is called, and the node is "live"
- * (override me) - * @param {Number} dt - */ - update:function (dt) { - if(this._componentContainer && !this._componentContainer.isEmpty()) - this._componentContainer.visit(dt); - }, - - /** - *

- * Calls children's updateTransform() method recursively.
- *
- * This method is moved from CCSprite, so it's no longer specific to CCSprite.
- * As the result, you apply CCSpriteBatchNode's optimization on your customed CCNode.
- * e.g., batchNode->addChild(myCustomNode), while you can only addChild(sprite) before. - *

- */ - updateTransform:function () { - // Recursively iterate over children - this._arrayMakeObjectsPerformSelector(this._children, cc.Node.StateCallbackType.updateTransform); - }, - - /** - * Currently JavaScript Bindigns (JSB), in some cases, needs to use retain and release. This is a bug in JSB, - * and the ugly workaround is to use retain/release. So, these 2 methods were added to be compatible with JSB. - * This is a hack, and should be removed once JSB fixes the retain/release bug - */ - retain:function () { - }, - release:function () { - }, - - /** - * gets a component by its name - * @param {String} name - * @return {cc.Component} gets a component by its name - */ - getComponent:function(name){ - return this._componentContainer.getComponent(name); - }, - - /** - * adds a component - * @param {cc.Component} component - */ - addComponent:function(component){ - this._componentContainer.add(component); - }, - - /** - * removes a component by its name - * @param {String} name - */ - removeComponent:function(name){ - return this._componentContainer.remove(name); - }, - - /** - * removes all components - */ - removeAllComponents:function(){ - this._componentContainer.removeAll(); - }, - /// ---- common properties end ---- - - /** - * Constructor - */ - ctor:function () { - this._initNode(); - }, - - /** - * recursive method that visit its children and draw them - * @param {CanvasContext} ctx - */ - visit:function (ctx) { - // quick return if not visible - if (!this._visible) - return; - - //visit for canvas - var context = ctx || cc.renderContext, i; - var children = this._children,child; - context.save(); - this.transform(context); - var len = children.length; - if (len > 0) { - this.sortAllChildren(); - // draw children zOrder < 0 - for (i = 0; i < len; i++) { - child = children[i]; - if (child._zOrder < 0) - child.visit(context); - else - break; - } - this.draw(context); - for (; i < len; i++) { - children[i].visit(context); - } - } else - this.draw(context); - - this._orderOfArrival = 0; - context.restore(); - }, - - /** - * Performs OpenGL view-matrix transformation based on position, scale, rotation and other attributes. - */ - transform:function (ctx) { - // transform for canvas - var context = ctx || cc.renderContext; - var t = this.nodeToParentTransform(); - context.transform(t.a, t.b, t.c, t.d, t.tx, -t.ty); - }, - - /** Returns the matrix that transform the node's (local) space coordinates into the parent's space coordinates.
- * The matrix is in Pixels. - * @return {cc.AffineTransform} - */ - nodeToParentTransform:function () { - if (!this._transform) - this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0}; - if (this._transformDirty) { - var t = this._transform;// quick reference - // base position - t.tx = this._position.x; - t.ty = this._position.y; - - // rotation Cos and Sin - var Cos = 1, Sin = 0; - if (this._rotationX) { - Cos = Math.cos(this._rotationRadiansX); - Sin = Math.sin(this._rotationRadiansX); - } - - // base abcd - t.a = t.d = Cos; - t.c = -Sin; - t.b = Sin; - - var lScaleX = this._scaleX, lScaleY = this._scaleY; - var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y; - - // Firefox on Vista and XP crashes - // GPU thread in case of scale(0.0, 0.0) - var sx = (lScaleX < 0.000001 && lScaleX > -0.000001)? 0.000001 : lScaleX, - sy = (lScaleY < 0.000001 && lScaleY > -0.000001)? 0.000001 : lScaleY; - - // skew - if (this._skewX || this._skewY) { - // offset the anchorpoint - var skx = Math.tan(-this._skewX * Math.PI / 180); - var sky = Math.tan(-this._skewY * Math.PI / 180); - var xx = appY * skx * sx; - var yy = appX * sky * sy; - t.a = Cos + -Sin * sky; - t.c = Cos * skx + -Sin; - t.b = Sin + Cos * sky; - t.d = Sin * skx + Cos; - t.tx += Cos * xx + -Sin * yy; - t.ty += Sin * xx + Cos * yy; - } - - // scale - if (lScaleX !== 1 || lScaleY !== 1) { - t.a *= sx; - t.b *= sx; - t.c *= sy; - t.d *= sy; - } - - // adjust anchorPoint - t.tx += Cos * -appX * sx + -Sin * appY * sy; - t.ty -= Sin * -appX * sx + Cos * appY * sy; - - // if ignore anchorPoint - if (this._ignoreAnchorPointForPosition) { - t.tx += appX - t.ty += appY; - } - - if (this._additionalTransformDirty) { - this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform); - //Because the cartesian coordination is inverted in html5 canvas, these needs to be inverted as well - this._transform.b *= -1; - this._transform.c *= -1; - - this._additionalTransformDirty = false; - } - - t.tx = t.tx | 0; - t.ty = t.ty | 0; - this._transformDirty = false; - } - return this._transform; - }, - - /** - * set the dirty node - */ - setNodeDirty:function () { - this._setNodeDirtyForCache(); - if(this._transformDirty === false) - this._transformDirty = this._inverseDirty = true; - }, - - _setNodeDirtyForCache:function () { - this._cacheDirty = true; - if (this._parent) { - this._parent._setNodeDirtyForCache(); - } }, /** returns a "world" axis aligned bounding box of the node.
@@ -3661,7 +2057,21 @@ cc.NodeCanvas = cc.Class.extend(/** @lends cc.NodeCanvas# */{ } }); -cc.Node = cc.Browser.supportWebGL ? cc.NodeWebGL : cc.NodeCanvas; +if(cc.Browser.supportWebGL){ + //WebGL + cc.Node.prototype.ctor = cc.Node.prototype._ctorForWebGL; + cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForWebGL; + cc.Node.prototype.visit = cc.Node.prototype._visitForWebGL; + cc.Node.prototype.transform = cc.Node.prototype._transformForWebGL; + cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForWebGL; +}else{ + //Canvas + cc.Node.prototype.ctor = cc.Node.prototype._ctorForCanvas; + cc.Node.prototype.setNodeDirty = cc.Node.prototype._setNodeDirtyForCanvas; + cc.Node.prototype.visit = cc.Node.prototype._visitForCanvas; + cc.Node.prototype.transform = cc.Node.prototype._transformForCanvas; + cc.Node.prototype.nodeToParentTransform = cc.Node.prototype._nodeToParentTransformForCanvas; +} /** * allocates and initializes a node. @@ -3727,9 +2137,9 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ this._displayedOpacity = this._realOpacity = opacity; if (this._cascadeOpacityEnabled) { - var parentOpacity = 255; - if (this._parent && this._parent.RGBAProtocol && this._parent.isCascadeOpacityEnabled()) - parentOpacity = this._parent.getDisplayedOpacity(); + var parentOpacity = 255, locParent = this._parent; + if (locParent && locParent.RGBAProtocol && locParent.isCascadeOpacityEnabled()) + parentOpacity = locParent.getDisplayedOpacity(); this.updateDisplayedOpacity(parentOpacity); } }, @@ -3774,8 +2184,9 @@ cc.NodeRGBA = cc.Node.extend(/** @lends cc.NodeRGBA# */{ if (this._cascadeColorEnabled) { var parentColor = cc.white(); - if (this._parent && this._parent.RGBAProtocol && this._parent.isCascadeColorEnabled()) - parentColor = this._parent.getDisplayedColor(); + var locParent = this._parent; + if (locParent && locParent.RGBAProtocol && locParent.isCascadeColorEnabled()) + parentColor = locParent.getDisplayedColor(); this.updateDisplayedColor(parentColor); } }, diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index 12dd596cdc..18395bc3cd 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -163,7 +163,8 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight)); if (this._children) { var locChildren = this._children; - for (var i = 0, len = locChildren.length; i < len; i++) { + len = locChildren.length; + for (var i = 0; i < len; i++) { var node = locChildren[i]; if (node) node.setVisible(false); diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 66e8b83353..2dfb17565f 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -24,719 +24,19 @@ THE SOFTWARE. ****************************************************************************/ - -/** - * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels (Canvas implement)
- * All features from cc.TextureNode are valid in cc.LabelTTF
- * cc.LabelTTF objects are slow for js-binding on mobile devices.Consider using CCLabelAtlas or CCLabelBMFont instead.
- * Consider using cc.LabelAtlas or cc.LabelBMFont instead.
- * @class - * @extends cc.Sprite - */ -cc.LabelTTFCanvas = cc.Sprite.extend(/** @lends cc.LabelTTFCanvas# */{ - /// ---- common properties start ---- - _dimensions:null, - _hAlignment:cc.TEXT_ALIGNMENT_CENTER, - _vAlignment:cc.VERTICAL_TEXT_ALIGNMENT_TOP, - _fontName: null, - _fontSize:0.0, - _string:"", - _isMultiLine:false, - _fontStyleStr:null, - _colorStyleStr:null, - - // font shadow - _shadowEnabled:false, - _shadowOffset:null, - _shadowOpacity:0, - _shadowBlur:0, - - // font stroke - _strokeEnabled:false, - _strokeColor:null, - _strokeSize:0, - _strokeColorStr:null, - - // font tint - _textFillColor:null, - - _strokeShadowOffsetX:0, - _strokeShadowOffsetY:0, - _originalPosition:null, - _needUpdateTexture:false, - - _labelCanvas:null, - _labelContext:null, - - /** - * Constructor - */ - ctor:function () { - cc.Sprite.prototype.ctor.call(this); - this._dimensions = cc.SizeZero(); - this._hAlignment = cc.TEXT_ALIGNMENT_LEFT; - this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; - this._opacityModifyRGB = false; - this._fontStyleStr = ""; - this._colorStyleStr = ""; - this._fontName = "Arial"; - this._isMultiLine = false; - - this._shadowEnabled = false; - this._shadowOffset = cc.SizeZero(); - this._shadowOpacity = 0; - this._shadowBlur = 0; - - this._strokeEnabled = false; - this._strokeColor = cc.white(); - this._strokeSize = 0; - this._strokeColorStr = ""; - - this._textFillColor = cc.white(); - this._strokeShadowOffsetX = 0; - this._strokeShadowOffsetY = 0; - this._originalPosition = cc.PointZero(); - this._needUpdateTexture = false; - - this._setColorStyleStr(); - }, - - init:function () { - return this.initWithString(" ", this._fontName, this._fontSize); - }, - /** - * Prints out a description of this class - * @return {String} - */ - description:function () { - return ""; - }, - - setColor:function (color3) { - this.setFontFillColor(color3, true); - }, - - getColor:function(){ - return this._textFillColor; - }, - - setOpacity:function (opacity) { - if (this._opacity === opacity) - return; - cc.Sprite.prototype.setOpacity.call(this, opacity); - this._setColorStyleStr(); - this._needUpdateTexture = true; - }, - - _setColorStyleStr:function () { - var locFillColor = this._textFillColor; - this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")"; - }, - - /** - * returns the text of the label - * @return {String} - */ - getString:function () { - return this._string; - }, - - /** - * return Horizontal Alignment of cc.LabelTTF - * @return {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} - */ - getHorizontalAlignment:function () { - return this._hAlignment; - }, - - /** - * return Vertical Alignment of cc.LabelTTF - * @return {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} - */ - getVerticalAlignment:function () { - return this._vAlignment; - }, - - /** - * return Dimensions of cc.LabelTTF - * @return {cc.Size} - */ - getDimensions:function () { - return this._dimensions; - }, - - /** - * return font size of cc.LabelTTF - * @return {Number} - */ - getFontSize:function () { - return this._fontSize; - }, - - /** - * return font name of cc.LabelTTF - * @return {String} - */ - getFontName:function () { - return this._fontName; - }, - - /** - * initializes the cc.LabelTTF with a font name, alignment, dimension and font size - * @param {String} label string - * @param {String} fontName - * @param {Number} fontSize - * @param {cc.Size} [dimensions=] - * @param {Number} [hAlignment=] - * @param {Number} [vAlignment=] - * @return {Boolean} return false on error - */ - initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { - var strInfo = label + ""; - cc.Assert(strInfo != null, "cc.LabelTTF.initWithString() label is null"); - - fontSize = fontSize || 16; - dimensions = dimensions || cc.size(0, fontSize); - hAlignment = hAlignment || cc.TEXT_ALIGNMENT_LEFT; - vAlignment = vAlignment || cc.VERTICAL_TEXT_ALIGNMENT_TOP; - - if (cc.Sprite.prototype.init.call(this)) { - this._opacityModifyRGB = false; - this._dimensions = cc.size(dimensions.width, dimensions.height); - this._fontName = fontName || "Arial"; - this._hAlignment = hAlignment; - this._vAlignment = vAlignment; - this._fontSize = fontSize * cc.CONTENT_SCALE_FACTOR(); - this._fontStyleStr = this._fontSize + "px '" + fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize); - this.setString(strInfo); - this._setColorStyleStr(); - this._updateTexture(); - this._needUpdateTexture = false; - return true; - } - - return false; - }, - /// ---- common properties end ---- - - _getLabelContext:function () { - if (this._labelContext) - return this._labelContext; - - if (!this._labelCanvas) { - var locCanvas = document.createElement("canvas"); - var labelTexture = new cc.Texture2D(); - labelTexture.initWithElement(locCanvas); - this.setTexture(labelTexture); - this._labelCanvas = locCanvas; - } - this._labelContext = this._labelCanvas.getContext("2d"); - return this._labelContext; - }, - - _updateTexture:function () { - var locContext = this._getLabelContext(); - var locContentSize = this._contentSize; - - if(this._string.length === 0){ - this._labelCanvas.width = 1; - this._labelCanvas.height = locContentSize.height; - this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height)); - return true; - } - - //set size for labelCanvas - locContext.font = this._fontStyleStr; - this._updateTTF(); - var width = locContentSize.width, height = locContentSize.height; - this._labelCanvas.width = width; - this._labelCanvas.height = height; - - //draw text to labelCanvas - this._drawTTFInCanvas(locContext); - this._texture.handleLoadedTexture(); - - this.setTextureRect(cc.rect(0, 0, width, height)); - return true; - }, - - _drawTTFInCanvas: function (context) { - if (!context) - return; - - var locContentSizeHeight = this._contentSize.height, locVAlignment = this._vAlignment, locHAlignment = this._hAlignment, - locFontHeight = this._fontClientHeight; - - context.setTransform(1, 0, 0, 1, 0, locContentSizeHeight); - //this is fillText for canvas - if (context.font != this._fontStyleStr) - context.font = this._fontStyleStr; - context.fillStyle = this._colorStyleStr; - - //stroke style setup - var locStrokeEnabled = this._strokeEnabled; - if (locStrokeEnabled) { - context.lineWidth = this._strokeSize; - context.strokeStyle = this._strokeColorStr; - } - - var isNegForOffsetX = false, isNegForOffsetY = false; - //shadow style setup - if (this._shadowEnabled) { - var locShadowOffset = this._shadowOffset; - context.shadowColor = "rgba(128,128,128,1)"; - isNegForOffsetX = locShadowOffset.width < 0; - isNegForOffsetY = locShadowOffset.height < 0; - context.shadowOffsetX = locShadowOffset.width; - context.shadowOffsetY = -locShadowOffset.height; - context.shadowBlur = this._shadowBlur; - } - - context.textBaseline = cc.LabelTTF._textBaseline[locVAlignment]; - context.textAlign = cc.LabelTTF._textAlign[locHAlignment]; - - var xOffset = 0, locStrokeShadowOffsetX = this._strokeShadowOffsetX, locStrokeShadowOffsetY = this._strokeShadowOffsetY; - var yOffset = 0; - var locContentWidth = this._contentSize.width - locStrokeShadowOffsetX; - if (locHAlignment === cc.TEXT_ALIGNMENT_RIGHT) - xOffset = isNegForOffsetX ? locContentWidth + locStrokeShadowOffsetX : locContentWidth; - else if (locHAlignment === cc.TEXT_ALIGNMENT_CENTER) - xOffset = isNegForOffsetX ? locContentWidth / 2 + locStrokeShadowOffsetX : locContentWidth / 2; - else - xOffset = isNegForOffsetX ? locStrokeShadowOffsetX : 0; - if (this._isMultiLine) { - var locStrLen = this._strings.length; - if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM){ - yOffset = locFontHeight + locContentSizeHeight - locFontHeight * locStrLen; - if(isNegForOffsetY) - yOffset -= locStrokeShadowOffsetY; - } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_CENTER){ - yOffset = locFontHeight / 2 + (locContentSizeHeight - locFontHeight * locStrLen) / 2; - if(isNegForOffsetY) - yOffset -= locStrokeShadowOffsetY; - } else{ - if(isNegForOffsetY) - yOffset -= locStrokeShadowOffsetY/2; - else - yOffset += locStrokeShadowOffsetY/2; - } - - for (var i = 0; i < locStrLen; i++) { - var line = this._strings[i]; - var tmpOffsetY = -locContentSizeHeight + (locFontHeight * i) + yOffset; - if (locStrokeEnabled) - context.strokeText(line, xOffset, tmpOffsetY); - context.fillText(line, xOffset, tmpOffsetY); - } - } else { - if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM) { - yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY : 0; - if (locStrokeEnabled) - context.strokeText(this._string, xOffset, yOffset); - context.fillText(this._string, xOffset, yOffset); - } else if (locVAlignment === cc.VERTICAL_TEXT_ALIGNMENT_TOP) { - yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY/2 -locContentSizeHeight : - locContentSizeHeight + locStrokeShadowOffsetY/2; - if (locStrokeEnabled) - context.strokeText(this._string, xOffset, yOffset); - context.fillText(this._string, xOffset, yOffset); - } else { - yOffset = isNegForOffsetY ? -locStrokeShadowOffsetY -locContentSizeHeight / 2 : - locContentSizeHeight / 2; - if (locStrokeEnabled) - context.strokeText(this._string, xOffset, yOffset); - context.fillText(this._string, xOffset, yOffset); - } - } - }, - - visit:function(ctx){ - if(!this._string || this._string == "") - return; - if(this._needUpdateTexture ){ - this._needUpdateTexture = false; - this._updateTexture(); - } - var context = ctx || cc.renderContext; - cc.Sprite.prototype.visit.call(this,context); - }, - - setPosition:function(posX, posY){ - if (arguments.length == 2) - this._originalPosition = cc.p(posX, posY); - else - this._originalPosition = cc.p(posX.x, posX.y); - - //get real position - var locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0; - if(this._strokeEnabled) - locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2; - if(this._shadowEnabled){ - var locOffsetSize = this._shadowOffset; - locStrokeShadowOffsetX += locOffsetSize.width> 0?0:locOffsetSize.width; - locStrokeShadowOffsetY += locOffsetSize.height>0?0:locOffsetSize.height; - } - var realPosition = cc.p(this._originalPosition.x + locStrokeShadowOffsetX, this._originalPosition.y + locStrokeShadowOffsetY); - cc.Sprite.prototype.setPosition.call(this, realPosition); - }, - - getPosition:function(){ - return cc.p(this._originalPosition.x, this._originalPosition.y); - }, - - /** - * initializes the CCLabelTTF with a font name, alignment, dimension and font size - * @param {String} text - * @param {cc.FontDefinition} textDefinition - * @return {Boolean} - */ - initWithStringAndTextDefinition:function(text, textDefinition){ - if(!cc.Sprite.prototype.init.call(this)) - return false; - - // prepare everything needed to render the label - this._updateWithTextDefinition(textDefinition, false); - - // set the string - this.setString(text); - - return true; - }, - - /** - * set the text definition used by this label - * @param {cc.FontDefinition} theDefinition - */ - setTextDefinition:function(theDefinition){ - if (theDefinition) - this._updateWithTextDefinition(theDefinition, true); - }, - - /** - * get the text definition used by this label - * @return {cc.FontDefinition} - */ - getTextDefinition:function(){ - return this._prepareTextDefinition(false); - }, - - /** - * enable or disable shadow for the label - * @param {cc.Size} shadowOffset - * @param {Number} shadowOpacity - * @param {Number} shadowBlur - * @param {Boolean} [mustUpdateTexture=false] - */ - enableShadow:function(shadowOffset, shadowOpacity, shadowBlur, mustUpdateTexture){ - if (false === this._shadowEnabled) - this._shadowEnabled = true; - - var locShadowOffset = this._shadowOffset; - if ((locShadowOffset.width != shadowOffset.width) || (locShadowOffset.height != shadowOffset.height)) { - locShadowOffset.width = shadowOffset.width; - locShadowOffset.height = shadowOffset.height; - } - - if (this._shadowOpacity != shadowOpacity ) - this._shadowOpacity = shadowOpacity; - - if (this._shadowBlur != shadowBlur) - this._shadowBlur = shadowBlur; - - this._needUpdateTexture = true; - }, - - /** - * disable shadow rendering - * @param {Boolean} [mustUpdateTexture=false] - */ - disableShadow:function(mustUpdateTexture){ - if (this._shadowEnabled) { - this._shadowEnabled = false; - this._needUpdateTexture = true; - } - }, - - /** - * enable or disable stroke - * @param {cc.Color3B} strokeColor - * @param {Number} strokeSize - * @param {Boolean} [mustUpdateTexture=] - */ - enableStroke:function(strokeColor, strokeSize, mustUpdateTexture){ - if(this._strokeEnabled === false) - this._strokeEnabled = true; - - var locStrokeColor = this._strokeColor; - if ( (locStrokeColor.r !== strokeColor.r) || (locStrokeColor.g !== strokeColor.g) || (locStrokeColor.b !== strokeColor.b) ) { - this._strokeColor = strokeColor; - this._strokeColorStr = "rgba("+ (0 | strokeColor.r) + "," + (0 | strokeColor.g) + "," + (0 | strokeColor.b) + ", 1)"; - } - - if (this._strokeSize!== strokeSize) - this._strokeSize = strokeSize || 0; - - this._needUpdateTexture = true; - }, - - /** - * disable stroke - * @param {Boolean} mustUpdateTexture - */ - disableStroke:function(mustUpdateTexture){ - if (this._strokeEnabled){ - this._strokeEnabled = false; - this._needUpdateTexture = true; - } - }, - - /** - * set text tinting - * @param {cc.Color3B} tintColor - * @param {Boolean} mustUpdateTexture - */ - setFontFillColor:function(tintColor, mustUpdateTexture){ - var locTextFillColor = this._textFillColor; - if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b){ - this._textFillColor = tintColor; - this._setColorStyleStr(); - this._needUpdateTexture = true; - } - }, - - //set the text definition for this label - _updateWithTextDefinition:function(textDefinition, mustUpdateTexture){ - this._dimensions = cc.SizeMake(textDefinition.fontDimensions.width, textDefinition.fontDimensions.height); - this._hAlignment = textDefinition.fontAlignmentH; - this._vAlignment = textDefinition.fontAlignmentV; - - this._fontName = textDefinition.fontName; - this._fontSize = textDefinition.fontSize; - this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); - - // shadow - if ( textDefinition.shadowEnabled) - this.enableShadow(textDefinition.shadowOffset, textDefinition.shadowOpacity, textDefinition.shadowBlur, false); - - // stroke - if ( textDefinition.strokeEnabled ) - this.enableStroke(textDefinition.strokeColor, textDefinition.strokeSize, false); - - // fill color - this.setFontFillColor(textDefinition.fontFillColor, false); - - if (mustUpdateTexture) - this._updateTexture(); - }, - - _prepareTextDefinition:function(adjustForResolution){ - var texDef = new cc.FontDefinition(); - - if (adjustForResolution){ - texDef.fontSize = this._fontSize * cc.CONTENT_SCALE_FACTOR(); - texDef.fontDimensions = cc.SIZE_POINTS_TO_PIXELS(this._dimensions); - } else { - texDef.fontSize = this._fontSize; - texDef.fontDimensions = cc.SizeMake(this._dimensions.width, this._dimensions.height); - } - - texDef.fontName = this._fontName; - texDef.fontAlignmentH = this._hAlignment; - texDef.fontAlignmentV = this._vAlignment; - - // stroke - if ( this._strokeEnabled ){ - texDef.strokeEnabled = true; - var locStrokeColor = this._strokeColor; - texDef.strokeColor = new cc.Color3B(locStrokeColor.r, locStrokeColor.g, locStrokeColor.b); - texDef.strokeSize = adjustForResolution ? this._strokeSize * cc.CONTENT_SCALE_FACTOR() : this._strokeSize; - }else - texDef.strokeEnabled = false; - - // shadow - if ( this._shadowEnabled ){ - texDef.shadowEnabled = true; - texDef.shadowBlur = this._shadowBlur; - texDef.shadowOpacity = this._shadowOpacity; - - texDef.shadowOffset = adjustForResolution ? cc.SIZE_POINTS_TO_PIXELS(this._shadowOffset) - : cc.size(this._shadowOffset.width,this._shadowOffset.height); - }else - texDef._shadowEnabled = false; - - // text tint - var locTextFillColor = this._textFillColor; - texDef.fontFillColor = new cc.Color3B(locTextFillColor.r, locTextFillColor.g, locTextFillColor.b); - return texDef; - }, - - /** - * changes the string to render - * @warning Changing the string is as expensive as creating a new cc.LabelTTF. To obtain better performance use cc.LabelAtlas - * @param {String} text text for the label - */ - setString:function (text) { - text = String(text); - if (this._string != text) { - this._string = text + ""; - - // Force update - this._needUpdateTexture = true; - } - }, - - /** - * set Horizontal Alignment of cc.LabelTTF - * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment - */ - setHorizontalAlignment:function (alignment) { - if (alignment !== this._hAlignment) { - this._hAlignment = alignment; - - // Force update - this._needUpdateTexture = true; - } - }, - - /** - * set Vertical Alignment of cc.LabelTTF - * @param {cc.VERTICAL_TEXT_ALIGNMENT_TOP|cc.VERTICAL_TEXT_ALIGNMENT_CENTER|cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM} verticalAlignment - */ - setVerticalAlignment:function (verticalAlignment) { - if (verticalAlignment != this._vAlignment) { - this._vAlignment = verticalAlignment; - - // Force update - this._needUpdateTexture = true; - } - }, - - /** - * set Dimensions of cc.LabelTTF - * @param {cc.Size} dim - */ - setDimensions:function (dim) { - if (dim.width != this._dimensions.width || dim.height != this._dimensions.height) { - this._dimensions = dim; - - // Force udpate - this._needUpdateTexture = true; - } - }, - - /** - * set font size of cc.LabelTTF - * @param {Number} fontSize - */ - setFontSize:function (fontSize) { - if (this._fontSize != fontSize) { - this._fontSize = fontSize; - this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); - // Force update - this._needUpdateTexture = true; - } - }, - - /** - * set font name of cc.LabelTTF - * @param {String} fontName - */ - setFontName:function (fontName) { - if (this._fontName != fontName ) { - this._fontName = fontName; - this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); - // Force update - this._needUpdateTexture = true; - } - }, - - _updateTTF:function () { - var locDimensionsWidth = this._dimensions.width, locLabelContext = this._labelContext; - - var stringWidth = locLabelContext.measureText(this._string).width; - if(this._string.indexOf('\n') !== -1 || (locDimensionsWidth !== 0 && stringWidth > locDimensionsWidth && this._string.indexOf(" ") !== -1)) { - var strings = this._strings = this._string.split('\n'); - var lineWidths = this._lineWidths = []; - for (var i = 0; i < strings.length; i++) { - if (strings[i].indexOf(" ") !== -1 && locDimensionsWidth > 0) { - var percent = locDimensionsWidth / locLabelContext.measureText(this._strings[i]).width; - var startSearch = 0 | (percent * strings[i].length + 1); - var cutoff = startSearch; - var tempLineWidth = 0; - if (percent < 1) { - do { - cutoff = strings[i].lastIndexOf(" ", cutoff - 1); - var str = strings[i].substring(0, cutoff); - tempLineWidth = locLabelContext.measureText(str).width; - if (cutoff === -1) { - cutoff = strings[i].indexOf(" ", startSearch); - break; - } - } while (tempLineWidth > locDimensionsWidth); - var newline = strings[i].substr(cutoff + 1); - strings.splice(i + 1, 0, newline); - strings[i] = str; - } - } - lineWidths[i] = tempLineWidth || locLabelContext.measureText(strings[i]).width; - } - this._isMultiLine = true; - } else - this._isMultiLine = false; - - var locSize, locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0; - if(this._strokeEnabled) - locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2; - if(this._shadowEnabled){ - var locOffsetSize = this._shadowOffset; - locStrokeShadowOffsetX += Math.abs(locOffsetSize.width); - locStrokeShadowOffsetY += Math.abs(locOffsetSize.height); - } - - //get offset for stroke and shadow - if (locDimensionsWidth === 0) { - if (this._isMultiLine) - locSize = cc.size(0 | (Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); - else - locSize = cc.size(0 | (stringWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); - } else { - if(this._dimensions.height === 0){ - if (this._isMultiLine) - locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); - else - locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); - } else { - //dimension is already set, contentSize must be same as dimension - locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY)); - } - } - this.setContentSize(locSize); - this._strokeShadowOffsetX = locStrokeShadowOffsetX; - this._strokeShadowOffsetY = locStrokeShadowOffsetY; - - this._anchorPointInPoints.x = this._contentSize.width * this._anchorPoint.x; - this._anchorPointInPoints.y = this._contentSize.height * this._anchorPoint.y; - - this.setPosition(this._originalPosition); - } -}); - /** - * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels (WebGL implement)
+ * cc.LabelTTF is a subclass of cc.TextureNode that knows how to render text labels
* All features from cc.TextureNode are valid in cc.LabelTTF
- * cc.LabelTTF objects are slow for js-binding on mobile devices.
+ * cc.LabelTTF objects are slow for js-binding on mobile devices.Consider using cc.LabelAtlas or cc.LabelBMFont instead.
* Consider using cc.LabelAtlas or cc.LabelBMFont instead.
* @class * @extends cc.Sprite */ -cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ - /// ---- common properties start ---- +cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ _dimensions:null, _hAlignment:cc.TEXT_ALIGNMENT_CENTER, _vAlignment:cc.VERTICAL_TEXT_ALIGNMENT_TOP, - _fontName : null, + _fontName: null, _fontSize:0.0, _string:"", _isMultiLine:false, @@ -763,6 +63,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ _strokeShadowOffsetY:0, _originalPosition:null, _needUpdateTexture:false, + _labelCanvas:null, _labelContext:null, @@ -772,14 +73,12 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ ctor:function () { cc.Sprite.prototype.ctor.call(this); this._dimensions = cc.SizeZero(); - this._hAlignment = cc.TEXT_ALIGNMENT_CENTER; + this._hAlignment = cc.TEXT_ALIGNMENT_LEFT; this._vAlignment = cc.VERTICAL_TEXT_ALIGNMENT_TOP; this._opacityModifyRGB = false; this._fontStyleStr = ""; this._colorStyleStr = ""; this._fontName = "Arial"; - this._opacity = 255; - this._color = cc.white(); this._isMultiLine = false; this._shadowEnabled = false; @@ -794,7 +93,6 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ this._textFillColor = cc.white(); this._fillColorStr = "rgba(255,255,255,1)"; - this._strokeShadowOffsetX = 0; this._strokeShadowOffsetY = 0; this._originalPosition = cc.PointZero(); @@ -814,6 +112,28 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ return ""; }, + setColor: null, + + _setColorForCanvas: function (color3) { + this.setFontFillColor(color3, true); + }, + + getColor: null, + + _getColorForCanvas: function () { + return this._textFillColor; + }, + + setOpacity: null, + + _setOpacityForCanvas: function (opacity) { + if (this._opacity === opacity) + return; + cc.Sprite.prototype.setOpacity.call(this, opacity); + this._setColorStyleStr(); + this._needUpdateTexture = true; + }, + _setColorStyleStr:function () { var locFillColor = this._textFillColor; this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")"; @@ -872,9 +192,9 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {String} label string * @param {String} fontName * @param {Number} fontSize - * @param {cc.Size} dimensions - * @param {Number} hAlignment - * @param {Number} vAlignment + * @param {cc.Size} [dimensions=] + * @param {Number} [hAlignment=] + * @param {Number} [vAlignment=] * @return {Boolean} return false on error */ initWithString:function (label, fontName, fontSize, dimensions, hAlignment, vAlignment) { @@ -893,16 +213,16 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ this._hAlignment = hAlignment; this._vAlignment = vAlignment; this._fontSize = fontSize * cc.CONTENT_SCALE_FACTOR(); - this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; - this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); + this._fontStyleStr = this._fontSize + "px '" + fontName + "'"; + this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize); this.setString(strInfo); + this._setColorStyleStr(); this._updateTexture(); this._needUpdateTexture = false; return true; } return false; }, - /// ---- common properties end ---- /** * initializes the CCLabelTTF with a font name, alignment, dimension and font size @@ -910,7 +230,22 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {cc.FontDefinition} textDefinition * @return {Boolean} */ - initWithStringAndTextDefinition:function(text, textDefinition){ + initWithStringAndTextDefinition:null, + + _initWithStringAndTextDefinitionForCanvas:function(text, textDefinition){ + if(!cc.Sprite.prototype.init.call(this)) + return false; + + // prepare everything needed to render the label + this._updateWithTextDefinition(textDefinition, false); + + // set the string + this.setString(text); + + return true; + }, + + _initWithStringAndTextDefinitionForWebGL:function(text, textDefinition){ if(!cc.Sprite.prototype.init.call(this)) return false; @@ -954,11 +289,10 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ if (false === this._shadowEnabled) this._shadowEnabled = true; - if(this._shadowOffset){ - if ((this._shadowOffset.width != shadowOffset.width) || (this._shadowOffset.height != shadowOffset.height)) { - this._shadowOffset.width = shadowOffset.width; - this._shadowOffset.height = shadowOffset.height; - } + var locShadowOffset = this._shadowOffset; + if (locShadowOffset && (locShadowOffset.width != shadowOffset.width) || (locShadowOffset.height != shadowOffset.height)) { + locShadowOffset.width = shadowOffset.width; + locShadowOffset.height = shadowOffset.height; } if (this._shadowOpacity != shadowOpacity ) @@ -1000,7 +334,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ if (this._strokeSize!== strokeSize) this._strokeSize = strokeSize || 0; - this._needUpdateTexture = true; + this._needUpdateTexture = true; }, /** @@ -1019,27 +353,41 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {cc.Color3B} tintColor * @param {Boolean} [mustUpdateTexture=false] */ - setFontFillColor:function(tintColor, mustUpdateTexture){ + setFontFillColor:null, + + _setFontFillColorForCanvas: function (tintColor, mustUpdateTexture) { + var locTextFillColor = this._textFillColor; + if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) { + this._textFillColor = tintColor; + this._setColorStyleStr(); + this._needUpdateTexture = true; + } + }, + + _setFontFillColorForWebGL: function (tintColor, mustUpdateTexture) { var locTextFillColor = this._textFillColor; - if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b){ + if (locTextFillColor.r != tintColor.r || locTextFillColor.g != tintColor.g || locTextFillColor.b != tintColor.b) { this._textFillColor = tintColor; - this._fillColorStr = "rgba("+ (0 | tintColor.r) + "," + (0 | tintColor.g) + "," + (0 | tintColor.b) + ", 1)"; + this._fillColorStr = "rgba(" + (0 | tintColor.r) + "," + (0 | tintColor.g) + "," + (0 | tintColor.b) + ", 1)"; this._needUpdateTexture = true; } }, //set the text definition for this label _updateWithTextDefinition:function(textDefinition, mustUpdateTexture){ - if(textDefinition.fontDimensions) - this._dimensions = cc.SizeMake(textDefinition.fontDimensions.width, textDefinition.fontDimensions.height); - else - this._dimensions = cc.SizeMake(0,0); + if(textDefinition.fontDimensions){ + this._dimensions.width = textDefinition.fontDimensions.width; + this._dimensions.height = textDefinition.fontDimensions.height; + } else { + this._dimensions.width = 0; + this._dimensions.height = 0; + } this._hAlignment = textDefinition.fontAlignmentH; this._vAlignment = textDefinition.fontAlignmentV; this._fontName = textDefinition.fontName; - this._fontSize = textDefinition.fontSize || 12; + this._fontSize = textDefinition.fontSize||12; this._fontStyleStr = this._fontSize + "px '" + this._fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,this._fontSize); @@ -1120,7 +468,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {cc.TEXT_ALIGNMENT_LEFT|cc.TEXT_ALIGNMENT_CENTER|cc.TEXT_ALIGNMENT_RIGHT} alignment Horizontal Alignment */ setHorizontalAlignment:function (alignment) { - if (alignment != this._hAlignment) { + if (alignment !== this._hAlignment) { this._hAlignment = alignment; // Force update @@ -1159,7 +507,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {Number} fontSize */ setFontSize:function (fontSize) { - if (this._fontSize != fontSize) { + if (this._fontSize !== fontSize) { this._fontSize = fontSize; this._fontStyleStr = fontSize + "px '" + this._fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(this._fontName,fontSize); @@ -1173,7 +521,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ * @param {String} fontName */ setFontName:function (fontName) { - if (this._fontName && this._fontName != fontName) { + if (this._fontName && this._fontName != fontName ) { this._fontName = fontName; this._fontStyleStr = this._fontSize + "px '" + fontName + "'"; this._fontClientHeight = cc.LabelTTF.__getFontHeightByDiv(fontName,this._fontSize); @@ -1182,7 +530,7 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ } }, - _drawTTFInCanvasForWebGL: function (context) { + _drawTTFInCanvas: function (context) { if (!context) return; @@ -1193,7 +541,10 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ //this is fillText for canvas if (context.font != this._fontStyleStr) context.font = this._fontStyleStr; - context.fillStyle = "rgba(255,255,255,1)"; + if(cc.renderContextType === cc.CANVAS) + context.fillStyle = this._colorStyleStr; + else + context.fillStyle = "rgba(255,255,255,1)"; //stroke style setup var locStrokeEnabled = this._strokeEnabled; @@ -1275,10 +626,11 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ return this._labelContext; if (!this._labelCanvas) { - this._labelCanvas = document.createElement("canvas"); + var locCanvas = document.createElement("canvas"); var labelTexture = new cc.Texture2D(); - labelTexture.initWithElement(this._labelCanvas); + labelTexture.initWithElement(locCanvas); this.setTexture(labelTexture); + this._labelCanvas = locCanvas; } this._labelContext = this._labelCanvas.getContext("2d"); return this._labelContext; @@ -1330,18 +682,19 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ //get offset for stroke and shadow if (locDimensionsWidth === 0) { if (this._isMultiLine) - locSize = cc.size(Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); + locSize = cc.size(0 | (Math.max.apply(Math, this._lineWidths) + locStrokeShadowOffsetX), + 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); else - locSize = cc.size(stringWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); + locSize = cc.size(0 | (stringWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); } else { if(this._dimensions.height === 0){ if (this._isMultiLine) - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, (this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | ((this._fontClientHeight * this._strings.length) + locStrokeShadowOffsetY)); else - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._fontClientHeight + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._fontClientHeight + locStrokeShadowOffsetY)); } else { //dimension is already set, contentSize must be same as dimension - locSize = cc.size(locDimensionsWidth + locStrokeShadowOffsetX, this._dimensions.height + locStrokeShadowOffsetY); + locSize = cc.size(0 | (locDimensionsWidth + locStrokeShadowOffsetX), 0 | (this._dimensions.height + locStrokeShadowOffsetY)); } } this.setContentSize(locSize); @@ -1378,45 +731,50 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ }, _updateTexture:function () { - this._labelContext = this._getLabelContext(); + var locContext = this._getLabelContext(), locLabelCanvas = this._labelCanvas; + var locContentSize = this._contentSize; if(this._string.length === 0){ - this._labelCanvas.width = 1; - this._labelCanvas.height = this._contentSize.height; - this.setTextureRect(cc.rect(0, 0, 1, this._contentSize.height)); + locLabelCanvas.width = 1; + locLabelCanvas.height = locContentSize.height; + this.setTextureRect(cc.rect(0, 0, 1, locContentSize.height)); return true; } //set size for labelCanvas - this._labelContext.font = this._fontStyleStr; + locContext.font = this._fontStyleStr; this._updateTTF(); - var width = this._contentSize.width, height = this._contentSize.height; - this._labelCanvas.width = width; - this._labelCanvas.height = height; + var width = locContentSize.width, height = locContentSize.height; + locLabelCanvas.width = width; + locLabelCanvas.height = height; //draw text to labelCanvas - this._drawTTFInCanvasForWebGL(this._labelContext); - + this._drawTTFInCanvas(locContext); this._texture.handleLoadedTexture(); this.setTextureRect(cc.rect(0, 0, width, height)); return true; }, - visit:function(){ + visit:function(ctx){ + if(!this._string || this._string == "") + return; if(this._needUpdateTexture ){ this._needUpdateTexture = false; this._updateTexture(); } - cc.Sprite.prototype.visit.call(this); + var context = ctx || cc.renderContext; + cc.Sprite.prototype.visit.call(this,context); }, + draw: null, + /** * draw sprite to canvas * @param {WebGLRenderingContext} ctx 3d context of canvas */ - draw:function (ctx) { - if(!this._string || this._string == "") + _drawForWebGL: function (ctx) { + if (!this._string || this._string == "") return; var gl = ctx || cc.renderContext, locTexture = this._texture; @@ -1447,11 +805,12 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ if (cc.SPRITE_DEBUG_DRAW === 1) { // draw bounding box + var locQuad = this._quad; var verticesG1 = [ - cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y), - 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(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) { @@ -1463,15 +822,24 @@ cc.LabelTTFWebGL = cc.Sprite.extend(/** @lends cc.LabelTTFWebGL# */{ cc.drawingUtil.drawPoly(verticesG2, 4, true); } // CC_SPRITE_DEBUG_DRAW cc.g_NumberOfDraws++; - }, - - releaseTexture:function(){ - if(this._texture) - this._texture.releaseTexture(); } }); -cc.LabelTTF = (cc.Browser.supportWebGL) ? cc.LabelTTFWebGL : cc.LabelTTFCanvas; +if(cc.Browser.supportWebGL){ + cc.LabelTTF.prototype.setColor = cc.Sprite.prototype.setColor; + cc.LabelTTF.prototype.getColor = cc.Sprite.prototype.getColor; + cc.LabelTTF.prototype.setOpacity = cc.Sprite.prototype.setOpacity; + cc.LabelTTF.prototype.initWithStringAndTextDefinition = cc.LabelTTF.prototype._initWithStringAndTextDefinitionForWebGL; + cc.LabelTTF.prototype.setFontFillColor = cc.LabelTTF.prototype._setFontFillColorForWebGL; + cc.LabelTTF.prototype.draw = cc.LabelTTF.prototype._drawForWebGL; +} else { + cc.LabelTTF.prototype.setColor = cc.LabelTTF.prototype._setColorForCanvas; + cc.LabelTTF.prototype.getColor = cc.LabelTTF.prototype._getColorForCanvas; + cc.LabelTTF.prototype.setOpacity = cc.LabelTTF.prototype._setOpacityForCanvas; + cc.LabelTTF.prototype.initWithStringAndTextDefinition = cc.LabelTTF.prototype._initWithStringAndTextDefinitionForCanvas; + cc.LabelTTF.prototype.setFontFillColor = cc.LabelTTF.prototype._setFontFillColorForCanvas; + cc.LabelTTF.prototype.draw = cc.Sprite.prototype.draw; +} cc.LabelTTF._textAlign = ["left", "center", "right"]; diff --git a/cocos2d/platform/CCApplication.js b/cocos2d/platform/CCApplication.js index 5ccf92c4bb..57d130e2b4 100644 --- a/cocos2d/platform/CCApplication.js +++ b/cocos2d/platform/CCApplication.js @@ -227,14 +227,6 @@ cc.setup = function (el, width, height) { cc.setContextMenuEnable(false); - //binding window size - /* - cc.canvas.addEventListener("resize", function () { - if (!cc.firstRun) { - cc.Director.getInstance().addRegionToDirtyRegion(cc.rect(0, 0, cc.canvas.width, cc.canvas.height)); - } - }, true); - */ if(cc.Browser.isMobile){ cc._addUserSelectStatus(); cc._addBottomTag(); diff --git a/cocos2d/platform/CCClass.js b/cocos2d/platform/CCClass.js index cfe9295024..5f88fe391b 100644 --- a/cocos2d/platform/CCClass.js +++ b/cocos2d/platform/CCClass.js @@ -84,8 +84,7 @@ ClassManager.getNewID=function(){ (function () { var initializing = false, fnTest = /\b_super\b/; var releaseMode = (document['ccConfig'] && document['ccConfig']['CLASS_RELEASE_MODE']) ? document['ccConfig']['CLASS_RELEASE_MODE'] : null; - if(releaseMode) - { + if(releaseMode) { console.log("release Mode"); } @@ -117,12 +116,10 @@ ClassManager.getNewID=function(){ // these function properties cacheable in Carakan. var desc = { writable: true, enumerable: false, configurable: true }; for (var name in prop) { - if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) - { + if(releaseMode && typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])) { desc.value = ClassManager.compileSuper(prop[name], name, classId); Object.defineProperty(prototype, name, desc); - } - else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){ + } else if(typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name])){ desc.value = (function (name, fn) { return function () { var tmp = this._super; @@ -140,12 +137,10 @@ ClassManager.getNewID=function(){ }; })(name, prop[name]); Object.defineProperty(prototype, name, desc); - } - else if(typeof prop[name] == "function") { + } else if(typeof prop[name] == "function") { desc.value = prop[name]; Object.defineProperty(prototype, name, desc); - } - else{ + } else{ prototype[name] = prop[name]; } } @@ -167,13 +162,20 @@ ClassManager.getNewID=function(){ // See https://github.com/oupengsoftware/v8/wiki/Dictionary-mode-%28English%29#wiki-append-property // // for principles under the hood. - var functionBody = releaseMode? "": "this._super=null;"; + /*var functionBody = releaseMode? "": "this._super=null;"; for (var p in prototype) { functionBody += "this." + p + "=this." + p + ";"; } if (prototype.ctor) functionBody += "this.ctor.apply(this,arguments)"; - var Class = new Function(functionBody); + var Class = new Function(functionBody);*/ + + // The dummy Class constructor + function Class() { + // All construction is actually done in the init method + if (this.ctor) + this.ctor.apply(this, arguments); + } Class.id = classId; // desc = { writable: true, enumerable: false, configurable: true, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 2903ae8c78..47784e799d 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -25,7 +25,7 @@ ****************************************************************************/ /** - * cc.Sprite invalid index on the cc.SpriteBatchode + * cc.Sprite invalid index on the cc.SpriteBatchNode * @constant * @type Number */ @@ -264,7 +264,7 @@ if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) { } /** - *

cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) (Canvas implement)
+ *

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.
* @@ -292,8 +292,7 @@ if (cc.SPRITEBATCHNODE_RENDER_SUBPIXEL) { * var aSprite = new cc.Sprite(); * aSprite.initWithFile("HelloHTML5World.png",cc.rect(0,0,480,320)); */ -cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ - /// ---- common properties start ---- +cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ RGBAProtocol:true, // // Data used when the sprite is rendered using a CCSpriteSheet @@ -331,7 +330,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ _flipX:false, //Whether the sprite is flipped horizontally or not. _flipY:false, //Whether the sprite is flipped vertically or not. - _textureLoaded: false, + _textureLoaded:false, _loadedEventListeners: null, _newTextureWhenChangeColor: null, //hack property for LabelBMFont @@ -369,15 +368,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ }, /** - * Returns the quad (tex coords, vertex coords and color) information. (Use in WebGL model only) - * @return {null} - */ - getQuad:function () { - return null; - }, - - /** - * returns whether or not the texture rectangle is rotated + * Returns whether or not the texture rectangle is rotated. * @return {Boolean} */ isTextureRectRotated:function () { @@ -425,6 +416,22 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ 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} @@ -463,7 +470,15 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ return ret; }, - _spriteFrameLoadedCallback:function(spriteFrame){ + _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(); @@ -600,8 +615,10 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // recursively set dirty var locChildren = this._children; if (locChildren != null) { - for (var i = 0; i < locChildren.length; i++) - locChildren[i].setDirtyRecursively(true); + for (var i = 0; i < locChildren.length; i++) { + if (locChildren[i] instanceof cc.Sprite) + locChildren[i].setDirtyRecursively(true); + } } }, @@ -694,7 +711,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ *

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} [scaleY=] + * @param {Number|null} [scaleY=] * @override */ setScale:function (scale, scaleY) { @@ -797,13 +814,20 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // // RGBA protocol // - - // RGBAProtocol /** - * opacity: conforms to cc.RGBAProtocol protocol + * opacity: conforms to CCRGBAProtocol protocol * @param {Boolean} modify */ - setOpacityModifyRGB:function (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(); @@ -818,7 +842,13 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ return this._opacityModifyRGB; }, - updateDisplayedOpacity:function (parentOpacity) { + 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._changeTextureColor(); this.setNodeDirty(); @@ -865,28 +895,66 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ getTexture:function () { return this._texture; }, - /// ---- common properties end ---- + _quad:null, // vertex coords, texture coords and color info + _quadWebBuffer:null, + _quadDirty:false, _colorized:false, _isLighterMode:false, _originalTexture:null, /** * Constructor - * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement} fileName sprite construct parameter + * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter */ - ctor:function (fileName) { + 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._blendFunc = {src: cc.BLEND_SRC, dst: cc.BLEND_DST}; + + this._quad = new cc.V3F_C4B_T2F_Quad(); + this._quadWebBuffer = cc.renderContext.createBuffer(); + this._quadDirty = true; + this._textureLoaded = true; this._loadedEventListeners = []; + + 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._newTextureWhenChangeColor = false; + this._textureLoaded = true; + this._loadedEventListeners = []; if (fileName) { - if (typeof(fileName) == "string") { + if (typeof(fileName) === "string") { var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(fileName); this.initWithSpriteFrame(frame); } else if (typeof(fileName) === "object") { @@ -896,24 +964,41 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ var texture2d = new cc.Texture2D(); texture2d.initWithElement(fileName); texture2d.handleLoadedTexture(); - this.initWithTexture(texture2d) + this.initWithTexture(texture2d); } else if (fileName instanceof cc.Texture2D) { - this.initWithTexture(fileName) + 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:function (src, dst) { + setBlendFunc: null, + + _setBlendFuncForWebGL: function (src, dst) { + if (arguments.length == 1) + this._blendFunc = src; + else + this._blendFunc = {src: src, dst: dst}; + }, + + _setBlendFuncForCanvas: function (src, dst) { if (arguments.length == 1) this._blendFunc = src; else - this._blendFunc = {src:src, dst:dst}; + this._blendFunc = {src: src, dst: dst}; this._isLighterMode = (this._blendFunc && (this._blendFunc.src === gl.SRC_ALPHA) && (this._blendFunc.dst === gl.ONE)); }, @@ -921,7 +1006,46 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ * Initializes an empty sprite with nothing init. * @return {Boolean} */ - init:function () { + 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._flipX = this._flipY = false; + + // default transform anchor: center + this.setAnchorPoint(cc.p(0.5, 0.5)); + + // zwoptex default values + this._offsetPosition = cc.PointZero(); + 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]); @@ -981,18 +1105,79 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ }, /** - * Initializes a sprite with a texture and a rect in points, optionally rotated.
+ * 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. + * @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:function (texture, rect, rotated) { + 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._flipX = this._flipY = false; + + // default transform anchor: center + this.setAnchorPoint(cc.p(0.5, 0.5)); + + // zwoptex default values + this._offsetPosition = cc.p(0, 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; + this._rect = rect; + texture.addLoadedEventListener(this._textureLoadedCallback, this); + return true; + } + + if (!rect) { + rect = cc.rect(0, 0, 0, 0); + rect.size = texture.getContentSize(); + } + 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 "; @@ -1023,7 +1208,7 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ var locTextureLoaded = texture.isLoaded(); this._textureLoaded = locTextureLoaded; - if(!locTextureLoaded){ + if (!locTextureLoaded) { this._rectRotated = rotated || false; this._rect = rect; texture.addLoadedEventListener(this._textureLoadedCallback, this); @@ -1045,16 +1230,17 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ return true; }, - _textureLoadedCallback:function(sender){ + _textureLoadedCallback: null, + + _textureLoadedCallbackForWebGL: function (sender) { this._textureLoaded = true; var locRect = this._rect; if (!locRect) { locRect = cc.rect(0, 0, 0, 0); locRect.size = sender.getContentSize(); - } else if(cc._rectEqualToZero(locRect)){ + } else if (cc._rectEqualToZero(locRect)) { locRect.size = sender.getContentSize(); } - this._originalTexture = sender; this.setTexture(sender); this.setTextureRect(locRect, this._rectRotated, locRect.size); @@ -1062,7 +1248,27 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ // 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; + this._callLoadedEventCallbacks(); + }, + + _textureLoadedCallbackForCanvas: function (sender) { + this._textureLoaded = true; + var locRect = this._rect; + if (!locRect) { + locRect = cc.rect(0, 0, 0, 0); + locRect.size = sender.getContentSize(); + } else if (cc._rectEqualToZero(locRect)) { + locRect.size = sender.getContentSize(); + } + 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(null); this._callLoadedEventCallbacks(); }, @@ -1072,7 +1278,51 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ * @param {Boolean} rotated * @param {cc.Size} untrimmedSize */ - setTextureRect:function (rect, rotated, 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._flipX) + relativeOffset.x = -relativeOffset.x; + if (this._flipY) + 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; @@ -1099,14 +1349,20 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ /** * updates the quad according the the rotation, position, scale values. */ - updateTransform:function () { + 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._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: - var locParent = this._parent; 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; @@ -1117,1170 +1373,24 @@ cc.SpriteCanvas = cc.NodeRGBA.extend(/** @lends cc.SpriteCanvas# */{ //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:function (child, zOrder, tag) { - cc.Assert(child != null, "Argument must 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.Node.prototype.addChild.call(this, child, zOrder, tag); - this._hasChildren = true; - }, - - /** - * opacity setter - * @param {Number} opacity - */ - setOpacity:function (opacity) { - cc.NodeRGBA.prototype.setOpacity.call(this, opacity); - this.setNodeDirty(); - }, - - /** - * color setter - * @param {cc.Color3B} color3 - */ - setColor: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.setNodeDirty(); - }, - - updateDisplayedColor:function (parentColor) { - cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); - this._changeTextureColor(); - this.setNodeDirty(); - }, - - // Frames - /** - * Sets a new display frame to the cc.Sprite. - * @param {cc.SpriteFrame} newFrame - */ - setDisplayFrame: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(), this._rectRotated, 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: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._frameWithTextureForCanvas(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.RectMake(0, 0, 57, 57)); - * batch.addChild(sprite); - * layer.addChild(batch); - */ - setBatchNode: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 {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture - */ - setTexture:function (texture) { - // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet - cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument"); - if (this._texture != texture) { - if(texture && texture.getHtmlElementObj() instanceof HTMLImageElement){ - this._originalTexture = texture; - } - this._texture = texture; - } - }, - - _changeTextureColor: function () { - var locElement, locTexture = this._texture, locRect = this.getTextureRect(); - if (locTexture && locRect.width > 0) { - 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); - } - } - } - }, - - /** - * draw sprite to canvas - * @param {CanvasRenderingContext2D} ctx 2d context of canvas - */ - draw:function (ctx) { - if(!this._textureLoaded) - return; - - var context = ctx || cc.renderContext; - if (this._isLighterMode) - context.globalCompositeOperation = 'lighter'; - - context.globalAlpha = this._displayedOpacity / 255; - var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; - var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - if (this._flipX) { - flipXOffset = -locOffsetPosition.x - locRect.width; - context.scale(-1, 1); - } - if (this._flipY) { - flipYOffset = locOffsetPosition.y; - context.scale(1, -1); - } - if (this._texture && locRect.width > 0) { - var image = this._texture.getHtmlElementObj(); - if (this._colorized) { - context.drawImage(image, - 0, 0, 0 | locRect.width, 0 | locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.height); - } else { - context.drawImage(image, - 0 | locRect.x, 0 | locRect.y, 0 | locRect.width, 0 | locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.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, locContentSize.height); - } - - if (cc.SPRITE_DEBUG_DRAW === 1) { - // draw bounding box - context.strokeStyle = "rgba(0,255,0,1)"; - 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); - } - cc.g_NumberOfDraws++; - } -}); - -/** - *

cc.Sprite is a 2d image ( http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) (WebGL implement)
- * - * 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.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ - /// ---- common properties start ---- - 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:cc.rect(0, 0, 0, 0), //Retangle of cc.Texture2D - _rectRotated:false, //Whether the texture is rotated - - // Offset Position (used by Zwoptex) - _offsetPosition:null, // absolute - _unflippedOffsetPositionFromCenter:null, - - // opacity and RGB protocol - _opacityModifyRGB:false, - - // image is flipped - _flipX:false, //Whether the sprite is flipped horizontally or not. - _flipY:false, //Whether the sprite is flipped vertically or not. - - _textureLoaded:false, - - textureLoaded:function(){ - return this._textureLoaded; - }, - - addLoadedEventListener:function(callback, target){ - this._loadedEventListeners.push({eventCallback:callback, eventTarget:target}); - }, - - _callLoadedEventCallbacks:function(){ - var locListeners = this._loadedEventListeners; - for(var i = 0, len = locListeners.length; i < len; i++){ - var selCallback = locListeners[i]; - selCallback.eventCallback.call(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.x, this._offsetPosition.y); - }, - - /** - * 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) { - cc.Assert(spriteFrame != 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:function(spriteFrame){ - this.setNodeDirty(); - this.setTextureRect(spriteFrame.getRect(), spriteFrame.isRotated(), spriteFrame.getOriginalSize()); - 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 CCSpriteFrame from CCSpriteFrameCache - * @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) { - cc.Assert(spriteFrameName != null, ""); - var frame = cc.SpriteFrameCache.getInstance().getSpriteFrame(spriteFrameName); - 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 rect - */ - setVertexRect:function (rect) { - this._rect = rect; - }, - - 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) { - cc.Assert(child != null, "child is null"); - cc.Assert(this._children.indexOf(child) > -1, "this child is not in children list"); - - 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 CCSpriteBatchNode - * @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} pos - * @override - */ - setPosition:function (pos) { - 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(); - }, - - /** - * AnchorPoint setter (override cc.Node ) - * @param {cc.Point} anchor - * @override - */ - setAnchorPoint:function (anchor) { - cc.Node.prototype.setAnchorPoint.call(this, anchor); - 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) { - cc.Assert(!this._batchNode, "ignoreAnchorPointForPosition is invalid in cc.Sprite"); - cc.Node.prototype.ignoreAnchorPointForPosition.call(this, relative); - }, - - /** - * Sets whether the sprite should be flipped horizontally or not. - * @param {Boolean} flipX true if the sprite should be flipped horizaontally, false otherwise. - */ - setFlipX:function (flipX) { - if (this._flipX != flipX) { - this._flipX = flipX; - this.setTextureRect(this._rect, this._rectRotated, this._contentSize); - this.setNodeDirty(); - } - }, - - /** - * FlipY value setter (override cc.Node ) - * @param {Boolean} flipY - */ - setFlipY:function (flipY) { - if (this._flipY != flipY) { - this._flipY = flipY; - 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._flipX; - }, - - /** - *

- * 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._flipY; - }, - - // - // RGBA protocol - // - - // RGBAProtocol - /** - * opacity: conforms to CCRGBAProtocol protocol - * @param {Boolean} modify - */ - setOpacityModifyRGB:function (modify) { - if (this._opacityModifyRGB !== modify) { - this._opacityModifyRGB = modify; - this.updateColor(); - } - }, - - /** - * return IsOpacityModifyRGB value - * @return {Boolean} - */ - isOpacityModifyRGB:function () { - return this._opacityModifyRGB; - }, - - updateDisplayedOpacity:function (parentOpacity) { - cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, parentOpacity); - this.updateColor(); - }, - - // 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) { - cc.Assert(animationName, "cc.Sprite#setDisplayFrameWithAnimationName. animationName must not be null"); - var cache = cc.AnimationCache.getInstance().getAnimation(animationName); - cc.Assert(cache, "cc.Sprite#setDisplayFrameWithAnimationName: Frame not found"); - var animFrame = cache.getFrames()[frameIndex]; - cc.Assert(animFrame, "cc.Sprite#setDisplayFrame. Invalid frame"); - 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; - }, - /// ---- common properties end ---- - - _quad:null, // vertex coords, texture coords and color info - _quadWebBuffer:null, - _quadDirty:false, - - /** - * Constructor - * @param {String|cc.SpriteFrame|cc.SpriteBatchNode|HTMLImageElement|cc.Texture2D} fileName sprite construct parameter - */ - ctor: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._quad = new cc.V3F_C4B_T2F_Quad(); - this._quadWebBuffer = cc.renderContext.createBuffer(); - this._quadDirty = true; - this._textureLoaded = true; - this._loadedEventListeners = []; - - 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:function (src, dst) { - if (arguments.length == 1) - this._blendFunc = src; - else - this._blendFunc = {src:src, dst:dst}; - }, - - /** - * Initializes an empty sprite with nothing init. - * @return {Boolean} - */ - init: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._flipX = this._flipY = false; - - // default transform anchor: center - this.setAnchorPoint(cc.p(0.5, 0.5)); - - // zwoptex default values - this._offsetPosition = cc.PointZero(); - 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; - }, - /** - *

- * 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) { - cc.Assert(filename != null, "Sprite#initWithFile():Invalid filename for sprite"); - 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.
- * 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: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._flipX = this._flipY = false; - - // default transform anchor: center - this.setAnchorPoint(cc.p(0.5, 0.5)); - - // zwoptex default values - this._offsetPosition = cc.p(0, 0); - this._hasChildren = false; - - // Atlas: Color - var tmpColor = new cc.Color4B(255, 255, 255, 255); - this._quad.bl.colors = tmpColor; - this._quad.br.colors = tmpColor; - this._quad.tl.colors = tmpColor; - this._quad.tr.colors = tmpColor; - - var locTextureLoaded = texture.isLoaded(); - this._textureLoaded = locTextureLoaded; - - if(!locTextureLoaded){ - this._rectRotated = rotated || false; - this._rect = rect; - texture.addLoadedEventListener(this._textureLoadedCallback, this); - return true; - } - - if (!rect) { - rect = cc.rect(0, 0, 0, 0); - rect.size = texture.getContentSize(); - } - 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; - }, - - _textureLoadedCallback:function(sender){ - this._textureLoaded = true; - var locRect = this._rect; - if (!locRect) { - locRect = cc.rect(0, 0, 0, 0); - locRect.size = sender.getContentSize(); - } else if(cc._rectEqualToZero(locRect)){ - locRect.size = sender.getContentSize(); - } - - 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(null); - this._quadDirty = true; - }, - /** - * 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: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._flipX) - relativeOffset.x = -relativeOffset.x; - if (this._flipY) - 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; - } else { - // self rendering - // Atlas: Vertex - var x1 = 0 + this._offsetPosition.x; - var y1 = 0 + this._offsetPosition.y; - var x2 = x1 + this._rect.width; - var y2 = y1 + this._rect.height; - - // Don't update Z. - this._quad.bl.vertices = {x:x1, y:y1, z:0}; - this._quad.br.vertices = {x:x2, y:y1, z:0}; - this._quad.tl.vertices = {x:x1, y:y2, z:0}; - this._quad.tr.vertices = {x:x2, y:y2, z:0}; - - this._quadDirty = true; - } - }, - - // BatchNode methods - /** - * updates the quad according the the rotation, position, scale values. - */ - updateTransform: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()) { - // If it is not visible, or one of its ancestors is not visible, then do nothing: - if (!this._visible || ( this._parent && this._parent != this._batchNode && this._parent._shouldBeHidden)) { - this._quad.br.vertices = {x:0, y:0, z:0}; - this._quad.tl.vertices = {x:0, y:0, z:0}; - this._quad.tr.vertices = {x:0, y:0, z:0}; - this._quad.bl.vertices = {x:0, y:0, z:0}; - this._shouldBeHidden = true; - } else { - this._shouldBeHidden = false; - - if (!this._parent || this._parent == 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(), this._parent._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 = this._transformToBatch.tx; - var y = this._transformToBatch.ty; + var x = locTransformToBatch.tx; + var y = locTransformToBatch.ty; - var cr = this._transformToBatch.a; - var sr = this._transformToBatch.b; - var cr2 = this._transformToBatch.d; - var sr2 = -this._transformToBatch.c; + 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; @@ -2293,13 +1403,13 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ var dx = x1 * cr - y2 * sr2 + x; var dy = x1 * sr + y2 * cr2 + y; - this._quad.bl.vertices = {x:cc.RENDER_IN_SUBPIXEL(ax), y:cc.RENDER_IN_SUBPIXEL(ay), z:this._vertexZ}; - this._quad.br.vertices = {x:cc.RENDER_IN_SUBPIXEL(bx), y:cc.RENDER_IN_SUBPIXEL(by), z:this._vertexZ}; - this._quad.tl.vertices = {x:cc.RENDER_IN_SUBPIXEL(dx), y:cc.RENDER_IN_SUBPIXEL(dy), z:this._vertexZ}; - this._quad.tr.vertices = {x:cc.RENDER_IN_SUBPIXEL(cx), y:cc.RENDER_IN_SUBPIXEL(cy), z:this._vertexZ}; + 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}; } - if (cc.renderContextType === cc.WEBGL) - this._textureAtlas.updateQuad(this._quad, this._atlasIndex); + this._textureAtlas.updateQuad(locQuad, this._atlasIndex); this._recursiveDirty = false; this.setDirty(false); } @@ -2320,6 +1430,34 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } }, + _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 @@ -2327,7 +1465,9 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * @param {String} tag child's tag * @override */ - addChild:function (child, zOrder, tag) { + addChild: null, + + _addChildForWebGL:function (child, zOrder, tag) { cc.Assert(child != null, "Argument must be non-NULL"); if (zOrder == null) zOrder = child._zOrder; @@ -2348,26 +1488,41 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ cc.Node.prototype.addChild.call(this, child, zOrder, tag); this._hasChildren = true; }, + + _addChildForCanvas: function (child, zOrder, tag) { + cc.Assert(child != null, "Argument must 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.Node.prototype.addChild.call(this, child, zOrder, tag); + this._hasChildren = true; + }, + /** * Update sprite's color */ updateColor:function () { - var color4 = {r:this._displayedColor.r, g:this._displayedColor.g, b:this._displayedColor.b, a:this._displayedOpacity}; + 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 *= this._displayedOpacity / 255.0; - color4.g *= this._displayedOpacity / 255.0; - color4.b *= this._displayedOpacity / 255.0; + color4.r *= locDisplayedOpacity / 255.0; + color4.g *= locDisplayedOpacity / 255.0; + color4.b *= locDisplayedOpacity / 255.0; } - this._quad.bl.colors = color4; - this._quad.br.colors = color4; - this._quad.tl.colors = color4; - this._quad.tr.colors = color4; + 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(this._quad, this._atlasIndex) + this._textureAtlas.updateQuad(locQuad, this._atlasIndex) } else { // no need to set it recursively // update dirty_, don't update recursiveDirty_ @@ -2384,31 +1539,60 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * opacity setter * @param {Number} opacity */ - setOpacity:function (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.setNodeDirty(); + }, + /** * color setter * @param {cc.Color3B} color3 */ - setColor:function (color3) { + setColor: null, + + _setColorForWebGL: function (color3) { cc.NodeRGBA.prototype.setColor.call(this, color3); this.updateColor(); }, - updateDisplayedColor:function (parentColor) { + _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.setNodeDirty(); + }, + + updateDisplayedColor: null, + + _updateDisplayedColorForWebGL: function (parentColor) { cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); this.updateColor(); }, + _updateDisplayedColorForCanvas: function (parentColor) { + cc.NodeRGBA.prototype.updateDisplayedColor.call(this, parentColor); + this._changeTextureColor(); + this.setNodeDirty(); + }, + // Frames /** * Sets a new display frame to the cc.Sprite. * @param {cc.SpriteFrame} newFrame */ - setDisplayFrame:function (newFrame) { + setDisplayFrame: null, + + _setDisplayFrameForWebGL: function (newFrame) { this.setNodeDirty(); var frameOffset = newFrame.getOffset(); this._unflippedOffsetPositionFromCenter.x = frameOffset.x; @@ -2416,16 +1600,16 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ var pNewTexture = newFrame.getTexture(); var locTextureLoaded = newFrame.textureLoaded(); - if(!locTextureLoaded){ + if (!locTextureLoaded) { this._textureLoaded = false; - newFrame.addLoadedEventListener(function(sender){ + newFrame.addLoadedEventListener(function (sender) { this._textureLoaded = true; var locNewTexture = sender.getTexture(); if (locNewTexture != this._texture) this.setTexture(locNewTexture); this.setTextureRect(sender.getRect(), sender._rectRotated, sender.getOriginalSize()); this._callLoadedEventCallbacks(); - },this); + }, this); } // update texture before updating texture rect if (pNewTexture != this._texture) @@ -2436,21 +1620,70 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ 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(), this._rectRotated, 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:function (frame) { + 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 () { + displayFrame: null, + + _displayFrameForWebGL: function () { return cc.SpriteFrame.createWithTexture(this._texture, cc.RECT_POINTS_TO_PIXELS(this._rect), this._rectRotated, @@ -2458,6 +1691,14 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ cc.SIZE_POINTS_TO_PIXELS(this._contentSize)); }, + _displayFrameForCanvas: function () { + return cc.SpriteFrame._frameWithTextureForCanvas(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 @@ -2467,7 +1708,9 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ * batch.addChild(sprite); * layer.addChild(batch); */ - setBatchNode:function (spriteBatchNode) { + setBatchNode:null, + + _setBatchNodeForWebGL:function (spriteBatchNode) { this._batchNode = spriteBatchNode; // weak reference // self render @@ -2481,10 +1724,11 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ var y1 = this._offsetPosition.y; var x2 = x1 + this._rect.width; var y2 = y1 + this._rect.height; - this._quad.bl.vertices = {x:x1, y:y1, z:0}; - this._quad.br.vertices = {x:x2, y:y1, z:0}; - this._quad.tl.vertices = {x:x1, y:y2, z:0}; - this._quad.tr.vertices = {x:x2, y:y2, z:0}; + 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 { @@ -2494,12 +1738,30 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } }, + _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 {HTMLImageElement|HTMLCanvasElement|cc.Texture2D} texture */ - setTexture:function (texture) { + setTexture: null, + + _setTextureForWebGL: function (texture) { // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet cc.Assert(!texture || texture instanceof cc.Texture2D, "setTexture expects a CCTexture2D. Invalid argument"); @@ -2517,6 +1779,17 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } }, + _setTextureForCanvas: function (texture) { + // CCSprite: setTexture doesn't work when the sprite is rendered using a CCSpriteSheet + cc.Assert(!texture || texture instanceof cc.Texture2D, "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 () { cc.Assert(!this._batchNode, "cc.Sprite: _updateBlendFunc doesn't work when the sprite is rendered using a cc.CCSpriteBatchNode"); @@ -2532,6 +1805,30 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ } }, + _changeTextureColor: function () { + var locElement, locTexture = this._texture, locRect = this.getTextureRect(); + if (locTexture && locRect.width > 0) { + 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); @@ -2542,7 +1839,7 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ var atlasWidth = tex.getPixelsWide(); var atlasHeight = tex.getPixelsHigh(); - var left, right, top, bottom, tempSwap; + 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); @@ -2568,14 +1865,14 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ right = tempSwap; } - this._quad.bl.texCoords.u = left; - this._quad.bl.texCoords.v = top; - this._quad.br.texCoords.u = left; - this._quad.br.texCoords.v = bottom; - this._quad.tl.texCoords.u = right; - this._quad.tl.texCoords.v = top; - this._quad.tr.texCoords.u = right; - this._quad.tr.texCoords.v = bottom; + 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); @@ -2601,22 +1898,24 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ bottom = tempSwap; } - this._quad.bl.texCoords.u = left; - this._quad.bl.texCoords.v = bottom; - this._quad.br.texCoords.u = right; - this._quad.br.texCoords.v = bottom; - this._quad.tl.texCoords.u = left; - this._quad.tl.texCoords.v = top; - this._quad.tr.texCoords.u = right; - this._quad.tr.texCoords.v = top; + 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:function () { - if(!this._textureLoaded) + draw: null, + + _drawForWebGL: function () { + if (!this._textureLoaded) return; var gl = cc.renderContext, locTexture = this._texture; @@ -2667,11 +1966,12 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ if (cc.SPRITE_DEBUG_DRAW === 1) { // draw bounding box + var locQuad = this._quad; var verticesG1 = [ - cc.p(this._quad.tl.vertices.x, this._quad.tl.vertices.y), - 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(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) { @@ -2682,10 +1982,107 @@ cc.SpriteWebGL = cc.NodeRGBA.extend(/** @lends cc.SpriteWebGL# */{ 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'; + + context.globalAlpha = this._displayedOpacity / 255; + var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; + var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; + if (this._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (this._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); + } + if (this._texture && locRect.width > 0) { + var image = this._texture.getHtmlElementObj(); + if (this._colorized) { + context.drawImage(image, + 0, 0, 0 | locRect.width, 0 | locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.height); + } else { + context.drawImage(image, + 0 | locRect.x, 0 | locRect.y, 0 | locRect.width, 0 | locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.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, locContentSize.height); + } + + if (cc.SPRITE_DEBUG_DRAW === 1) { + // draw bounding box + context.strokeStyle = "rgba(0,255,0,1)"; + 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); + } + cc.g_NumberOfDraws++; } }); -cc.Sprite = cc.Browser.supportWebGL ? cc.SpriteWebGL : cc.SpriteCanvas; +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.displayFrame = cc.Sprite.prototype._displayFrameForWebGL; + 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.displayFrame = cc.Sprite.prototype._displayFrameForCanvas; + cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas; + cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas; + cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas; +} /** *

@@ -2695,7 +2092,6 @@ cc.Sprite = cc.Browser.supportWebGL ? cc.SpriteWebGL : cc.SpriteCanvas; * @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. - * @param {cc.Point} offset offset of the texture * @return {cc.Sprite} A valid sprite object * @example * //get an image @@ -2707,10 +2103,8 @@ cc.Sprite = cc.Browser.supportWebGL ? cc.SpriteWebGL : cc.SpriteCanvas; * //create a sprite with texture and rect * var sprite2 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320)); * - * //create a sprite with texture and rect and offset - * var sprite3 = cc.Sprite.createWithTexture(img, cc.rect(0,0,480,320),cc.p(0,0)); */ -cc.Sprite.createWithTexture = function (texture, rect, offset) { +cc.Sprite.createWithTexture = function (texture, rect) { var argnum = arguments.length; var sprite = new cc.Sprite(); switch (argnum) { @@ -2719,9 +2113,8 @@ cc.Sprite.createWithTexture = function (texture, rect, offset) { The rect used will be the size of the texture. The offset will be (0,0). */ - if (sprite && sprite.initWithTexture(texture)) { + if (sprite && sprite.initWithTexture(texture)) return sprite; - } return null; break; @@ -2729,16 +2122,8 @@ cc.Sprite.createWithTexture = function (texture, rect, offset) { /** Creates an sprite with a texture and a rect. The offset will be (0,0). */ - if (sprite && sprite.initWithTexture(texture, rect)) { + if (sprite && sprite.initWithTexture(texture, rect)) return sprite; - } - return null; - break; - - case 3: - /** Creates an sprite with a texture, a rect and offset. */ - // not implement - cc.Assert(0, ""); return null; break; From 0a5966fe8f8894b38f6674664da224f60c8ee26a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 5 Sep 2013 15:01:30 +0800 Subject: [PATCH 086/141] issue #2772: Optimize Armature logic , add blend Type supported --- extensions/CCArmature/CCArmature.js | 112 ++++++++++--- extensions/CCArmature/CCBone.js | 121 +++++++++----- .../animation/CCArmatureAnimation.js | 125 +++++++++----- .../CCArmature/animation/CCProcessBase.js | 58 ++++--- extensions/CCArmature/animation/CCTween.js | 152 ++++++++++-------- extensions/CCArmature/datas/CCDatas.js | 99 ++++++++++-- .../CCArmature/display/CCDecorativeDisplay.js | 3 - .../CCArmature/display/CCDisplayFactory.js | 85 ++++------ .../CCArmature/display/CCDisplayManager.js | 80 +++++++-- extensions/CCArmature/display/CCSkin.js | 83 +++++++++- .../CCArmature/utils/CCArmatureDefine.js | 3 +- .../CCArmature/utils/CCDataReaderHelper.js | 115 +++++++++---- .../utils/CCSpriteFrameCacheHelper.js | 39 ++--- .../CCArmature/utils/CCTransformHelp.js | 16 +- .../CCArmature/utils/CSArmatureDataManager.js | 59 ++++++- 15 files changed, 814 insertions(+), 336 deletions(-) diff --git a/extensions/CCArmature/CCArmature.js b/extensions/CCArmature/CCArmature.js index ad54b83225..a803bb8a3d 100644 --- a/extensions/CCArmature/CCArmature.js +++ b/extensions/CCArmature/CCArmature.js @@ -38,6 +38,8 @@ cc.Armature = cc.NodeRGBA.extend({ _topBoneList:[], _armatureIndexDic:{}, _offsetPoint:cc.p(0, 0), + _version:0, + _armatureTransformDirty:false, ctor:function () { cc.NodeRGBA.prototype.ctor.call(this); this._animation = null; @@ -50,6 +52,8 @@ cc.Armature = cc.NodeRGBA.extend({ this._topBoneList = []; this._armatureIndexDic = {}; this._offsetPoint = cc.p(0, 0); + this._version = 0, + this._armatureTransformDirty = false; }, /** @@ -233,13 +237,21 @@ cc.Armature = cc.NodeRGBA.extend({ changeBoneParent:function (bone, parentName) { if (!bone) { cc.log("bone must be added to the bone dictionary!"); + return; + } + var parentBone = bone.getParentBone(); + if(parentBone){ + cc.ArrayRemoveObject(parentBone.getChildrenBone(), bone); + bone.setParentBone(null); } - cc.ArrayRemoveObject(bone.getParentBone().getChildrenBone(), bone); - bone.removeFromParent(false); + if (parentName) { var boneParent = this._boneDic[parentName]; if (boneParent) { boneParent.addChildBone(bone); + cc.ArrayRemoveObject(this._topBoneList,bone); + }else{ + this._topBoneList.push(bone); } } }, @@ -260,7 +272,9 @@ cc.Armature = cc.NodeRGBA.extend({ var rect = this.boundingBox(); this.setContentSize(rect.size); this._offsetPoint = cc.p(-rect.origin.x, -rect.origin.y); - this.setAnchorPoint(cc.p(this._offsetPoint.x / rect.size.width, this._offsetPoint.y / rect.size.height)); + if (rect.width != 0 && rect.height != 0) { + this.setAnchorPoint(cc.p(this._offsetPoint.x / rect.size.width, this._offsetPoint.y / rect.size.height)); + } }, update:function (dt) { @@ -268,6 +282,7 @@ cc.Armature = cc.NodeRGBA.extend({ for (var i = 0; i < this._topBoneList.length; i++) { this._topBoneList[i].update(dt); } + this._armatureTransformDirty = false; }, nodeToParentTransform:function () { @@ -276,6 +291,7 @@ cc.Armature = cc.NodeRGBA.extend({ nodeToParentTransformWEBGL:function () { if (this._transformDirty) { + this._armatureTransformDirty = true; // Translate values var x = this._position.x; var y = this._position.y; @@ -342,6 +358,7 @@ cc.Armature = cc.NodeRGBA.extend({ if (!this._transform) this._transform = {a:1, b:0, c:0, d:1, tx:0, ty:0}; if (this._transformDirty) { + this._armatureTransformDirty = true; var t = this._transform;// quick reference // base position t.tx = this._position.x; @@ -423,7 +440,36 @@ cc.Armature = cc.NodeRGBA.extend({ }, draw:function () { - cc.g_NumberOfDraws++; + //cc.g_NumberOfDraws++; + }, + + /** + * update blendType + * @param {cc.BlendType} blendType + */ + updateBlendType: function (blendType) { + var blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); + switch (blendType) { + case cc.BlendType.NORMAL: + blendFunc.src = cc.BLEND_SRC; + blendFunc.dst = cc.BLEND_DST; + break; + case cc.BlendType.ADD: + blendFunc.src = gl.SRC_ALPHA; + blendFunc.dst = gl.ONE; + break; + case cc.BlendType.MULTIPLY: + blendFunc.src = gl.ONE_MINUS_SRC_ALPHA; + blendFunc.dst = gl.ONE_MINUS_DST_COLOR; + break; + case cc.BlendType.SCREEN: + blendFunc.src = gl.ONE; + blendFunc.dst = gl.ONE_MINUS_DST_COLOR; + break; + default: + break; + } + this.setBlendFunc(blendFunc.src, blendFunc.dst); }, /** @@ -436,22 +482,24 @@ cc.Armature = cc.NodeRGBA.extend({ var boundingBox = cc.rect(0, 0, 0, 0); for (var i = 0; i < this._children.length; i++) { var bone = this._children[i]; - var r = bone.getDisplayManager().getBoundingBox(); - if (first) { - minx = cc.rectGetMinX(r); - miny = cc.rectGetMinY(r); - maxx = cc.rectGetMaxX(r); - maxy = cc.rectGetMaxY(r); - - first = false; - } - else { - minx = cc.rectGetMinX(r) < cc.rectGetMinX(boundingBox) ? cc.rectGetMinX(r) : cc.rectGetMinX(boundingBox); - miny = cc.rectGetMinY(r) < cc.rectGetMinY(boundingBox) ? cc.rectGetMinY(r) : cc.rectGetMinY(boundingBox); - maxx = cc.rectGetMaxX(r) > cc.rectGetMaxX(boundingBox) ? cc.rectGetMaxX(r) : cc.rectGetMaxX(boundingBox); - maxy = cc.rectGetMaxY(r) > cc.rectGetMaxY(boundingBox) ? cc.rectGetMaxY(r) : cc.rectGetMaxY(boundingBox); + if (bone instanceof cc.Bone) { + var r = bone.getDisplayManager().getBoundingBox(); + if (first) { + minx = cc.rectGetMinX(r); + miny = cc.rectGetMinY(r); + maxx = cc.rectGetMaxX(r); + maxy = cc.rectGetMaxY(r); + + first = false; + } + else { + minx = cc.rectGetMinX(r) < cc.rectGetMinX(boundingBox) ? cc.rectGetMinX(r) : cc.rectGetMinX(boundingBox); + miny = cc.rectGetMinY(r) < cc.rectGetMinY(boundingBox) ? cc.rectGetMinY(r) : cc.rectGetMinY(boundingBox); + maxx = cc.rectGetMaxX(r) > cc.rectGetMaxX(boundingBox) ? cc.rectGetMaxX(r) : cc.rectGetMaxX(boundingBox); + maxy = cc.rectGetMaxY(r) > cc.rectGetMaxY(boundingBox) ? cc.rectGetMaxY(r) : cc.rectGetMaxY(boundingBox); + } + boundingBox = cc.rect(minx, miny, maxx - minx, maxy - miny); } - boundingBox = cc.rect(minx, miny, maxx - minx, maxy - miny); } return boundingBox; }, @@ -499,11 +547,29 @@ cc.Armature = cc.NodeRGBA.extend({ setBatchNode:function (batchNode) { this._batchNode = batchNode; }, - getParentBone:function () { - return this._parentBone; + + /** + * version getter + * @returns {Number} + */ + getVersion:function () { + return this._version; }, - setParentBone:function (parentBone) { - this._parentBone = parentBone; + + /** + * version setter + * @param {Number} version + */ + setVersion:function (version) { + this._version = version; + }, + + /** + * armatureTransformDirty getter + * @returns {Boolean} + */ + getArmatureTransformDirty:function () { + return this._armatureTransformDirty; } }); diff --git a/extensions/CCArmature/CCBone.js b/extensions/CCArmature/CCBone.js index 13e2d5b7e2..8423b3a492 100644 --- a/extensions/CCArmature/CCBone.js +++ b/extensions/CCArmature/CCBone.js @@ -38,8 +38,9 @@ cc.Bone = cc.NodeRGBA.extend({ _name:"", _childrenBone:[], _parentBone:null, - _selfTransformDirty:false, - _worldTransform:cc.AffineTransformMake(1, 0, 0, 1, 0, 0), + _boneTransformDirty:false, + _worldTransform:null, + _blendType:0, ctor:function () { cc.NodeRGBA.prototype.ctor.call(this); this._boneData = null; @@ -52,8 +53,9 @@ cc.Bone = cc.NodeRGBA.extend({ this._name = ""; this._childrenBone = []; this._parentBone = null; - this._selfTransformDirty = true; + this._boneTransformDirty = true; this._worldTransform = cc.AffineTransformMake(1, 0, 0, 1, 0, 0); + this._blendType=cc.BlendType.NORMAL; }, /** @@ -118,7 +120,9 @@ cc.Bone = cc.NodeRGBA.extend({ */ setArmature:function (armature) { this._armature = armature; - this._tween.setAnimation(this._armature.getAnimation()); + if(armature){ + this._tween.setAnimation(this._armature.getAnimation()); + } }, /** @@ -135,20 +139,16 @@ cc.Bone = cc.NodeRGBA.extend({ */ update:function (dt) { if (this._parentBone) { - this._selfTransformDirty = this._selfTransformDirty || this._parentBone.isTransformDirty(); + this._boneTransformDirty = this._boneTransformDirty || this._parentBone.isTransformDirty(); } - if (this._selfTransformDirty) { - var cosX = Math.cos(this._tweenData.skewX); - var sinX = Math.sin(this._tweenData.skewX); - var cosY = Math.cos(this._tweenData.skewY); - var sinY = Math.sin(this._tweenData.skewY); - - this._worldTransform.a = this._tweenData.scaleX * cosY; - this._worldTransform.b = this._tweenData.scaleX * sinY; - this._worldTransform.c = this._tweenData.scaleY * sinX; - this._worldTransform.d = this._tweenData.scaleY * cosX; - this._worldTransform.tx = this._tweenData.x; - this._worldTransform.ty = this._tweenData.y; + if (this._boneTransformDirty) { + if (this._armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) { + cc.TransformHelp.nodeConcat(this._tweenData, this._boneData); + this._tweenData.scaleX -= 1; + this._tweenData.scaleY -= 1; + } + + cc.TransformHelp.nodeToMatrix(this._tweenData, this._worldTransform); this._worldTransform = cc.AffineTransformConcat(this.nodeToParentTransform(), this._worldTransform); @@ -156,25 +156,21 @@ cc.Bone = cc.NodeRGBA.extend({ this._worldTransform = cc.AffineTransformConcat(this._worldTransform, this._parentBone._worldTransform); } } - cc.DisplayFactory.updateDisplay(this, this._displayManager.getCurrentDecorativeDisplay(), dt, this._selfTransformDirty); + cc.DisplayFactory.updateDisplay(this, this._displayManager.getCurrentDecorativeDisplay(), dt, this._boneTransformDirty|| this._armature.getArmatureTransformDirty()); for (var i = 0; i < this._childrenBone.length; i++) { this._childrenBone[i].update(dt); } - - this._selfTransformDirty = false; + this._boneTransformDirty = false; }, - old_NumberOfDraws:0, /** * Rewrite visit ,when node draw, g_NumberOfDraws is changeless */ - visit:function () { - this.old_NumberOfDraws = cc.g_NumberOfDraws++; + visit:function (ctx) { var node = this.getDisplayManager().getDisplayRenderNode(); if (node) { node.visit(ctx); } - cc.g_NumberOfDraws = this.old_NumberOfDraws; }, /** @@ -182,6 +178,7 @@ cc.Bone = cc.NodeRGBA.extend({ * @param {cc.c3b} color */ updateDisplayedColor:function (color) { + this._realColor = cc.c3b(255,255,255); cc.NodeRGBA.prototype.updateDisplayedColor.call(this, color); this.updateColor(); }, @@ -191,6 +188,7 @@ cc.Bone = cc.NodeRGBA.extend({ * @param {Number} opacity */ updateDisplayedOpacity:function (opacity) { + this._realOpacity = 255; cc.NodeRGBA.prototype.updateDisplayedOpacity.call(this, opacity); this.updateColor(); }, @@ -200,9 +198,27 @@ cc.Bone = cc.NodeRGBA.extend({ */ updateColor:function () { var display = this._displayManager.getDisplayRenderNode(); - if (display) { - display.setColor(cc.c3b(this._displayedColor.r * this._tweenData.r / 255, this._displayedColor.g * this._tweenData.g / 255, this._displayedColor.b * this._tweenData.b / 255)); - display.setOpacity(this._displayedOpacity * this._tweenData.a / 255); + if (display&&display instanceof cc.Skin) { + //display.setColor(cc.c3b(this._displayedColor.r * this._tweenData.r / 255, this._displayedColor.g * this._tweenData.g / 255, this._displayedColor.b * this._tweenData.b / 255)); + if(cc.Browser.supportWebGL){ + display.setOpacity(this._displayedOpacity * this._tweenData.a / 255); + }else{ + cc.NodeRGBA.prototype.setOpacity.call(display, this._displayedOpacity * this._tweenData.a / 255); + } + + } + }, + + /** + * update display zOrder + */ + updateZOrder: function () { + if (this._armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) { + var zorder = this._tweenData.zOrder + this._boneData.zOrder; + this.setZOrder(zorder); + } + else { + this.setZOrder(this._tweenData.zOrder); } }, @@ -219,9 +235,6 @@ cc.Bone = cc.NodeRGBA.extend({ cc.log("child already added. It can't be added again"); return; } - if (!this._childrenBone) { - this.childrenAlloc(); - } if (cc.ArrayGetIndexOfObject(this._childrenBone, child) < 0) { this._childrenBone.push(child); child.setParentBone(this); @@ -277,10 +290,6 @@ cc.Bone = cc.NodeRGBA.extend({ return this._parentBone; }, - childrenAlloc:function () { - this._childrenBone = []; - }, - /** * child armature setter * @param {cc.Armature} armature @@ -329,7 +338,7 @@ cc.Bone = cc.NodeRGBA.extend({ * @param {Boolean} */ setTransformDirty:function (dirty) { - this._selfTransformDirty = dirty; + this._boneTransformDirty = dirty; }, /** @@ -337,7 +346,7 @@ cc.Bone = cc.NodeRGBA.extend({ * @return {Boolean} */ isTransformDirty:function () { - return this._selfTransformDirty; + return this._boneTransformDirty; }, /** @@ -348,6 +357,22 @@ cc.Bone = cc.NodeRGBA.extend({ return this._worldTransform; }, + /** + * Returns the world affine transform matrix. The matrix is in Pixels. + * @returns {cc.AffineTransform} + */ + nodeToWorldTransform: function () { + return cc.AffineTransformConcat(this._worldTransform, this._armature.nodeToWorldTransform()); + }, + + /** + * get render node + * @returns {cc.Node} + */ + getDisplayRenderNode: function () { + return this._displayManager.getDisplayRenderNode(); + }, + /** * Add display and use _displayData init the display. * If index already have a display, then replace it. @@ -358,7 +383,13 @@ cc.Bone = cc.NodeRGBA.extend({ * -1 : append display from back */ addDisplay:function (displayData, index) { - this._displayManager.addDisplay(displayData, index); + index = index || 0; + return this._displayManager.addDisplay(displayData, index); + }, + + addSkin:function (skin, index) { + index = index||0; + return this._displayManager.addSkin(skin, index); }, /** @@ -425,6 +456,22 @@ cc.Bone = cc.NodeRGBA.extend({ */ getName:function () { return this._name; + }, + + /** + * blendType setter + * @param {cc.BlendType} blendType + */ + setBlendType:function (blendType) { + this._blendType = blendType; + }, + + /** + * blendType getter + * @return {cc.BlendType} + */ + getBlendType:function () { + return this._blendType; } }); diff --git a/extensions/CCArmature/animation/CCArmatureAnimation.js b/extensions/CCArmature/animation/CCArmatureAnimation.js index 4a8890d5e5..5745aab8c4 100644 --- a/extensions/CCArmature/animation/CCArmatureAnimation.js +++ b/extensions/CCArmature/animation/CCArmatureAnimation.js @@ -32,7 +32,7 @@ CC_MovementEventType_LOOP_COMPLETE = 2; * @class * @extends cc.Class */ -cc.MovementEvent = cc.Class.extend({ +cc.AnimationEvent = cc.Class.extend({ _arguments:null, _callFunc:null, _selectorTarget:null, @@ -64,19 +64,21 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ _prevFrameIndex:0, _toIndex:0, _tweenList:[], - MovementEventSignal:{}, _frameEvent:null, - + _movementEvent:null, + _speedScale:1, ctor:function () { cc.ProcessBase.prototype.ctor.call(this); this._animationData = null; - this._currentFrameData = null; + this._movementData = null; this._movementID = ""; this._armature = null; this._prevFrameIndex = 0; this._toIndex = 0; - this.MovementEventSignal = {}; - this.FrameEventSignal = {}; + this._tweenList = []; + this._frameEvent = null; + this._movementEvent = null; + this._speedScale = 1; }, /** @@ -112,20 +114,47 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ /** * scale animation play speed - * @param {Number} animationScale + * @param {Number} speedScale */ - setAnimationScale:function (animationScale) { - if (animationScale == this._animationScale) { + setSpeedScale:function (speedScale) { + if (speedScale == this._speedScale) { + return; + } + this._speedScale = speedScale; + this._processScale = !this._movementData ? this._speedScale : this._speedScale * this._movementData.scale; + var dict = this._armature.getBoneDic(); + for (var key in dict) { + var bone = dict[key]; + bone.getTween().setProcessScale(this._processScale); + if (bone.getChildArmature()) { + bone.getChildArmature().getAnimation().setProcessScale(this._processScale); + } + } + }, + + getSpeedScale:function(){ + return this._speedScale; + }, + + getAnimationScale:function(){ + return this.getSpeedScale(); + }, + setAnimationScale:function(animationScale){ + return this.setSpeedScale(animationScale); + }, + + setAnimationInternal:function (animationInternal) { + if (animationInternal == this._animationInternal) { return; } - this._animationScale = animationScale; + this._animationInternal = animationInternal; var dict = this._armature.getBoneDic(); for (var key in dict) { var bone = dict[key]; - bone.getTween().setAnimationScale(this._animationScale); + bone.getTween().setAnimationInternal(this._animationInternal); if (bone.getChildArmature()) { - bone.getChildArmature().getAnimation().setAnimationScale(this._animationScale); + bone.getChildArmature().getAnimation().setAnimationInternal(this._animationInternal); } } }, @@ -173,11 +202,12 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ loop = -1; } if (typeof tweenEasing == "undefined") { - tweenEasing = 10000; + tweenEasing = cc.TweenType.TWEEN_EASING_MAX; } //Get key frame count this._rawDuration = this._movementData.duration; this._movementID = animationName; + this._processScale = this._speedScale * this._movementData.scale; //Further processing parameters durationTo = (durationTo == -1) ? this._movementData.durationTo : durationTo; durationTween = (durationTween == -1) ? this._movementData.durationTween : durationTween; @@ -187,7 +217,7 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ cc.ProcessBase.prototype.play.call(this, animationName, durationTo, durationTween, loop, tweenEasing); - if (this._rawDuration == 1) { + if (this._rawDuration == 0) { this._loopType = CC_ANIMATION_TYPE_SINGLE_FRAME; } else { @@ -208,11 +238,14 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ var tween = bone.getTween(); if (movementBoneData && movementBoneData.frameList.length > 0) { this._tweenList.push(tween); + movementBoneData.duration = this._movementData.duration; tween.play(movementBoneData, durationTo, durationTween, loop, tweenEasing); - tween.setAnimationScale(this._animationScale); + tween.setProcessScale(this._processScale); + tween.setAnimationInternal(this._animationInternal); if (bone.getChildArmature()) { - bone.getChildArmature().getAnimation().setAnimationScale(this._animationScale); + bone.getChildArmature().getAnimation().setProcessScale(this._processScale); + bone.getChildArmature().getAnimation().setAnimationInternal(this._animationInternal); } } else { if (!bone.getIgnoreMovementBoneData()) { @@ -246,7 +279,7 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ } var moveNames = this._animationData.movementNames; if (animationIndex < -1 || animationIndex >= moveNames.length) { - return + return; } var animationName = moveNames[animationIndex]; this.play(animationName, durationTo, durationTween, loop, tweenEasing); @@ -261,9 +294,10 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ }, update:function (dt) { - cc.ProcessBase.prototype.update.call(this, dt); - for (var i = 0; i < this._tweenList.length; i++) { - this._tweenList[i].update(dt); + if(cc.ProcessBase.prototype.update.call(this, dt)){ + for (var i = 0; i < this._tweenList.length; i++) { + this._tweenList[i].update(dt); + } } }, @@ -279,44 +313,61 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ this._currentPercent = this._currentFrame / this._durationTween; if (this._currentPercent < 1.0) { this._nextFrameIndex = this._durationTween; - this.callEvent([this, CC_MovementEventType_START, this._movementID]); + this.callMovementEvent([this._armature, CC_MovementEventType_START, this._movementID]); break; } case CC_ANIMATION_TYPE_MAX: case CC_ANIMATION_TYPE_SINGLE_FRAME: this._currentPercent = 1; this._isComplete = true; - this.callEvent([this, CC_MovementEventType_COMPLETE, this._movementID]); + this._isPlaying = false; + this.callMovementEvent([this._armature, CC_MovementEventType_COMPLETE, this._movementID]); break; case CC_ANIMATION_TYPE_TO_LOOP_FRONT: this._loopType = CC_ANIMATION_TYPE_LOOP_FRONT; this._currentPercent = cc.fmodf(this._currentPercent, 1); - this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); + this._currentFrame = this._nextFrameIndex == 0 ? 0 :cc.fmodf(this._currentFrame, this._nextFrameIndex); this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1; - this.callEvent([this, CC_MovementEventType_START, this._movementID]); + this.callMovementEvent([this, CC_MovementEventType_START, this._movementID]); break; default: this._currentPercent = cc.fmodf(this._currentPercent, 1); this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); this._toIndex = 0; - this.callEvent([this, CC_MovementEventType_LOOP_COMPLETE, this._movementID]); + this.callMovementEvent([this._armature, CC_MovementEventType_LOOP_COMPLETE, this._movementID]); break; } } + }, - if (this._loopType == CC_ANIMATION_TYPE_LOOP_BACK || this._loopType == CC_ANIMATION_TYPE_LOOP_FRONT) { - this.updateFrameData(this._currentPercent); - } + /** + * Get current movementID + * @returns {String} + */ + getCurrentMovementID: function () { + if (this._isComplete) + return ""; + return this._movementID; + }, + + /** + * connect a event + * @param {Object} target + * @param {function} callFunc + */ + setMovementEventCallFunc:function (callFunc, target) { + this._movementEvent = new cc.AnimationEvent(target, callFunc); }, /** - * Update current key frame, and process auto stop, pause - * @param {Number} currentPercent + * call event + * @param {Array} args */ - updateFrameData:function (currentPercent) { - this._prevFrameIndex = this._curFrameIndex; - this._curFrameIndex = this._rawDuration * currentPercent; - this._curFrameIndex = this._curFrameIndex % this._rawDuration; + callMovementEvent:function (args) { + if (this._movementEvent) { + this._movementEvent.setArguments(args); + this._movementEvent.call(); + } }, /** @@ -324,15 +375,15 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ * @param {Object} target * @param {function} callFunc */ - connectEvent:function (target, callFunc) { - this._frameEvent = new cc.MovementEvent(target, callFunc); + setFrameEventCallFunc:function (callFunc, target) { + this._frameEvent = new cc.AnimationEvent(target, callFunc); }, /** * call event * @param {Array} args */ - callEvent:function (args) { + callFrameEvent:function (args) { if (this._frameEvent) { this._frameEvent.setArguments(args); this._frameEvent.call(); diff --git a/extensions/CCArmature/animation/CCProcessBase.js b/extensions/CCArmature/animation/CCProcessBase.js index 36d0f8daa2..cf12153d77 100644 --- a/extensions/CCArmature/animation/CCProcessBase.js +++ b/extensions/CCArmature/animation/CCProcessBase.js @@ -38,7 +38,7 @@ CC_ANIMATION_TYPE_MAX = 2;//the animation max * @extends cc.Class */ cc.ProcessBase = cc.Class.extend({ - _animationScale:1, + _processScale:1, _isComplete:true, _isPause:true, _isPlaying:false, @@ -53,7 +53,7 @@ cc.ProcessBase = cc.Class.extend({ _curFrameIndex:null, _isLoopBack:false, ctor:function () { - this._animationScale = 1; + this._processScale = 1; this._isComplete = true; this._isPause = true; this._isPlaying = false; @@ -72,15 +72,18 @@ cc.ProcessBase = cc.Class.extend({ pause:function () { this._isPause = true; + this._isPlaying = false; }, resume:function () { this._isPause = false; + this._isPlaying = true; }, stop:function () { this._isComplete = true; + this._isPlaying = false; this._currentFrame = 0; this._currentPercent = 0; }, @@ -123,29 +126,32 @@ cc.ProcessBase = cc.Class.extend({ update:function (dt) { if (this._isComplete || this._isPause) { - return; + return false; } if (this._rawDuration <= 0 || dt > 1) { - return; + return false; } if (this._nextFrameIndex <= 0) { - this._currentFrame = this._nextFrameIndex = 1; + this._currentPercent = 1; + this._currentFrame = 0; + }else{ + /* + * update this._currentFrame, every update add the frame passed. + * dt/this._animationInternal determine it is not a frame animation. If frame speed changed, it will not make our + * animation speed slower or quicker. + */ + this._currentFrame += this._processScale * (dt / this._animationInternal); + + this._currentPercent = this._currentFrame / this._nextFrameIndex; + + /* + * if this._currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util this._currentFrame is + * smaller than this._nextFrameIndex + */ + this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); } - /* - * update this._currentFrame, every update add the frame passed. - * dt/this._animationInternal determine it is not a frame animation. If frame speed changed, it will not make our - * animation speed slower or quicker. - */ - this._currentFrame += this._animationScale * (dt / this._animationInternal); - - this._currentPercent = this._currentFrame / this._nextFrameIndex; - - /* - * if this._currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util this._currentFrame is - * smaller than this._nextFrameIndex - */ - this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); this.updateHandler(); + return true; }, /** @@ -156,7 +162,7 @@ cc.ProcessBase = cc.Class.extend({ }, gotoFrame:function (keyFrameIndex) { this._curFrameIndex = keyFrameIndex; - this.stop(); + this.pause(); }, /** @@ -164,6 +170,7 @@ cc.ProcessBase = cc.Class.extend({ * @return {Number} */ getCurrentFrameIndex:function () { + this._curFrameIndex = this._rawDuration * this._currentPercent; return this._curFrameIndex; }, @@ -188,11 +195,14 @@ cc.ProcessBase = cc.Class.extend({ getAnimationInternal:function () { return this._animationInternal; }, - getAnimationScale:function () { - return this._animationScale; + setAnimationInternal:function(animationInternal){ + this._animationInternal = animationInternal; + }, + getProcessScale:function () { + return this._processScale; }, - setAnimationScale:function (animationScale) { - this._animationScale = animationScale; + setProcessScale:function (processScale) { + this._processScale = processScale; }, isPlaying:function () { return this._isPlaying; diff --git a/extensions/CCArmature/animation/CCTween.js b/extensions/CCArmature/animation/CCTween.js index 4850317fb5..bd76eb3cef 100644 --- a/extensions/CCArmature/animation/CCTween.js +++ b/extensions/CCArmature/animation/CCTween.js @@ -33,23 +33,20 @@ cc.Tween = cc.ProcessBase.extend({ _from:null, _between:null, _movementBoneData:null, - _currentKeyFrame:null, _bone:null, _frameTweenEasing:0, - _isTweenKeyFrame:false, _betweenDuration:0, _totalDuration:0, _toIndex:0, _fromIndex:0, - _animation:false, + _animation:null, ctor:function () { cc.ProcessBase.prototype.ctor.call(this); + this._tweenData = null; + this._to = null; this._from = null; this._between = null; this._bone = null; - this._currentKeyFrame = null; - this._nextKeyFrame = null; - this._editKeyFrame = null; this._movementBoneData = null; this._frameTweenEasing = cc.TweenType.Linear; this._toIndex = 0; @@ -68,6 +65,7 @@ cc.Tween = cc.ProcessBase.extend({ this._bone = bone; this._tweenData = this._bone.getTweenData(); + this._tweenData.displayIndex = -1; this._animation = this._bone.getArmature() != null ? this._bone.getArmature().getAnimation() : null; return true; }, @@ -97,38 +95,41 @@ cc.Tween = cc.ProcessBase.extend({ play:function (movementBoneData, durationTo, durationTween, loop, tweenEasing) { cc.ProcessBase.prototype.play.call(this, null, durationTo, durationTween, loop, tweenEasing); this._loopType = loop; - this._currentKeyFrame = null; - this._isTweenKeyFrame = false; this._totalDuration = 0; this._betweenDuration = 0; - this._toIndex = 0; + this._fromIndex = this._toIndex = 0; + + var difMovement = movementBoneData != this._movementBoneData; this._movementBoneData = movementBoneData; - if (this._movementBoneData.frameList.length == 1) { + this._rawDuration = this._movementBoneData.duration; + + var nextKeyFrame = this._movementBoneData.getFrameData(0); + this._tweenData.displayIndex = nextKeyFrame.displayIndex; + + if (this._bone.getArmature().getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) { + cc.TransformHelp.nodeSub(this._tweenData, this._bone.getBoneData()); + this._tweenData.scaleX += 1; + this._tweenData.scaleY += 1; + } + + if (this._rawDuration==0) { this._loopType = CC_ANIMATION_TYPE_SINGLE_FRAME; - var nextKeyFrame = this._movementBoneData.getFrameData(0); if (durationTo == 0) { this.setBetween(nextKeyFrame, nextKeyFrame); } else { - this._tweenData.displayIndex = nextKeyFrame.displayIndex; this.setBetween(this._tweenData, nextKeyFrame); } - - this._isTweenKeyFrame = true; this._frameTweenEasing = cc.TweenType.Linear; - this._rawDuration = this._movementBoneData.duration; - this._fromIndex = this._toIndex = 0; } else if (this._movementBoneData.frameList.length > 1) { if (loop) { this._loopType = CC_ANIMATION_TYPE_TO_LOOP_BACK; - this._rawDuration = this._movementBoneData.duration; } else { this._loopType = CC_ANIMATION_TYPE_NO_LOOP; - this._rawDuration = this._movementBoneData.duration - 1; } this._durationTween = durationTween * this._movementBoneData.scale; @@ -136,11 +137,13 @@ cc.Tween = cc.ProcessBase.extend({ this.setBetween(this._tweenData, this.tweenNodeTo(this.updateFrameData(1 - this._movementBoneData.delay), this._between)); } else { - var nextKeyFrame = this._movementBoneData.getFrameData(0); - this.setBetween(this._tweenData, nextKeyFrame); - this._isTweenKeyFrame = true; + if (!difMovement || durationTo == 0) + this.setBetween(nextKeyFrame, nextKeyFrame); + else + this.setBetween(this._tweenData, nextKeyFrame); } } + this.tweenNodeTo(0); }, /** @@ -171,7 +174,7 @@ cc.Tween = cc.ProcessBase.extend({ this._currentFrame = this._currentPercent * this._nextFrameIndex; this._totalDuration = 0; this._betweenDuration = 0; - this._toIndex = 0; + this._fromIndex = this._toIndex = 0; break; } case CC_ANIMATION_TYPE_TO_LOOP_BACK: @@ -188,7 +191,7 @@ cc.Tween = cc.ProcessBase.extend({ this._totalDuration = 0; this._betweenDuration = 0; - this._toIndex = 0; + this._fromIndex = this._toIndex = 0; break; case CC_ANIMATION_TYPE_MAX: this._currentPercent = 1; @@ -199,7 +202,7 @@ cc.Tween = cc.ProcessBase.extend({ this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); this._totalDuration = 0; this._betweenDuration = 0; - this._toIndex = 0; + this._fromIndex = this._toIndex = 0; break; } } @@ -212,12 +215,9 @@ cc.Tween = cc.ProcessBase.extend({ if (this._loopType > CC_ANIMATION_TYPE_TO_LOOP_BACK) { percent = this.updateFrameData(percent, true); } - if (this._frameTweenEasing != cc.TWEEN_EASING_MAX) { + if (this._frameTweenEasing != cc.TweenType.TWEEN_EASING_MAX) { this.tweenNodeTo(percent); } - else if (this._currentKeyFrame) { - this.tweenNodeTo(0); - } }, @@ -229,12 +229,13 @@ cc.Tween = cc.ProcessBase.extend({ setBetween:function (from, to) { do { - if (to.displayIndex < 0 && from.displayIndex > 0) { - this._from.copy(from); + if (from.displayIndex < 0 && to.displayIndex >= 0) { + this._from.copy(to); this._between.subtract(to, to); break; - } else if (from.displayIndex < 0 && to.displayIndex > 0) { - this._from.copy(to); + } + if (to.displayIndex < 0 && from.displayIndex >= 0) { + this._from.copy(from); this._between.subtract(to, to); break; } @@ -251,22 +252,20 @@ cc.Tween = cc.ProcessBase.extend({ arriveKeyFrame:function (keyFrameData) { if (keyFrameData) { var displayIndex = keyFrameData.displayIndex; - if (!this._bone.getDisplayManager().getForceChangeDisplay()) { - this._bone.getDisplayManager().changeDisplayByIndex(displayIndex, false); + var displayManager = this._bone.getDisplayManager(); + if (!displayManager.getForceChangeDisplay()) { + displayManager.changeDisplayByIndex(displayIndex, false); + } - this._bone.setZOrder(keyFrameData.zOrder); + this._tweenData.zOrder = keyFrameData.zOrder; + this._bone.updateZOrder(); + this._bone.setBlendType(keyFrameData.blendType); var childAramture = this._bone.getChildArmature(); if (childAramture) { if (keyFrameData.movement != "") { childAramture.getAnimation().play(keyFrameData.movement); } } - if (keyFrameData.event != "") { - //this._animation.FrameEventSignal.emit(this._bone, keyFrameData.event); - } - if (keyFrameData.sound) { - //soundManager.dispatchEventWith(Event.SOUND_FRAME, m_pCurrentKeyFrame.sound); - } } }, @@ -286,59 +285,78 @@ cc.Tween = cc.ProcessBase.extend({ node.scaleY = this._from.scaleY + percent * this._between.scaleY; node.skewX = this._from.skewX + percent * this._between.skewX; node.skewY = this._from.skewY + percent * this._between.skewY; + this._bone.setTransformDirty(true); - if (this._between.isUseColorInfo) { - node.a = this._from.a + percent * this._between.a; - node.r = this._from.r + percent * this._between.r; - node.g = this._from.g + percent * this._between.g; - node.b = this._from.b + percent * this._between.b; - this._bone.updateColor(); - } + if (node && this._between.isUseColorInfo) + this.tweenColorTo(percent, node); + return node; }, + tweenColorTo:function(percent,node){ + node.a = this._from.a + percent * this._between.a; + node.r = this._from.r + percent * this._between.r; + node.g = this._from.g + percent * this._between.g; + node.b = this._from.b + percent * this._between.b; + this._bone.updateColor(); + }, + /** * Calculate which frame arrived, and if current frame have event, then call the event listener * @param {Number} currentPercent * @param {Boolean} activeFrame * @return {Number} */ - updateFrameData:function (currentPercent, activeFrame) { + updateFrameData:function (currentPercent) { + if (currentPercent > 1 && this._movementBoneData.delay != 0) { + currentPercent = cc.fmodf(currentPercent,1); + } var playedTime = this._rawDuration * currentPercent; - var from; - var to; - var isListEnd; + var from,to; // if play to current frame's front or back, then find current frame again - if (playedTime >= this._totalDuration || playedTime < this._totalDuration - this._betweenDuration) { + if (playedTime < this._totalDuration || playedTime > this._totalDuration + this._betweenDuration) { /* * get frame length, if this._toIndex >= _length, then set this._toIndex to 0, start anew. * this._toIndex is next index will play */ var length = this._movementBoneData.frameList.length; + var frames = this._movementBoneData.frameList; + if (playedTime < frames[0].frameID){ + from = to = frames[0]; + this.setBetween(from, to); + return currentPercent; + } + else if(playedTime >= frames[length - 1].frameID){ + from = to = frames[length - 1]; + this.setBetween(from, to); + return currentPercent; + } + do { - this._betweenDuration = this._movementBoneData.getFrameData(this._toIndex).duration; - this._totalDuration += this._betweenDuration; - this._fromIndex = this._toIndex; + from = frames[this._fromIndex]; + this._totalDuration = from.frameID; if (++this._toIndex >= length) { this._toIndex = 0; } - } - while (playedTime >= this._totalDuration); + this._fromIndex = this._toIndex; + to = frames[this._toIndex]; - isListEnd = this._loopType == CC_ANIMATION_TYPE_MAX && this._toIndex == 0; + //! Guaranteed to trigger frame event + if(from.event){ + this._animation.callFrameEvent([this._bone, from.event,from.frameID, playedTime]); + } - if (isListEnd) { - to = from = this._movementBoneData.getFrameData(this._fromIndex); - } - else { - from = this._movementBoneData.getFrameData(this._fromIndex); - to = this._movementBoneData.getFrameData(this._toIndex); + if (playedTime == from.frameID) { + break; + } } + while (playedTime < from.frameID || playedTime >= to.frameID); + this._betweenDuration = to.frameID - from.frameID; this._frameTweenEasing = from.tweenEasing; this.setBetween(from, to); } - currentPercent = 1 - (this._totalDuration - playedTime) / this._betweenDuration; + currentPercent = this._betweenDuration == 0 ? 0 : (playedTime - this._totalDuration) / this._betweenDuration; /* * if frame tween easing equal to TWEEN_EASING_MAX, then it will not do tween. */ @@ -346,7 +364,7 @@ cc.Tween = cc.ProcessBase.extend({ if (this._frameTweenEasing != cc.TweenType.TWEEN_EASING_MAX) { tweenType = (this._tweenEasing == cc.TweenType.TWEEN_EASING_MAX) ? this._frameTweenEasing : this._tweenEasing; - if (tweenType != cc.TweenType.TWEEN_EASING_MAX) { + if (tweenType != cc.TweenType.TWEEN_EASING_MAX&&tweenType != cc.TweenType.Linear) { currentPercent = cc.TweenFunction.tweenTo(0, 1, currentPercent, 1, tweenType); } } diff --git a/extensions/CCArmature/datas/CCDatas.js b/extensions/CCArmature/datas/CCDatas.js index 89522d39f6..3d15c6b64d 100644 --- a/extensions/CCArmature/datas/CCDatas.js +++ b/extensions/CCArmature/datas/CCDatas.js @@ -22,11 +22,27 @@ THE SOFTWARE. ****************************************************************************/ +cc.BlendType = { + NORMAL: 0, + LAYER: 1, + DARKEN: 2, + MULTIPLY: 3, + LIGHTEN: 4, + SCREEN: 5, + OVERLAY: 6, + HARD_LIGHT: 7, + ADD: 8, + SUBSTRACT: 9, + DIFFERENCE: 10, + INVERT: 11, + ALPHA: 12, + ERASE: 13 +}; + CC_DISPLAY_SPRITE = 0; CC_DISPLAY_ARMATURE = 1; CC_DISPLAY_PARTICLE = 2; -CC_DISPLAY_SHADER = 3; -CC_DISPLAY_MAX = 1000; +CC_DISPLAY_MAX = 3; cc.BaseData = cc.Class.extend({ x:0, @@ -38,10 +54,10 @@ cc.BaseData = cc.Class.extend({ scaleY:1, tweenRotate:0, isUseColorInfo:false, - r:0, - g:0, - b:0, - a:0, + r:255, + g:255, + b:255, + a:255, ctor:function () { this.x = 0; @@ -73,6 +89,17 @@ cc.BaseData = cc.Class.extend({ this.a = node.a; }, + setColor:function(color){ + this.r = color.r; + this.g = color.g; + this.b = color.b; + this.a = color.a; + }, + + getColor:function(){ + return cc.c4f(this.r, this.g, this.b, this.a); + }, + subtract:function (from, to) { this.x = to.x - from.x; this.y = to.y - from.y; @@ -81,12 +108,15 @@ cc.BaseData = cc.Class.extend({ this.skewX = to.skewX - from.skewX; this.skewY = to.skewY - from.skewY; - if (from.isUseColorInfo || to.isUseColorInfo) { + if (this.isUseColorInfo || from.isUseColorInfo || to.isUseColorInfo) { this.a = to.a - from.a; this.r = to.r - from.r; this.g = to.g - from.g; this.b = to.b - from.b; - this._useColorInfo = true; + this.isUseColorInfo = true; + } else { + this.a = this.r = this.g = this.b = 0; + this.isUseColorInfo = false; } if (this.skewX > cc.PI) { @@ -112,7 +142,7 @@ cc.BaseData = cc.Class.extend({ cc.DisplayData = cc.Class.extend({ displayType:CC_DISPLAY_SPRITE, ctor:function () { - this.displayType = CC_DISPLAY_SPRITE; + this.displayType = CC_DISPLAY_MAX; }, changeDisplayToTexture:function (displayName) { // remove .xxx @@ -128,8 +158,10 @@ cc.DisplayData = cc.Class.extend({ cc.SpriteDisplayData = cc.DisplayData.extend({ displayName:"", + skinData:null, ctor:function () { this.displayName = ""; + this.skinData = null; this.displayType = CC_DISPLAY_SPRITE; }, setParam:function (displayName) { @@ -138,6 +170,21 @@ cc.SpriteDisplayData = cc.DisplayData.extend({ copy:function (displayData) { this.displayName = displayData.displayName; this.displayType = displayData.displayType; + this.skinData = displayData.skinData; + } +}); + +cc.NodeDisplayData = cc.DisplayData.extend({ + node:null, + ctor:function () { + this.displayName = ""; + this.displayType = CC_DISPLAY_NODE; + this.node = null; + }, + copy:function (displayData) { + this.displayName = displayData.displayName; + this.displayType = displayData.displayType; + this.node = displayData.node; } }); @@ -197,10 +244,12 @@ cc.BoneData = cc.BaseData.extend({ displayDataList:[], name:"", parentName:"", + boneDataTransform:null, ctor:function () { this.displayDataList = []; this.name = ""; this.parentName = ""; + this.boneDataTransform = null; }, init:function () { @@ -217,19 +266,18 @@ cc.BoneData = cc.BaseData.extend({ cc.ArmatureData = cc.Class.extend({ boneDataDic:{}, - boneList:[], name:"", + dataVersion:0, ctor:function () { this.boneDataDic = {}; - this.boneList = []; this.name = ""; + this.dataVersion = 0; }, init:function () { - + return true; }, addBoneData:function (boneData) { this.boneDataDic[boneData.name] = boneData; - this.boneList.push(boneData); }, getBoneDataDic:function () { return this.boneDataDic; @@ -240,13 +288,15 @@ cc.ArmatureData = cc.Class.extend({ }); cc.FrameData = cc.BaseData.extend({ - duration:1, + duration:0, tweenEasing:0, - displayIndex:0, + displayIndex:-1, movement:"", event:"", sound:"", soundEffect:"", + blendType:0, + frameID:0, ctor:function () { cc.BaseData.prototype.ctor.call(this); @@ -257,6 +307,8 @@ cc.FrameData = cc.BaseData.extend({ this.event = ""; this.sound = ""; this.soundEffect = ""; + this.blendType = cc.BlendType.NORMAL; + this.frameID = 0; }, copy:function (frameData) { @@ -264,6 +316,11 @@ cc.FrameData = cc.BaseData.extend({ this.duration = frameData.duration; this.tweenEasing = frameData.tweenEasing; this.displayIndex = frameData.displayIndex; + this.movement = frameData.movement; + this.event = frameData.event; + this.sound = frameData.sound; + this.soundEffect = frameData.soundEffect; + this.blendType = frameData.blendType; } } ); @@ -296,6 +353,7 @@ cc.MovementBoneData = cc.Class.extend({ cc.MovementData = cc.Class.extend({ movBoneDataDic:{}, duration:0, + scale:0, durationTo:0, durationTween:cc.TweenType.Linear, loop:true, @@ -304,6 +362,7 @@ cc.MovementData = cc.Class.extend({ ctor:function () { this.name = ""; this.duration = 0; + this.scale = 1; this.durationTo = 0; this.durationTween = 0; this.loop = true; @@ -352,6 +411,16 @@ cc.ContourData = cc.Class.extend({ init:function () { this.vertexList = []; + return true; + }, + + /** + * + * @param {cc.p} p + */ + addVertex: function (p) { + var v = cc.ContourVertex2(p.x, p.y); + this.vertexList.push(v); } }); diff --git a/extensions/CCArmature/display/CCDecorativeDisplay.js b/extensions/CCArmature/display/CCDecorativeDisplay.js index 9664f7b155..f2544159db 100644 --- a/extensions/CCArmature/display/CCDecorativeDisplay.js +++ b/extensions/CCArmature/display/CCDecorativeDisplay.js @@ -34,12 +34,9 @@ cc.DecotativeDisplay = cc.Class.extend({ }, init:function () { - return true; }, - anchorPointChanged:function (pointX, pointY) { - }, setDisplay:function (display) { this._display = display; }, diff --git a/extensions/CCArmature/display/CCDisplayFactory.js b/extensions/CCArmature/display/CCDisplayFactory.js index 46e2ea9fa9..3292442301 100644 --- a/extensions/CCArmature/display/CCDisplayFactory.js +++ b/extensions/CCArmature/display/CCDisplayFactory.js @@ -68,18 +68,19 @@ cc.DisplayFactory.updateDisplay = function (bone, decoDisplay, dt, dirty) { } } } - + var display = decoDisplay.getDisplay(); switch (decoDisplay.getDisplayData().displayType) { case CC_DISPLAY_SPRITE: - this.updateSpriteDisplay(bone, decoDisplay, dt, dirty); + this.updateSpriteDisplay(bone, display, dt, dirty); break; case CC_DISPLAY_PARTICLE: - this.updateParticleDisplay(bone, decoDisplay, dt, dirty); + this.updateParticleDisplay(bone, display, dt, dirty); break; case CC_DISPLAY_ARMATURE: - this.updateArmatureDisplay(bone, decoDisplay, dt, dirty); + this.updateArmatureDisplay(bone, display, dt, dirty); break; default: + display.setAdditionalTransform(bone.nodeToArmatureTransform()); break; } }; @@ -106,40 +107,39 @@ cc.DisplayFactory.createSpriteDisplay = function (bone, decoDisplay) { else { skin = cc.Skin.createWithSpriteFrameName(textureName + ".png"); } - /*var atlas = cc.SpriteFrameCacheHelper.getInstance().getTextureAtlas(textureName + ".png"); - skin.setTextureAtlas(atlas);*/ - //todo - /*var batchNode = cc.SpriteFrameCacheHelper.getInstance().getBatchNode(textureName + ".png"); + this.initSpriteDisplay(bone, decoDisplay, displayData.displayName, skin); + skin.setBone(bone); + var armature = bone.getArmature(); + if (armature) { + if (armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) + skin.setSkinData(displayData.skinData); + else + skin.setSkinData(bone.getBoneData()); + } - skin.setBatchNode(batchNode); - skin.setTextureAtlas(batchNode.getTextureAtlas());*/ + decoDisplay.setDisplay(skin); +}; +cc.DisplayFactory.initSpriteDisplay = function(bone, decoDisplay, displayName, skin){ + var textureName = displayName; + var startPos = textureName.lastIndexOf("."); + if (startPos != -1) { + textureName = textureName.substring(0, startPos); + } var textureData = cc.ArmatureDataManager.getInstance().getTextureData(textureName); if (textureData) { //! Init display anchorPoint, every Texture have a anchor point skin.setAnchorPoint(cc.p(textureData.pivotX, textureData.pivotY)); } - skin.setBone(bone); - skin.setSkinData(bone.getBoneData()); - decoDisplay.setDisplay(skin); - - if (ENABLE_PHYSICS_DETECT) { - if (textureData && textureData.contourDataList.count() > 0) { +}, - //! create ContourSprite - var colliderDetector = cc.ColliderDetector.create(bone); - colliderDetector.addContourDataList(textureData.contourDataList); - decoDisplay.setColliderDetector(colliderDetector); - } - } -}; - -cc.DisplayFactory.updateSpriteDisplay = function (bone, decoDisplay, dt, dirty) { - var skin = decoDisplay.getDisplay(); - skin.updateSelfTransform(); +cc.DisplayFactory.updateSpriteDisplay = function (bone, skin, dt, dirty) { + if(!dirty) + return; + skin.updateBlendType(bone.getBlendType()); + skin.updateArmatureTransform(); }; - cc.DisplayFactory.addArmatureDisplay = function (bone, decoDisplay, displayData) { var adp = new cc.ArmatureDisplayData(); adp.copy(displayData); @@ -157,11 +157,9 @@ cc.DisplayFactory.createArmatureDisplay = function (bone, decoDisplay) { armature.setName(bone.getName() + "_armatureChild"); decoDisplay.setDisplay(armature); }; -cc.DisplayFactory.updateArmatureDisplay = function (bone, decoDisplay, dt, dirty) { - if (!dirty) { +cc.DisplayFactory.updateArmatureDisplay = function (bone, armature, dt, dirty) { + if (!dirty) return; - } - var armature = bone.getChildArmature(); if (armature) { armature.sortAllChildren(); armature.update(dt); @@ -179,24 +177,11 @@ cc.DisplayFactory.createParticleDisplay = function (bone, decoDisplay) { var system = cc.ParticleSystemQuad.create(displayData.plist); decoDisplay.setDisplay(system); }; -cc.DisplayFactory.updateParticleDisplay = function (bone, decoDisplay, dt, dirty) { - var system = decoDisplay.getDisplay(); +cc.DisplayFactory.updateParticleDisplay = function (bone, particleSystem, dt, dirty) { var node = new cc.BaseData(); cc.TransformHelp.matrixToNode(bone.nodeToArmatureTransform(), node); - system.setPosition(cc.p(node.x, node.y)); - system.setScaleX(node.scaleX); - system.setScaleY(node.scaleY); - system.update(dt); -}; - -cc.DisplayFactory.addShaderDisplay = function (bone, decoDisplay, displayData) { - var sdp = new cc.ShaderDisplayData(); - sdp.copy(displayData); - decoDisplay.setDisplayData(sdp); - this.createShaderDisplay(bone, decoDisplay); -}; -cc.DisplayFactory.createShaderDisplay = function (bone, decoDisplay) { - var displayData = decoDisplay.getDisplayData(); - var sn = cc.ShaderNode.shaderNodeWithVertex(displayData.vert, displayData.frag); - decoDisplay.setDisplay(sn); + particleSystem.setPosition(cc.p(node.x, node.y)); + particleSystem.setScaleX(node.scaleX); + particleSystem.setScaleY(node.scaleY); + particleSystem.update(dt); }; diff --git a/extensions/CCArmature/display/CCDisplayManager.js b/extensions/CCArmature/display/CCDisplayManager.js index bb8b5615ef..d1b35b9793 100644 --- a/extensions/CCArmature/display/CCDisplayManager.js +++ b/extensions/CCArmature/display/CCDisplayManager.js @@ -47,18 +47,21 @@ cc.DisplayManager = cc.Class.extend({ return true; }, - addDisplay:function (displayData, index) { + addDisplay: function (displayData, index) { var decoDisplay = null; - if (index >= 0 && index < this._decoDisplayList.length) { - decoDisplay = this._decoDisplayList[index]; + decoDisplay = this._decoDisplayList[i]; } else { decoDisplay = cc.DecotativeDisplay.create(); this._decoDisplayList.push(decoDisplay); } - cc.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData); + if(displayData instanceof cc.DisplayData){ + cc.DisplayFactory.addDisplay(this._bone, decoDisplay, displayData); + }else{ + this._addDisplayOther(decoDisplay,displayData); + } //! if changed display index is current display index, then change current display to the new display if (index == this._displayIndex) { @@ -67,33 +70,77 @@ cc.DisplayManager = cc.Class.extend({ } }, + _addDisplayOther:function(decoDisplay,display){ + var displayData = null; + if (display instanceof cc.Skin){ + var skin = display; + skin.setBone(this._bone); + displayData = new cc.SpriteDisplayData(); + cc.DisplayFactory.initSpriteDisplay(this._bone, decoDisplay, skin.getDisplayName(), skin); + var spriteDisplayData = decoDisplay.getDisplayData(); + if (spriteDisplayData instanceof cc.SpriteDisplayData) + skin.setSkinData(spriteDisplayData.skinData); + else + skin.setSkinData(new cc.BaseData()); + } + else if (display instanceof cc.ParticleSystemQuad){ + displayData = new cc.ParticleDisplayData(); + } + else if (display instanceof cc.Armature){ + displayData = new cc.ArmatureDisplayData(); + display.setParentBone(this._bone); + } + else { + displayData = new cc.DisplayData(); + } + decoDisplay.setDisplay(display); + decoDisplay.setDisplayData(displayData); + }, + removeDisplay:function (index) { - cc.ArrayRemoveObjectAtIndex(this._decoDisplayList, index); + //cc.ArrayRemoveObjectAtIndex(this._decoDisplayList, index); + this._decoDisplayList[index] = null; if (index == this._displayIndex) { this.setCurrentDecorativeDisplay(null); } }, + getDecorativeDisplayList:function(){ + return this._decoDisplayList; + }, + changeDisplayByIndex:function (index, force) { - if (index < -1 || index > this._decoDisplayList.length) { + if (index >= this._decoDisplayList.length) { cc.log("the index value is out of range"); return; } + this._forceChangeDisplay = force; - //if index is equal to current display index,then do nothing - if (this._displayIndex == index) { - return; - } - this._displayIndex = index; + //this._displayIndex == -1, it means you want to hide you display - if (this._displayIndex < 0) { + if (index < 0) { + this._displayIndex = index; if (this._displayRenderNode) { this._displayRenderNode.removeFromParent(true); this.setCurrentDecorativeDisplay(null); + this._displayRenderNode = null; } return; } + + //if index is equal to current display index,then do nothing + if (this._displayIndex == index) { + return; + } + + this._displayIndex = index; + var decoDisplay = this._decoDisplayList[this._displayIndex]; + + if(!decoDisplay){ + return; + } + this.setCurrentDecorativeDisplay(decoDisplay); }, @@ -119,6 +166,7 @@ cc.DisplayManager = cc.Class.extend({ } this._displayRenderNode.removeFromParent(true); this._displayRenderNode.release(); + this._displayRenderNode = null; } this._displayRenderNode = displayRenderNode; @@ -126,8 +174,16 @@ cc.DisplayManager = cc.Class.extend({ if (this._displayRenderNode) { if (this._displayRenderNode instanceof cc.Armature) { this._bone.setChildArmature(this._displayRenderNode); + }else if(this._displayRenderNode instanceof cc.ParticleSystemQuad) { + this._displayRenderNode.resetSystem(); + } + if (this._displayRenderNode.RGBAProtocol) { + this._displayRenderNode.setColor(this._bone.getColor()); + this._displayRenderNode.setOpacity(this._bone.getOpacity()); } this._displayRenderNode.retain(); + //todo + //this._displayRenderNode.setVisible(this._visible); } }, diff --git a/extensions/CCArmature/display/CCSkin.js b/extensions/CCArmature/display/CCSkin.js index e6c8b0874f..3a05d0efd3 100644 --- a/extensions/CCArmature/display/CCSkin.js +++ b/extensions/CCArmature/display/CCSkin.js @@ -26,13 +26,28 @@ cc.Skin = cc.Sprite.extend({ _skinData:null, _bone:null, _skinTransform:cc.AffineTransformIdentity(), + _displayName:"", ctor:function () { cc.Sprite.prototype.ctor.call(this); this._skinData = null; this._bone = null; + this._displayName = ""; this._skinTransform = cc.AffineTransformIdentity(); }, - + initWithSpriteFrameName:function(spriteFrameName){ + var ret = cc.Sprite.prototype.initWithSpriteFrameName.call(this,spriteFrameName); + var atlas = cc.SpriteFrameCacheHelper.getInstance().getTexureAtlasWithTexture(this._texture); + this.setTextureAtlas(atlas); + this._displayName = spriteFrameName; + return ret; + }, + initWithFile:function(spriteFrameName){ + var ret = cc.Sprite.prototype.initWithFile.call(this,spriteFrameName); + var atlas = cc.SpriteFrameCacheHelper.getInstance().getTexureAtlasWithTexture(this._texture); + this.setTextureAtlas(atlas); + this._displayName = spriteFrameName; + return ret; + }, setSkinData:function (skinData) { this._skinData = skinData; @@ -60,7 +75,7 @@ cc.Skin = cc.Sprite.extend({ return this._bone; }, - updateSelfTransform:function () { + updateArmatureTransform:function () { this._transform = cc.AffineTransformConcat(this._skinTransform, this._bone.nodeToArmatureTransform()); if (cc.renderContextType === cc.CANVAS) { this._transform.b *= -1; @@ -80,6 +95,56 @@ cc.Skin = cc.Sprite.extend({ return cc.RectApplyAffineTransform(rect, transForm); }, + /** + * display name getter + * @returns {String} + */ + getDisplayName:function(){ + return this._displayName; + }, + + nodeToWorldTransform: function () { + return cc.AffineTransformConcat(this._transform, this._bone.getArmature().nodeToWorldTransform()); + }, + + nodeToWorldTransformAR: function () { + var displayTransform = this._transform; + var anchorPoint = this._anchorPointInPoints; + + anchorPoint = cc.PointApplyAffineTransform(anchorPoint, displayTransform); + displayTransform.tx = anchorPoint.x; + displayTransform.ty = anchorPoint.y; + + return cc.AffineTransformConcat(displayTransform, this._bone.getArmature().nodeToWorldTransform()); + }, + /** + * update blendType + * @param {cc.BlendType} blendType + */ + updateBlendType: function (blendType) { + var blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); + switch (blendType) { + case cc.BlendType.NORMAL: + blendFunc.src = cc.BLEND_SRC; + blendFunc.dst = cc.BLEND_DST; + break; + case cc.BlendType.ADD: + blendFunc.src = gl.SRC_ALPHA; + blendFunc.dst = gl.ONE; + break; + case cc.BlendType.MULTIPLY: + blendFunc.src = gl.ONE_MINUS_SRC_ALPHA; + blendFunc.dst = gl.ONE_MINUS_DST_COLOR; + break; + case cc.BlendType.SCREEN: + blendFunc.src = gl.ONE; + blendFunc.dst = gl.ONE_MINUS_DST_COLOR; + break; + default: + break; + } + this.setBlendFunc(blendFunc.src, blendFunc.dst); + }, updateQuad:function () { return; // If it is not visible, or one of its ancestors is not visible, then do nothing: @@ -131,17 +196,21 @@ cc.Skin = cc.Sprite.extend({ } }); -cc.Skin.create = function () { - var skin = new cc.Skin(); - if (skin && skin.init()) { - return skin; +cc.Skin.create = function (fileName, rect) { + var argnum = arguments.length; + var sprite = new cc.Skin(); + if (argnum === 0) { + if (sprite.init()) + return sprite; + } else { + if (sprite && sprite.initWithFile(fileName, rect)) + return sprite; } return null; }; cc.Skin.createWithSpriteFrameName = function (pszSpriteFrameName) { var skin = new cc.Skin(); - skin.testSpriteFrameName = pszSpriteFrameName; if (skin && skin.initWithSpriteFrameName(pszSpriteFrameName)) { return skin; } diff --git a/extensions/CCArmature/utils/CCArmatureDefine.js b/extensions/CCArmature/utils/CCArmatureDefine.js index 0927e06b15..fbe6d2e4ed 100644 --- a/extensions/CCArmature/utils/CCArmatureDefine.js +++ b/extensions/CCArmature/utils/CCArmatureDefine.js @@ -25,4 +25,5 @@ cc.MAX_VERTEXZ_VALUE = 5000000.0; cc.ARMATURE_MAX_CHILD = 50.0; cc.ARMATURE_MAX_ZORDER = 100; -cc.ARMATURE_MAX_COUNT = ((cc.MAX_VERTEXZ_VALUE) / (cc.ARMATURE_MAX_CHILD) / cc.ARMATURE_MAX_ZORDER); \ No newline at end of file +cc.ARMATURE_MAX_COUNT = ((cc.MAX_VERTEXZ_VALUE) / (cc.ARMATURE_MAX_CHILD) / cc.ARMATURE_MAX_ZORDER); +cc.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false; \ No newline at end of file diff --git a/extensions/CCArmature/utils/CCDataReaderHelper.js b/extensions/CCArmature/utils/CCDataReaderHelper.js index 4695d8a957..dcb074ce3a 100644 --- a/extensions/CCArmature/utils/CCDataReaderHelper.js +++ b/extensions/CCArmature/utils/CCDataReaderHelper.js @@ -24,6 +24,7 @@ cc.CONST_VERSION = "version"; cc.CONST_VERSION_2_0 = 2.0; +cc.CONST_VERSION_COMBINED = 0.3; cc.CONST_SKELETON = "skeleton"; cc.CONST_ARMATURES = "armatures"; @@ -41,6 +42,7 @@ cc.CONST_SUB_TEXTURE = "SubTexture"; cc.CONST_A_NAME = "name"; cc.CONST_A_DURATION = "dr"; +cc.CONST_A_FRAME_INDEX = "fi"; cc.CONST_A_DURATION_TO = "to"; cc.CONST_A_DURATION_TWEEN = "drTW"; cc.CONST_A_LOOP = "lp"; @@ -66,6 +68,7 @@ cc.CONST_A_TWEEN_ROTATE = "twR"; cc.CONST_A_IS_ARMATURE = "isArmature"; cc.CONST_A_DISPLAY_TYPE = "displayType"; cc.CONST_A_MOVEMENT = "mov"; +cc.CONST_A_BLEND_TYPE = "bd"; cc.CONST_A_X = "x"; cc.CONST_A_Y = "y"; @@ -107,6 +110,7 @@ cc.CONST_MOVEMENT_FRAME_DATA = "mov_frame_data"; cc.CONST_MOVEMENT_DATA = "mov_data"; cc.CONST_ANIMATION_DATA = "animation_data"; cc.CONST_DISPLAY_DATA = "display_data"; +cc.CONST_SKIN_DATA = "skin_data"; cc.CONST_BONE_DATA = "bone_data"; cc.CONST_ARMATURE_DATA = "armature_data"; cc.CONST_CONTOUR_DATA = "contour_data"; @@ -114,16 +118,19 @@ cc.CONST_TEXTURE_DATA = "texture_data"; cc.CONST_VERTEX_POINT = "vertex"; cc.CONST_COLOR_INFO = "color"; +cc.CONST_CONFIG_FILE_PATH = "config_file_path"; cc.DataReaderHelper = cc.DataReaderHelper || {}; cc.DataReaderHelper._configFileList = []; cc.DataReaderHelper._flashToolVersion = cc.CONST_VERSION_2_0; +cc.DataReaderHelper._cocoStudioVersion = cc.CONST_VERSION_COMBINED; cc.DataReaderHelper._XMLFileList = []; cc.DataReaderHelper._armarureDatas = {}; cc.DataReaderHelper._animationDatas = {}; cc.DataReaderHelper._textureDatas = {}; cc.DataReaderHelper._json = {}; cc.DataReaderHelper._positionReadScale = 1; +cc.DataReaderHelper._basefilePath = ""; cc.DataReaderHelper.setPositionReadScale = function (scale) { this._positionReadScale = scale; @@ -138,6 +145,9 @@ cc.DataReaderHelper.clear = function () { }; cc.DataReaderHelper.addDataFromFile = function (filePath) { + var fileUtils = cc.FileUtils.getInstance(); + filePath = fileUtils.fullPathForFilename(filePath); + if (cc.ArrayAppendObject(this._configFileList, filePath)) { return; } @@ -218,19 +228,18 @@ cc.DataReaderHelper.decodeArmature = function (armatureXML) { return armatureData; }; -cc.DataReaderHelper.decodeBone = function (_boneXML, parentXML) { +cc.DataReaderHelper.decodeBone = function (boneXML, parentXML) { - var _name = _boneXML.getAttribute(cc.CONST_A_NAME); + var _name = boneXML.getAttribute(cc.CONST_A_NAME); if (_name == "") { return; } var boneData = new cc.BoneData(); - boneData.name = _name; + boneData.parentName = boneXML.getAttribute(cc.CONST_A_PARENT) || ""; + boneData.zOrder = parseInt(boneXML.getAttribute(cc.CONST_A_Z)) || 0; - boneData.parentName = _boneXML.getAttribute(cc.CONST_A_PARENT) || ""; - - var _displaysXML = _boneXML.querySelectorAll(cc.CONST_BONE + " > " + cc.CONST_DISPLAY); + var _displaysXML = boneXML.querySelectorAll(cc.CONST_BONE + " > " + cc.CONST_DISPLAY); var _displayXML for (var i = 0; i < _displaysXML.length; i++) { @@ -304,10 +313,10 @@ cc.DataReaderHelper.decodeMovement = function (movementXML, _armatureData) { var easing = movementXML.getAttribute(cc.CONST_A_TWEEN_EASING); if (easing) { if (easing != cc.CONST_FL_NAN) { - tweenEasing = parseFloat(movementXML.getAttribute(cc.CONST_A_TWEEN_EASING)) || 0; + tweenEasing = parseFloat(easing) || 0; movementData.tweenEasing = tweenEasing; } else { - movementData.tweenEasing = cc.TWEEN_EASING_MAX; + movementData.tweenEasing = cc.TweenType.TWEEN_EASING_MAX; } } @@ -390,9 +399,17 @@ cc.DataReaderHelper.decodeMovementBone = function (movBoneXml, parentXml, boneDa } var frameData = this.decodeFrame(frameXML, parentFrameXML, boneData, movBoneData); movBoneData.addFrameData(frameData); + frameData.frameID = totalDuration; totalDuration += frameData.duration; + movBoneData.duration = totalDuration; + } + //todo + if(movBoneData.frameList.length>0){ + var frameData = new cc.FrameData(); + frameData.copy(movBoneData.frameList[movBoneData.frameList.length-1]); + frameData.frameID = movBoneData.duration; + movBoneData.addFrameData(frameData); } - return movBoneData; }; @@ -400,6 +417,7 @@ cc.DataReaderHelper.decodeFrame = function (frameXML, parentFrameXml, boneData, var frameData = new cc.FrameData(); frameData.movement = frameXML.getAttribute(cc.CONST_A_MOVEMENT) || ""; frameData.event = frameXML.getAttribute(cc.CONST_A_EVENT) || ""; + frameData.blendType = parseInt(frameXML.getAttribute(cc.CONST_A_BLEND_TYPE)) || cc.BlendType.NORMAL; frameData.sound = frameXML.getAttribute(cc.CONST_A_SOUND) || ""; frameData.soundEffect = frameXML.getAttribute(cc.CONST_A_SOUND_EFFECT) || ""; @@ -424,18 +442,30 @@ cc.DataReaderHelper.decodeFrame = function (frameXML, parentFrameXml, boneData, var colorTransformXMLList = frameXML.querySelectorAll(cc.CONST_FRAME + " > " + cc.CONST_A_COLOR_TRANSFORM); if (colorTransformXMLList.length > 0) { var colorTransformXML = colorTransformXMLList[0]; - var alpha, red, green, blue = 100; - var alphaOffset, redOffset, greenOffset, blueOffset = 0; + var alpha = red = green = blue = 0; + var alphaOffset = redOffset = greenOffset = blueOffset = 100; alpha = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_ALPHA)) || alpha; red = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_RED)) || red; green = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_GREEN)) || green; blue = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_BLUE)) || blue; - alphaOffset = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_ALPHA_OFFSET)) || alphaOffset; - redOffset = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_RED_OFFSET)) || redOffset; - greenOffset = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_GREEN_OFFSET)) || greenOffset; - blueOffset = parseFloat(colorTransformXML.getAttribute(cc.CONST_A_BLUE_OFFSET)) || blueOffset; + var str_alphaOffset = colorTransformXML.getAttribute(cc.CONST_A_ALPHA_OFFSET); + if(str_alphaOffset){ + alphaOffset = parseFloat(str_alphaOffset); + } + var str_redOffset = colorTransformXML.getAttribute(cc.CONST_A_RED_OFFSET); + if(str_redOffset){ + redOffset = parseFloat(str_redOffset); + } + var str_greenOffset = colorTransformXML.getAttribute(cc.CONST_A_GREEN_OFFSET); + if(str_redOffset){ + greenOffset = parseFloat(str_greenOffset); + } + var str_blueOffset = colorTransformXML.getAttribute(cc.CONST_A_BLUE_OFFSET); + if(str_blueOffset){ + blueOffset = parseFloat(str_blueOffset); + } frameData.a = 2.55 * alphaOffset + alpha; frameData.r = 2.55 * redOffset + red; @@ -444,13 +474,16 @@ cc.DataReaderHelper.decodeFrame = function (frameXML, parentFrameXml, boneData, frameData.isUseColorInfo = true; } + if(frameData.displayIndex==-1){ + frameData.a = 0; + } var easing = frameXML.getAttribute(cc.CONST_A_TWEEN_EASING); if (easing) { if (easing != cc.CONST_FL_NAN) { - frameData.tweenEasing = parseFloat(frameXML.getAttribute(cc.CONST_A_TWEEN_EASING)) || 0; + frameData.tweenEasing = parseFloat(easing) || 0; } else { - frameData.tweenEasing = cc.TWEEN_EASING_MAX; + frameData.tweenEasing = cc.TweenType.TWEEN_EASING_MAX; } } @@ -562,6 +595,8 @@ cc.DataReaderHelper.decodeArmatureFromJSON = function (json) { armatureData.name = name; } + this._cocoStudioVersion = armatureData.dataVersion = json[cc.CONST_VERSION] || 0.1; + var boneDataList = json[cc.CONST_BONE_DATA]; for (var i = 0; i < boneDataList.length; i++) { armatureData.addBoneData(this.decodeBoneFromJson(boneDataList[i])); @@ -588,21 +623,26 @@ cc.DataReaderHelper.decodeBoneDisplayFromJson = function (json) { case CC_DISPLAY_SPRITE: displayData = new cc.SpriteDisplayData(); displayData.displayName = json[cc.CONST_A_NAME] || ""; + + var dicArray = json[cc.CONST_SKIN_DATA]|| []; + var dic = dicArray[0]; + if(dic){ + displayData.skinData.x = (dic[cc.CONST_A_X]|| 0) * this._positionReadScale; + displayData.skinData.y = (dic[cc.CONST_A_Y]||0) * this._positionReadScale; + displayData.skinData.scaleX = dic[cc.CONST_A_SCALE_X]|| 1; + displayData.skinData.scaleY = dic[cc.CONST_A_SCALE_Y]|| 1; + displayData.skinData.skewX = dic[cc.CONST_A_SKEW_X]|| 0; + displayData.skinData.skewY = dic[cc.CONST_A_SKEW_Y]||0; + dic = null; + } break; case CC_DISPLAY_ARMATURE: displayData = new cc.ArmatureDisplayData(); displayData.displayName = json[cc.CONST_A_NAME] || ""; break; case CC_DISPLAY_PARTICLE: - { displayData = new cc.ParticleDisplayData(); - displayData.plist = json[cc.CONST_A_PLIST] || ""; - } - break; - case CC_DISPLAY_SHADER: - displayData = new cc.ShaderDisplayData(); - displayData.vert = json[cc.CONST_A_VERT] || ""; - displayData.frag = json[cc.CONST_A_FRAG] || ""; + displayData.plist = this._basefilePath + json[cc.CONST_A_PLIST] || ""; break; default: displayData = new cc.SpriteDisplayData(); @@ -627,10 +667,11 @@ cc.DataReaderHelper.decodeAnimationFromJson = function (json) { cc.DataReaderHelper.decodeMovementFromJson = function (json) { var movementData = new cc.MovementData(); - movementData.loop = json[cc.CONST_A_LOOP] || true; + movementData.loop = json[cc.CONST_A_LOOP] || false; movementData.durationTween = json[cc.CONST_A_DURATION_TWEEN] || 0; movementData.durationTo = json[cc.CONST_A_DURATION_TO] || 0; movementData.duration = json[cc.CONST_A_DURATION] || 0; + movementData.scale = json[cc.CONST_A_MOVEMENT_SCALE] || 1; movementData.tweenEasing = json[cc.CONST_A_TWEEN_EASING] || cc.TweenType.Linear; movementData.name = json[cc.CONST_A_NAME] || ""; @@ -649,7 +690,20 @@ cc.DataReaderHelper.decodeMovementBoneFromJson = function (json) { movementBoneData.name = json[cc.CONST_A_NAME] || ""; var frameDataList = json[cc.CONST_FRAME_DATA] || []; for (var i = 0; i < frameDataList.length; i++) { - movementBoneData.addFrameData(this.decodeFrameFromJson(frameDataList[i])); + var frameData = this.decodeFrameFromJson(frameDataList[i]); + movementBoneData.addFrameData(frameData); + if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED) { + frameData.frameID = movementBoneData.duration; + movementBoneData.duration += frameData.duration; + } + } + if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED) { + if (movementBoneData.frameList.length > 0) { + var frameData = new cc.FrameData(); + frameData.copy(movementBoneData.frameList[movementBoneData.frameList.length - 1]); + movementBoneData.addFrameData(frameData); + frameData.frameID = movementBoneData.duration; + } } return movementBoneData; }; @@ -660,7 +714,12 @@ cc.DataReaderHelper.decodeFrameFromJson = function (json) { frameData.duration = json[cc.CONST_A_DURATION] || 1; frameData.tweenEasing = json[cc.CONST_A_TWEEN_EASING] || cc.TweenType.Linear; frameData.displayIndex = json[cc.CONST_A_DISPLAY_INDEX] || 0; - + frameData.blendType = json[cc.CONST_A_BLEND_TYPE] || 0; + frameData.event = json[cc.CONST_A_EVENT] || null; + if (this._cocoStudioVersion < cc.CONST_VERSION_COMBINED) + frameData.duration = json[cc.CONST_A_DURATION] || 1; + else + frameData.frameID = json[cc.CONST_A_FRAME_INDEX] || 0; return frameData; }; diff --git a/extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js b/extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js index 905ddcd5f5..1e6e52d011 100644 --- a/extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js +++ b/extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js @@ -23,47 +23,26 @@ ****************************************************************************/ cc.SpriteFrameCacheHelper = cc.Class.extend({ - _display2ImageMap:[], - _display2TextureAtlas:null, + _textureAtlasDic:null, _imagePaths:[], - _batchNodes:null, ctor:function () { - this._display2ImageMap = []; - this._display2TextureAtlas = {}; + this._textureAtlasDic = {}; this._imagePaths = []; - this._batchNodes = {}; }, addSpriteFrameFromFile:function (plistPath, imagePath) { - var dict = cc.FileUtils.getInstance().dictionaryWithContentsOfFileThreadSafe(plistPath); - var framesDict = dict["frames"]; - for (var key in framesDict) { - var spriteFrameName = key.toString(); - this._display2ImageMap[spriteFrameName] = imagePath; - } - dict = null; cc.SpriteFrameCache.getInstance().addSpriteFrames(plistPath, imagePath); }, - getDisplayImagePath:function (_displayName) { - return this._display2ImageMap[_displayName]; - }, - getTextureAtlas:function (displayName) { - var textureName = this.getDisplayImagePath(displayName); - var atlas = this._display2TextureAtlas[textureName]; + getTexureAtlasWithTexture:function (texture) { + //todo + return null; + var textureName = texture.getName(); + var atlas = this._textureAtlasDic[textureName]; if (atlas == null) { - atlas = cc.TextureAtlas.createWithTexture(cc.TextureCache.getInstance().addImage(textureName), 20); - this._display2TextureAtlas[textureName] = atlas; + atlas = cc.TextureAtlas.createWithTexture(texture, 20); + this._textureAtlasDic[textureName] = atlas; } return atlas; - }, - getBatchNode:function (displayName) { - var textureName = this.getDisplayImagePath(displayName); - var batchNode = this._batchNodes[textureName]; - if (batchNode == null) { - var batchNode = cc.SpriteBatchNode.create(this._display2ImageMap[displayName], 40); - this._batchNodes[textureName] = batchNode; - } - return batchNode; } }); cc.SpriteFrameCacheHelper.getInstance = function () { diff --git a/extensions/CCArmature/utils/CCTransformHelp.js b/extensions/CCArmature/utils/CCTransformHelp.js index d696354136..5cd4887b90 100644 --- a/extensions/CCArmature/utils/CCTransformHelp.js +++ b/extensions/CCArmature/utils/CCTransformHelp.js @@ -54,7 +54,7 @@ cc.TransformHelp.nodeToMatrix = function (node, matrix) { matrix.a = node.scaleX * Math.cos(node.skewY); matrix.b = node.scaleX * Math.sin(node.skewY); matrix.c = node.scaleY * Math.sin(node.skewX); - matrix.d = node.scaleY * Math.cos(node.skewX); + matrix.d = node.scaleY * Math.cos(node.skewY); matrix.tx = node.x; matrix.ty = node.y; }; @@ -102,4 +102,18 @@ cc.TransformHelp.nodeConcat = function (target, source) { target.skewY += source.skewY; target.scaleX += source.scaleX; target.scaleY += source.scaleY; +}; + +/** + * @function + * @param {cc.BaseData} target + * @param {cc.BaseData} source + */ +cc.TransformHelp.nodeSub = function (target, source) { + target.x -= source.x; + target.y -= source.y; + target.skewX -= source.skewX; + target.skewY -= source.skewY; + target.scaleX -= source.scaleX; + target.scaleY -= source.scaleY; }; \ No newline at end of file diff --git a/extensions/CCArmature/utils/CSArmatureDataManager.js b/extensions/CCArmature/utils/CSArmatureDataManager.js index 33d2e33ec8..6d4778e4ef 100644 --- a/extensions/CCArmature/utils/CSArmatureDataManager.js +++ b/extensions/CCArmature/utils/CSArmatureDataManager.js @@ -31,10 +31,12 @@ cc.ArmatureDataManager = cc.Class.extend({ _animationDatas:null, _armarureDatas:null, _textureDatas:null, + _autoLoadSpriteFile:false, ctor:function () { this._animationDatas = {}; this._armarureDatas = {}; this._textureDatas = {}; + this._autoLoadSpriteFile = false; }, init:function () { @@ -51,6 +53,15 @@ cc.ArmatureDataManager = cc.Class.extend({ } }, + /** + * remove armature data + * @param {string} id + */ + removeArmatureData:function(id){ + if (this._armarureDatas.hasOwnProperty(id)) + delete this._armarureDatas[id]; + }, + /** * get armatureData by id * @param {String} id @@ -64,6 +75,14 @@ cc.ArmatureDataManager = cc.Class.extend({ return armatureData; }, + /** + * get armatureDatas + * @return {Object} + */ + getArmatureDatas:function () { + return this._armarureDatas; + }, + /** * add animation data * @param {String} id @@ -75,6 +94,15 @@ cc.ArmatureDataManager = cc.Class.extend({ } }, + /** + * remove animation data + * @param {string} id + */ + removeAnimationData:function(id){ + if (this._animationDatas.hasOwnProperty(id)) + delete this._animationDatas[id]; + }, + /** * get animationData by id * @param {String} id @@ -88,6 +116,14 @@ cc.ArmatureDataManager = cc.Class.extend({ return animationData; }, + /** + * get animationDatas + * @return {Object} + */ + getAnimationDatas:function () { + return this._animationDatas; + }, + /** * add texture data * @param {String} id @@ -100,7 +136,16 @@ cc.ArmatureDataManager = cc.Class.extend({ }, /** - * get animationData by id + * remove texture data + * @param {string} id + */ + removeTextureData:function(id){ + if (this._textureDatas.hasOwnProperty(id)) + delete this._textureDatas[id]; + }, + + /** + * get textureData by id * @param {String} id * @return {cc.TextureData} */ @@ -112,6 +157,14 @@ cc.ArmatureDataManager = cc.Class.extend({ return textureData; }, + /** + * get textureDatas + * @return {Object} + */ + getTextureDatas:function () { + return this._textureDatas; + }, + /** * Add ArmatureFileInfo, it is managed by CCArmatureDataManager. * @param {String} imagePath @@ -132,6 +185,10 @@ cc.ArmatureDataManager = cc.Class.extend({ cc.SpriteFrameCacheHelper.getInstance().addSpriteFrameFromFile(plistPath, imagePath); }, + isAutoLoadSpriteFile:function(){ + return this._autoLoadSpriteFile; + }, + removeAll:function () { this._animationDatas = null; this._armarureDatas = null; From 9a76e94857cd7b9f9336b452570b32eaeea25c7e Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 6 Sep 2013 15:33:56 +0800 Subject: [PATCH 087/141] Closed #2226: Improve Sprite, Node, LabelTTF class define for maintainability and performance --- cocos2d/label_nodes/CCLabelAtlas.js | 307 +++--- cocos2d/label_nodes/CCLabelTTF.js | 24 +- .../CCLayer.js | 342 +++--- cocos2d/misc_nodes/CCProgressTimer.js | 629 +++++------ cocos2d/misc_nodes/CCRenderTexture.js | 561 ++++------ cocos2d/sprite_nodes/CCSprite.js | 20 +- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 979 ++++++------------ cocos2d/sprite_nodes/CCSpriteFrame.js | 8 +- cocos2d/textures/CCTextureAtlas.js | 64 +- cocos2d/textures/CCTextureCache.js | 496 +-------- 10 files changed, 1147 insertions(+), 2283 deletions(-) diff --git a/cocos2d/label_nodes/CCLabelAtlas.js b/cocos2d/label_nodes/CCLabelAtlas.js index 0da76a2a29..66479026ca 100644 --- a/cocos2d/label_nodes/CCLabelAtlas.js +++ b/cocos2d/label_nodes/CCLabelAtlas.js @@ -25,27 +25,29 @@ ****************************************************************************/ /** - * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont (Canvas version) + * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont * @class * @extends cc.AtlasNode */ -cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ - // ---- common properties start ---- +cc.LabelAtlas = cc.AtlasNode.extend(/** @lends cc.LabelAtlas# */{ // string to render _string:null, // the first char in the charmap _mapStartChar:null, /** - * initializes the cc.LabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas - * It accepts two groups of parameters: - * a) string, fntFile - * b) label, textureFilename, width, height, startChar + *

+ * initializes the cc.LabelAtlas with a string, a char map file(the atlas),
+ * the width and height of each element and the starting char of the atlas
+ * It accepts two groups of parameters:
+ * a) string, fntFile
+ * b) label, textureFilename, width, height, startChar
+ *

* @param {String} strText * @param {String|cc.Texture2D} charMapFile charMapFile or fntFile or texture file - * @param {Number} itemWidth - * @param {Number} itemHeight - * @param {Number} startCharMap + * @param {Number} [itemWidth=0] + * @param {Number} [itemHeight=0] + * @param {Number} [startCharMap=""] * @return {Boolean} returns true on success */ initWithString:function (strText, charMapFile, itemWidth, itemHeight, startCharMap) { @@ -60,8 +62,9 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ cc.Assert(parseInt(dict["version"], 10) == 1, "Unsupported version. Upgrade cocos2d version"); textureFilename = relPathStr + dict["textureFilename"]; - width = parseInt(dict["itemWidth"], 10) / cc.CONTENT_SCALE_FACTOR(); - height = parseInt(dict["itemHeight"], 10) / cc.CONTENT_SCALE_FACTOR(); + var locScaleFactor = cc.CONTENT_SCALE_FACTOR(); + width = parseInt(dict["itemWidth"], 10) / locScaleFactor; + height = parseInt(dict["itemHeight"], 10) / locScaleFactor; startChar = String.fromCharCode(parseInt(dict["firstChar"], 10)); } else { textureFilename = charMapFile; @@ -102,8 +105,8 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ /** * draw the label */ - draw:function () { - cc.AtlasNode.prototype.draw.call(this); + draw:function (ctx) { + cc.AtlasNode.prototype.draw.call(this,ctx); if (cc.LABELATLAS_DEBUG_DRAW) { var s = this.getContentSize(); var vertices = [cc.p(0, 0), cc.p(s.width, 0), @@ -111,21 +114,25 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ cc.drawingUtil.drawPoly(vertices, 4, true); } }, - // ---- common properties end ---- /** * Atlas generation */ - updateAtlasValues:function () { + updateAtlasValues: null, + + _updateAtlasValuesForCanvas: function () { + var locString = this._string; + var n = locString.length; var texture = this.getTexture(); var locItemWidth = this._itemWidth, locItemHeight = this._itemHeight; - for (var i = 0; i < this._string.length; i++) { - var a = this._string.charCodeAt(i) - this._mapStartChar.charCodeAt(0); - var row = parseInt(a % this._itemsPerRow, 10) * cc.CONTENT_SCALE_FACTOR(); - var col = parseInt(a / this._itemsPerRow, 10) * cc.CONTENT_SCALE_FACTOR(); + var locScaleFactor = cc.CONTENT_SCALE_FACTOR(); + for (var i = 0; i < n; i++) { + var a = locString.charCodeAt(i) - this._mapStartChar.charCodeAt(0); + var row = parseInt(a % this._itemsPerRow, 10) * locScaleFactor; + var col = parseInt(a / this._itemsPerRow, 10) * locScaleFactor; var rect = cc.rect(row * locItemWidth, col * locItemHeight, locItemWidth, locItemHeight); - var c = this._string.charCodeAt(i); + var c = locString.charCodeAt(i); var fontChar = this.getChildByTag(i); if (!fontChar) { fontChar = new cc.Sprite(); @@ -152,151 +159,27 @@ cc.LabelAtlasCanvas = cc.AtlasNode.extend(/** @lends cc.LabelAtlasCanvas# */{ } }, - /** - * set the display string - * @param {String} label - */ - setString:function (label) { - label = String(label); - var len = label.length; - this._string = label; - this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight)); - if (this._children) { - var locChildren = this._children; - len = locChildren.length; - for (var i = 0; i < len; i++) { - var node = locChildren[i]; - if (node) - node.setVisible(false); - } - } - - this.updateAtlasValues(); - this._quadsToDraw = len; - }, - - setOpacity:function (opacity) { - if (this._displayedOpacity != opacity) { - cc.AtlasNode.prototype.setOpacity.call(this, opacity); - var locChildren = this._children; - for (var i = 0, len = locChildren.length; i < len; i++) { - if (locChildren[i]) - locChildren[i].setOpacity(opacity); - } - } - } -}); - -/** - * using image file to print text label on the screen, might be a bit slower than cc.Label, similar to cc.LabelBMFont (WebGL version) - * @class - * @extends cc.AtlasNode - */ -cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ - // ---- common properties start ---- - // string to render - _string:null, - // the first char in the charmap - _mapStartChar:null, - - /** - * initializes the cc.LabelAtlas with a string, a char map file(the atlas), the width and height of each element and the starting char of the atlas - * It accepts two groups of parameters: - * a) string, fntFile - * b) label, textureFilename, width, height, startChar - * @param {String} strText - * @param {String | cc.Texture2D} charMapFile charMapFile or fntFile - * @param {Number} itemWidth - * @param {Number} itemHeight - * @param {Number} startCharMap - * @return {Boolean} returns true on success - */ - initWithString:function (strText, charMapFile, itemWidth, itemHeight, startCharMap) { - var label = strText + "", textureFilename, width, height, startChar; - cc.Assert(label !== null, "Label must be non-nil"); - if (arguments.length === 2) { - var fileUtils = cc.FileUtils.getInstance(); - var pathStr = fileUtils.fullPathForFilename(charMapFile); - var relPathStr = pathStr.substr(0, pathStr.lastIndexOf('/')) + '/'; - - var dict = fileUtils.dictionaryWithContentsOfFileThreadSafe(pathStr); - cc.Assert(parseInt(dict["version"], 10) == 1, "Unsupported version. Upgrade cocos2d version"); - - textureFilename = relPathStr + dict["textureFilename"]; - width = parseInt(dict["itemWidth"], 10) / cc.CONTENT_SCALE_FACTOR(); - height = parseInt(dict["itemHeight"], 10) / cc.CONTENT_SCALE_FACTOR(); - startChar = String.fromCharCode(parseInt(dict["firstChar"], 10)); - } else { - textureFilename = charMapFile; - width = itemWidth || 0; - height = itemHeight || 0; - startChar = startCharMap || " "; - } - - var texture = null; - if(textureFilename instanceof cc.Texture2D) - texture = textureFilename; - else - texture = cc.TextureCache.getInstance().addImage(textureFilename); - - if (this.initWithTexture(texture, width, height, label.length)) { - this._mapStartChar = startChar; - this.setString(label); - return true; - } - return false; - }, - - /** - * @param {cc.Color3B} color3 - */ - setColor:function (color3) { - cc.AtlasNode.prototype.setColor.call(this, color3); - this.updateAtlasValues(); - }, - /** - * return the text of this label - * @return {String} - */ - getString:function () { - return this._string; - }, - - /** - * draw the label - */ - draw:function () { - cc.AtlasNode.prototype.draw.call(this); - if (cc.LABELATLAS_DEBUG_DRAW) { - var s = this.getContentSize(); - var vertices = [cc.p(0, 0), cc.p(s.width, 0), - cc.p(s.width, s.height), cc.p(0, s.height)]; - cc.drawingUtil.drawPoly(vertices, 4, true); - } - }, - // ---- common properties end ---- - - /** - * Atlas generation - */ - updateAtlasValues:function () { - var n = this._string.length; + _updateAtlasValuesForWebGL: function () { + var locString = this._string; + var n = locString.length; var locTextureAtlas = this._textureAtlas; var texture = locTextureAtlas.getTexture(); var textureWide = texture.getPixelsWide(); var textureHigh = texture.getPixelsHigh(); - var itemWidthInPixels = this._itemWidth ; + var itemWidthInPixels = this._itemWidth; var itemHeightInPixels = this._itemHeight; - if(!this._ignoreContentScaleFactor){ + if (!this._ignoreContentScaleFactor) { itemWidthInPixels = this._itemWidth * cc.CONTENT_SCALE_FACTOR(); itemHeightInPixels = this._itemHeight * cc.CONTENT_SCALE_FACTOR(); } - cc.Assert( n <= locTextureAtlas.getCapacity(), "updateAtlasValues: Invalid String length"); + cc.Assert(n <= locTextureAtlas.getCapacity(), "updateAtlasValues: Invalid String length"); var quads = locTextureAtlas.getQuads(); - var curColor = {r: this._displayedColor.r, g:this._displayedColor.g, b:this._displayedColor.b, a:this._displayedOpacity}; + var locDisplayedColor = this._displayedColor; + var curColor = {r: locDisplayedColor.r, g: locDisplayedColor.g, b: locDisplayedColor.b, a: this._displayedOpacity}; + var locItemWidth = this._itemWidth; for (var i = 0; i < n; i++) { - var a = this._string.charCodeAt(i) - this._mapStartChar.charCodeAt(0); + var a = locString.charCodeAt(i) - this._mapStartChar.charCodeAt(0); var row = a % this._itemsPerRow; var col = 0 | (a / this._itemsPerRow); @@ -314,33 +197,34 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ bottom = top + itemHeightInPixels / textureHigh; } var quad = quads[i]; - quad.tl.texCoords.u = left; - quad.tl.texCoords.v = top; - quad.tr.texCoords.u = right; - quad.tr.texCoords.v = top; - quad.bl.texCoords.u = left; - quad.bl.texCoords.v = bottom; - quad.br.texCoords.u = right; - quad.br.texCoords.v = bottom; - - quad.bl.vertices.x = (i * this._itemWidth); - quad.bl.vertices.y = 0; - quad.bl.vertices.z = 0.0; - quad.br.vertices.x = (i * this._itemWidth + this._itemWidth); - quad.br.vertices.y = 0; - quad.br.vertices.z = 0.0; - quad.tl.vertices.x = i * this._itemWidth; - quad.tl.vertices.y = this._itemHeight; - quad.tl.vertices.z = 0.0; - quad.tr.vertices.x = i * this._itemWidth + this._itemWidth; - quad.tr.vertices.y = this._itemHeight; - quad.tr.vertices.z = 0.0; - quad.tl.colors = curColor; - quad.tr.colors = curColor; - quad.bl.colors = curColor; - quad.br.colors = curColor; + var locQuadTL = quad.tl, locQuadTR = quad.tr, locQuadBL = quad.bl, locQuadBR = quad.br; + locQuadTL.texCoords.u = left; + locQuadTL.texCoords.v = top; + locQuadTR.texCoords.u = right; + locQuadTR.texCoords.v = top; + locQuadBL.texCoords.u = left; + locQuadBL.texCoords.v = bottom; + locQuadBR.texCoords.u = right; + locQuadBR.texCoords.v = bottom; + + locQuadBL.vertices.x = (i * locItemWidth); + locQuadBL.vertices.y = 0; + locQuadBL.vertices.z = 0.0; + locQuadBR.vertices.x = (i * locItemWidth + locItemWidth); + locQuadBR.vertices.y = 0; + locQuadBR.vertices.z = 0.0; + locQuadTL.vertices.x = i * locItemWidth; + locQuadTL.vertices.y = this._itemHeight; + locQuadTL.vertices.z = 0.0; + locQuadTR.vertices.x = i * locItemWidth + locItemWidth; + locQuadTR.vertices.y = this._itemHeight; + locQuadTR.vertices.z = 0.0; + locQuadTL.colors = curColor; + locQuadTR.colors = curColor; + locQuadBL.colors = curColor; + locQuadBR.colors = curColor; } - if (n > 0 ){ + if (n > 0) { locTextureAtlas.setDirty(true); var totalQuads = locTextureAtlas.getTotalQuads(); if (n > totalQuads) @@ -352,7 +236,28 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ * set the display string * @param {String} label */ - setString:function (label) { + setString: null, + + _setStringForCanvas: function (label) { + label = String(label); + var len = label.length; + this._string = label; + this.setContentSize(cc.size(len * this._itemWidth, this._itemHeight)); + if (this._children) { + var locChildren = this._children; + len = locChildren.length; + for (var i = 0; i < len; i++) { + var node = locChildren[i]; + if (node) + node.setVisible(false); + } + } + + this.updateAtlasValues(); + this._quadsToDraw = len; + }, + + _setStringForWebGL: function (label) { label = String(label); var len = label.length; if (len > this._textureAtlas.getTotalQuads()) @@ -365,24 +270,46 @@ cc.LabelAtlasWebGL = cc.AtlasNode.extend(/** @lends cc.LabelAtlasWebGL# */{ this._quadsToDraw = len; }, - setOpacity:function (opacity) { + setOpacity: null, + + _setOpacityForCanvas: function (opacity) { if (this._displayedOpacity !== opacity) { cc.AtlasNode.prototype.setOpacity.call(this, opacity); + var locChildren = this._children; + for (var i = 0, len = locChildren.length; i < len; i++) { + if (locChildren[i]) + locChildren[i].setOpacity(opacity); + } } + }, + + _setOpacityForWebGL: function (opacity) { + if (this._opacity !== opacity) + cc.AtlasNode.prototype.setOpacity.call(this, opacity); } }); -cc.LabelAtlas = cc.Browser.supportWebGL ? cc.LabelAtlasWebGL : cc.LabelAtlasCanvas; +if(cc.Browser.supportWebGL){ + cc.LabelAtlas.prototype.updateAtlasValues = cc.LabelAtlas.prototype._updateAtlasValuesForWebGL; + cc.LabelAtlas.prototype.setString = cc.LabelAtlas.prototype._setStringForWebGL; + cc.LabelAtlas.prototype.setOpacity = cc.LabelAtlas.prototype._setOpacityForWebGL; +} else { + cc.LabelAtlas.prototype.updateAtlasValues = cc.LabelAtlas.prototype._updateAtlasValuesForCanvas; + cc.LabelAtlas.prototype.setString = cc.LabelAtlas.prototype._setStringForCanvas; + cc.LabelAtlas.prototype.setOpacity = cc.LabelAtlas.prototype._setOpacityForCanvas; +} /** - * It accepts two groups of parameters: - * a) string, fntFile - * b) label, textureFilename, width, height, startChar + *

+ * It accepts two groups of parameters:
+ * a) string, fntFile
+ * b) label, textureFilename, width, height, startChar
+ *

* @param {String} strText * @param {String} charMapFile charMapFile or fntFile - * @param {Number} itemWidth - * @param {Number} itemHeight - * @param {Number} startCharMap + * @param {Number} [itemWidth=0] + * @param {Number} [itemHeight=0] + * @param {Number} [startCharMap=""] * @return {cc.LabelAtlas|Null} returns the LabelAtlas object on success * @example * //Example diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 2dfb17565f..fa4b29d913 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -137,6 +137,10 @@ cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ _setColorStyleStr:function () { var locFillColor = this._textFillColor; this._colorStyleStr = "rgba(" + locFillColor.r + "," + locFillColor.g + "," + locFillColor.b + ", " + this._displayedOpacity / 255 + ")"; + if(this._strokeEnabled){ + var locStrokeColor = this._strokeColor; + this._strokeColorStr = "rgba(" + locStrokeColor.r + "," + locStrokeColor.g + "," + locStrokeColor.b + ", " + this._displayedOpacity / 255 + ")"; + } }, /** @@ -708,21 +712,25 @@ cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ }, setPosition:function(posX, posY){ - if (arguments.length == 2) - this._originalPosition = cc.p(posX, posY); - else - this._originalPosition = cc.p(posX.x, posX.y); + var locOriginalPosition = this._originalPosition; + if (arguments.length == 2){ + locOriginalPosition.x = posX; + locOriginalPosition.y = posY; + }else { + locOriginalPosition.x = posX.x; + locOriginalPosition.y = posX.y; + } //get real position var locStrokeShadowOffsetX = 0, locStrokeShadowOffsetY = 0; if(this._strokeEnabled) locStrokeShadowOffsetX = locStrokeShadowOffsetY = this._strokeSize * 2; - if(this._shadowEnabled){ + if (this._shadowEnabled) { var locOffsetSize = this._shadowOffset; - locStrokeShadowOffsetX += locOffsetSize.width> 0?0:locOffsetSize.width; - locStrokeShadowOffsetY += locOffsetSize.height>0?0:locOffsetSize.height; + locStrokeShadowOffsetX += locOffsetSize.width > 0 ? 0 : locOffsetSize.width; + locStrokeShadowOffsetY += locOffsetSize.height > 0 ? 0 : locOffsetSize.height; } - var realPosition = cc.p(this._originalPosition.x + locStrokeShadowOffsetX, this._originalPosition.y + locStrokeShadowOffsetY); + var realPosition = cc.p(locOriginalPosition.x + locStrokeShadowOffsetX, locOriginalPosition.y + locStrokeShadowOffsetY); cc.Sprite.prototype.setPosition.call(this, realPosition); }, diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 6b3839212f..1332cc018f 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -708,15 +708,16 @@ cc.LayerRGBA = cc.Layer.extend(/** @lends cc.LayerRGBA# */{ }); /** - * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. (Canvas implement)
- * All features from CCLayer are valid, plus the following new features:
- *
  • opacity
  • - *
  • RGB colors
+ *

+ * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol.
+ * All features from CCLayer are valid, plus the following new features:
+ *

  • opacity

  • + *
  • RGB colors

+ *

* @class * @extends cc.Layer */ -cc.LayerColorCanvas = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ - // ---- common properties start ---- +cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{ _blendFunc:null, /** @@ -776,155 +777,8 @@ cc.LayerColorCanvas = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ cc.LayerRGBA.prototype.setOpacity.call(this, opacity); this._updateColor(); }, - // ---- common properties end ---- - - _updateColor:function () { - }, _isLighterMode:false, - /** - * Constructor - */ - ctor:function () { - cc.LayerRGBA.prototype.ctor.call(this); - this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); - this._color = new cc.Color4B(0, 0, 0, 0); - this._opacity = 255; - }, - - /** - * blendFunc setter - * @param {Number} src - * @param {Number} dst - */ - setBlendFunc:function (src, dst) { - if (arguments.length == 1) - this._blendFunc = src; - else - this._blendFunc = {src:src, dst:dst}; - this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771)); - }, - - /** - * @param {cc.Color4B} color - * @param {Number} width - * @param {Number} height - * @return {Boolean} - */ - init:function (color, width, height) { - if(!cc.Layer.prototype.init.call(this)) - return false; - - var winSize = cc.Director.getInstance().getWinSize(); - color = color || new cc.Color4B(0, 0, 0, 255); - width = width || winSize.width; - height = height || winSize.height; - - this._displayedColor.r = color.r; - this._displayedColor.g = color.g; - this._displayedColor.b = color.b; - - this._realColor.r = color.r; - this._realColor.g = color.g; - this._realColor.b = color.b; - - this._displayedOpacity = color.a; - this._realOpacity = color.a; - - this.setContentSize(cc.size(width, height)); - this._updateColor(); - return true; - }, - - /** - * renders the layer - * @param {CanvasRenderingContext2D|Null} ctx - */ - draw:function (ctx) { - var context = ctx || cc.renderContext; - - var tWidth = this.getContentSize().width; - var tHeight = this.getContentSize().height; - var locDisplayedColor = this._displayedColor; - - context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + "," + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")"; - context.fillRect(0, 0, tWidth, -tHeight); - - cc.g_NumberOfDraws++; - } -}); - -/** - * CCLayerColor is a subclass of CCLayer that implements the CCRGBAProtocol protocol. (WebGL implement)
- * All features from CCLayer are valid, plus the following new features:
- *
  • opacity
  • - *
  • RGB colors
- * @class - * @extends cc.Layer - */ -cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ - // ---- common properties start ---- - _blendFunc:null, - - /** - * blendFunc getter - * @return {cc.BlendFunc} - */ - getBlendFunc:function () { - return this._blendFunc; - }, - - /** - * change width and height in Points - * @param {Number} w width - * @param {Number} h height - */ - changeWidthAndHeight:function (w, h) { - this.setContentSize(cc.size(w, h)); - }, - - /** - * change width in Points - * @param {Number} w width - */ - changeWidth:function (w) { - this.setContentSize(cc.size(w, this._contentSize.height)); - }, - - /** - * change height in Points - * @param {Number} h height - */ - changeHeight:function (h) { - this.setContentSize(cc.size(this._contentSize.width, h)); - }, - - /** - * set OpacityModifyRGB of cc.LayerColor - * @param {Boolean} value - */ - setOpacityModifyRGB:function (value) { - }, - - /** - * is OpacityModifyRGB - * @return {Boolean} - */ - isOpacityModifyRGB:function () { - return false; - }, - - setColor:function(color){ - cc.LayerRGBA.prototype.setColor.call(this, color); - this._updateColor(); - }, - - setOpacity:function(opacity){ - cc.LayerRGBA.prototype.setOpacity.call(this, opacity); - this._updateColor(); - }, - - // ---- common properties end ---- _squareVertices:null, _squareColors:null, _verticesFloat32Buffer:null, @@ -935,26 +789,36 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ /** * Constructor */ - ctor:function () { + ctor: null, + + _ctorForCanvas: function () { + cc.LayerRGBA.prototype.ctor.call(this); + this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); + this._color = new cc.Color4B(0, 0, 0, 0); + this._opacity = 255; + }, + + _ctorForWebGL: function () { cc.LayerRGBA.prototype.ctor.call(this); this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); this._squareVerticesAB = new ArrayBuffer(32); this._squareColorsAB = new ArrayBuffer(64); - this._squareVertices = [new cc.Vertex2F(0, 0, this._squareVerticesAB, 0), - new cc.Vertex2F(0, 0, this._squareVerticesAB, cc.Vertex2F.BYTES_PER_ELEMENT), - new cc.Vertex2F(0, 0, this._squareVerticesAB, cc.Vertex2F.BYTES_PER_ELEMENT * 2), - new cc.Vertex2F(0, 0, this._squareVerticesAB, cc.Vertex2F.BYTES_PER_ELEMENT * 3)]; - this._squareColors = [new cc.Color4F(0, 0, 0, 1, this._squareColorsAB, 0), - new cc.Color4F(0, 0, 0, 1, this._squareColorsAB, cc.Color4F.BYTES_PER_ELEMENT), - new cc.Color4F(0, 0, 0, 1, this._squareColorsAB, cc.Color4F.BYTES_PER_ELEMENT * 2), - new cc.Color4F(0, 0, 0, 1, this._squareColorsAB, cc.Color4F.BYTES_PER_ELEMENT * 3)]; + var locSquareVerticesAB = this._squareVerticesAB, locSquareColorsAB = this._squareColorsAB; + var locVertex2FLen = cc.Vertex2F.BYTES_PER_ELEMENT, locColor4FLen = cc.Color4F.BYTES_PER_ELEMENT; + this._squareVertices = [new cc.Vertex2F(0, 0, locSquareVerticesAB, 0), + new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen), + new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 2), + new cc.Vertex2F(0, 0, locSquareVerticesAB, locVertex2FLen * 3)]; + this._squareColors = [new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, 0), + new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen), + new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 2), + new cc.Color4F(0, 0, 0, 1, locSquareColorsAB, locColor4FLen * 3)]; this._verticesFloat32Buffer = cc.renderContext.createBuffer(); this._colorsUint8Buffer = cc.renderContext.createBuffer(); }, - /** * blendFunc setter * @param {Number} src @@ -965,6 +829,8 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ this._blendFunc = src; else this._blendFunc = {src:src, dst:dst}; + if(cc.renderContextType === cc.CANVAS) + this._isLighterMode = (this._blendFunc && (this._blendFunc.src == 1) && (this._blendFunc.dst == 771)); }, /** @@ -977,20 +843,23 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ if(!cc.Layer.prototype.init.call(this)) return false; - this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); + if(cc.renderContextType !== cc.CANVAS) + this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_COLOR)); var winSize = cc.Director.getInstance().getWinSize(); color = color || new cc.Color4B(0, 0, 0, 255); width = width || winSize.width; height = height || winSize.height; - this._displayedColor.r = color.r; - this._displayedColor.g = color.g; - this._displayedColor.b = color.b; + var locDisplayedColor = this._displayedColor; + locDisplayedColor.r = color.r; + locDisplayedColor.g = color.g; + locDisplayedColor.b = color.b; - this._realColor.r = color.r; - this._realColor.g = color.g; - this._realColor.b = color.b; + var locRealColor = this._realColor; + locRealColor.r = color.r; + locRealColor.g = color.g; + locRealColor.b = color.b; this._displayedOpacity = color.a; this._realOpacity = color.a; @@ -1004,32 +873,67 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ * override contentSize * @param {cc.Size} size */ - setContentSize:function (size) { - this._squareVertices[1].x = size.width; - this._squareVertices[2].y = size.height; - this._squareVertices[3].x = size.width; - this._squareVertices[3].y = size.height; + setContentSize:null, + + _setContentSizeForWebGL:function (size) { + var locSquareVertices = this._squareVertices; + locSquareVertices[1].x = size.width; + locSquareVertices[2].y = size.height; + locSquareVertices[3].x = size.width; + locSquareVertices[3].y = size.height; this._bindLayerVerticesBufferData(); cc.Layer.prototype.setContentSize.call(this,size); }, - _updateColor:function () { + _updateColor:null, + + _updateColorForCanvas:function () { + }, + + _updateColorForWebGL:function () { var locDisplayedColor = this._displayedColor; - var locDisplayedOpacity = this._displayedOpacity; + var locDisplayedOpacity = this._displayedOpacity, locSquareColors = this._squareColors; for (var i = 0; i < 4; i++) { - this._squareColors[i].r = locDisplayedColor.r / 255; - this._squareColors[i].g = locDisplayedColor.g / 255; - this._squareColors[i].b = locDisplayedColor.b / 255; - this._squareColors[i].a = locDisplayedOpacity / 255; + locSquareColors[i].r = locDisplayedColor.r / 255; + locSquareColors[i].g = locDisplayedColor.g / 255; + locSquareColors[i].b = locDisplayedColor.b / 255; + locSquareColors[i].a = locDisplayedOpacity / 255; } this._bindLayerColorsBufferData(); }, + _bindLayerVerticesBufferData:function () { + var glContext = cc.renderContext; + glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer); + glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW); + }, + + _bindLayerColorsBufferData:function () { + var glContext = cc.renderContext; + glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer); + glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW); + }, + /** * renders the layer - * @param {CanvasContext|Null} ctx + * @param {CanvasRenderingContext2D|Null} ctx */ - draw:function (ctx) { + draw:null, + + _drawForCanvas:function (ctx) { + var context = ctx || cc.renderContext; + + var locContentSize = this.getContentSize(); + var locDisplayedColor = this._displayedColor; + + context.fillStyle = "rgba(" + (0 | locDisplayedColor.r) + "," + (0 | locDisplayedColor.g) + "," + + (0 | locDisplayedColor.b) + "," + this._displayedOpacity / 255 + ")"; + context.fillRect(0, 0, locContentSize.width, -locContentSize.height); + + cc.g_NumberOfDraws++; + }, + + _drawForWebGL:function (ctx) { var context = ctx || cc.renderContext; cc.NODE_DRAW_SETUP(this); @@ -1046,22 +950,21 @@ cc.LayerColorWebGL = cc.LayerRGBA.extend(/** @lends cc.LayerColorCanvas# */{ cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst); context.drawArrays(context.TRIANGLE_STRIP, 0, 4); - }, - - _bindLayerVerticesBufferData:function () { - var glContext = cc.renderContext; - glContext.bindBuffer(glContext.ARRAY_BUFFER, this._verticesFloat32Buffer); - glContext.bufferData(glContext.ARRAY_BUFFER, this._squareVerticesAB , glContext.STATIC_DRAW); - }, - - _bindLayerColorsBufferData:function () { - var glContext = cc.renderContext; - glContext.bindBuffer(glContext.ARRAY_BUFFER, this._colorsUint8Buffer); - glContext.bufferData(glContext.ARRAY_BUFFER, this._squareColorsAB, glContext.STATIC_DRAW); } }); -cc.LayerColor = cc.Browser.supportWebGL ? cc.LayerColorWebGL : cc.LayerColorCanvas; +if(cc.Browser.supportWebGL){ + cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForWebGL; + cc.LayerColor.prototype.setContentSize = cc.LayerColor.prototype._setContentSizeForWebGL; + cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForWebGL; + cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForWebGL; +} else { + cc.LayerColor.prototype.ctor = cc.LayerColor.prototype._ctorForCanvas; + cc.LayerColor.prototype.setContentSize = cc.LayerRGBA.prototype.setContentSize; + cc.LayerColor.prototype._updateColor = cc.LayerColor.prototype._updateColorForCanvas; + cc.LayerColor.prototype.draw = cc.LayerColor.prototype._drawForCanvas; +} + /** * creates a cc.Layer with color, width and height in Points @@ -1264,14 +1167,15 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ v = v || cc.p(0, -1); // Initializes the CCLayer with a gradient between start and end in the direction of v. - this._startColor.r = start.r; - this._startColor.g = start.g; - this._startColor.b = start.b; + var locStartColor = this._startColor, locEndColor = this._endColor; + locStartColor.r = start.r; + locStartColor.g = start.g; + locStartColor.b = start.b; this._startOpacity = start.a; - this._endColor.r = end.r; - this._endColor.g = end.g; - this._endColor.b = end.b; + locEndColor.r = end.r; + locEndColor.g = end.g; + locEndColor.b = end.b; this._endOpacity = end.a; this._alongVector = v; @@ -1338,25 +1242,27 @@ cc.LayerGradient = cc.LayerColor.extend(/** @lends cc.LayerGradient# */{ var E = {r: locEndColor.r / 255, g: locEndColor.g / 255, b: locEndColor.b / 255, a: (this._endOpacity * opacityf) / 255}; // (-1, -1) - this._squareColors[0].r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c)))); - this._squareColors[0].g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c)))); - this._squareColors[0].b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c)))); - this._squareColors[0].a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c)))); + var locSquareColors = this._squareColors; + var locSquareColor0 = locSquareColors[0], locSquareColor1 = locSquareColors[1], locSquareColor2 = locSquareColors[2],locSquareColor3 = locSquareColors[3]; + locSquareColor0.r = ((E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0 * c)))); + locSquareColor0.g = ((E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0 * c)))); + locSquareColor0.b = ((E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0 * c)))); + locSquareColor0.a = ((E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0 * c)))); // (1, -1) - this._squareColors[1].r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c)))); - this._squareColors[1].g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c)))); - this._squareColors[1].b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c)))); - this._squareColors[1].a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c)))); + locSquareColor1.r = ((E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0 * c)))); + locSquareColor1.g = ((E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0 * c)))); + locSquareColor1.b = ((E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0 * c)))); + locSquareColor1.a = ((E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0 * c)))); // (-1, 1) - this._squareColors[2].r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c)))); - this._squareColors[2].g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c)))); - this._squareColors[2].b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c)))); - this._squareColors[2].a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c)))); + locSquareColor2.r = ((E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0 * c)))); + locSquareColor2.g = ((E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0 * c)))); + locSquareColor2.b = ((E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0 * c)))); + locSquareColor2.a = ((E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0 * c)))); // (1, 1) - this._squareColors[3].r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c)))); - this._squareColors[3].g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c)))); - this._squareColors[3].b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c)))); - this._squareColors[3].a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c)))); + locSquareColor3.r = ((E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0 * c)))); + locSquareColor3.g = ((E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0 * c)))); + locSquareColor3.b = ((E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0 * c)))); + locSquareColor3.a = ((E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0 * c)))); this._bindLayerColorsBufferData(); } diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index c8722c85cf..49d4dbc289 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -50,14 +50,13 @@ cc.PROGRESS_TEXTURE_COORDS_COUNT = 4; cc.PROGRESS_TEXTURE_COORDS = 0x4b; /** - * cc.Progresstimer is a subclass of cc.Node. (Canvas implement)
+ * cc.Progresstimer is a subclass of cc.Node.
* It renders the inner sprite according to the percentage.
* The progress can be Radial, Horizontal or vertical. * @class * @extends cc.NodeRGBA */ -cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# */{ - /// ---- common properties start ---- +cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ _type:null, _percentage:0.0, _sprite:null, @@ -164,398 +163,41 @@ cc.ProgressTimerCanvas = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerCanvas# * return cc.PointZero(); }, - /// ---- common properties end ---- _origin:null, _startAngle:270, _endAngle:270, _radius:0, _counterClockWise:false, _barRect:null, - ctor:function () { - cc.NodeRGBA.prototype.ctor.call(this); - - this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; - this._percentage = 0.0; - this._midPoint = cc.p(0, 0); - this._barChangeRate = cc.p(0, 0); - this._reverseDirection = false; - - this._sprite = null; - - this._origin = cc.PointZero(); - this._startAngle = 270; - this._endAngle = 270; - this._radius = 0; - this._counterClockWise = false; - this._barRect = cc.RectZero(); - }, - - /** - * @param {Boolean} reverse - */ - setReverseProgress:function (reverse) { - if (this._reverseDirection !== reverse) { - this._reverseDirection = reverse; - } - }, - - /** - * @param {cc.Sprite} sprite - */ - setSprite:function (sprite) { - if (this._sprite != sprite) { - this._sprite = sprite; - this.setContentSize(this._sprite.getContentSize()); - } - }, - - /** - * set Progress type of cc.ProgressTimer - * @param {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} type - */ - setType:function (type) { - if (type !== this._type) { - this._type = type; - } - }, - - /** - * set color of sprite - * @param {cc.Color3B} color - */ - setColor:function (color) { - this._sprite.setColor(color); - }, - - /** - * Opacity - * @param {Number} opacity - */ - setOpacity:function (opacity) { - this._sprite.setOpacity(opacity); - }, - - /** - * return color of sprite - * @return {cc.Color3B} - */ - getColor:function () { - return this._sprite.getColor(); - }, - - /** - * return Opacity of sprite - * @return {Number} - */ - getOpacity:function () { - return this._sprite.getOpacity(); - }, - - /** - * Reverse Progress setter - * @param {Boolean} reverse - */ - setReverseDirection:function (reverse) { - if (this._reverseDirection !== reverse) { - this._reverseDirection = reverse; - } - }, - - /** - * Initializes a progress timer with the sprite as the shape the timer goes through - * @param {cc.Sprite} sprite - * @return {Boolean} - */ - initWithSprite:function (sprite) { - this.setPercentage(0); - this.setAnchorPoint(cc.p(0.5, 0.5)); - - this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; - this._reverseDirection = false; - this.setMidpoint(cc.p(0.5, 0.5)); - this.setBarChangeRate(cc.p(1, 1)); - this.setSprite(sprite); - - return true; - }, - - /** - * stuff gets drawn here - * @param {CanvasRenderingContext2D} ctx - */ - draw:function (ctx) { - var context = ctx || cc.renderContext; - - var locSprite = this._sprite; - context.globalAlpha = locSprite._displayedOpacity / 255; - var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition; - var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - - context.save(); - if (locSprite._flipX) { - flipXOffset = -locOffsetPosition.x - locRect.width; - context.scale(-1, 1); - } - if (locSprite._flipY) { - flipYOffset = locOffsetPosition.y; - context.scale(1, -1); - } - - //clip - if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { - var locBarRect = this._barRect; - context.beginPath(); - context.rect(locBarRect.x,locBarRect.y,locBarRect.width,locBarRect.height); - context.clip(); - context.closePath(); - }else if(this._type == cc.PROGRESS_TIMER_TYPE_RADIAL){ - var locOrigin = this._origin; - context.beginPath(); - context.arc(locOrigin.x, locOrigin.y, this._radius, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, this._counterClockWise); - context.lineTo(locOrigin.x, locOrigin.y); - context.clip(); - context.closePath(); - } - - //draw sprite - if (locSprite._texture && locRect.width > 0) { - var image = locSprite._texture.getHtmlElementObj(); - if (locSprite._colorized) { - context.drawImage(image, - 0, 0, locRect.width, locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.height); - } else { - context.drawImage(image, - locRect.x, locRect.y, locRect.width, locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.height); - } - } - - context.restore(); - cc.INCREMENT_GL_DRAWS(1); - }, - - _updateProgress:function () { - var locSprite = this._sprite; - var spriteSize = locSprite.getContentSize(); - var locMidPoint = this._midPoint; - - if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { - this._radius = Math.round(Math.sqrt(spriteSize.width * spriteSize.width + spriteSize.height * spriteSize.height)); - var locStartAngle = 270; - var locEndAngle = 270; - var locCounterClockWise = false; - var locOrigin = this._origin; - - locOrigin.x = spriteSize.width * locMidPoint.x; - locOrigin.y = -spriteSize.height * locMidPoint.y; - - if (this._reverseDirection) { - locStartAngle = 270 - 3.6 * this._percentage; - } else { - locEndAngle = 270 + 3.6 * this._percentage; - } - - if (locSprite._flipX) { - locOrigin.x -= spriteSize.width * (this._midPoint.x * 2); - locStartAngle= -locStartAngle; - locEndAngle= -locEndAngle; - locStartAngle -= 180; - locEndAngle -= 180; - locCounterClockWise = !locCounterClockWise; - } - if (locSprite._flipY) { - locOrigin.y+=spriteSize.height*(this._midPoint.y*2); - locCounterClockWise = !locCounterClockWise; - locStartAngle= -locStartAngle; - locEndAngle= -locEndAngle; - } - - this._startAngle = locStartAngle; - this._endAngle = locEndAngle; - this._counterClockWise = locCounterClockWise; - - } else { - var locBarChangeRate = this._barChangeRate; - var percentageF = this._percentage / 100; - var locBarRect = this._barRect; - - var drawedSize = cc.size((spriteSize.width * (1 - locBarChangeRate.x)), (spriteSize.height * (1 - locBarChangeRate.y))); - var drawingSize = cc.size((spriteSize.width - drawedSize.width) * percentageF, (spriteSize.height - drawedSize.height) * percentageF); - var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); - - var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y); - var needToLeft = startPoint.x - currentDrawSize.width / 2; - var needToTop = startPoint.y - currentDrawSize.height / 2; - - //left pos - locBarRect.x = 0; - var flipXNeed = 1; - if (locSprite._flipX) { - locBarRect.x -= currentDrawSize.width; - flipXNeed = -1; - } - - if (needToLeft > 0) { - locBarRect.x += needToLeft * flipXNeed; - } - - //right pos - locBarRect.y = 0; - var flipYNeed = 1; - if (locSprite._flipY) { - locBarRect.y += currentDrawSize.height; - flipYNeed = -1; - } - - if (needToTop > 0) { - locBarRect.y -= needToTop * flipYNeed; - } - - //clip width and clip height - locBarRect.width = currentDrawSize.width; - locBarRect.height = -currentDrawSize.height; - } - } -}); - -/** - * create a progress timer object with image file name that renders the inner sprite according to the percentage - * @param {cc.Sprite} sprite - * @return {cc.ProgressTimer} - * @example - * // Example - * var progress = cc.ProgressTimer.create('progress.png') - */ -cc.ProgressTimerCanvas.create = function (sprite) { - var progressTimer = new cc.ProgressTimerCanvas(); - if (progressTimer.initWithSprite(sprite)) - return progressTimer; - return null; -}; - -/** - * cc.Progresstimer is a subclass of cc.Node. (Canvas implement)
- * It renders the inner sprite according to the percentage.
- * The progress can be Radial, Horizontal or vertical. - * @class - * @extends cc.NodeRGBA - */ -cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ - /// ---- common properties start ---- - _type:null, - _percentage:0.0, - _sprite:null, - - _midPoint:null, - _barChangeRate:null, - _reverseDirection:false, - - /** - * Midpoint is used to modify the progress start position. - * If you're using radials type then the midpoint changes the center point - * If you're using bar type the the midpoint changes the bar growth - * it expands from the center but clamps to the sprites edge so: - * you want a left to right then set the midpoint all the way to cc.p(0,y) - * you want a right to left then set the midpoint all the way to cc.p(1,y) - * you want a bottom to top then set the midpoint all the way to cc.p(x,0) - * you want a top to bottom then set the midpoint all the way to cc.p(x,1) - * @return {cc.Point} - */ - getMidpoint:function () { - return this._midPoint; - }, - - /** - * Midpoint setter - * @param {cc.Point} mpoint - */ - setMidpoint:function (mpoint) { - this._midPoint = cc.pClamp(mpoint, cc.p(0, 0), cc.p(1, 1)); - }, - - /** - * This allows the bar type to move the component at a specific rate - * Set the component to 0 to make sure it stays at 100%. - * For example you want a left to right bar but not have the height stay 100% - * Set the rate to be cc.p(0,1); and set the midpoint to = cc.p(0,.5f); - * @return {cc.Point} - */ - getBarChangeRate:function () { - return this._barChangeRate; - }, - - /** - * @param {cc.Point} barChangeRate - */ - setBarChangeRate:function (barChangeRate) { - this._barChangeRate = cc.pClamp(barChangeRate, cc.p(0, 0), cc.p(1, 1)); - }, - - /** - * Change the percentage to change progress - * @return {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} - */ - getType:function () { - return this._type; - }, - - /** - * Percentages are from 0 to 100 - * @return {Number} - */ - getPercentage:function () { - return this._percentage; - }, - /** - * The image to show the progress percentage, retain - * @return {cc.Sprite} - */ - getSprite:function () { - return this._sprite; - }, + _vertexDataCount:0, + _vertexData:null, + _vertexArrayBuffer:null, + _vertexWebGLBuffer:null, + _vertexDataDirty:false, - /** - * from 0-100 - * @param {Number} percentage - */ - setPercentage:function (percentage) { - if (this._percentage != percentage) { - this._percentage = cc.clampf(percentage, 0, 100); - this._updateProgress(); - } - }, + ctor: null, - setOpacityModifyRGB:function (bValue) { - }, + _ctorForCanvas: function () { + cc.NodeRGBA.prototype.ctor.call(this); - isOpacityModifyRGB:function () { - return false; - }, + this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; + this._percentage = 0.0; + this._midPoint = cc.p(0, 0); + this._barChangeRate = cc.p(0, 0); + this._reverseDirection = false; - isReverseDirection:function () { - return this._reverseDirection; - }, + this._sprite = null; - _boundaryTexCoord:function (index) { - if (index < cc.PROGRESS_TEXTURE_COORDS_COUNT) { - if (this._reverseDirection) - return cc.p((cc.PROGRESS_TEXTURE_COORDS >> (7 - (index << 1))) & 1, (cc.PROGRESS_TEXTURE_COORDS >> (7 - ((index << 1) + 1))) & 1); - else - return cc.p((cc.PROGRESS_TEXTURE_COORDS >> ((index << 1) + 1)) & 1, (cc.PROGRESS_TEXTURE_COORDS >> (index << 1)) & 1); - } - return cc.PointZero(); + this._origin = cc.PointZero(); + this._startAngle = 270; + this._endAngle = 270; + this._radius = 0; + this._counterClockWise = false; + this._barRect = cc.RectZero(); }, - /// ---- common properties end ---- - - _vertexDataCount:0, - _vertexData:null, - _vertexArrayBuffer:null, - _vertexWebGLBuffer:null, - _vertexDataDirty:false, - ctor:function () { + _ctorForWebGL: function () { cc.NodeRGBA.prototype.ctor.call(this); this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; this._percentage = 0.0; @@ -607,7 +249,14 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ /** * @param {Boolean} reverse */ - setReverseProgress:function (reverse) { + setReverseProgress:null, + + _setReverseProgressForCanvas:function (reverse) { + if (this._reverseDirection !== reverse) + this._reverseDirection = reverse; + }, + + _setReverseProgressForWebGL:function (reverse) { if (this._reverseDirection !== reverse) { this._reverseDirection = reverse; @@ -621,10 +270,19 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ /** * @param {cc.Sprite} sprite */ - setSprite:function (sprite) { + setSprite:null, + + _setSpriteForCanvas:function (sprite) { if (this._sprite != sprite) { this._sprite = sprite; this.setContentSize(this._sprite.getContentSize()); + } + }, + + _setSpriteForWebGL:function (sprite) { + if (sprite && this._sprite != sprite) { + this._sprite = sprite; + this.setContentSize(sprite.getContentSize()); // Everytime we set a new sprite, we free the current vertex data if (this._vertexData) { @@ -639,7 +297,14 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ * set Progress type of cc.ProgressTimer * @param {cc.PROGRESS_TIMER_TYPE_RADIAL|cc.PROGRESS_TIMER_TYPE_BAR} type */ - setType:function (type) { + setType:null, + + _setTypeForCanvas:function (type) { + if (type !== this._type) + this._type = type; + }, + + _setTypeForWebGL:function (type) { if (type !== this._type) { // release all previous information if (this._vertexData) { @@ -647,7 +312,6 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ this._vertexArrayBuffer = null; this._vertexDataCount = 0; } - this._type = type; } }, @@ -656,7 +320,14 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ * Reverse Progress setter * @param {Boolean} reverse */ - setReverseDirection:function (reverse) { + setReverseDirection: null, + + _setReverseDirectionForCanvas: function (reverse) { + if (this._reverseDirection !== reverse) + this._reverseDirection = reverse; + }, + + _setReverseDirectionForWebGL: function (reverse) { if (this._reverseDirection !== reverse) { this._reverseDirection = reverse; //release all previous information @@ -698,12 +369,28 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ var max = cc.p(quad.tr.vertices.x, quad.tr.vertices.y); return {x: min.x * (1 - alpha.x) + max.x * alpha.x, y: min.y * (1 - alpha.y) + max.y * alpha.y}; }, + /** * Initializes a progress timer with the sprite as the shape the timer goes through * @param {cc.Sprite} sprite * @return {Boolean} */ - initWithSprite:function (sprite) { + initWithSprite:null, + + _initWithSpriteForCanvas:function (sprite) { + this.setPercentage(0); + this.setAnchorPoint(cc.p(0.5, 0.5)); + + this._type = cc.PROGRESS_TIMER_TYPE_RADIAL; + this._reverseDirection = false; + this.setMidpoint(cc.p(0.5, 0.5)); + this.setBarChangeRate(cc.p(1, 1)); + this.setSprite(sprite); + + return true; + }, + + _initWithSpriteForWebGL:function (sprite) { this.setPercentage(0); this._vertexData = null; this._vertexArrayBuffer = null; @@ -723,9 +410,63 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ /** * stuff gets drawn here - * @param {WebGLRenderingContext } ctx + * @param {CanvasRenderingContext2D} ctx */ - draw:function (ctx) { + draw:null, + + _drawForCanvas:function (ctx) { + var context = ctx || cc.renderContext; + + var locSprite = this._sprite; + context.globalAlpha = locSprite._displayedOpacity / 255; + var locRect = locSprite._rect, locOffsetPosition = locSprite._offsetPosition; + var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; + + context.save(); + if (locSprite._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (locSprite._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); + } + + //clip + if (this._type == cc.PROGRESS_TIMER_TYPE_BAR) { + var locBarRect = this._barRect; + context.beginPath(); + context.rect(locBarRect.x,locBarRect.y,locBarRect.width,locBarRect.height); + context.clip(); + context.closePath(); + }else if(this._type == cc.PROGRESS_TIMER_TYPE_RADIAL){ + var locOrigin = this._origin; + context.beginPath(); + context.arc(locOrigin.x, locOrigin.y, this._radius, (Math.PI / 180) * this._startAngle, (Math.PI / 180) * this._endAngle, this._counterClockWise); + context.lineTo(locOrigin.x, locOrigin.y); + context.clip(); + context.closePath(); + } + + //draw sprite + if (locSprite._texture && locRect.width > 0) { + var image = locSprite._texture.getHtmlElementObj(); + if (locSprite._colorized) { + context.drawImage(image, + 0, 0, locRect.width, locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.height); + } else { + context.drawImage(image, + locRect.x, locRect.y, locRect.width, locRect.height, + flipXOffset, flipYOffset, locRect.width, locRect.height); + } + } + + context.restore(); + cc.INCREMENT_GL_DRAWS(1); + }, + + _drawForWebGL:function (ctx) { var context = ctx || cc.renderContext; if (!this._vertexData || !this._sprite) return; @@ -1026,7 +767,89 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ this._vertexDataDirty = true; }, - _updateProgress:function () { + _updateProgress:null, + + _updateProgressForCanvas:function () { + var locSprite = this._sprite; + var spriteSize = locSprite.getContentSize(); + var locMidPoint = this._midPoint; + + if (this._type == cc.PROGRESS_TIMER_TYPE_RADIAL) { + this._radius = Math.round(Math.sqrt(spriteSize.width * spriteSize.width + spriteSize.height * spriteSize.height)); + var locStartAngle = 270; + var locEndAngle = 270; + var locCounterClockWise = false; + var locOrigin = this._origin; + + locOrigin.x = spriteSize.width * locMidPoint.x; + locOrigin.y = -spriteSize.height * locMidPoint.y; + + if (this._reverseDirection) { + locStartAngle = 270 - 3.6 * this._percentage; + } else { + locEndAngle = 270 + 3.6 * this._percentage; + } + + if (locSprite._flipX) { + locOrigin.x -= spriteSize.width * (this._midPoint.x * 2); + locStartAngle= -locStartAngle; + locEndAngle= -locEndAngle; + locStartAngle -= 180; + locEndAngle -= 180; + locCounterClockWise = !locCounterClockWise; + } + if (locSprite._flipY) { + locOrigin.y+=spriteSize.height*(this._midPoint.y*2); + locCounterClockWise = !locCounterClockWise; + locStartAngle= -locStartAngle; + locEndAngle= -locEndAngle; + } + + this._startAngle = locStartAngle; + this._endAngle = locEndAngle; + this._counterClockWise = locCounterClockWise; + } else { + var locBarChangeRate = this._barChangeRate; + var percentageF = this._percentage / 100; + var locBarRect = this._barRect; + + var drawedSize = cc.size((spriteSize.width * (1 - locBarChangeRate.x)), (spriteSize.height * (1 - locBarChangeRate.y))); + var drawingSize = cc.size((spriteSize.width - drawedSize.width) * percentageF, (spriteSize.height - drawedSize.height) * percentageF); + var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); + + var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y); + var needToLeft = startPoint.x - currentDrawSize.width / 2; + var needToTop = startPoint.y - currentDrawSize.height / 2; + + //left pos + locBarRect.x = 0; + var flipXNeed = 1; + if (locSprite._flipX) { + locBarRect.x -= currentDrawSize.width; + flipXNeed = -1; + } + + if (needToLeft > 0) + locBarRect.x += needToLeft * flipXNeed; + + //right pos + locBarRect.y = 0; + var flipYNeed = 1; + if (locSprite._flipY) { + locBarRect.y += currentDrawSize.height; + flipYNeed = -1; + } + + if (needToTop > 0) + locBarRect.y -= needToTop * flipYNeed; + + //clip width and clip height + locBarRect.width = currentDrawSize.width; + locBarRect.height = -currentDrawSize.height; + } + }, + + _updateProgressForWebGL:function () { var locType = this._type; if(locType === cc.PROGRESS_TIMER_TYPE_RADIAL) this._updateRadial(); @@ -1037,6 +860,26 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ } }); +if(cc.Browser.supportWebGL) { + cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForWebGL; + cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForWebGL; + cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForWebGL; + cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForWebGL; + cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForWebGL; + cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForWebGL; + cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForWebGL; + cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForWebGL; +} else { + cc.ProgressTimer.prototype.ctor = cc.ProgressTimer.prototype._ctorForCanvas; + cc.ProgressTimer.prototype.setReverseProgress = cc.ProgressTimer.prototype._setReverseProgressForCanvas; + cc.ProgressTimer.prototype.setSprite = cc.ProgressTimer.prototype._setSpriteForCanvas; + cc.ProgressTimer.prototype.setType = cc.ProgressTimer.prototype._setTypeForCanvas; + cc.ProgressTimer.prototype.setReverseDirection = cc.ProgressTimer.prototype._setReverseDirectionForCanvas; + cc.ProgressTimer.prototype.initWithSprite = cc.ProgressTimer.prototype._initWithSpriteForCanvas; + cc.ProgressTimer.prototype.draw = cc.ProgressTimer.prototype._drawForCanvas; + cc.ProgressTimer.prototype._updateProgress = cc.ProgressTimer.prototype._updateProgressForCanvas; +} + /** * create a progress timer object with image file name that renders the inner sprite according to the percentage * @param {cc.Sprite} sprite @@ -1045,13 +888,11 @@ cc.ProgressTimerWebGL = cc.NodeRGBA.extend(/** @lends cc.ProgressTimerWebGL# */{ * // Example * var progress = cc.ProgressTimer.create('progress.png') */ -cc.ProgressTimerWebGL.create = function (sprite) { - var progressTimer = new cc.ProgressTimerWebGL(); +cc.ProgressTimer.create = function (sprite) { + var progressTimer = new cc.ProgressTimer(); if (progressTimer.initWithSprite(sprite)) return progressTimer; return null; }; -cc.ProgressTimer = (cc.Browser.supportWebGL) ? cc.ProgressTimerWebGL : cc.ProgressTimerCanvas; - diff --git a/cocos2d/misc_nodes/CCRenderTexture.js b/cocos2d/misc_nodes/CCRenderTexture.js index 24a472fdbc..40d8e0a4a8 100644 --- a/cocos2d/misc_nodes/CCRenderTexture.js +++ b/cocos2d/misc_nodes/CCRenderTexture.js @@ -69,7 +69,7 @@ cc.NextPOT = function (x) { * @class * @extends cc.Node */ -cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ +cc.RenderTexture = cc.Node.extend(/** @lends cc.RenderTexture# */{ /** * the offscreen canvas for rendering and storing the texture * @type HTMLCanvasElement @@ -81,6 +81,13 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ */ _cacheContext:null, + _fBO:0, + _depthRenderBuffer:0, + _oldFBO:0, + _texture:null, + _textureCopy:null, + _uITextureImage:null, + _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, _sprite:null, @@ -96,9 +103,11 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ /** * Constructor */ - ctor:function () { + ctor: null, + + _ctorForCanvas: function () { cc.Node.prototype.ctor.call(this); - this._clearColor = cc.c4f(1,1,1,1); + this._clearColor = cc.c4f(1, 1, 1, 1); this._clearColorStr = "rgba(255,255,255,1)"; this._cacheCanvas = document.createElement('canvas'); @@ -106,318 +115,20 @@ cc.RenderTextureCanvas = cc.Node.extend(/** @lends cc.RenderTextureCanvas# */{ this.setAnchorPoint(cc.p(0, 0)); }, - onExit:function () { - cc.Node.prototype.onExit.call(this); - this._cacheContext = null; - this._cacheCanvas = null; - }, - - /** - * The sprite - * @return {cc.Sprite} - */ - getSprite:function () { - return this._sprite; - }, - - /** - * @param {cc.Sprite} sprite - */ - setSprite:function (sprite) { - this._sprite = sprite; - }, - - /** - * @param {Number} width - * @param {Number} height - * @param {cc.IMAGE_FORMAT_JPEG|cc.IMAGE_FORMAT_PNG|cc.IMAGE_FORMAT_RAWDATA} format - * @param {Number} depthStencilFormat - * @return {Boolean} - */ - initWithWidthAndHeight:function (width, height, format, depthStencilFormat) { - this._cacheCanvas.width = width || 10; - this._cacheCanvas.height = height || 10; - this._cacheContext.translate(0, this._cacheCanvas.height); - var texture = new cc.Texture2D(); - texture.initWithElement(this._cacheCanvas); - texture.handleLoadedTexture(); - this._sprite = cc.Sprite.createWithTexture(texture); - return true; - }, - - /** - * starts grabbing - */ - begin:function () { - cc.renderContext = this._cacheContext; - - /*// Save the current matrix - cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); - cc.kmGLPushMatrix(); - cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); - cc.kmGLPushMatrix();*/ - }, - - /** - * starts rendering to the texture while clearing the texture first.
- * This is more efficient then calling -clear first and then -begin - * @param {Number} r red 0-1 - * @param {Number} g green 0-1 - * @param {Number} b blue 0-1 - * @param {Number} a alpha 0-1 0 is transparent - * @param {Number} depthValue - * @param {Number} stencilValue - */ - beginWithClear:function (r, g, b, a, depthValue, stencilValue) { - var gl = cc.renderContext; - depthValue = depthValue || gl.COLOR_BUFFER_BIT; - stencilValue = stencilValue || (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - - this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)); - }, - - _beginWithClear:function (r, g, b, a, depthValue, stencilValue, flags) { - this.begin(); - - r = r || 0; - g = g || 0; - b = b || 0; - a = a || 1; - - var context = cc.renderContext; - var locCanvas = this._cacheCanvas; - context.save(); - context.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")"; - context.clearRect(0,0,locCanvas.width, -locCanvas.height); - context.fillRect(0,0,locCanvas.width, -locCanvas.height); - context.restore(); - }, - - /** - * ends grabbing - */ - end:function () { - cc.renderContext = cc.mainRenderContextBackup; - - //TODO - /*//restore viewport - director.setViewport(); - cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); - cc.kmGLPopMatrix(); - cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); - cc.kmGLPopMatrix();*/ - }, - - /** - * clears the texture with a color - * @param {Number|cc.Rect} r red 0-1 - * @param {Number} g green 0-1 - * @param {Number} b blue 0-1 - * @param {Number} a alpha 0-1 - */ - clear:function (r, g, b, a) { - this.beginWithClear(r, g, b, a); - this.end(); - }, - - clearRect:function(x, y, width, height){ - this._cacheContext.clearRect(x, y, width, -height); - }, - - /** - * clears the texture with a specified depth value - * @param {Number} depthValue - */ - clearDepth:function (depthValue) { - cc.log("clearDepth isn't supported on Cocos2d-Html5"); - }, - - /** - * clears the texture with a specified stencil value - * @param {Number} stencilValue - */ - clearStencil:function (stencilValue) { - cc.log("clearDepth isn't supported on Cocos2d-Html5"); - }, - - visit:function (ctx) { - // override visit. - // Don't call visit on its children - if (!this._visible) - return; - - ctx = ctx || cc.renderContext; - ctx.save(); - - this.draw(ctx); // update children of RenderTexture before - this.transform(ctx); - this._sprite.visit(); // draw the RenderTexture - - ctx.restore(); - - this._orderOfArrival = 0; - }, - - draw:function (ctx) { - ctx = ctx || cc.renderContext; - if (this._autoDraw) { - this.begin(); - - if (this._clearFlags) { - var locCanvas = this._cacheCanvas; - ctx.save(); - ctx.fillStyle = this._clearColorStr; - ctx.clearRect(0,0,locCanvas.width, -locCanvas.height); - ctx.fillRect(0,0,locCanvas.width, -locCanvas.height); - ctx.restore(); - } - - //! make sure all children are drawn - this.sortAllChildren(); - var locChildren = this._children; - var childrenLen = locChildren.length; - var selfSprite = this._sprite; - for (var i = 0; i < childrenLen; i++) { - var getChild = locChildren[i]; - if (getChild != selfSprite) - getChild.visit(); - } - - this.end(); - } - }, - - /** - * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete. - * @return {cc.Image} - */ - newCCImage:function (flipImage) { - cc.log("saveToFile isn't supported on Cocos2d-Html5"); - return null; - }, - - _memcpy:function (destArr, destIndex, srcArr, srcIndex, size) { - for (var i = 0; i < size; i++) { - destArr[destIndex + i] = srcArr[srcIndex + i]; - } - }, - - /** - * saves the texture into a file using JPEG format. The file will be saved in the Documents folder. - * Returns YES if the operation is successful. - * (doesn't support in HTML5) - * @param {Number} filePath - * @param {Number} format - */ - saveToFile:function (filePath, format) { - cc.log("saveToFile isn't supported on Cocos2d-Html5"); - }, - - /** - * Listen "come to background" message, and save render texture. It only has effect on Android. - * @param {cc.Class} obj - */ - listenToBackground:function (obj) { - cc.log("listenToBackground isn't supported on Cocos2d-Html5"); - }, - - /** - * Listen "come to foreground" message and restore the frame buffer object. It only has effect on Android. - * @param {cc.Class} obj - */ - listenToForeground:function (obj) { - cc.log("listenToForeground isn't supported on Cocos2d-Html5"); - }, - - /** - * Valid flags: GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT. They can be OR'ed. Valid when "autoDraw is YES. - * @return {Number} - */ - getClearFlags:function () { - return this._clearFlags; - }, - - setClearFlags:function (clearFlags) { - this._clearFlags = clearFlags; - }, - - /** - * Clear color value. Valid only when "autoDraw" is true. - * @return {cc.Color4F} - */ - getClearColor:function () { - return this._clearColor; - }, - - setClearColor:function (clearColor) { - this._clearColor = cc.c4f(clearColor.r, clearColor.g, clearColor.b, clearColor.a); - this._clearColorStr = "rgba(" + (0 | (clearColor.r * 255)) + "," + (0 | (clearColor.g * 255)) + "," + (0 | (clearColor.b * 255)) + "," + clearColor.a + ")"; - }, - - /** - * Value for clearDepth. Valid only when autoDraw is true. - * @return {Number} - */ - getClearDepth:function () { - return this._clearDepth; - }, - - setClearDepth:function (clearDepth) { - this._clearDepth = clearDepth; - }, - - /** - * Value for clear Stencil. Valid only when autoDraw is true - * @return {Number} - */ - getClearStencil:function () { - return this._clearStencil; - }, - - setClearStencil:function (clearStencil) { - this._clearStencil = clearStencil; - }, - - /** - * When enabled, it will render its children into the texture automatically. Disabled by default for compatiblity reasons.
- * Will be enabled in the future. - * @return {Boolean} - */ - isAutoDraw:function () { - return this._autoDraw; + _ctorForWebGL: function () { + cc.Node.prototype.ctor.call(this); + this._clearColor = cc.c4f(0, 0, 0, 0); }, - setAutoDraw:function (autoDraw) { - this._autoDraw = autoDraw; - } -}); - -cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ - _fBO:0, - _depthRenderBuffer:0, - _oldFBO:0, - _texture:null, - _textureCopy:null, - _uITextureImage:null, - _pixelFormat:cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, - _sprite:null, - - //code for "auto" update - _clearFlags:0, - _clearColor:null, - _clearDepth:0, - _clearStencil:0, - _autoDraw:false, + onExit:null, - /** - * Constructor - */ - ctor:function () { - cc.Node.prototype.ctor.call(this); - this._clearColor = cc.c4f(0, 0, 0, 0); + _onExitForCanvas:function () { + cc.Node.prototype.onExit.call(this); + this._cacheContext = null; + this._cacheCanvas = null; }, - onExit: function () { + _onExitForWebGL: function () { cc.Node.prototype.onExit.call(this); this._sprite = null; @@ -454,7 +165,21 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ * @param {Number} depthStencilFormat * @return {Boolean} */ - initWithWidthAndHeight:function (width, height, format, depthStencilFormat) { + initWithWidthAndHeight: null, + + _initWithWidthAndHeightForCanvas: function (width, height, format, depthStencilFormat) { + var locCacheCanvas = this._cacheCanvas; + locCacheCanvas.width = width || 10; + locCacheCanvas.height = height || 10; + this._cacheContext.translate(0, locCacheCanvas.height); + var texture = new cc.Texture2D(); + texture.initWithElement(locCacheCanvas); + texture.handleLoadedTexture(); + this._sprite = cc.Sprite.createWithTexture(texture); + return true; + }, + + _initWithWidthAndHeightForWebGL: function (width, height, format, depthStencilFormat) { cc.Assert(format != cc.TEXTURE_2D_PIXEL_FORMAT_A8, "only RGB and RGBA formats are valid for a render texture"); var gl = cc.renderContext; @@ -488,7 +213,8 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ if (!this._texture) return false; - this._texture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); + var locTexture = this._texture; + locTexture.initWithData(data, this._pixelFormat, powW, powH, cc.size(width, height)); //free( data ); var oldRBO = gl.getParameter(gl.RENDERBUFFER_BINDING); @@ -506,7 +232,7 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ gl.bindFramebuffer(gl.FRAMEBUFFER, this._fBO); // associate texture with FBO - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this._texture._webTextureObj, 0); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, locTexture._webTextureObj, 0); if (depthStencilFormat != 0) { //create and attach depth buffer @@ -523,27 +249,40 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ // check if it worked (probably worth doing :) ) cc.Assert(gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE, "Could not attach texture to framebuffer"); - this._texture.setAliasTexParameters(); + locTexture.setAliasTexParameters(); - this._sprite = cc.Sprite.createWithTexture(this._texture); - this._sprite.setScaleY(-1); - this._sprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + this._sprite = cc.Sprite.createWithTexture(locTexture); + var locSprite = this._sprite; + locSprite.setScaleY(-1); + locSprite.setBlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.bindRenderbuffer(gl.RENDERBUFFER, oldRBO); gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO); - // Diabled by default. + // Disabled by default. this._autoDraw = false; // add sprite for backward compatibility - this.addChild(this._sprite); + this.addChild(locSprite); return true; }, /** * starts grabbing */ - begin:function () { + begin: null, + + _beginForCanvas: function () { + cc.renderContext = this._cacheContext; + + /*// Save the current matrix + cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); + cc.kmGLPushMatrix(); + cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); + cc.kmGLPushMatrix();*/ + }, + + _beginForWebGL: function () { // Save the current matrix cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); cc.kmGLPushMatrix(); @@ -594,8 +333,8 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ * @param {Number} g green 0-1 * @param {Number} b blue 0-1 * @param {Number} a alpha 0-1 0 is transparent - * @param {Number} depthValue - * @param {Number} stencilValue + * @param {Number} [depthValue=] + * @param {Number} [stencilValue=] */ beginWithClear:function (r, g, b, a, depthValue, stencilValue) { var gl = cc.renderContext; @@ -605,7 +344,27 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ this._beginWithClear(r, g, b, a, depthValue, stencilValue, (gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)); }, - _beginWithClear:function (r, g, b, a, depthValue, stencilValue, flags) { + _beginWithClear: null, + + _beginWithClearForCanvas: function (r, g, b, a, depthValue, stencilValue, flags) { + this.begin(); + + r = r || 0; + g = g || 0; + b = b || 0; + a = a || 1; + + //var context = cc.renderContext; + var context = this._cacheContext; + var locCanvas = this._cacheCanvas; + context.save(); + context.fillStyle = "rgba(" + (0 | (r * 255)) + "," + (0 | (g * 255)) + "," + (0 | (b * 255)) + "," + a + ")"; + context.clearRect(0, 0, locCanvas.width, -locCanvas.height); + context.fillRect(0, 0, locCanvas.width, -locCanvas.height); + context.restore(); + }, + + _beginWithClearForWebGL: function (r, g, b, a, depthValue, stencilValue, flags) { this.begin(); var gl = cc.renderContext; @@ -646,7 +405,21 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ /** * ends grabbing */ - end:function () { + end: null, + + _endForCanvas: function () { + cc.renderContext = cc.mainRenderContextBackup; + + //TODO + /*//restore viewport + director.setViewport(); + cc.kmGLMatrixMode(cc.KM_GL_PROJECTION); + cc.kmGLPopMatrix(); + cc.kmGLMatrixMode(cc.KM_GL_MODELVIEW); + cc.kmGLPopMatrix();*/ + }, + + _endForWebGL: function () { var gl = cc.renderContext; var director = cc.Director.getInstance(); gl.bindFramebuffer(gl.FRAMEBUFFER, this._oldFBO); @@ -683,11 +456,27 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ this.end(); }, + clearRect:null, + + _clearRectForCanvas:function(x, y, width, height){ + this._cacheContext.clearRect(x, y, width, -height); + }, + + _clearRectForWebGL:function(x, y, width, height){ + //TODO need to implement + }, + /** * clears the texture with a specified depth value * @param {Number} depthValue */ - clearDepth:function (depthValue) { + clearDepth:null, + + _clearDepthForCanvas:function (depthValue) { + cc.log("clearDepth isn't supported on Cocos2d-Html5"); + }, + + _clearDepthForWebGL:function (depthValue) { this.begin(); var gl = cc.renderContext; @@ -706,7 +495,13 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ * clears the texture with a specified stencil value * @param {Number} stencilValue */ - clearStencil:function (stencilValue) { + clearStencil:null, + + _clearStencilForCanvas:function (stencilValue) { + cc.log("clearDepth isn't supported on Cocos2d-Html5"); + }, + + _clearStencilForWebGL:function (stencilValue) { var gl = cc.renderContext; // save old stencil value var stencilClearValue = gl.getParameter(gl.STENCIL_CLEAR_VALUE); @@ -718,7 +513,27 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ gl.clearStencil(stencilClearValue); }, - visit:function (ctx) { + visit:null, + + _visitForCanvas:function (ctx) { + // override visit. + // Don't call visit on its children + if (!this._visible) + return; + + ctx = ctx || cc.renderContext; + ctx.save(); + + this.draw(ctx); // update children of RenderTexture before + this.transform(ctx); + this._sprite.visit(); // draw the RenderTexture + + ctx.restore(); + + this._orderOfArrival = 0; + }, + + _visitForWebGL:function (ctx) { // override visit. // Don't call visit on its children if (!this._visible) @@ -744,7 +559,38 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ this._orderOfArrival = 0; }, - draw:function (ctx) { + draw:null, + + _drawForCanvas: function (ctx) { + ctx = ctx || cc.renderContext; + if (this._autoDraw) { + this.begin(); + + if (this._clearFlags) { + var locCanvas = this._cacheCanvas; + ctx.save(); + ctx.fillStyle = this._clearColorStr; + ctx.clearRect(0, 0, locCanvas.width, -locCanvas.height); + ctx.fillRect(0, 0, locCanvas.width, -locCanvas.height); + ctx.restore(); + } + + //! make sure all children are drawn + this.sortAllChildren(); + var locChildren = this._children; + var childrenLen = locChildren.length; + var selfSprite = this._sprite; + for (var i = 0; i < childrenLen; i++) { + var getChild = locChildren[i]; + if (getChild != selfSprite) + getChild.visit(); + } + + this.end(); + } + }, + + _drawForWebGL: function (ctx) { var gl = cc.renderContext; if (this._autoDraw) { this.begin(); @@ -802,7 +648,14 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ * creates a new CCImage from with the texture's data. Caller is responsible for releasing it by calling delete. * @return {cc.Image} */ - newCCImage:function (flipImage) { + newCCImage:null, + + _newCCImageForCanvas:function (flipImage) { + cc.log("saveToFile isn't supported on Cocos2d-Html5"); + return null; + }, + + _newCCImageForWebGL:function (flipImage) { if(flipImage === null) flipImage = true; cc.Assert(this._pixelFormat == cc.TEXTURE_2D_PIXEL_FORMAT_RGBA8888, "only RGBA8888 can be saved as image"); @@ -901,8 +754,24 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ return this._clearColor; }, - setClearColor:function (clearColor) { - this._clearColor = cc.c4f(clearColor.r, clearColor.g, clearColor.b, clearColor.a); + setClearColor:null, + + _setClearColorForCanvas:function (clearColor) { + var locClearColor = this._clearColor; + locClearColor.r = clearColor.r; + locClearColor.g = clearColor.g; + locClearColor.b = clearColor.b; + locClearColor.a = clearColor.a; + + this._clearColorStr = "rgba(" + (0 | (clearColor.r * 255)) + "," + (0 | (clearColor.g * 255)) + "," + (0 | (clearColor.b * 255)) + "," + clearColor.a + ")"; + }, + + _setClearColorForWebGL:function (clearColor) { + var locClearColor = this._clearColor; + locClearColor.r = clearColor.r; + locClearColor.g = clearColor.g; + locClearColor.b = clearColor.b; + locClearColor.a = clearColor.a; }, /** @@ -943,7 +812,35 @@ cc.RenderTextureWebGL = cc.Node.extend(/** @lends cc.RenderTextureWebGL# */{ } }); -cc.RenderTexture = cc.Browser.supportWebGL ? cc.RenderTextureWebGL : cc.RenderTextureCanvas; +if(cc.Browser.supportWebGL){ + cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForWebGL; + cc.RenderTexture.prototype.onExit = cc.RenderTexture.prototype._onExitForWebGL; + cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForWebGL; + cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForWebGL; + cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForWebGL; + cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForWebGL; + cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForWebGL; + cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForWebGL; + cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForWebGL; + cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForWebGL; + cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForWebGL; + cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForWebGL; + cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForWebGL; +} else { + cc.RenderTexture.prototype.ctor = cc.RenderTexture.prototype._ctorForCanvas; + cc.RenderTexture.prototype.onExit = cc.RenderTexture.prototype._onExitForCanvas; + cc.RenderTexture.prototype.initWithWidthAndHeight = cc.RenderTexture.prototype._initWithWidthAndHeightForCanvas; + cc.RenderTexture.prototype.begin = cc.RenderTexture.prototype._beginForCanvas; + cc.RenderTexture.prototype._beginWithClear = cc.RenderTexture.prototype._beginWithClearForCanvas; + cc.RenderTexture.prototype.end = cc.RenderTexture.prototype._endForCanvas; + cc.RenderTexture.prototype.clearRect = cc.RenderTexture.prototype._clearRectForCanvas; + cc.RenderTexture.prototype.clearDepth = cc.RenderTexture.prototype._clearDepthForCanvas; + cc.RenderTexture.prototype.clearStencil = cc.RenderTexture.prototype._clearStencilForCanvas; + cc.RenderTexture.prototype.visit = cc.RenderTexture.prototype._visitForCanvas; + cc.RenderTexture.prototype.draw = cc.RenderTexture.prototype._drawForCanvas; + cc.RenderTexture.prototype.newCCImage = cc.RenderTexture.prototype._newCCImageForCanvas; + cc.RenderTexture.prototype.setClearColor = cc.RenderTexture.prototype._setClearColorForCanvas; +} /** * creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are valid diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 47784e799d..6c0b3e5fdf 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1995,14 +1995,18 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ context.globalAlpha = this._displayedOpacity / 255; var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - if (this._flipX) { - flipXOffset = -locOffsetPosition.x - locRect.width; - context.scale(-1, 1); - } - if (this._flipY) { - flipYOffset = locOffsetPosition.y; - context.scale(1, -1); + if (this._flipX || this._flipY) { + context.save(); + if (this._flipX) { + flipXOffset = -locOffsetPosition.x - locRect.width; + context.scale(-1, 1); + } + if (this._flipY) { + flipYOffset = locOffsetPosition.y; + context.scale(1, -1); + } } + if (this._texture && locRect.width > 0) { var image = this._texture.getHtmlElementObj(); if (this._colorized) { @@ -2036,6 +2040,8 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; cc.drawingUtil.drawPoly(vertices2, 4, true); } + if (this._flipX || this._flipY) + context.restore(); cc.g_NumberOfDraws++; } }); diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index 92e3a00c66..d3a7f2b549 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -33,7 +33,7 @@ cc.DEFAULT_SPRITE_BATCH_CAPACITY = 29; /** *

* In Canvas render mode ,cc.SpriteBatchNodeCanvas is like a normal node: if it contains children.
- * If its _useCache is set to true, it can cache the result that all children of SpriteBatchNodeCanvas to a canvas
+ * If its _useCache is set to true, it can cache the result that all children of SpriteBatchNode to a canvas
* (often known as "batch draw").
*
* A cc.SpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
@@ -51,593 +51,9 @@ cc.DEFAULT_SPRITE_BATCH_CAPACITY = 29; * @extends cc.Node * @example * //create a SpriteBatchNode - * var parent2 = cc.SpriteBatchNodeCanvas.create("res/animations/grossini.png", 50); - */ -cc.SpriteBatchNodeCanvas = cc.Node.extend(/** @lends cc.SpriteBatchNodeCanvas# */{ - /// ---- common properties start ---- - _textureAtlas:null, - _blendFunc:null, - // all descendants: chlidren, gran children, etc... - _descendants:null, - - /** - *

- * This is the opposite of "addQuadFromSprite.
- * It add the sprite to the children and descendants array, but it doesn't update add it to the texture atlas
- *

- * @param {cc.Sprite} child - * @param {Number} z zOrder - * @param {Number} aTag - * @return {cc.SpriteBatchNode} - */ - addSpriteWithoutQuad:function (child, z, aTag) { - cc.Assert(child != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil"); - cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); - - // quad index is Z - child.setAtlasIndex(z); - - // XXX: optimize with a binary search - var i = 0, locDescendants = this._descendants; - if (locDescendants && locDescendants.length > 0) { - for (var index = 0; index < locDescendants.length; index++) { - var obj = locDescendants[index]; - if (obj && (obj.getAtlasIndex() >= z)) - ++i; - } - } - this._descendants = cc.ArrayAppendObjectToIndex(locDescendants, child, i); - - // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array - cc.Node.prototype.addChild.call(this, child, z, aTag); - - //#issue 1262 don't use lazy sorting, tiles are added as quads not as sprites, so sprites need to be added in order - this.reorderBatch(false); - return this; - }, - - // property - /** - * Return TextureAtlas of cc.SpriteBatchNode - * @return {cc.TextureAtlas} - */ - getTextureAtlas:function () { - return this._textureAtlas; - }, - - /** - * TextureAtlas of cc.SpriteBatchNode setter - * @param {cc.TextureAtlas} textureAtlas - */ - setTextureAtlas:function (textureAtlas) { - if (textureAtlas != this._textureAtlas) { - this._textureAtlas = textureAtlas; - } - }, - - /** - * Return Descendants of cc.SpriteBatchNode - * @return {Array} - */ - getDescendants:function () { - return this._descendants; - }, - - /** - *

- * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr. - *

- * @param {String} fileImage - * @param {Number} capacity - * @return {Boolean} - */ - initWithFile:function (fileImage, capacity) { - var texture2D = cc.TextureCache.getInstance().textureForKey(fileImage); - if (!texture2D) - texture2D = cc.TextureCache.getInstance().addImage(fileImage); - return this.initWithTexture(texture2D, capacity); - }, - - _setNodeDirtyForCache:function () { - this._cacheDirty = true; - }, - - /** - *

- * initializes a cc.SpriteBatchNode with a file image (.png, .jpeg, .pvr, etc) and a capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space.
- * The file will be loaded using the TextureMgr. - *

- * @param {String} fileImage - * @param {Number} capacity - * @return {Boolean} - */ - init:function (fileImage, capacity) { - var texture2D = cc.TextureCache.getInstance().textureForKey(fileImage); - if (!texture2D) - texture2D = cc.TextureCache.getInstance().addImage(fileImage); - return this.initWithTexture(texture2D, capacity); - }, - - /** - * increase Atlas Capacity - */ - increaseAtlasCapacity:function () { - // if we're going beyond the current TextureAtlas's capacity, - // all the previously initialized sprites will need to redo their texture coords - // this is likely computationally expensive - var quantity = Math.floor((this._textureAtlas.getCapacity() + 1) * 4 / 3); - - cc.log("cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from " + this._textureAtlas.getCapacity() + " to " + quantity + "."); - - if (!this._textureAtlas.resizeCapacity(quantity)) { - // serious problems - cc.log("cocos2d: WARNING: Not enough memory to resize the atlas"); - cc.Assert(false, "Not enough memory to resize the atla"); - } - }, - - /** - * removes a child given a certain index. It will also cleanup the running actions depending on the cleanup parameter. - * @warning Removing a child from a cc.SpriteBatchNode is very slow - * @param {Number} index - * @param {Boolean} doCleanup - */ - removeChildAtIndex:function (index, doCleanup) { - this.removeChild(this._children[index], doCleanup); - }, - - /** - * rebuild index in order for child - * @param {cc.Sprite} pobParent - * @param {Number} index - * @return {Number} - */ - rebuildIndexInOrder:function (pobParent, index) { - var children = pobParent.getChildren(); - if (children && children.length > 0) { - for (var i = 0; i < children.length; i++) { - var obj = children[i]; - if (obj && (obj.getZOrder() < 0)) { - index = this.rebuildIndexInOrder(obj, index); - } - } - } - // ignore self (batch node) - if (!pobParent == this) { - pobParent.setAtlasIndex(index); - index++; - } - if (children && children.length > 0) { - for (i = 0; i < children.length; i++) { - obj = children[i]; - if (obj && (obj.getZOrder() >= 0)) { - index = this.rebuildIndexInOrder(obj, index); - } - } - } - return index; - }, - - /** - * get highest atlas index in child - * @param {cc.Sprite} sprite - * @return {Number} - */ - highestAtlasIndexInChild:function (sprite) { - var children = sprite.getChildren(); - - if (!children || children.length == 0) - return sprite.getAtlasIndex(); - else - return this.highestAtlasIndexInChild(children[children.length - 1]); - }, - - /** - * get lowest atlas index in child - * @param {cc.Sprite} sprite - * @return {Number} - */ - lowestAtlasIndexInChild:function (sprite) { - var children = sprite.getChildren(); - - if (!children || children.length == 0) - return sprite.getAtlasIndex(); - else - return this.lowestAtlasIndexInChild(children[children.length - 1]); - }, - - /** - * get atlas index for child - * @param {cc.Sprite} sprite - * @param {Number} nZ - * @return {Number} - */ - atlasIndexForChild:function (sprite, nZ) { - var brothers = sprite.getParent().getChildren(); - var childIndex = cc.ArrayGetIndexOfObject(brothers, sprite); - - // ignore parent Z if parent is spriteSheet - var ignoreParent = sprite.getParent() == this; - var previous = null; - if (childIndex > 0 && childIndex < cc.UINT_MAX) - previous = brothers[childIndex - 1]; - - // first child of the sprite sheet - if (ignoreParent) { - if (childIndex == 0) - return 0; - return this.highestAtlasIndexInChild(previous) + 1; - } - - // parent is a cc.Sprite, so, it must be taken into account - // first child of an cc.Sprite ? - var selParent; - if (childIndex == 0) { - selParent = sprite.getParent(); - - // less than parent and brothers - if (nZ < 0) - return selParent.getAtlasIndex(); - else - return selParent.getAtlasIndex() + 1; - } else { - // previous & sprite belong to the same branch - if ((previous.getZOrder() < 0 && nZ < 0) || (previous.getZOrder() >= 0 && nZ >= 0)) - return this.highestAtlasIndexInChild(previous) + 1; - - // else (previous < 0 and sprite >= 0 ) - selParent = sprite.getParent(); - return selParent.getAtlasIndex() + 1; - } - }, - - /** - * Sprites use this to start sortChildren, don't call this manually - * @param {Boolean} reorder - */ - reorderBatch:function (reorder) { - this._reorderChildDirty = reorder; - }, - - /** - * set the source blending function for the texture - * @param {Number | cc.BlendFunc} src - * @param {Number} dst - */ - setBlendFunc:function (src, dst) { - if (arguments.length == 1) - this._blendFunc = src; - else - this._blendFunc = {src:src, dst:dst}; - }, - - /** - * returns the blending function used for the texture - * @return {cc.BlendFunc} - */ - getBlendFunc:function () { - return this._blendFunc; - }, - - /** - * (override reorderChild of cc.Node) - * @override - * @param {cc.Sprite} child - * @param {Number} zOrder - */ - reorderChild:function (child, zOrder) { - cc.Assert(child != null, "SpriteBatchNode.addChild():the child should not be null"); - cc.Assert(this._children.indexOf(child) > -1, "SpriteBatchNode.addChild():Child doesn't belong to Sprite"); - - if (zOrder === child.getZOrder()) - return; - - //set the z-order and sort later - cc.Node.prototype.reorderChild.call(this, child, zOrder); - this.setNodeDirty(); - }, - - /** - * remove child from cc.SpriteBatchNode (override removeChild of cc.Node) - * @param {cc.Sprite} child - * @param cleanup - */ - removeChild:function (child, cleanup) { - // explicit null handling - if (child == null) - return; - - cc.Assert(this._children.indexOf(child) > -1, "SpriteBatchNode.addChild():sprite batch node should contain the child"); - - // cleanup before removing - this.removeSpriteFromAtlas(child); - cc.Node.prototype.removeChild.call(this, child, cleanup); - }, - /// ---- common properties end ---- - - _textureForCanvas:null, - _useCache:false, - _originalTexture:null, - - /** - * Constructor - * @param {String} fileImage - */ - ctor:function (fileImage) { - cc.Node.prototype.ctor.call(this); - if (fileImage) - this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY); - }, - - /** - *

- * Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array.
- * This method should be called only when you are dealing with very big AtlasSrite and when most of the cc.Sprite won't be updated.
- * For example: a tile map (cc.TMXMap) or a label with lots of characters (BitmapFontAtlas)
- *

- * @param {cc.Sprite} sprite - * @param {Number} index - */ - updateQuadFromSprite:function (sprite, index) { - cc.Assert(sprite != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil"); - cc.Assert((sprite instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); - - // - // update the quad directly. Don't add the sprite to the scene graph - // - sprite.setBatchNode(this); - sprite.setAtlasIndex(index); - - sprite.setDirty(true); - // UpdateTransform updates the textureAtlas quad - sprite.updateTransform(); - }, - - /** - *

- * Inserts a quad at a certain index into the texture atlas. The cc.Sprite won't be added into the children array.
- * This method should be called only when you are dealing with very big AtlasSprite and when most of the cc.Sprite won't be updated.
- * For example: a tile map (cc.TMXMap) or a label with lots of characters (cc.LabelBMFont) - *

- * @param {cc.Sprite} sprite - * @param {Number} index - */ - insertQuadFromSprite:function (sprite, index) { - cc.Assert(sprite != null, "Argument must be non-NULL"); - cc.Assert(sprite instanceof cc.Sprite, "cc.SpriteBatchNode only supports cc.Sprites as children"); - - // - // update the quad directly. Don't add the sprite to the scene graph - // - sprite.setBatchNode(this); - sprite.setAtlasIndex(index); - - // XXX: updateTransform will update the textureAtlas too, using updateQuad. - // XXX: so, it should be AFTER the insertQuad - sprite.setDirty(true); - sprite.updateTransform(); - this._children = cc.ArrayAppendObjectToIndex(this._children, sprite, index); - }, - - /** - *

- * initializes a CCSpriteBatchNode with a texture2d and capacity of children.
- * The capacity will be increased in 33% in runtime if it run out of space. - *

- * @param {cc.Texture2D} tex - * @param {Number} capacity - * @return {Boolean} - */ - initWithTexture:function (tex, capacity) { - this._children = []; - this._descendants = []; - - this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); - - this._originalTexture = tex; - this._textureForCanvas = tex; - return true; - }, - - /** - * addChild helper, faster than insertChild - * @param {cc.Sprite} sprite - */ - appendChild:function (sprite) { - this._reorderChildDirty = true; - sprite.setBatchNode(this); - sprite.setDirty(true); - - this._descendants.push(sprite); - var index = this._descendants.length - 1; - sprite.setAtlasIndex(index); - - // add children recursively - var children = sprite.getChildren(); - for (var i = 0; i < children.length; i++) - this.appendChild(children[i]); - }, - - /** - * remove sprite from TextureAtlas - * @param {cc.Sprite} sprite - */ - removeSpriteFromAtlas:function (sprite) { - // Cleanup sprite. It might be reused (issue #569) - sprite.setBatchNode(null); - var locDescendants = this._descendants; - var index = cc.ArrayGetIndexOfObject(locDescendants, sprite); - if (index != -1) { - cc.ArrayRemoveObjectAtIndex(locDescendants, index); - - // update all sprites beyond this one - var len = locDescendants.length; - for (; index < len; ++index) { - var s = locDescendants[index]; - s.setAtlasIndex(s.getAtlasIndex() - 1); - } - } - - // remove children recursively - var children = sprite.getChildren(); - if (children && children.length > 0) { - for (var i = 0; i < children.length; i++) - if (children[i]) - this.removeSpriteFromAtlas(children[i]); - } - }, - // CCTextureProtocol - /** - * Return texture of cc.SpriteBatchNode - * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} - */ - getTexture:function () { - return this._textureForCanvas; - }, - - /** - * texture of cc.SpriteBatchNode setter - * @param {cc.Texture2D} texture - */ - setTexture:function (texture) { - this._textureForCanvas = texture; - var locChildren = this._children; - for (var i = 0; i < locChildren.length; i++) - locChildren[i].setTexture(texture); - }, - - /** - * don't call visit on it's children ( override visit of cc.Node ) - * @override - * @param {CanvasRenderingContext2D} ctx - */ - visit:function (ctx) { - var context = ctx || cc.renderContext; - // quick return if not visible - if (!this._visible) - return; - - context.save(); - this.transform(ctx); - var i, locChildren = this._children; - - if (locChildren) { - this.sortAllChildren(); - for (i = 0; i < locChildren.length; i++) { - if (locChildren[i]) - locChildren[i].visit(context); - } - } - - context.restore(); - }, - - /** - * add child to cc.SpriteBatchNode (override addChild of cc.Node) - * @override - * @param {cc.Sprite} child - * @param {Number} zOrder - * @param {Number} tag - */ - addChild:function (child, zOrder, tag) { - if (child == null) - return; - - if (arguments.length === 4) - if (arguments[3] == true) { - cc.Node.prototype.addChild.call(this, child, zOrder, tag); - this.setNodeDirty(); - return; - } - - zOrder = (zOrder == null) ? child.getZOrder() : zOrder; - tag = (tag == null) ? child.getTag() : tag; - - cc.Assert(child != null, "SpriteBatchNode.addChild():child should not be null"); - cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); - - cc.Node.prototype.addChild.call(this, child, zOrder, tag); - this.appendChild(child); - this.setNodeDirty(); - }, - - /** - *

Removes all children from the container and do a cleanup all running actions depending on the cleanup parameter.
- * (override removeAllChildren of cc.Node)

- * @param {Boolean} cleanup - */ - removeAllChildren:function (cleanup) { - // Invalidate atlas index. issue #569 - // useSelfRender should be performed on all descendants. issue #1216 - var locDescendants = this._descendants; - if (locDescendants && locDescendants.length > 0) { - for (var i = 0; i < locDescendants.length; i++) { - if (locDescendants[i]) - locDescendants[i].setBatchNode(null); - } - } - - cc.Node.prototype.removeAllChildren.call(this, cleanup); - this._descendants = []; - }, - - sortAllChildren:function () { - if (this._reorderChildDirty) { - var i, j = 0, locChildren = this._children; - var length = locChildren.length, tempChild; - //insertion sort - for (i = 1; i < length; i++) { - var 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; - } - - //sorted now check all children - if (locChildren.length > 0) { - //first sort all children recursively based on zOrder - this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); - } - this._reorderChildDirty = false; - } - } -}); - -/** - *

- * In WebGL render mode ,cc.SpriteBatchNode is like a batch node: if it contains children, it will draw them in 1 single OpenGL call
- * (often known as "batch draw").
- *
- * A cc.SpriteBatchNode can reference one and only one texture (one image file, one texture atlas).
- * Only the cc.Sprites that are contained in that texture can be added to the cc.SpriteBatchNode.
- * All cc.Sprites added to a cc.SpriteBatchNode are drawn in one WebGL draw call.
- * If the cc.Sprites are not added to a cc.SpriteBatchNode then an WebGL draw call will be needed for each one, which is less efficient.
- *
- * Limitations:
- * - The only object that is accepted as child (or grandchild, grand-grandchild, etc...) is cc.Sprite or any subclass of cc.Sprite.
- * eg: particles, labels and layer can't be added to a cc.SpriteBatchNode.
- * - Either all its children are Aliased or Antialiased. It can't be a mix.
- * This is because "alias" is a property of the texture, and all the sprites share the same texture.
- *

- * @class - * @extends cc.Node - * @example - * //create a SpriteBatchNodeWebGL - * var parent2 = cc.SpriteBatchNodeWebGL.create("res/animations/grossini.png", 50); + * var parent2 = cc.SpriteBatchNode.create("res/animations/grossini.png", 50); */ -cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ - /// ---- common properties start ---- +cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{ _textureAtlas:null, _blendFunc:null, // all descendants: chlidren, gran children, etc... @@ -661,15 +77,15 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ child.setAtlasIndex(z); // XXX: optimize with a binary search - var i = 0; - if (this._descendants && this._descendants.length > 0) { - for (var index = 0; index < this._descendants.length; index++) { - var obj = this._descendants[index]; + var i = 0, locDescendants = this._descendants; + if (locDescendants && locDescendants.length > 0) { + for (var index = 0; index < locDescendants.length; index++) { + var obj = locDescendants[index]; if (obj && (obj.getAtlasIndex() >= z)) ++i; } } - this._descendants = cc.ArrayAppendObjectToIndex(this._descendants, child, i); + this._descendants = cc.ArrayAppendObjectToIndex(locDescendants, child, i); // IMPORTANT: Call super, and not self. Avoid adding it to the texture atlas array cc.Node.prototype.addChild.call(this, child, z, aTag); @@ -751,9 +167,10 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ // if we're going beyond the current TextureAtlas's capacity, // all the previously initialized sprites will need to redo their texture coords // this is likely computationally expensive - var quantity = 0 | ((this._textureAtlas.getCapacity() + 1) * 4 / 3); + var locCapacity = this._textureAtlas.getCapacity(); + var quantity = Math.floor((locCapacity + 1) * 4 / 3); - cc.log("cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from " + this._textureAtlas.getCapacity() + " to [" + quantity + "]."); + cc.log("cocos2d: CCSpriteBatchNode: resizing TextureAtlas capacity from " + locCapacity + " to " + quantity + "."); if (!this._textureAtlas.resizeCapacity(quantity)) { // serious problems @@ -937,22 +354,34 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ // cleanup before removing this.removeSpriteFromAtlas(child); - cc.Node.prototype.removeChild.call(this, child, cleanup); }, - /// ---- common properties end ---- + _mvpMatrix:null, + _textureForCanvas:null, + _useCache:false, + _originalTexture:null, + /** * Constructor * @param {String} fileImage */ - ctor:function (fileImage) { + ctor: null, + + _ctorForCanvas: function (fileImage) { + cc.Node.prototype.ctor.call(this); + if (fileImage) + this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY); + }, + + _ctorForWebGL: function (fileImage) { cc.Node.prototype.ctor.call(this); this._mvpMatrix = new cc.kmMat4(); if (fileImage) this.init(fileImage, cc.DEFAULT_SPRITE_BATCH_CAPACITY); }, + /** *

* Updates a quad at a certain index into the texture atlas. The CCSprite won't be added into the children array.
@@ -962,12 +391,30 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * @param {cc.Sprite} sprite * @param {Number} index */ - updateQuadFromSprite:function (sprite, index) { + updateQuadFromSprite:null, + + _updateQuadFromSpriteForCanvas:function (sprite, index) { + cc.Assert(sprite != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil"); + cc.Assert((sprite instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); + + // + // update the quad directly. Don't add the sprite to the scene graph + // + sprite.setBatchNode(this); + sprite.setAtlasIndex(index); + + sprite.setDirty(true); + // UpdateTransform updates the textureAtlas quad + sprite.updateTransform(); + }, + + _updateQuadFromSpriteForWebGL:function (sprite, index) { cc.Assert(sprite != null, "SpriteBatchNode.addQuadFromSprite():Argument must be non-nil"); cc.Assert((sprite instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); // make needed room - while (index >= this._textureAtlas.getCapacity() || this._textureAtlas.getCapacity() == this._textureAtlas.getTotalQuads()) { + var locCapacity = this._textureAtlas.getCapacity(); + while (index >= locCapacity || locCapacity == this._textureAtlas.getTotalQuads()) { this.increaseAtlasCapacity(); } @@ -983,17 +430,19 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ }, _swap:function (oldIndex, newIndex) { - var quads = this._textureAtlas.getQuads(); - var tempItem = this._descendants[oldIndex]; + var locDescendants = this._descendants; + var locTextureAtlas = this._textureAtlas; + var quads = locTextureAtlas.getQuads(); + var tempItem = locDescendants[oldIndex]; var tempIteQuad = cc.V3F_C4B_T2F_QuadCopy(quads[oldIndex]); //update the index of other swapped item - this._descendants[newIndex].setAtlasIndex(oldIndex); - this._descendants[oldIndex] = this._descendants[newIndex]; + locDescendants[newIndex].setAtlasIndex(oldIndex); + locDescendants[oldIndex] = locDescendants[newIndex]; - this._textureAtlas.updateQuad(quads[newIndex], oldIndex); - this._descendants[newIndex] = tempItem; - this._textureAtlas.updateQuad(tempIteQuad, newIndex); + locTextureAtlas.updateQuad(quads[newIndex], oldIndex); + locDescendants[newIndex] = tempItem; + locTextureAtlas.updateQuad(tempIteQuad, newIndex); }, /** @@ -1005,12 +454,33 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * @param {cc.Sprite} sprite * @param {Number} index */ - insertQuadFromSprite:function (sprite, index) { + insertQuadFromSprite:null, + + _insertQuadFromSpriteForCanvas:function (sprite, index) { + cc.Assert(sprite != null, "Argument must be non-NULL"); + cc.Assert(sprite instanceof cc.Sprite, "cc.SpriteBatchNode only supports cc.Sprites as children"); + + // + // update the quad directly. Don't add the sprite to the scene graph + // + sprite.setBatchNode(this); + sprite.setAtlasIndex(index); + + // XXX: updateTransform will update the textureAtlas too, using updateQuad. + // XXX: so, it should be AFTER the insertQuad + sprite.setDirty(true); + sprite.updateTransform(); + this._children = cc.ArrayAppendObjectToIndex(this._children, sprite, index); + }, + + _insertQuadFromSpriteForWebGL:function (sprite, index) { cc.Assert(sprite != null, "Argument must be non-NULL"); cc.Assert(sprite instanceof cc.Sprite, "cc.SpriteBatchNode only supports cc.Sprites as children"); // make needed room - while (index >= this._textureAtlas.getCapacity() || this._textureAtlas.getCapacity() === this._textureAtlas.getTotalQuads()) + var locTextureAtlas = this._textureAtlas; + var locCapacity = locTextureAtlas.getCapacity(); + while (index >= locCapacity || locCapacity === locTextureAtlas.getTotalQuads()) this.increaseAtlasCapacity(); // @@ -1018,7 +488,7 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ // sprite.setBatchNode(this); sprite.setAtlasIndex(index); - this._textureAtlas.insertQuad(sprite.getQuad(), index); + locTextureAtlas.insertQuad(sprite.getQuad(), index); // XXX: updateTransform will update the textureAtlas too, using updateQuad. // XXX: so, it should be AFTER the insertQuad @@ -1095,10 +565,23 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * The capacity will be increased in 33% in runtime if it run out of space. *

* @param {cc.Texture2D} tex - * @param {Number} capacity + * @param {Number} [capacity] * @return {Boolean} */ - initWithTexture:function (tex, capacity) { + initWithTexture:null, + + _initWithTextureForCanvas:function (tex, capacity) { + this._children = []; + this._descendants = []; + + this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); + + this._originalTexture = tex; + this._textureForCanvas = tex; + return true; + }, + + _initWithTextureForWebGL:function (tex, capacity) { this._children = []; this._descendants = []; @@ -1110,6 +593,7 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); return true; }, + /** * add child helper * @param {cc.Sprite} sprite @@ -1120,26 +604,27 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ sprite.setAtlasIndex(index); sprite.setDirty(true); - if (this._textureAtlas.getTotalQuads() == this._textureAtlas.getCapacity()) + var locTextureAtlas = this._textureAtlas; + if (locTextureAtlas.getTotalQuads() >= locTextureAtlas.getCapacity()) this.increaseAtlasCapacity(); - this._textureAtlas.insertQuad(sprite.getQuad(), index); + locTextureAtlas.insertQuad(sprite.getQuad(), index); this._descendants = cc.ArrayAppendObjectToIndex(this._descendants, sprite, index); // update indices - var i = index + 1; - if (this._descendants && this._descendants.length > 0) { - for (; i < this._descendants.length; i++) - this._descendants[i].setAtlasIndex(this._descendants[i].getAtlasIndex() + 1); + var i = index + 1, locDescendant = this._descendants; + if (locDescendant && locDescendant.length > 0) { + for (; i < locDescendant.length; i++) + locDescendant[i].setAtlasIndex(locDescendant[i].getAtlasIndex() + 1); } // add children recursively - var children = sprite.getChildren(); - if (children && children.length > 0) { - for (i = 0; i < children.length; i++) { - if (children[i]) { - var getIndex = this.atlasIndexForChild(children[i], children[i].getZOrder()); - this.insertChild(children[i], getIndex); + var locChildren = sprite.getChildren(); + if (locChildren && locChildren.length > 0) { + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) { + var getIndex = this.atlasIndexForChild(locChildren[i], locChildren[i].getZOrder()); + this.insertChild(locChildren[i], getIndex); } } } @@ -1149,18 +634,36 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * addChild helper, faster than insertChild * @param {cc.Sprite} sprite */ - appendChild:function (sprite) { + appendChild:null, + + _appendChildForCanvas:function (sprite) { + this._reorderChildDirty = true; + sprite.setBatchNode(this); + sprite.setDirty(true); + + this._descendants.push(sprite); + var index = this._descendants.length - 1; + sprite.setAtlasIndex(index); + + // add children recursively + var children = sprite.getChildren(); + for (var i = 0; i < children.length; i++) + this.appendChild(children[i]); + }, + + _appendChildForWebGL:function (sprite) { this._reorderChildDirty = true; sprite.setBatchNode(this); sprite.setDirty(true); - cc.ArrayAppendObject(this._descendants, sprite); + this._descendants.push(sprite); var index = this._descendants.length - 1; sprite.setAtlasIndex(index); - if (this._textureAtlas.getTotalQuads() == this._textureAtlas.getCapacity()) + var locTextureAtlas = this._textureAtlas; + if (locTextureAtlas.getTotalQuads() == locTextureAtlas.getCapacity()) this.increaseAtlasCapacity(); - this._textureAtlas.insertQuad(sprite.getQuad(), index); + locTextureAtlas.insertQuad(sprite.getQuad(), index); // add children recursively var children = sprite.getChildren(); @@ -1172,20 +675,49 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * remove sprite from TextureAtlas * @param {cc.Sprite} sprite */ - removeSpriteFromAtlas:function (sprite) { + removeSpriteFromAtlas:null, + + _removeSpriteFromAtlasForCanvas:function (sprite) { + // Cleanup sprite. It might be reused (issue #569) + sprite.setBatchNode(null); + var locDescendants = this._descendants; + var index = cc.ArrayGetIndexOfObject(locDescendants, sprite); + if (index != -1) { + cc.ArrayRemoveObjectAtIndex(locDescendants, index); + + // update all sprites beyond this one + var len = locDescendants.length; + for (; index < len; ++index) { + var s = locDescendants[index]; + s.setAtlasIndex(s.getAtlasIndex() - 1); + } + } + + // remove children recursively + var children = sprite.getChildren(); + if (children && children.length > 0) { + for (var i = 0; i < children.length; i++) + if (children[i]) + this.removeSpriteFromAtlas(children[i]); + } + }, + + _removeSpriteFromAtlasForWebGL:function (sprite) { this._textureAtlas.removeQuadAtIndex(sprite.getAtlasIndex()); // remove from TextureAtlas // Cleanup sprite. It might be reused (issue #569) sprite.setBatchNode(null); - var index = cc.ArrayGetIndexOfObject(this._descendants, sprite); + var locDescendants = this._descendants; + var index = cc.ArrayGetIndexOfObject(locDescendants, sprite); if (index != -1) { - cc.ArrayRemoveObjectAtIndex(this._descendants, index); + cc.ArrayRemoveObjectAtIndex(locDescendants, index); // update all sprites beyond this one - var len = this._descendants.length; + + var len = locDescendants.length; for (; index < len; ++index) { - var s = this._descendants[index]; + var s = locDescendants[index]; s.setAtlasIndex(s.getAtlasIndex() - 1); } } @@ -1198,13 +730,18 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ this.removeSpriteFromAtlas(children[i]); } }, - // CCTextureProtocol /** * Return texture of cc.SpriteBatchNode * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} */ - getTexture:function () { + getTexture:null, + + _getTextureForCanvas:function () { + return this._textureForCanvas; + }, + + _getTextureForWebGL:function () { return this._textureAtlas.getTexture(); }, @@ -1212,7 +749,16 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * texture of cc.SpriteBatchNode setter * @param {cc.Texture2D} texture */ - setTexture:function (texture) { + setTexture:null, + + _setTextureForCanvas:function (texture) { + this._textureForCanvas = texture; + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) + locChildren[i].setTexture(texture); + }, + + _setTextureForWebGL:function (texture) { this._textureAtlas.setTexture(texture); this._updateBlendFunc(); }, @@ -1220,9 +766,32 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ /** * don't call visit on it's children ( override visit of cc.Node ) * @override - * @param {WebGLRenderingContext} ctx + * @param {CanvasRenderingContext2D} ctx */ - visit:function (ctx) { + visit:null, + + _visitForCanvas:function (ctx) { + var context = ctx || cc.renderContext; + // quick return if not visible + if (!this._visible) + return; + + context.save(); + this.transform(ctx); + var i, locChildren = this._children; + + if (locChildren) { + this.sortAllChildren(); + for (i = 0; i < locChildren.length; i++) { + if (locChildren[i]) + locChildren[i].visit(context); + } + } + + context.restore(); + }, + + _visitForWebGL:function (ctx) { var gl = ctx || cc.renderContext; // CAREFUL: @@ -1235,15 +804,16 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ if (!this._visible) return; cc.kmGLPushMatrix(); - if (this._grid && this._grid.isActive()) { - this._grid.beforeDraw(); + var locGrid = this._grid; + if (locGrid && locGrid.isActive()) { + locGrid.beforeDraw(); this.transformAncestors(); } this.sortAllChildren(); this.transform(gl); this.draw(gl); - if (this._grid && this._grid.isActive()) - this._grid.afterDraw(this); + if (locGrid && locGrid.isActive()) + locGrid.afterDraw(this); cc.kmGLPopMatrix(); this.setOrderOfArrival(0); }, @@ -1252,19 +822,29 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * add child to cc.SpriteBatchNode (override addChild of cc.Node) * @override * @param {cc.Sprite} child - * @param {Number} zOrder - * @param {Number} tag + * @param {Number} [zOrder] + * @param {Number} [tag] */ - addChild:function (child, zOrder, tag) { + addChild: null, + + _addChildForCanvas: function (child, zOrder, tag) { if (child == null) return; - if (arguments.length === 4) - if (arguments[3] == true) { - cc.Node.prototype.addChild.call(this, child, zOrder, tag); - this.setNodeDirty(); - return; - } + zOrder = (zOrder == null) ? child.getZOrder() : zOrder; + tag = (tag == null) ? child.getTag() : tag; + + cc.Assert(child != null, "SpriteBatchNode.addChild():child should not be null"); + cc.Assert((child instanceof cc.Sprite), "cc.SpriteBatchNode only supports cc.Sprites as children"); + + cc.Node.prototype.addChild.call(this, child, zOrder, tag); + this.appendChild(child); + this.setNodeDirty(); + }, + + _addChildForWebGL: function (child, zOrder, tag) { + if (child == null) + return; zOrder = (zOrder == null) ? child.getZOrder() : zOrder; tag = (tag == null) ? child.getTag() : tag; @@ -1285,13 +865,31 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ * (override removeAllChildren of cc.Node)

* @param {Boolean} cleanup */ - removeAllChildren:function (cleanup) { + removeAllChildren:null, + + _removeAllChildrenForCanvas:function (cleanup) { + // Invalidate atlas index. issue #569 + // useSelfRender should be performed on all descendants. issue #1216 + var locDescendants = this._descendants; + if (locDescendants && locDescendants.length > 0) { + for (var i = 0, len = locDescendants.length; i < len; i++) { + if (locDescendants[i]) + locDescendants[i].setBatchNode(null); + } + } + + cc.Node.prototype.removeAllChildren.call(this, cleanup); + this._descendants = []; + }, + + _removeAllChildrenForWebGL:function (cleanup) { // Invalidate atlas index. issue #569 // useSelfRender should be performed on all descendants. issue #1216 - if (this._descendants && this._descendants.length > 0) { - for (var i = 0; i < this._descendants.length; i++) { - if (this._descendants[i]) - this._descendants[i].setBatchNode(null); + var locDescendants = this._descendants; + if (locDescendants && locDescendants.length > 0) { + for (var i = 0, len = locDescendants.length; i < len; i++) { + if (locDescendants[i]) + locDescendants[i].setBatchNode(null); } } cc.Node.prototype.removeAllChildren.call(this, cleanup); @@ -1299,7 +897,38 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ this._textureAtlas.removeAllQuads(); }, - sortAllChildren:function () { + sortAllChildren:null, + + _sortAllChildrenForCanvas:function () { + if (this._reorderChildDirty) { + var i, j = 0, locChildren = this._children; + var length = locChildren.length, tempChild; + //insertion sort + for (i = 1; i < length; i++) { + var 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; + } + + //sorted now check all children + if (locChildren.length > 0) { + //first sort all children recursively based on zOrder + this._arrayMakeObjectsPerformSelector(locChildren, cc.Node.StateCallbackType.sortAllChildren); + } + this._reorderChildDirty = false; + } + }, + + _sortAllChildrenForWebGL:function () { if (this._reorderChildDirty) { var childrenArr = this._children; var i, j = 0, length = childrenArr.length, tempChild; @@ -1336,7 +965,9 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ /** * draw cc.SpriteBatchNode (override draw of cc.Node) */ - draw:function () { + draw:null, + + _drawForWebGL:function () { // Optimization: Fast Dispatch if (this._textureAtlas.getTotalQuads() === 0) return; @@ -1351,7 +982,35 @@ cc.SpriteBatchNodeWebGL = cc.Node.extend(/** @lends cc.SpriteBatchNodeWebGL# */{ } }); -cc.SpriteBatchNode = (cc.Browser.supportWebGL)?cc.SpriteBatchNodeWebGL:cc.SpriteBatchNodeCanvas; +if(cc.Browser.supportWebGL){ + cc.SpriteBatchNode.prototype.ctor = cc.SpriteBatchNode.prototype._ctorForWebGL; + cc.SpriteBatchNode.prototype.updateQuadFromSprite = cc.SpriteBatchNode.prototype._updateQuadFromSpriteForWebGL; + cc.SpriteBatchNode.prototype.insertQuadFromSprite = cc.SpriteBatchNode.prototype._insertQuadFromSpriteForWebGL; + cc.SpriteBatchNode.prototype.initWithTexture = cc.SpriteBatchNode.prototype._initWithTextureForWebGL; + cc.SpriteBatchNode.prototype.appendChild = cc.SpriteBatchNode.prototype._appendChildForWebGL; + cc.SpriteBatchNode.prototype.removeSpriteFromAtlas = cc.SpriteBatchNode.prototype._removeSpriteFromAtlasForWebGL; + cc.SpriteBatchNode.prototype.getTexture = cc.SpriteBatchNode.prototype._getTextureForWebGL; + cc.SpriteBatchNode.prototype.setTexture = cc.SpriteBatchNode.prototype._setTextureForWebGL; + cc.SpriteBatchNode.prototype.visit = cc.SpriteBatchNode.prototype._visitForWebGL; + cc.SpriteBatchNode.prototype.addChild = cc.SpriteBatchNode.prototype._addChildForWebGL; + cc.SpriteBatchNode.prototype.removeAllChildren = cc.SpriteBatchNode.prototype._removeAllChildrenForWebGL; + cc.SpriteBatchNode.prototype.sortAllChildren = cc.SpriteBatchNode.prototype._sortAllChildrenForWebGL; + cc.SpriteBatchNode.prototype.draw = cc.SpriteBatchNode.prototype._drawForWebGL; +} else { + cc.SpriteBatchNode.prototype.ctor = cc.SpriteBatchNode.prototype._ctorForCanvas; + cc.SpriteBatchNode.prototype.updateQuadFromSprite = cc.SpriteBatchNode.prototype._updateQuadFromSpriteForCanvas; + cc.SpriteBatchNode.prototype.insertQuadFromSprite = cc.SpriteBatchNode.prototype._insertQuadFromSpriteForCanvas; + cc.SpriteBatchNode.prototype.initWithTexture = cc.SpriteBatchNode.prototype._initWithTextureForCanvas; + cc.SpriteBatchNode.prototype.appendChild = cc.SpriteBatchNode.prototype._appendChildForCanvas; + cc.SpriteBatchNode.prototype.removeSpriteFromAtlas = cc.SpriteBatchNode.prototype._removeSpriteFromAtlasForCanvas; + cc.SpriteBatchNode.prototype.getTexture = cc.SpriteBatchNode.prototype._getTextureForCanvas; + cc.SpriteBatchNode.prototype.setTexture = cc.SpriteBatchNode.prototype._setTextureForCanvas; + cc.SpriteBatchNode.prototype.visit = cc.SpriteBatchNode.prototype._visitForCanvas; + cc.SpriteBatchNode.prototype.removeAllChildren = cc.SpriteBatchNode.prototype._removeAllChildrenForCanvas; + cc.SpriteBatchNode.prototype.addChild = cc.SpriteBatchNode.prototype._addChildForCanvas; + cc.SpriteBatchNode.prototype.sortAllChildren = cc.SpriteBatchNode.prototype._sortAllChildrenForCanvas; + cc.SpriteBatchNode.prototype.draw = cc.Node.prototype.draw; +} /** *

@@ -1387,6 +1046,4 @@ cc.SpriteBatchNode.createWithTexture = function (texture, capacity) { var batchNode = new cc.SpriteBatchNode(); batchNode.initWithTexture(texture, capacity); return batchNode; -}; - - +}; \ No newline at end of file diff --git a/cocos2d/sprite_nodes/CCSpriteFrame.js b/cocos2d/sprite_nodes/CCSpriteFrame.js index 9315519d8f..b113920052 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrame.js +++ b/cocos2d/sprite_nodes/CCSpriteFrame.js @@ -192,8 +192,12 @@ cc.SpriteFrame = cc.Class.extend(/** @lends cc.SpriteFrame# */{ getTexture:function () { if (this._texture) return this._texture; - if (this._textureFilename !== "") - return cc.TextureCache.getInstance().addImage(this._textureFilename); + if (this._textureFilename !== "") { + var locTexture = cc.TextureCache.getInstance().addImage(this._textureFilename); + if (locTexture) + this._textureLoaded = locTexture.isLoaded(); + return locTexture; + } return null; }, diff --git a/cocos2d/textures/CCTextureAtlas.js b/cocos2d/textures/CCTextureAtlas.js index 9a34e5c569..80179f824b 100644 --- a/cocos2d/textures/CCTextureAtlas.js +++ b/cocos2d/textures/CCTextureAtlas.js @@ -122,20 +122,20 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ if(!quads) return; - for(var i = 0; i < quads.length ; i++){ + for(var i = 0; i < quads.length ; i++) this._setQuadToArray(quads[i], index + i); - } }, _setQuadToArray: function (quad, index) { - if (!this._quads[index]) { - this._quads[index] = new cc.V3F_C4B_T2F_Quad(quad.tl, quad.bl, quad.tr, quad.br, this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT); + var locQuads = this._quads; + if (!locQuads[index]) { + locQuads[index] = new cc.V3F_C4B_T2F_Quad(quad.tl, quad.bl, quad.tr, quad.br, this._quadsArrayBuffer, index * cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT); return; } - this._quads[index].bl = quad.bl; - this._quads[index].br = quad.br; - this._quads[index].tl = quad.tl; - this._quads[index].tr = quad.tr; + locQuads[index].bl = quad.bl; + locQuads[index].br = quad.br; + locQuads[index].tl = quad.tl; + locQuads[index].tr = quad.tr; }, /** @@ -149,24 +149,24 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ _setupIndices:function () { if (this._capacity === 0) return; - - for (var i = 0; i < this._capacity; i++) { + var locIndices = this._indices, locCapacity = this._capacity; + for (var i = 0; i < locCapacity; i++) { if (cc.TEXTURE_ATLAS_USE_TRIANGLE_STRIP) { - this._indices[i * 6 + 0] = i * 4 + 0; - this._indices[i * 6 + 1] = i * 4 + 0; - this._indices[i * 6 + 2] = i * 4 + 2; - this._indices[i * 6 + 3] = i * 4 + 1; - this._indices[i * 6 + 4] = i * 4 + 3; - this._indices[i * 6 + 5] = i * 4 + 3; + locIndices[i * 6 + 0] = i * 4 + 0; + locIndices[i * 6 + 1] = i * 4 + 0; + locIndices[i * 6 + 2] = i * 4 + 2; + locIndices[i * 6 + 3] = i * 4 + 1; + locIndices[i * 6 + 4] = i * 4 + 3; + locIndices[i * 6 + 5] = i * 4 + 3; } else { - this._indices[i * 6 + 0] = i * 4 + 0; - this._indices[i * 6 + 1] = i * 4 + 1; - this._indices[i * 6 + 2] = i * 4 + 2; + locIndices[i * 6 + 0] = i * 4 + 0; + locIndices[i * 6 + 1] = i * 4 + 1; + locIndices[i * 6 + 2] = i * 4 + 2; // inverted index. issue #179 - this._indices[i * 6 + 3] = i * 4 + 3; - this._indices[i * 6 + 4] = i * 4 + 2; - this._indices[i * 6 + 5] = i * 4 + 1; + locIndices[i * 6 + 3] = i * 4 + 3; + locIndices[i * 6 + 4] = i * 4 + 2; + locIndices[i * 6 + 5] = i * 4 + 1; } } }, @@ -345,18 +345,19 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ return; var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; - var sourceArr = this._quadsReader.subarray(fromIndex * quadSize,quadSize); + var locQuadsReader = this._quadsReader; + var sourceArr = locQuadsReader.subarray(fromIndex * quadSize,quadSize); var startOffset, moveLength; if(fromIndex > newIndex){ startOffset = newIndex * quadSize; moveLength = (fromIndex - newIndex) * quadSize; - this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength),startOffset + quadSize); - this._quadsReader.set(sourceArr,startOffset); + locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength),startOffset + quadSize); + locQuadsReader.set(sourceArr,startOffset); }else{ startOffset = (fromIndex + 1) * quadSize; moveLength = (newIndex - fromIndex) * quadSize; - this._quadsReader.set(this._quadsReader.subarray(startOffset, startOffset + moveLength),startOffset - quadSize); - this._quadsReader.set(sourceArr, newIndex * quadSize); + locQuadsReader.set(locQuadsReader.subarray(startOffset, startOffset + moveLength),startOffset - quadSize); + locQuadsReader.set(sourceArr, newIndex * quadSize); } this._dirty = true; }, @@ -515,19 +516,20 @@ cc.TextureAtlas = cc.Class.extend(/** @lends cc.TextureAtlas# */{ var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; var srcOffset = oldIndex * quadSize; var srcLength = amount * quadSize; - var sourceArr = this._quadsReader.subarray(srcOffset, srcOffset + srcLength); + var locQuadsReader = this._quadsReader; + var sourceArr = locQuadsReader.subarray(srcOffset, srcOffset + srcLength); var dstOffset = newIndex * quadSize; var moveLength, moveStart; if (newIndex < oldIndex) { moveLength = (oldIndex - newIndex) * quadSize; moveStart = newIndex * quadSize; - this._quadsReader.set(this._quadsReader.subarray(moveStart, moveStart + moveLength), moveStart + srcLength) + locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), moveStart + srcLength) } else { moveLength = (newIndex - oldIndex) * quadSize; moveStart = (oldIndex + amount) * quadSize; - this._quadsReader.set(this._quadsReader.subarray(moveStart, moveStart + moveLength), srcOffset); + locQuadsReader.set(locQuadsReader.subarray(moveStart, moveStart + moveLength), srcOffset); } - this._quadsReader.set(sourceArr, dstOffset); + locQuadsReader.set(sourceArr, dstOffset); this._dirty = true; }, diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index f1abdbaaaa..583a7f10a7 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -67,401 +67,14 @@ cc.computeImageFormatType = function (filename) { }; /** - * Implementation TextureCache (Canvas implement) + * Implementation TextureCache * @class * @extends cc.Class */ -cc.TextureCacheCanvas = cc.Class.extend(/** @lends cc.TextureCacheCanvas# */{ - /// ---- common properties start ---- +cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{ _textures:null, _textureColorsCache:null, - _textureKeySeq:1000, - - /** - * Constructor - */ - ctor:function () { - cc.Assert(cc.g_sharedTextureCache == null, "Attempted to allocate a second instance of a singleton."); - this._textureKeySeq += (0 | Math.random() * 1000); - this._textures = {}; - this._textureColorsCache = {}; - }, - - _addImageAsyncCallBack:function (target, selector) { - if (target && (typeof(selector) == "string")) { - target[selector](); - } else if (target && (typeof(selector) == "function")) { - selector.call(target); - } - }, - - /** - *

- * Returns a Texture2D object given an PVR filename
- * If the file image was not previously loaded, it will create a new CCTexture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image
- * note: AddPVRTCImage does not support on HTML5 - *

- * @param {String} filename - * @return {cc.Texture2D} - */ - addPVRTCImage:function (filename) { - cc.Assert(0, "TextureCache:addPVRTCImage does not support on HTML5"); - }, - - - /** - *

- * Returns a Texture2D object given an ETC filename
- * If the file image was not previously loaded, it will create a new CCTexture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image
- * note:addETCImage does not support on HTML5 - *

- * @param {String} filename - * @return {cc.Texture2D} - */ - addETCImage:function (filename) { - cc.Assert(0, "TextureCache:addPVRTCImage does not support on HTML5"); - }, - - /** - * Description - * @return {String} - */ - description:function () { - return ""; - }, - - /** - * Returns an already created texture. Returns null if the texture doesn't exist. - * @param {String} textureKeyName - * @return {HTMLImageElement|cc.Texture2D|Null} - * @example - * //example - * var key = cc.TextureCache.getInstance().textureForKey("hello.png"); - */ - textureForKey:function (textureKeyName) { - var fullPath = cc.FileUtils.getInstance().fullPathForFilename(textureKeyName); - if (this._textures.hasOwnProperty(fullPath)) - return this._textures[fullPath]; - return null; - }, - - /** - * @param {Image} texture - * @return {String|Null} - * @example - * //example - * var key = cc.TextureCache.getInstance().getKeyByTexture(texture); - */ - getKeyByTexture:function (texture) { - for (var key in this._textures) { - if (this._textures[key] == texture) { - return key; - } - } - return null; - }, - - _generalTextureKey:function () { - this._textureKeySeq++; - return "_textureKey_" + this._textureKeySeq; - }, - - /** - * @param {Image} texture - * @return {Array} - * @example - * //example - * var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(texture); - */ - getTextureColors:function (texture) { - var key = this.getKeyByTexture(texture); - if (!key) { - if (texture instanceof HTMLImageElement) - key = texture.src; - else - key = this._generalTextureKey(); - } - - if (!this._textureColorsCache.hasOwnProperty(key)) - this._textureColorsCache[key] = cc.generateTextureCacheForColor(texture); - return this._textureColorsCache[key]; - }, - - /** - *

Returns a Texture2D object given an PVR filename
- * If the file image was not previously loaded, it will create a new Texture2D
- * object and it will return it. Otherwise it will return a reference of a previously loaded image

- * @param {String} path - * @return {cc.Texture2D} - */ - addPVRImage:function (path) { - cc.Assert(path != null, "TextureCache: file image MUST not be null"); - - path = cc.FileUtils.getInstance().fullPathForFilename(path); - - var key = path; - - if (this._textures[key] != null) { - return this._textures[key]; - } - - // Split up directory and filename - var tex = new cc.Texture2D(); - if (tex.initWithPVRFile(key)) { - this._textures[key] = tex; - } else { - cc.log("cocos2d: Couldn't add PVRImage:" + key + " in TextureCache"); - } - return tex; - }, - /// ---- common properties end ---- - /** - *

Purges the dictionary of loaded textures.
- * Call this method if you receive the "Memory Warning"
- * In the short term: it will free some resources preventing your app from being killed
- * In the medium term: it will allocate more resources
- * In the long term: it will be the same

- * @example - * //example - * cc.TextureCache.getInstance().removeAllTextures(); - */ - removeAllTextures:function () { - this._textures = {}; - }, - - /** - * Deletes a texture from the cache given a texture - * @param {Image} texture - * @example - * //example - * cc.TextureCache.getInstance().removeTexture(texture); - */ - removeTexture:function (texture) { - if (!texture) - return; - - for (var selKey in this._textures) { - if (this._textures[selKey] == texture) { - delete(this._textures[selKey]); - } - } - }, - - /** - * Deletes a texture from the cache given a its key name - * @param {String} textureKeyName - * @example - * //example - * cc.TextureCache.getInstance().removeTexture("hello.png"); - */ - removeTextureForKey:function (textureKeyName) { - if (textureKeyName == null) - return; - var fullPath = cc.FileUtils.getInstance().fullPathForFilename(textureKeyName); - if (this._textures[fullPath]) - delete(this._textures[fullPath]); - }, - - /** - * Loading the images asynchronously - * @param {String} path - * @param {cc.Node} target - * @param {Function} selector - * @return {HTMLImageElement|cc.Texture2D} - * @example - * //example - * cc.TextureCache.getInstance().addImageAsync("hello.png", this, this.loadingCallBack); - */ - addImageAsync:function (path, target, selector) { - cc.Assert(path != null, "TextureCache: path MUST not be null"); - path = cc.FileUtils.getInstance().fullPathForFilename(path); - var texture = this._textures[path]; - var image,that; - if (texture) { - if(texture.isLoaded()){ - this._addImageAsyncCallBack(target, selector); - }else{ - that = this; - image = texture.getHtmlElementObj(); - image.addEventListener("load", function () { - texture.handleLoadedTexture(); - that._addImageAsyncCallBack(target, selector); - this.removeEventListener('load', arguments.callee, false); - }); - } - } else { - image = new Image(); - image.crossOrigin = "Anonymous"; - - that = this; - image.addEventListener("load", function () { - if (that._textures.hasOwnProperty(path)) - that._textures[path].handleLoadedTexture(); - that._addImageAsyncCallBack(target, selector); - this.removeEventListener('load', arguments.callee, false); - this.removeEventListener('error', arguments.callee, false); - }); - image.addEventListener("error", function () { - cc.Loader.getInstance().onResLoadingErr(path); - //remove from cache - if (that._textures.hasOwnProperty(path)) - delete that._textures[path]; - - this.removeEventListener('error', arguments.callee, false); - }); - image.src = path; - var texture2d = new cc.Texture2D(); - texture2d.initWithElement(image); - this._textures[path] = texture2d; - } - return this._textures[path]; - }, - - /** - *

Returns a Texture2D object given an file image
- * If the file image was not previously loaded, it will create a new Texture2D
- * object and it will return it. It will use the filename as a key.
- * Otherwise it will return a reference of a previously loaded image.
- * Supported image extensions: .png, .jpg, .gif

- * @param {String} path - * @return {HTMLImageElement|cc.Texture2D} - * @example - * //example - * cc.TextureCache.getInstance().addImage("hello.png"); - */ - addImage:function (path) { - cc.Assert(path != null, "TextureCache: path MUST not be null"); - - path = cc.FileUtils.getInstance().fullPathForFilename(path); - - var texture = this._textures[path]; - var image; - if (texture) { - if (texture.isLoaded()) { - cc.Loader.getInstance().onResLoaded(); - } else { - image = texture.getHtmlElementObj(); - image.addEventListener("load", function () { - texture.handleLoadedTexture(); - cc.Loader.getInstance().onResLoaded(); - this.removeEventListener('load', arguments.callee, false); - }); - } - } else { - image = new Image(); - image.crossOrigin = "Anonymous"; - - var that = this; - image.addEventListener("load", function () { - cc.Loader.getInstance().onResLoaded(); - if (that._textures.hasOwnProperty(path)) - that._textures[path].handleLoadedTexture(); - this.removeEventListener('load', arguments.callee, false); - this.removeEventListener('error', arguments.callee, false); - }); - image.addEventListener("error", function () { - cc.Loader.getInstance().onResLoadingErr(path); - //remove from cache - if (that._textures.hasOwnProperty(path)) - delete that._textures[path]; - - this.removeEventListener('error', arguments.callee, false); - }); - image.src = path; - var texture2d = new cc.Texture2D(); - texture2d.initWithElement(image); - this._textures[path] = texture2d; - } - - return this._textures[path]; - }, - - /** - * Cache the image data - * @param {String} path - * @param {Image|HTMLImageElement|HTMLCanvasElement} texture - */ - cacheImage:function (path, texture) { - if(texture instanceof cc.Texture2D){ - this._textures[path] = texture; - return ; - } - var texture2d = new cc.Texture2D(); - texture2d.initWithElement(texture); - texture2d.handleLoadedTexture(); - this._textures[path] = texture2d; - }, - - /** - *

Returns a Texture2D object given an UIImage image
- * If the image was not previously loaded, it will create a new Texture2D object and it will return it.
- * Otherwise it will return a reference of a previously loaded image
- * The "key" parameter will be used as the "key" for the cache.
- * If "key" is null, then a new texture will be created each time.

- * @param {HTMLImageElement|HTMLCanvasElement} image - * @param {String} key - * @return {HTMLImageElement|HTMLCanvasElement} - */ - addUIImage:function (image, key) { - cc.Assert(image != null, "TextureCache: image MUST not be nulll"); - - if (key) { - if (this._textures.hasOwnProperty(key) && this._textures[key]) - return this._textures[key]; - } - - // prevents overloading the autorelease pool - var texture = new cc.Texture2D(); - texture.initWithImage(image); - if ((key != null) && (texture != null)) - this._textures[key] = texture; - else - cc.log("cocos2d: Couldn't add UIImage in TextureCache"); - return texture; - }, - - /** - *

Output to cc.log the current contents of this TextureCache
- * This will attempt to calculate the size of each texture, and the total texture memory in use.

- */ - dumpCachedTextureInfo:function () { - var count = 0; - var totalBytes = 0; - for (var key in this._textures) { - var selTexture = this._textures[key]; - count++; - if (selTexture.getHtmlElementObj() instanceof HTMLImageElement) - cc.log("cocos2d: '" + key + "' id=" + selTexture.getHtmlElementObj().src + " " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); - else { - cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); - totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; - } - } - - for (key in this._textureColorsCache) { - var selCanvas = this._textureColorsCache[key]; - count++; - cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.getPixelsWide() + " x " + selCanvas.getPixelsHigh()); - totalBytes += selCanvas.getPixelsWide() * selCanvas.getPixelsHigh() * 4; - } - - cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for " - + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)"); - } -}); - -/** - * Implementation TextureCache (WebGL implement) - * @class - * @extends cc.Class - */ -cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ - /// ---- common properties start ---- - _textures:null, - _textureColorsCache:null, - _textureKeySeq:1000, + _textureKeySeq:null, _rendererInitialized:false, _loadedTexturesBefore:null, @@ -470,19 +83,21 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ /** * Constructor */ - ctor:function () { + ctor: function () { cc.Assert(cc.g_sharedTextureCache == null, "Attempted to allocate a second instance of a singleton."); this._textureKeySeq += (0 | Math.random() * 1000); this._textures = {}; this._textureColorsCache = {}; - this._loadedTexturesBefore = {}; - this._loadingTexturesBefore = {}; + if(cc.renderContextType === cc.WEBGL){ + this._loadedTexturesBefore = {}; + this._loadingTexturesBefore = {}; + } }, _addImageAsyncCallBack:function (target, selector) { - if (target && (typeof(selector) == "string")) { + if (target && (typeof(selector) === "string")) { target[selector](); - } else if (target && (typeof(selector) == "function")) { + } else if (target && (typeof(selector) === "function")) { selector.call(target); } }, @@ -492,19 +107,14 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ var selPath; //init texture from _loadedTexturesBefore - for(selPath in this._loadedTexturesBefore){ - var htmlImage = this._loadedTexturesBefore[selPath]; + var locLoadedTexturesBefore = this._loadedTexturesBefore, locTextures = this._textures; + for(selPath in locLoadedTexturesBefore){ + var htmlImage = locLoadedTexturesBefore[selPath]; var texture2d = new cc.Texture2D(); texture2d.initWithElement(htmlImage); texture2d.handleLoadedTexture(); - this._textures[selPath] = texture2d; - } - this._loadedTexturesBefore = {}; - - //init texture from _loadingTexturesBefore - for(selPath in this._loadedTexturesBefore){ - this.addImage(selPath); + locTextures[selPath] = texture2d; } this._loadedTexturesBefore = {}; }, @@ -523,6 +133,7 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Assert(0, "TextureCache:addPVRTCImage does not support on HTML5"); }, + /** *

* Returns a Texture2D object given an ETC filename
@@ -548,7 +159,7 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ /** * Returns an already created texture. Returns null if the texture doesn't exist. * @param {String} textureKeyName - * @return {HTMLImageElement|cc.Texture2D|Null} + * @return {cc.Texture2D|Null} * @example * //example * var key = cc.TextureCache.getInstance().textureForKey("hello.png"); @@ -629,7 +240,6 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ } return tex; }, - /// ---- common properties end ---- /** *

Purges the dictionary of loaded textures.
@@ -642,9 +252,10 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ * cc.TextureCache.getInstance().removeAllTextures(); */ removeAllTextures:function () { - for (var selKey in this._textures) { - if(this._textures[selKey]) - this._textures[selKey].releaseTexture(); + var locTextures = this._textures; + for (var selKey in locTextures) { + if(locTextures[selKey]) + locTextures[selKey].releaseTexture(); } this._textures = {}; }, @@ -660,10 +271,11 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ if (!texture) return; - for (var selKey in this._textures) { - if (this._textures[selKey] == texture) { - this._textures[selKey].releaseTexture(); - delete(this._textures[selKey]); + var locTextures = this._textures; + for (var selKey in locTextures) { + if (locTextures[selKey] == texture) { + locTextures[selKey].releaseTexture(); + delete(locTextures[selKey]); } } }, @@ -679,10 +291,8 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ if (textureKeyName == null) return; var fullPath = cc.FileUtils.getInstance().fullPathForFilename(textureKeyName); - if (this._textures[fullPath]){ - this._textures[fullPath].releaseTexture(); + if (this._textures[fullPath]) delete(this._textures[fullPath]); - } }, /** @@ -690,7 +300,7 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ * @param {String} path * @param {cc.Node} target * @param {Function} selector - * @return {HTMLImageElement|cc.Texture2D} + * @return {cc.Texture2D} * @example * //example * cc.TextureCache.getInstance().addImageAsync("hello.png", this, this.loadingCallBack); @@ -699,17 +309,16 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Assert(path != null, "TextureCache: path MUST not be null"); path = cc.FileUtils.getInstance().fullPathForFilename(path); var texture = this._textures[path]; - var image; + var image,that; if (texture) { if(texture.isLoaded()){ this._addImageAsyncCallBack(target, selector); }else{ - var that = this; + that = this; image = texture.getHtmlElementObj(); image.addEventListener("load", function () { texture.handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); - this.removeEventListener('load', arguments.callee, false); }); } @@ -717,12 +326,11 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ image = new Image(); image.crossOrigin = "Anonymous"; - var that = this; + that = this; image.addEventListener("load", function () { if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); that._addImageAsyncCallBack(target, selector); - this.removeEventListener('load', arguments.callee, false); this.removeEventListener('error', arguments.callee, false); }); @@ -771,15 +379,17 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ * Otherwise it will return a reference of a previously loaded image.
* Supported image extensions: .png, .jpg, .gif

* @param {String} path - * @return {HTMLImageElement|cc.Texture2D} + * @return {cc.Texture2D} * @example * //example * cc.TextureCache.getInstance().addImage("hello.png"); */ addImage:function (path) { cc.Assert(path != null, "TextureCache: path MUST not be null"); - if (!this._rendererInitialized) - return this._addImageBeforeRenderer(path); + if(cc.renderContextType === cc.WEBGL){ + if (!this._rendererInitialized) + return this._addImageBeforeRenderer(path); + } path = cc.FileUtils.getInstance().fullPathForFilename(path); @@ -793,7 +403,6 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ image.addEventListener("load", function () { texture.handleLoadedTexture(); cc.Loader.getInstance().onResLoaded(); - this.removeEventListener('load', arguments.callee, false); }); } @@ -806,7 +415,6 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ cc.Loader.getInstance().onResLoaded(); if (that._textures.hasOwnProperty(path)) that._textures[path].handleLoadedTexture(); - this.removeEventListener('load', arguments.callee, false); this.removeEventListener('error', arguments.callee, false); }); @@ -819,7 +427,6 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ this.removeEventListener('error', arguments.callee, false); }); image.src = path; - var texture2d = new cc.Texture2D(); texture2d.initWithElement(image); this._textures[path] = texture2d; @@ -850,7 +457,7 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ * Otherwise it will return a reference of a previously loaded image
* The "key" parameter will be used as the "key" for the cache.
* If "key" is null, then a new texture will be created each time.

- * @param {cc.Image} image + * @param {HTMLImageElement|HTMLCanvasElement} image * @param {String} key * @return {cc.Texture2D} */ @@ -878,23 +485,32 @@ cc.TextureCacheWebGL = cc.Class.extend(/** @lends cc.TextureCacheWebGL# */{ */ dumpCachedTextureInfo:function () { var count = 0; - var totalBytes = 0; - for (var key in this._textures) { - var tex = this._textures[key]; - var bpp = tex.bitsPerPixelForFormat(); - // Each texture takes up width * height * bytesPerPixel bytes. - var bytes = tex.getPixelsWide() * tex.getPixelsHigh() * bpp / 8; - totalBytes += bytes; + var totalBytes = 0, locTextures = this._textures; + + for (var key in locTextures) { + var selTexture = locTextures[key]; count++; - cc.log("cocos2d: Texture URL=" + tex._htmlElementObj.src + " " + tex.getPixelsWide() + " x " + tex.getPixelsHigh() + " @ " + bpp + " bpp => " + bytes / 1024 + " KB"); + if (selTexture.getHtmlElementObj() instanceof HTMLImageElement) + cc.log("cocos2d: '" + key + "' id=" + selTexture.getHtmlElementObj().src + " " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); + else { + cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); + totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; + } + } + + var locTextureColorsCache = this._textureColorsCache; + for (key in locTextureColorsCache) { + var selCanvas = locTextureColorsCache[key]; + count++; + cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.getPixelsWide() + " x " + selCanvas.getPixelsHigh()); + totalBytes += selCanvas.getPixelsWide() * selCanvas.getPixelsHigh() * 4; } - cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, for " + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)"); + cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for " + + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)"); } }); -cc.TextureCache = cc.Browser.supportWebGL ? cc.TextureCacheWebGL : cc.TextureCacheCanvas; - /** * Return ths shared instance of the cache * @return {cc.TextureCache} From 074963d10d6f35bea92748224851b07b4c50fab8 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 9 Sep 2013 11:29:26 +0800 Subject: [PATCH 088/141] Closed #2226: remove an unused variable "_opacity" from cc.LayerColor --- cocos2d/layers_scenes_transitions_nodes/CCLayer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 1332cc018f..c5d233aa90 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -795,7 +795,6 @@ cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{ cc.LayerRGBA.prototype.ctor.call(this); this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST); this._color = new cc.Color4B(0, 0, 0, 0); - this._opacity = 255; }, _ctorForWebGL: function () { From dd5a746419fb20038b87ad537dd1946d6365f166 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 9 Sep 2013 15:28:54 +0800 Subject: [PATCH 089/141] Closed #2226: modify some comments --- cocos2d/base_nodes/CCNode.js | 4 ++-- cocos2d/layers_scenes_transitions_nodes/CCLayer.js | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index 12f2062c8d..f3e3ea2d07 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -974,8 +974,8 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ *

If the child is added to a 'running' node, then 'onEnter' and 'onEnterTransitionDidFinish' will be called immediately.

* * @param {cc.Node} child A child node - * @param {Number} zOrder Z order for drawing priority. Please refer to setZOrder(int) - * @param {Number} tag A interger to identify the node easily. Please refer to setTag(int) + * @param {Number} [zOrder=] Z order for drawing priority. Please refer to setZOrder(int) + * @param {Number} [tag=] A interger to identify the node easily. Please refer to setTag(int) */ addChild:function (child, zOrder, tag) { if (child === this) { diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index c5d233aa90..627879292b 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -523,7 +523,7 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ /** * Call back when a key is pressed down - * @param {Integer} keyCode + * @param {Number} keyCode * @example * // example * if(keyCode == cc.KEY.w){} @@ -533,7 +533,7 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ /** * Call back when a key is released - * @param {Integer} keyCode + * @param {Number} keyCode * @example * // example * if(keyCode == cc.KEY.w){} @@ -833,9 +833,9 @@ cc.LayerColor = cc.LayerRGBA.extend(/** @lends cc.LayerColor# */{ }, /** - * @param {cc.Color4B} color - * @param {Number} width - * @param {Number} height + * @param {cc.Color4B} [color=] + * @param {Number} [width=] + * @param {Number} [height=] * @return {Boolean} */ init:function (color, width, height) { From 10fe6a343dacdaff8e37c537d13ba408ff078f7a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 9 Sep 2013 18:24:22 +0800 Subject: [PATCH 090/141] issue #2772 add getPositionX and getPositionY for PhysicsSprite --- cocos2d/physics_nodes/CCPhysicsSprite.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js index 10873ea427..ed07989e73 100644 --- a/cocos2d/physics_nodes/CCPhysicsSprite.js +++ b/cocos2d/physics_nodes/CCPhysicsSprite.js @@ -101,12 +101,23 @@ getBody:function () { return this._body; }, + getPositionX:function(){ + return this._body.p.x; + }, + getPositionY:function(){ + return this._body.p.y; + }, getPosition:function () { return {x:this._body.p.x, y:this._body.p.y}; }, - setPosition:function (pos) { - this._body.p.x = pos.x; - this._body.p.y = pos.y; + setPosition:function (newPosOrxValue, yValue) { + if(arguments.length==2){ + this._body.p.x = newPosOrxValue; + this._body.p.y = yValue; + }else{ + this._body.p.x = newPosOrxValue.x; + this._body.p.y = newPosOrxValue.y; + } //this._syncPosition(); }, _syncPosition:function () { From b732d7a6c7f3c4ced709b5333f124e915fdc0c96 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 9 Sep 2013 18:28:28 +0800 Subject: [PATCH 091/141] issue #2772 remove CCPhysicsWorld.js --- HelloHTML5World/build.xml | 1 - cocos2d/build.xml | 1 - cocos2d/platform/jsloader.js | 1 - .../CCArmature/physics/CCPhysicsWorld.js | 35 ------------------- template/build.xml | 1 - 5 files changed, 39 deletions(-) delete mode 100644 extensions/CCArmature/physics/CCPhysicsWorld.js diff --git a/HelloHTML5World/build.xml b/HelloHTML5World/build.xml index e79a277aaf..ae0daa9a7f 100644 --- a/HelloHTML5World/build.xml +++ b/HelloHTML5World/build.xml @@ -176,7 +176,6 @@ - diff --git a/cocos2d/build.xml b/cocos2d/build.xml index c3d1ade5c3..4415b4241e 100644 --- a/cocos2d/build.xml +++ b/cocos2d/build.xml @@ -177,7 +177,6 @@ - diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index df804a8cd5..752e5c92d9 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -192,7 +192,6 @@ '../extensions/CCArmature/animation/CCArmatureAnimation.js', '../extensions/CCArmature/animation/CCTween.js', '../extensions/CCArmature/physics/CCColliderDetector.js', - '../extensions/CCArmature/physics/CCPhysicsWorld.js', '../extensions/CCArmature/CCArmature.js', '../extensions/CCArmature/CCBone.js' diff --git a/extensions/CCArmature/physics/CCPhysicsWorld.js b/extensions/CCArmature/physics/CCPhysicsWorld.js deleted file mode 100644 index ecccaf8cb7..0000000000 --- a/extensions/CCArmature/physics/CCPhysicsWorld.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Created with JetBrains WebStorm. - * User: Administrator - * Date: 13-6-20 - * Time: 下午3:54 - * To change this template use File | Settings | File Templates. - */ - -cc.PhysicsWorld = cc.Class.extend({ - BoneColliderSignal:[], - _noGravityWorld:null, - _contactListener:null, - _debugDraw:null, - ctor:function () { - - }, - initNoGravityWorld:function () { - - }, - update:function () { - - }, - drawDebug:function () { - - }, - getNoGravityWorld:function () { - - } -}); -cc.PhysicsWorld.getInstance = function () { - -}; -cc.PhysicsWorld.purge = function () { - -}; \ No newline at end of file diff --git a/template/build.xml b/template/build.xml index f230d2f633..48846e4c02 100644 --- a/template/build.xml +++ b/template/build.xml @@ -176,7 +176,6 @@ - From d857146d1550d8955e1a04705a44fc43a91cc5bb Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 9 Sep 2013 18:33:14 +0800 Subject: [PATCH 092/141] issue #2772 add collide for Armature --- extensions/CCArmature/CCArmature.js | 34 +++- .../CCArmature/display/CCDisplayFactory.js | 19 +- .../CCArmature/display/CCDisplayManager.js | 8 +- .../CCArmature/physics/CCColliderDetector.js | 182 +++++++++++++++--- 4 files changed, 206 insertions(+), 37 deletions(-) diff --git a/extensions/CCArmature/CCArmature.js b/extensions/CCArmature/CCArmature.js index a803bb8a3d..73d40c74b8 100644 --- a/extensions/CCArmature/CCArmature.js +++ b/extensions/CCArmature/CCArmature.js @@ -40,6 +40,7 @@ cc.Armature = cc.NodeRGBA.extend({ _offsetPoint:cc.p(0, 0), _version:0, _armatureTransformDirty:false, + _body:null, ctor:function () { cc.NodeRGBA.prototype.ctor.call(this); this._animation = null; @@ -52,8 +53,9 @@ cc.Armature = cc.NodeRGBA.extend({ this._topBoneList = []; this._armatureIndexDic = {}; this._offsetPoint = cc.p(0, 0); - this._version = 0, + this._version = 0; this._armatureTransformDirty = false; + this._body = null; }, /** @@ -570,7 +572,37 @@ cc.Armature = cc.NodeRGBA.extend({ */ getArmatureTransformDirty:function () { return this._armatureTransformDirty; + }, + getBody:function(){ + return this._body; + }, + + setBody:function(body){ + if (this._body == body) + return; + + this._body = body; + this._body.data = this; + var child,displayObject; + for (var i = 0; i < this._children.length; i++) { + child = this._children[i]; + if (child instanceof cc.Bone) { + var displayList = child.getDisplayManager().getDecorativeDisplayList(); + for (var j = 0; j < displayList.length; j++) { + displayObject = displayList[j]; + var detector = displayObject.getColliderDetector(); + if (detector) + detector.setBody(this._body); + } + } + } + }, + getShapeList:function(){ + if(this._body) + return this._body.shapeList; + return []; } + }); /** diff --git a/extensions/CCArmature/display/CCDisplayFactory.js b/extensions/CCArmature/display/CCDisplayFactory.js index 3292442301..cfacad1204 100644 --- a/extensions/CCArmature/display/CCDisplayFactory.js +++ b/extensions/CCArmature/display/CCDisplayFactory.js @@ -59,11 +59,17 @@ cc.DisplayFactory.updateDisplay = function (bone, decoDisplay, dt, dirty) { return; } - if (ENABLE_PHYSICS_DETECT) { + if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { if (dirty) { var detector = decoDisplay.getColliderDetector(); - if (detector) { - var t = cc.AffineTransformConcat(bone.nodeToArmatureTransform(), bone.getArmature().nodeToWorldTransform()); + if (detector&&detector.getBody()) { + var node = decoDisplay.getDisplay(); + var displayTransform = node.nodeToParentTransform(); + var anchorPoint = node.getAnchorPointInPoints(); + anchorPoint = cc.PointApplyAffineTransform(anchorPoint, displayTransform); + displayTransform.tx = anchorPoint.x; + displayTransform.ty = anchorPoint.y; + var t = cc.AffineTransformConcat(displayTransform, bone.getArmature().nodeToParentTransform()); detector.updateTransform(t); } } @@ -131,6 +137,13 @@ cc.DisplayFactory.initSpriteDisplay = function(bone, decoDisplay, displayName, s //! Init display anchorPoint, every Texture have a anchor point skin.setAnchorPoint(cc.p(textureData.pivotX, textureData.pivotY)); } + if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { + if (textureData && textureData.contourDataList.length > 0) { + var colliderDetector = cc.ColliderDetector.create(bone); + colliderDetector.addContourDataList(textureData.contourDataList); + decoDisplay.setColliderDetector(colliderDetector); + } + } }, cc.DisplayFactory.updateSpriteDisplay = function (bone, skin, dt, dirty) { diff --git a/extensions/CCArmature/display/CCDisplayManager.js b/extensions/CCArmature/display/CCDisplayManager.js index d1b35b9793..cf265f3323 100644 --- a/extensions/CCArmature/display/CCDisplayManager.js +++ b/extensions/CCArmature/display/CCDisplayManager.js @@ -145,7 +145,7 @@ cc.DisplayManager = cc.Class.extend({ }, setCurrentDecorativeDisplay:function (decoDisplay) { - if (ENABLE_PHYSICS_DETECT) { + if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { if (this._currentDecoDisplay && this._currentDecoDisplay.getColliderDetector()) { this._currentDecoDisplay.getColliderDetector().setActive(false); } @@ -153,7 +153,7 @@ cc.DisplayManager = cc.Class.extend({ this._currentDecoDisplay = decoDisplay; - if (ENABLE_PHYSICS_DETECT) { + if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { if (this._currentDecoDisplay && this._currentDecoDisplay.getColliderDetector()) { this._currentDecoDisplay.getColliderDetector().setActive(true); } @@ -178,8 +178,8 @@ cc.DisplayManager = cc.Class.extend({ this._displayRenderNode.resetSystem(); } if (this._displayRenderNode.RGBAProtocol) { - this._displayRenderNode.setColor(this._bone.getColor()); - this._displayRenderNode.setOpacity(this._bone.getOpacity()); + //this._displayRenderNode.setColor(this._bone.getColor()); + //this._displayRenderNode.setOpacity(this._bone.getOpacity()); } this._displayRenderNode.retain(); //todo diff --git a/extensions/CCArmature/physics/CCColliderDetector.js b/extensions/CCArmature/physics/CCColliderDetector.js index 25a4995d44..f40e53d269 100644 --- a/extensions/CCArmature/physics/CCColliderDetector.js +++ b/extensions/CCArmature/physics/CCColliderDetector.js @@ -1,46 +1,170 @@ -/** - * Created with JetBrains WebStorm. - * User: Administrator - * Date: 13-6-20 - * Time: 下午3:57 - * To change this template use File | Settings | File Templates. - */ -cc.ColliderBody = cc.Class.extend({ - _b2b:null, - _contourData:null, - ctor:function () { +/**************************************************************************** + Copyright (c) 2010-2012 cocos2d-x.org - }, - getB2Body:function () { + http://www.cocos2d-x.org - }, - getContourData:function () { + 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.ColliderBody = cc.Class.extend({ + _shape: null, + _contourData: null, + ctor: function (contourData) { + this._contourData = contourData; + }, + getContourData: function () { + return this._contourData; + }, + setContourData: function (contourData) { + this._contourData = contourData; + }, + getShape: function () { + return this._shape; + }, + setShape: function (shage) { + this._shape = shage; } }); cc.ColliderDetector = cc.Class.extend({ - _colliderBodyList:null, - _bone:null, - ctor:function () { - + _colliderBodyList: null, + _bone: null, + _body: null, + _active: false, + ctor: function () { + this._colliderBodyList = []; + }, + init: function (bone) { + this._colliderBodyList = []; + if (bone) + this._bone = bone; + return true; + }, + addContourData: function (contourData) { + var colliderBody = new cc.ColliderBody(contourData); + this._colliderBodyList.push(colliderBody); + }, + addContourDataList: function (contourDataList) { + for (var i = 0; i < contourDataList.length; i++) { + this.addContourData(contourDataList[i]); + } + }, + removeContourData: function (contourData) { + //todo + //cc.ArrayRemoveObject(this._colliderBodyList,contourData); }, - init:function (bone) { + removeAll: function () { + this._colliderBodyList = []; }, - addContourData:function (contourData) { + + setColliderFilter: function (filter) { + }, - addContourDataList:function (contourDataList) { + setActive: function (active) { + if (this._active == active) + return; + this._active = active; + if (this._body) { + var colliderBody = null; + if (this._active) { + for (var i = 0; i < this._colliderBodyList.length; i++) { + colliderBody = this._colliderBodyList[i]; + var shape = colliderBody.getShape(); + this._body.space.addShape(shape); + } + } + else { + for (var i = 0; i < this._colliderBodyList.length; i++) { + colliderBody = this._colliderBodyList[i]; + var shape = colliderBody.getShape(); + this._body.space.removeShape(shape); + } + } + } }, - removeContourData:function (contourData) { + getActive: function () { + return this._active; }, - removeAll:function () { + getColliderBodyList: function () { + return this._colliderBodyList; }, - updateTransform:function (t) { + helpPoint: cc.p(0, 0), + updateTransform: function (t) { + if (!this._active) + return; + + var colliderBody = null; + if(!cc.Browser.supportWebGL){ + t.b*=-1; + t.c*=-1; + } + for (var i = 0; i < this._colliderBodyList.length; i++) { + colliderBody = this._colliderBodyList[i]; + var contourData = colliderBody.getContourData(); + var shape = null; + if (this._body) + shape = colliderBody.getShape(); + this._body.p.x = t.tx; + this._body.p.y = t.ty; + this._body.p.a = t.a; + var vs = contourData.vertexList; + for (var i = 0; i < vs.length; i++) { + this.helpPoint.x = vs[i].x; + this.helpPoint.y = vs[i].y; + this.helpPoint = cc.PointApplyAffineTransform(this.helpPoint, t); + if (shape) { + var v = new cp.Vect(0, 0); + v.x = this.helpPoint.x; + v.y = this.helpPoint.y; + shape.verts[i * 2] = this.helpPoint.x - t.tx; + shape.verts[i * 2 + 1] = this.helpPoint.y - t.ty; + } + } + } }, - setColliderFilter:function (filter) { + getBody: function () { + return this._body; }, - setActive:function (active) { + setBody: function (body) { + this._body = body; + var colliderBody; + for (var i = 0; i < this._colliderBodyList.length; i++) { + colliderBody = this._colliderBodyList[i]; + var contourData = colliderBody.getContourData(); + var verts = []; + var vs = contourData.vertexList; + for (var i = 0; i < vs.length; i++) { + var v = vs[i]; + verts.push(v.x); + verts.push(v.y); + } + var shape = new cp.PolyShape(this._body, verts, cp.vzero); + shape.sensor = true; + shape.data = this._bone; + this._body.space.addShape(shape); + colliderBody.setShape(shape); + } } }); -cc.ColliderDetector.create = function () { - +cc.ColliderDetector.create = function (bone) { + var colliderDetector = new cc.ColliderDetector(); + if (colliderDetector && colliderDetector.init(bone)) { + return colliderDetector; + } + return null; }; \ No newline at end of file From baf30ef927af3cc36ec0e4b087efe299085f0958 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 9 Sep 2013 18:35:46 +0800 Subject: [PATCH 093/141] issue #2772 add async load for Armature --- extensions/CCArmature/datas/CCDatas.js | 3 +- .../CCArmature/utils/CCArmatureDefine.js | 9 +- .../CCArmature/utils/CCDataReaderHelper.js | 105 ++++++++++++++---- .../CCArmature/utils/CSArmatureDataManager.js | 52 +++++++-- 4 files changed, 133 insertions(+), 36 deletions(-) diff --git a/extensions/CCArmature/datas/CCDatas.js b/extensions/CCArmature/datas/CCDatas.js index 3d15c6b64d..fd4c86b367 100644 --- a/extensions/CCArmature/datas/CCDatas.js +++ b/extensions/CCArmature/datas/CCDatas.js @@ -161,7 +161,7 @@ cc.SpriteDisplayData = cc.DisplayData.extend({ skinData:null, ctor:function () { this.displayName = ""; - this.skinData = null; + this.skinData = new cc.BaseData(); this.displayType = CC_DISPLAY_SPRITE; }, setParam:function (displayName) { @@ -343,7 +343,6 @@ cc.MovementBoneData = cc.Class.extend({ }, addFrameData:function (frameData) { this.frameList.push(frameData); - this.duration += frameData.duration; }, getFrameData:function (index) { return this.frameList[index]; diff --git a/extensions/CCArmature/utils/CCArmatureDefine.js b/extensions/CCArmature/utils/CCArmatureDefine.js index fbe6d2e4ed..ce00a1f6e1 100644 --- a/extensions/CCArmature/utils/CCArmatureDefine.js +++ b/extensions/CCArmature/utils/CCArmatureDefine.js @@ -26,4 +26,11 @@ cc.MAX_VERTEXZ_VALUE = 5000000.0; cc.ARMATURE_MAX_CHILD = 50.0; cc.ARMATURE_MAX_ZORDER = 100; cc.ARMATURE_MAX_COUNT = ((cc.MAX_VERTEXZ_VALUE) / (cc.ARMATURE_MAX_CHILD) / cc.ARMATURE_MAX_ZORDER); -cc.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false; \ No newline at end of file +cc.AUTO_ADD_SPRITE_FRAME_NAME_PREFIX = false; +cc.ENABLE_PHYSICS_CHIPMUNK_DETECT = true; + +cc.armatureVersion = function(){ + return "0.4.0.0"; +}; + +cc.RESOURCE_TYPE.TEXT.push("ExportJson"); \ No newline at end of file diff --git a/extensions/CCArmature/utils/CCDataReaderHelper.js b/extensions/CCArmature/utils/CCDataReaderHelper.js index dcb074ce3a..25480e559d 100644 --- a/extensions/CCArmature/utils/CCDataReaderHelper.js +++ b/extensions/CCArmature/utils/CCDataReaderHelper.js @@ -131,6 +131,8 @@ cc.DataReaderHelper._textureDatas = {}; cc.DataReaderHelper._json = {}; cc.DataReaderHelper._positionReadScale = 1; cc.DataReaderHelper._basefilePath = ""; +cc.DataReaderHelper._asyncRefCount = 0; +cc.DataReaderHelper._asyncRefTotalCount = 0; cc.DataReaderHelper.setPositionReadScale = function (scale) { this._positionReadScale = scale; @@ -144,25 +146,69 @@ cc.DataReaderHelper.clear = function () { this._configFileList = []; }; -cc.DataReaderHelper.addDataFromFile = function (filePath) { +cc.DataReaderHelper.addDataFromFile = function (filePath,isLoadSpriteFrame) { var fileUtils = cc.FileUtils.getInstance(); - filePath = fileUtils.fullPathForFilename(filePath); + var fullFilePath = fileUtils.fullPathForFilename(filePath); - if (cc.ArrayAppendObject(this._configFileList, filePath)) { + if (cc.ArrayAppendObject(this._configFileList, fullFilePath)) { return; } - this._configFileList.push(filePath); + this._configFileList.push(fullFilePath); - var startPos = filePath.lastIndexOf("."); - var str = filePath.substring(startPos, filePath.length); + this._initBaseFilePath(filePath); + + var startPos = fullFilePath.lastIndexOf("."); + var str = fullFilePath.substring(startPos, fullFilePath.length); if (str == ".xml") { - this.addDataFromXML(filePath); + this.addDataFromXML(fullFilePath); } else if (str == ".json" || str == ".ExportJson") { - this.addDataFromJson(filePath); + this.addDataFromJson(fullFilePath,isLoadSpriteFrame); + } +}; + +cc.DataReaderHelper.addDataFromFileAsync = function (filePath,target,selector,isLoadSpriteFrame) { + var fileUtils = cc.FileUtils.getInstance(); + var fullFilePath = fileUtils.fullPathForFilename(filePath); + + if (cc.ArrayAppendObject(this._configFileList, fullFilePath)) { + if (target && selector) { + if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0) + this._asyncCallBack(target, selector, 1); + else + this._asyncCallBack(target, selector, (this._asyncRefTotalCount - this._asyncRefCount) / this._asyncRefTotalCount); + } + return; + } + this._asyncRefTotalCount++; + this._asyncRefCount++; + var self = this; + var fun = function () { + self.addDataFromFile(filePath,isLoadSpriteFrame); + self._asyncRefCount--; + self._asyncCallBack(target, selector, (self._asyncRefTotalCount - self._asyncRefCount) / self._asyncRefTotalCount); + }; + cc.Director.getInstance().getScheduler().scheduleCallbackForTarget(this, fun, 0.1, false); +}; + +cc.DataReaderHelper._asyncCallBack=function (target, selector,percent) { + if (target && (typeof(selector) == "string")) { + target[selector](percent); + } else if (target && (typeof(selector) == "function")) { + selector.call(target,percent); } }; +cc.DataReaderHelper._initBaseFilePath = function(filePath){ + //! find the base file path + this._basefilePath = filePath; + var pos = this._basefilePath.lastIndexOf("/"); + if(pos>-1) + this._basefilePath = this._basefilePath.substr(0, pos + 1); + else + this._basefilePath = ""; +}; + cc.DataReaderHelper.addDataFromXML = function (xml) { /* * Need to get the full path of the xml file, or the Tiny XML can't find the xml at IOS @@ -555,33 +601,46 @@ cc.DataReaderHelper.decodeContour = function (contourXML) { }; -cc.DataReaderHelper.addDataFromJson = function (filePath) { +cc.DataReaderHelper.addDataFromJson = function (filePath,isLoadSpriteFrame) { var fileContent = cc.FileUtils.getInstance().getTextFileData(filePath); - this.addDataFromJsonCache(fileContent); + this.addDataFromJsonCache(fileContent,isLoadSpriteFrame); }; -cc.DataReaderHelper.addDataFromJsonCache = function (content) { +cc.DataReaderHelper.addDataFromJsonCache = function (content,isLoadSpriteFrame) { var dic = JSON.parse(content); - var armatureData = dic[cc.CONST_ARMATURE_DATA] || []; - for (var i = 0; i < armatureData.length; i++) { - var armatureDic = armatureData[i]; - var armatureData = this.decodeArmatureFromJSON(armatureDic); + var armatureDataArr = dic[cc.CONST_ARMATURE_DATA] || []; + var armatureData; + for (var i = 0; i < armatureDataArr.length; i++) { + armatureData = this.decodeArmatureFromJSON(armatureDataArr[i]); cc.ArmatureDataManager.getInstance().addArmatureData(armatureData.name, armatureData); } - var animationData = dic[cc.CONST_ANIMATION_DATA] || []; - for (var i = 0; i < animationData.length; i++) { - var animationDic = animationData[i]; - var animationData = this.decodeAnimationFromJson(animationDic); + var animationDataArr = dic[cc.CONST_ANIMATION_DATA] || []; + var animationData; + for (var i = 0; i < animationDataArr.length; i++) { + animationData = this.decodeAnimationFromJson(animationDataArr[i]); cc.ArmatureDataManager.getInstance().addAnimationData(animationData.name, animationData); } - var textData = dic[cc.CONST_TEXTURE_DATA] || []; - for (var i = 0; i < textData.length; i++) { - var textureDic = textData[i]; - var textureData = this.decodeTextureFromJson(textureDic); + var textureDataArr = dic[cc.CONST_TEXTURE_DATA] || []; + var textureData; + for (var i = 0; i < textureDataArr.length; i++) { + textureData = this.decodeTextureFromJson(textureDataArr[i]); cc.ArmatureDataManager.getInstance().addTextureData(textureData.name, textureData); } + if (isLoadSpriteFrame) { + var configFiles = dic[cc.CONST_CONFIG_FILE_PATH] || []; + var locFilePath, locPos, locPlistPath, locImagePath; + for (var i = 0; i < configFiles.length; i++) { + locFilePath = configFiles[i]; + locPos = locFilePath.lastIndexOf("."); + locFilePath = locFilePath.substring(0, locPos); + locPlistPath = this._basefilePath + locFilePath + ".plist"; + locImagePath = this._basefilePath + locFilePath + ".png"; + cc.ArmatureDataManager.getInstance().addSpriteFrameFromFile(locPlistPath, locImagePath); + } + } + armatureData = null; animationData = null; textData = null; diff --git a/extensions/CCArmature/utils/CSArmatureDataManager.js b/extensions/CCArmature/utils/CSArmatureDataManager.js index 6d4778e4ef..f26e6793b5 100644 --- a/extensions/CCArmature/utils/CSArmatureDataManager.js +++ b/extensions/CCArmature/utils/CSArmatureDataManager.js @@ -31,12 +31,10 @@ cc.ArmatureDataManager = cc.Class.extend({ _animationDatas:null, _armarureDatas:null, _textureDatas:null, - _autoLoadSpriteFile:false, ctor:function () { this._animationDatas = {}; this._armarureDatas = {}; this._textureDatas = {}; - this._autoLoadSpriteFile = false; }, init:function () { @@ -171,9 +169,48 @@ cc.ArmatureDataManager = cc.Class.extend({ * @param {String} plistPath * @param {String} configFilePath */ - addArmatureFileInfo:function (imagePath, plistPath, configFilePath) { - cc.DataReaderHelper.addDataFromFile(configFilePath); - this.addSpriteFrameFromFile(plistPath, imagePath); + addArmatureFileInfo:function (/*imagePath,plistPath,configFilePath*/) { + var imagePath,plistPath,configFilePath; + var isLoadSpriteFrame = false; + if (arguments.length == 1) { + configFilePath = arguments[0]; + isLoadSpriteFrame = true; + } else if (arguments.length == 3){ + imagePath = arguments[0]; + plistPath = arguments[1]; + configFilePath = arguments[2]; + this.addSpriteFrameFromFile(plistPath, imagePath); + } + cc.DataReaderHelper.addDataFromFile(configFilePath,isLoadSpriteFrame); + }, + + /** + * Add ArmatureFileInfo, it is managed by CCArmatureDataManager. + * @param {String} imagePath + * @param {String} plistPath + * @param {String} configFilePath + * @param {Object} target + * @param {Function} configFilePath + */ + addArmatureFileInfoAsync:function (/*imagePath, plistPath, configFilePath,target,selector*/) { + var imagePath, plistPath, configFilePath,target,selector; + var isLoadSpriteFrame = false; + if (arguments.length == 3) { + configFilePath = arguments[0]; + target = arguments[1]; + selector = arguments[2]; + isLoadSpriteFrame = true; + } else if (arguments.length == 5){ + imagePath = arguments[0]; + plistPath = arguments[1]; + configFilePath = arguments[2]; + target = arguments[3]; + selector = arguments[4]; + this.addSpriteFrameFromFile(plistPath, imagePath); + } + + cc.DataReaderHelper.addDataFromFileAsync(configFilePath,target,selector,isLoadSpriteFrame); + }, /** @@ -185,10 +222,6 @@ cc.ArmatureDataManager = cc.Class.extend({ cc.SpriteFrameCacheHelper.getInstance().addSpriteFrameFromFile(plistPath, imagePath); }, - isAutoLoadSpriteFile:function(){ - return this._autoLoadSpriteFile; - }, - removeAll:function () { this._animationDatas = null; this._armarureDatas = null; @@ -207,6 +240,5 @@ cc.ArmatureDataManager.getInstance = function () { }; cc.ArmatureDataManager.purge = function () { cc.SpriteFrameCacheHelper.purge(); - cc.PhysicsWorld.purge(); this._instance = null; }; \ No newline at end of file From cc52f9d520fdf7dad467061d2a8a910b20eeb8f7 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 9 Sep 2013 18:48:20 +0800 Subject: [PATCH 094/141] issue #2772 move directory CCArmature to CocoStudio --- HelloHTML5World/build.xml | 40 +++++++++---------- cocos2d/build.xml | 40 +++++++++---------- cocos2d/platform/jsloader.js | 40 +++++++++---------- .../Armature}/CCArmature.js | 0 .../Armature}/CCBone.js | 0 .../animation/CCArmatureAnimation.js | 0 .../Armature}/animation/CCProcessBase.js | 0 .../Armature}/animation/CCTween.js | 0 .../Armature}/datas/CCDatas.js | 0 .../Armature}/display/CCBatchNode.js | 0 .../Armature}/display/CCDecorativeDisplay.js | 0 .../Armature}/display/CCDisplayFactory.js | 0 .../Armature}/display/CCDisplayManager.js | 0 .../Armature}/display/CCShaderNode.js | 0 .../Armature}/display/CCSkin.js | 0 .../Armature}/physics/CCColliderDetector.js | 0 .../Armature}/utils/CCArmatureDefine.js | 0 .../Armature}/utils/CCDataReaderHelper.js | 0 .../utils/CCSpriteFrameCacheHelper.js | 0 .../Armature}/utils/CCTransformHelp.js | 0 .../Armature}/utils/CCTweenFunction.js | 0 .../Armature}/utils/CCUtilMath.js | 0 .../Armature}/utils/CSArmatureDataManager.js | 0 template/build.xml | 40 +++++++++---------- 24 files changed, 80 insertions(+), 80 deletions(-) rename extensions/{CCArmature => CocoStudio/Armature}/CCArmature.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/CCBone.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/animation/CCArmatureAnimation.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/animation/CCProcessBase.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/animation/CCTween.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/datas/CCDatas.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCBatchNode.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCDecorativeDisplay.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCDisplayFactory.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCDisplayManager.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCShaderNode.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/display/CCSkin.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/physics/CCColliderDetector.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCArmatureDefine.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCDataReaderHelper.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCSpriteFrameCacheHelper.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCTransformHelp.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCTweenFunction.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CCUtilMath.js (100%) rename extensions/{CCArmature => CocoStudio/Armature}/utils/CSArmatureDataManager.js (100%) diff --git a/HelloHTML5World/build.xml b/HelloHTML5World/build.xml index ae0daa9a7f..2584803dd8 100644 --- a/HelloHTML5World/build.xml +++ b/HelloHTML5World/build.xml @@ -158,26 +158,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/cocos2d/build.xml b/cocos2d/build.xml index 4415b4241e..6121f8628c 100644 --- a/cocos2d/build.xml +++ b/cocos2d/build.xml @@ -159,26 +159,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index 752e5c92d9..c694f5b657 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -174,26 +174,26 @@ '../extensions/CCBReader/CCBRelativePositioning.js', '../extensions/CCBReader/CCBAnimationManager.js', '../extensions/CCEditBox.js', - '../extensions/CCArmature/utils/CCArmatureDefine.js', - '../extensions/CCArmature/utils/CCDataReaderHelper.js', - '../extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js', - '../extensions/CCArmature/utils/CCTransformHelp.js', - '../extensions/CCArmature/utils/CCTweenFunction.js', - '../extensions/CCArmature/utils/CCUtilMath.js', - '../extensions/CCArmature/utils/CSArmatureDataManager.js', - '../extensions/CCArmature/datas/CCDatas.js', - '../extensions/CCArmature/display/CCBatchNode.js', - '../extensions/CCArmature/display/CCDecorativeDisplay.js', - '../extensions/CCArmature/display/CCDisplayFactory.js', - '../extensions/CCArmature/display/CCDisplayManager.js', - '../extensions/CCArmature/display/CCShaderNode.js', - '../extensions/CCArmature/display/CCSkin.js', - '../extensions/CCArmature/animation/CCProcessBase.js', - '../extensions/CCArmature/animation/CCArmatureAnimation.js', - '../extensions/CCArmature/animation/CCTween.js', - '../extensions/CCArmature/physics/CCColliderDetector.js', - '../extensions/CCArmature/CCArmature.js', - '../extensions/CCArmature/CCBone.js' + '../extensions/CocoStudio/Armature/utils/CCArmatureDefine.js', + '../extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js', + '../extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js', + '../extensions/CocoStudio/Armature/utils/CCTransformHelp.js', + '../extensions/CocoStudio/Armature/utils/CCTweenFunction.js', + '../extensions/CocoStudio/Armature/utils/CCUtilMath.js', + '../extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js', + '../extensions/CocoStudio/Armature/datas/CCDatas.js', + '../extensions/CocoStudio/Armature/display/CCBatchNode.js', + '../extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js', + '../extensions/CocoStudio/Armature/display/CCDisplayFactory.js', + '../extensions/CocoStudio/Armature/display/CCDisplayManager.js', + '../extensions/CocoStudio/Armature/display/CCShaderNode.js', + '../extensions/CocoStudio/Armature/display/CCSkin.js', + '../extensions/CocoStudio/Armature/animation/CCProcessBase.js', + '../extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js', + '../extensions/CocoStudio/Armature/animation/CCTween.js', + '../extensions/CocoStudio/Armature/physics/CCColliderDetector.js', + '../extensions/CocoStudio/Armature/CCArmature.js', + '../extensions/CocoStudio/Armature/CCBone.js' ]); } diff --git a/extensions/CCArmature/CCArmature.js b/extensions/CocoStudio/Armature/CCArmature.js similarity index 100% rename from extensions/CCArmature/CCArmature.js rename to extensions/CocoStudio/Armature/CCArmature.js diff --git a/extensions/CCArmature/CCBone.js b/extensions/CocoStudio/Armature/CCBone.js similarity index 100% rename from extensions/CCArmature/CCBone.js rename to extensions/CocoStudio/Armature/CCBone.js diff --git a/extensions/CCArmature/animation/CCArmatureAnimation.js b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js similarity index 100% rename from extensions/CCArmature/animation/CCArmatureAnimation.js rename to extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js diff --git a/extensions/CCArmature/animation/CCProcessBase.js b/extensions/CocoStudio/Armature/animation/CCProcessBase.js similarity index 100% rename from extensions/CCArmature/animation/CCProcessBase.js rename to extensions/CocoStudio/Armature/animation/CCProcessBase.js diff --git a/extensions/CCArmature/animation/CCTween.js b/extensions/CocoStudio/Armature/animation/CCTween.js similarity index 100% rename from extensions/CCArmature/animation/CCTween.js rename to extensions/CocoStudio/Armature/animation/CCTween.js diff --git a/extensions/CCArmature/datas/CCDatas.js b/extensions/CocoStudio/Armature/datas/CCDatas.js similarity index 100% rename from extensions/CCArmature/datas/CCDatas.js rename to extensions/CocoStudio/Armature/datas/CCDatas.js diff --git a/extensions/CCArmature/display/CCBatchNode.js b/extensions/CocoStudio/Armature/display/CCBatchNode.js similarity index 100% rename from extensions/CCArmature/display/CCBatchNode.js rename to extensions/CocoStudio/Armature/display/CCBatchNode.js diff --git a/extensions/CCArmature/display/CCDecorativeDisplay.js b/extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js similarity index 100% rename from extensions/CCArmature/display/CCDecorativeDisplay.js rename to extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js diff --git a/extensions/CCArmature/display/CCDisplayFactory.js b/extensions/CocoStudio/Armature/display/CCDisplayFactory.js similarity index 100% rename from extensions/CCArmature/display/CCDisplayFactory.js rename to extensions/CocoStudio/Armature/display/CCDisplayFactory.js diff --git a/extensions/CCArmature/display/CCDisplayManager.js b/extensions/CocoStudio/Armature/display/CCDisplayManager.js similarity index 100% rename from extensions/CCArmature/display/CCDisplayManager.js rename to extensions/CocoStudio/Armature/display/CCDisplayManager.js diff --git a/extensions/CCArmature/display/CCShaderNode.js b/extensions/CocoStudio/Armature/display/CCShaderNode.js similarity index 100% rename from extensions/CCArmature/display/CCShaderNode.js rename to extensions/CocoStudio/Armature/display/CCShaderNode.js diff --git a/extensions/CCArmature/display/CCSkin.js b/extensions/CocoStudio/Armature/display/CCSkin.js similarity index 100% rename from extensions/CCArmature/display/CCSkin.js rename to extensions/CocoStudio/Armature/display/CCSkin.js diff --git a/extensions/CCArmature/physics/CCColliderDetector.js b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js similarity index 100% rename from extensions/CCArmature/physics/CCColliderDetector.js rename to extensions/CocoStudio/Armature/physics/CCColliderDetector.js diff --git a/extensions/CCArmature/utils/CCArmatureDefine.js b/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js similarity index 100% rename from extensions/CCArmature/utils/CCArmatureDefine.js rename to extensions/CocoStudio/Armature/utils/CCArmatureDefine.js diff --git a/extensions/CCArmature/utils/CCDataReaderHelper.js b/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js similarity index 100% rename from extensions/CCArmature/utils/CCDataReaderHelper.js rename to extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js diff --git a/extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js b/extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js similarity index 100% rename from extensions/CCArmature/utils/CCSpriteFrameCacheHelper.js rename to extensions/CocoStudio/Armature/utils/CCSpriteFrameCacheHelper.js diff --git a/extensions/CCArmature/utils/CCTransformHelp.js b/extensions/CocoStudio/Armature/utils/CCTransformHelp.js similarity index 100% rename from extensions/CCArmature/utils/CCTransformHelp.js rename to extensions/CocoStudio/Armature/utils/CCTransformHelp.js diff --git a/extensions/CCArmature/utils/CCTweenFunction.js b/extensions/CocoStudio/Armature/utils/CCTweenFunction.js similarity index 100% rename from extensions/CCArmature/utils/CCTweenFunction.js rename to extensions/CocoStudio/Armature/utils/CCTweenFunction.js diff --git a/extensions/CCArmature/utils/CCUtilMath.js b/extensions/CocoStudio/Armature/utils/CCUtilMath.js similarity index 100% rename from extensions/CCArmature/utils/CCUtilMath.js rename to extensions/CocoStudio/Armature/utils/CCUtilMath.js diff --git a/extensions/CCArmature/utils/CSArmatureDataManager.js b/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js similarity index 100% rename from extensions/CCArmature/utils/CSArmatureDataManager.js rename to extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js diff --git a/template/build.xml b/template/build.xml index 48846e4c02..174c0c5ba5 100644 --- a/template/build.xml +++ b/template/build.xml @@ -158,26 +158,26 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + From 345f3f69635f0e6dc04a361d5b72ca17856063a3 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 10 Sep 2013 10:44:04 +0800 Subject: [PATCH 095/141] Closed #2786: Refactor cc.PhysicsSprite for Performance --- .../particle_nodes/CCParticleSystemQuad.js | 2 +- cocos2d/physics_nodes/CCPhysicsSprite.js | 94 +++++++++++-------- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 2 +- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/cocos2d/particle_nodes/CCParticleSystemQuad.js b/cocos2d/particle_nodes/CCParticleSystemQuad.js index 8eb273f696..4b9debb67c 100644 --- a/cocos2d/particle_nodes/CCParticleSystemQuad.js +++ b/cocos2d/particle_nodes/CCParticleSystemQuad.js @@ -284,7 +284,7 @@ cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQua * @param {cc.SpriteFrame} spriteFrame */ setDisplayFrame:function (spriteFrame) { - cc.Assert(cc.pointEqualToPoint(spriteFrame.getOffsetInPixels(), cc.PointZero()), "QuadParticle only supports SpriteFrames with no offsets"); + cc.Assert(cc._rectEqualToZero(spriteFrame.getOffsetInPixels()), "QuadParticle only supports SpriteFrames with no offsets"); // update texture before updating texture rect if (cc.renderContextType === cc.WEBGL) diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js index 10873ea427..05071ee048 100644 --- a/cocos2d/physics_nodes/CCPhysicsSprite.js +++ b/cocos2d/physics_nodes/CCPhysicsSprite.js @@ -51,11 +51,13 @@ }, getPosition:function () { var pos = this._body.GetPosition(); - return cc.p(pos.x * this._PTMRatio, pos.y * this._PTMRatio); + var locPTMRatio =this._PTMRatio; + return cc.p(pos.x * locPTMRatio, pos.y * locPTMRatio); }, setPosition:function (p) { var angle = this._body.GetAngle(); - this._body.setTransform(Box2D.b2Vec2(p.x / this._PTMRatio, p.y / this._PTMRatio), angle); + var locPTMRatio =this._PTMRatio; + this._body.setTransform(Box2D.b2Vec2(p.x / locPTMRatio, p.y / locPTMRatio), angle); this.setNodeDirty(); }, getRotation:function () { @@ -64,10 +66,10 @@ setRotation:function (r) { if (this._ignoreBodyRotation) { this._rotation = r; - } - else { - var p = this._body.GetPosition(); - this._body.SetTransform(p, cc.DEGREES_TO_RADIANS(r)); + } else { + var locBody = this._body; + var p = locBody.GetPosition(); + locBody.SetTransform(p, cc.DEGREES_TO_RADIANS(r)); } this.setNodeDirty(); }, @@ -102,16 +104,28 @@ return this._body; }, getPosition:function () { - return {x:this._body.p.x, y:this._body.p.y}; + var locBody = this._body; + return {x:locBody.p.x, y:locBody.p.y}; + }, + + getPositionX:function () { + return this._body.p.x; + }, + + getPositionY:function () { + return this._body.p.y; }, + setPosition:function (pos) { - this._body.p.x = pos.x; - this._body.p.y = pos.y; + var locBody = this._body; + locBody.p.x = pos.x; + locBody.p.y = pos.y; //this._syncPosition(); }, _syncPosition:function () { - if (this._position.x != this._body.p.x || this._position.y != this._body.p.y) { - cc.Sprite.prototype.setPosition.call(this, {x:this._body.p.x, y:this._body.p.y}); + var locPosition = this._position, locBody = this._body; + if (locPosition.x != locBody.p.x || locPosition.y != locBody.p.y) { + cc.Sprite.prototype.setPosition.call(this, locBody.p.x, locBody.p.y); } }, getRotation:function () { @@ -134,48 +148,50 @@ if(cc.renderContextType === cc.CANVAS) return this._nodeToParentTransformForCanvas(); - var x = this._body.p.x; - var y = this._body.p.y; + var locBody = this._body, locAnchorPIP = this._anchorPointInPoints, locScaleX = this._scaleX, locScaleY = this._scaleY; + var x = locBody.p.x; + var y = locBody.p.y; if (this._ignoreAnchorPointForPosition) { - x += this._anchorPointInPoints.x; - y += this._anchorPointInPoints.y; + x += locAnchorPIP.x; + y += locAnchorPIP.y; } // Make matrix - var radians = this._body.a; + var radians = locBody.a; var c = Math.cos(radians); var s = Math.sin(radians); // Although scale is not used by physics engines, it is calculated just in case // the sprite is animated (scaled up/down) using actions. // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 - if (!cc.pointEqualToPoint(this._anchorPointInPoints, cc.PointZero())) { - x += c * -this._anchorPointInPoints.x * this._scaleX + -s * -this._anchorPointInPoints.y * this._scaleY; - y += s * -this._anchorPointInPoints.x * this._scaleX + c * -this._anchorPointInPoints.y * this._scaleY; + if (!cc._rectEqualToZero(locAnchorPIP)) { + x += c * -locAnchorPIP.x * locScaleX + -s * -locAnchorPIP.y * locScaleY; + y += s * -locAnchorPIP.x * locScaleX + c * -locAnchorPIP.y * locScaleY; } // Rot, Translate Matrix - this._transform = cc.AffineTransformMake(c * this._scaleX, s * this._scaleX, - -s * this._scaleY, c * this._scaleY, + this._transform = cc.AffineTransformMake(c * locScaleX, s * locScaleX, + -s * locScaleY, c * locScaleY, x, y); return this._transform; }, - _nodeToParentTransformForCanvas:function(){ - if(!this._transform) - this._transform = {a:1,b:0,c:0,d:1,tx:0,ty:0}; - if(this.isDirty()){ + _nodeToParentTransformForCanvas: function () { + if (!this._transform) + this._transform = {a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0}; + if (this.isDirty()) { var t = this._transform;// quick reference // base position - t.tx = this._body.p.x; - t.ty = this._body.p.y; + var locBody = this._body, locScaleX = this._scaleX, locScaleY = this._scaleY, locAnchorPIP = this._anchorPointInPoints; + t.tx = locBody.p.x; + t.ty = locBody.p.y; // rotation Cos and Sin - var radians = -this._body.a; + var radians = -locBody.a; var Cos = 1, Sin = 0; - if(radians){ + if (radians) { Cos = Math.cos(radians); Sin = Math.sin(radians); } @@ -186,21 +202,21 @@ t.b = Sin; // scale - if(this._scaleX !== 1 || this._scaleY !== 1){ - t.a *= this._scaleX; - t.b *= this._scaleX; - t.c *= this._scaleY; - t.d *= this._scaleY; + if (locScaleX !== 1 || locScaleY !== 1) { + t.a *= locScaleX; + t.b *= locScaleX; + t.c *= locScaleY; + t.d *= locScaleY; } // adjust anchorPoint - t.tx += Cos*-this._anchorPointInPoints.x*this._scaleX + -Sin*this._anchorPointInPoints.y*this._scaleY; - t.ty -= Sin*-this._anchorPointInPoints.x*this._scaleX + Cos*this._anchorPointInPoints.y*this._scaleY; + t.tx += Cos * -locAnchorPIP.x * locScaleX + -Sin * locAnchorPIP.y * locScaleY; + t.ty -= Sin * -locAnchorPIP.x * locScaleX + Cos * locAnchorPIP.y * locScaleY; // if ignore anchorPoint - if(this._ignoreAnchorPointForPosition){ - t.tx += this._anchorPointInPoints.x; - t.ty += this._anchorPointInPoints.y; + if (this._ignoreAnchorPointForPosition) { + t.tx += locAnchorPIP.x; + t.ty += locAnchorPIP.y; } this._transformDirty = false; } diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index b139fad240..f30680f79f 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -636,7 +636,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ (this._mapTileSize.height / 2 ) * (-pos.x - pos.y)); break; case cc.TMX_ORIENTATION_HEX: - cc.Assert(cc.pointEqualToPoint(pos, cc.PointZero()), "offset for hexagonal map not implemented yet"); + cc.Assert(cc._rectEqualToZero(pos), "offset for hexagonal map not implemented yet"); break; } return ret; From 2de4be8f8b30c5410c0ad1fb927276eba9bd0c2a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Tue, 10 Sep 2013 17:59:27 +0800 Subject: [PATCH 096/141] closed #2772: fixed some bug for Armature --- .../Armature/animation/CCArmatureAnimation.js | 4 +++- .../CocoStudio/Armature/animation/CCTween.js | 2 +- .../Armature/display/CCDisplayManager.js | 2 +- .../Armature/utils/CCDataReaderHelper.js | 24 +++++++------------ .../Armature/utils/CSArmatureDataManager.js | 1 + 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js index 5745aab8c4..d4ae8025f0 100644 --- a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js +++ b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js @@ -182,7 +182,6 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ * 2 : fade in and out */ play:function (animationName, durationTo, durationTween, loop, tweenEasing) { - this.stop(); if (this._animationData == null) { cc.log("this._animationData can not be null"); return; @@ -230,6 +229,9 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ } this._durationTween = durationTween; } + + this._tweenList = []; + var movementBoneData; var dict = this._armature.getBoneDic(); for (var key in dict) { diff --git a/extensions/CocoStudio/Armature/animation/CCTween.js b/extensions/CocoStudio/Armature/animation/CCTween.js index bd76eb3cef..86f760405c 100644 --- a/extensions/CocoStudio/Armature/animation/CCTween.js +++ b/extensions/CocoStudio/Armature/animation/CCTween.js @@ -314,7 +314,7 @@ cc.Tween = cc.ProcessBase.extend({ var playedTime = this._rawDuration * currentPercent; var from,to; // if play to current frame's front or back, then find current frame again - if (playedTime < this._totalDuration || playedTime > this._totalDuration + this._betweenDuration) { + if (playedTime < this._totalDuration || playedTime >= this._totalDuration + this._betweenDuration) { /* * get frame length, if this._toIndex >= _length, then set this._toIndex to 0, start anew. * this._toIndex is next index will play diff --git a/extensions/CocoStudio/Armature/display/CCDisplayManager.js b/extensions/CocoStudio/Armature/display/CCDisplayManager.js index cf265f3323..1552dc32cf 100644 --- a/extensions/CocoStudio/Armature/display/CCDisplayManager.js +++ b/extensions/CocoStudio/Armature/display/CCDisplayManager.js @@ -50,7 +50,7 @@ cc.DisplayManager = cc.Class.extend({ addDisplay: function (displayData, index) { var decoDisplay = null; if (index >= 0 && index < this._decoDisplayList.length) { - decoDisplay = this._decoDisplayList[i]; + decoDisplay = this._decoDisplayList[index]; } else { decoDisplay = cc.DecotativeDisplay.create(); diff --git a/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js b/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js index 25480e559d..2da264a14d 100644 --- a/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js +++ b/extensions/CocoStudio/Armature/utils/CCDataReaderHelper.js @@ -124,11 +124,6 @@ cc.DataReaderHelper = cc.DataReaderHelper || {}; cc.DataReaderHelper._configFileList = []; cc.DataReaderHelper._flashToolVersion = cc.CONST_VERSION_2_0; cc.DataReaderHelper._cocoStudioVersion = cc.CONST_VERSION_COMBINED; -cc.DataReaderHelper._XMLFileList = []; -cc.DataReaderHelper._armarureDatas = {}; -cc.DataReaderHelper._animationDatas = {}; -cc.DataReaderHelper._textureDatas = {}; -cc.DataReaderHelper._json = {}; cc.DataReaderHelper._positionReadScale = 1; cc.DataReaderHelper._basefilePath = ""; cc.DataReaderHelper._asyncRefCount = 0; @@ -144,13 +139,16 @@ cc.DataReaderHelper.getPositionReadScale = function () { cc.DataReaderHelper.clear = function () { this._configFileList = []; + this._basefilePath = ""; + cc.DataReaderHelper._asyncRefCount = 0; + cc.DataReaderHelper._asyncRefTotalCount = 0; }; cc.DataReaderHelper.addDataFromFile = function (filePath,isLoadSpriteFrame) { var fileUtils = cc.FileUtils.getInstance(); var fullFilePath = fileUtils.fullPathForFilename(filePath); - if (cc.ArrayAppendObject(this._configFileList, fullFilePath)) { + if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) { return; } this._configFileList.push(fullFilePath); @@ -172,7 +170,7 @@ cc.DataReaderHelper.addDataFromFileAsync = function (filePath,target,selector,is var fileUtils = cc.FileUtils.getInstance(); var fullFilePath = fileUtils.fullPathForFilename(filePath); - if (cc.ArrayAppendObject(this._configFileList, fullFilePath)) { + if (cc.ArrayContainsObject(this._configFileList, fullFilePath)) { if (target && selector) { if (this._asyncRefTotalCount == 0 && this._asyncRefCount == 0) this._asyncCallBack(target, selector, 1); @@ -320,11 +318,7 @@ cc.DataReaderHelper.decodeBoneDisplay = function (_displayXML) { cc.DataReaderHelper.decodeAnimation = function (_animationXML) { var name = _animationXML.getAttribute(cc.CONST_A_NAME); - var aniData = this._animationDatas[name]; - if (aniData) { - return; - } - aniData = new cc.AnimationData(); + var aniData = new cc.AnimationData(); var _armatureData = cc.ArmatureDataManager.getInstance().getArmatureData(name); aniData.name = name; @@ -353,7 +347,7 @@ cc.DataReaderHelper.decodeMovement = function (movementXML, _armatureData) { durationTween = parseFloat(movementXML.getAttribute(cc.CONST_A_DURATION_TWEEN)) || 0; movementData.durationTween = durationTween; - loop = parseFloat(movementXML.getAttribute(cc.CONST_A_LOOP)) || 0; + loop = parseFloat(movementXML.getAttribute(cc.CONST_A_LOOP)) || 1; movementData.loop = Boolean(loop); var easing = movementXML.getAttribute(cc.CONST_A_TWEEN_EASING); @@ -450,12 +444,12 @@ cc.DataReaderHelper.decodeMovementBone = function (movBoneXml, parentXml, boneDa movBoneData.duration = totalDuration; } //todo - if(movBoneData.frameList.length>0){ + /*if(movBoneData.frameList.length>0){ var frameData = new cc.FrameData(); frameData.copy(movBoneData.frameList[movBoneData.frameList.length-1]); frameData.frameID = movBoneData.duration; movBoneData.addFrameData(frameData); - } + }*/ return movBoneData; }; diff --git a/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js b/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js index f26e6793b5..69406e93c0 100644 --- a/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js +++ b/extensions/CocoStudio/Armature/utils/CSArmatureDataManager.js @@ -240,5 +240,6 @@ cc.ArmatureDataManager.getInstance = function () { }; cc.ArmatureDataManager.purge = function () { cc.SpriteFrameCacheHelper.purge(); + cc.DataReaderHelper.clear(); this._instance = null; }; \ No newline at end of file From 11cb48eb4f81b12c3ff268095abc2c52bec04d75 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 11:58:27 +0800 Subject: [PATCH 097/141] issue #2772: delete CCShaderNode.js --- HelloHTML5World/build.xml | 1 - cocos2d/build.xml | 1 - cocos2d/platform/jsloader.js | 1 - .../Armature/display/CCShaderNode.js | 111 ------------------ template/build.xml | 1 - 5 files changed, 115 deletions(-) delete mode 100644 extensions/CocoStudio/Armature/display/CCShaderNode.js diff --git a/HelloHTML5World/build.xml b/HelloHTML5World/build.xml index 2584803dd8..b41ffc7848 100644 --- a/HelloHTML5World/build.xml +++ b/HelloHTML5World/build.xml @@ -170,7 +170,6 @@ - diff --git a/cocos2d/build.xml b/cocos2d/build.xml index 6121f8628c..42fb12afe6 100644 --- a/cocos2d/build.xml +++ b/cocos2d/build.xml @@ -171,7 +171,6 @@ - diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index c694f5b657..e5d65f1b42 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -186,7 +186,6 @@ '../extensions/CocoStudio/Armature/display/CCDecorativeDisplay.js', '../extensions/CocoStudio/Armature/display/CCDisplayFactory.js', '../extensions/CocoStudio/Armature/display/CCDisplayManager.js', - '../extensions/CocoStudio/Armature/display/CCShaderNode.js', '../extensions/CocoStudio/Armature/display/CCSkin.js', '../extensions/CocoStudio/Armature/animation/CCProcessBase.js', '../extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js', diff --git a/extensions/CocoStudio/Armature/display/CCShaderNode.js b/extensions/CocoStudio/Armature/display/CCShaderNode.js deleted file mode 100644 index 8c8a6bda88..0000000000 --- a/extensions/CocoStudio/Armature/display/CCShaderNode.js +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** - Copyright (c) 2010-2012 cocos2d-x.org - - 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.SIZE_X = 128; -cc.SIZE_Y = 128; - -cc.ShaderNode = cc.Node.extend({ - _center:cc.Vertex2(0.0, 0.0), - _resolution:cc.Vertex2(0.0, 0.0), - _time:0, - _uniformCenter:0, - _uniformResolution:0, - _uniformTime:0, - ctor:function () { - this._center = cc.Vertex2(0.0, 0.0); - this._resolution = cc.Vertex2(0.0, 0.0); - this._time = 0; - this._uniformCenter = 0; - this._uniformResolution = 0; - this._uniformTime = 0; - }, - - initWithVertex:function (vert, frag) { - this.loadShaderVertex(vert, frag); - this._time = 0; - this._resolution = cc.Vertex2(cc.SIZE_X, cc.SIZE_Y); - this.scheduleUpdate(); - this.setContentSize(cc.size(cc.SIZE_X, cc.SIZE_Y)); - this.setAnchorPoint(cc.p(0.5, 0.5)); - return true; - }, - - loadShaderVertex:function (vert, frag) { - var shader = new cc.GLProgram(); - shader.initWithVertexShaderFilename(vert, frag); - - shader.addAttribute("aVertex", cc.VERTEX_ATTRIB_POSITION); - shader.link(); - - shader.updateUniforms(); - - this._uniformCenter = cc.renderContext.getUniformLocation(shader.getProgram(), "center"); - this._uniformResolution = cc.renderContext.getUniformLocation(shader.getProgram(), "resolution"); - this._uniformTime = cc.renderContext.getUniformLocation(shader.getProgram(), "time"); - - this.setShaderProgram(shader); - - shader.release(); - }, - - update:function (dt) { - this._time += dt; - }, - - translateFormOtherNode:function (transform) { - this.setAdditionalTransform(transform); - - this._center = cc.Vertex2(this._additionalTransform.tx * cc.CONTENT_SCALE_FACTOR(), this._additionalTransform.ty * cc.CONTENT_SCALE_FACTOR()); - this._resolution = cc.Vertex2(cc.SIZE_X * this._additionalTransform.a, cc.SIZE_Y * this._additionalTransform.d); - }, - - setPosition:function (newPosition) { - cc.Node.prototype.setPosition.call(this, newPosition); - var position = this.getPosition(); - this._center = cc.Vertex2(position.x * cc.CONTENT_SCALE_FACTOR(), position.y * cc.CONTENT_SCALE_FACTOR()); - }, - - draw:function () { - cc.NODE_DRAW_SETUP(this); - var w = cc.SIZE_X, h = cc.SIZE_Y; - var vertices = [0, 0, w, 0, w, h, 0, 0, 0, h, w, h]; - - // Uniforms - this.getShaderProgram().setUniformLocationWith2f(this._uniformCenter, this._center.x, this._center.y); - this.getShaderProgram().setUniformLocationWith2f(this._uniformResolution, this._resolution.x, this._resolution.y); - - // time changes all the time, so it is Ok to call OpenGL directly, and not the "cached" version - cc.renderContext.uniform1f(this._uniformTime, this._time); - cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION); - cc.renderContext.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, cc.renderContext.FLOAT, false, 0, vertices); - cc.renderContext.drawArrays(cc.renderContext.TRIANGLES, 0, 6); - - cc.INCREMENT_GL_DRAWS(1); - } -}); -cc.ShaderNode.shaderNodeWithVertex = function (vert, frag) { - var node = new cc.ShaderNode(); - node.initWithVertex(vert, frag); - return node; -}; \ No newline at end of file diff --git a/template/build.xml b/template/build.xml index 174c0c5ba5..4a5e365e1b 100644 --- a/template/build.xml +++ b/template/build.xml @@ -170,7 +170,6 @@ - From b335c268631c4f2fda7536990301b6a60fc8329b Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 12:01:55 +0800 Subject: [PATCH 098/141] issue #2772 Optimize javascript code for Armature --- cocos2d/physics_nodes/CCPhysicsSprite.js | 12 +- extensions/CocoStudio/Armature/CCArmature.js | 11 +- extensions/CocoStudio/Armature/CCBone.js | 35 +++--- .../Armature/animation/CCArmatureAnimation.js | 39 +++--- .../Armature/animation/CCProcessBase.js | 7 +- .../CocoStudio/Armature/animation/CCTween.js | 111 ++++++++++-------- .../CocoStudio/Armature/datas/CCDatas.js | 16 +-- .../Armature/display/CCDisplayManager.js | 30 ++--- .../CocoStudio/Armature/display/CCSkin.js | 10 +- .../Armature/physics/CCColliderDetector.js | 60 ++++++---- 10 files changed, 186 insertions(+), 145 deletions(-) diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js index 05071ee048..e937777941 100644 --- a/cocos2d/physics_nodes/CCPhysicsSprite.js +++ b/cocos2d/physics_nodes/CCPhysicsSprite.js @@ -116,10 +116,14 @@ return this._body.p.y; }, - setPosition:function (pos) { - var locBody = this._body; - locBody.p.x = pos.x; - locBody.p.y = pos.y; + setPosition:function (newPosOrxValue, yValue) { + if(arguments.length==2){ + this._body.p.x = newPosOrxValue; + this._body.p.y = yValue; + }else{ + this._body.p.x = newPosOrxValue.x; + this._body.p.y = newPosOrxValue.y; + } //this._syncPosition(); }, _syncPosition:function () { diff --git a/extensions/CocoStudio/Armature/CCArmature.js b/extensions/CocoStudio/Armature/CCArmature.js index 73d40c74b8..638c56883d 100644 --- a/extensions/CocoStudio/Armature/CCArmature.js +++ b/extensions/CocoStudio/Armature/CCArmature.js @@ -35,9 +35,9 @@ cc.Armature = cc.NodeRGBA.extend({ _textureAtlas:null, _parentBone:null, _boneDic:null, - _topBoneList:[], - _armatureIndexDic:{}, - _offsetPoint:cc.p(0, 0), + _topBoneList:null, + _armatureIndexDic:null, + _offsetPoint:null, _version:0, _armatureTransformDirty:false, _body:null, @@ -281,8 +281,9 @@ cc.Armature = cc.NodeRGBA.extend({ update:function (dt) { this._animation.update(dt); - for (var i = 0; i < this._topBoneList.length; i++) { - this._topBoneList[i].update(dt); + var locTopBoneList = this._topBoneList; + for (var i = 0; i < locTopBoneList.length; i++) { + locTopBoneList[i].update(dt); } this._armatureTransformDirty = false; }, diff --git a/extensions/CocoStudio/Armature/CCBone.js b/extensions/CocoStudio/Armature/CCBone.js index 8423b3a492..d63ef0998a 100644 --- a/extensions/CocoStudio/Armature/CCBone.js +++ b/extensions/CocoStudio/Armature/CCBone.js @@ -36,7 +36,7 @@ cc.Bone = cc.NodeRGBA.extend({ _tween:null, _tweenData:null, _name:"", - _childrenBone:[], + _childrenBone:null, _parentBone:null, _boneTransformDirty:false, _worldTransform:null, @@ -138,27 +138,34 @@ cc.Bone = cc.NodeRGBA.extend({ * @param dt */ update:function (dt) { - if (this._parentBone) { - this._boneTransformDirty = this._boneTransformDirty || this._parentBone.isTransformDirty(); + var locParentBone = this._parentBone; + var locArmature = this._armature; + var locTweenData = this._tweenData; + var locWorldTransform = this._worldTransform; + + if (locParentBone) { + this._boneTransformDirty = this._boneTransformDirty || locParentBone.isTransformDirty(); } if (this._boneTransformDirty) { - if (this._armature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) { - cc.TransformHelp.nodeConcat(this._tweenData, this._boneData); - this._tweenData.scaleX -= 1; - this._tweenData.scaleY -= 1; + if (locArmature.getArmatureData().dataVersion >= cc.CONST_VERSION_COMBINED) { + cc.TransformHelp.nodeConcat(locTweenData, this._boneData); + locTweenData.scaleX -= 1; + locTweenData.scaleY -= 1; } - cc.TransformHelp.nodeToMatrix(this._tweenData, this._worldTransform); + cc.TransformHelp.nodeToMatrix(locTweenData, locWorldTransform); - this._worldTransform = cc.AffineTransformConcat(this.nodeToParentTransform(), this._worldTransform); + this._worldTransform = cc.AffineTransformConcat(this.nodeToParentTransform(), locWorldTransform); - if (this._parentBone) { - this._worldTransform = cc.AffineTransformConcat(this._worldTransform, this._parentBone._worldTransform); + if (locParentBone) { + this._worldTransform = cc.AffineTransformConcat(this._worldTransform, locParentBone._worldTransform); } } - cc.DisplayFactory.updateDisplay(this, this._displayManager.getCurrentDecorativeDisplay(), dt, this._boneTransformDirty|| this._armature.getArmatureTransformDirty()); - for (var i = 0; i < this._childrenBone.length; i++) { - this._childrenBone[i].update(dt); + cc.DisplayFactory.updateDisplay(this, this._displayManager.getCurrentDecorativeDisplay(), dt, this._boneTransformDirty || locArmature.getArmatureTransformDirty()); + + var locChildrenBone = this._childrenBone; + for (var i = 0; i < locChildrenBone.length; i++) { + locChildrenBone[i].update(dt); } this._boneTransformDirty = false; }, diff --git a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js index d4ae8025f0..8bcfd5100f 100644 --- a/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js +++ b/extensions/CocoStudio/Armature/animation/CCArmatureAnimation.js @@ -63,7 +63,7 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ _movementID:"", _prevFrameIndex:0, _toIndex:0, - _tweenList:[], + _tweenList:null, _frameEvent:null, _movementEvent:null, _speedScale:1, @@ -203,16 +203,17 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ if (typeof tweenEasing == "undefined") { tweenEasing = cc.TweenType.TWEEN_EASING_MAX; } + var locMovementData = this._movementData; //Get key frame count - this._rawDuration = this._movementData.duration; + this._rawDuration = locMovementData.duration; this._movementID = animationName; - this._processScale = this._speedScale * this._movementData.scale; + this._processScale = this._speedScale * locMovementData.scale; //Further processing parameters - durationTo = (durationTo == -1) ? this._movementData.durationTo : durationTo; - durationTween = (durationTween == -1) ? this._movementData.durationTween : durationTween; - durationTween = (durationTween == 0) ? this._movementData.duration : durationTween;//todo - tweenEasing = (tweenEasing == cc.TweenType.TWEEN_EASING_MAX) ? this._movementData.tweenEasing : tweenEasing; - loop = (loop < 0) ? this._movementData.loop : loop; + durationTo = (durationTo == -1) ? locMovementData.durationTo : durationTo; + durationTween = (durationTween == -1) ? locMovementData.durationTween : durationTween; + durationTween = (durationTween == 0) ? locMovementData.duration : durationTween;//todo + tweenEasing = (tweenEasing == cc.TweenType.TWEEN_EASING_MAX) ? locMovementData.tweenEasing : tweenEasing; + loop = (loop < 0) ? locMovementData.loop : loop; cc.ProcessBase.prototype.play.call(this, animationName, durationTo, durationTween, loop, tweenEasing); @@ -236,11 +237,11 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ var dict = this._armature.getBoneDic(); for (var key in dict) { var bone = dict[key]; - movementBoneData = this._movementData.getMovementBoneData(bone.getName()); + movementBoneData = locMovementData.getMovementBoneData(bone.getName()); var tween = bone.getTween(); if (movementBoneData && movementBoneData.frameList.length > 0) { this._tweenList.push(tween); - movementBoneData.duration = this._movementData.duration; + movementBoneData.duration = locMovementData.duration; tween.play(movementBoneData, durationTo, durationTween, loop, tweenEasing); tween.setProcessScale(this._processScale); @@ -307,38 +308,40 @@ cc.ArmatureAnimation = cc.ProcessBase.extend({ * update will call this handler, you can handle your logic here */ updateHandler:function () { - if (this._currentPercent >= 1) { + var locCurrentPercent = this._currentPercent; + if (locCurrentPercent >= 1) { switch (this._loopType) { case CC_ANIMATION_TYPE_NO_LOOP: this._loopType = CC_ANIMATION_TYPE_MAX; - this._currentFrame = (this._currentPercent - 1) * this._nextFrameIndex; - this._currentPercent = this._currentFrame / this._durationTween; - if (this._currentPercent < 1.0) { + this._currentFrame = (locCurrentPercent - 1) * this._nextFrameIndex; + locCurrentPercent = this._currentFrame / this._durationTween; + if (locCurrentPercent < 1.0) { this._nextFrameIndex = this._durationTween; this.callMovementEvent([this._armature, CC_MovementEventType_START, this._movementID]); break; } case CC_ANIMATION_TYPE_MAX: case CC_ANIMATION_TYPE_SINGLE_FRAME: - this._currentPercent = 1; + locCurrentPercent = 1; this._isComplete = true; this._isPlaying = false; this.callMovementEvent([this._armature, CC_MovementEventType_COMPLETE, this._movementID]); break; case CC_ANIMATION_TYPE_TO_LOOP_FRONT: this._loopType = CC_ANIMATION_TYPE_LOOP_FRONT; - this._currentPercent = cc.fmodf(this._currentPercent, 1); - this._currentFrame = this._nextFrameIndex == 0 ? 0 :cc.fmodf(this._currentFrame, this._nextFrameIndex); + locCurrentPercent = cc.fmodf(locCurrentPercent, 1); + this._currentFrame = this._nextFrameIndex == 0 ? 0 : cc.fmodf(this._currentFrame, this._nextFrameIndex); this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1; this.callMovementEvent([this, CC_MovementEventType_START, this._movementID]); break; default: - this._currentPercent = cc.fmodf(this._currentPercent, 1); + locCurrentPercent = cc.fmodf(locCurrentPercent, 1); this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); this._toIndex = 0; this.callMovementEvent([this._armature, CC_MovementEventType_LOOP_COMPLETE, this._movementID]); break; } + this._currentPercent = locCurrentPercent; } }, diff --git a/extensions/CocoStudio/Armature/animation/CCProcessBase.js b/extensions/CocoStudio/Armature/animation/CCProcessBase.js index cf12153d77..a67ade99f6 100644 --- a/extensions/CocoStudio/Armature/animation/CCProcessBase.js +++ b/extensions/CocoStudio/Armature/animation/CCProcessBase.js @@ -131,7 +131,8 @@ cc.ProcessBase = cc.Class.extend({ if (this._rawDuration <= 0 || dt > 1) { return false; } - if (this._nextFrameIndex <= 0) { + var locNextFrameIndex = this._nextFrameIndex; + if (locNextFrameIndex <= 0) { this._currentPercent = 1; this._currentFrame = 0; }else{ @@ -142,13 +143,13 @@ cc.ProcessBase = cc.Class.extend({ */ this._currentFrame += this._processScale * (dt / this._animationInternal); - this._currentPercent = this._currentFrame / this._nextFrameIndex; + this._currentPercent = this._currentFrame / locNextFrameIndex; /* * if this._currentFrame is bigger or equal than this._nextFrameIndex, then reduce it util this._currentFrame is * smaller than this._nextFrameIndex */ - this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); + this._currentFrame = cc.fmodf(this._currentFrame, locNextFrameIndex); } this.updateHandler(); return true; diff --git a/extensions/CocoStudio/Armature/animation/CCTween.js b/extensions/CocoStudio/Armature/animation/CCTween.js index 86f760405c..1a0ef754ca 100644 --- a/extensions/CocoStudio/Armature/animation/CCTween.js +++ b/extensions/CocoStudio/Armature/animation/CCTween.js @@ -150,42 +150,44 @@ cc.Tween = cc.ProcessBase.extend({ * update will call this handler, you can handle your logic here */ updateHandler:function () { - if (this._currentPercent >= 1) { - switch (this._loopType) { + var locCurrentPercent = this._currentPercent; + var locLoopType = this._loopType; + if (locCurrentPercent >= 1) { + switch (locLoopType) { case CC_ANIMATION_TYPE_SINGLE_FRAME: - this._currentPercent = 1; + locCurrentPercent = 1; this._isComplete = true; break; case CC_ANIMATION_TYPE_NO_LOOP: - this._loopType = CC_ANIMATION_TYPE_MAX; + locLoopType = CC_ANIMATION_TYPE_MAX; if (this._durationTween <= 0) { - this._currentPercent = 1; + locCurrentPercent = 1; } else { - this._currentPercent = (this._currentPercent - 1) * this._nextFrameIndex / this._durationTween; + locCurrentPercent = (locCurrentPercent - 1) * this._nextFrameIndex / this._durationTween; } - if (this._currentPercent >= 1) { - this._currentPercent = 1; + if (locCurrentPercent >= 1) { + locCurrentPercent = 1; this._isComplete = true; break; } else { this._nextFrameIndex = this._durationTween; - this._currentFrame = this._currentPercent * this._nextFrameIndex; + this._currentFrame = locCurrentPercent * this._nextFrameIndex; this._totalDuration = 0; this._betweenDuration = 0; this._fromIndex = this._toIndex = 0; break; } case CC_ANIMATION_TYPE_TO_LOOP_BACK: - this._loopType = CC_ANIMATION_TYPE_LOOP_BACK; + locLoopType = CC_ANIMATION_TYPE_LOOP_BACK; this._nextFrameIndex = this._durationTween > 0 ? this._durationTween : 1; if (this._movementBoneData.delay != 0) { this._currentFrame = (1 - this._movementBoneData.delay) * this._nextFrameIndex; - this._currentPercent = this._currentFrame / this._nextFrameIndex; + locCurrentPercent = this._currentFrame / this._nextFrameIndex; } else { - this._currentPercent = 0; + locCurrentPercent = 0; this._currentFrame = 0; } @@ -194,11 +196,11 @@ cc.Tween = cc.ProcessBase.extend({ this._fromIndex = this._toIndex = 0; break; case CC_ANIMATION_TYPE_MAX: - this._currentPercent = 1; + locCurrentPercent = 1; this._isComplete = true; break; default: - this._currentPercent = cc.fmodf(this._currentPercent, 1); + locCurrentPercent = cc.fmodf(locCurrentPercent, 1); this._currentFrame = cc.fmodf(this._currentFrame, this._nextFrameIndex); this._totalDuration = 0; this._betweenDuration = 0; @@ -207,16 +209,18 @@ cc.Tween = cc.ProcessBase.extend({ } } - if (this._currentPercent < 1 && this._loopType < CC_ANIMATION_TYPE_TO_LOOP_BACK) { - this._currentPercent = Math.sin(this._currentPercent * cc.PI / 2); + if (locCurrentPercent < 1 && locLoopType < CC_ANIMATION_TYPE_TO_LOOP_BACK) { + locCurrentPercent = Math.sin(locCurrentPercent * cc.PI / 2); } - var percent = this._currentPercent; - if (this._loopType > CC_ANIMATION_TYPE_TO_LOOP_BACK) { - percent = this.updateFrameData(percent, true); + this._currentPercent = locCurrentPercent; + this._loopType = locLoopType; + + if (locLoopType > CC_ANIMATION_TYPE_TO_LOOP_BACK) { + locCurrentPercent = this.updateFrameData(locCurrentPercent, true); } if (this._frameTweenEasing != cc.TweenType.TWEEN_EASING_MAX) { - this.tweenNodeTo(percent); + this.tweenNodeTo(locCurrentPercent); } }, @@ -251,16 +255,17 @@ cc.Tween = cc.ProcessBase.extend({ */ arriveKeyFrame:function (keyFrameData) { if (keyFrameData) { + var locBone = this._bone; var displayIndex = keyFrameData.displayIndex; - var displayManager = this._bone.getDisplayManager(); + var displayManager = locBone.getDisplayManager(); if (!displayManager.getForceChangeDisplay()) { displayManager.changeDisplayByIndex(displayIndex, false); } this._tweenData.zOrder = keyFrameData.zOrder; - this._bone.updateZOrder(); - this._bone.setBlendType(keyFrameData.blendType); - var childAramture = this._bone.getChildArmature(); + locBone.updateZOrder(); + locBone.setBlendType(keyFrameData.blendType); + var childAramture = locBone.getChildArmature(); if (childAramture) { if (keyFrameData.movement != "") { childAramture.getAnimation().play(keyFrameData.movement); @@ -279,25 +284,29 @@ cc.Tween = cc.ProcessBase.extend({ if (!node) { node = this._tweenData; } - node.x = this._from.x + percent * this._between.x; - node.y = this._from.y + percent * this._between.y; - node.scaleX = this._from.scaleX + percent * this._between.scaleX; - node.scaleY = this._from.scaleY + percent * this._between.scaleY; - node.skewX = this._from.skewX + percent * this._between.skewX; - node.skewY = this._from.skewY + percent * this._between.skewY; + var locFrom = this._from; + var locBetween = this._between; + node.x = locFrom.x + percent * locBetween.x; + node.y = locFrom.y + percent * locBetween.y; + node.scaleX = locFrom.scaleX + percent * locBetween.scaleX; + node.scaleY = locFrom.scaleY + percent * locBetween.scaleY; + node.skewX = locFrom.skewX + percent * locBetween.skewX; + node.skewY = locFrom.skewY + percent * locBetween.skewY; this._bone.setTransformDirty(true); - if (node && this._between.isUseColorInfo) + if (node && locBetween.isUseColorInfo) this.tweenColorTo(percent, node); return node; }, tweenColorTo:function(percent,node){ - node.a = this._from.a + percent * this._between.a; - node.r = this._from.r + percent * this._between.r; - node.g = this._from.g + percent * this._between.g; - node.b = this._from.b + percent * this._between.b; + var locFrom = this._from; + var locBetween = this._between; + node.a = locFrom.a + percent * locBetween.a; + node.r = locFrom.r + percent * locBetween.r; + node.g = locFrom.g + percent * locBetween.g; + node.b = locFrom.b + percent * locBetween.b; this._bone.updateColor(); }, @@ -312,9 +321,10 @@ cc.Tween = cc.ProcessBase.extend({ currentPercent = cc.fmodf(currentPercent,1); } var playedTime = this._rawDuration * currentPercent; - var from,to; + var from, to; + var locTotalDuration = this._totalDuration,locBetweenDuration = this._betweenDuration, locToIndex = this._toIndex; // if play to current frame's front or back, then find current frame again - if (playedTime < this._totalDuration || playedTime >= this._totalDuration + this._betweenDuration) { + if (playedTime < locTotalDuration || playedTime >= locTotalDuration + locBetweenDuration) { /* * get frame length, if this._toIndex >= _length, then set this._toIndex to 0, start anew. * this._toIndex is next index will play @@ -334,12 +344,12 @@ cc.Tween = cc.ProcessBase.extend({ do { from = frames[this._fromIndex]; - this._totalDuration = from.frameID; - if (++this._toIndex >= length) { - this._toIndex = 0; + locTotalDuration = from.frameID; + if (++locToIndex >= length) { + locToIndex = 0; } - this._fromIndex = this._toIndex; - to = frames[this._toIndex]; + this._fromIndex = locToIndex; + to = frames[locToIndex]; //! Guaranteed to trigger frame event if(from.event){ @@ -352,19 +362,24 @@ cc.Tween = cc.ProcessBase.extend({ } while (playedTime < from.frameID || playedTime >= to.frameID); - this._betweenDuration = to.frameID - from.frameID; + locBetweenDuration = to.frameID - from.frameID; this._frameTweenEasing = from.tweenEasing; this.setBetween(from, to); + this._totalDuration = locTotalDuration; + this._betweenDuration = locBetweenDuration; + this._toIndex = locToIndex; } - currentPercent = this._betweenDuration == 0 ? 0 : (playedTime - this._totalDuration) / this._betweenDuration; + + currentPercent = locBetweenDuration == 0 ? 0 : (playedTime - locTotalDuration) / locBetweenDuration; + /* * if frame tween easing equal to TWEEN_EASING_MAX, then it will not do tween. */ var tweenType = null; - - if (this._frameTweenEasing != cc.TweenType.TWEEN_EASING_MAX) { - tweenType = (this._tweenEasing == cc.TweenType.TWEEN_EASING_MAX) ? this._frameTweenEasing : this._tweenEasing; - if (tweenType != cc.TweenType.TWEEN_EASING_MAX&&tweenType != cc.TweenType.Linear) { + var locTWEEN_EASING_MAX = cc.TweenType.TWEEN_EASING_MAX; + if (this._frameTweenEasing != locTWEEN_EASING_MAX) { + tweenType = (this._tweenEasing == locTWEEN_EASING_MAX) ? this._frameTweenEasing : this._tweenEasing; + if (tweenType != locTWEEN_EASING_MAX&&tweenType != cc.TweenType.Linear) { currentPercent = cc.TweenFunction.tweenTo(0, 1, currentPercent, 1, tweenType); } } diff --git a/extensions/CocoStudio/Armature/datas/CCDatas.js b/extensions/CocoStudio/Armature/datas/CCDatas.js index fd4c86b367..3e5bd83cef 100644 --- a/extensions/CocoStudio/Armature/datas/CCDatas.js +++ b/extensions/CocoStudio/Armature/datas/CCDatas.js @@ -241,7 +241,7 @@ cc.ShaderDisplayData = cc.DisplayData.extend({ }); cc.BoneData = cc.BaseData.extend({ - displayDataList:[], + displayDataList:null, name:"", parentName:"", boneDataTransform:null, @@ -265,7 +265,7 @@ cc.BoneData = cc.BaseData.extend({ }); cc.ArmatureData = cc.Class.extend({ - boneDataDic:{}, + boneDataDic:null, name:"", dataVersion:0, ctor:function () { @@ -329,7 +329,7 @@ cc.MovementBoneData = cc.Class.extend({ delay:0, scale:1, duration:0, - frameList:[], + frameList:null, name:"", ctor:function () { this.delay = 0; @@ -350,7 +350,7 @@ cc.MovementBoneData = cc.Class.extend({ }); cc.MovementData = cc.Class.extend({ - movBoneDataDic:{}, + movBoneDataDic:null, duration:0, scale:0, durationTo:0, @@ -378,8 +378,8 @@ cc.MovementData = cc.Class.extend({ }); cc.AnimationData = cc.Class.extend({ - moveDataDic:{}, - movementNames:[], + moveDataDic:null, + movementNames:null, name:"", ctor:function () { this.moveDataDic = {}; @@ -403,7 +403,7 @@ cc.ContourVertex2 = function (x, y) { }; cc.ContourData = cc.Class.extend({ - vertexList:[], + vertexList:null, ctor:function () { this.vertexList = []; }, @@ -429,7 +429,7 @@ cc.TextureData = cc.Class.extend({ pivotX:0, pivotY:0, name:"", - contourDataList:[], + contourDataList:null, ctor:function () { this.height = 0; this.width = 0; diff --git a/extensions/CocoStudio/Armature/display/CCDisplayManager.js b/extensions/CocoStudio/Armature/display/CCDisplayManager.js index 1552dc32cf..0dbee6adef 100644 --- a/extensions/CocoStudio/Armature/display/CCDisplayManager.js +++ b/extensions/CocoStudio/Armature/display/CCDisplayManager.js @@ -23,7 +23,7 @@ ****************************************************************************/ cc.DisplayManager = cc.Class.extend({ - _decoDisplayList:[], + _decoDisplayList:null, _currentDecoDisplay:null, _displayRenderNode:null, _displayIndex:-1, @@ -41,7 +41,6 @@ cc.DisplayManager = cc.Class.extend({ }, init:function (bone) { - this._bone = bone; this.initDisplayList(bone.getBoneData()); return true; @@ -145,21 +144,22 @@ cc.DisplayManager = cc.Class.extend({ }, setCurrentDecorativeDisplay:function (decoDisplay) { + var locCurrentDecoDisplay = this._currentDecoDisplay; if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { - if (this._currentDecoDisplay && this._currentDecoDisplay.getColliderDetector()) { - this._currentDecoDisplay.getColliderDetector().setActive(false); + if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) { + locCurrentDecoDisplay.getColliderDetector().setActive(false); } } this._currentDecoDisplay = decoDisplay; - + locCurrentDecoDisplay = this._currentDecoDisplay; if (cc.ENABLE_PHYSICS_CHIPMUNK_DETECT) { - if (this._currentDecoDisplay && this._currentDecoDisplay.getColliderDetector()) { - this._currentDecoDisplay.getColliderDetector().setActive(true); + if (locCurrentDecoDisplay && locCurrentDecoDisplay.getColliderDetector()) { + locCurrentDecoDisplay.getColliderDetector().setActive(true); } } - var displayRenderNode = this._currentDecoDisplay == null ? null : this._currentDecoDisplay.getDisplay(); + var displayRenderNode = locCurrentDecoDisplay == null ? null : locCurrentDecoDisplay.getDisplay(); if (this._displayRenderNode) { if (this._displayRenderNode instanceof cc.Armature) { this._bone.setChildArmature(null); @@ -171,17 +171,17 @@ cc.DisplayManager = cc.Class.extend({ this._displayRenderNode = displayRenderNode; - if (this._displayRenderNode) { - if (this._displayRenderNode instanceof cc.Armature) { - this._bone.setChildArmature(this._displayRenderNode); - }else if(this._displayRenderNode instanceof cc.ParticleSystemQuad) { - this._displayRenderNode.resetSystem(); + if (displayRenderNode) { + if (displayRenderNode instanceof cc.Armature) { + this._bone.setChildArmature(displayRenderNode); + }else if(displayRenderNode instanceof cc.ParticleSystemQuad) { + displayRenderNode.resetSystem(); } - if (this._displayRenderNode.RGBAProtocol) { + if (displayRenderNode.RGBAProtocol) { //this._displayRenderNode.setColor(this._bone.getColor()); //this._displayRenderNode.setOpacity(this._bone.getOpacity()); } - this._displayRenderNode.retain(); + displayRenderNode.retain(); //todo //this._displayRenderNode.setVisible(this._visible); } diff --git a/extensions/CocoStudio/Armature/display/CCSkin.js b/extensions/CocoStudio/Armature/display/CCSkin.js index 3a05d0efd3..470a536e3d 100644 --- a/extensions/CocoStudio/Armature/display/CCSkin.js +++ b/extensions/CocoStudio/Armature/display/CCSkin.js @@ -25,7 +25,7 @@ cc.Skin = cc.Sprite.extend({ _skinData:null, _bone:null, - _skinTransform:cc.AffineTransformIdentity(), + _skinTransform:null, _displayName:"", ctor:function () { cc.Sprite.prototype.ctor.call(this); @@ -51,10 +51,10 @@ cc.Skin = cc.Sprite.extend({ setSkinData:function (skinData) { this._skinData = skinData; - this.setScaleX(this._skinData.scaleX); - this.setScaleY(this._skinData.scaleY); - this.setRotation(cc.RADIANS_TO_DEGREES(this._skinData.skewX)); - this.setPosition(cc.p(this._skinData.x, this._skinData.y)); + this.setScaleX(skinData.scaleX); + this.setScaleY(skinData.scaleY); + this.setRotation(cc.RADIANS_TO_DEGREES(skinData.skewX)); + this.setPosition(skinData.x, skinData.y); this._skinTransform = this.nodeToParentTransform(); if (cc.renderContextType === cc.CANVAS) { diff --git a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js index f40e53d269..209338450f 100644 --- a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js +++ b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js @@ -65,8 +65,13 @@ cc.ColliderDetector = cc.Class.extend({ } }, removeContourData: function (contourData) { - //todo - //cc.ArrayRemoveObject(this._colliderBodyList,contourData); + var locColliderBodyList = this._colliderBodyList; + for (var i = 0; i < locColliderBodyList.length; i++) { + if(locColliderBodyList[i].getContourData()==contourData){ + locColliderBodyList.splice(i, 1); + return; + } + } }, removeAll: function () { this._colliderBodyList = []; @@ -79,20 +84,22 @@ cc.ColliderDetector = cc.Class.extend({ if (this._active == active) return; this._active = active; - if (this._body) { + var locBody = this._body; + var locShape; + if (locBody) { var colliderBody = null; if (this._active) { for (var i = 0; i < this._colliderBodyList.length; i++) { colliderBody = this._colliderBodyList[i]; - var shape = colliderBody.getShape(); - this._body.space.addShape(shape); + locShape = colliderBody.getShape(); + locBody.space.addShape(locShape); } } else { for (var i = 0; i < this._colliderBodyList.length; i++) { colliderBody = this._colliderBodyList[i]; - var shape = colliderBody.getShape(); - this._body.space.removeShape(shape); + locShape = colliderBody.getShape(); + locBody.space.removeShape(locShape); } } } @@ -109,30 +116,33 @@ cc.ColliderDetector = cc.Class.extend({ return; var colliderBody = null; - if(!cc.Browser.supportWebGL){ - t.b*=-1; - t.c*=-1; + if (!cc.Browser.supportWebGL) { + t.b *= -1; + t.c *= -1; } + var locBody = this._body; + var locHelpPoint = this.helpPoint; for (var i = 0; i < this._colliderBodyList.length; i++) { colliderBody = this._colliderBodyList[i]; var contourData = colliderBody.getContourData(); var shape = null; - if (this._body) + if (locBody) { shape = colliderBody.getShape(); - this._body.p.x = t.tx; - this._body.p.y = t.ty; - this._body.p.a = t.a; - var vs = contourData.vertexList; - for (var i = 0; i < vs.length; i++) { - this.helpPoint.x = vs[i].x; - this.helpPoint.y = vs[i].y; - this.helpPoint = cc.PointApplyAffineTransform(this.helpPoint, t); - if (shape) { - var v = new cp.Vect(0, 0); - v.x = this.helpPoint.x; - v.y = this.helpPoint.y; - shape.verts[i * 2] = this.helpPoint.x - t.tx; - shape.verts[i * 2 + 1] = this.helpPoint.y - t.ty; + locBody.p.x = t.tx; + locBody.p.y = t.ty; + locBody.p.a = t.a; + var vs = contourData.vertexList; + for (var i = 0; i < vs.length; i++) { + locHelpPoint.x = vs[i].x; + locHelpPoint.y = vs[i].y; + locHelpPoint = cc.PointApplyAffineTransform(locHelpPoint, t); + if (shape) { + var v = new cp.Vect(0, 0); + v.x = locHelpPoint.x; + v.y = locHelpPoint.y; + shape.verts[i * 2] = locHelpPoint.x - t.tx; + shape.verts[i * 2 + 1] = locHelpPoint.y - t.ty; + } } } } From ede76c5576676bd0e2a2fe1af9fdeb0e3cd3b8f9 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Wed, 11 Sep 2013 15:09:19 +0800 Subject: [PATCH 099/141] fixed #2798 : disable webgl on mobile browser --- HelloHTML5World/index.html | 13 ++++++------- HelloHTML5World/main.js | 3 +-- cocos2d/platform/miniFramework.js | 2 +- template/cocos2d.js | 1 + template/index.html | 7 ++++--- template/main.js | 18 +++++++++--------- template/src/myApp.js | 3 ++- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/HelloHTML5World/index.html b/HelloHTML5World/index.html index 728316cf86..e644972d08 100644 --- a/HelloHTML5World/index.html +++ b/HelloHTML5World/index.html @@ -4,11 +4,12 @@ Cocos2d-html5 Hello World test - - + + + -
- -
+ + - - \ No newline at end of file + \ No newline at end of file diff --git a/HelloHTML5World/main.js b/HelloHTML5World/main.js index 975f74dfd8..3caec9bd2f 100644 --- a/HelloHTML5World/main.js +++ b/HelloHTML5World/main.js @@ -43,8 +43,7 @@ var cocos2dApp = cc.Application.extend({ // initialize director var director = cc.Director.getInstance(); - // enable High Resource Mode(2x, such as iphone4) and maintains low resource on other devices. - //director.enableRetinaDisplay(true); + cc.EGLView.getInstance().setDesignResolutionSize(800, 450, cc.RESOLUTION_POLICY.SHOW_ALL); // turn on display FPS director.setDisplayStats(this.config['showFPS']); diff --git a/cocos2d/platform/miniFramework.js b/cocos2d/platform/miniFramework.js index dea0805b08..d10f19fc6c 100644 --- a/cocos2d/platform/miniFramework.js +++ b/cocos2d/platform/miniFramework.js @@ -77,7 +77,7 @@ cc.Browser = {}; // check supportWebGL item cc._userRenderMode = parseInt(c["renderMode"]) || 0; - if (cc._userRenderMode === 1) { + if (cc._userRenderMode === 1 || (cc._userRenderMode === 0 && cc.Browser.isMobile)) { //canvas only cc.Browser.supportWebGL = false; } else { diff --git a/template/cocos2d.js b/template/cocos2d.js index 26f3954ca6..ddc50c1494 100644 --- a/template/cocos2d.js +++ b/template/cocos2d.js @@ -33,6 +33,7 @@ showFPS:true, loadExtension:false, frameRate:60, + renderMode:0, //Choose of RenderMode: 0(default), 1(Canvas only), 2(WebGL only) tag:'gameCanvas', //the dom element to run cocos2d on engineDir:'../cocos2d/', //SingleEngineFile:'', diff --git a/template/index.html b/template/index.html index d0fe274dbd..a5d692d68a 100644 --- a/template/index.html +++ b/template/index.html @@ -4,11 +4,12 @@ Cocos2d-html5 Hello World test - - + + + - + \ No newline at end of file diff --git a/template/main.js b/template/main.js index e2266e2522..7cccd2aaa2 100644 --- a/template/main.js +++ b/template/main.js @@ -39,8 +39,8 @@ var cocos2dApp = cc.Application.extend({ var director = cc.Director.getInstance(); var screenSize = cc.EGLView.getInstance().getFrameSize(); - var resourceSize = cc.size(800, 450); - var designSize = cc.size(800, 450); + var resourceSize = cc.size(480, 800); + var designSize = cc.size(480, 800); var searchPaths = []; var resDirOrders = []; @@ -50,24 +50,24 @@ var cocos2dApp = cc.Application.extend({ var platform = cc.Application.getInstance().getTargetPlatform(); if (platform == cc.TARGET_PLATFORM.MOBILE_BROWSER) { - if (screenSize.height > 450) { + resDirOrders.push("HD"); + } + else if (platform == cc.TARGET_PLATFORM.PC_BROWSER) { + if (screenSize.height >= 800) { resDirOrders.push("HD"); } else { - resourceSize = cc.size(400, 225); - designSize = cc.size(400, 225); + resourceSize = cc.size(320, 480); + designSize = cc.size(320, 480); resDirOrders.push("Normal"); } } - else if (platform == cc.TARGET_PLATFORM.PC_BROWSER) { - resDirOrders.push("HD"); - } cc.FileUtils.getInstance().setSearchResolutionsOrder(resDirOrders); director.setContentScaleFactor(resourceSize.width / designSize.width); - cc.EGLView.getInstance().setDesignResolutionSize(designSize.width, designSize.height, cc.RESOLUTION_POLICY.SHOW_ALL); + cc.EGLView.getInstance().setDesignResolutionSize(screenSize.width, screenSize.height, cc.RESOLUTION_POLICY.SHOW_ALL); // turn on display FPS director.setDisplayStats(this.config['showFPS']); diff --git a/template/src/myApp.js b/template/src/myApp.js index 44216c7123..81f2bd9fdb 100644 --- a/template/src/myApp.js +++ b/template/src/myApp.js @@ -41,7 +41,7 @@ var MyLayer = cc.Layer.extend({ // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // ask director the window size - var size = cc.Director.getInstance().getWinSize(); + var size = cc.Director.getInstance().getVisibleSize(); // add a "close" icon to exit the progress. it's an autorelease object var closeItem = cc.MenuItemImage.create( @@ -71,6 +71,7 @@ var MyLayer = cc.Layer.extend({ this.sprite = cc.Sprite.create(s_HelloWorld); this.sprite.setAnchorPoint(cc.p(0.5, 0.5)); this.sprite.setPosition(cc.p(size.width / 2, size.height / 2)); + this.sprite.setScale(size.height/this.sprite.getContentSize().height); this.addChild(this.sprite, 0); } }); From e3d46408d345a53f2bcfe642b56bd0ce8151916e Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Wed, 11 Sep 2013 15:44:36 +0800 Subject: [PATCH 100/141] Closed #2795: Fix a bug of cc.Node that nodeToWorldTransform returns wrong value on Canvas Mode and refactor menu_nodes's codes for performance. --- cocos2d/base_nodes/CCNode.js | 22 ++++------ cocos2d/menu_nodes/CCMenu.js | 73 +++++++++++++++++--------------- cocos2d/menu_nodes/CCMenuItem.js | 18 ++++---- 3 files changed, 58 insertions(+), 55 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index f3e3ea2d07..d28c3a9c97 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -1502,7 +1502,7 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ }, /** - * Retrusn the world affine transform matrix. The matrix is in Pixels. + * Returns the world affine transform matrix. The matrix is in Pixels. * @return {cc.AffineTransform} */ nodeToWorldTransform:function () { @@ -1774,7 +1774,7 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ // transform for canvas var context = ctx || cc.renderContext; var t = this.nodeToParentTransform(); - context.transform(t.a, t.b, t.c, t.d, t.tx, -t.ty); + context.transform(t.a, t.c, t.b, t.d, t.tx, -t.ty); }, _transformForWebGL: function () { @@ -1837,8 +1837,8 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ // base abcd t.a = t.d = Cos; - t.c = -Sin; - t.b = Sin; + t.b = -Sin; + t.c = Sin; var lScaleX = this._scaleX, lScaleY = this._scaleY; var appX = this._anchorPointInPoints.x, appY = this._anchorPointInPoints.y; @@ -1856,8 +1856,8 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ var xx = appY * skx * sx; var yy = appX * sky * sy; t.a = Cos + -Sin * sky; - t.c = Cos * skx + -Sin; - t.b = Sin + Cos * sky; + t.b = Cos * skx + -Sin; + t.c = Sin + Cos * sky; t.d = Sin * skx + Cos; t.tx += Cos * xx + -Sin * yy; t.ty += Sin * xx + Cos * yy; @@ -1866,8 +1866,8 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ // scale if (lScaleX !== 1 || lScaleY !== 1) { t.a *= sx; - t.b *= sx; - t.c *= sy; + t.c *= sx; + t.b *= sy; t.d *= sy; } @@ -1877,16 +1877,12 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ // if ignore anchorPoint if (this._ignoreAnchorPointForPosition) { - t.tx += appX + t.tx += appX; t.ty += appY; } if (this._additionalTransformDirty) { this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform); - //Because the cartesian coordination is inverted in html5 canvas, these needs to be inverted as well - this._transform.b *= -1; - this._transform.c *= -1; - this._additionalTransformDirty = false; } diff --git a/cocos2d/menu_nodes/CCMenu.js b/cocos2d/menu_nodes/CCMenu.js index 407df91346..97b7153f92 100644 --- a/cocos2d/menu_nodes/CCMenu.js +++ b/cocos2d/menu_nodes/CCMenu.js @@ -174,8 +174,8 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ /** * @param {cc.Node} child - * @param {Number|Null} zOrder - * @param {Number|Null} tag + * @param {Number|Null} [zOrder=] + * @param {Number|Null} [tag=] */ addChild:function (child, zOrder, tag) { cc.Assert((child instanceof cc.MenuItem), "Menu only supports MenuItem objects as children"); @@ -194,18 +194,19 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ * @param {Number} padding */ alignItemsVerticallyWithPadding:function (padding) { - var height = -padding; - if (this._children && this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - height += this._children[i].getContentSize().height * this._children[i].getScaleY() + padding; - } - } + var height = -padding, locChildren = this._children, len, i, locScaleY, locHeight, locChild; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) + height += locChildren[i].getContentSize().height * locChildren[i].getScaleY() + padding; - var y = height / 2.0; - if (this._children && this._children.length > 0) { - for (i = 0; i < this._children.length; i++) { - this._children[i].setPosition(0, y - this._children[i].getContentSize().height * this._children[i].getScaleY() / 2); - y -= this._children[i].getContentSize().height * this._children[i].getScaleY() + padding; + var y = height / 2.0; + + for (i = 0, len = locChildren.length; i < len; i++) { + locChild = locChildren[i]; + locHeight = locChild.getContentSize().height; + locScaleY = locChild.getScaleY(); + locChild.setPosition(0, y - locHeight * locScaleY / 2); + y -= locHeight * locScaleY + padding; } } }, @@ -222,18 +223,19 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ * @param {Number} padding */ alignItemsHorizontallyWithPadding:function (padding) { - var width = -padding; - if (this._children && this._children.length > 0) { - for (var i = 0; i < this._children.length; i++) { - width += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding; - } - } + var width = -padding, locChildren = this._children, i, len, locScaleX, locWidth, locChild; + if (locChildren && locChildren.length > 0) { + for (i = 0, len = locChildren.length; i < len; i++) + width += locChildren[i].getContentSize().width * locChildren[i].getScaleX() + padding; - var x = -width / 2.0; - if (this._children && this._children.length > 0) { - for (i = 0; i < this._children.length; i++) { - this._children[i].setPosition(x + this._children[i].getContentSize().width * this._children[i].getScaleX() / 2, 0); - x += this._children[i].getContentSize().width * this._children[i].getScaleX() + padding; + var x = -width / 2.0; + + for (i = 0, len = locChildren.length; i < len; i++) { + locChild = locChildren[i]; + locScaleX = locChild.getScaleX(); + locWidth = locChildren[i].getContentSize().width; + locChild.setPosition(x + locWidth * locScaleX / 2, 0); + x += locWidth * locScaleX + padding; } } }, @@ -341,7 +343,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ var column = 0; var columnWidth = 0; var rowsOccupied = 0; - var columnRows, child, len, tmp; + var columnRows, child, len, tmp, locContentSize; var locChildren = this._children; if (locChildren && locChildren.length > 0) { @@ -355,10 +357,11 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ cc.Assert(columnRows, ""); // columnWidth = fmaxf(columnWidth, [item contentSize].width); - tmp = child.getContentSize().width; + locContentSize = child.getContentSize(); + tmp = locContentSize.width; columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp); - columnHeight += (child.getContentSize().height + 5); + columnHeight += (locContentSize.height + 5); ++rowsOccupied; if (rowsOccupied >= columnRows) { @@ -393,12 +396,13 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ } // columnWidth = fmaxf(columnWidth, [item contentSize].width); - tmp = child.getContentSize().width; + locContentSize = child.getContentSize(); + tmp = locContentSize.width; columnWidth = ((columnWidth >= tmp || isNaN(tmp)) ? columnWidth : tmp); child.setPosition(x + columnWidths[column] / 2, y - winSize.height / 2); - y -= child.getContentSize().height + 10; + y -= locContentSize.height + 10; ++rowsOccupied; if (rowsOccupied >= columnRows) { @@ -522,16 +526,17 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ _itemForTouch:function (touch) { var touchLocation = touch.getLocation(); - var itemChildren = this._children; + var itemChildren = this._children, locItemChild; if (itemChildren && itemChildren.length > 0) { for (var i = 0; i < itemChildren.length; i++) { - if (itemChildren[i].isVisible() && itemChildren[i].isEnabled()) { - var local = itemChildren[i].convertToNodeSpace(touchLocation); - var r = itemChildren[i].rect(); + locItemChild = itemChildren[i]; + if (locItemChild.isVisible() && locItemChild.isEnabled()) { + var local = locItemChild.convertToNodeSpace(touchLocation); + var r = locItemChild.rect(); r.x = 0; r.y = 0; if (cc.rectContainsPoint(r, local)) - return itemChildren[i]; + return locItemChild; } } } diff --git a/cocos2d/menu_nodes/CCMenuItem.js b/cocos2d/menu_nodes/CCMenuItem.js index 8985d195ef..534c9a88f4 100644 --- a/cocos2d/menu_nodes/CCMenuItem.js +++ b/cocos2d/menu_nodes/CCMenuItem.js @@ -184,12 +184,13 @@ cc.MenuItem = cc.NodeRGBA.extend(/** @lends cc.MenuItem# */{ */ activate:function () { if (this._isEnabled) { - if (this._target && (typeof(this._callback) == "string")) { - this._target[this._callback](this); - } else if (this._target && (typeof(this._callback) == "function")) { - this._callback.call(this._target, this); + var locTarget = this._target, locCallback = this._callback; + if (locTarget && (typeof(locCallback) == "string")) { + locTarget[locCallback](this); + } else if (locTarget && (typeof(locCallback) == "function")) { + locCallback.call(locTarget, this); } else - this._callback(this); + locCallback(this); } } }); @@ -274,11 +275,12 @@ cc.MenuItemLabel = cc.MenuItem.extend(/** @lends cc.MenuItemLabel# */{ */ setEnabled:function (enabled) { if (this._isEnabled != enabled) { + var locLabel = this._label; if (!enabled) { - this._colorBackup = this._label.getColor(); - this._label.setColor(this._disabledColor); + this._colorBackup = locLabel.getColor(); + locLabel.setColor(this._disabledColor); } else { - this._label.setColor(this._colorBackup); + locLabel.setColor(this._colorBackup); } } cc.MenuItem.prototype.setEnabled.call(this, enabled); From 2a2fb3a45b44190f8f299382e7cd57a1577f7a3e Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 16:23:07 +0800 Subject: [PATCH 101/141] fixed #2772 fixed transform bug for Armature in canvas model --- extensions/CocoStudio/Armature/CCArmature.js | 4 ---- extensions/CocoStudio/Armature/display/CCSkin.js | 11 ----------- .../CocoStudio/Armature/physics/CCColliderDetector.js | 4 ---- 3 files changed, 19 deletions(-) diff --git a/extensions/CocoStudio/Armature/CCArmature.js b/extensions/CocoStudio/Armature/CCArmature.js index 638c56883d..b33edf30a5 100644 --- a/extensions/CocoStudio/Armature/CCArmature.js +++ b/extensions/CocoStudio/Armature/CCArmature.js @@ -428,10 +428,6 @@ cc.Armature = cc.NodeRGBA.extend({ if (this._additionalTransformDirty) { this._transform = cc.AffineTransformConcat(this._transform, this._additionalTransform); - //Because the cartesian coordination is inverted in html5 canvas, these needs to be inverted as well - this._transform.b *= -1; - this._transform.c *= -1; - this._additionalTransformDirty = false; } diff --git a/extensions/CocoStudio/Armature/display/CCSkin.js b/extensions/CocoStudio/Armature/display/CCSkin.js index 470a536e3d..421f2175f2 100644 --- a/extensions/CocoStudio/Armature/display/CCSkin.js +++ b/extensions/CocoStudio/Armature/display/CCSkin.js @@ -57,10 +57,6 @@ cc.Skin = cc.Sprite.extend({ this.setPosition(skinData.x, skinData.y); this._skinTransform = this.nodeToParentTransform(); - if (cc.renderContextType === cc.CANVAS) { - this._skinTransform.b *= -1; - this._skinTransform.c *= -1; - } }, getSkinData:function () { @@ -77,10 +73,6 @@ cc.Skin = cc.Sprite.extend({ updateArmatureTransform:function () { this._transform = cc.AffineTransformConcat(this._skinTransform, this._bone.nodeToArmatureTransform()); - if (cc.renderContextType === cc.CANVAS) { - this._transform.b *= -1; - this._transform.c *= -1; - } }, /** returns a "local" axis aligned bounding box of the node.
* The returned box is relative only to its parent. @@ -89,9 +81,6 @@ cc.Skin = cc.Sprite.extend({ getBoundingBox:function () { var rect = cc.rect(0, 0, this._contentSize.width, this._contentSize.height); var transForm = this.nodeToParentTransform(); - if (cc.renderContextType === cc.CANVAS) { - transForm = {a:transForm.a, b:-transForm.b, c:-transForm.c, d:transForm.d, tx:transForm.tx, ty:transForm.ty}; - } return cc.RectApplyAffineTransform(rect, transForm); }, diff --git a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js index 209338450f..00044399a2 100644 --- a/extensions/CocoStudio/Armature/physics/CCColliderDetector.js +++ b/extensions/CocoStudio/Armature/physics/CCColliderDetector.js @@ -116,10 +116,6 @@ cc.ColliderDetector = cc.Class.extend({ return; var colliderBody = null; - if (!cc.Browser.supportWebGL) { - t.b *= -1; - t.c *= -1; - } var locBody = this._body; var locHelpPoint = this.helpPoint; for (var i = 0; i < this._colliderBodyList.length; i++) { From d42ee4950d86d2b147a03c5da27423312bac806e Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 16:31:16 +0800 Subject: [PATCH 102/141] fixed #2748: Fixed some bugs about progress --- cocos2d/misc_nodes/CCProgressTimer.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index 49d4dbc289..ee81ea8e7c 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -818,8 +818,20 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ var currentDrawSize = cc.size(drawedSize.width + drawingSize.width, drawedSize.height + drawingSize.height); var startPoint = cc.p(spriteSize.width * locMidPoint.x, spriteSize.height * locMidPoint.y); + var needToLeft = startPoint.x - currentDrawSize.width / 2; + if (locMidPoint.x > 0.5) { + if (currentDrawSize.width / 2 >= spriteSize.width - startPoint.x) { + needToLeft = spriteSize.width - currentDrawSize.width; + } + } + var needToTop = startPoint.y - currentDrawSize.height / 2; + if (locMidPoint.y > 0.5) { + if (currentDrawSize.height / 2 >= spriteSize.height - startPoint.y) { + needToTop = spriteSize.height - currentDrawSize.height; + } + } //left pos locBarRect.x = 0; From df0340ae4d9e087f404b8d941200decbec7e6a43 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 17:04:58 +0800 Subject: [PATCH 103/141] issue #2772 optimize updateOffsetPoint --- extensions/CocoStudio/Armature/CCArmature.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/extensions/CocoStudio/Armature/CCArmature.js b/extensions/CocoStudio/Armature/CCArmature.js index b33edf30a5..7e1e88d632 100644 --- a/extensions/CocoStudio/Armature/CCArmature.js +++ b/extensions/CocoStudio/Armature/CCArmature.js @@ -273,9 +273,11 @@ cc.Armature = cc.NodeRGBA.extend({ // Set contentsize and Calculate anchor point. var rect = this.boundingBox(); this.setContentSize(rect.size); - this._offsetPoint = cc.p(-rect.origin.x, -rect.origin.y); + var locOffsetPoint = this._offsetPoint; + locOffsetPoint.x = -rect.x; + locOffsetPoint.y = -rect.y; if (rect.width != 0 && rect.height != 0) { - this.setAnchorPoint(cc.p(this._offsetPoint.x / rect.size.width, this._offsetPoint.y / rect.size.height)); + this.setAnchorPoint(cc.p(locOffsetPoint.x / rect.width, locOffsetPoint.y / rect.height)); } }, From 70815eaa9a48f713b5fcc5e834bad063b142bdef Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 17:19:38 +0800 Subject: [PATCH 104/141] fixed #2741 add setPositionX /setPositionY for LabelTTF --- cocos2d/label_nodes/CCLabelTTF.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index fa4b29d913..ff58ab96ba 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -734,6 +734,16 @@ cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ cc.Sprite.prototype.setPosition.call(this, realPosition); }, + setPositionX:function(x){ + this._originalPosition.x = x; + cc.Sprite.prototype.setPositionX.call(this, x); + }, + + setPositionY:function(y){ + this._originalPosition.y = y; + cc.Sprite.prototype.setPositionY.call(this, y); + }, + getPosition:function(){ return cc.p(this._originalPosition.x, this._originalPosition.y); }, From 6cef2e99fd5beb63eae555493c825e92ef7b53e6 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Wed, 11 Sep 2013 18:17:28 +0800 Subject: [PATCH 105/141] issue #2772 update samples commit --- samples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples b/samples index edbbf529dc..b2940ff14b 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit edbbf529dcb6369ba0ec7cd396adb6db3a821680 +Subproject commit b2940ff14bb0efa8dd9006182e19b804bea03eae From baceeb645816db120e5b3f0cfa79eadc1de42ec0 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 10:15:41 +0800 Subject: [PATCH 106/141] fixed #2801: Remove cc.RectMake . Use cc.rect instead. --- cocos2d/cocoa/CCGeometry.js | 1 + cocos2d/label_nodes/CCLabelBMFont.js | 2 +- cocos2d/platform/CCEGLView.js | 2 +- cocos2d/sprite_nodes/CCSprite.js | 2 +- extensions/CCBReader/CCBReader.js | 2 +- extensions/CCBReader/CCNodeLoader.js | 2 +- extensions/CCEditBox.js | 2 +- extensions/GUI/CCControlExtension/CCControlSlider.js | 2 +- extensions/GUI/CCControlExtension/CCScale9Sprite.js | 4 ++-- extensions/GUI/CCScrollView/CCScrollView.js | 6 +++--- 10 files changed, 13 insertions(+), 12 deletions(-) diff --git a/cocos2d/cocoa/CCGeometry.js b/cocos2d/cocoa/CCGeometry.js index 6cca20be8a..ae9293d8a5 100644 --- a/cocos2d/cocoa/CCGeometry.js +++ b/cocos2d/cocoa/CCGeometry.js @@ -237,6 +237,7 @@ cc.Rect = function (x1, y1, width1, height1) { * @return {cc.Rect} */ cc.RectMake = function (x, y, width, height) { + cc.log("cc.RectMake will be deprecated sooner or later. Use cc.rect instead."); return cc.rect(x, y, width, height); }; diff --git a/cocos2d/label_nodes/CCLabelBMFont.js b/cocos2d/label_nodes/CCLabelBMFont.js index 2e430c64dc..7b9f3c0319 100644 --- a/cocos2d/label_nodes/CCLabelBMFont.js +++ b/cocos2d/label_nodes/CCLabelBMFont.js @@ -725,7 +725,7 @@ cc.LabelBMFont = cc.SpriteBatchNode.extend(/** @lends cc.LabelBMFont# */{ this._opacityModifyRGB = locTexture.hasPremultipliedAlpha(); this._reusedChar = new cc.Sprite(); - this._reusedChar.initWithTexture(locTexture, cc.RectMake(0, 0, 0, 0), false); + this._reusedChar.initWithTexture(locTexture, cc.rect(0, 0, 0, 0), false); this._reusedChar.setBatchNode(this); } this.setString(theString,true); diff --git a/cocos2d/platform/CCEGLView.js b/cocos2d/platform/CCEGLView.js index c551ced119..ed8979c11f 100644 --- a/cocos2d/platform/CCEGLView.js +++ b/cocos2d/platform/CCEGLView.js @@ -416,7 +416,7 @@ cc.EGLView = cc.Class.extend(/** @lends cc.EGLView# */{ getScissorRect:function () { var gl = cc.renderContext, scaleX = this._scaleX, scaleY = this._scaleY; var boxArr = gl.getParameter(gl.SCISSOR_BOX); - return cc.RectMake((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / this._scaleY, + return cc.rect((boxArr[0] - this._viewPortRect.x) / scaleX, (boxArr[1] - this._viewPortRect.y) / this._scaleY, boxArr[2] / scaleX, boxArr[3] / scaleY); }, diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 6c0b3e5fdf..bf14f88cfc 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1704,7 +1704,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.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.RectMake(0, 0, 57, 57)); + * var sprite = cc.Sprite.createWithTexture(batch.getTexture(), cc.rect(0, 0, 57, 57)); * batch.addChild(sprite); * layer.addChild(batch); */ diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index 142da066c3..5b4746f008 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -643,7 +643,7 @@ cc.BuilderReader = cc.Class.extend({ spriteFile = this._ccbRootPath + spriteFile; var texture = cc.TextureCache.getInstance().addImage(spriteFile); var locContentSize = texture.getContentSize(); - var bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); + var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height); value = cc.SpriteFrame.createWithTexture(texture, bounds); } else { spriteSheet = this._ccbRootPath + spriteSheet; diff --git a/extensions/CCBReader/CCNodeLoader.js b/extensions/CCBReader/CCNodeLoader.js index d13df20fe2..2bdbb32ddc 100644 --- a/extensions/CCBReader/CCNodeLoader.js +++ b/extensions/CCBReader/CCNodeLoader.js @@ -485,7 +485,7 @@ cc.NodeLoader = cc.Class.extend({ var texture = cc.TextureCache.getInstance().addImage(spriteFile); var locContentSize = texture.getContentSize(); - var bounds = cc.RectMake(0, 0, locContentSize.width, locContentSize.height); + var bounds = cc.rect(0, 0, locContentSize.width, locContentSize.height); spriteFrame = cc.SpriteFrame.createWithTexture(texture, bounds); } else { var frameCache = cc.SpriteFrameCache.getInstance(); diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index 1bb6a3ba3c..99c970af74 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -497,7 +497,7 @@ cc.EditBox = cc.ControlButton.extend({ cc.EditBox.getRect = function (node) { var contentSize = node.getContentSize(); - var rect = cc.RectMake(0, 0, contentSize.width, contentSize.height); + var rect = cc.rect(0, 0, contentSize.width, contentSize.height); return cc.RectApplyAffineTransform(rect, node.nodeToWorldTransform()); }; diff --git a/extensions/GUI/CCControlExtension/CCControlSlider.js b/extensions/GUI/CCControlExtension/CCControlSlider.js index bf93540ff3..1c2b303307 100644 --- a/extensions/GUI/CCControlExtension/CCControlSlider.js +++ b/extensions/GUI/CCControlExtension/CCControlSlider.js @@ -224,7 +224,7 @@ cc.ControlSlider = cc.Control.extend({ // Stretches content proportional to newLevel var textureRect = this._progressSprite.getTextureRect(); - textureRect = cc.RectMake(textureRect.x, textureRect.y, pos.x, textureRect.height); + textureRect = cc.rect(textureRect.x, textureRect.y, pos.x, textureRect.height); this._progressSprite.setTextureRect(textureRect, this._progressSprite.isTextureRectRotated(), textureRect.size); }, /** Returns the value for the given location. */ diff --git a/extensions/GUI/CCControlExtension/CCScale9Sprite.js b/extensions/GUI/CCControlExtension/CCScale9Sprite.js index 5dc3b2ed72..5daab20170 100644 --- a/extensions/GUI/CCControlExtension/CCScale9Sprite.js +++ b/extensions/GUI/CCControlExtension/CCScale9Sprite.js @@ -87,10 +87,10 @@ cc.Scale9Sprite = cc.Node.extend(/** @lends cc.Scale9Sprite# */{ if (locInsetLeft === 0 && locInsetTop === 0 && locInsetRight === 0 && locInsetBottom === 0) { insets = cc.RectZero(); } else { - insets = this._spriteFrameRotated ? cc.RectMake(locInsetBottom, locInsetLeft, + insets = this._spriteFrameRotated ? cc.rect(locInsetBottom, locInsetLeft, locSpriteRect.width - locInsetRight - locInsetLeft, locSpriteRect.height - locInsetTop - locInsetBottom) : - cc.RectMake(locInsetLeft, locInsetTop, + cc.rect(locInsetLeft, locInsetTop, locSpriteRect.width - locInsetLeft - locInsetRight, locSpriteRect.height - locInsetTop - locInsetBottom); } diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index 2d2180a775..b16dfd52d9 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -272,7 +272,7 @@ cc.ScrollView = cc.Layer.extend({ var size = this.getViewSize(); var scale = this.getZoomScale(); - var viewRect = cc.RectMake(-offset.x / scale, -offset.y / scale, size.width / scale, size.height / scale); + var viewRect = cc.rect(-offset.x / scale, -offset.y / scale, size.width / scale, size.height / scale); return cc.rectIntersectsRect(viewRect, node.getBoundingBox()); }, @@ -372,7 +372,7 @@ cc.ScrollView = cc.Layer.extend({ if (!this.isVisible()) return false; //var frameOriginal = this.getParent().convertToWorldSpace(this.getPosition()); - //var frame = cc.RectMake(frameOriginal.x, frameOriginal.y, this._viewSize.width, this._viewSize.height); + //var frame = cc.rect(frameOriginal.x, frameOriginal.y, this._viewSize.width, this._viewSize.height); var frame = this._getViewRect(); //dispatcher does not know about clipping. reject touches outside visible bounds. @@ -411,7 +411,7 @@ cc.ScrollView = cc.Layer.extend({ if (this._touches.length === 1 && this._dragging) { // scrolling this._touchMoved = true; //var frameOriginal = this.getParent().convertToWorldSpace(this.getPosition()); - //var frame = cc.RectMake(frameOriginal.x, frameOriginal.y, this._viewSize.width, this._viewSize.height); + //var frame = cc.rect(frameOriginal.x, frameOriginal.y, this._viewSize.width, this._viewSize.height); var frame = this._getViewRect(); //var newPoint = this.convertTouchToNodeSpace(this._touches[0]); From c2c93551716bac98c592c5b535ebed40dfd9a31a Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 10:22:42 +0800 Subject: [PATCH 107/141] fixed #2801: Remove cc.SizeMake . Use cc.size instead. --- cocos2d/actions/CCActionTiledGrid.js | 8 ++++---- cocos2d/cocoa/CCGeometry.js | 1 + cocos2d/label_nodes/CCLabelTTF.js | 2 +- cocos2d/layers_scenes_transitions_nodes/CCTransition.js | 4 ++-- .../CCTransitionPageTurn.js | 2 +- extensions/GUI/CCControlExtension/CCControlSlider.js | 2 +- extensions/GUI/CCControlExtension/CCMenuPassive.js | 8 ++++---- extensions/GUI/CCScrollView/CCScrollView.js | 2 +- extensions/GUI/CCScrollView/CCTableView.js | 4 ++-- 9 files changed, 17 insertions(+), 16 deletions(-) diff --git a/cocos2d/actions/CCActionTiledGrid.js b/cocos2d/actions/CCActionTiledGrid.js index 4cd0a55bce..2a05c4d451 100644 --- a/cocos2d/actions/CCActionTiledGrid.js +++ b/cocos2d/actions/CCActionTiledGrid.js @@ -260,7 +260,7 @@ cc.ShuffleTiles = cc.TiledGrid3DAction.extend(/** @lends cc.ShuffleTiles# */{ getDelta:function (pos) { var locGridSize = this._gridSize; var idx = pos.width * locGridSize.height + pos.height; - return cc.SizeMake(((this._tilesOrder[idx] / locGridSize.height) - pos.width), + return cc.size(((this._tilesOrder[idx] / locGridSize.height) - pos.width), ((this._tilesOrder[idx] % locGridSize.height) - pos.height)); }, @@ -316,7 +316,7 @@ cc.ShuffleTiles = cc.TiledGrid3DAction.extend(/** @lends cc.ShuffleTiles# */{ locTiles[tileIndex] = new cc.Tile(); locTiles[tileIndex].position = cc.p(i, j); locTiles[tileIndex].startPosition = cc.p(i, j); - locTiles[tileIndex].delta = this.getDelta(cc.SizeMake(i, j)); + locTiles[tileIndex].delta = this.getDelta(cc.size(i, j)); ++tileIndex; } } @@ -891,7 +891,7 @@ cc.SplitRows = cc.TiledGrid3DAction.extend(/** @lends cc.SplitRows# */{ */ initWithDuration:function (duration, rows) { this._rows = rows; - return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.SizeMake(1, rows)); + return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.size(1, rows)); }, update:function (time) { @@ -954,7 +954,7 @@ cc.SplitCols = cc.TiledGrid3DAction.extend(/** @lends cc.SplitCols# */{ */ initWithDuration:function (duration, cols) { this._cols = cols; - return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.SizeMake(cols, 1)); + return cc.TiledGrid3DAction.prototype.initWithDuration.call(this, duration, cc.size(cols, 1)); }, update:function (time) { diff --git a/cocos2d/cocoa/CCGeometry.js b/cocos2d/cocoa/CCGeometry.js index ae9293d8a5..919767c811 100644 --- a/cocos2d/cocoa/CCGeometry.js +++ b/cocos2d/cocoa/CCGeometry.js @@ -134,6 +134,7 @@ cc.Size = function (_width, _height) { * @return {cc.Size} */ cc.SizeMake = function (width, height) { + cc.log("cc.SizeMake will be deprecated sooner or later. Use cc.size instead."); return cc.size(width, height); }; diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index ff58ab96ba..3549e19e37 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -418,7 +418,7 @@ cc.LabelTTF = cc.Sprite.extend(/** @lends cc.LabelTTF# */{ texDef.fontDimensions = cc.SIZE_POINTS_TO_PIXELS(this._dimensions); } else { texDef.fontSize = this._fontSize; - texDef.fontDimensions = cc.SizeMake(this._dimensions.width, this._dimensions.height); + texDef.fontDimensions = cc.size(this._dimensions.width, this._dimensions.height); } texDef.fontName = this._fontName; diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 96b5e330c6..20299113f9 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -1420,7 +1420,7 @@ cc.TransitionTurnOffTiles = cc.TransitionScene.extend(/** @lends cc.TransitionTu var aspect = winSize.width / winSize.height; var x = 0 | (12 * aspect); var y = 12; - var toff = cc.TurnOffTiles.create(this._duration, cc.SizeMake(x, y)); + var toff = cc.TurnOffTiles.create(this._duration, cc.size(x, y)); var action = this.easeActionWithAction(toff); this._outScene.runAction(cc.Sequence.create(action, cc.CallFunc.create(this.finish, this), cc.StopGrid.create())); }, @@ -1559,7 +1559,7 @@ cc.TransitionFadeTR = cc.TransitionScene.extend(/** @lends cc.TransitionFadeTR# var x = 0 | (12 * aspect); var y = 12; - var action = this.actionWithSize(cc.SizeMake(x, y)); + var action = this.actionWithSize(cc.size(x, y)); this._outScene.runAction( cc.Sequence.create(this.easeActionWithAction(action), cc.CallFunc.create(this.finish, this), cc.StopGrid.create()) diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js index f5c8d2546f..896e444fcd 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js @@ -86,7 +86,7 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu y = 16; } - var action = this.actionWithSize(cc.SizeMake(x, y)); + var action = this.actionWithSize(cc.size(x, y)); if (!this._back) { this._outScene.runAction( cc.Sequence.create(action,cc.CallFunc.create(this.finish, this),cc.StopGrid.create())); diff --git a/extensions/GUI/CCControlExtension/CCControlSlider.js b/extensions/GUI/CCControlExtension/CCControlSlider.js index 1c2b303307..33b47b644b 100644 --- a/extensions/GUI/CCControlExtension/CCControlSlider.js +++ b/extensions/GUI/CCControlExtension/CCControlSlider.js @@ -140,7 +140,7 @@ cc.ControlSlider = cc.Control.extend({ // Defines the content size var maxRect = cc.ControlUtils.CCRectUnion(backgroundSprite.getBoundingBox(), thumbSprite.getBoundingBox()); - var size = cc.SizeMake(maxRect.width, maxRect.height); + var size = cc.size(maxRect.width, maxRect.height); this.setContentSize(size); // Add the slider background diff --git a/extensions/GUI/CCControlExtension/CCMenuPassive.js b/extensions/GUI/CCControlExtension/CCMenuPassive.js index 5ffa14cb4e..a608ecd72a 100644 --- a/extensions/GUI/CCControlExtension/CCMenuPassive.js +++ b/extensions/GUI/CCControlExtension/CCMenuPassive.js @@ -27,14 +27,14 @@ cc.Spacer = cc.Layer.extend({}); cc.Spacer.verticalSpacer = function (space) { var pRet = new cc.Spacer(); pRet.init(); - pRet.setContentSize(cc.SizeMake(0, space)); + pRet.setContentSize(cc.size(0, space)); return pRet; }; cc.Spacer.horizontalSpacer = function (space) { var pRet = new cc.Spacer(); pRet.init(); - pRet.setContentSize(cc.SizeMake(space, 0)); + pRet.setContentSize(cc.size(space, 0)); return pRet; }; @@ -141,7 +141,7 @@ cc.MenuPassive = cc.Layer.extend({ } } } - this.setContentSize(cc.SizeMake(width, height)); + this.setContentSize(cc.size(width, height)); }, /** align items horizontally */ @@ -174,7 +174,7 @@ cc.MenuPassive = cc.Layer.extend({ } } } - this.setContentSize(cc.SizeMake(width, height)); + this.setContentSize(cc.size(width, height)); }, /** align items in rows of columns */ diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index b16dfd52d9..6dd2b270f2 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -97,7 +97,7 @@ cc.ScrollView = cc.Layer.extend({ }, init:function () { - return this.initWithViewSize(cc.SizeMake(200, 200), null); + return this.initWithViewSize(cc.size(200, 200), null); }, registerWithTouchDispatcher:function () { diff --git a/extensions/GUI/CCScrollView/CCTableView.js b/extensions/GUI/CCScrollView/CCTableView.js index 67003ebe76..2156eda1f7 100644 --- a/extensions/GUI/CCScrollView/CCTableView.js +++ b/extensions/GUI/CCScrollView/CCTableView.js @@ -231,10 +231,10 @@ cc.TableView = cc.ScrollView.extend({ switch (this.getDirection()) { case cc.SCROLLVIEW_DIRECTION_HORIZONTAL: - size = cc.SizeMake(cellCount * cellSize.width, cellSize.height); + size = cc.size(cellCount * cellSize.width, cellSize.height); break; default: - size = cc.SizeMake(cellSize.width, cellCount * cellSize.height); + size = cc.size(cellSize.width, cellCount * cellSize.height); break; } this.setContentSize(size); From 4ad32c82ccf5f8a0150789a9fe132f12acf2b656 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 10:26:21 +0800 Subject: [PATCH 108/141] fixed #2801: Remove cc.PointMake . Use cc.p instead. --- cocos2d/cocoa/CCGeometry.js | 1 + .../CCControlExtension/CCControlSaturationBrightnessPicker.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/cocoa/CCGeometry.js b/cocos2d/cocoa/CCGeometry.js index 919767c811..503fe76d42 100644 --- a/cocos2d/cocoa/CCGeometry.js +++ b/cocos2d/cocoa/CCGeometry.js @@ -47,6 +47,7 @@ cc.Point = function (_x, _y) { * @return {cc.Point} */ cc.PointMake = function (x, y) { + cc.log("cc.PointMake will be deprecated sooner or later. Use cc.p instead."); return new cc.Point(x, y); }; diff --git a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js b/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js index 7957a55e83..c6ceb37226 100644 --- a/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js +++ b/extensions/GUI/CCControlExtension/CCControlSaturationBrightnessPicker.js @@ -102,7 +102,7 @@ cc.ControlSaturationBrightnessPicker = cc.Control.extend({ }, updateDraggerWithHSV:function (hsv) { // Set the position of the slider to the correct saturation and brightness - var pos = cc.PointMake(this._startPos.x + this._boxPos + (this._boxSize * (1 - hsv.s)), + var pos = cc.p(this._startPos.x + this._boxPos + (this._boxSize * (1 - hsv.s)), this._startPos.y + this._boxPos + (this._boxSize * hsv.v)); // update From 99eb548baba199db954652666c3a1ebcbe52b613 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 11:06:08 +0800 Subject: [PATCH 109/141] fixed #2801: Change local variable from _actionManager to _animationManager. --- extensions/CCBReader/CCBReader.js | 46 +++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/extensions/CCBReader/CCBReader.js b/extensions/CCBReader/CCBReader.js index 5b4746f008..c8c02c74b2 100644 --- a/extensions/CCBReader/CCBReader.js +++ b/extensions/CCBReader/CCBReader.js @@ -135,7 +135,7 @@ cc.BuilderReader = cc.Class.extend({ _loadedSpriteSheets:null, _owner:null, - _actionManager:null, + _animationManager:null, _animationManagers:null, _animatedProps:null, @@ -196,7 +196,7 @@ cc.BuilderReader = cc.Class.extend({ initWithData:function (data, owner) { //setup action manager - this._actionManager = new cc.BuilderAnimationManager(); + this._animationManager = new cc.BuilderAnimationManager(); //setup byte array //Array replace to CCData in Javascript @@ -208,7 +208,7 @@ cc.BuilderReader = cc.Class.extend({ this._owner = owner; //setup resolution scale and container size - this._actionManager.setRootContainerSize(cc.Director.getInstance().getWinSize()); + this._animationManager.setRootContainerSize(cc.Director.getInstance().getWinSize()); return true; }, @@ -229,9 +229,9 @@ cc.BuilderReader = cc.Class.extend({ readNodeGraphFromData:function (data, owner, parentSize) { this.initWithData(data, owner); - var locActionManager = this._actionManager; - locActionManager.setRootContainerSize(parentSize); - locActionManager.setOwner(owner); + var locAnimationManager = this._animationManager; + locAnimationManager.setRootContainerSize(parentSize); + locAnimationManager.setOwner(owner); this._ownerOutletNames = []; this._ownerOutletNodes = []; @@ -241,20 +241,20 @@ cc.BuilderReader = cc.Class.extend({ var nodeGraph = this.readFileWithCleanUp(true); - if (nodeGraph && locActionManager.getAutoPlaySequenceId() != -1) { + if (nodeGraph && locAnimationManager.getAutoPlaySequenceId() != -1) { //auto play animations - locActionManager.runAnimations(locActionManager.getAutoPlaySequenceId(), 0); + locAnimationManager.runAnimations(locAnimationManager.getAutoPlaySequenceId(), 0); } if (this._jsControlled) { var locNodes = []; var locAnimations = []; - var locAnimationManager = this._animationManagers; - var getAllKeys = locAnimationManager.allKeys(); + var locAnimationManagers = this._animationManagers; + var getAllKeys = locAnimationManagers.allKeys(); for (var i = 0; i < getAllKeys.length; i++) { locNodes.push(getAllKeys[i]); - locAnimations.push(locAnimationManager.objectForKey(getAllKeys[i])); + locAnimations.push(locAnimationManagers.objectForKey(getAllKeys[i])); } this._nodesWithAnimationManagers = locNodes; @@ -280,11 +280,11 @@ cc.BuilderReader = cc.Class.extend({ }, getAnimationManager:function () { - return this._actionManager; + return this._animationManager; }, setAnimationManager:function (animationManager) { - this._actionManager = animationManager; + this._animationManager = animationManager; }, getAnimatedProperties:function () { @@ -478,15 +478,15 @@ cc.BuilderReader = cc.Class.extend({ }, addDocumentCallbackName:function (name) { - this._actionManager.addDocumentCallbackName(name); + this._animationManager.addDocumentCallbackName(name); }, addDocumentCallbackNode:function (node) { - this._actionManager.addDocumentCallbackNode(node); + this._animationManager.addDocumentCallbackNode(node); }, addDocumentCallbackControlEvents:function(controlEvents){ - this._actionManager.addDocumentCallbackControlEvents(controlEvents); + this._animationManager.addDocumentCallbackControlEvents(controlEvents); }, readFileWithCleanUp:function (cleanUp) { @@ -498,7 +498,7 @@ cc.BuilderReader = cc.Class.extend({ return null; var node = this._readNodeGraph(); - this._animationManagers.setObject(this._actionManager, node); + this._animationManagers.setObject(this._animationManager, node); if (cleanUp) this._cleanUpNodeGraph(node); @@ -531,7 +531,7 @@ cc.BuilderReader = cc.Class.extend({ return true; var channel = new cc.BuilderSequenceProperty(); - var locJsControlled = this._jsControlled, locActionManager = this._actionManager, locKeyframes = channel.getKeyframes(); + var locJsControlled = this._jsControlled, locAnimationManager = this._animationManager, locKeyframes = channel.getKeyframes(); for (var i = 0; i < numKeyframes; i++) { var time = this.readFloat(); var callbackName = this.readCachedString(); @@ -544,7 +544,7 @@ cc.BuilderReader = cc.Class.extend({ keyframe.setValue(value); if(locJsControlled) - locActionManager.getKeyframeCallbacks().push(callbackType+":"+callbackName); + locAnimationManager.getKeyframeCallbacks().push(callbackType+":"+callbackName); locKeyframes.push(keyframe); } @@ -583,7 +583,7 @@ cc.BuilderReader = cc.Class.extend({ return true; }, _readSequences:function () { - var sequences = this._actionManager.getSequences(); + var sequences = this._animationManager.getSequences(); var numSeqs = this.readInt(false); for (var i = 0; i < numSeqs; i++) { var seq = new cc.BuilderSequence(); @@ -599,7 +599,7 @@ cc.BuilderReader = cc.Class.extend({ sequences.push(seq); } - this._actionManager.setAutoPlaySequenceId(this.readInt(true)); + this._animationManager.setAutoPlaySequenceId(this.readInt(true)); return true; }, @@ -682,7 +682,7 @@ cc.BuilderReader = cc.Class.extend({ } this._jsControlled = this.readBool(); - this._actionManager._jsControlled = this._jsControlled; + this._animationManager._jsControlled = this._jsControlled; // no need to set if it is "jscontrolled". It is obvious. return true; }, @@ -730,7 +730,7 @@ cc.BuilderReader = cc.Class.extend({ /* Read class name. */ var className = this.readCachedString(); - var jsControlledName, locJsControlled = this._jsControlled, locActionManager = this._actionManager; + var jsControlledName, locJsControlled = this._jsControlled, locActionManager = this._animationManager; if (locJsControlled) jsControlledName = this.readCachedString(); From 56f96e2beec091fc2d36177d40065429582543ff Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 11:34:35 +0800 Subject: [PATCH 110/141] fixed #2801: Rename tileAt to getTileAt. --- cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js | 2 +- cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js b/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js index cd23fae034..09147115d5 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXTiledMap.js @@ -55,7 +55,7 @@ cc.TMX_ORIENTATION_ISO = 2; * *

Features:
* - Each tile will be treated as an cc.Sprite
- * - The sprites are created on demand. They will be created only when you call "layer.tileAt(position)"
+ * - The sprites are created on demand. They will be created only when you call "layer.getTileAt(position)"
* - Each tile can be rotated / moved / scaled / tinted / "opacitied", since each tile is a cc.Sprite
* - Tiles can be added/removed in runtime
* - The z-order of the tiles can be modified in runtime
diff --git a/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js b/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js index d2efa47a2f..969c85a693 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js +++ b/cocos2d/tileMap_parallax_nodes/CCTileMapAtlas.js @@ -97,7 +97,7 @@ cc.TileMapAtlas = cc.AtlasNode.extend(/** @lends cc.TileMapAtlas# */{ * @param {cc.Point} position * @return {cc.Color3B} */ - tileAt:function (position) { + getTileAt:function (position) { cc.Assert(this._TGAInfo != null, "tgaInfo must not be nil"); cc.Assert(position.x < this._TGAInfo.width, "Invalid position.x"); cc.Assert(position.y < this._TGAInfo.height, "Invalid position.y"); From 6a670c1eeea391e7c2bba055f635ec599b6046e5 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 11:43:07 +0800 Subject: [PATCH 111/141] fixed #2801: Rename Sequence.initOneTwo to Sequence.initWithTwoActions --- cocos2d/actions/CCActionInterval.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index e5096a74f0..b9204e518c 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -181,9 +181,9 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ * @param {cc.FiniteTimeAction} actionTwo * @return {Boolean} */ - initOneTwo:function (actionOne, actionTwo) { - cc.Assert(actionOne != null, "Sequence.initOneTwo"); - cc.Assert(actionTwo != null, "Sequence.initOneTwo"); + initWithTwoActions:function (actionOne, actionTwo) { + cc.Assert(actionOne != null, "Sequence.initWithTwoActions"); + cc.Assert(actionTwo != null, "Sequence.initWithTwoActions"); var d = actionOne.getDuration() + actionTwo.getDuration(); this.initWithDuration(d); @@ -199,7 +199,7 @@ cc.Sequence = cc.ActionInterval.extend(/** @lends cc.Sequence# */{ */ clone:function () { var action = new cc.Sequence(); - action.initOneTwo(this._actions[0].clone(), this._actions[1].clone()); + action.initWithTwoActions(this._actions[0].clone(), this._actions[1].clone()); return action; }, @@ -317,7 +317,7 @@ cc.Sequence.create = function (/*Multiple Arguments*/tempArray) { */ cc.Sequence._actionOneTwo = function (actionOne, actionTwo) { var sequence = new cc.Sequence(); - sequence.initOneTwo(actionOne, actionTwo); + sequence.initWithTwoActions(actionOne, actionTwo); return sequence; }; @@ -599,7 +599,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ * @param {cc.FiniteTimeAction} action2 * @return {Boolean} */ - initOneTwo:function (action1, action2) { + initWithTwoActions:function (action1, action2) { cc.Assert(action1 != null, "no action1"); cc.Assert(action2 != null, "no action2"); @@ -629,7 +629,7 @@ cc.Spawn = cc.ActionInterval.extend(/** @lends cc.Spawn# */{ */ clone:function () { var action = new cc.Spawn(); - action.initOneTwo(this._one.clone(), this._two.clone()); + action.initWithTwoActions(this._one.clone(), this._two.clone()); return action; }, @@ -697,7 +697,7 @@ cc.Spawn.create = function (/*Multiple Arguments*/tempArray) { */ cc.Spawn._actionOneTwo = function (action1, action2) { var pSpawn = new cc.Spawn(); - pSpawn.initOneTwo(action1, action2); + pSpawn.initWithTwoActions(action1, action2); return pSpawn; }; From 26b7e98c756e2d675b57a9ace81bad107dd19ab3 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 14:11:06 +0800 Subject: [PATCH 112/141] fixed #2801: add setFontName/setFontSize/setPlaceholderFontName/setPlaceholderFontSize for EditBox . --- extensions/CCEditBox.js | 54 +++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/extensions/CCEditBox.js b/extensions/CCEditBox.js index 99c970af74..9524b3a38a 100644 --- a/extensions/CCEditBox.js +++ b/extensions/CCEditBox.js @@ -281,13 +281,32 @@ cc.EditBox = cc.ControlButton.extend({ setFont: function (fontName, fontSize) { this._edFontSize = fontSize; this._edFontName = fontName; - if (this._edTxt.value == this._placeholderText) - this._setFontToEditBox(); + this._setFontToEditBox(); + }, + + /** + * set fontName + * @param {String} fontName + */ + setFontName: function(fontName){ + this._edFontName = fontName; + this._setFontToEditBox(); + }, + + /** + * set fontSize + * @param {Number} fontSize + */ + setFontSize: function(fontSize){ + this._edFontSize = fontSize; + this._setFontToEditBox(); }, _setFontToEditBox: function () { - this._edTxt.style.fontFamily = this._placeholderFontName; - this._edTxt.style.fontSize = this._placeholderFontSize; + if (this._edTxt.value != this._placeholderText){ + this._edTxt.style.fontFamily = this._edFontName; + this._edTxt.style.fontSize = this._edFontSize+"px"; + } }, /** @@ -363,13 +382,32 @@ cc.EditBox = cc.ControlButton.extend({ setPlaceholderFont: function (fontName, fontSize) { this._placeholderFontName = fontName; this._placeholderFontSize = fontSize; - if (this._edTxt.value == this._placeholderText) - this._setPlaceholderFontToEditText(); + this._setPlaceholderFontToEditText(); + }, + + /** + * Set the placeholder's fontName. + * @param {String} fontName + */ + setPlaceholderFont: function (fontName) { + this._placeholderFontName = fontName; + this._setPlaceholderFontToEditText(); + }, + + /** + * Set the placeholder's fontSize. + * @param {Number} fontSize + */ + setPlaceholderFont: function (fontSize) { + this._placeholderFontSize = fontSize; + this._setPlaceholderFontToEditText(); }, _setPlaceholderFontToEditText: function () { - this._edTxt.style.fontFamily = this._placeholderFontName; - this._edTxt.style.fontSize = this._placeholderFontSize; + if (this._edTxt.value == this._placeholderText){ + this._edTxt.style.fontFamily = this._placeholderFontName; + this._edTxt.style.fontSize = this._placeholderFontSize + "px"; + } }, /** From 5d3436754e35ccc0d7a899e18305e9cbb7c26fae Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 14:19:43 +0800 Subject: [PATCH 113/141] closed #2801: add preloadMusic/preloadEffect for SimpleAudioEngine. --- CocosDenshion/SimpleAudioEngine.js | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CocosDenshion/SimpleAudioEngine.js b/CocosDenshion/SimpleAudioEngine.js index 76acc46b61..d31fe46b51 100644 --- a/CocosDenshion/SimpleAudioEngine.js +++ b/CocosDenshion/SimpleAudioEngine.js @@ -158,6 +158,22 @@ cc.SimpleAudioEngine = cc.AudioEngine.extend(/** @lends cc.SimpleAudioEngine# */ return this._soundSupported; }, + /** + * Preload music resource. + * @param {String} path + */ + preloadMusic:function(path){ + this.preloadSound(path); + }, + + /** + * Preload effect resource. + * @param {String} path + */ + preloadEffect:function(path){ + this.preloadSound(path); + }, + /** * Preload music resource.
* This method is called when cc.Loader preload resources. @@ -766,6 +782,22 @@ cc.WebAudioEngine = cc.AudioEngine.extend(/** @lends cc.WebAudioEngine# */{ req.send(); }, + /** + * Preload music resource. + * @param {String} path + */ + preloadMusic:function(path){ + this.preloadSound(path); + }, + + /** + * Preload effect resource. + * @param {String} path + */ + preloadEffect:function(path){ + this.preloadSound(path); + }, + /** * Preload music resource.
* This method is called when cc.Loader preload resources. From 5ead84dbe520d2136d90caad6cbd493ee766ef34 Mon Sep 17 00:00:00 2001 From: NeroChan Date: Thu, 12 Sep 2013 15:11:45 +0800 Subject: [PATCH 114/141] fixed #2798 : disable webgl on mobile browser --- template/res/HD/HelloWorld.jpg | Bin 0 -> 55905 bytes template/res/HD/HelloWorld.png | Bin 326763 -> 0 bytes template/res/Normal/HelloWorld.jpg | Bin 0 -> 55938 bytes template/res/Normal/HelloWorld.png | Bin 108713 -> 0 bytes template/src/resource.js | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 template/res/HD/HelloWorld.jpg delete mode 100644 template/res/HD/HelloWorld.png create mode 100644 template/res/Normal/HelloWorld.jpg delete mode 100644 template/res/Normal/HelloWorld.png diff --git a/template/res/HD/HelloWorld.jpg b/template/res/HD/HelloWorld.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b886487f38eff0fe040e726b63ef893c59a4f522 GIT binary patch literal 55905 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%0DA%}CAZ^hi5toi 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�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 z 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 {=xyt5G;j|^(R0=KftH5!q&q; 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¬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�c7A@Q-6Fby7YAz9bK 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�A&_bA43Cw$%``52G3XoP?S*-#quK+_QL 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 jERoBcsf45d|b;s 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 sIxY*(kKIaR2}S literal 0 HcmV?d00001 diff --git a/template/res/Normal/HelloWorld.png b/template/res/Normal/HelloWorld.png deleted file mode 100644 index 03bf58b66c53522d8b457b3580d4f7bd309473dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 108713 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


MSa|nf3N{*W;G5J*f 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 Date: Thu, 12 Sep 2013 15:53:47 +0800 Subject: [PATCH 115/141] fixed #2795: Fix a bug of cc.Node that nodeToWorldTransform returns wrong value on Canvas Mode --- cocos2d/base_nodes/CCNode.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index d28c3a9c97..f51b32f678 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -1886,8 +1886,6 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ this._additionalTransformDirty = false; } - t.tx = t.tx | 0; - t.ty = t.ty | 0; this._transformDirty = false; } return this._transform; From 084b719a7abbbab75b7f03bde4544fb3e9332a50 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Thu, 12 Sep 2013 16:26:12 +0800 Subject: [PATCH 116/141] fixed #2795 fixed bug for _calculateLayerOffset. --- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index f30680f79f..5402ad5056 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -636,7 +636,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ (this._mapTileSize.height / 2 ) * (-pos.x - pos.y)); break; case cc.TMX_ORIENTATION_HEX: - cc.Assert(cc._rectEqualToZero(pos), "offset for hexagonal map not implemented yet"); + cc.Assert((pos.x == 0 && pos.y == 0), "offset for hexagonal map not implemented yet"); break; } return ret; From 2512c9e06d966caa9ed91c0bc0fbb2cdbb47b7f2 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Fri, 13 Sep 2013 10:01:51 +0800 Subject: [PATCH 117/141] fixed #2795: Fix a bug of cc.PhysicsSprite that nodeToWorldTransform returns wrong value on Canvas Mode --- cocos2d/physics_nodes/CCPhysicsSprite.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cocos2d/physics_nodes/CCPhysicsSprite.js b/cocos2d/physics_nodes/CCPhysicsSprite.js index e937777941..c50c9ada60 100644 --- a/cocos2d/physics_nodes/CCPhysicsSprite.js +++ b/cocos2d/physics_nodes/CCPhysicsSprite.js @@ -202,14 +202,14 @@ // base abcd t.a = t.d = Cos; - t.c = -Sin; - t.b = Sin; + t.b = -Sin; + t.c = Sin; // scale if (locScaleX !== 1 || locScaleY !== 1) { t.a *= locScaleX; - t.b *= locScaleX; - t.c *= locScaleY; + t.c *= locScaleX; + t.b *= locScaleY; t.d *= locScaleY; } From a8f0d691c0105a8d015443a4e241b8bca28d792a Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 13 Sep 2013 10:31:01 +0800 Subject: [PATCH 118/141] Closed #2802: Sync the APIs of HTML5 to the JSB --- HelloHTML5World/build.xml | 1 - cocos2d/actions/CCActionManager.js | 2 +- cocos2d/build.xml | 1 - .../CCLayer.js | 8 +- cocos2d/menu_nodes/CCMenu.js | 2 +- cocos2d/particle_nodes/CCParticleBatchNode.js | 52 +- cocos2d/particle_nodes/CCParticleExamples.js | 66 +- cocos2d/particle_nodes/CCParticleSystem.js | 777 ++++++++++++++++- .../particle_nodes/CCParticleSystemQuad.js | 819 ------------------ cocos2d/platform/CCTypes.js | 2 +- cocos2d/platform/jsloader.js | 1 - cocos2d/sprite_nodes/CCSprite.js | 3 +- cocos2d/sprite_nodes/CCSpriteFrameCache.js | 2 + .../CCTouchDelegateProtocol.js | 10 +- cocos2d/touch_dispatcher/CCTouchDispatcher.js | 45 +- cocos2d/touch_dispatcher/CCTouchHandler.js | 16 +- extensions/CCBReader/CCNodeLoaderLibrary.js | 2 +- extensions/CCBReader/CCSpriteLoader.js | 8 +- .../Armature/display/CCDisplayFactory.js | 2 +- .../Armature/display/CCDisplayManager.js | 4 +- .../GUI/CCControlExtension/CCControl.js | 2 +- extensions/GUI/CCScrollView/CCScrollView.js | 2 +- template/build.xml | 1 - tools/jsdoc_toolkit/build.xml | 1 - 24 files changed, 865 insertions(+), 964 deletions(-) delete mode 100644 cocos2d/particle_nodes/CCParticleSystemQuad.js diff --git a/HelloHTML5World/build.xml b/HelloHTML5World/build.xml index b41ffc7848..951921bde0 100644 --- a/HelloHTML5World/build.xml +++ b/HelloHTML5World/build.xml @@ -95,7 +95,6 @@ - diff --git a/cocos2d/actions/CCActionManager.js b/cocos2d/actions/CCActionManager.js index fdc80f8f15..ed5c01df78 100644 --- a/cocos2d/actions/CCActionManager.js +++ b/cocos2d/actions/CCActionManager.js @@ -329,7 +329,7 @@ cc.ActionManager = cc.Class.extend({ for (var elt = 0; elt < locTargets.length; elt++) { this._currentTarget = locTargets[elt]; locCurrTarget = this._currentTarget; - this._currentTargetSalvaged = false; + //this._currentTargetSalvaged = false; if (!locCurrTarget.paused) { // The 'actions' CCMutableArray may change while inside this loop. for (locCurrTarget.actionIndex = 0; locCurrTarget.actionIndex < locCurrTarget.actions.length; diff --git a/cocos2d/build.xml b/cocos2d/build.xml index 42fb12afe6..e614520513 100644 --- a/cocos2d/build.xml +++ b/cocos2d/build.xml @@ -95,7 +95,6 @@ - diff --git a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js index 627879292b..9b17d55273 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCLayer.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCLayer.js @@ -81,9 +81,9 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ */ registerWithTouchDispatcher:function () { if (this._touchMode === cc.TOUCH_ALL_AT_ONCE) - cc.Director.getInstance().getTouchDispatcher().addStandardDelegate(this, this._touchPriority); + cc.registerStandardDelegate(this,this._touchPriority); else - cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this._touchPriority, true); + cc.registerTargetedDelegate(this._touchPriority, true, this); }, isMouseEnabled:function () { @@ -140,7 +140,7 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ this.registerWithTouchDispatcher(); } else { // have problems? - cc.Director.getInstance().getTouchDispatcher().removeDelegate(this); + cc.unregisterTouchDelegate(this); } } } @@ -289,7 +289,7 @@ cc.Layer = cc.Node.extend(/** @lends cc.Layer# */{ onExit:function () { var director = cc.Director.getInstance(); if (this._isTouchEnabled) - director.getTouchDispatcher().removeDelegate(this); + cc.unregisterTouchDelegate(this); // remove this layer from the delegates who concern Accelerometer Sensor if (this._isAccelerometerEnabled) diff --git a/cocos2d/menu_nodes/CCMenu.js b/cocos2d/menu_nodes/CCMenu.js index 97b7153f92..f2c5f4bcf4 100644 --- a/cocos2d/menu_nodes/CCMenu.js +++ b/cocos2d/menu_nodes/CCMenu.js @@ -420,7 +420,7 @@ cc.Menu = cc.LayerRGBA.extend(/** @lends cc.Menu# */{ * make the menu clickable */ registerWithTouchDispatcher:function () { - cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this.getTouchPriority(), true); + cc.registerTargetedDelegate(this.getTouchPriority(), true, this); }, /** diff --git a/cocos2d/particle_nodes/CCParticleBatchNode.js b/cocos2d/particle_nodes/CCParticleBatchNode.js index 00a0aee906..947e7ca78c 100644 --- a/cocos2d/particle_nodes/CCParticleBatchNode.js +++ b/cocos2d/particle_nodes/CCParticleBatchNode.js @@ -45,7 +45,7 @@ cc.PARTICLE_DEFAULT_CAPACITY = 500; * If the cc.ParticleSystems are not added to a cc.ParticleBatchNode then an OpenGL ES draw call will be needed for each one, which is less efficient.
* * Limitations:
- * - At the moment only cc.ParticleSystemQuad is supported
+ * - At the moment only cc.ParticleSystem is supported
* - All systems need to be drawn with the same parameters, blend function, aliasing, texture
* * Most efficient usage
@@ -108,13 +108,13 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ /** * Add a child into the cc.ParticleBatchNode - * @param {cc.ParticleSystemQuad} child + * @param {cc.ParticleSystem} child * @param {Number} zOrder * @param {Number} tag */ addChild:function (child, zOrder, tag) { cc.Assert(child != null, "Argument must be non-NULL"); - cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystemQuads as children"); + cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystem as children"); zOrder = (zOrder == null) ? child.getZOrder() : zOrder; tag = (tag == null) ? child.getTag() : tag; @@ -151,20 +151,21 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ */ insertChild:function (pSystem, index) { var totalParticles = pSystem.getTotalParticles(); - var totalQuads = this._textureAtlas.getTotalQuads(); + var locTextureAtlas = this._textureAtlas; + var totalQuads = locTextureAtlas.getTotalQuads(); pSystem.setAtlasIndex(index); - if (totalQuads + totalParticles > this._textureAtlas.getCapacity()) { + if (totalQuads + totalParticles > locTextureAtlas.getCapacity()) { this._increaseAtlasCapacityTo(totalQuads + totalParticles); // after a realloc empty quads of textureAtlas can be filled with gibberish (realloc doesn't perform calloc), insert empty quads to prevent it - this._textureAtlas.fillWithEmptyQuadsFromIndex(this._textureAtlas.getCapacity() - totalParticles, totalParticles); + locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.getCapacity() - totalParticles, totalParticles); } // make room for quads, not necessary for last child if (pSystem.getAtlasIndex() + totalParticles != totalQuads) - this._textureAtlas.moveQuadsFromIndex(index, index + totalParticles); + locTextureAtlas.moveQuadsFromIndex(index, index + totalParticles); // increase totalParticles here for new particles, update method of particlesystem will fill the quads - this._textureAtlas.increaseTotalQuadsWith(totalParticles); + locTextureAtlas.increaseTotalQuadsWith(totalParticles); this._updateAllAtlasIndexes(); }, @@ -177,16 +178,17 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ if (child == null) return; - cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystemQuads as children"); + cc.Assert(child instanceof cc.ParticleSystem, "cc.ParticleBatchNode only supports cc.ParticleSystem as children"); cc.Assert(this._children.indexOf(child) > -1, "cc.ParticleBatchNode doesn't contain the sprite. Can't remove it"); cc.Node.prototype.removeChild.call(this, child, cleanup); + var locTextureAtlas = this._textureAtlas; // remove child helper - this._textureAtlas.removeQuadsAtIndex(child.getAtlasIndex(), child.getTotalParticles()); + locTextureAtlas.removeQuadsAtIndex(child.getAtlasIndex(), child.getTotalParticles()); // after memmove of data, empty the quads at the end of array - this._textureAtlas.fillWithEmptyQuadsFromIndex(this._textureAtlas.getTotalQuads(), child.getTotalParticles()); + locTextureAtlas.fillWithEmptyQuadsFromIndex(locTextureAtlas.getTotalQuads(), child.getTotalParticles()); // paticle could be reused for self rendering child.setBatchNode(null); @@ -224,8 +226,9 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ // Find new AtlasIndex var newAtlasIndex = 0; - for (var i = 0; i < this._children.length; i++) { - var pNode = this._children[i]; + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) { + var pNode = locChildren[i]; if (pNode == child) { newAtlasIndex = child.getAtlasIndex(); break; @@ -307,9 +310,10 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ this._textureAtlas.setTexture(texture); // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it - if (texture && !texture.hasPremultipliedAlpha() && ( this._blendFunc.src == gl.BLEND_SRC && this._blendFunc.dst == gl.BLEND_DST )) { - this._blendFunc.src = gl.SRC_ALPHA; - this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; + var locBlendFunc = this._blendFunc; + if (texture && !texture.hasPremultipliedAlpha() && ( locBlendFunc.src == gl.BLEND_SRC && locBlendFunc.dst == gl.BLEND_DST )) { + locBlendFunc.src = gl.SRC_ALPHA; + locBlendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; } }, @@ -366,8 +370,9 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ _updateAllAtlasIndexes:function () { var index = 0; - for (var i = 0; i < this._children[0].length; i++) { - var child = this._children[i]; + var locChildren = this._children; + for (var i = 0; i < locChildren.length; i++) { + var child = locChildren[i]; child.setAtlasIndex(index); index += child.getTotalParticles(); } @@ -385,9 +390,10 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ }, _searchNewPositionInChildrenForZ:function (z) { - var count = this._children.length; + var locChildren = this._children; + var count = locChildren.length; for (var i = 0; i < count; i++) { - if (this._children[i].getZOrder() > z) + if (locChildren[i].getZOrder() > z) return i; } return count; @@ -400,10 +406,10 @@ cc.ParticleBatchNode = cc.Node.extend(/** @lends cc.ParticleBatchNode# */{ var newIndex = 0; var oldIndex = 0; - var minusOne = 0; - var count = this._children.length; + var minusOne = 0, locChildren = this._children; + var count = locChildren.length; for (var i = 0; i < count; i++) { - var pNode = this._children[i]; + var pNode = locChildren[i]; // new index if (pNode.getZOrder() > z && !foundNewIdx) { newIndex = i; diff --git a/cocos2d/particle_nodes/CCParticleExamples.js b/cocos2d/particle_nodes/CCParticleExamples.js index 27d99061a0..8d7f977141 100644 --- a/cocos2d/particle_nodes/CCParticleExamples.js +++ b/cocos2d/particle_nodes/CCParticleExamples.js @@ -27,12 +27,12 @@ /** * A fire particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleFire.create(); */ -cc.ParticleFire = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFire# */{ +cc.ParticleFire = cc.ParticleSystem.extend(/** @lends cc.ParticleFire# */{ /** * initialize a fire particle system * @return {Boolean} @@ -47,7 +47,7 @@ cc.ParticleFire = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFire# */{ * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -131,12 +131,12 @@ cc.ParticleFire.create = function () { /** * A fireworks particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleFireworks.create(); */ -cc.ParticleFireworks = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFireworks# */{ +cc.ParticleFireworks = cc.ParticleSystem.extend(/** @lends cc.ParticleFireworks# */{ /** * initialize a fireworks particle system * @return {Boolean} @@ -151,7 +151,7 @@ cc.ParticleFireworks = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFirewo * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -233,12 +233,12 @@ cc.ParticleFireworks.create = function () { /** * A sun particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleSun.create(); */ -cc.ParticleSun = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSun# */{ +cc.ParticleSun = cc.ParticleSystem.extend(/** @lends cc.ParticleSun# */{ /** * initialize a sun particle system * @return {Boolean} @@ -253,7 +253,7 @@ cc.ParticleSun = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSun# */{ * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // additive this.setBlendAdditive(true); @@ -338,12 +338,12 @@ cc.ParticleSun.create = function () { /** * A galaxy particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleGalaxy.create(); */ -cc.ParticleGalaxy = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleGalaxy# */{ +cc.ParticleGalaxy = cc.ParticleSystem.extend(/** @lends cc.ParticleGalaxy# */{ /** * initialize a galaxy particle system * @return {Boolean} @@ -359,7 +359,7 @@ cc.ParticleGalaxy = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleGalaxy# * * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -445,12 +445,12 @@ cc.ParticleGalaxy.create = function () { /** * A flower particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleFlower.create(); */ -cc.ParticleFlower = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFlower# */{ +cc.ParticleFlower = cc.ParticleSystem.extend(/** @lends cc.ParticleFlower# */{ /** * initialize a flower particle system * @return {Boolean} @@ -465,7 +465,7 @@ cc.ParticleFlower = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleFlower# * * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -553,12 +553,12 @@ cc.ParticleFlower.create = function () { /** * A meteor particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleMeteor.create(); */ -cc.ParticleMeteor = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleMeteor# */{ +cc.ParticleMeteor = cc.ParticleSystem.extend(/** @lends cc.ParticleMeteor# */{ /** * initialize a meteor particle system * @return {Boolean} @@ -573,7 +573,7 @@ cc.ParticleMeteor = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleMeteor# * * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -660,12 +660,12 @@ cc.ParticleMeteor.create = function () { /** * A spiral particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleSpiral.create(); */ -cc.ParticleSpiral = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSpiral# */{ +cc.ParticleSpiral = cc.ParticleSystem.extend(/** @lends cc.ParticleSpiral# */{ /** * initialize a spiral particle system * @return {Boolean} @@ -680,7 +680,7 @@ cc.ParticleSpiral = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSpiral# * * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -767,12 +767,12 @@ cc.ParticleSpiral.create = function () { /** * An explosion particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleExplosion.create(); */ -cc.ParticleExplosion = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleExplosion# */{ +cc.ParticleExplosion = cc.ParticleSystem.extend(/** @lends cc.ParticleExplosion# */{ /** * initialize an explosion particle system * @return {Boolean} @@ -788,7 +788,7 @@ cc.ParticleExplosion = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleExplos * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = 0.1; @@ -874,12 +874,12 @@ cc.ParticleExplosion.create = function () { /** * A smoke particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleSmoke.create(); */ -cc.ParticleSmoke = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSmoke# */{ +cc.ParticleSmoke = cc.ParticleSystem.extend(/** @lends cc.ParticleSmoke# */{ /** * initialize a smoke particle system * @return {Boolean} @@ -895,7 +895,7 @@ cc.ParticleSmoke = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSmoke# */{ * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -978,12 +978,12 @@ cc.ParticleSmoke.create = function () { /** * A snow particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleSnow.create(); */ -cc.ParticleSnow = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSnow# */{ +cc.ParticleSnow = cc.ParticleSystem.extend(/** @lends cc.ParticleSnow# */{ /** * initialize a snow particle system * @return {Boolean} @@ -998,7 +998,7 @@ cc.ParticleSnow = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleSnow# */{ * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; @@ -1086,12 +1086,12 @@ cc.ParticleSnow.create = function () { /** * A rain particle system * @class - * @extends cc.ParticleSystemQuad + * @extends cc.ParticleSystem * * @example * var emitter = cc.ParticleRain.create(); */ -cc.ParticleRain = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleRain# */{ +cc.ParticleRain = cc.ParticleSystem.extend(/** @lends cc.ParticleRain# */{ /** * initialize a rain particle system * @return {Boolean} @@ -1106,7 +1106,7 @@ cc.ParticleRain = cc.ParticleSystemQuad.extend(/** @lends cc.ParticleRain# */{ * @return {Boolean} */ initWithTotalParticles:function (numberOfParticles) { - if (cc.ParticleSystemQuad.prototype.initWithTotalParticles.call(this, numberOfParticles)) { + if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { // duration this._duration = cc.PARTICLE_DURATION_INFINITY; diff --git a/cocos2d/particle_nodes/CCParticleSystem.js b/cocos2d/particle_nodes/CCParticleSystem.js index 05834c754b..a68c370bd5 100644 --- a/cocos2d/particle_nodes/CCParticleSystem.js +++ b/cocos2d/particle_nodes/CCParticleSystem.js @@ -232,7 +232,7 @@ cc.Particle.TemporaryPoints = [ * 'Radius Mode' in Particle Designer uses a fixed emit rate of 30 hz. Since that can't be guarateed in cocos2d,
* cocos2d uses a another approach, but the results are almost identical.
* cocos2d supports all the variables used by Particle Designer plus a bit more:
- * - spinning particles (supported when using CCParticleSystemQuad)
+ * - spinning particles (supported when using ParticleSystem)
* - tangential acceleration (Gravity mode)
* - radial acceleration (Gravity mode)
* - radius direction (Radius mode) (Particle Designer supports outwards to inwards direction only)
@@ -288,8 +288,8 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ _isActive: false, _particleCount: 0, _duration: 0, - _sourcePosition: cc.PointZero(), - _posVar: cc.PointZero(), + _sourcePosition: null, + _posVar: null, _life: 0, _lifeVar: 0, _angle: 0, @@ -298,10 +298,10 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ _startSizeVar: 0, _endSize: 0, _endSizeVar: 0, - _startColor: new cc.Color4F(0, 0, 0, 1), - _startColorVar: new cc.Color4F(0, 0, 0, 1), - _endColor: new cc.Color4F(0, 0, 0, 1), - _endColorVar: new cc.Color4F(0, 0, 0, 1), + _startColor: null, + _startColorVar: null, + _endColor: null, + _endColorVar: null, _startSpin: 0, _startSpinVar: 0, _endSpin: 0, @@ -315,6 +315,19 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ _isAutoRemoveOnFinish: false, _emitterMode: 0, + // quads to be rendered + _quads:null, + // indices + _indices:null, + + //_VAOname:0, + //0: vertex 1: indices + _buffersVBO:null, + _pointRect:null, + + _textureLoaded: null, + _quadsArrayBuffer:null, + /** * Constructor * @override @@ -370,6 +383,110 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ this._opacityModifyRGB = false; this._positionType = cc.PARTICLE_TYPE_FREE; this._isAutoRemoveOnFinish = false; + + this._buffersVBO = [0, 0]; + this._quads = []; + this._indices = []; + this._pointRect = cc.RectZero(); + this._textureLoaded = true; + + if (cc.renderContextType === cc.WEBGL) { + this._quadsArrayBuffer = null; + } + }, + + /** + * initializes the indices for the vertices + */ + initIndices:function () { + var locIndices = this._indices; + for (var i = 0, len = this._totalParticles; i < len; ++i) { + var i6 = i * 6; + var i4 = i * 4; + locIndices[i6 + 0] = i4 + 0; + locIndices[i6 + 1] = i4 + 1; + locIndices[i6 + 2] = i4 + 2; + + locIndices[i6 + 5] = i4 + 1; + locIndices[i6 + 4] = i4 + 2; + locIndices[i6 + 3] = i4 + 3; + } + }, + + /** + *

initializes the texture with a rectangle measured Points
+ * pointRect should be in Texture coordinates, not pixel coordinates + *

+ * @param {cc.Rect} pointRect + */ + initTexCoordsWithRect:function (pointRect) { + var scaleFactor = cc.CONTENT_SCALE_FACTOR(); + // convert to pixels coords + var rect = cc.rect( + pointRect.x * scaleFactor, + pointRect.y * scaleFactor, + pointRect.width * scaleFactor, + pointRect.height * scaleFactor); + + var wide = pointRect.width; + var high = pointRect.height; + + if (this._texture) { + wide = this._texture.getPixelsWide(); + high = this._texture.getPixelsHigh(); + } + + if(cc.renderContextType === cc.CANVAS) + return; + + var left, bottom, right, top; + if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { + left = (rect.x * 2 + 1) / (wide * 2); + bottom = (rect.y * 2 + 1) / (high * 2); + right = left + (rect.width * 2 - 2) / (wide * 2); + top = bottom + (rect.height * 2 - 2) / (high * 2); + } else { + left = rect.x / wide; + bottom = rect.y / high; + right = left + rect.width / wide; + top = bottom + rect.height / high; + } + + // Important. Texture in cocos2d are inverted, so the Y component should be inverted + var temp = top; + top = bottom; + bottom = temp; + + var quads; + var start = 0, end = 0; + if (this._batchNode) { + quads = this._batchNode.getTextureAtlas().getQuads(); + start = this._atlasIndex; + end = this._atlasIndex + this._totalParticles; + } else { + quads = this._quads; + start = 0; + end = this._totalParticles; + } + + for (var i = start; i < end; i++) { + if (!quads[i]) + quads[i] = cc.V3F_C4B_T2F_QuadZero(); + + // bottom-left vertex: + var selQuad = quads[i]; + selQuad.bl.texCoords.u = left; + selQuad.bl.texCoords.v = bottom; + // bottom-right vertex: + selQuad.br.texCoords.u = right; + selQuad.br.texCoords.v = bottom; + // top-left vertex: + selQuad.tl.texCoords.u = left; + selQuad.tl.texCoords.v = top; + // top-right vertex: + selQuad.tr.texCoords.u = right; + selQuad.tr.texCoords.v = top; + } }, /** @@ -386,11 +503,35 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ */ setBatchNode:function (batchNode) { if (this._batchNode != batchNode) { + var oldBatch = this._batchNode; + this._batchNode = batchNode; //weak reference if (batchNode) { + var locParticles = this._particles; for (var i = 0; i < this._totalParticles; i++) - this._particles[i].atlasIndex = i; + locParticles[i].atlasIndex = i; + } + + // NEW: is self render ? + if (!batchNode) { + this._allocMemory(); + this.initIndices(); + this.setTexture(oldBatch.getTexture()); + //if (cc.TEXTURE_ATLAS_USE_VAO) + // this._setupVBOandVAO(); + //else + this._setupVBO(); + } else if (!oldBatch) { + // OLD: was it self render cleanup ? + // copy current state to batch + this._batchNode.getTextureAtlas()._copyQuadsToTextureAtlas(this._quads, this._atlasIndex); + + //delete buffer + cc.renderContext.deleteBuffer(this._buffersVBO[1]); //where is re-bindBuffer code? + + //if (cc.TEXTURE_ATLAS_USE_VAO) + // glDeleteVertexArrays(1, this._VAOname); } } }, @@ -1081,11 +1222,57 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ /** * set maximum particles of the system - * @param {Number} totalParticles + * @param {Number} tp totalParticles */ - setTotalParticles:function (totalParticles) { - cc.Assert(totalParticles <= this._allocatedParticles, "Particle: resizing particle array only supported for quads"); - this._totalParticles = totalParticles; + setTotalParticles:function (tp) { + //cc.Assert(tp <= this._allocatedParticles, "Particle: resizing particle array only supported for quads"); + if (cc.renderContextType === cc.CANVAS){ + this._totalParticles = (tp < 200) ? tp : 200; + return; + } + + // If we are setting the total numer of particles to a number higher + // than what is allocated, we need to allocate new arrays + if (tp > this._allocatedParticles) { + var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; + // Allocate new memory + this._indices = new Uint16Array(tp * 6); + var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize); + //TODO need fix + // Assign pointers + var locParticles = []; + var locQuads = []; + for (var j = 0; j < tp; j++) { + locParticles[j] = new cc.Particle(); + locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize); + } + this._allocatedParticles = tp; + this._totalParticles = tp; + + // Init particles + if (this._batchNode) { + for (var i = 0; i < tp; i++) + locParticles[i].atlasIndex = i; + } + + this._particles = locParticles; + this._quadsArrayBuffer = locQuadsArrayBuffer; + this._quads = locQuads; + + this.initIndices(); + //if (cc.TEXTURE_ATLAS_USE_VAO) + // this._setupVBOandVAO(); + //else + this._setupVBO(); + + //set the texture coord + if(this._texture){ + var size = this._texture.getContentSize(); + this.initTexCoordsWithRect(cc.rect(0, 0, size.width, size.height)); + } + } else + this._totalParticles = tp; + this.resetSystem(); }, /** @@ -1098,12 +1285,19 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ /** * set Texture of Particle System - * @param {cc.Texture2D | HTMLImageElement | HTMLCanvasElement} texture + * @param {cc.Texture2D } texture */ setTexture:function (texture) { - if (this._texture != texture) { - this._texture = texture; - this._updateBlendFunc(); + if(texture.isLoaded()){ + var size = texture.getContentSize(); + this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height)); + } else { + this._textureLoaded = false; + texture.addLoadedEventListener(function(sender){ + this._textureLoaded = true; + var size = sender.getContentSize(); + this.setTextureWithRect(sender, cc.rect(0, 0, size.width, size.height)); + }, this); } }, @@ -1516,6 +1710,20 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ // udpate after action in run! this.scheduleUpdateWithPriority(1); + if(cc.renderContextType === cc.WEBGL){ + // allocating data space + if (!this._allocMemory()) + return false; + + this.initIndices(); + //if (cc.TEXTURE_ATLAS_USE_VAO) + // this._setupVBOandVAO(); + //else + this._setupVBO(); + + this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); + } + return true; }, @@ -1678,8 +1886,9 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ resetSystem:function () { this._isActive = true; this._elapsed = 0; + var locParticles = this._particles; for (this._particleIdx = 0; this._particleIdx < this._particleCount; ++this._particleIdx) - this._particles[this._particleIdx].timeToLive = 0 ; + locParticles[this._particleIdx].timeToLive = 0 ; }, /** @@ -1696,14 +1905,129 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ * @param {cc.Point} newPosition */ updateQuadWithParticle:function (particle, newPosition) { - // should be overriden + var quad = null; + if (this._batchNode) { + var batchQuads = this._batchNode.getTextureAtlas().getQuads(); + quad = batchQuads[this._atlasIndex + particle.atlasIndex]; + this._batchNode.getTextureAtlas()._dirty = true; + } else + quad = this._quads[this._particleIdx]; + + var r, g, b, a; + if(this._opacityModifyRGB){ + r = 0 | (particle.color.r * particle.color.a * 255); + g = 0 | (particle.color.g * particle.color.a * 255); + b = 0 | (particle.color.b * particle.color.a * 255); + a = 0 | (particle.color.a * 255); + }else{ + r = 0 | (particle.color.r * 255); + g = 0 | (particle.color.g * 255); + b = 0 | (particle.color.b * 255); + a = 0 | (particle.color.a * 255); + } + + var locColors = quad.bl.colors; + locColors.r = r; + locColors.g = g; + locColors.b = b; + locColors.a = a; + + locColors = quad.br.colors; + locColors.r = r; + locColors.g = g; + locColors.b = b; + locColors.a = a; + + locColors = quad.tl.colors; + locColors.r = r; + locColors.g = g; + locColors.b = b; + locColors.a = a; + + locColors = quad.tr.colors; + locColors.r = r; + locColors.g = g; + locColors.b = b; + locColors.a = a; + + // vertices + var size_2 = particle.size / 2; + if (particle.rotation) { + var x1 = -size_2; + var y1 = -size_2; + + var x2 = size_2; + var y2 = size_2; + var x = newPosition.x; + var y = newPosition.y; + + var rad = -cc.DEGREES_TO_RADIANS(particle.rotation); + var cr = Math.cos(rad); + var sr = Math.sin(rad); + var ax = x1 * cr - y1 * sr + x; + var ay = x1 * sr + y1 * cr + y; + var bx = x2 * cr - y1 * sr + x; + var by = x2 * sr + y1 * cr + y; + var cx = x2 * cr - y2 * sr + x; + var cy = x2 * sr + y2 * cr + y; + var dx = x1 * cr - y2 * sr + x; + var dy = x1 * sr + y2 * cr + y; + + // bottom-left + quad.bl.vertices.x = ax; + quad.bl.vertices.y = ay; + + // bottom-right vertex: + quad.br.vertices.x = bx; + quad.br.vertices.y = by; + + // top-left vertex: + quad.tl.vertices.x = dx; + quad.tl.vertices.y = dy; + + // top-right vertex: + quad.tr.vertices.x = cx; + quad.tr.vertices.y = cy; + } else { + // bottom-left vertex: + quad.bl.vertices.x = newPosition.x - size_2; + quad.bl.vertices.y = newPosition.y - size_2; + + // bottom-right vertex: + quad.br.vertices.x = newPosition.x + size_2; + quad.br.vertices.y = newPosition.y - size_2; + + // top-left vertex: + quad.tl.vertices.x = newPosition.x - size_2; + quad.tl.vertices.y = newPosition.y + size_2; + + // top-right vertex: + quad.tr.vertices.x = newPosition.x + size_2; + quad.tr.vertices.y = newPosition.y + size_2; + } }, /** * should be overridden by subclasses */ postStep:function () { - // should be overriden + if (cc.renderContextType === cc.WEBGL) { + var gl = cc.renderContext; + + gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); + gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW); + + // Option 2: Data + // glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * particleCount, quads_, GL_DYNAMIC_DRAW); + + // Option 3: Orphaning + glMapBuffer + // glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*m_uTotalParticles, NULL, GL_STREAM_DRAW); + // void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + // memcpy(buf, m_pQuads, sizeof(m_pQuads[0])*m_uTotalParticles); + // glUnmapBuffer(GL_ARRAY_BUFFER); + + //cc.CHECK_GL_ERROR_DEBUG(); + } }, /** @@ -1745,6 +2069,7 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ tpb = cc.Particle.TemporaryPoints[2], tpc = cc.Particle.TemporaryPoints[3]; + var locParticles = this._particles; while (this._particleIdx < this._particleCount) { // Reset the working particles @@ -1752,7 +2077,7 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ cc.pZeroIn(tpb); cc.pZeroIn(tpc); - var selParticle = this._particles[this._particleIdx]; + var selParticle = locParticles[this._particleIdx]; // life selParticle.timeToLive -= dt; @@ -1767,7 +2092,6 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ if (selParticle.pos.x || selParticle.pos.y) { cc.pIn(radial, selParticle.pos); cc.pNormalizeIn(radial); - } else { cc.pZeroIn(radial); } @@ -1860,20 +2184,19 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ // life < 0 var currentIndex = selParticle.atlasIndex; if(this._particleIdx !== this._particleCount -1){ - var deadParticle = this._particles[this._particleIdx]; - this._particles[this._particleIdx] = this._particles[this._particleCount -1]; - this._particles[this._particleCount -1] = deadParticle; + var deadParticle = locParticles[this._particleIdx]; + locParticles[this._particleIdx] = locParticles[this._particleCount -1]; + locParticles[this._particleCount -1] = deadParticle; } if (this._batchNode) { //disable the switched particle this._batchNode.disableParticle(this._atlasIndex + currentIndex); //switch indexes - this._particles[this._particleCount - 1].atlasIndex = currentIndex; + locParticles[this._particleCount - 1].atlasIndex = currentIndex; } --this._particleCount; - if (this._particleCount == 0 && this._isAutoRemoveOnFinish) { this.unscheduleUpdate(); this._parent.removeChild(this, true); @@ -1910,38 +2233,403 @@ cc.ParticleSystem = cc.Node.extend(/** @lends cc.ParticleSystem# */{ _updateBlendFunc:function () { cc.Assert(!this._batchNode, "Can't change blending functions when the particle is being batched"); - if (this._texture) { - if (this._texture instanceof cc.Texture2D) { - var premultiplied = this._texture.hasPremultipliedAlpha(); - this._opacityModifyRGB = false; + var locTexture = this._texture; + if (locTexture && locTexture instanceof cc.Texture2D) { + this._opacityModifyRGB = false; + var locBlendFunc = this._blendFunc; + if (locBlendFunc.src == cc.BLEND_SRC && locBlendFunc.dst == cc.BLEND_DST) { + if (locTexture.hasPremultipliedAlpha()) { + this._opacityModifyRGB = true; + } else { + locBlendFunc.src = gl.SRC_ALPHA; + locBlendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; + } + } + } + }, - if (this._texture && ( this._blendFunc.src == cc.BLEND_SRC && this._blendFunc.dst == cc.BLEND_DST )) { - if (premultiplied) { - this._opacityModifyRGB = true; - } else { - this._blendFunc.src = gl.SRC_ALPHA; - this._blendFunc.dst = gl.ONE_MINUS_SRC_ALPHA; + clone:function () { + var retParticle = new cc.ParticleSystem(); + + // self, not super + if (retParticle.initWithTotalParticles(this._totalParticles)) { + // angle + retParticle._angle = this._angle; + retParticle._angleVar = this._angleVar; + + // duration + retParticle._duration = this._duration; + + // blend function + retParticle._blendFunc.src = this._blendFunc.src; + retParticle._blendFunc.dst = this._blendFunc.dst; + + // color + var particleStartColor = retParticle._startColor, locStartColor = this._startColor; + particleStartColor.r = locStartColor.r; + particleStartColor.g = locStartColor.g; + particleStartColor.b = locStartColor.b; + particleStartColor.a = locStartColor.a; + + var particleStartColorVar = retParticle._startColorVar, locStartColorVar = this._startColorVar; + particleStartColorVar.r = locStartColorVar.r; + particleStartColorVar.g = locStartColorVar.g; + particleStartColorVar.b = locStartColorVar.b; + particleStartColorVar.a = locStartColorVar.a; + + var particleEndColor = retParticle._endColor, locEndColor = this._endColor; + particleEndColor.r = locEndColor.r; + particleEndColor.g = locEndColor.g; + particleEndColor.b = locEndColor.b; + particleEndColor.a = locEndColor.a; + + var particleEndColorVar = retParticle._endColorVar, locEndColorVar = this._endColorVar; + particleEndColorVar.r = locEndColorVar.r; + particleEndColorVar.g = locEndColorVar.g; + particleEndColorVar.b = locEndColorVar.b; + particleEndColorVar.a = locEndColorVar.a; + + // particle size + retParticle._startSize = this._startSize; + retParticle._startSizeVar = this._startSizeVar; + retParticle._endSize = this._endSize; + retParticle._endSizeVar = this._endSizeVar; + + // position + retParticle.setPosition(new cc.Point(this._position.x, this._position.y)); + retParticle._posVar.x = this._posVar.x; + retParticle._posVar.y = this._posVar.y; + + // Spinning + retParticle._startSpin = this._startSpin; + retParticle._startSpinVar = this._startSpinVar; + retParticle._endSpin = this._endSpin; + retParticle._endSpinVar = this._endSpinVar; + + retParticle._emitterMode = this._emitterMode; + + // Mode A: Gravity + tangential accel + radial accel + if (this._emitterMode == cc.PARTICLE_MODE_GRAVITY) { + var particleModeA = retParticle.modeA, locModeA = this.modeA; + // gravity + particleModeA.gravity.x = locModeA.gravity.x; + particleModeA.gravity.y = locModeA.gravity.y; + + // speed + particleModeA.speed = locModeA.speed; + particleModeA.speedVar = locModeA.speedVar; + + // radial acceleration + particleModeA.radialAccel = locModeA.radialAccel; + + particleModeA.radialAccelVar = locModeA.radialAccelVar; + + // tangential acceleration + particleModeA.tangentialAccel = locModeA.tangentialAccel; + + particleModeA.tangentialAccelVar = locModeA.tangentialAccelVar; + } else if (this._emitterMode == cc.PARTICLE_MODE_RADIUS) { + var particleModeB = retParticle.modeB, locModeB = this.modeB; + // or Mode B: radius movement + particleModeB.startRadius = locModeB.startRadius; + particleModeB.startRadiusVar = locModeB.startRadiusVar; + particleModeB.endRadius = locModeB.endRadius; + particleModeB.endRadiusVar = locModeB.endRadiusVar; + particleModeB.rotatePerSecond = locModeB.rotatePerSecond; + particleModeB.rotatePerSecondVar = locModeB.rotatePerSecondVar; + } + + // life span + retParticle._life = this._life; + retParticle._lifeVar = this._lifeVar; + + // emission Rate + retParticle._emissionRate = this._emissionRate; + + //don't get the internal texture if a batchNode is used + if (!this._batchNode) { + // Set a compatible default for the alpha transfer + retParticle._opacityModifyRGB = this._opacityModifyRGB; + + // texture + retParticle._texture = this._texture; + } + } + return retParticle; + }, + + /** + *

Sets a new CCSpriteFrame as particle.
+ * WARNING: this method is experimental. Use setTextureWithRect instead. + *

+ * @param {cc.SpriteFrame} spriteFrame + */ + setDisplayFrame:function (spriteFrame) { + cc.Assert(cc._rectEqualToZero(spriteFrame.getOffsetInPixels()), "QuadParticle only supports SpriteFrames with no offsets"); + + // update texture before updating texture rect + if (cc.renderContextType === cc.WEBGL) + if (!this._texture || spriteFrame.getTexture()._webTextureObj != this._texture._webTextureObj) + this.setTexture(spriteFrame.getTexture()); + }, + + /** + * Sets a new texture with a rect. The rect is in Points. + * @param {cc.Texture2D} texture + * @param {cc.Rect} rect + */ + setTextureWithRect:function (texture, rect) { + var locTexture = this._texture; + if (cc.renderContextType === cc.WEBGL) { + // Only update the texture if is different from the current one + if ((!locTexture || texture._webTextureObj != locTexture._webTextureObj) && (locTexture != texture)) { + this._texture = texture; + this._updateBlendFunc(); + } + } else { + if ((!locTexture || texture != locTexture) && (locTexture != texture)) { + this._texture = texture; + this._updateBlendFunc(); + } + } + + this._pointRect = rect; + this.initTexCoordsWithRect(rect); + }, + + /** + * draw particle + * @param {CanvasRenderingContext2D} ctx CanvasContext + * @override + */ + draw:function (ctx) { + cc.Assert(!this._batchNode, "draw should not be called when added to a particleBatchNode"); + if(!this._textureLoaded) + return; + + if (cc.renderContextType === cc.CANVAS) + this._drawForCanvas(ctx); + else + this._drawForWebGL(ctx); + + cc.g_NumberOfDraws++; + }, + + _drawForCanvas:function (ctx) { + var context = ctx || cc.renderContext; + context.save(); + if (this.isBlendAdditive()) + context.globalCompositeOperation = 'lighter'; + else + context.globalCompositeOperation = 'source-over'; + + for (var i = 0; i < this._particleCount; i++) { + var particle = this._particles[i]; + var lpx = (0 | (particle.size * 0.5)); + + if (this._drawMode == cc.PARTICLE_TEXTURE_MODE) { + + var element = this._texture.getHtmlElementObj(); + + // Delay drawing until the texture is fully loaded by the browser + if (!element.width || !element.height) + continue; + + context.save(); + context.globalAlpha = particle.color.a; + context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y)); + + var size = Math.floor(particle.size / 4) * 4; + var w = this._pointRect.width; + var h = this._pointRect.height; + + context.scale( + Math.max((1 / w) * size, 0.000001), + Math.max((1 / h) * size, 0.000001) + ); + + + if (particle.rotation) + context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation)); + + context.translate(-(0 | (w / 2)), -(0 | (h / 2))); + if (particle.isChangeColor) { + + var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); + if (cacheTextureForColor) { + // Create another cache for the tinted version + // This speeds up things by a fair bit + if (!cacheTextureForColor.tintCache) { + cacheTextureForColor.tintCache = document.createElement('canvas'); + cacheTextureForColor.tintCache.width = element.width; + cacheTextureForColor.tintCache.height = element.height; + } + cc.generateTintImage(element, cacheTextureForColor, particle.color, this._pointRect, cacheTextureForColor.tintCache); + element = cacheTextureForColor.tintCache; } } + + context.drawImage(element, 0, 0); + context.restore(); + + } else { + context.save(); + context.globalAlpha = particle.color.a; + + context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y)); + + if (this._shapeType == cc.PARTICLE_STAR_SHAPE) { + if (particle.rotation) + context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation)); + cc.drawingUtil.drawStar(context, lpx, particle.color); + } else + cc.drawingUtil.drawColorBall(context, lpx, particle.color); + context.restore(); } } + context.restore(); + }, + + _drawForWebGL:function (ctx) { + if(!this._texture) + return; + + var gl = ctx || cc.renderContext; + + this._shaderProgram.use(); + this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); + + cc.glBindTexture2D(this._texture); + cc.glBlendFuncForParticle(this._blendFunc.src, this._blendFunc.dst); + + //cc.Assert(this._particleIdx == this._particleCount, "Abnormal error in particle quad"); + + // + // Using VBO without VAO + // + cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX); + + gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); + gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices + gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors + gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); + gl.drawElements(gl.TRIANGLES, this._particleIdx * 6, gl.UNSIGNED_SHORT, 0); + }, + + /** + * listen the event that coming to foreground on Android + * @param {cc.Class} obj + */ + listenBackToForeground:function (obj) { + if (cc.TEXTURE_ATLAS_USE_VAO) + this._setupVBOandVAO(); + else + this._setupVBO(); + }, + + _setupVBOandVAO:function () { + //Not support on WebGL + /*if (cc.renderContextType == cc.CANVAS) { + return; + }*/ + + //NOT SUPPORTED + /*glGenVertexArrays(1, this._VAOname); + glBindVertexArray(this._VAOname); + + var kQuadSize = sizeof(m_pQuads[0].bl); + + glGenBuffers(2, this._buffersVBO[0]); + + glBindBuffer(GL_ARRAY_BUFFER, this._buffersVBO[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(this._quads[0]) * this._totalParticles, this._quads, GL_DYNAMIC_DRAW); + + // vertices + glEnableVertexAttribArray(kCCVertexAttrib_Position); + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, vertices)); + + // colors + glEnableVertexAttribArray(kCCVertexAttrib_Color); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, offsetof(ccV3F_C4B_T2F, colors)); + + // tex coords + glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uTotalParticles * 6, m_pIndices, GL_STATIC_DRAW); + + glBindVertexArray(0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + CHECK_GL_ERROR_DEBUG();*/ + }, + + _setupVBO:function () { + if (cc.renderContextType == cc.CANVAS) + return; + + var gl = cc.renderContext; + + //gl.deleteBuffer(this._buffersVBO[0]); + this._buffersVBO[0] = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); + gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW); + + this._buffersVBO[1] = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW); + + //cc.CHECK_GL_ERROR_DEBUG(); + }, + + _allocMemory:function () { + if (cc.renderContextType === cc.CANVAS) + return true; + + //cc.Assert((!this._quads && !this._indices), "Memory already allocated"); + cc.Assert(!this._batchNode, "Memory should not be allocated when not using batchNode"); + var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; + var totalParticles = this._totalParticles; + var locQuads = []; + this._indices = new Uint16Array(totalParticles * 6); + var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles); + + for (var i = 0; i < totalParticles; i++) + locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize); + if (!locQuads || !this._indices) { + cc.log("cocos2d: Particle system: not enough memory"); + return false; + } + this._quads = locQuads; + this._quadsArrayBuffer = locQuadsArrayBuffer; + return true; } }); /** *

return the string found by key in dict.
- * This plist files can be creted manually or with Particle Designer:
+ * This plist files can be create manually or with Particle Designer:
* http://particledesigner.71squared.com/
*

* @param {String} plistFile * @return {cc.ParticleSystem} */ cc.ParticleSystem.create = function (plistFile) { - return cc.ParticleSystemQuad.create(plistFile); - /*var particle = new cc.ParticleSystem(); - if (particle && particle.initWithFile(plistFile)) - return particle; - return null;*/ + var ret = new cc.ParticleSystem(); + if (!plistFile || typeof(plistFile) === "number") { + var ton = plistFile || 100; + ret.setDrawMode(cc.PARTICLE_TEXTURE_MODE); + ret.initWithTotalParticles(ton); + return ret; + } + + if (ret && ret.initWithFile(plistFile)) + return ret; + return null; }; /** @@ -1950,12 +2638,11 @@ cc.ParticleSystem.create = function (plistFile) { * @return {cc.ParticleSystem} */ cc.ParticleSystem.createWithTotalParticles = function (number_of_particles) { - return cc.ParticleSystemQuad.create(number_of_particles); - /*//emitter.initWithTotalParticles(number_of_particles); + //emitter.initWithTotalParticles(number_of_particles); var particle = new cc.ParticleSystem(); if (particle && particle.initWithTotalParticles(number_of_particles)) return particle; - return null;*/ + return null; }; // Different modes diff --git a/cocos2d/particle_nodes/CCParticleSystemQuad.js b/cocos2d/particle_nodes/CCParticleSystemQuad.js deleted file mode 100644 index 4b9debb67c..0000000000 --- a/cocos2d/particle_nodes/CCParticleSystemQuad.js +++ /dev/null @@ -1,819 +0,0 @@ -/**************************************************************************** - 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. - ****************************************************************************/ - -/** - *

- * CCParticleSystemQuad is a subclass of CCParticleSystem
- *
- * It includes all the features of ParticleSystem.
- *
- * Special features and Limitations:
- * - Particle size can be any float number.
- * - The system can be scaled
- * - The particles can be rotated
- * - It supports subrects
- * - It supports batched rendering since 1.1
- *

- * @class - * @extends cc.ParticleSystem - * @example - * //create a particle system - * this._emitter = new cc.ParticleSystemQuad(); - * this._emitter.initWithTotalParticles(150); - */ -cc.ParticleSystemQuad = cc.ParticleSystem.extend(/** @lends cc.ParticleSystemQuad# */{ - // quads to be rendered - _quads:null, - // indices - _indices:null, - - //_VAOname:0, - //0: vertex 1: indices - _buffersVBO:null, - _pointRect:null, - - _textureLoaded: null, - - /** - * Constructor - * @override - */ - ctor:function () { - cc.ParticleSystem.prototype.ctor.call(this); - this._buffersVBO = [0, 0]; - this._quads = []; - this._indices = []; - this._pointRect = cc.RectZero(); - this._textureLoaded = true; - - if (cc.renderContextType === cc.WEBGL) { - this._quadsArrayBuffer = null; - } - }, - - /** - * initialices the indices for the vertices - */ - initIndices:function () { - var locIndices = this._indices; - for (var i = 0, len = this._totalParticles; i < len; ++i) { - var i6 = i * 6; - var i4 = i * 4; - locIndices[i6 + 0] = i4 + 0; - locIndices[i6 + 1] = i4 + 1; - locIndices[i6 + 2] = i4 + 2; - - locIndices[i6 + 5] = i4 + 1; - locIndices[i6 + 4] = i4 + 2; - locIndices[i6 + 3] = i4 + 3; - } - }, - - /** - *

initilizes the texture with a rectangle measured Points
- * pointRect should be in Texture coordinates, not pixel coordinates - *

- * @param {cc.Rect} pointRect - */ - initTexCoordsWithRect:function (pointRect) { - var scaleFactor = cc.CONTENT_SCALE_FACTOR(); - // convert to pixels coords - var rect = cc.rect( - pointRect.x * scaleFactor, - pointRect.y * scaleFactor, - pointRect.width * scaleFactor, - pointRect.height * scaleFactor); - - var wide = pointRect.width; - var high = pointRect.height; - - if (this._texture) { - wide = this._texture.getPixelsWide(); - high = this._texture.getPixelsHigh(); - } - - if(cc.renderContextType === cc.CANVAS) - return; - - var left, bottom, right, top; - if (cc.FIX_ARTIFACTS_BY_STRECHING_TEXEL) { - left = (rect.x * 2 + 1) / (wide * 2); - bottom = (rect.y * 2 + 1) / (high * 2); - right = left + (rect.width * 2 - 2) / (wide * 2); - top = bottom + (rect.height * 2 - 2) / (high * 2); - } else { - left = rect.x / wide; - bottom = rect.y / high; - right = left + rect.width / wide; - top = bottom + rect.height / high; - } - - // Important. Texture in cocos2d are inverted, so the Y component should be inverted - var temp = top; - top = bottom; - bottom = temp; - - var quads; - var start = 0, end = 0; - if (this._batchNode) { - quads = this._batchNode.getTextureAtlas().getQuads(); - start = this._atlasIndex; - end = this._atlasIndex + this._totalParticles; - } else { - quads = this._quads; - start = 0; - end = this._totalParticles; - } - - for (var i = start; i < end; i++) { - if (!quads[i]) - quads[i] = cc.V3F_C4B_T2F_QuadZero(); - - // bottom-left vertex: - quads[i].bl.texCoords.u = left; - quads[i].bl.texCoords.v = bottom; - // bottom-right vertex: - quads[i].br.texCoords.u = right; - quads[i].br.texCoords.v = bottom; - // top-left vertex: - quads[i].tl.texCoords.u = left; - quads[i].tl.texCoords.v = top; - // top-right vertex: - quads[i].tr.texCoords.u = right; - quads[i].tr.texCoords.v = top; - } - }, - - clone:function () { - var retParticle = new cc.ParticleSystemQuad(); - - // self, not super - if (retParticle.initWithTotalParticles(this._totalParticles)) { - // angle - retParticle._angle = this._angle; - retParticle._angleVar = this._angleVar; - - // duration - retParticle._duration = this._duration; - - // blend function - retParticle._blendFunc.src = this._blendFunc.src; - retParticle._blendFunc.dst = this._blendFunc.dst; - - // color - var particleStartColor = retParticle._startColor, locStartColor = this._startColor; - particleStartColor.r = locStartColor.r; - particleStartColor.g = locStartColor.g; - particleStartColor.b = locStartColor.b; - particleStartColor.a = locStartColor.a; - - var particleStartColorVar = retParticle._startColorVar, locStartColorVar = this._startColorVar; - particleStartColorVar.r = locStartColorVar.r; - particleStartColorVar.g = locStartColorVar.g; - particleStartColorVar.b = locStartColorVar.b; - particleStartColorVar.a = locStartColorVar.a; - - var particleEndColor = retParticle._endColor, locEndColor = this._endColor; - particleEndColor.r = locEndColor.r; - particleEndColor.g = locEndColor.g; - particleEndColor.b = locEndColor.b; - particleEndColor.a = locEndColor.a; - - var particleEndColorVar = retParticle._endColorVar, locEndColorVar = this._endColorVar; - particleEndColorVar.r = locEndColorVar.r; - particleEndColorVar.g = locEndColorVar.g; - particleEndColorVar.b = locEndColorVar.b; - particleEndColorVar.a = locEndColorVar.a; - - // particle size - retParticle._startSize = this._startSize; - retParticle._startSizeVar = this._startSizeVar; - retParticle._endSize = this._endSize; - retParticle._endSizeVar = this._endSizeVar; - - // position - retParticle.setPosition(new cc.Point(this._position.x, this._position.y)); - retParticle._posVar.x = this._posVar.x; - retParticle._posVar.y = this._posVar.y; - - // Spinning - retParticle._startSpin = this._startSpin; - retParticle._startSpinVar = this._startSpinVar; - retParticle._endSpin = this._endSpin; - retParticle._endSpinVar = this._endSpinVar; - - retParticle._emitterMode = this._emitterMode; - - // Mode A: Gravity + tangential accel + radial accel - if (this._emitterMode == cc.PARTICLE_MODE_GRAVITY) { - var particleModeA = retParticle.modeA, locModeA = this.modeA; - // gravity - particleModeA.gravity.x = locModeA.gravity.x; - particleModeA.gravity.y = locModeA.gravity.y; - - // speed - particleModeA.speed = locModeA.speed; - particleModeA.speedVar = locModeA.speedVar; - - // radial acceleration - particleModeA.radialAccel = locModeA.radialAccel; - - particleModeA.radialAccelVar = locModeA.radialAccelVar; - - // tangential acceleration - particleModeA.tangentialAccel = locModeA.tangentialAccel; - - particleModeA.tangentialAccelVar = locModeA.tangentialAccelVar; - } else if (this._emitterMode == cc.PARTICLE_MODE_RADIUS) { - var particleModeB = retParticle.modeB, locModeB = this.modeB; - // or Mode B: radius movement - particleModeB.startRadius = locModeB.startRadius; - particleModeB.startRadiusVar = locModeB.startRadiusVar; - particleModeB.endRadius = locModeB.endRadius; - particleModeB.endRadiusVar = locModeB.endRadiusVar; - particleModeB.rotatePerSecond = locModeB.rotatePerSecond; - particleModeB.rotatePerSecondVar = locModeB.rotatePerSecondVar; - } - - // life span - retParticle._life = this._life; - retParticle._lifeVar = this._lifeVar; - - // emission Rate - retParticle._emissionRate = this._emissionRate; - - //don't get the internal texture if a batchNode is used - if (!this._batchNode) { - // Set a compatible default for the alpha transfer - retParticle._opacityModifyRGB = this._opacityModifyRGB; - - // texture - retParticle._texture = this._texture; - } - } - return retParticle; - }, - - /** - *

Sets a new CCSpriteFrame as particle.
- * WARNING: this method is experimental. Use setTexture:withRect instead. - *

- * @param {cc.SpriteFrame} spriteFrame - */ - setDisplayFrame:function (spriteFrame) { - cc.Assert(cc._rectEqualToZero(spriteFrame.getOffsetInPixels()), "QuadParticle only supports SpriteFrames with no offsets"); - - // update texture before updating texture rect - if (cc.renderContextType === cc.WEBGL) - if (!this._texture || spriteFrame.getTexture()._webTextureObj != this._texture._webTextureObj) - this.setTexture(spriteFrame.getTexture()); - }, - - /** - * Sets a new texture with a rect. The rect is in Points. - * @param {cc.Texture2D} texture - * @param {cc.Rect} rect - */ - setTextureWithRect:function (texture, rect) { - if (cc.renderContextType === cc.WEBGL) { - // Only update the texture if is different from the current one - if (!this._texture || texture._webTextureObj != this._texture._webTextureObj) - cc.ParticleSystem.prototype.setTexture.call(this, texture); - this._pointRect = rect; - this.initTexCoordsWithRect(rect); - } else { - if (!this._texture || texture != this._texture) - cc.ParticleSystem.prototype.setTexture.call(this, texture); - this._pointRect = rect; - this.initTexCoordsWithRect(rect); - } - }, - - // super methods - // overriding the init method - /** - * Initializes a system with a fixed number of particles - * @override - * @param {Number} numberOfParticles - * @return {Boolean} - */ - initWithTotalParticles:function (numberOfParticles) { - // base initialization - if (cc.ParticleSystem.prototype.initWithTotalParticles.call(this, numberOfParticles)) { - if (cc.renderContextType === cc.CANVAS) - return true; - - // allocating data space - if (!this._allocMemory()) - return false; - - this.initIndices(); - //if (cc.TEXTURE_ATLAS_USE_VAO) - // this._setupVBOandVAO(); - //else - this._setupVBO(); - - this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_TEXTURECOLOR)); - return true; - } - return false; - }, - - /** - * set Texture of Particle System - * @override - * @param {cc.Texture2D} texture - */ - setTexture:function (texture) { - if(texture.isLoaded()){ - var size = texture.getContentSize(); - this.setTextureWithRect(texture, cc.rect(0, 0, size.width, size.height)); - } else { - this._textureLoaded = false; - texture.addLoadedEventListener(function(sender){ - this._textureLoaded = true; - var size = sender.getContentSize(); - this.setTextureWithRect(sender, cc.rect(0, 0, size.width, size.height)); - }, this); - } - }, - - /** - * update particle's quad - * @override - * @param {cc.Particle} particle - * @param {cc.Point} newPosition - */ - updateQuadWithParticle:function (particle, newPosition) { - var quad = null; - if (this._batchNode) { - var batchQuads = this._batchNode.getTextureAtlas().getQuads(); - quad = batchQuads[this._atlasIndex + particle.atlasIndex]; - this._batchNode.getTextureAtlas()._dirty = true; - - } else - quad = this._quads[this._particleIdx]; - - var r, g, b, a; - if(this._opacityModifyRGB){ - r = 0 | (particle.color.r * particle.color.a * 255); - g = 0 | (particle.color.g * particle.color.a * 255); - b = 0 | (particle.color.b * particle.color.a * 255); - a = 0 | (particle.color.a * 255); - }else{ - r = 0 | (particle.color.r * 255); - g = 0 | (particle.color.g * 255); - b = 0 | (particle.color.b * 255); - a = 0 | (particle.color.a * 255); - } - - var locColors = quad.bl.colors; - locColors.r = r; - locColors.g = g; - locColors.b = b; - locColors.a = a; - - locColors = quad.br.colors; - locColors.r = r; - locColors.g = g; - locColors.b = b; - locColors.a = a; - - locColors = quad.tl.colors; - locColors.r = r; - locColors.g = g; - locColors.b = b; - locColors.a = a; - - locColors = quad.tr.colors; - locColors.r = r; - locColors.g = g; - locColors.b = b; - locColors.a = a; - - // vertices - var size_2 = particle.size / 2; - if (particle.rotation) { - var x1 = -size_2; - var y1 = -size_2; - - var x2 = size_2; - var y2 = size_2; - var x = newPosition.x; - var y = newPosition.y; - - var rad = -cc.DEGREES_TO_RADIANS(particle.rotation); - var cr = Math.cos(rad); - var sr = Math.sin(rad); - var ax = x1 * cr - y1 * sr + x; - var ay = x1 * sr + y1 * cr + y; - var bx = x2 * cr - y1 * sr + x; - var by = x2 * sr + y1 * cr + y; - var cx = x2 * cr - y2 * sr + x; - var cy = x2 * sr + y2 * cr + y; - var dx = x1 * cr - y2 * sr + x; - var dy = x1 * sr + y2 * cr + y; - - // bottom-left - quad.bl.vertices.x = ax; - quad.bl.vertices.y = ay; - - // bottom-right vertex: - quad.br.vertices.x = bx; - quad.br.vertices.y = by; - - // top-left vertex: - quad.tl.vertices.x = dx; - quad.tl.vertices.y = dy; - - // top-right vertex: - quad.tr.vertices.x = cx; - quad.tr.vertices.y = cy; - } else { - // bottom-left vertex: - quad.bl.vertices.x = newPosition.x - size_2; - quad.bl.vertices.y = newPosition.y - size_2; - - // bottom-right vertex: - quad.br.vertices.x = newPosition.x + size_2; - quad.br.vertices.y = newPosition.y - size_2; - - // top-left vertex: - quad.tl.vertices.x = newPosition.x - size_2; - quad.tl.vertices.y = newPosition.y + size_2; - - // top-right vertex: - quad.tr.vertices.x = newPosition.x + size_2; - quad.tr.vertices.y = newPosition.y + size_2; - } - }, - - /** - * override cc.ParticleSystem - * @override - */ - postStep:function () { - if (cc.renderContextType === cc.WEBGL) { - var gl = cc.renderContext; - - gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); - gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW); - - // Option 2: Data - // glBufferData(GL_ARRAY_BUFFER, sizeof(quads_[0]) * particleCount, quads_, GL_DYNAMIC_DRAW); - - // Option 3: Orphaning + glMapBuffer - // glBufferData(GL_ARRAY_BUFFER, sizeof(m_pQuads[0])*m_uTotalParticles, NULL, GL_STREAM_DRAW); - // void *buf = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - // memcpy(buf, m_pQuads, sizeof(m_pQuads[0])*m_uTotalParticles); - // glUnmapBuffer(GL_ARRAY_BUFFER); - - //cc.CHECK_GL_ERROR_DEBUG(); - } - }, - - /** - * draw particle - * @param {CanvasContext} ctx CanvasContext - * @override - */ - draw:function (ctx) { - cc.Assert(!this._batchNode, "draw should not be called when added to a particleBatchNode"); - if(!this._textureLoaded) - return; - - if (cc.renderContextType === cc.CANVAS) - this._drawForCanvas(ctx); - else - this._drawForWebGL(ctx); - - cc.g_NumberOfDraws++; - }, - - _drawForCanvas:function (ctx) { - var context = ctx || cc.renderContext; - context.save(); - if (this.isBlendAdditive()) - context.globalCompositeOperation = 'lighter'; - else - context.globalCompositeOperation = 'source-over'; - - for (var i = 0; i < this._particleCount; i++) { - var particle = this._particles[i]; - var lpx = (0 | (particle.size * 0.5)); - - if (this._drawMode == cc.PARTICLE_TEXTURE_MODE) { - - var element = this._texture.getHtmlElementObj(); - - // Delay drawing until the texture is fully loaded by the browser - if (!element.width || !element.height) - continue; - - context.save(); - context.globalAlpha = particle.color.a; - context.translate((0 | particle.drawPos.x), -(0 | particle.drawPos.y)); - - var size = Math.floor(particle.size / 4) * 4; - var w = this._pointRect.width; - var h = this._pointRect.height; - - context.scale( - Math.max((1 / w) * size, 0.000001), - Math.max((1 / h) * size, 0.000001) - ); - - - if (particle.rotation) - context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation)); - - context.translate(-(0 | (w / 2)), -(0 | (h / 2))); - if (particle.isChangeColor) { - - var cacheTextureForColor = cc.TextureCache.getInstance().getTextureColors(element); - if (cacheTextureForColor) { - // Create another cache for the tinted version - // This speeds up things by a fair bit - if (!cacheTextureForColor.tintCache) { - cacheTextureForColor.tintCache = document.createElement('canvas'); - cacheTextureForColor.tintCache.width = element.width; - cacheTextureForColor.tintCache.height = element.height; - } - cc.generateTintImage(element, cacheTextureForColor, particle.color, this._pointRect, cacheTextureForColor.tintCache); - element = cacheTextureForColor.tintCache; - } - } - - context.drawImage(element, 0, 0); - context.restore(); - - } else { - context.save(); - context.globalAlpha = particle.color.a; - - context.translate(0 | particle.drawPos.x, -(0 | particle.drawPos.y)); - - if (this._shapeType == cc.PARTICLE_STAR_SHAPE) { - if (particle.rotation) - context.rotate(cc.DEGREES_TO_RADIANS(particle.rotation)); - cc.drawingUtil.drawStar(context, lpx, particle.color); - } else - cc.drawingUtil.drawColorBall(context, lpx, particle.color); - context.restore(); - } - } - context.restore(); - }, - - _drawForWebGL:function (ctx) { - if(!this._texture) - return; - - var gl = ctx || cc.renderContext; - - this._shaderProgram.use(); - this._shaderProgram.setUniformForModelViewAndProjectionMatrixWithMat4(); - - cc.glBindTexture2D(this._texture); - cc.glBlendFuncForParticle(this._blendFunc.src, this._blendFunc.dst); - - //cc.Assert(this._particleIdx == this._particleCount, "Abnormal error in particle quad"); - - // - // Using VBO without VAO - // - cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSCOLORTEX); - - gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 3, gl.FLOAT, false, 24, 0); // vertices - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, 24, 12); // colors - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, 24, 16); // tex coords - - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); - gl.drawElements(gl.TRIANGLES, this._particleIdx * 6, gl.UNSIGNED_SHORT, 0); - }, - - setBatchNode:function (batchNode) { - if (this._batchNode != batchNode) { - var oldBatch = this._batchNode; - cc.ParticleSystem.prototype.setBatchNode.call(this, batchNode); - - // NEW: is self render ? - if (!batchNode) { - this._allocMemory(); - this.initIndices(); - this.setTexture(oldBatch.getTexture()); - //if (cc.TEXTURE_ATLAS_USE_VAO) - // this._setupVBOandVAO(); - //else - this._setupVBO(); - } else if (!oldBatch) { - // OLD: was it self render cleanup ? - // copy current state to batch - this._batchNode.getTextureAtlas()._copyQuadsToTextureAtlas(this._quads, this._atlasIndex); - - //delete buffer - cc.renderContext.deleteBuffer(this._buffersVBO[1]); //where is re-bindBuffer code? - - //if (cc.TEXTURE_ATLAS_USE_VAO) - // glDeleteVertexArrays(1, this._VAOname); - } - } - }, - - setTotalParticles:function (tp) { - if (cc.renderContextType === cc.CANVAS){ - this._totalParticles = (tp < 200) ? tp : 200; - return; - } - - // If we are setting the total numer of particles to a number higher - // than what is allocated, we need to allocate new arrays - if (tp > this._allocatedParticles) { - var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; - // Allocate new memory - this._indices = new Uint16Array(tp * 6); - var locQuadsArrayBuffer = new ArrayBuffer(tp * quadSize); - //TODO need fix - // Assign pointers - var locParticles = []; - var locQuads = []; - for (var j = 0; j < tp; j++) { - locParticles[j] = new cc.Particle(); - locQuads[j] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, j * quadSize); - } - this._allocatedParticles = tp; - this._totalParticles = tp; - - // Init particles - if (this._batchNode) { - for (var i = 0; i < tp; i++) - locParticles[i].atlasIndex = i; - } - - this._particles = locParticles; - this._quadsArrayBuffer = locQuadsArrayBuffer; - this._quads = locQuads; - - this.initIndices(); - //if (cc.TEXTURE_ATLAS_USE_VAO) - // this._setupVBOandVAO(); - //else - this._setupVBO(); - - //set the texture coord - if(this._texture){ - var size = this._texture.getContentSize(); - this.initTexCoordsWithRect(cc.rect(0, 0, size.width, size.height)); - } - } else - this._totalParticles = tp; - this.resetSystem(); - }, - - /** - * listen the event that coming to foreground on Android - * @param {cc.Class} obj - */ - listenBackToForeground:function (obj) { - if (cc.TEXTURE_ATLAS_USE_VAO) - this._setupVBOandVAO(); - else - this._setupVBO(); - }, - - _setupVBOandVAO:function () { - //Not support on WebGL - /*if (cc.renderContextType == cc.CANVAS) { - return; - }*/ - - //NOT SUPPORTED - /*glGenVertexArrays(1, this._VAOname); - glBindVertexArray(this._VAOname); - - var kQuadSize = sizeof(m_pQuads[0].bl); - - glGenBuffers(2, this._buffersVBO[0]); - - glBindBuffer(GL_ARRAY_BUFFER, this._buffersVBO[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(this._quads[0]) * this._totalParticles, this._quads, GL_DYNAMIC_DRAW); - - // vertices - glEnableVertexAttribArray(kCCVertexAttrib_Position); - glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, vertices)); - - // colors - glEnableVertexAttribArray(kCCVertexAttrib_Color); - glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, offsetof(ccV3F_C4B_T2F, colors)); - - // tex coords - glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); - glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, offsetof(ccV3F_C4B_T2F, texCoords)); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_pIndices[0]) * m_uTotalParticles * 6, m_pIndices, GL_STATIC_DRAW); - - glBindVertexArray(0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - CHECK_GL_ERROR_DEBUG();*/ - }, - - _setupVBO:function () { - if (cc.renderContextType == cc.CANVAS) - return; - - var gl = cc.renderContext; - - //gl.deleteBuffer(this._buffersVBO[0]); - this._buffersVBO[0] = gl.createBuffer(); - gl.bindBuffer(gl.ARRAY_BUFFER, this._buffersVBO[0]); - gl.bufferData(gl.ARRAY_BUFFER, this._quadsArrayBuffer, gl.DYNAMIC_DRAW); - - this._buffersVBO[1] = gl.createBuffer(); - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._buffersVBO[1]); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._indices, gl.STATIC_DRAW); - - //cc.CHECK_GL_ERROR_DEBUG(); - }, - - _allocMemory:function () { - if (cc.renderContextType === cc.CANVAS) - return; - - //cc.Assert((!this._quads && !this._indices), "Memory already allocated"); - cc.Assert(!this._batchNode, "Memory should not be allocated when not using batchNode"); - var quadSize = cc.V3F_C4B_T2F_Quad.BYTES_PER_ELEMENT; - var totalParticles = this._totalParticles; - var locQuads = []; - this._indices = new Uint16Array(totalParticles * 6); - var locQuadsArrayBuffer = new ArrayBuffer(quadSize * totalParticles); - - for (var i = 0; i < totalParticles; i++) - locQuads[i] = new cc.V3F_C4B_T2F_Quad(null, null, null, null, locQuadsArrayBuffer, i * quadSize); - if (!locQuads || !this._indices) { - cc.log("cocos2d: Particle system: not enough memory"); - return false; - } - this._quads = locQuads; - this._quadsArrayBuffer = locQuadsArrayBuffer; - return true; - } -}); - -/** - *

- * creates an initializes a CCParticleSystemQuad from a plist file.
- * This plist files can be creted manually or with Particle Designer:
- * http://particledesigner.71squared.com/
- *

- * @param {String|Number} pListFile - * @return {cc.ParticleSystem} - * @example - * //creates an initializes a CCParticleSystemQuad from a plist file. - * var system = cc.ParticleSystemQuad.create("Images/SpinningPeas.plist"); - */ -cc.ParticleSystemQuad.create = function (pListFile) { - var ret = new cc.ParticleSystemQuad(); - if (!pListFile || typeof(pListFile) === "number") { - var ton = pListFile || 100; - ret.setDrawMode(cc.PARTICLE_TEXTURE_MODE); - ret.initWithTotalParticles(ton); - return ret; - } - - if (ret && ret.initWithFile(pListFile)) - return ret; - return null; -}; - -cc.ParticleSystemQuad.createWithTotalParticles = function (numberOfParticles) { - return cc.ParticleSystemQuad.create(numberOfParticles); -}; - -cc.ARCH_OPTIMAL_PARTICLE_SYSTEM = cc.ParticleSystemQuad; diff --git a/cocos2d/platform/CCTypes.js b/cocos2d/platform/CCTypes.js index 8658a80a4e..8ab9dff686 100644 --- a/cocos2d/platform/CCTypes.js +++ b/cocos2d/platform/CCTypes.js @@ -683,7 +683,7 @@ cc.T2F_Quad = function(bl, br, tl, tr){ }; /** - * struct that holds the size in pixels, texture coordinates and delays for animated cc.ParticleSystemQuad + * struct that holds the size in pixels, texture coordinates and delays for animated cc.ParticleSystem * @param {cc.T2F_Quad} texCoords * @param delay * @param size diff --git a/cocos2d/platform/jsloader.js b/cocos2d/platform/jsloader.js index e5d65f1b42..19bfa526ab 100644 --- a/cocos2d/platform/jsloader.js +++ b/cocos2d/platform/jsloader.js @@ -110,7 +110,6 @@ 'label_nodes/CCLabelTTF.js', 'label_nodes/CCLabelBMFont.js', 'particle_nodes/CCParticleSystem.js', - 'particle_nodes/CCParticleSystemQuad.js', 'particle_nodes/CCParticleExamples.js', 'particle_nodes/CCParticleBatchNode.js', 'touch_dispatcher/CCTouchDelegateProtocol.js', diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 6c0b3e5fdf..94eabf6e75 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -999,7 +999,8 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ this._blendFunc = src; else this._blendFunc = {src: src, dst: dst}; - this._isLighterMode = (this._blendFunc && (this._blendFunc.src === gl.SRC_ALPHA) && (this._blendFunc.dst === gl.ONE)); + this._isLighterMode = (this._blendFunc && + (( this._blendFunc.src == gl.SRC_ALPHA && this._blendFunc.dst == gl.ONE) || (this._blendFunc.src == gl.ONE && this._blendFunc.dst == gl.ONE))); }, /** diff --git a/cocos2d/sprite_nodes/CCSpriteFrameCache.js b/cocos2d/sprite_nodes/CCSpriteFrameCache.js index 90f7336750..20b0d0d32f 100644 --- a/cocos2d/sprite_nodes/CCSpriteFrameCache.js +++ b/cocos2d/sprite_nodes/CCSpriteFrameCache.js @@ -161,8 +161,10 @@ cc.SpriteFrameCache = cc.Class.extend(/** @lends cc.SpriteFrameCache# */{ /** * Adds multiple Sprite Frames from a json file. A texture will be loaded automatically. * @param {object} jsonData + * @deprecated */ addSpriteFramesWithJson:function (jsonData) { + cc.log("addSpriteFramesWithJson is deprecated, because Json format doesn't support on JSB. Use XML format instead"); var dict = jsonData; var texturePath = ""; diff --git a/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js b/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js index 3e0d73d2f4..fc2a42af7a 100644 --- a/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js +++ b/cocos2d/touch_dispatcher/CCTouchDelegateProtocol.js @@ -137,7 +137,7 @@ cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{ /** * Virtual function - * @param {cc.Touch} touch + * @param {Array} touches * @param {event} event */ onTouchesBegan:function (touches, event) { @@ -145,7 +145,7 @@ cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{ /** * Virtual function - * @param {cc.Touch} touch + * @param {Array} touches * @param {event} event */ onTouchesMoved:function (touches, event) { @@ -153,7 +153,7 @@ cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{ /** * Virtual function - * @param {cc.Touch} touch + * @param {Array} touches * @param {event} event */ onTouchesEnded:function (touches, event) { @@ -161,7 +161,7 @@ cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{ /** * Virtual function - * @param {cc.Touch} touch + * @param {Array} touches * @param {event} event */ onTouchesCancelled:function (touches, event) { @@ -169,7 +169,7 @@ cc.TouchDelegate = cc.Class.extend(/** @lends cc.TouchDelegate# */{ /* * In TouchesTest, class Padle inherits from cc.Sprite and cc.TargetedTouchDelegate. - * When it invoke cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, 0, true), + * When it invoke cc.registerTargetedDelegate(0, true, this), * it will crash in cc.TouchHandler.initWithDelegate() because of dynamic_cast() on android. * I don't know why, so add these functions for the subclass to invoke it's own retain() and release *Virtual function diff --git a/cocos2d/touch_dispatcher/CCTouchDispatcher.js b/cocos2d/touch_dispatcher/CCTouchDispatcher.js index 933adb9408..d935ecb1d0 100644 --- a/cocos2d/touch_dispatcher/CCTouchDispatcher.js +++ b/cocos2d/touch_dispatcher/CCTouchDispatcher.js @@ -178,11 +178,12 @@ cc.TouchDispatcher = cc.Class.extend(/** @lends cc.TouchDispatcher# */ { * Adds a standard touch delegate to the dispatcher's list. * See StandardTouchDelegate description. * IMPORTANT: The delegate will be retained. - * @param {cc.TouchDelegate} delegate - * @param {Number} priority + * @param {Object} delegate + * @param {Number} [priority=0] */ - addStandardDelegate:function (delegate, priority) { - var handler = cc.StandardTouchHandler.handlerWithDelegate(delegate, priority); + _addStandardDelegate:function (delegate, priority) { + priority = priority || 0; + var handler = cc.StandardTouchHandler.create(delegate, priority); if (!this._locked) { this._standardHandlers = this.forceAddHandler(handler, this._standardHandlers); @@ -201,12 +202,12 @@ cc.TouchDispatcher = cc.Class.extend(/** @lends cc.TouchDispatcher# */ { }, /** - * @param {cc.TouchDelegate} delegate + * @param {Object} delegate * @param {Number} priority * @param {Boolean} swallowsTouches */ - addTargetedDelegate:function (delegate, priority, swallowsTouches) { - var handler = cc.TargetedTouchHandler.handlerWithDelegate(delegate, priority, swallowsTouches); + _addTargetedDelegate:function (delegate, priority, swallowsTouches) { + var handler = cc.TargetedTouchHandler.create(delegate, priority, swallowsTouches); if (!this._locked) { this._targetedHandlers = this.forceAddHandler(handler, this._targetedHandlers); } else { @@ -259,7 +260,7 @@ cc.TouchDispatcher = cc.Class.extend(/** @lends cc.TouchDispatcher# */ { * The delegate will be released * @param {cc.TouchDelegate} delegate */ - removeDelegate:function (delegate) { + _removeDelegate:function (delegate) { if (delegate == null) { return; } @@ -1031,3 +1032,31 @@ cc.TouchDispatcher._preTouchPool = []; * @type {Number} */ cc.TouchDispatcher._preTouchPoolPointer = 0; + +/** + * register a targeted touch delegate to the dispatcher's list. + * @param {Number} priority + * @param {Boolean} swallowsTouches + * @param {Object} delegate + */ +cc.registerTargetedDelegate = function(priority, swallowsTouches, delegate){ + cc.Director.getInstance().getTouchDispatcher()._addTargetedDelegate(delegate, priority, swallowsTouches); +}; + +/** + * Adds a standard touch delegate to the dispatcher's list. + * See StandardTouchDelegate description. + * @param {Object} delegate + * @param {Number} [priority=] + */ +cc.registerStandardDelegate = function(delegate, priority){ + cc.Director.getInstance().getTouchDispatcher()._addStandardDelegate(delegate, priority); +}; + +/** + * Removes a touch delegate. from TouchDispatcher + * @param delegate + */ +cc.unregisterTouchDelegate = function(delegate){ + cc.Director.getInstance().getTouchDispatcher()._removeDelegate(delegate); +}; \ No newline at end of file diff --git a/cocos2d/touch_dispatcher/CCTouchHandler.js b/cocos2d/touch_dispatcher/CCTouchHandler.js index 90f010cceb..cd3bb2c647 100644 --- a/cocos2d/touch_dispatcher/CCTouchHandler.js +++ b/cocos2d/touch_dispatcher/CCTouchHandler.js @@ -94,12 +94,12 @@ cc.TouchHandler = cc.Class.extend(/** @lends cc.TouchHandler# */{ }); /** - * Allocates a TouchHandler with a delegate and a priority + * Create a TouchHandler with a delegate and a priority * @param {cc.TouchDelegate} delegate * @param {Number} priority * @return {cc.TouchHandler} */ -cc.TouchHandler.handlerWithDelegate = function (delegate, priority) { +cc.TouchHandler.create = function (delegate, priority) { var handler = new cc.TouchHandler(); if (handler) { handler.initWithDelegate(delegate, priority); @@ -126,12 +126,12 @@ cc.StandardTouchHandler = cc.TouchHandler.extend(/** @lends cc.StandardTouchHand }); /** - * Allocates a TouchHandler with a delegate and a priority - * @param {cc.TouchDelegate} delegate + * Create a TouchHandler with a delegate and a priority + * @param {Object} delegate * @param {Number} priority * @return {cc.StandardTouchHandler} */ -cc.StandardTouchHandler.handlerWithDelegate = function (delegate, priority) { +cc.StandardTouchHandler.create = function (delegate, priority) { var handler = new cc.StandardTouchHandler(); if (handler) { handler.initWithDelegate(delegate, priority); @@ -188,13 +188,13 @@ cc.TargetedTouchHandler = cc.TouchHandler.extend(/** @lends cc.TargetedTouchHand }); /** - * Allocates a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not - * @param {cc.TouchDelegate} delegate + * Create a TargetedTouchHandler with a delegate, a priority and whether or not it swallows touches or not + * @param {Object} delegate * @param {Number} priority * @param {Boolean} swallow * @return {cc.TargetedTouchHandler} */ -cc.TargetedTouchHandler.handlerWithDelegate = function (delegate, priority, swallow) { +cc.TargetedTouchHandler.create = function (delegate, priority, swallow) { var handler = new cc.TargetedTouchHandler(); if (handler) { handler.initWithDelegate(delegate, priority, swallow); diff --git a/extensions/CCBReader/CCNodeLoaderLibrary.js b/extensions/CCBReader/CCNodeLoaderLibrary.js index 001437bf49..cff3b6996b 100644 --- a/extensions/CCBReader/CCNodeLoaderLibrary.js +++ b/extensions/CCBReader/CCNodeLoaderLibrary.js @@ -45,7 +45,7 @@ cc.NodeLoaderLibrary = cc.Class.extend({ this.registerCCNodeLoader("CCMenu", cc.MenuLoader.loader()); this.registerCCNodeLoader("CCMenuItemImage", cc.MenuItemImageLoader.loader()); this.registerCCNodeLoader("CCControlButton", cc.ControlButtonLoader.loader()); - this.registerCCNodeLoader("CCParticleSystemQuad", cc.ParticleSystemQuadLoader.loader()); + this.registerCCNodeLoader("CCParticleSystemQuad", cc.ParticleSystemLoader.loader()); }, registerCCNodeLoader:function(className,ccNodeLoader){ diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 4021ae1706..68644dea69 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -418,9 +418,9 @@ var PROPERTY_STARTRADIUS = "startRadius"; var PROPERTY_ENDRADIUS = "endRadius"; var PROPERTY_ROTATEPERSECOND = "rotatePerSecond"; -cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ +cc.ParticleSystemLoader = cc.NodeLoader.extend({ _createCCNode:function (parent, ccbReader) { - return cc.ParticleSystemQuad.create(); + return cc.ParticleSystem.create(); }, onHandlePropTypeIntegerLabeled:function (node, parent, propertyName, integerLabeled, ccbReader) { @@ -523,8 +523,8 @@ cc.ParticleSystemQuadLoader = cc.NodeLoader.extend({ } }); -cc.ParticleSystemQuadLoader.loader = function () { - return new cc.ParticleSystemQuadLoader(); +cc.ParticleSystemLoader.loader = function () { + return new cc.ParticleSystemLoader(); }; diff --git a/extensions/CocoStudio/Armature/display/CCDisplayFactory.js b/extensions/CocoStudio/Armature/display/CCDisplayFactory.js index cfacad1204..9def225c85 100644 --- a/extensions/CocoStudio/Armature/display/CCDisplayFactory.js +++ b/extensions/CocoStudio/Armature/display/CCDisplayFactory.js @@ -187,7 +187,7 @@ cc.DisplayFactory.addParticleDisplay = function (bone, decoDisplay, displayData) }; cc.DisplayFactory.createParticleDisplay = function (bone, decoDisplay) { var displayData = decoDisplay.getDisplayData(); - var system = cc.ParticleSystemQuad.create(displayData.plist); + var system = cc.ParticleSystem.create(displayData.plist); decoDisplay.setDisplay(system); }; cc.DisplayFactory.updateParticleDisplay = function (bone, particleSystem, dt, dirty) { diff --git a/extensions/CocoStudio/Armature/display/CCDisplayManager.js b/extensions/CocoStudio/Armature/display/CCDisplayManager.js index 0dbee6adef..55550f6655 100644 --- a/extensions/CocoStudio/Armature/display/CCDisplayManager.js +++ b/extensions/CocoStudio/Armature/display/CCDisplayManager.js @@ -82,7 +82,7 @@ cc.DisplayManager = cc.Class.extend({ else skin.setSkinData(new cc.BaseData()); } - else if (display instanceof cc.ParticleSystemQuad){ + else if (display instanceof cc.ParticleSystem){ displayData = new cc.ParticleDisplayData(); } else if (display instanceof cc.Armature){ @@ -174,7 +174,7 @@ cc.DisplayManager = cc.Class.extend({ if (displayRenderNode) { if (displayRenderNode instanceof cc.Armature) { this._bone.setChildArmature(displayRenderNode); - }else if(displayRenderNode instanceof cc.ParticleSystemQuad) { + }else if(displayRenderNode instanceof cc.ParticleSystem) { displayRenderNode.resetSystem(); } if (displayRenderNode.RGBAProtocol) { diff --git a/extensions/GUI/CCControlExtension/CCControl.js b/extensions/GUI/CCControlExtension/CCControl.js index 14836390d0..9a1a837939 100644 --- a/extensions/GUI/CCControlExtension/CCControl.js +++ b/extensions/GUI/CCControlExtension/CCControl.js @@ -164,7 +164,7 @@ cc.Control = cc.LayerRGBA.extend({ }, registerWithTouchDispatcher:function () { - cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this.getTouchPriority(), true); + cc.registerTargetedDelegate(this.getTouchPriority(), true, this); }, /** diff --git a/extensions/GUI/CCScrollView/CCScrollView.js b/extensions/GUI/CCScrollView/CCScrollView.js index 2d2180a775..279b8f3d2f 100644 --- a/extensions/GUI/CCScrollView/CCScrollView.js +++ b/extensions/GUI/CCScrollView/CCScrollView.js @@ -101,7 +101,7 @@ cc.ScrollView = cc.Layer.extend({ }, registerWithTouchDispatcher:function () { - cc.Director.getInstance().getTouchDispatcher().addTargetedDelegate(this, this.getTouchPriority(), false); + cc.registerTargetedDelegate(this.getTouchPriority(), false, this); }, /** diff --git a/template/build.xml b/template/build.xml index 4a5e365e1b..e8394e89be 100644 --- a/template/build.xml +++ b/template/build.xml @@ -95,7 +95,6 @@ - diff --git a/tools/jsdoc_toolkit/build.xml b/tools/jsdoc_toolkit/build.xml index 0f1977a8d3..f21d456110 100644 --- a/tools/jsdoc_toolkit/build.xml +++ b/tools/jsdoc_toolkit/build.xml @@ -74,7 +74,6 @@ - From cb64446890bf37434d9dac9ebdbdf28b04e8da8c Mon Sep 17 00:00:00 2001 From: xingsenma Date: Fri, 13 Sep 2013 14:27:49 +0800 Subject: [PATCH 119/141] closed #2805: Fixed a bug of cc.Sprite that displayFrame return wrong value on canvas model. --- cocos2d/sprite_nodes/CCSprite.js | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 8541ff0931..4398b12bbe 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -1682,9 +1682,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ * Returns the current displayed frame. * @return {cc.SpriteFrame} */ - displayFrame: null, - - _displayFrameForWebGL: function () { + displayFrame: function () { return cc.SpriteFrame.createWithTexture(this._texture, cc.RECT_POINTS_TO_PIXELS(this._rect), this._rectRotated, @@ -1692,14 +1690,6 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ cc.SIZE_POINTS_TO_PIXELS(this._contentSize)); }, - _displayFrameForCanvas: function () { - return cc.SpriteFrame._frameWithTextureForCanvas(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 @@ -2064,7 +2054,6 @@ if(cc.Browser.supportWebGL){ 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.displayFrame = cc.Sprite.prototype._displayFrameForWebGL; cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForWebGL; cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForWebGL; cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForWebGL; @@ -2085,7 +2074,6 @@ if(cc.Browser.supportWebGL){ 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.displayFrame = cc.Sprite.prototype._displayFrameForCanvas; cc.Sprite.prototype.setBatchNode = cc.Sprite.prototype._setBatchNodeForCanvas; cc.Sprite.prototype.setTexture = cc.Sprite.prototype._setTextureForCanvas; cc.Sprite.prototype.draw = cc.Sprite.prototype._drawForCanvas; From cd85aa5581042202cc0254bd16c47d4c31be7b12 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 13 Sep 2013 14:43:17 +0800 Subject: [PATCH 120/141] fixed #208: fixed a TMXLayer's bug --- cocos2d/sprite_nodes/CCSpriteBatchNode.js | 3 +- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 36 +++++++++++++++----- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSpriteBatchNode.js b/cocos2d/sprite_nodes/CCSpriteBatchNode.js index d3a7f2b549..535d3e7ae3 100644 --- a/cocos2d/sprite_nodes/CCSpriteBatchNode.js +++ b/cocos2d/sprite_nodes/CCSpriteBatchNode.js @@ -479,8 +479,7 @@ cc.SpriteBatchNode = cc.Node.extend(/** @lends cc.SpriteBatchNode# */{ // make needed room var locTextureAtlas = this._textureAtlas; - var locCapacity = locTextureAtlas.getCapacity(); - while (index >= locCapacity || locCapacity === locTextureAtlas.getTotalQuads()) + while (index >= locTextureAtlas.getCapacity() || locTextureAtlas.getCapacity() === locTextureAtlas.getTotalQuads()) this.increaseAtlasCapacity(); // diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index 5402ad5056..ce9d429f57 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -71,6 +71,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ _cacheCanvas:null, _cacheContext:null, + _cacheTexture:null, /** * Constructor @@ -90,6 +91,10 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ tmpCanvas.height = locCanvas.height; this._cacheCanvas = tmpCanvas; this._cacheContext = this._cacheCanvas.getContext('2d'); + var tempTexture = new cc.Texture2D(); + tempTexture.initWithElement(tmpCanvas); + tempTexture.handleLoadedTexture(); + this._cacheTexture = tempTexture; this.setContentSize(cc.size(locCanvas.width, locCanvas.height)); } }, @@ -100,18 +105,25 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ cc.Node.prototype.setContentSize.call(this, size); if(cc.renderContextType === cc.CANVAS){ - this._cacheCanvas.width = size.width * 1.5; - this._cacheCanvas.height = size.height * 1.5; - this._cacheContext.translate(0, this._cacheCanvas.height); + var locCanvas = this._cacheCanvas; + locCanvas.width = 0|(size.width * 1.5); + locCanvas.height = 0|(size.height * 1.5); + this._cacheContext.translate(0, locCanvas.height); + var locContentSize = this._cacheTexture._contentSize; + locContentSize.width = locCanvas.width; + locContentSize.height = locCanvas.height; } }, /** * Return texture of cc.SpriteBatchNode - * @return {cc.Texture2D|HTMLImageElement|HTMLCanvasElement} + * @return {cc.Texture2D} */ getTexture:function () { - return this._cacheCanvas; + if(cc.renderContextType === cc.CANVAS) + return this._cacheTexture; + else + return cc.SpriteBatchNode.prototype.getTexture.call(this); }, /** @@ -158,7 +170,9 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ * draw cc.SpriteBatchNode (override draw of cc.Node) * @param {CanvasRenderingContext2D} ctx */ - draw:function (ctx) { + draw:null, + + _drawForCanvas:function (ctx) { var context = ctx || cc.renderContext; //context.globalAlpha = this._opacity / 255; var posX = 0 | ( -this._anchorPointInPoints.x), posY = 0 | ( -this._anchorPointInPoints.y); @@ -466,7 +480,7 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ var sprite = this.getChildByTag(z); if (sprite) - cc.SpriteBatchNode.prototype.removeChild.call(this,sprite,true); //this.removeChild(sprite, true); + cc.SpriteBatchNode.prototype.removeChild.call(this, sprite, true); //this.removeChild(sprite, true); else { if(cc.renderContextType === cc.WEBGL) this._textureAtlas.removeQuadAtIndex(atlasIndex); @@ -807,8 +821,6 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ this._reusedTile.initWithTexture(this._textureForCanvas, rect, false); this._reusedTile.setBatchNode(this); this._reusedTile.setParent(this); - - return this._reusedTile; } return this._reusedTile; }, @@ -862,6 +874,12 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ } }); +if(cc.Browser.supportWebGL){ + cc.TMXLayer.prototype.draw = cc.SpriteBatchNode.prototype.draw; +}else{ + cc.TMXLayer.prototype.draw = cc.TMXLayer.prototype._drawForCanvas; +} + /** * Creates a cc.TMXLayer with an tile set info, a layer info and a map info * @param {cc.TMXTilesetInfo} tilesetInfo From 7c62f5f08efddde4932c2d987eebcc9bb0ae4283 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Fri, 13 Sep 2013 18:32:47 +0800 Subject: [PATCH 121/141] Closed #2806: Correct a mistake of cc.clone --- cocos2d/platform/CCCommon.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cocos2d/platform/CCCommon.js b/cocos2d/platform/CCCommon.js index ac38bc2a46..9fd76a5523 100644 --- a/cocos2d/platform/CCCommon.js +++ b/cocos2d/platform/CCCommon.js @@ -48,9 +48,9 @@ cc.clone = function (obj) { // derived class forgets to set "constructor" on the prototype. We ignore // these possibities for and the ultimate solution is a standardized // Object.clone(). - var newObj = new obj.constructor; + var newObj = (obj.constructor) ? new obj.constructor : {}; - // Assuming that the constuctor above initialized all properies on obj, the + // Assuming that the constuctor above initialized all properies on obj, the // following keyed assignments won't turn newObj into dictionary mode // becasue they're not *appending new properties* but *assigning existing // ones* (note that appending indexed properties is another story). See @@ -71,10 +71,10 @@ cc.clone = function (obj) { /** * Function added for JS bindings compatibility. Not needed in cocos2d-html5. * @function - * @param {object} jsobj subclass - * @param {object} klass superclass + * @param {object} jsObj subclass + * @param {object} superclass */ -cc.associateWithNative = function (jsobj, superclass) { +cc.associateWithNative = function (jsObj, superclass) { }; /** From 83bed39ba4c52ca5e1375da65de07152eeaa456b Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 10:59:35 +0800 Subject: [PATCH 122/141] Issue #2803: updated CHANGELOG.txt and AUTHORS.txt, updated version number and fixed two bugs for releasing v2.1.6 --- AUTHORS.txt | 13 +++++++- CHANGELOG.txt | 33 ++++++++++++++++++- cocos2d/base_nodes/CCNode.js | 2 +- cocos2d/build.xml | 2 +- .../CCTransition.js | 6 ---- cocos2d/menu_nodes/CCMenuItem.js | 2 ++ cocos2d/platform/CCConfig.js | 2 +- samples | 2 +- 8 files changed, 50 insertions(+), 12 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 0016bb9aa8..4ea2107dd3 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -81,7 +81,18 @@ Kang-Hao Lu(Opera/Oupeng) @kennyluck Optimize John Resig's inheritance patter Mark Henderson @MarkEHenderson Code review, LabelTTF and Scale9Sprite bug fix -06wj @06wj CCScheduler improvements +Wang Jing @06wj CCScheduler improvements + Js file loading image add + cc.RectApplyAffineTransform improvements + +Wang Zhe @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent + +Christian Schwartz @cschwartz SpriteFrame.initWithTextureFilename converted fix + +Zhen XiaoJun @SmallAiTT _getResType error fix + cc.ScrollView bug fix + +Cheng Guozhu @bengol cc.SimpleAudioEngine bug fix Cocos2d-x and cocos2d-html5 can not grow so fast without the active community. diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a71dc76729..63e3c23aad 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,33 @@ +Cocos2d-html5-v2.1.6 @ Sep.19, 2013 +* Improved Sprite, Node, LabelTTF class define from separated code to combined code for maintainability, now it is clean and clear +* cc.Sprite and its subClasses's texture has been replaced from DOM element to cc.Texture2D on Canvas mode +* Improved cc.Texture2d for direct using without pre-loading image resources, you don't need to wait resources loading when create a new scene or layers +* Migrated CCBReader and GUI to Cocos2d-x 2.1.4 +* Improved update function of Action, and avoid using temporary object, it is good for GC and performance +* Modified LabelTTF's rendering from direct drawing to pre-rendering for performance, 100% faster than before on mobile browser +* Fixed APIs of HTML5 according to JSB for compatibility, e.g. cc.ParticleSystemQuad has merged into cc.ParticleSystem, please check it on upgrade guide v2.1.5 to v2.1.6(wiki link) +* Added Hiding url address bar for mobile browser, please check the template and hello world +* Re-writed Canvas Mode of RenderTexture to adapt WebGL interface +* Added frame event, collider and blend type supporting for Armature. Now Armature supports two tools:1.CocoStudio(windows,http://www.cocostudio.org),2.DragonBones v2.3(flash,http://dragonbones.github.io) +* Set auto render mode default value to canvas in mobile browsers and WebGL in desktop browsers + +* Bug fix: +1. Fixed cc.Sprite's displayFrame returns wrong value on Canvas mode. +2. Fixed cc.LabelBMFont is very slow when calling setString +3. Fixed a bug of CCBReader that cc.ControlButton doesn't work when its controller is _jsControlled +4. Fixed a bug of cc.TextureCache that the status of texture is wrong in callback +5. Fixed a bug of cc.Scale9Sprite that its contentSize is wrong when call setCapInsets +6. Fixed a bug of cc.TableView's that contentSize is wrong when change datasource +7. Fixed a bug of cc.Sprite that its children also follow fliped when it was fliped +8. Fixed cc.Node's nodeToWorldTransform returns wrong value on Canvas Mode +9. Fixed a bug of cc.LayerColor that represent incorrect opacity passed into init method +10. Stop listening and remove the event for HtmlImageElement object onload +11. Fixed cc.ProgressTimer display wrong when its sprite was flipped + +* Known Issues: + 1. Effect Advanced Lens3D doesn't work + 2. ClipNodeTest effects varies in different browsers + Cocos2d-html5-v2.1.5 @ July.24, 2013 * Ported engine API to keep the same as Cocos2d-x v2.1.4 API * Optimized John Resig's inheritance pattern (cc.Class.extend) with advanced property initialization. @@ -8,7 +38,7 @@ Cocos2d-html5-v2.1.5 @ July.24, 2013 * Optimized performance for MoonWarriors and CocosDragonJS * Bug fix: - 1. Fixed cc.EditBox Dom Element position issue when EGLView is setted + 1. Fixed cc.EditBox Dom Element position issue when EGLView is set 2. Fixed cc.EGLView adjustSize bug 3. Fixed the bug of cc.ParticleBatchNode that it doesn't hide particles after particle life has expired when calling stopSystem() 4. Fixed a bug that LabelTTF dimension behavior doesn't support height=0 @@ -17,6 +47,7 @@ Cocos2d-html5-v2.1.5 @ July.24, 2013 * Known Issues: 1. Effect Advanced Lens3D doesn't work 2. ClipNodeTest effects varies in different browsers + 3. nodeToParentTransform in cc.Node returns wrong value on Canvas mode Cocos2d-html5-v2.1.4 @ Jun.12, 2013 * Added support for multiple resources loading. This mechanic is the same as cocos2d-x now diff --git a/cocos2d/base_nodes/CCNode.js b/cocos2d/base_nodes/CCNode.js index f51b32f678..b535ca8829 100644 --- a/cocos2d/base_nodes/CCNode.js +++ b/cocos2d/base_nodes/CCNode.js @@ -468,7 +468,7 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{ /** * The scale factor of the node. 1.0 is the default scale factor. It modifies the X and Y scale at the same time. * @param {Number} scale or scaleX value - * @param {Number} scaleY + * @param {Number} [scaleY=] */ setScale:function (scale, scaleY) { this._scaleX = scale; diff --git a/cocos2d/build.xml b/cocos2d/build.xml index e614520513..59c01d81e2 100644 --- a/cocos2d/build.xml +++ b/cocos2d/build.xml @@ -6,7 +6,7 @@ + debug="false" output="../lib/Cocos2d-html5-v2.1.6.min.js"> diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 20299113f9..0d25903e06 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -546,12 +546,6 @@ cc.TransitionSlideInL = cc.TransitionScene.extend(/** @lends cc.TransitionSlideI this._isInSceneOnTop = false; }, - /** - * Constructor - */ - ctor:function () { - }, - /** * custom on enter */ diff --git a/cocos2d/menu_nodes/CCMenuItem.js b/cocos2d/menu_nodes/CCMenuItem.js index 534c9a88f4..94204b1a34 100644 --- a/cocos2d/menu_nodes/CCMenuItem.js +++ b/cocos2d/menu_nodes/CCMenuItem.js @@ -185,6 +185,8 @@ cc.MenuItem = cc.NodeRGBA.extend(/** @lends cc.MenuItem# */{ activate:function () { if (this._isEnabled) { var locTarget = this._target, locCallback = this._callback; + if(!locCallback) + return ; if (locTarget && (typeof(locCallback) == "string")) { locTarget[locCallback](this); } else if (locTarget && (typeof(locCallback) == "function")) { diff --git a/cocos2d/platform/CCConfig.js b/cocos2d/platform/CCConfig.js index 9e6fdd8bcd..9abd0bfee6 100644 --- a/cocos2d/platform/CCConfig.js +++ b/cocos2d/platform/CCConfig.js @@ -33,7 +33,7 @@ * @constant * @type String */ -cc.ENGINE_VERSION = "Cocos2d-html5-v2.1.5"; +cc.ENGINE_VERSION = "Cocos2d-html5-v2.1.6"; /** *

diff --git a/samples b/samples index b2940ff14b..33632ab4ce 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit b2940ff14bb0efa8dd9006182e19b804bea03eae +Subproject commit 33632ab4ce7b8136352b5985893303b7474a4519 From 5b40cc99b0fd553c8264cad310d83e4edfaae026 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 12:52:58 +0800 Subject: [PATCH 123/141] Issue #2803: correct a mistake in AUTHORS.txt --- AUTHORS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 4ea2107dd3..5dcce9a5bf 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -85,7 +85,7 @@ Wang Jing @06wj CCScheduler improvements Js file loading image add cc.RectApplyAffineTransform improvements -Wang Zhe @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent +Wang Ze @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent Christian Schwartz @cschwartz SpriteFrame.initWithTextureFilename converted fix From 0361117565d6ba1afa74b4768cbec9f8a0d40f62 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 13:53:51 +0800 Subject: [PATCH 124/141] Issue #2803: update a wiki link --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 63e3c23aad..ff7253c96c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,7 +5,7 @@ Cocos2d-html5-v2.1.6 @ Sep.19, 2013 * Migrated CCBReader and GUI to Cocos2d-x 2.1.4 * Improved update function of Action, and avoid using temporary object, it is good for GC and performance * Modified LabelTTF's rendering from direct drawing to pre-rendering for performance, 100% faster than before on mobile browser -* Fixed APIs of HTML5 according to JSB for compatibility, e.g. cc.ParticleSystemQuad has merged into cc.ParticleSystem, please check it on upgrade guide v2.1.5 to v2.1.6(wiki link) +* Fixed APIs of HTML5 according to JSB for compatibility, e.g. cc.ParticleSystemQuad has merged into cc.ParticleSystem, please check it on upgrade guide v2.1.5 to v2.1.6(http://www.cocos2d-x.org/wiki/Upgrade_Guide_from_Cocos2d-html5_v215_to_v216) * Added Hiding url address bar for mobile browser, please check the template and hello world * Re-writed Canvas Mode of RenderTexture to adapt WebGL interface * Added frame event, collider and blend type supporting for Armature. Now Armature supports two tools:1.CocoStudio(windows,http://www.cocostudio.org),2.DragonBones v2.3(flash,http://dragonbones.github.io) From 8b00e7488974ea9cb13a951fd687b6fd5c0f93f2 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 14:33:58 +0800 Subject: [PATCH 125/141] Issue #2803: update submodule reference --- samples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples b/samples index 33632ab4ce..d97d49bc10 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit 33632ab4ce7b8136352b5985893303b7474a4519 +Subproject commit d97d49bc1099ad75bd2ec1b7e787faf04ac3fa56 From ef6f9a47fc9e0c3907f5f760c050791a58993b84 Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 16 Sep 2013 15:43:59 +0800 Subject: [PATCH 126/141] fixed #2806: Correct the errors of CCLabelTTF that labelHeightDiv show on uc browser. --- cocos2d/label_nodes/CCLabelTTF.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cocos2d/label_nodes/CCLabelTTF.js b/cocos2d/label_nodes/CCLabelTTF.js index 3549e19e37..39731b39bd 100644 --- a/cocos2d/label_nodes/CCLabelTTF.js +++ b/cocos2d/label_nodes/CCLabelTTF.js @@ -903,7 +903,6 @@ else cc.LabelTTF.__labelHeightDiv = document.createElement("div"); cc.LabelTTF.__labelHeightDiv.style.fontFamily = "Arial"; -cc.LabelTTF.__labelHeightDiv.innerHTML = "ajghl~!"; cc.LabelTTF.__labelHeightDiv.style.position = "absolute"; cc.LabelTTF.__labelHeightDiv.style.left = "-100px"; cc.LabelTTF.__labelHeightDiv.style.top = "-100px"; @@ -914,10 +913,12 @@ cc.LabelTTF.__getFontHeightByDiv = function(fontName, fontSize){ var clientHeight = cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize]; if (clientHeight > 0) return clientHeight; var labelDiv = cc.LabelTTF.__labelHeightDiv; + labelDiv.innerHTML = "ajghl~!"; labelDiv.style.fontFamily = fontName; labelDiv.style.fontSize = fontSize + "px"; clientHeight = labelDiv.clientHeight ; cc.LabelTTF.__fontHeightCache[fontName + "." + fontSize] = clientHeight; + labelDiv.innerHTML = ""; return clientHeight; }; From a03dbe4e6bbbe3e301d7420d0e1982cd7d8fe66c Mon Sep 17 00:00:00 2001 From: xingsenma Date: Mon, 16 Sep 2013 15:47:15 +0800 Subject: [PATCH 127/141] Bug #2806: Correct the errors of CCArmatureDefine for Cocos2d-Html5 releasing --- extensions/CocoStudio/Armature/utils/CCArmatureDefine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js b/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js index ce00a1f6e1..baf3ae4cad 100644 --- a/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js +++ b/extensions/CocoStudio/Armature/utils/CCArmatureDefine.js @@ -33,4 +33,4 @@ cc.armatureVersion = function(){ return "0.4.0.0"; }; -cc.RESOURCE_TYPE.TEXT.push("ExportJson"); \ No newline at end of file +cc.RESOURCE_TYPE["TEXT"].push("ExportJson"); \ No newline at end of file From 1bd376a4f2cf859c5ddb6bf4dc282a0f465f873e Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 16:22:48 +0800 Subject: [PATCH 128/141] Issue #2803: correct some mistakes in AUTHORS.txt --- AUTHORS.txt | 14 +++++++------- tools/jsdoc_toolkit/build.xml | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 5dcce9a5bf..1f79aa5177 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -25,7 +25,7 @@ Chris @hannon235 added node.js api for box2d Jason Aeschliman @jaeschliman fixed cc.Node setposition -Sun Zhuoshi(Intel) @sunzhuoshi engine loader fixed +Zhuoshi Sun(Intel) @sunzhuoshi engine loader fixed Alejandro Reyero @KaTXi fixed error message @@ -58,7 +58,7 @@ keisuke hata(Square) @Seasons7 Code review, bug fix Marat Yakupov @moadib Various bug fixes -Wu Liang @akira-cn Touch location fix for designResolution +Liang Wu @akira-cn Touch location fix for designResolution Jimmy Sambuo @jsambuo AudioEngine improvements @@ -74,25 +74,25 @@ Szymon Piłkowski @ardcore CCTexture Bug fix Tomasz Tunik @tomasztunik CCNode Memory leak fix -Lin Xuankang(Intel) @AndriyLin cc.WebAudioEngine implements +Xuankang Lin(Intel) @AndriyLin cc.WebAudioEngine implements Kang-Hao Lu(Opera/Oupeng) @kennyluck Optimize John Resig's inheritance pattern cc.clone improvements Mark Henderson @MarkEHenderson Code review, LabelTTF and Scale9Sprite bug fix -Wang Jing @06wj CCScheduler improvements +Jing Wang @06wj CCScheduler improvements Js file loading image add cc.RectApplyAffineTransform improvements -Wang Ze @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent +Ze Wang @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent Christian Schwartz @cschwartz SpriteFrame.initWithTextureFilename converted fix -Zhen XiaoJun @SmallAiTT _getResType error fix +XiaoJun Zheng @SmallAiTT _getResType error fix cc.ScrollView bug fix -Cheng Guozhu @bengol cc.SimpleAudioEngine bug fix +Guozhu Cheng @bengol cc.SimpleAudioEngine bug fix Cocos2d-x and cocos2d-html5 can not grow so fast without the active community. diff --git a/tools/jsdoc_toolkit/build.xml b/tools/jsdoc_toolkit/build.xml index f21d456110..de57ef9147 100644 --- a/tools/jsdoc_toolkit/build.xml +++ b/tools/jsdoc_toolkit/build.xml @@ -38,6 +38,8 @@ + + From 3f1a1e19f17ee4dcd3a447b39f1bfa4e91abeb99 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 16:34:31 +0800 Subject: [PATCH 129/141] Issue #2803: Update authors of Cocos2d-html5 --- AUTHORS.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index 1f79aa5177..4ca81f88af 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -50,7 +50,6 @@ Ivo Wetzel(Zynga Germany) @BonsaiDen Fixes for Audio Support Detection, Texture Support in Particle System, and Performance improvements - Mario Adrian @many20 Code review, multi touch improvements, ccbi bugs fixed @@ -86,6 +85,7 @@ Jing Wang @06wj CCScheduler improvements cc.RectApplyAffineTransform improvements Ze Wang @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent + LabelTTF improvements Christian Schwartz @cschwartz SpriteFrame.initWithTextureFilename converted fix @@ -94,6 +94,8 @@ XiaoJun Zheng @SmallAiTT _getResType error fix Guozhu Cheng @bengol cc.SimpleAudioEngine bug fix +Jing Xiao @xbruce cc.SAXParser bug fix + Cocos2d-x and cocos2d-html5 can not grow so fast without the active community. Thanks to all developers who report & trace bugs, dicuss the engine usage in forum & QQ groups! From 9b34fe47e893e0779a7a98b57bd9079e1b490386 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Mon, 16 Sep 2013 18:19:20 +0800 Subject: [PATCH 130/141] Issue #2803: update submodule reference --- samples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples b/samples index d97d49bc10..9f73f0db3b 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit d97d49bc1099ad75bd2ec1b7e787faf04ac3fa56 +Subproject commit 9f73f0db3b2a95a8c9fe087e7770dc469c27c94a From 243666f202bf382d49e87cc81606283b066cbeeb Mon Sep 17 00:00:00 2001 From: WanderWang Date: Mon, 16 Sep 2013 22:04:57 +0800 Subject: [PATCH 131/141] Update CCTextureCache.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1、Fix error that cc.TextureCache.dumpCachedTextureInfo() will crash when there are cc.LabelBMFont has been created 2、Fix bug when calculate HTMLCanvasElement 's memory --- cocos2d/textures/CCTextureCache.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index 583a7f10a7..c6058f917d 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -484,7 +484,7 @@ cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{ * This will attempt to calculate the size of each texture, and the total texture memory in use.

*/ dumpCachedTextureInfo:function () { - var count = 0; + var count = 0; var totalBytes = 0, locTextures = this._textures; for (var key in locTextures) { @@ -494,18 +494,22 @@ cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{ cc.log("cocos2d: '" + key + "' id=" + selTexture.getHtmlElementObj().src + " " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); else { cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selTexture.getPixelsWide() + " x " + selTexture.getPixelsHigh()); - totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; } + totalBytes += selTexture.getPixelsWide() * selTexture.getPixelsHigh() * 4; } var locTextureColorsCache = this._textureColorsCache; for (key in locTextureColorsCache) { - var selCanvas = locTextureColorsCache[key]; - count++; - cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.getPixelsWide() + " x " + selCanvas.getPixelsHigh()); - totalBytes += selCanvas.getPixelsWide() * selCanvas.getPixelsHigh() * 4; - } + var selCanvasColorsArr = locTextureColorsCache[key]; + for (var selCanvasKey in selCanvasColorsArr){ + var selCanvas = selCanvasColorsArr[selCanvasKey]; + count++; + cc.log("cocos2d: '" + key + "' id= HTMLCanvasElement " + selCanvas.width + " x " + selCanvas.height); + totalBytes += selCanvas.width * selCanvas.height * 4; + } + } +// cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for " + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)"); } From 6f2b4e73b1f25ab5e8176b1547fe121334d939a0 Mon Sep 17 00:00:00 2001 From: WanderWang Date: Tue, 17 Sep 2013 10:18:37 +0800 Subject: [PATCH 132/141] Update CCTextureCache.js fix code format --- cocos2d/textures/CCTextureCache.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cocos2d/textures/CCTextureCache.js b/cocos2d/textures/CCTextureCache.js index c6058f917d..9bd22e8d34 100644 --- a/cocos2d/textures/CCTextureCache.js +++ b/cocos2d/textures/CCTextureCache.js @@ -484,7 +484,7 @@ cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{ * This will attempt to calculate the size of each texture, and the total texture memory in use.

*/ dumpCachedTextureInfo:function () { - var count = 0; + var count = 0; var totalBytes = 0, locTextures = this._textures; for (var key in locTextures) { @@ -509,7 +509,6 @@ cc.TextureCache = cc.Class.extend(/** @lends cc.TextureCache# */{ } } -// cc.log("cocos2d: TextureCache dumpDebugInfo: " + count + " textures, HTMLCanvasElement for " + (totalBytes / 1024) + " KB (" + (totalBytes / (1024.0 * 1024.0)).toFixed(2) + " MB)"); } From 81a0819ba29862ac735cc125be6f2ffd6ff929ff Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 11:15:38 +0800 Subject: [PATCH 133/141] Issue #2803: fixed some bugs for actions that set their object property through reference when initiating actions. --- cocos2d/actions/CCActionGrid.js | 3 ++- cocos2d/actions/CCActionGrid3D.js | 15 +++++++++------ cocos2d/actions/CCActionInterval.js | 9 ++++++--- .../CCTransition.js | 2 +- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cocos2d/actions/CCActionGrid.js b/cocos2d/actions/CCActionGrid.js index b00edbd113..1db91db1e3 100644 --- a/cocos2d/actions/CCActionGrid.js +++ b/cocos2d/actions/CCActionGrid.js @@ -75,7 +75,8 @@ cc.GridAction = cc.ActionInterval.extend(/** @lends cc.GridAction# */{ */ initWithDuration:function (duration, gridSize) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - this._gridSize = gridSize; + this._gridSize.width = gridSize.width; + this._gridSize.height = gridSize.height; return true; } return false; diff --git a/cocos2d/actions/CCActionGrid3D.js b/cocos2d/actions/CCActionGrid3D.js index 3a7c812544..da4fe9d03a 100644 --- a/cocos2d/actions/CCActionGrid3D.js +++ b/cocos2d/actions/CCActionGrid3D.js @@ -375,7 +375,8 @@ cc.Lens3D = cc.Grid3DAction.extend(/** @lends cc.Lens3D# */{ */ setPosition:function (position) { if (!cc.pointEqualToPoint(position, this._position)) { - this._position = position; + this._position.x = position.x; + this._position.y = position.y; this._dirty = true; } }, @@ -474,7 +475,7 @@ cc.Ripple3D = cc.Grid3DAction.extend(/** @lends cc.Ripple3D# */{ ctor:function () { cc.GridAction.prototype.ctor.call(this); - this._position = null; + this._position = cc.p(0,0); this._radius = 0; this._waves = 0; this._amplitude = 0; @@ -494,7 +495,8 @@ cc.Ripple3D = cc.Grid3DAction.extend(/** @lends cc.Ripple3D# */{ * @param {cc.Point} position */ setPosition:function (position) { - this._position = position; + this._position.x = position.x; + this._position.y = position.y; }, /** @@ -886,7 +888,7 @@ cc.Twirl = cc.Grid3DAction.extend({ ctor:function () { cc.GridAction.prototype.ctor.call(this); - this._position = null; + this._position = cc.p(0,0); this._twirls = 0; this._amplitude = 0; this._amplitudeRate = 0; @@ -902,10 +904,11 @@ cc.Twirl = cc.Grid3DAction.extend({ /** * set twirl center - * @param {Number} position + * @param {cc.Point} position */ setPosition:function (position) { - this._position = position; + this._position.x = position.x; + this._position.y = position.y; }, /** diff --git a/cocos2d/actions/CCActionInterval.js b/cocos2d/actions/CCActionInterval.js index b9204e518c..6ee4107efa 100644 --- a/cocos2d/actions/CCActionInterval.js +++ b/cocos2d/actions/CCActionInterval.js @@ -930,7 +930,8 @@ cc.MoveBy = cc.ActionInterval.extend(/** @lends cc.MoveBy# */{ */ initWithDuration:function (duration, position) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - this._positionDelta = position; + this._positionDelta.x = position.x; + this._positionDelta.y = position.y; return true; } return false; @@ -1030,7 +1031,8 @@ cc.MoveTo = cc.MoveBy.extend(/** @lends cc.MoveTo# */{ */ initWithDuration:function (duration, position) { if (cc.MoveBy.prototype.initWithDuration.call(this, duration, position)) { - this._endPosition = position; + this._endPosition.x = position.x; + this._endPosition.y = position.y; return true; } return false; @@ -1261,7 +1263,8 @@ cc.JumpBy = cc.ActionInterval.extend(/** @lends cc.JumpBy# */{ */ initWithDuration:function (duration, position, height, jumps) { if (cc.ActionInterval.prototype.initWithDuration.call(this, duration)) { - this._delta = position; + this._delta.x = position.x; + this._delta.y = position.y; this._height = height; this._jumps = jumps; return true; diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 0d25903e06..6841198c4c 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -1228,7 +1228,7 @@ cc.TransitionFade = cc.TransitionScene.extend(/** @lends cc.TransitionFade# */{ */ ctor:function () { cc.TransitionScene.prototype.ctor.call(this); - this._color = new cc.Color3B() + this._color = new cc.Color4B() }, /** From bfa3ff101b1d283a67164a43168118bcd8216682 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 11:17:12 +0800 Subject: [PATCH 134/141] Issue #2803: updates AUTHORS.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 4ca81f88af..6312a866c4 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -86,6 +86,7 @@ Jing Wang @06wj CCScheduler improvements Ze Wang @WanderWang Fix crash when BrowserTypes match nothing from navigator.userAgent LabelTTF improvements + cc.TextureCache.dumpCachedTextureInfo 's bug fix Christian Schwartz @cschwartz SpriteFrame.initWithTextureFilename converted fix From 5a25eadd8c30d582f6166dc1014dae68d6ad8801 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 11:19:49 +0800 Subject: [PATCH 135/141] Issue #2803: updates build.xml of Jsdoc --- tools/jsdoc_toolkit/build.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/jsdoc_toolkit/build.xml b/tools/jsdoc_toolkit/build.xml index de57ef9147..c2b9c7e119 100644 --- a/tools/jsdoc_toolkit/build.xml +++ b/tools/jsdoc_toolkit/build.xml @@ -33,7 +33,7 @@ - + From ce1195ddecb5024f77b910a1cdd9734a34f3925d Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 12:07:57 +0800 Subject: [PATCH 136/141] Issue #2803: fixed a bug for cc.Sprite that its drawing doesn't work when _rect's width or height greater than 0 and less than 1. --- cocos2d/sprite_nodes/CCSprite.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 4398b12bbe..5a2653c808 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -2003,11 +2003,11 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ if (this._colorized) { context.drawImage(image, 0, 0, 0 | locRect.width, 0 | locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.height); + flipXOffset, flipYOffset, 0 | locRect.width, 0 | locRect.height); } else { context.drawImage(image, 0 | locRect.x, 0 | locRect.y, 0 | locRect.width, 0 | locRect.height, - flipXOffset, flipYOffset, locRect.width, locRect.height); + flipXOffset, flipYOffset, 0 | locRect.width, 0 | locRect.height); } } else if (locContentSize.width !== 0) { var curColor = this.getColor(); From 6c5b88256788f915293ba78f6e60d6d9ea468eb4 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 12:08:54 +0800 Subject: [PATCH 137/141] Issue #2802: update some information in CHANGELOG.txt --- CHANGELOG.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ff7253c96c..189dca5f0b 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -23,6 +23,7 @@ Cocos2d-html5-v2.1.6 @ Sep.19, 2013 9. Fixed a bug of cc.LayerColor that represent incorrect opacity passed into init method 10. Stop listening and remove the event for HtmlImageElement object onload 11. Fixed cc.ProgressTimer display wrong when its sprite was flipped +12. Fixed some bugs for actions that set their object property through reference when initiating actions. * Known Issues: 1. Effect Advanced Lens3D doesn't work From 7a67b884bc742fca3e51fc10862e82748e56f2b6 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 15:02:25 +0800 Subject: [PATCH 138/141] Issue #2803: cc.Sprite's setFlipX, setFlipY have renamed to setFlippedX, setFlippedY --- cocos2d/actions/CCActionInstant.js | 24 ++++---- .../CCTransitionProgress.js | 20 +++---- cocos2d/misc_nodes/CCProgressTimer.js | 12 ++-- cocos2d/sprite_nodes/CCSprite.js | 56 +++++++++---------- cocos2d/tileMap_parallax_nodes/CCTMXLayer.js | 12 ++-- extensions/CCBReader/CCSpriteLoader.js | 4 +- .../GUI/CCControlExtension/CCControlSwitch.js | 2 +- samples | 2 +- 8 files changed, 66 insertions(+), 66 deletions(-) diff --git a/cocos2d/actions/CCActionInstant.js b/cocos2d/actions/CCActionInstant.js index 36197bb80b..30376d6181 100644 --- a/cocos2d/actions/CCActionInstant.js +++ b/cocos2d/actions/CCActionInstant.js @@ -203,17 +203,17 @@ cc.RemoveSelf.create = function(isNeedCleanUp){ * @extends cc.ActionInstant */ cc.FlipX = cc.ActionInstant.extend(/** @lends cc.FlipX# */{ - _flipX:false, + _flippedX:false, ctor:function(){ cc.FiniteTimeAction.prototype.ctor.call(this); - this._flipX = false; + this._flippedX = false; }, /** * @param {Boolean} x * @return {Boolean} */ initWithFlipX:function (x) { - this._flipX = x; + this._flippedX = x; return true; }, @@ -221,19 +221,19 @@ cc.FlipX = cc.ActionInstant.extend(/** @lends cc.FlipX# */{ * @param {Number} time */ update:function (time) { - this._target.setFlipX(this._flipX); + this._target.setFlippedX(this._flippedX); }, /** * @return {cc.FiniteTimeAction} */ reverse:function () { - return cc.FlipX.create(!this._flipX); + return cc.FlipX.create(!this._flippedX); }, clone:function(){ var action = new cc.FlipX(); - action.initWithFlipX(this._flipX); + action.initWithFlipX(this._flippedX); return action; } }); @@ -256,17 +256,17 @@ cc.FlipX.create = function (x) { * @extends cc.ActionInstant */ cc.FlipY = cc.ActionInstant.extend(/** @lends cc.FlipY# */{ - _flipY:false, + _flippedY:false, ctor:function(){ cc.FiniteTimeAction.prototype.ctor.call(this); - this._flipY = false; + this._flippedY = false; }, /** * @param {Boolean} Y * @return {Boolean} */ initWithFlipY:function (Y) { - this._flipY = Y; + this._flippedY = Y; return true; }, @@ -275,19 +275,19 @@ cc.FlipY = cc.ActionInstant.extend(/** @lends cc.FlipY# */{ */ update:function (time) { //this._super(); - this._target.setFlipY(this._flipY); + this._target.setFlippedY(this._flipY); }, /** * @return {cc.FiniteTimeAction} */ reverse:function () { - return cc.FlipY.create(!this._flipY); + return cc.FlipY.create(!this._flippedY); }, clone:function(){ var action = new cc.FlipY(); - action.initWithFlipY(this._flipY); + action.initWithFlipY(this._flippedY); return action; } }); diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js index c75fe1c65e..2b9f6e9032 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionProgress.js @@ -136,7 +136,7 @@ cc.TransitionProgressRadialCCW = cc.TransitionProgress.extend(/** @lends cc.Tran // but it is flipped upside down so we flip the sprite if (cc.renderContextType === cc.WEBGL) - pNode.getSprite().setFlipY(true); + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_RADIAL); // Return the radial type that we want to use @@ -178,7 +178,7 @@ cc.TransitionProgressRadialCW = cc.TransitionProgress.extend(/** @lends cc.Trans // but it is flipped upside down so we flip the sprite if (cc.renderContextType === cc.WEBGL) - pNode.getSprite().setFlipY(true); + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_RADIAL); // Return the radial type that we want to use @@ -219,8 +219,8 @@ cc.TransitionProgressHorizontal = cc.TransitionProgress.extend(/** @lends cc.Tra var pNode = cc.ProgressTimer.create(texture.getSprite()); // but it is flipped upside down so we flip the sprite - if (cc.renderContextType == cc.WEBGL) - pNode.getSprite().setFlipY(true); + if (cc.renderContextType === cc.WEBGL) + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR); pNode.setMidpoint(cc.p(1, 0)); @@ -261,8 +261,8 @@ cc.TransitionProgressVertical = cc.TransitionProgress.extend(/** @lends cc.Trans var pNode = cc.ProgressTimer.create(texture.getSprite()); // but it is flipped upside down so we flip the sprite - if (cc.renderContextType == cc.WEBGL) - pNode.getSprite().setFlipY(true); + if (cc.renderContextType === cc.WEBGL) + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR); pNode.setMidpoint(cc.p(0, 0)); @@ -302,8 +302,8 @@ cc.TransitionProgressInOut = cc.TransitionProgress.extend(/** @lends cc.Transiti var pNode = cc.ProgressTimer.create(texture.getSprite()); // but it is flipped upside down so we flip the sprite - if (cc.renderContextType == cc.WEBGL) - pNode.getSprite().setFlipY(true); + if (cc.renderContextType === cc.WEBGL) + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR); pNode.setMidpoint(cc.p(0.5, 0.5)); @@ -351,8 +351,8 @@ cc.TransitionProgressOutIn = cc.TransitionProgress.extend(/** @lends cc.Transiti var pNode = cc.ProgressTimer.create(texture.getSprite()); // but it is flipped upside down so we flip the sprite - if (cc.renderContextType == cc.WEBGL) - pNode.getSprite().setFlipY(true); + if (cc.renderContextType === cc.WEBGL) + pNode.getSprite().setFlippedY(true); pNode.setType(cc.PROGRESS_TIMER_TYPE_BAR); pNode.setMidpoint(cc.p(0.5, 0.5)); diff --git a/cocos2d/misc_nodes/CCProgressTimer.js b/cocos2d/misc_nodes/CCProgressTimer.js index ee81ea8e7c..3136104a77 100644 --- a/cocos2d/misc_nodes/CCProgressTimer.js +++ b/cocos2d/misc_nodes/CCProgressTimer.js @@ -423,11 +423,11 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; context.save(); - if (locSprite._flipX) { + if (locSprite._flippedX) { flipXOffset = -locOffsetPosition.x - locRect.width; context.scale(-1, 1); } - if (locSprite._flipY) { + if (locSprite._flippedY) { flipYOffset = locOffsetPosition.y; context.scale(1, -1); } @@ -790,7 +790,7 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ locEndAngle = 270 + 3.6 * this._percentage; } - if (locSprite._flipX) { + if (locSprite._flippedX) { locOrigin.x -= spriteSize.width * (this._midPoint.x * 2); locStartAngle= -locStartAngle; locEndAngle= -locEndAngle; @@ -798,7 +798,7 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ locEndAngle -= 180; locCounterClockWise = !locCounterClockWise; } - if (locSprite._flipY) { + if (locSprite._flippedY) { locOrigin.y+=spriteSize.height*(this._midPoint.y*2); locCounterClockWise = !locCounterClockWise; locStartAngle= -locStartAngle; @@ -836,7 +836,7 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ //left pos locBarRect.x = 0; var flipXNeed = 1; - if (locSprite._flipX) { + if (locSprite._flippedX) { locBarRect.x -= currentDrawSize.width; flipXNeed = -1; } @@ -847,7 +847,7 @@ cc.ProgressTimer = cc.NodeRGBA.extend(/** @lends cc.ProgressTimer# */{ //right pos locBarRect.y = 0; var flipYNeed = 1; - if (locSprite._flipY) { + if (locSprite._flippedY) { locBarRect.y += currentDrawSize.height; flipYNeed = -1; } diff --git a/cocos2d/sprite_nodes/CCSprite.js b/cocos2d/sprite_nodes/CCSprite.js index 5a2653c808..2644d0b4d6 100644 --- a/cocos2d/sprite_nodes/CCSprite.js +++ b/cocos2d/sprite_nodes/CCSprite.js @@ -327,8 +327,8 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ _opacityModifyRGB:false, // image is flipped - _flipX:false, //Whether the sprite is flipped horizontally or not. - _flipY:false, //Whether the sprite is flipped vertically or not. + _flippedX:false, //Whether the sprite is flipped horizontally or not. + _flippedY:false, //Whether the sprite is flipped vertically or not. _textureLoaded:false, _loadedEventListeners: null, @@ -761,11 +761,11 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ /** * Sets whether the sprite should be flipped horizontally or not. - * @param {Boolean} flipX true if the sprite should be flipped horizaontally, false otherwise. + * @param {Boolean} flippedX true if the sprite should be flipped horizontally, false otherwise. */ - setFlipX:function (flipX) { - if (this._flipX != flipX) { - this._flipX = flipX; + setFlippedX:function (flippedX) { + if (this._flippedX != flippedX) { + this._flippedX = flippedX; this.setTextureRect(this._rect, this._rectRotated, this._contentSize); this.setNodeDirty(); } @@ -773,11 +773,11 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ /** * Sets whether the sprite should be flipped vertically or not. - * @param {Boolean} flipY true if the sprite should be flipped vertically, flase otherwise. + * @param {Boolean} flippedY true if the sprite should be flipped vertically, false otherwise. */ - setFlipY:function (flipY) { - if (this._flipY != flipY) { - this._flipY = flipY; + setFlippedY:function (flippedY) { + if (this._flippedY != flippedY) { + this._flippedY = flippedY; this.setTextureRect(this._rect, this._rectRotated, this._contentSize); this.setNodeDirty(); } @@ -794,7 +794,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ * @return {Boolean} true if the sprite is flipped horizaontally, false otherwise. */ isFlippedX:function () { - return this._flipX; + return this._flippedX; }, /** @@ -808,7 +808,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ * @return {Boolean} true if the sprite is flipped vertically, flase otherwise. */ isFlippedY:function () { - return this._flipY; + return this._flippedY; }, // @@ -1023,7 +1023,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ // update texture (calls _updateBlendFunc) this.setTexture(null); this._textureLoaded = true; - this._flipX = this._flipY = false; + this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(cc.p(0.5, 0.5)); @@ -1060,7 +1060,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ // update texture (calls _updateBlendFunc) this.setTexture(null); this._textureLoaded = true; - this._flipX = this._flipY = false; + this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(cc.p(0.5, 0.5)); @@ -1137,7 +1137,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; - this._flipX = this._flipY = false; + this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(cc.p(0.5, 0.5)); @@ -1197,7 +1197,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ this._blendFunc.src = cc.BLEND_SRC; this._blendFunc.dst = cc.BLEND_DST; - this._flipX = this._flipY = false; + this._flippedX = this._flippedY = false; // default transform anchor: center this.setAnchorPoint(cc.p(0.5, 0.5)); @@ -1290,9 +1290,9 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ this._setTextureCoords(rect); var relativeOffset = this._unflippedOffsetPositionFromCenter; - if (this._flipX) + if (this._flippedX) relativeOffset.x = -relativeOffset.x; - if (this._flipY) + if (this._flippedY) relativeOffset.y = -relativeOffset.y; var locRect = this._rect; @@ -1331,9 +1331,9 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ this.setVertexRect(rect); var relativeOffset = this._unflippedOffsetPositionFromCenter; - if (this._flipX) + if (this._flippedX) relativeOffset.x = -relativeOffset.x; - if (this._flipY) + 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; @@ -1844,13 +1844,13 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ bottom = (rect.y + rect.width) / atlasHeight; }// CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL - if (this._flipX) { + if (this._flippedX) { tempSwap = top; top = bottom; bottom = tempSwap; } - if (this._flipY) { + if (this._flippedY) { tempSwap = left; left = right; right = tempSwap; @@ -1877,13 +1877,13 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ bottom = (rect.y + rect.height) / atlasHeight; } // ! CC_FIX_ARTIFACTS_BY_STRECHING_TEXEL - if (this._flipX) { + if (this._flippedX) { tempSwap = left; left = right; right = tempSwap; } - if (this._flipY) { + if (this._flippedY) { tempSwap = top; top = bottom; bottom = tempSwap; @@ -1986,13 +1986,13 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ context.globalAlpha = this._displayedOpacity / 255; var locRect = this._rect, locContentSize = this._contentSize, locOffsetPosition = this._offsetPosition; var flipXOffset = 0 | (locOffsetPosition.x), flipYOffset = -locOffsetPosition.y - locRect.height; - if (this._flipX || this._flipY) { + if (this._flippedX || this._flippedY) { context.save(); - if (this._flipX) { + if (this._flippedX) { flipXOffset = -locOffsetPosition.x - locRect.width; context.scale(-1, 1); } - if (this._flipY) { + if (this._flippedY) { flipYOffset = locOffsetPosition.y; context.scale(1, -1); } @@ -2031,7 +2031,7 @@ cc.Sprite = cc.NodeRGBA.extend(/** @lends cc.Sprite# */{ cc.p(flipXOffset + drawSize.width, flipYOffset - drawSize.height), cc.p(flipXOffset, flipYOffset - drawSize.height)]; cc.drawingUtil.drawPoly(vertices2, 4, true); } - if (this._flipX || this._flipY) + if (this._flippedX || this._flippedY) context.restore(); cc.g_NumberOfDraws++; } diff --git a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js index ce9d429f57..139ca28a62 100644 --- a/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js +++ b/cocos2d/tileMap_parallax_nodes/CCTMXLayer.js @@ -767,8 +767,8 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ sprite.setRotation(0.0); } - sprite.setFlipX(false); - sprite.setFlipY(false); + sprite.setFlippedX(false); + sprite.setFlippedY(false); // Rotation in tiled is achieved using 3 flipped states, flipping across the horizontal, vertical, and diagonal axes of the tiles. if ((gid & cc.TMX_TILE_DIAGONAL_FLAG) >>> 0) { @@ -785,17 +785,17 @@ cc.TMXLayer = cc.SpriteBatchNode.extend(/** @lends cc.TMXLayer# */{ sprite.setRotation(270); else if (flag == (cc.TMX_TILE_VERTICAL_FLAG | cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) { sprite.setRotation(90); - sprite.setFlipX(true); + sprite.setFlippedX(true); } else { sprite.setRotation(270); - sprite.setFlipX(true); + sprite.setFlippedX(true); } } else { if ((gid & cc.TMX_TILE_HORIZONTAL_FLAG) >>> 0) - sprite.setFlipX(true); + sprite.setFlippedX(true); if ((gid & cc.TMX_TILE_VERTICAL_FLAG) >>> 0) - sprite.setFlipY(true); + sprite.setFlippedY(true); } }, diff --git a/extensions/CCBReader/CCSpriteLoader.js b/extensions/CCBReader/CCSpriteLoader.js index 68644dea69..cdf95d96c0 100644 --- a/extensions/CCBReader/CCSpriteLoader.js +++ b/extensions/CCBReader/CCSpriteLoader.js @@ -70,8 +70,8 @@ cc.SpriteLoader = cc.NodeLoader.extend({ }, onHandlePropTypeFlip:function (node, parent, propertyName, flip, ccbReader) { if (propertyName === PROPERTY_FLIP) { - node.setFlipX(flip[0]); - node.setFlipY(flip[1]); + node.setFlippedX(flip[0]); + node.setFlippedY(flip[1]); } else { cc.NodeLoader.prototype.onHandlePropTypeFlip.call(this, node, parent, propertyName, flip, ccbReader); } diff --git a/extensions/GUI/CCControlExtension/CCControlSwitch.js b/extensions/GUI/CCControlExtension/CCControlSwitch.js index 292a4a93c2..5b52a2ba48 100644 --- a/extensions/GUI/CCControlExtension/CCControlSwitch.js +++ b/extensions/GUI/CCControlExtension/CCControlSwitch.js @@ -296,7 +296,7 @@ cc.ControlSwitchSprite = cc.Sprite.extend({ rt.end(); this.setTexture(rt.getSprite().getTexture()); - this.setFlipY(true); + this.setFlippedY(true); }, setSliderXPosition:function (sliderXPosition) { diff --git a/samples b/samples index 9f73f0db3b..2e476980f1 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit 9f73f0db3b2a95a8c9fe087e7770dc469c27c94a +Subproject commit 2e476980f18d717912bb669e031a1cdf406cdcc2 From e5114d9560678e3b544e4bd76ea789354f3abc82 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 15:57:09 +0800 Subject: [PATCH 139/141] Issue #2803: fixed a bug for cc.FlipY and fixed a bug for Transition --- cocos2d/actions/CCActionInstant.js | 2 +- cocos2d/layers_scenes_transitions_nodes/CCTransition.js | 6 ------ .../layers_scenes_transitions_nodes/CCTransitionPageTurn.js | 2 +- samples | 2 +- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cocos2d/actions/CCActionInstant.js b/cocos2d/actions/CCActionInstant.js index 30376d6181..3ee2c9e312 100644 --- a/cocos2d/actions/CCActionInstant.js +++ b/cocos2d/actions/CCActionInstant.js @@ -275,7 +275,7 @@ cc.FlipY = cc.ActionInstant.extend(/** @lends cc.FlipY# */{ */ update:function (time) { //this._super(); - this._target.setFlippedY(this._flipY); + this._target.setFlippedY(this._flippedY); }, /** diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js index 6841198c4c..dec51e86ce 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransition.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransition.js @@ -277,12 +277,6 @@ cc.TransitionSceneOriented.create = function (t, scene, orientation) { * @extends cc.TransitionScene */ cc.TransitionRotoZoom = cc.TransitionScene.extend(/** @lends cc.TransitionRotoZoom# */{ - /** - * Constructor - */ - ctor:function () { - }, - /** * Custom On Enter callback * @override diff --git a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js index 896e444fcd..168b7e93e0 100644 --- a/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js +++ b/cocos2d/layers_scenes_transitions_nodes/CCTransitionPageTurn.js @@ -54,7 +54,7 @@ cc.TransitionPageTurn = cc.TransitionScene.extend(/** @lends cc.TransitionPageTu // XXX: needed before [super init] this._back = backwards; - if (cc.TransitionScene.prototype.initWithDuration(this, t, scene)) { + if (cc.TransitionScene.prototype.initWithDuration.call(this, t, scene)) { // do something } return true; diff --git a/samples b/samples index 2e476980f1..db1ed102b8 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit 2e476980f18d717912bb669e031a1cdf406cdcc2 +Subproject commit db1ed102b809ee4c16b7898312bd5e97da071a94 From e459396c301338b5a1062788bcf12a7353bec791 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 17:22:22 +0800 Subject: [PATCH 140/141] Issue #2803: add a sample game link to index.html --- CHANGELOG.txt | 1 + index.html | 1 + samples | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 189dca5f0b..ba22fba641 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,5 +1,6 @@ Cocos2d-html5-v2.1.6 @ Sep.19, 2013 * Improved Sprite, Node, LabelTTF class define from separated code to combined code for maintainability, now it is clean and clear +* added a new sample game "Fruit attack" which works great on PC browsers, mobile browsers, and can even be run natively as an android and iOS app with JSB * cc.Sprite and its subClasses's texture has been replaced from DOM element to cc.Texture2D on Canvas mode * Improved cc.Texture2d for direct using without pre-loading image resources, you don't need to wait resources loading when create a new scene or layers * Migrated CCBReader and GUI to Cocos2d-x 2.1.4 diff --git a/index.html b/index.html index 31f2391edc..80b0b618c2 100644 --- a/index.html +++ b/index.html @@ -55,6 +55,7 @@

  • Test cases - Engine Testcases
  • Template - Cocos2d-html5 Template
  • MoonWarriors - Game
  • +
  • Fruit Attack - Game
  • Watermelon with Me - Game
  • CocosDragon - Game
  • Crystal Craze - Game
  • diff --git a/samples b/samples index db1ed102b8..022292761c 160000 --- a/samples +++ b/samples @@ -1 +1 @@ -Subproject commit db1ed102b809ee4c16b7898312bd5e97da071a94 +Subproject commit 022292761c6a9d056e25cc6e844430650208513f From 140df57b2116fda6de328c6b4714b4cfa22ebb37 Mon Sep 17 00:00:00 2001 From: dingpinglv Date: Tue, 17 Sep 2013 17:59:41 +0800 Subject: [PATCH 141/141] Closed #2803: update DragonBones' link in CHANGELOG.txt --- CHANGELOG.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ba22fba641..ebc12bd87c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -9,7 +9,7 @@ Cocos2d-html5-v2.1.6 @ Sep.19, 2013 * Fixed APIs of HTML5 according to JSB for compatibility, e.g. cc.ParticleSystemQuad has merged into cc.ParticleSystem, please check it on upgrade guide v2.1.5 to v2.1.6(http://www.cocos2d-x.org/wiki/Upgrade_Guide_from_Cocos2d-html5_v215_to_v216) * Added Hiding url address bar for mobile browser, please check the template and hello world * Re-writed Canvas Mode of RenderTexture to adapt WebGL interface -* Added frame event, collider and blend type supporting for Armature. Now Armature supports two tools:1.CocoStudio(windows,http://www.cocostudio.org),2.DragonBones v2.3(flash,http://dragonbones.github.io) +* Added frame event, collider and blend type supporting for Armature. Now Armature supports two tools:1.CocoStudio(windows,http://www.cocostudio.org),2.DragonBones(flash, https://github.com/2youyouo2/SkeletonAnimationDesignPanel) * Set auto render mode default value to canvas in mobile browsers and WebGL in desktop browsers * Bug fix: