Skip to content

Commit 9217012

Browse files
committed
state;s children depth sorting
1 parent 4684d23 commit 9217012

3 files changed

Lines changed: 132 additions & 2 deletions

File tree

v3/src/components/Transform.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,19 @@ var Transform = {
1313
_scaleX: 1,
1414
_scaleY: 1,
1515
_rotation: 0,
16+
_z: 0,
1617

1718
x: 0,
1819
y: 0,
19-
z: 0,
20+
z: {
21+
get: function () {
22+
return this._z;
23+
},
24+
set: function (value) {
25+
this.state.sortChildrenFlag = (this._z !== value);
26+
this._z = value;
27+
}
28+
},
2029

2130
scaleX: {
2231

v3/src/state/Systems.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var Component = require('../components');
1414
var Settings = require('./Settings');
1515
var RTree = require('../structs/RTree');
1616
var CameraManager = require('./systems/CameraManager');
17+
var StableSort = require('../utils/array/StableSort');
1718

1819
var Systems = function (state, config)
1920
{
@@ -110,17 +111,26 @@ Systems.prototype = {
110111
this.state.data = this.data;
111112
this.state.settings = this.settings;
112113
this.state.state = this.stateManager;
113-
114114
this.state.cameras = this.cameras;
115115

116116
this.state.cache = this.game.cache;
117117
this.state.input = this.game.input;
118118
this.state.textures = this.game.textures;
119+
this.state.sortChildrenFlag = false;
119120
},
120121

121122
// Called just once per frame, regardless of speed
122123
begin: function (timestamp, frameDelta)
123124
{
125+
var state = this.state;
126+
if (state.sortChildrenFlag)
127+
{
128+
/* Sort the current state children */
129+
StableSort.inplace(state.children.list, function (childA, childB) {
130+
return childA._z - childB._z;
131+
});
132+
state.sortChildrenFlag = false;
133+
}
124134
},
125135

126136
// Potentially called multiple times per frame (on super-fast systems)

v3/src/utils/array/StableSort.js

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//! stable.js 0.1.6, https://github.com/Two-Screen/stable
2+
//! © 2017 Angry Bytes and contributors. MIT licensed.
3+
4+
(function() {
5+
6+
// A stable array sort, because `Array#sort()` is not guaranteed stable.
7+
// This is an implementation of merge sort, without recursion.
8+
9+
var stable = function(arr, comp) {
10+
return exec(arr.slice(), comp);
11+
};
12+
13+
stable.inplace = function(arr, comp) {
14+
var result = exec(arr, comp);
15+
16+
// This simply copies back if the result isn't in the original array,
17+
// which happens on an odd number of passes.
18+
if (result !== arr) {
19+
pass(result, null, arr.length, arr);
20+
}
21+
22+
return arr;
23+
};
24+
25+
// Execute the sort using the input array and a second buffer as work space.
26+
// Returns one of those two, containing the final result.
27+
function exec(arr, comp) {
28+
if (typeof(comp) !== 'function') {
29+
comp = function(a, b) {
30+
return String(a).localeCompare(b);
31+
};
32+
}
33+
34+
// Short-circuit when there's nothing to sort.
35+
var len = arr.length;
36+
if (len <= 1) {
37+
return arr;
38+
}
39+
40+
// Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc.
41+
// Chunks are the size of the left or right hand in merge sort.
42+
// Stop when the left-hand covers all of the array.
43+
var buffer = new Array(len);
44+
for (var chk = 1; chk < len; chk *= 2) {
45+
pass(arr, comp, chk, buffer);
46+
47+
var tmp = arr;
48+
arr = buffer;
49+
buffer = tmp;
50+
}
51+
52+
return arr;
53+
}
54+
55+
// Run a single pass with the given chunk size.
56+
var pass = function(arr, comp, chk, result) {
57+
var len = arr.length;
58+
var i = 0;
59+
// Step size / double chunk size.
60+
var dbl = chk * 2;
61+
// Bounds of the left and right chunks.
62+
var l, r, e;
63+
// Iterators over the left and right chunk.
64+
var li, ri;
65+
66+
// Iterate over pairs of chunks.
67+
for (l = 0; l < len; l += dbl) {
68+
r = l + chk;
69+
e = r + chk;
70+
if (r > len) r = len;
71+
if (e > len) e = len;
72+
73+
// Iterate both chunks in parallel.
74+
li = l;
75+
ri = r;
76+
while (true) {
77+
// Compare the chunks.
78+
if (li < r && ri < e) {
79+
// This works for a regular `sort()` compatible comparator,
80+
// but also for a simple comparator like: `a > b`
81+
if (comp(arr[li], arr[ri]) <= 0) {
82+
result[i++] = arr[li++];
83+
}
84+
else {
85+
result[i++] = arr[ri++];
86+
}
87+
}
88+
// Nothing to compare, just flush what's left.
89+
else if (li < r) {
90+
result[i++] = arr[li++];
91+
}
92+
else if (ri < e) {
93+
result[i++] = arr[ri++];
94+
}
95+
// Both iterators are at the chunk ends.
96+
else {
97+
break;
98+
}
99+
}
100+
}
101+
};
102+
103+
// Export using CommonJS or to the window.
104+
if (typeof(module) !== 'undefined') {
105+
module.exports = stable;
106+
}
107+
else {
108+
window.stable = stable;
109+
}
110+
111+
})();

0 commit comments

Comments
 (0)