1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | (function (global, factory) {
|
7 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
8 | typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
9 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.pcx = {}));
|
10 | }(this, (function (exports) { 'use strict';
|
11 |
|
12 | function _defineProperties(target, props) {
|
13 | for (var i = 0; i < props.length; i++) {
|
14 | var descriptor = props[i];
|
15 | descriptor.enumerable = descriptor.enumerable || false;
|
16 | descriptor.configurable = true;
|
17 | if ("value" in descriptor) descriptor.writable = true;
|
18 | Object.defineProperty(target, descriptor.key, descriptor);
|
19 | }
|
20 | }
|
21 |
|
22 | function _createClass(Constructor, protoProps, staticProps) {
|
23 | if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
24 | if (staticProps) _defineProperties(Constructor, staticProps);
|
25 | return Constructor;
|
26 | }
|
27 |
|
28 | var CpuTimer = function () {
|
29 | function CpuTimer(app) {
|
30 | this._frameIndex = 0;
|
31 | this._frameTimings = [];
|
32 | this._timings = [];
|
33 | this._prevTimings = [];
|
34 | this.unitsName = "ms";
|
35 | this.decimalPlaces = 1;
|
36 | this.enabled = true;
|
37 | app.on('frameupdate', this.begin.bind(this, 'update'));
|
38 | app.on('framerender', this.mark.bind(this, 'render'));
|
39 | app.on('frameend', this.mark.bind(this, 'other'));
|
40 | }
|
41 |
|
42 | var _proto = CpuTimer.prototype;
|
43 |
|
44 | _proto.begin = function begin(name) {
|
45 | if (!this.enabled) {
|
46 | return;
|
47 | }
|
48 |
|
49 | if (this._frameIndex < this._frameTimings.length) {
|
50 | this._frameTimings.splice(this._frameIndex);
|
51 | }
|
52 |
|
53 | var tmp = this._prevTimings;
|
54 | this._prevTimings = this._timings;
|
55 | this._timings = this._frameTimings;
|
56 | this._frameTimings = tmp;
|
57 | this._frameIndex = 0;
|
58 | this.mark(name);
|
59 | };
|
60 |
|
61 | _proto.mark = function mark(name) {
|
62 | if (!this.enabled) {
|
63 | return;
|
64 | }
|
65 |
|
66 | var timestamp = pc.now();
|
67 | var prev;
|
68 |
|
69 | if (this._frameIndex > 0) {
|
70 | prev = this._frameTimings[this._frameIndex - 1];
|
71 | prev[1] = timestamp - prev[1];
|
72 | } else if (this._timings.length > 0) {
|
73 | prev = this._timings[this._timings.length - 1];
|
74 | prev[1] = timestamp - prev[1];
|
75 | }
|
76 |
|
77 | if (this._frameIndex >= this._frameTimings.length) {
|
78 | this._frameTimings.push([name, timestamp]);
|
79 | } else {
|
80 | var timing = this._frameTimings[this._frameIndex];
|
81 | timing[0] = name;
|
82 | timing[1] = timestamp;
|
83 | }
|
84 |
|
85 | this._frameIndex++;
|
86 | };
|
87 |
|
88 | _createClass(CpuTimer, [{
|
89 | key: "timings",
|
90 | get: function get() {
|
91 | return this._timings.slice(0, -1).map(function (v) {
|
92 | return v[1];
|
93 | });
|
94 | }
|
95 | }]);
|
96 |
|
97 | return CpuTimer;
|
98 | }();
|
99 |
|
100 | var GpuTimer = function () {
|
101 | function GpuTimer(app) {
|
102 | this._gl = app.graphicsDevice.gl;
|
103 | this._ext = app.graphicsDevice.extDisjointTimerQuery;
|
104 | this._freeQueries = [];
|
105 | this._frameQueries = [];
|
106 | this._frames = [];
|
107 | this._timings = [];
|
108 | this._prevTimings = [];
|
109 | this.enabled = true;
|
110 | this.unitsName = "ms";
|
111 | this.decimalPlaces = 1;
|
112 | app.on('frameupdate', this.begin.bind(this, 'update'));
|
113 | app.on('framerender', this.mark.bind(this, 'render'));
|
114 | app.on('frameend', this.end.bind(this));
|
115 | }
|
116 |
|
117 | var _proto = GpuTimer.prototype;
|
118 |
|
119 | _proto.loseContext = function loseContext() {
|
120 | this._freeQueries = [];
|
121 | this._frameQueries = [];
|
122 | this._frames = [];
|
123 | };
|
124 |
|
125 | _proto.begin = function begin(name) {
|
126 | if (!this.enabled) {
|
127 | return;
|
128 | }
|
129 |
|
130 | if (this._frameQueries.length > 0) {
|
131 | this.end();
|
132 | }
|
133 |
|
134 | this._checkDisjoint();
|
135 |
|
136 | if (this._frames.length > 0) {
|
137 | if (this._resolveFrameTimings(this._frames[0], this._prevTimings)) {
|
138 | var tmp = this._prevTimings;
|
139 | this._prevTimings = this._timings;
|
140 | this._timings = tmp;
|
141 | this._freeQueries = this._freeQueries.concat(this._frames.splice(0, 1)[0]);
|
142 | }
|
143 | }
|
144 |
|
145 | this.mark(name);
|
146 | };
|
147 |
|
148 | _proto.mark = function mark(name) {
|
149 | if (!this.enabled) {
|
150 | return;
|
151 | }
|
152 |
|
153 | if (this._frameQueries.length > 0) {
|
154 | this._gl.endQuery(this._ext.TIME_ELAPSED_EXT);
|
155 | }
|
156 |
|
157 | var query = this._allocateQuery();
|
158 |
|
159 | query[0] = name;
|
160 |
|
161 | this._gl.beginQuery(this._ext.TIME_ELAPSED_EXT, query[1]);
|
162 |
|
163 | this._frameQueries.push(query);
|
164 | };
|
165 |
|
166 | _proto.end = function end() {
|
167 | if (!this.enabled) {
|
168 | return;
|
169 | }
|
170 |
|
171 | this._gl.endQuery(this._ext.TIME_ELAPSED_EXT);
|
172 |
|
173 | this._frames.push(this._frameQueries);
|
174 |
|
175 | this._frameQueries = [];
|
176 | };
|
177 |
|
178 | _proto._checkDisjoint = function _checkDisjoint() {
|
179 | var disjoint = this._gl.getParameter(this._ext.GPU_DISJOINT_EXT);
|
180 |
|
181 | if (disjoint) {
|
182 | this._freeQueries = [this._frames, [this._frameQueries], [this._freeQueries]].flat(2);
|
183 | this._frameQueries = [];
|
184 | this._frames = [];
|
185 | }
|
186 | };
|
187 |
|
188 | _proto._allocateQuery = function _allocateQuery() {
|
189 | return this._freeQueries.length > 0 ? this._freeQueries.splice(-1, 1)[0] : ["", this._gl.createQuery()];
|
190 | };
|
191 |
|
192 | _proto._resolveFrameTimings = function _resolveFrameTimings(frame, timings) {
|
193 | if (!this._gl.getQueryParameter(frame[frame.length - 1][1], this._gl.QUERY_RESULT_AVAILABLE)) {
|
194 | return false;
|
195 | }
|
196 |
|
197 | for (var i = 0; i < frame.length; ++i) {
|
198 | timings[i] = [frame[i][0], this._gl.getQueryParameter(frame[i][1], this._gl.QUERY_RESULT) * 0.000001];
|
199 | }
|
200 |
|
201 | return true;
|
202 | };
|
203 |
|
204 | _createClass(GpuTimer, [{
|
205 | key: "timings",
|
206 | get: function get() {
|
207 | return this._timings.map(function (v) {
|
208 | return v[1];
|
209 | });
|
210 | }
|
211 | }]);
|
212 |
|
213 | return GpuTimer;
|
214 | }();
|
215 |
|
216 | var StatsTimer = function () {
|
217 | function StatsTimer(app, statNames, decimalPlaces, unitsName, multiplier) {
|
218 | this.app = app;
|
219 | this.values = [];
|
220 | this.statNames = statNames;
|
221 | if (this.statNames.length > 3) this.statNames.length = 3;
|
222 | this.unitsName = unitsName;
|
223 | this.decimalPlaces = decimalPlaces;
|
224 | this.multiplier = multiplier || 1;
|
225 | var self = this;
|
226 |
|
227 | function resolve(path, obj) {
|
228 | return path.split('.').reduce(function (prev, curr) {
|
229 | return prev ? prev[curr] : null;
|
230 | }, obj || self);
|
231 | }
|
232 |
|
233 | app.on('frameupdate', function (ms) {
|
234 | for (var i = 0; i < self.statNames.length; i++) {
|
235 | self.values[i] = resolve(self.statNames[i], self.app.stats) * self.multiplier;
|
236 | }
|
237 | });
|
238 | }
|
239 |
|
240 | _createClass(StatsTimer, [{
|
241 | key: "timings",
|
242 | get: function get() {
|
243 | return this.values;
|
244 | }
|
245 | }]);
|
246 |
|
247 | return StatsTimer;
|
248 | }();
|
249 |
|
250 | var Graph = function () {
|
251 | function Graph(name, app, watermark, textRefreshRate, timer) {
|
252 | this.name = name;
|
253 | this.device = app.graphicsDevice;
|
254 | this.timer = timer;
|
255 | this.watermark = watermark;
|
256 | this.enabled = false;
|
257 | this.textRefreshRate = textRefreshRate;
|
258 | this.avgTotal = 0;
|
259 | this.avgTimer = 0;
|
260 | this.avgCount = 0;
|
261 | this.timingText = "";
|
262 | this.texture = null;
|
263 | this.yOffset = 0;
|
264 | this.cursor = 0;
|
265 | this.sample = new Uint8ClampedArray(4);
|
266 | this.sample.set([0, 0, 0, 255]);
|
267 | app.on('frameupdate', this.update.bind(this));
|
268 | this.counter = 0;
|
269 | }
|
270 |
|
271 | var _proto = Graph.prototype;
|
272 |
|
273 | _proto.loseContext = function loseContext() {
|
274 | if (this.timer && typeof this.timer.loseContext === 'function') {
|
275 | this.timer.loseContext();
|
276 | }
|
277 | };
|
278 |
|
279 | _proto.update = function update(ms) {
|
280 | var timings = this.timer.timings;
|
281 | var total = timings.reduce(function (a, v) {
|
282 | return a + v;
|
283 | }, 0);
|
284 | this.avgTotal += total;
|
285 | this.avgTimer += ms;
|
286 | this.avgCount++;
|
287 |
|
288 | if (this.avgTimer > this.textRefreshRate) {
|
289 | this.timingText = (this.avgTotal / this.avgCount).toFixed(this.timer.decimalPlaces);
|
290 | this.avgTimer = 0;
|
291 | this.avgTotal = 0;
|
292 | this.avgCount = 0;
|
293 | }
|
294 |
|
295 | if (this.enabled) {
|
296 | var value = 0;
|
297 | var range = 1.5 * this.watermark;
|
298 |
|
299 | for (var i = 0; i < timings.length; ++i) {
|
300 | value += Math.floor(timings[i] / range * 255);
|
301 | this.sample[i] = value;
|
302 | }
|
303 |
|
304 | this.sample[3] = this.watermark / range * 255;
|
305 | var gl = this.device.gl;
|
306 | this.device.bindTexture(this.texture);
|
307 | gl.texSubImage2D(gl.TEXTURE_2D, 0, this.cursor, this.yOffset, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, this.sample);
|
308 | this.cursor++;
|
309 |
|
310 | if (this.cursor === this.texture.width) {
|
311 | this.cursor = 0;
|
312 | }
|
313 | }
|
314 | };
|
315 |
|
316 | _proto.render = function render(render2d, x, y, w, h) {
|
317 | render2d.quad(this.texture, x + w, y, -w, h, this.cursor, 0.5 + this.yOffset, -w, 0, this.enabled);
|
318 | };
|
319 |
|
320 | return Graph;
|
321 | }();
|
322 |
|
323 | var WordAtlas = function () {
|
324 | function WordAtlas(texture, words) {
|
325 | var canvas = document.createElement('canvas');
|
326 | canvas.width = texture.width;
|
327 | canvas.height = texture.height;
|
328 | var context = canvas.getContext('2d', {
|
329 | alpha: true
|
330 | });
|
331 | context.font = '10px "Lucida Console", Monaco, monospace';
|
332 | context.textAlign = "left";
|
333 | context.textBaseline = "alphabetic";
|
334 | context.fillStyle = "rgb(255, 255, 255)";
|
335 | var padding = 5;
|
336 | var x = padding;
|
337 | var y = padding;
|
338 | var placements = [];
|
339 | var i;
|
340 |
|
341 | for (i = 0; i < words.length; ++i) {
|
342 | var measurement = context.measureText(words[i]);
|
343 | var l = Math.ceil(-measurement.actualBoundingBoxLeft);
|
344 | var r = Math.ceil(measurement.actualBoundingBoxRight);
|
345 | var a = Math.ceil(measurement.actualBoundingBoxAscent);
|
346 | var d = Math.ceil(measurement.actualBoundingBoxDescent);
|
347 | var w = l + r;
|
348 | var h = a + d;
|
349 |
|
350 | if (x + w >= canvas.width) {
|
351 | x = padding;
|
352 | y += 16;
|
353 | }
|
354 |
|
355 | context.fillStyle = words[i].length === 1 ? "rgb(255, 255, 255)" : "rgb(150, 150, 150)";
|
356 | context.fillText(words[i], x - l, y + a);
|
357 | placements.push({
|
358 | l: l,
|
359 | r: r,
|
360 | a: a,
|
361 | d: d,
|
362 | x: x,
|
363 | y: y,
|
364 | w: w,
|
365 | h: h
|
366 | });
|
367 | x += w + padding;
|
368 | }
|
369 |
|
370 | var wordMap = {};
|
371 | words.forEach(function (w, i) {
|
372 | wordMap[w] = i;
|
373 | });
|
374 | this.words = words;
|
375 | this.wordMap = wordMap;
|
376 | this.placements = placements;
|
377 | this.texture = texture;
|
378 | var source = context.getImageData(0, 0, canvas.width, canvas.height);
|
379 | var dest = texture.lock();
|
380 | var red, alpha;
|
381 |
|
382 | for (y = 0; y < source.height; ++y) {
|
383 | for (x = 0; x < source.width; ++x) {
|
384 | var offset = (x + y * texture.width) * 4;
|
385 | dest[offset] = 255;
|
386 | dest[offset + 1] = 255;
|
387 | dest[offset + 2] = 255;
|
388 | red = source.data[(x + (source.height - 1 - y) * source.width) * 4];
|
389 | alpha = source.data[(x + (source.height - 1 - y) * source.width) * 4 + 3];
|
390 | dest[offset + 3] = alpha * (red > 150 ? 1 : 0.7);
|
391 | }
|
392 | }
|
393 | }
|
394 |
|
395 | var _proto = WordAtlas.prototype;
|
396 |
|
397 | _proto.render = function render(render2d, word, x, y) {
|
398 | var p = this.placements[this.wordMap[word]];
|
399 |
|
400 | if (p) {
|
401 | var padding = 1;
|
402 | render2d.quad(this.texture, x + p.l - padding, y - p.d + padding, p.w + padding * 2, p.h + padding * 2, p.x - padding, 64 - p.y - p.h - padding, undefined, undefined, true);
|
403 | return p.w;
|
404 | }
|
405 |
|
406 | return 0;
|
407 | };
|
408 |
|
409 | return WordAtlas;
|
410 | }();
|
411 |
|
412 | var Render2d = function () {
|
413 | function Render2d(device, colors, maxQuads) {
|
414 | if (maxQuads === void 0) {
|
415 | maxQuads = 512;
|
416 | }
|
417 |
|
418 | var vertexShader = 'attribute vec3 vertex_position;\n' + 'attribute vec4 vertex_texCoord0;\n' + 'uniform vec4 screenAndTextureSize;\n' + 'varying vec4 uv0;\n' + 'varying float enabled;\n' + 'void main(void) {\n' + ' vec2 pos = vertex_position.xy / screenAndTextureSize.xy;\n' + ' gl_Position = vec4(pos * 2.0 - 1.0, 0.5, 1.0);\n' + ' uv0 = vec4(vertex_texCoord0.xy / screenAndTextureSize.zw, vertex_texCoord0.zw);\n' + ' enabled = vertex_position.z;\n' + '}\n';
|
419 | var fragmentShader = 'varying vec4 uv0;\n' + 'varying float enabled;\n' + 'uniform vec4 clr;\n' + 'uniform vec4 col0;\n' + 'uniform vec4 col1;\n' + 'uniform vec4 col2;\n' + 'uniform vec4 watermark;\n' + 'uniform float watermarkSize;\n' + 'uniform vec4 background;\n' + 'uniform sampler2D source;\n' + 'void main (void) {\n' + ' vec4 tex = texture2D(source, uv0.xy);\n' + ' if (!(tex.rgb == vec3(1.0, 1.0, 1.0))) {\n' + ' if (enabled < 0.5)\n' + ' tex = background;\n' + ' else if (abs(uv0.w - tex.a) < watermarkSize)\n' + ' tex = watermark;\n' + ' else if (uv0.w < tex.r)\n' + ' tex = col0;\n' + ' else if (uv0.w < tex.g)\n' + ' tex = col1;\n' + ' else if (uv0.w < tex.b)\n' + ' tex = col2;\n' + ' else\n' + ' tex = background;\n' + ' }\n' + ' gl_FragColor = tex * clr;\n' + '}\n';
|
420 | var format = new pc.VertexFormat(device, [{
|
421 | semantic: pc.SEMANTIC_POSITION,
|
422 | components: 3,
|
423 | type: pc.TYPE_FLOAT32
|
424 | }, {
|
425 | semantic: pc.SEMANTIC_TEXCOORD0,
|
426 | components: 4,
|
427 | type: pc.TYPE_FLOAT32
|
428 | }]);
|
429 | var indices = new Uint16Array(maxQuads * 6);
|
430 |
|
431 | for (var i = 0; i < maxQuads; ++i) {
|
432 | indices[i * 6 + 0] = i * 4;
|
433 | indices[i * 6 + 1] = i * 4 + 1;
|
434 | indices[i * 6 + 2] = i * 4 + 2;
|
435 | indices[i * 6 + 3] = i * 4;
|
436 | indices[i * 6 + 4] = i * 4 + 2;
|
437 | indices[i * 6 + 5] = i * 4 + 3;
|
438 | }
|
439 |
|
440 | this.device = device;
|
441 | this.shader = pc.shaderChunks.createShaderFromCode(device, vertexShader, fragmentShader, "mini-stats");
|
442 | this.buffer = new pc.VertexBuffer(device, format, maxQuads * 4, pc.BUFFER_STREAM);
|
443 | this.data = new Float32Array(this.buffer.numBytes / 4);
|
444 | this.indexBuffer = new pc.IndexBuffer(device, pc.INDEXFORMAT_UINT16, maxQuads * 6, pc.BUFFER_STATIC, indices);
|
445 | this.prims = [];
|
446 | this.prim = null;
|
447 | this.primIndex = -1;
|
448 | this.quads = 0;
|
449 |
|
450 | var setupColor = function (name, value) {
|
451 | this[name] = new Float32Array([value.r, value.g, value.b, value.a]);
|
452 | this[name + "Id"] = device.scope.resolve(name);
|
453 | }.bind(this);
|
454 |
|
455 | setupColor("col0", colors.graph0);
|
456 | setupColor("col1", colors.graph1);
|
457 | setupColor("col2", colors.graph2);
|
458 | setupColor("watermark", colors.watermark);
|
459 | setupColor("background", colors.background);
|
460 | this.watermarkSizeId = device.scope.resolve('watermarkSize');
|
461 | this.clrId = device.scope.resolve('clr');
|
462 | this.clr = new Float32Array(4);
|
463 | this.screenTextureSizeId = device.scope.resolve('screenAndTextureSize');
|
464 | this.screenTextureSize = new Float32Array(4);
|
465 | }
|
466 |
|
467 | var _proto = Render2d.prototype;
|
468 |
|
469 | _proto.quad = function quad(texture, x, y, w, h, u, v, uw, uh, enabled) {
|
470 | var quad = this.quads++;
|
471 | var prim = this.prim;
|
472 |
|
473 | if (prim && prim.texture === texture) {
|
474 | prim.count += 6;
|
475 | } else {
|
476 | this.primIndex++;
|
477 |
|
478 | if (this.primIndex === this.prims.length) {
|
479 | prim = {
|
480 | type: pc.PRIMITIVE_TRIANGLES,
|
481 | indexed: true,
|
482 | base: quad * 6,
|
483 | count: 6,
|
484 | texture: texture
|
485 | };
|
486 | this.prims.push(prim);
|
487 | } else {
|
488 | prim = this.prims[this.primIndex];
|
489 | prim.base = quad * 6;
|
490 | prim.count = 6;
|
491 | prim.texture = texture;
|
492 | }
|
493 |
|
494 | this.prim = prim;
|
495 | }
|
496 |
|
497 | var x1 = x + w;
|
498 | var y1 = y + h;
|
499 | var u1 = u + (uw === undefined ? w : uw);
|
500 | var v1 = v + (uh === undefined ? h : uh);
|
501 | var colorize = enabled ? 1 : 0;
|
502 | this.data.set([x, y, colorize, u, v, 0, 0, x1, y, colorize, u1, v, 1, 0, x1, y1, colorize, u1, v1, 1, 1, x, y1, colorize, u, v1, 0, 1], 4 * 7 * quad);
|
503 | };
|
504 |
|
505 | _proto.render = function render(clr, height) {
|
506 | var device = this.device;
|
507 | var buffer = this.buffer;
|
508 | buffer.setData(this.data.buffer);
|
509 | device.updateBegin();
|
510 | device.setDepthTest(false);
|
511 | device.setDepthWrite(false);
|
512 | device.setCullMode(pc.CULLFACE_NONE);
|
513 | device.setBlending(true);
|
514 | device.setBlendFunctionSeparate(pc.BLENDMODE_SRC_ALPHA, pc.BLENDMODE_ONE_MINUS_SRC_ALPHA, pc.BLENDMODE_ONE, pc.BLENDMODE_ONE);
|
515 | device.setBlendEquationSeparate(pc.BLENDEQUATION_ADD, pc.BLENDEQUATION_ADD);
|
516 | device.setVertexBuffer(buffer, 0);
|
517 | device.setIndexBuffer(this.indexBuffer);
|
518 | device.setShader(this.shader);
|
519 | var pr = Math.min(device.maxPixelRatio, window.devicePixelRatio);
|
520 | this.clr.set(clr, 0);
|
521 | this.clrId.setValue(this.clr);
|
522 | this.screenTextureSize[0] = device.width / pr;
|
523 | this.screenTextureSize[1] = device.height / pr;
|
524 | this.col0Id.setValue(this.col0);
|
525 | this.col1Id.setValue(this.col1);
|
526 | this.col2Id.setValue(this.col2);
|
527 | this.watermarkId.setValue(this.watermark);
|
528 | this.backgroundId.setValue(this.background);
|
529 |
|
530 | for (var i = 0; i <= this.primIndex; ++i) {
|
531 | var prim = this.prims[i];
|
532 | this.screenTextureSize[2] = prim.texture.width;
|
533 | this.screenTextureSize[3] = prim.texture.height;
|
534 | this.screenTextureSizeId.setValue(this.screenTextureSize);
|
535 | device.constantTexSource.setValue(prim.texture);
|
536 | this.watermarkSizeId.setValue(0.5 / height);
|
537 | device.draw(prim);
|
538 | }
|
539 |
|
540 | device.updateEnd();
|
541 | this.prim = null;
|
542 | this.primIndex = -1;
|
543 | this.quads = 0;
|
544 | };
|
545 |
|
546 | return Render2d;
|
547 | }();
|
548 |
|
549 | var MiniStats = function () {
|
550 | function MiniStats(app, options) {
|
551 | var device = app.graphicsDevice;
|
552 |
|
553 | this._contextLostHandler = function (event) {
|
554 | event.preventDefault();
|
555 |
|
556 | if (this.graphs) {
|
557 | for (var i = 0; i < this.graphs.length; i++) {
|
558 | this.graphs[i].loseContext();
|
559 | }
|
560 | }
|
561 | }.bind(this);
|
562 |
|
563 | device.canvas.addEventListener("webglcontextlost", this._contextLostHandler, false);
|
564 | options = options || MiniStats.getDefaultOptions();
|
565 | var graphs = this.initGraphs(app, device, options);
|
566 | var words = ["", "ms", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."];
|
567 | graphs.forEach(function (graph) {
|
568 | words.push(graph.name);
|
569 | });
|
570 |
|
571 | if (options.stats) {
|
572 | options.stats.forEach(function (stat) {
|
573 | if (stat.unitsName) words.push(stat.unitsName);
|
574 | });
|
575 | }
|
576 |
|
577 | words = words.filter(function (item, index) {
|
578 | return words.indexOf(item) >= index;
|
579 | });
|
580 | var maxWidth = options.sizes.reduce(function (max, v) {
|
581 | return v.width > max ? v.width : max;
|
582 | }, 0);
|
583 | var wordAtlasData = this.initWordAtlas(device, words, maxWidth, graphs.length);
|
584 | var texture = wordAtlasData.texture;
|
585 | graphs.forEach(function (graph, i) {
|
586 | graph.texture = texture;
|
587 | graph.yOffset = i;
|
588 | });
|
589 | this.sizes = options.sizes;
|
590 | this._activeSizeIndex = options.startSizeIndex;
|
591 | var self = this;
|
592 | var div = document.createElement('div');
|
593 | div.style.cssText = 'position:fixed;bottom:0;left:0;background:transparent;';
|
594 | document.body.appendChild(div);
|
595 | div.addEventListener('mouseenter', function (event) {
|
596 | self.opacity = 1.0;
|
597 | });
|
598 | div.addEventListener('mouseleave', function (event) {
|
599 | self.opacity = 0.5;
|
600 | });
|
601 | div.addEventListener('click', function (event) {
|
602 | event.preventDefault();
|
603 |
|
604 | if (self._enabled) {
|
605 | self.activeSizeIndex = (self.activeSizeIndex + 1) % self.sizes.length;
|
606 | self.resize(self.sizes[self.activeSizeIndex].width, self.sizes[self.activeSizeIndex].height, self.sizes[self.activeSizeIndex].graphs);
|
607 | }
|
608 | });
|
609 | device.on("resizecanvas", function () {
|
610 | self.updateDiv();
|
611 | });
|
612 | app.on('postrender', function () {
|
613 | if (self._enabled) {
|
614 | self.render();
|
615 | }
|
616 | });
|
617 | this.device = device;
|
618 | this.texture = texture;
|
619 | this.wordAtlas = wordAtlasData.atlas;
|
620 | this.render2d = new Render2d(device, options.colors);
|
621 | this.graphs = graphs;
|
622 | this.div = div;
|
623 | this.width = 0;
|
624 | this.height = 0;
|
625 | this.gspacing = 2;
|
626 | this.clr = [1, 1, 1, 0.5];
|
627 | this._enabled = true;
|
628 | this.activeSizeIndex = this._activeSizeIndex;
|
629 | }
|
630 |
|
631 | MiniStats.getDefaultOptions = function getDefaultOptions() {
|
632 | return {
|
633 | sizes: [{
|
634 | width: 100,
|
635 | height: 16,
|
636 | spacing: 0,
|
637 | graphs: false
|
638 | }, {
|
639 | width: 128,
|
640 | height: 32,
|
641 | spacing: 2,
|
642 | graphs: true
|
643 | }, {
|
644 | width: 256,
|
645 | height: 64,
|
646 | spacing: 2,
|
647 | graphs: true
|
648 | }],
|
649 | startSizeIndex: 0,
|
650 | textRefreshRate: 500,
|
651 | colors: {
|
652 | graph0: new pc.Color(0.7, 0.2, 0.2, 1),
|
653 | graph1: new pc.Color(0.2, 0.7, 0.2, 1),
|
654 | graph2: new pc.Color(0.2, 0.2, 0.7, 1),
|
655 | watermark: new pc.Color(0.4, 0.4, 0.2, 1),
|
656 | background: new pc.Color(0, 0, 0, 1.0)
|
657 | },
|
658 | cpu: {
|
659 | enabled: true,
|
660 | watermark: 33
|
661 | },
|
662 | gpu: {
|
663 | enabled: true,
|
664 | watermark: 33
|
665 | },
|
666 | stats: [{
|
667 | name: "Frame",
|
668 | stats: ["frame.ms"],
|
669 | decimalPlaces: 1,
|
670 | unitsName: "ms",
|
671 | watermark: 33
|
672 | }, {
|
673 | name: "DrawCalls",
|
674 | stats: ["drawCalls.total"],
|
675 | watermark: 1000
|
676 | }]
|
677 | };
|
678 | };
|
679 |
|
680 | var _proto = MiniStats.prototype;
|
681 |
|
682 | _proto.initWordAtlas = function initWordAtlas(device, words, maxWidth, numGraphs) {
|
683 | var texture = new pc.Texture(device, {
|
684 | name: 'mini-stats',
|
685 | width: pc.math.nextPowerOfTwo(maxWidth),
|
686 | height: 64,
|
687 | mipmaps: false,
|
688 | minFilter: pc.FILTER_NEAREST,
|
689 | magFilter: pc.FILTER_NEAREST
|
690 | });
|
691 | var wordAtlas = new WordAtlas(texture, words);
|
692 | var dest = texture.lock();
|
693 |
|
694 | for (var i = 0; i < texture.width * numGraphs; ++i) {
|
695 | dest.set([0, 0, 0, 255], i * 4);
|
696 | }
|
697 |
|
698 | texture.unlock();
|
699 | device.setTexture(texture, 0);
|
700 | return {
|
701 | atlas: wordAtlas,
|
702 | texture: texture
|
703 | };
|
704 | };
|
705 |
|
706 | _proto.initGraphs = function initGraphs(app, device, options) {
|
707 | var graphs = [];
|
708 |
|
709 | if (options.cpu.enabled) {
|
710 | graphs.push(new Graph('CPU', app, options.cpu.watermark, options.textRefreshRate, new CpuTimer(app)));
|
711 | }
|
712 |
|
713 | if (options.gpu.enabled && device.extDisjointTimerQuery) {
|
714 | graphs.push(new Graph('GPU', app, options.gpu.watermark, options.textRefreshRate, new GpuTimer(app)));
|
715 | }
|
716 |
|
717 | if (options.stats) {
|
718 | options.stats.forEach(function (entry) {
|
719 | graphs.push(new Graph(entry.name, app, entry.watermark, options.textRefreshRate, new StatsTimer(app, entry.stats, entry.decimalPlaces, entry.unitsName, entry.multiplier)));
|
720 | });
|
721 | }
|
722 |
|
723 | return graphs;
|
724 | };
|
725 |
|
726 | _proto.render = function render() {
|
727 | var graphs = this.graphs;
|
728 | var wordAtlas = this.wordAtlas;
|
729 | var render2d = this.render2d;
|
730 | var width = this.width;
|
731 | var height = this.height;
|
732 | var gspacing = this.gspacing;
|
733 | var i, j, x, y, graph;
|
734 |
|
735 | for (i = 0; i < graphs.length; ++i) {
|
736 | graph = graphs[i];
|
737 | y = i * (height + gspacing);
|
738 | graph.render(render2d, 0, y, width, height);
|
739 | x = 1;
|
740 | y += height - 13;
|
741 | x += wordAtlas.render(render2d, graph.name, x, y) + 10;
|
742 | var timingText = graph.timingText;
|
743 |
|
744 | for (j = 0; j < timingText.length; ++j) {
|
745 | x += wordAtlas.render(render2d, timingText[j], x, y);
|
746 | }
|
747 |
|
748 | if (graph.timer.unitsName) {
|
749 | x += 3;
|
750 | wordAtlas.render(render2d, graph.timer.unitsName, x, y);
|
751 | }
|
752 | }
|
753 |
|
754 | render2d.render(this.clr, height);
|
755 | };
|
756 |
|
757 | _proto.resize = function resize(width, height, showGraphs) {
|
758 | var graphs = this.graphs;
|
759 |
|
760 | for (var i = 0; i < graphs.length; ++i) {
|
761 | graphs[i].enabled = showGraphs;
|
762 | }
|
763 |
|
764 | this.width = width;
|
765 | this.height = height;
|
766 | this.updateDiv();
|
767 | };
|
768 |
|
769 | _proto.updateDiv = function updateDiv() {
|
770 | var rect = this.device.canvas.getBoundingClientRect();
|
771 | this.div.style.left = rect.left + "px";
|
772 | this.div.style.bottom = window.innerHeight - rect.bottom + "px";
|
773 | this.div.style.width = this.width + "px";
|
774 | this.div.style.height = this.overallHeight + "px";
|
775 | };
|
776 |
|
777 | _createClass(MiniStats, [{
|
778 | key: "activeSizeIndex",
|
779 | get: function get() {
|
780 | return this._activeSizeIndex;
|
781 | },
|
782 | set: function set(value) {
|
783 | this._activeSizeIndex = value;
|
784 | this.gspacing = this.sizes[value].spacing;
|
785 | this.resize(this.sizes[value].width, this.sizes[value].height, this.sizes[value].graphs);
|
786 | }
|
787 | }, {
|
788 | key: "opacity",
|
789 | get: function get() {
|
790 | return this.clr[3];
|
791 | },
|
792 | set: function set(value) {
|
793 | this.clr[3] = value;
|
794 | }
|
795 | }, {
|
796 | key: "overallHeight",
|
797 | get: function get() {
|
798 | var graphs = this.graphs;
|
799 | var spacing = this.gspacing;
|
800 | return this.height * graphs.length + spacing * (graphs.length - 1);
|
801 | }
|
802 | }, {
|
803 | key: "enabled",
|
804 | get: function get() {
|
805 | return this._enabled;
|
806 | },
|
807 | set: function set(value) {
|
808 | if (value !== this._enabled) {
|
809 | this._enabled = value;
|
810 |
|
811 | for (var i = 0; i < this.graphs.length; ++i) {
|
812 | this.graphs[i].enabled = value;
|
813 | this.graphs[i].timer.enabled = value;
|
814 | }
|
815 | }
|
816 | }
|
817 | }]);
|
818 |
|
819 | return MiniStats;
|
820 | }();
|
821 |
|
822 | exports.MiniStats = MiniStats;
|
823 |
|
824 | Object.defineProperty(exports, '__esModule', { value: true });
|
825 |
|
826 | })));
|