Skip to content

Commit 2032c3a

Browse files
author
pandamicro
committed
Improve performance for transform by removing recursive logic
1 parent f60dde1 commit 2032c3a

File tree

1 file changed

+66
-41
lines changed

1 file changed

+66
-41
lines changed

Diff for: cocos2d/core/base-nodes/CCNodeCanvasRenderCmd.js

+66-41
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,40 @@ cc.CustomRenderCmd = function (target, func) {
3838
};
3939
};
4040

41-
cc.Node._dirtyFlags = {
41+
var dirtyFlags = cc.Node._dirtyFlags = {
4242
transformDirty: 1 << 0, visibleDirty: 1 << 1, colorDirty: 1 << 2, opacityDirty: 1 << 3, cacheDirty: 1 << 4,
4343
orderDirty: 1 << 5, textDirty: 1 << 6, gradientDirty: 1 << 7, textureDirty: 1 << 8,
4444
contentDirty: 1 << 9,
4545
COUNT: 10,
4646
all: (1 << 10) - 1
4747
};
4848

49+
var ONE_DEGREE = Math.PI / 180;
50+
var stack = new Array(50);
51+
52+
function transformChildTree (root) {
53+
var index = 1;
54+
var children, child, curr, parentCmd, i, len;
55+
stack[0] = root;
56+
while (index) {
57+
index--;
58+
curr = stack[index];
59+
// Avoid memory leak
60+
stack[index] = null;
61+
if (!curr) continue;
62+
children = curr._children;
63+
if (children && children.length > 0) {
64+
parentCmd = curr._renderCmd;
65+
for (i = 0, len = children.length; i < len; ++i) {
66+
child = children[i];
67+
stack[index] = child;
68+
index++;
69+
child._renderCmd.transform(parentCmd);
70+
}
71+
}
72+
}
73+
}
74+
4975
//-------------------------Base -------------------------
5076
cc.Node.RenderCmd = function (renderable) {
5177
this._dirtyFlag = 1; //need update the transform at first.
@@ -150,15 +176,15 @@ cc.Node.RenderCmd.prototype = {
150176

151177
// rotation
152178
if (hasRotation) {
153-
var rotationRadiansX = node._rotationX * 0.017453292519943295; //0.017453292519943295 = (Math.PI / 180); for performance
179+
var rotationRadiansX = node._rotationX * ONE_DEGREE;
154180
c = Math.sin(rotationRadiansX);
155181
d = Math.cos(rotationRadiansX);
156182
if (node._rotationY === node._rotationX) {
157183
a = d;
158184
b = -c;
159185
}
160186
else {
161-
var rotationRadiansY = node._rotationY * 0.017453292519943295; //0.017453292519943295 = (Math.PI / 180); for performance
187+
var rotationRadiansY = node._rotationY * ONE_DEGREE;
162188
a = Math.cos(rotationRadiansY);
163189
b = -Math.sin(rotationRadiansY);
164190
}
@@ -172,8 +198,8 @@ cc.Node.RenderCmd.prototype = {
172198

173199
// skew
174200
if (hasSkew) {
175-
var skx = Math.tan(node._skewX * Math.PI / 180);
176-
var sky = Math.tan(node._skewY * Math.PI / 180);
201+
var skx = Math.tan(node._skewX * ONE_DEGREE);
202+
var sky = Math.tan(node._skewY * ONE_DEGREE);
177203
if (skx === Infinity)
178204
skx = 99999999;
179205
if (sky === Infinity)
@@ -250,17 +276,13 @@ cc.Node.RenderCmd.prototype = {
250276
this._transform = cc.affineTransformConcat(t, node._additionalTransform);
251277
}
252278

253-
this._updateCurrentRegions && this._updateCurrentRegions();
254-
this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble);
279+
if (this._updateCurrentRegions) {
280+
this._updateCurrentRegions();
281+
this._notifyRegionStatus && this._notifyRegionStatus(cc.Node.CanvasRenderCmd.RegionStatus.DirtyDouble);
282+
}
255283

256284
if (recursive) {
257-
var locChildren = this._node._children;
258-
if (!locChildren || locChildren.length === 0)
259-
return;
260-
var i, len;
261-
for (i = 0, len = locChildren.length; i < len; i++) {
262-
locChildren[i]._renderCmd.transform(this, recursive);
263-
}
285+
transformChildTree(node);
264286
}
265287

266288
this._cacheDirty = true;
@@ -331,7 +353,7 @@ cc.Node.RenderCmd.prototype = {
331353
}
332354
}
333355
}
334-
this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.colorDirty ^ this._dirtyFlag;
356+
this._dirtyFlag &= ~dirtyFlags.colorDirty;
335357
},
336358

337359
_updateDisplayOpacity: function (parentOpacity) {
@@ -366,7 +388,7 @@ cc.Node.RenderCmd.prototype = {
366388
}
367389
}
368390
}
369-
this._dirtyFlag = this._dirtyFlag & cc.Node._dirtyFlags.opacityDirty ^ this._dirtyFlag;
391+
this._dirtyFlag &= ~dirtyFlags.opacityDirty;
370392
},
371393

