Skip to content

Commit 6325b10

Browse files
author
pandamicro
committed
Improve visit logic, reduce call stack depth
1 parent 4d71e89 commit 6325b10

35 files changed

+531
-624
lines changed

cocos2d/actions/CCAction.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ cc.Action.create = cc.action;
239239
*/
240240
cc.FiniteTimeAction = cc.Action.extend(/** @lends cc.FiniteTimeAction# */{
241241
// duration in seconds
242-
_duration:0,
242+
_duration: 0,
243243

244244
/**
245245
* Constructor function, override it to extend the construction behavior, remember to call "this._super()" in the extended "ctor" function.

cocos2d/clipping-nodes/CCClippingNode.js

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,6 @@ cc.ClippingNode = cc.Node.extend(/** @lends cc.ClippingNode# */{
6666
this._renderCmd.initStencilBits();
6767
},
6868

69-
/**
70-
* Initialization of the node, please do not call this function by yourself, you should pass the parameters to constructor to initialize it
.
71-
* @function
72-
* @param {cc.Node} [stencil=null]
73-
*/
74-
init: function (stencil) {
75-
this._stencil = stencil;
76-
this.alphaThreshold = 1;
77-
this.inverted = false;
78-
this._renderCmd.initStencilBits();
79-
return true;
80-
},
81-
8269
/**
8370
* <p>
8471
* Event callback that is invoked every time when node enters the 'stage'. <br/>
@@ -135,6 +122,28 @@ cc.ClippingNode = cc.Node.extend(/** @lends cc.ClippingNode# */{
135122
cc.Node.prototype.onExit.call(this);
136123
},
137124

125+
visit: function (parent) {
126+
if (!this._visible)
127+
return;
128+
129+
this._renderCmd.clippingVisit(parent && parent._renderCmd);
130+
},
131+
132+
_visitChildren: function () {
133+
var renderer = cc.renderer;
134+
if (this._reorderChildDirty) {
135+
this.sortAllChildren();
136+
}
137+
var children = this._children, child;
138+
for (var i = 0, len = children.length; i < len; i++) {
139+
child = children[i];
140+
if (child && child._visible) {
141+
child.visit(this);
142+
}
143+
}
144+
this._renderCmd._dirtyFlag = 0;
145+
},
146+
138147
/**
139148
* <p>
140149
* The alpha threshold. <br/>

cocos2d/clipping-nodes/CCClippingNodeCanvasRenderCmd.js

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -168,47 +168,40 @@
168168
return cc.ClippingNode.CanvasRenderCmd.prototype._godhelpme;
169169
};
170170

171-
proto.visit = function(parentCmd){
171+
proto.clippingVisit = function (parentCmd) {
172172
var node = this._node;
173-
// quick return if not visible
174-
if (!node._visible)
175-
return;
176-
177173
parentCmd = parentCmd || this.getParentRenderCmd();
178-
if( parentCmd)
179-
this._curLevel = parentCmd._curLevel + 1;
180-
var transformRenderCmd = this;
174+
this.visit(parentCmd);
181175

182-
this._syncStatus(parentCmd);
183176
// Composition mode, costy but support texture stencil
184177
this._clipElemType = !(!this._cangodhelpme() && node._stencil instanceof cc.DrawNode);
185178
if (!node._stencil || !node._stencil.visible) {
186179
if (this.inverted)
187-
this.originVisit(parentCmd); // draw everything
180+
node._visitChildren(); // draw everything
188181
return;
189182
}
190183

191184
cc.renderer.pushRenderCommand(this._rendererSaveCmd);
192-
if(this._clipElemType){
185+
if (this._clipElemType) {
193186
// Draw everything first using node visit function
194-
this.originVisit(parentCmd);
195-
}else{
196-
node._stencil.visit(this);
187+
node._visitChildren();
188+
} else {
189+
node._stencil.visit(node);
197190
}
198191
cc.renderer.pushRenderCommand(this._rendererClipCmd);
199192

200-
if(this._clipElemType){
201-
node._stencil.visit(transformRenderCmd);
202-
}else{
203-
var i, children = node._children;
193+
if (this._clipElemType) {
194+
node._stencil.visit(node);
195+
} else {
204196
// Clip mode doesn't support recursive stencil, so once we used a clip stencil,
205197
// so if it has ClippingNode as a child, the child must uses composition stencil.
206198
this._cangodhelpme(true);
207-
var len = children.length;
199+
var children = node._children;
200+
var i, len = children.length;
208201
if (len > 0) {
209202
node.sortAllChildren();
210203
for (i = 0; i < len; i++)
211-
children[i]._renderCmd.visit(this);
204+
children[i].visit(node);
212205
}
213206
this._cangodhelpme(false);
214207
}

cocos2d/clipping-nodes/CCClippingNodeWebGLRenderCmd.js

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -58,29 +58,26 @@
5858
var node = this._node;
5959
this.originTransform(parentCmd, recursive);
6060
if (node._stencil) {
61-
node._stencil._renderCmd.transform(this, recursive);
61+
node._stencil._renderCmd.transform(this, true);
62+
node._stencil._dirtyFlag &= ~cc.Node._dirtyFlags.transformDirty;
6263
}
6364
};
6465

65-
proto.visit = function(parentCmd){
66+
proto.clippingVisit = function (parentCmd) {
6667
var node = this._node;
67-
// quick return if not visible
68-
if (!node._visible)
69-
return;
70-
71-
if( node._parent && node._parent._renderCmd)
72-
this._curLevel = node._parent._renderCmd._curLevel + 1;
68+
parentCmd = parentCmd || this.getParentRenderCmd();
69+
this.visit(parentCmd);
7370

7471
// if stencil buffer disabled
7572
if (cc.stencilBits < 1) {
7673
// draw everything, as if there were no stencil
77-
this.originVisit(parentCmd);
74+
node._visitChildren();
7875
return;
7976
}
8077

8178
if (!node._stencil || !node._stencil.visible) {
8279
if (node.inverted)
83-
this.originVisit(parentCmd); // draw everything
80+
node._visitChildren(); // draw everything
8481
return;
8582
}
8683

@@ -91,20 +88,14 @@
9188
cc.ClippingNode.WebGLRenderCmd._visit_once = false;
9289
}
9390
// draw everything, as if there were no stencil
94-
this.originVisit(parentCmd);
91+
node._visitChildren();
9592
return;
9693
}
9794

9895
cc.renderer.pushRenderCommand(this._beforeVisitCmd);
9996

100-
//optimize performance for javascript
101-
var currentStack = cc.current_stack;
102-
currentStack.stack.push(currentStack.top);
103-
this._syncStatus(parentCmd);
104-
currentStack.top = this._stackMatrix;
105-
10697
// node._stencil._stackMatrix = node._stackMatrix;
107-
node._stencil._renderCmd.visit(this);
98+
node._stencil.visit(node);
10899

109100
cc.renderer.pushRenderCommand(this._afterDrawStencilCmd);
110101

@@ -115,15 +106,13 @@
115106
node.sortAllChildren();
116107
// draw children zOrder < 0
117108
for (var i = 0; i < childLen; i++) {
118-
locChildren[i]._renderCmd.visit(this);
109+
locChildren[i].visit(node);
119110
}
120111
}
121112

122113
cc.renderer.pushRenderCommand(this._afterVisitCmd);
123114

124115
this._dirtyFlag = 0;
125-
//optimize performance for javascript
126-
currentStack.top = currentStack.stack.pop();
127116
};
128117

129118
proto.setStencil = function (stencil) {

cocos2d/core/base-nodes/CCNode.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,10 +2091,40 @@ cc.Node = cc.Class.extend(/** @lends cc.Node# */{
20912091
/**
20922092
* Recursive method that visit its children and draw them
20932093
* @function
2094-
* @param {cc.Node.RenderCmd} parentCmd
2094+
* @param {cc.Node} parent
20952095
*/
2096-
visit: function(parentCmd){
2097-
this._renderCmd.visit(parentCmd);
2096+
visit: function (parent) {
2097+
// quick return if not visible
2098+
if (!this._visible)
2099+
return;
2100+
2101+
var renderer = cc.renderer, cmd = this._renderCmd;
2102+
cmd.visit(parent && parent._renderCmd);
2103+
2104+
var i, children = this._children, len = children.length, child;
2105+
if (len > 0) {
2106+
if (this._reorderChildDirty) {
2107+
this.sortAllChildren();
2108+
}
2109+
// draw children zOrder < 0
2110+
for (i = 0; i < len; i++) {
2111+
child = children[i];
2112+
if (child._localZOrder < 0) {
2113+
child.visit(this);
2114+
}
2115+
else {
2116+
break;
2117+
}
2118+
}
2119+
2120+
renderer.pushRenderCommand(cmd);
2121+
for (; i < len; i++) {
2122+
children[i].visit(this);
2123+
}
2124+
} else {
2125+
renderer.pushRenderCommand(cmd);
2126+
}
2127+
cmd._dirtyFlag = 0;
20982128
},
20992129

21002130
/**

cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,17 @@ var dirtyFlags = cc.Node._dirtyFlags = {
4646
};
4747

4848
var ONE_DEGREE = Math.PI / 180;
49-
var stack = new Array(50);
5049

5150
function transformChildTree(root) {
5251
var index = 1;
5352
var children, child, curr, parentCmd, i, len;
53+
var stack = cc.Node._performStacks[cc.Node._performing];
54+
if (!stack) {
55+
stack = [];
56+
cc.Node._performStacks.push(stack);
57+
}
58+
stack.length = 0;
59+
cc.Node._performing++;
5460
stack[0] = root;
5561
while (index) {
5662
index--;
@@ -79,6 +85,7 @@ function transformChildTree(root) {
7985
}
8086
}
8187
}
88+
cc.Node._performing--;
8289
}
8390

8491
//-------------------------Base -------------------------
@@ -317,9 +324,6 @@ cc.Node.RenderCmd.prototype = {
317324

318325
visit: function (parentCmd) {
319326
var node = this._node, renderer = cc.renderer;
320-
// quick return if not visible
321-
if (!node._visible)
322-
return;
323327

324328
parentCmd = parentCmd || this.getParentRenderCmd();
325329
if (parentCmd)
@@ -331,7 +335,6 @@ cc.Node.RenderCmd.prototype = {
331335
}
332336

333337
this._syncStatus(parentCmd);
334-
this.visitChildren();
335338
},
336339

337340
_updateDisplayColor: function (parentColor) {
@@ -436,7 +439,8 @@ cc.Node.RenderCmd.prototype = {
436439
this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
437440
},
438441

439-
_updateColor: function(){},
442+
_updateColor: function () {
443+
},
440444

441445
updateStatus: function () {
442446
var locFlag = this._dirtyFlag;
@@ -470,7 +474,7 @@ cc.Node.RenderCmd.prototype = {
470474
_syncStatus: function (parentCmd) {
471475
// In the visit logic does not restore the _dirtyFlag
472476
// Because child elements need parent's _dirtyFlag to change himself
473-
var locFlag = this._dirtyFlag, parentNode = null;
477+
var locFlag = this._dirtyFlag, parentNode = parentCmd ? parentCmd._node : null;
474478

475479
// There is a possibility:
476480
// The parent element changed color, child element not change
@@ -509,39 +513,11 @@ cc.Node.RenderCmd.prototype = {
509513

510514
if (locFlag & dirtyFlags.orderDirty)
511515
this._dirtyFlag &= ~dirtyFlags.orderDirty;
512-
},
513-
514-
visitChildren: function () {
515-
var renderer = cc.renderer;
516-
var node = this._node;
517-
var i, children = node._children, child;
518-
var len = children.length;
519-
if (len > 0) {
520-
node.sortAllChildren();
521-
// draw children zOrder < 0
522-
for (i = 0; i < len; i++) {
523-
child = children[i];
524-
if (child._localZOrder < 0) {
525-
child._renderCmd.visit(this);
526-
}
527-
else {
528-
break;
529-
}
530-
}
531-
532-
renderer.pushRenderCommand(this);
533-
for (; i < len; i++) {
534-
children[i]._renderCmd.visit(this);
535-
}
536-
} else {
537-
renderer.pushRenderCommand(this);
538-
}
539-
this._dirtyFlag = 0;
540516
}
541517
};
542518

543-
cc.Node.RenderCmd.prototype.originVisit = cc.Node.RenderCmd.prototype.visit;
544519
cc.Node.RenderCmd.prototype.originTransform = cc.Node.RenderCmd.prototype.transform;
520+
cc.Node.RenderCmd.prototype.originUpdateStatus = cc.Node.RenderCmd.prototype.updateStatus;
545521
cc.Node.RenderCmd.prototype._originSyncStatus = cc.Node.RenderCmd.prototype._syncStatus;
546522

547523
//-----------------------Canvas ---------------------------

cocos2d/core/base-nodes/CCNodeWebGLRenderCmd.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
THE SOFTWARE.
2323
****************************************************************************/
2424
// ------------------------------ The cc.Node's render command for WebGL ----------------------------------
25-
(function() {
25+
(function () {
2626
cc.Node.WebGLRenderCmd = function (renderable) {
2727
this._node = renderable;
2828
this._anchorPointInPoints = {x: 0, y: 0};

cocos2d/core/labelttf/CCLabelTTFCanvasRenderCmd.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ cc.LabelTTF._firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/;
327327
if (locFlag & flags.textDirty)
328328
this._updateTexture();
329329

330-
cc.Node.RenderCmd.prototype.updateStatus.call(this);
330+
this.originUpdateStatus();
331331
};
332332

333333
proto._syncStatus = function (parentCmd) {

0 commit comments

Comments
 (0)