372394
_syncDisplayColor: function (parentColor) {
@@ -394,14 +416,17 @@ cc.Node.RenderCmd.prototype = {
394416
this._displayedOpacity = node._realOpacity * parentOpacity / 255.0;
395417
},
396418

397-
_updateColor: function () {
398-
},
419+
_updateColor: function(){},
399420

400421
updateStatus: function () {
401-
var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag;
402-
var colorDirty = locFlag & flags.colorDirty,
403-
opacityDirty = locFlag & flags.opacityDirty;
404-
this._savedDirtyFlag = this._savedDirtyFlag || locFlag;
422+
var locFlag = this._dirtyFlag;
423+
var colorDirty = locFlag & dirtyFlags.colorDirty,
424+
opacityDirty = locFlag & dirtyFlags.opacityDirty;
425+
426+
if (locFlag & dirtyFlags.contentDirty) {
427+
this._notifyRegionStatus && this._notifyRegionStatus(_ccsg.Node.CanvasRenderCmd.RegionStatus.Dirty);
428+
this._dirtyFlag &= ~dirtyFlags.contentDirty;
429+
}
405430

406431
if (colorDirty)
407432
this._updateDisplayColor();
@@ -412,20 +437,20 @@ cc.Node.RenderCmd.prototype = {
412437
if (colorDirty || opacityDirty)
413438
this._updateColor();
414439

415-
if (locFlag & flags.transformDirty) {
440+
if (locFlag & dirtyFlags.transformDirty) {
416441
//update the transform
417442
this.transform(this.getParentRenderCmd(), true);
418-
this._dirtyFlag = this._dirtyFlag & flags.transformDirty ^ this._dirtyFlag;
443+
this._dirtyFlag &= ~dirtyFlags.transformDirty;
419444
}
420445

421-
if (locFlag & flags.orderDirty)
422-
this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
446+
if (locFlag & dirtyFlags.orderDirty)
447+
this._dirtyFlag &= ~dirtyFlags.orderDirty;
423448
},
424449

425450
_syncStatus: function (parentCmd) {
426451
// In the visit logic does not restore the _dirtyFlag
427452
// Because child elements need parent's _dirtyFlag to change himself
428-
var flags = cc.Node._dirtyFlags, locFlag = this._dirtyFlag, parentNode = null;
453+
var locFlag = this._dirtyFlag, parentNode = null;
429454
if (parentCmd) {
430455
parentNode = parentCmd._node;
431456
this._savedDirtyFlag = this._savedDirtyFlag || parentCmd._savedDirtyFlag || locFlag;
@@ -440,37 +465,37 @@ cc.Node.RenderCmd.prototype = {
440465
// But while the child element does not enter the circulation
441466
// Here will be reset state in last
442467
// In order the child elements get the parent state
443-
if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & flags.colorDirty))
444-
locFlag |= flags.colorDirty;
468+
if (parentNode && parentNode._cascadeColorEnabled && (parentCmd._dirtyFlag & dirtyFlags.colorDirty))
469+
locFlag |= dirtyFlags.colorDirty;
445470

446-
if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & flags.opacityDirty))
447-
locFlag |= flags.opacityDirty;
471+
if (parentNode && parentNode._cascadeOpacityEnabled && (parentCmd._dirtyFlag & dirtyFlags.opacityDirty))
472+
locFlag |= dirtyFlags.opacityDirty;
448473

449-
if (parentCmd && (parentCmd._dirtyFlag & flags.transformDirty))
450-
locFlag |= flags.transformDirty;
474+
if (parentCmd && (parentCmd._dirtyFlag & dirtyFlags.transformDirty))
475+
locFlag |= dirtyFlags.transformDirty;
451476

452-
var colorDirty = locFlag & flags.colorDirty,
453-
opacityDirty = locFlag & flags.opacityDirty;
477+
var colorDirty = locFlag & dirtyFlags.colorDirty,
478+
opacityDirty = locFlag & dirtyFlags.opacityDirty;
454479

455480
this._dirtyFlag = locFlag;
456481

457482
if (colorDirty)
458-
//update the color
483+
//update the color
459484
this._syncDisplayColor();
460485

461486
if (opacityDirty)
462-
//update the opacity
487+
//update the opacity
463488
this._syncDisplayOpacity();
464489

465490
if (colorDirty || opacityDirty)
466491
this._updateColor();
467492

468-
if (locFlag & flags.transformDirty)
493+
if (locFlag & dirtyFlags.transformDirty)
469494
//update the transform
470495
this.transform(parentCmd);
471496

472-
if (locFlag & flags.orderDirty)
473-
this._dirtyFlag = this._dirtyFlag & flags.orderDirty ^ this._dirtyFlag;
497+
if (locFlag & dirtyFlags.orderDirty)
498+
this._dirtyFlag &= ~dirtyFlags.orderDirty;
474499
},
475500

476501
visitChildren: function () {
@@ -612,4 +637,4 @@ cc.Node.RenderCmd.prototype.originTransform = cc.Node.RenderCmd.prototype.transf
612637
return "source-over";
613638
}
614639
};
615-
})();
640+
})();

0 commit comments

Comments
 (0)