babylon.debugLayer.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  1. var BABYLON;
  2. (function (BABYLON) {
  3. var DebugLayer = (function () {
  4. function DebugLayer(scene) {
  5. var _this = this;
  6. this._transformationMatrix = BABYLON.Matrix.Identity();
  7. this._enabled = false;
  8. this._labelsEnabled = false;
  9. this._displayStatistics = true;
  10. this._displayTree = false;
  11. this._displayLogs = false;
  12. this._skeletonViewers = new Array();
  13. this._identityMatrix = BABYLON.Matrix.Identity();
  14. this.axisRatio = 0.02;
  15. this.accentColor = "orange";
  16. this._scene = scene;
  17. this._syncPositions = function () {
  18. var engine = _this._scene.getEngine();
  19. var canvasRect = engine.getRenderingCanvasClientRect();
  20. if (_this._showUI) {
  21. _this._statsDiv.style.left = (canvasRect.width - 410) + "px";
  22. _this._statsDiv.style.top = (canvasRect.height - 290) + "px";
  23. _this._statsDiv.style.width = "400px";
  24. _this._statsDiv.style.height = "auto";
  25. _this._statsSubsetDiv.style.maxHeight = "240px";
  26. _this._optionsDiv.style.left = "0px";
  27. _this._optionsDiv.style.top = "10px";
  28. _this._optionsDiv.style.width = "200px";
  29. _this._optionsDiv.style.height = "auto";
  30. _this._optionsSubsetDiv.style.maxHeight = (canvasRect.height - 225) + "px";
  31. _this._logDiv.style.left = "0px";
  32. _this._logDiv.style.top = (canvasRect.height - 170) + "px";
  33. _this._logDiv.style.width = "600px";
  34. _this._logDiv.style.height = "160px";
  35. _this._treeDiv.style.left = (canvasRect.width - 310) + "px";
  36. _this._treeDiv.style.top = "10px";
  37. _this._treeDiv.style.width = "300px";
  38. _this._treeDiv.style.height = "auto";
  39. _this._treeSubsetDiv.style.maxHeight = (canvasRect.height - 340) + "px";
  40. }
  41. _this._globalDiv.style.left = canvasRect.left + "px";
  42. _this._globalDiv.style.top = canvasRect.top + "px";
  43. _this._drawingCanvas.style.left = "0px";
  44. _this._drawingCanvas.style.top = "0px";
  45. _this._drawingCanvas.style.width = engine.getRenderWidth() + "px";
  46. _this._drawingCanvas.style.height = engine.getRenderHeight() + "px";
  47. var devicePixelRatio = window.devicePixelRatio || 1;
  48. var context = _this._drawingContext;
  49. var backingStoreRatio = context.webkitBackingStorePixelRatio ||
  50. context.mozBackingStorePixelRatio ||
  51. context.msBackingStorePixelRatio ||
  52. context.oBackingStorePixelRatio ||
  53. context.backingStorePixelRatio || 1;
  54. _this._ratio = devicePixelRatio / backingStoreRatio;
  55. _this._drawingCanvas.width = engine.getRenderWidth() * _this._ratio;
  56. _this._drawingCanvas.height = engine.getRenderHeight() * _this._ratio;
  57. };
  58. this._onCanvasClick = function (evt) {
  59. _this._clickPosition = {
  60. x: evt.clientX * _this._ratio,
  61. y: evt.clientY * _this._ratio
  62. };
  63. };
  64. this._syncUI = function () {
  65. if (_this._showUI) {
  66. if (_this._displayStatistics) {
  67. _this._displayStats();
  68. _this._statsDiv.style.display = "";
  69. }
  70. else {
  71. _this._statsDiv.style.display = "none";
  72. }
  73. if (_this._displayLogs) {
  74. _this._logDiv.style.display = "";
  75. }
  76. else {
  77. _this._logDiv.style.display = "none";
  78. }
  79. if (_this._displayTree) {
  80. _this._treeDiv.style.display = "";
  81. if (_this._needToRefreshMeshesTree) {
  82. _this._needToRefreshMeshesTree = false;
  83. _this._refreshMeshesTreeContent();
  84. }
  85. }
  86. else {
  87. _this._treeDiv.style.display = "none";
  88. }
  89. }
  90. };
  91. this._syncData = function () {
  92. if (_this._labelsEnabled || !_this._showUI) {
  93. _this._camera.getViewMatrix().multiplyToRef(_this._camera.getProjectionMatrix(), _this._transformationMatrix);
  94. _this._drawingContext.clearRect(0, 0, _this._drawingCanvas.width, _this._drawingCanvas.height);
  95. var engine = _this._scene.getEngine();
  96. var viewport = _this._camera.viewport;
  97. var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
  98. // Meshes
  99. var meshes = _this._camera.getActiveMeshes();
  100. var index;
  101. var projectedPosition;
  102. for (index = 0; index < meshes.length; index++) {
  103. var mesh = meshes.data[index];
  104. var position = mesh.getBoundingInfo().boundingSphere.center;
  105. projectedPosition = BABYLON.Vector3.Project(position, mesh.getWorldMatrix(), _this._transformationMatrix, globalViewport);
  106. if (mesh.renderOverlay || _this.shouldDisplayAxis && _this.shouldDisplayAxis(mesh)) {
  107. _this._renderAxis(projectedPosition, mesh, globalViewport);
  108. }
  109. if (!_this.shouldDisplayLabel || _this.shouldDisplayLabel(mesh)) {
  110. _this._renderLabel(mesh.name, projectedPosition, 12, function () { mesh.renderOverlay = !mesh.renderOverlay; }, function () { return mesh.renderOverlay ? 'red' : 'black'; });
  111. }
  112. }
  113. // Cameras
  114. var cameras = _this._scene.cameras;
  115. for (index = 0; index < cameras.length; index++) {
  116. var camera = cameras[index];
  117. if (camera === _this._camera) {
  118. continue;
  119. }
  120. projectedPosition = BABYLON.Vector3.Project(BABYLON.Vector3.Zero(), camera.getWorldMatrix(), _this._transformationMatrix, globalViewport);
  121. if (!_this.shouldDisplayLabel || _this.shouldDisplayLabel(camera)) {
  122. _this._renderLabel(camera.name, projectedPosition, 12, function () {
  123. _this._camera.detachControl(engine.getRenderingCanvas());
  124. _this._camera = camera;
  125. _this._camera.attachControl(engine.getRenderingCanvas());
  126. }, function () { return "purple"; });
  127. }
  128. }
  129. // Lights
  130. var lights = _this._scene.lights;
  131. for (index = 0; index < lights.length; index++) {
  132. var light = lights[index];
  133. if (light.position) {
  134. projectedPosition = BABYLON.Vector3.Project(light.getAbsolutePosition(), _this._identityMatrix, _this._transformationMatrix, globalViewport);
  135. if (!_this.shouldDisplayLabel || _this.shouldDisplayLabel(light)) {
  136. _this._renderLabel(light.name, projectedPosition, -20, function () {
  137. light.setEnabled(!light.isEnabled());
  138. }, function () { return light.isEnabled() ? "orange" : "gray"; });
  139. }
  140. }
  141. }
  142. }
  143. _this._clickPosition = undefined;
  144. };
  145. }
  146. DebugLayer.prototype._refreshMeshesTreeContent = function () {
  147. while (this._treeSubsetDiv.hasChildNodes()) {
  148. this._treeSubsetDiv.removeChild(this._treeSubsetDiv.lastChild);
  149. }
  150. // Add meshes
  151. var sortedArray = this._scene.meshes.slice(0, this._scene.meshes.length);
  152. sortedArray.sort(function (a, b) {
  153. if (a.name === b.name) {
  154. return 0;
  155. }
  156. return (a.name > b.name) ? 1 : -1;
  157. });
  158. for (var index = 0; index < sortedArray.length; index++) {
  159. var mesh = sortedArray[index];
  160. if (!mesh.isEnabled()) {
  161. continue;
  162. }
  163. this._generateAdvancedCheckBox(this._treeSubsetDiv, mesh.name, mesh.getTotalVertices() + " verts", mesh.isVisible, function (element, m) {
  164. m.isVisible = element.checked;
  165. }, mesh);
  166. }
  167. };
  168. DebugLayer.prototype._renderSingleAxis = function (zero, unit, unitText, label, color) {
  169. this._drawingContext.beginPath();
  170. this._drawingContext.moveTo(zero.x, zero.y);
  171. this._drawingContext.lineTo(unit.x, unit.y);
  172. this._drawingContext.strokeStyle = color;
  173. this._drawingContext.lineWidth = 4;
  174. this._drawingContext.stroke();
  175. this._drawingContext.font = "normal 14px Segoe UI";
  176. this._drawingContext.fillStyle = color;
  177. this._drawingContext.fillText(label, unitText.x, unitText.y);
  178. };
  179. DebugLayer.prototype._renderAxis = function (projectedPosition, mesh, globalViewport) {
  180. var position = mesh.getBoundingInfo().boundingSphere.center;
  181. var worldMatrix = mesh.getWorldMatrix();
  182. var unprojectedVector = BABYLON.Vector3.UnprojectFromTransform(projectedPosition.add(new BABYLON.Vector3(this._drawingCanvas.width * this.axisRatio, 0, 0)), globalViewport.width, globalViewport.height, worldMatrix, this._transformationMatrix);
  183. var unit = (unprojectedVector.subtract(position)).length();
  184. var xAxis = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(unit, 0, 0)), worldMatrix, this._transformationMatrix, globalViewport);
  185. var xAxisText = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(unit * 1.5, 0, 0)), worldMatrix, this._transformationMatrix, globalViewport);
  186. this._renderSingleAxis(projectedPosition, xAxis, xAxisText, "x", "#FF0000");
  187. var yAxis = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(0, unit, 0)), worldMatrix, this._transformationMatrix, globalViewport);
  188. var yAxisText = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(0, unit * 1.5, 0)), worldMatrix, this._transformationMatrix, globalViewport);
  189. this._renderSingleAxis(projectedPosition, yAxis, yAxisText, "y", "#00FF00");
  190. var zAxis = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(0, 0, unit)), worldMatrix, this._transformationMatrix, globalViewport);
  191. var zAxisText = BABYLON.Vector3.Project(position.add(new BABYLON.Vector3(0, 0, unit * 1.5)), worldMatrix, this._transformationMatrix, globalViewport);
  192. this._renderSingleAxis(projectedPosition, zAxis, zAxisText, "z", "#0000FF");
  193. };
  194. DebugLayer.prototype._renderLabel = function (text, projectedPosition, labelOffset, onClick, getFillStyle) {
  195. if (projectedPosition.z > 0 && projectedPosition.z < 1.0) {
  196. this._drawingContext.font = "normal 12px Segoe UI";
  197. var textMetrics = this._drawingContext.measureText(text);
  198. var centerX = projectedPosition.x - textMetrics.width / 2;
  199. var centerY = projectedPosition.y;
  200. var clientRect = this._drawingCanvas.getBoundingClientRect();
  201. if (this._showUI && this._isClickInsideRect(clientRect.left * this._ratio + centerX - 5, clientRect.top * this._ratio + centerY - labelOffset - 12, textMetrics.width + 10, 17)) {
  202. onClick();
  203. }
  204. this._drawingContext.beginPath();
  205. this._drawingContext.rect(centerX - 5, centerY - labelOffset - 12, textMetrics.width + 10, 17);
  206. this._drawingContext.fillStyle = getFillStyle();
  207. this._drawingContext.globalAlpha = 0.5;
  208. this._drawingContext.fill();
  209. this._drawingContext.globalAlpha = 1.0;
  210. this._drawingContext.strokeStyle = '#FFFFFF';
  211. this._drawingContext.lineWidth = 1;
  212. this._drawingContext.stroke();
  213. this._drawingContext.fillStyle = "#FFFFFF";
  214. this._drawingContext.fillText(text, centerX, centerY - labelOffset);
  215. this._drawingContext.beginPath();
  216. this._drawingContext.arc(projectedPosition.x, centerY, 5, 0, 2 * Math.PI, false);
  217. this._drawingContext.fill();
  218. }
  219. };
  220. DebugLayer.prototype._isClickInsideRect = function (x, y, width, height) {
  221. if (!this._clickPosition) {
  222. return false;
  223. }
  224. if (this._clickPosition.x < x || this._clickPosition.x > x + width) {
  225. return false;
  226. }
  227. if (this._clickPosition.y < y || this._clickPosition.y > y + height) {
  228. return false;
  229. }
  230. return true;
  231. };
  232. DebugLayer.prototype.isVisible = function () {
  233. return this._enabled;
  234. };
  235. DebugLayer.prototype.hide = function () {
  236. if (!this._enabled) {
  237. return;
  238. }
  239. this._enabled = false;
  240. var engine = this._scene.getEngine();
  241. this._scene.unregisterBeforeRender(this._syncData);
  242. this._scene.unregisterAfterRender(this._syncUI);
  243. this._rootElement.removeChild(this._globalDiv);
  244. this._scene.forceShowBoundingBoxes = false;
  245. this._scene.forceWireframe = false;
  246. BABYLON.StandardMaterial.DiffuseTextureEnabled = true;
  247. BABYLON.StandardMaterial.AmbientTextureEnabled = true;
  248. BABYLON.StandardMaterial.SpecularTextureEnabled = true;
  249. BABYLON.StandardMaterial.EmissiveTextureEnabled = true;
  250. BABYLON.StandardMaterial.BumpTextureEnabled = true;
  251. BABYLON.StandardMaterial.OpacityTextureEnabled = true;
  252. BABYLON.StandardMaterial.ReflectionTextureEnabled = true;
  253. BABYLON.StandardMaterial.LightmapTextureEnabled = true;
  254. BABYLON.StandardMaterial.RefractionTextureEnabled = true;
  255. BABYLON.StandardMaterial.ColorGradingTextureEnabled = true;
  256. this._scene.shadowsEnabled = true;
  257. this._scene.particlesEnabled = true;
  258. this._scene.postProcessesEnabled = true;
  259. this._scene.collisionsEnabled = true;
  260. this._scene.lightsEnabled = true;
  261. this._scene.texturesEnabled = true;
  262. this._scene.lensFlaresEnabled = true;
  263. this._scene.proceduralTexturesEnabled = true;
  264. this._scene.renderTargetsEnabled = true;
  265. this._scene.probesEnabled = true;
  266. engine.getRenderingCanvas().removeEventListener("click", this._onCanvasClick);
  267. this._clearSkeletonViewers();
  268. };
  269. DebugLayer.prototype._clearSkeletonViewers = function () {
  270. for (var index = 0; index < this._skeletonViewers.length; index++) {
  271. this._skeletonViewers[index].dispose();
  272. }
  273. this._skeletonViewers = [];
  274. };
  275. DebugLayer.prototype.show = function (showUI, camera, rootElement) {
  276. if (showUI === void 0) { showUI = true; }
  277. if (camera === void 0) { camera = null; }
  278. if (rootElement === void 0) { rootElement = null; }
  279. if (this._enabled) {
  280. return;
  281. }
  282. this._enabled = true;
  283. if (camera) {
  284. this._camera = camera;
  285. }
  286. else {
  287. this._camera = this._scene.activeCamera;
  288. }
  289. this._showUI = showUI;
  290. var engine = this._scene.getEngine();
  291. this._globalDiv = document.createElement("div");
  292. this._rootElement = rootElement || document.body;
  293. this._rootElement.appendChild(this._globalDiv);
  294. this._generateDOMelements();
  295. engine.getRenderingCanvas().addEventListener("click", this._onCanvasClick);
  296. this._syncPositions();
  297. this._scene.registerBeforeRender(this._syncData);
  298. this._scene.registerAfterRender(this._syncUI);
  299. };
  300. DebugLayer.prototype._clearLabels = function () {
  301. this._drawingContext.clearRect(0, 0, this._drawingCanvas.width, this._drawingCanvas.height);
  302. for (var index = 0; index < this._scene.meshes.length; index++) {
  303. var mesh = this._scene.meshes[index];
  304. mesh.renderOverlay = false;
  305. }
  306. };
  307. DebugLayer.prototype._generateheader = function (root, text) {
  308. var header = document.createElement("div");
  309. header.innerHTML = text + "&nbsp;";
  310. header.style.textAlign = "right";
  311. header.style.width = "100%";
  312. header.style.color = "white";
  313. header.style.backgroundColor = "Black";
  314. header.style.padding = "5px 5px 4px 0px";
  315. header.style.marginLeft = "-5px";
  316. header.style.fontWeight = "bold";
  317. root.appendChild(header);
  318. };
  319. DebugLayer.prototype._generateTexBox = function (root, title, color) {
  320. var label = document.createElement("label");
  321. label.style.display = "inline";
  322. label.innerHTML = title;
  323. label.style.color = color;
  324. root.appendChild(label);
  325. root.appendChild(document.createElement("br"));
  326. };
  327. DebugLayer.prototype._generateAdvancedCheckBox = function (root, leftTitle, rightTitle, initialState, task, tag) {
  328. if (tag === void 0) { tag = null; }
  329. var label = document.createElement("label");
  330. label.style.display = "inline";
  331. var boundingBoxesCheckbox = document.createElement("input");
  332. boundingBoxesCheckbox.type = "checkbox";
  333. boundingBoxesCheckbox.checked = initialState;
  334. boundingBoxesCheckbox.style.display = "inline";
  335. boundingBoxesCheckbox.style.margin = "0px 5px 0px 0px";
  336. boundingBoxesCheckbox.style.verticalAlign = "sub";
  337. boundingBoxesCheckbox.addEventListener("change", function (evt) {
  338. task(evt.target, tag);
  339. });
  340. label.appendChild(boundingBoxesCheckbox);
  341. var container = document.createElement("span");
  342. var leftPart = document.createElement("span");
  343. var rightPart = document.createElement("span");
  344. rightPart.style.cssFloat = "right";
  345. leftPart.innerHTML = leftTitle;
  346. rightPart.innerHTML = rightTitle;
  347. rightPart.style.fontSize = "12px";
  348. rightPart.style.maxWidth = "200px";
  349. container.appendChild(leftPart);
  350. container.appendChild(rightPart);
  351. label.appendChild(container);
  352. root.appendChild(label);
  353. root.appendChild(document.createElement("br"));
  354. };
  355. DebugLayer.prototype._generateCheckBox = function (root, title, initialState, task, tag) {
  356. if (tag === void 0) { tag = null; }
  357. var label = document.createElement("label");
  358. label.style.display = "inline";
  359. var checkBox = document.createElement("input");
  360. checkBox.type = "checkbox";
  361. checkBox.checked = initialState;
  362. checkBox.style.display = "inline";
  363. checkBox.style.margin = "0px 5px 0px 0px";
  364. checkBox.style.verticalAlign = "sub";
  365. checkBox.addEventListener("change", function (evt) {
  366. task(evt.target, tag);
  367. });
  368. label.appendChild(checkBox);
  369. label.appendChild(document.createTextNode(title));
  370. root.appendChild(label);
  371. root.appendChild(document.createElement("br"));
  372. };
  373. DebugLayer.prototype._generateButton = function (root, title, task, tag) {
  374. if (tag === void 0) { tag = null; }
  375. var button = document.createElement("button");
  376. button.innerHTML = title;
  377. button.style.height = "24px";
  378. button.style.width = "150px";
  379. button.style.marginBottom = "5px";
  380. button.style.color = "#444444";
  381. button.style.border = "1px solid white";
  382. button.className = "debugLayerButton";
  383. button.addEventListener("click", function (evt) {
  384. task(evt.target, tag);
  385. });
  386. root.appendChild(button);
  387. root.appendChild(document.createElement("br"));
  388. };
  389. DebugLayer.prototype._generateRadio = function (root, title, name, initialState, task, tag) {
  390. if (tag === void 0) { tag = null; }
  391. var label = document.createElement("label");
  392. label.style.display = "inline";
  393. var boundingBoxesRadio = document.createElement("input");
  394. boundingBoxesRadio.type = "radio";
  395. boundingBoxesRadio.name = name;
  396. boundingBoxesRadio.checked = initialState;
  397. boundingBoxesRadio.style.display = "inline";
  398. boundingBoxesRadio.style.margin = "0px 5px 0px 0px";
  399. boundingBoxesRadio.style.verticalAlign = "sub";
  400. boundingBoxesRadio.addEventListener("change", function (evt) {
  401. task(evt.target, tag);
  402. });
  403. label.appendChild(boundingBoxesRadio);
  404. label.appendChild(document.createTextNode(title));
  405. root.appendChild(label);
  406. root.appendChild(document.createElement("br"));
  407. };
  408. DebugLayer.prototype._generateDOMelements = function () {
  409. var _this = this;
  410. this._globalDiv.id = "DebugLayer";
  411. this._globalDiv.style.position = "absolute";
  412. this._globalDiv.style.fontFamily = "Segoe UI, Arial";
  413. this._globalDiv.style.fontSize = "14px";
  414. this._globalDiv.style.color = "white";
  415. // Drawing canvas
  416. this._drawingCanvas = document.createElement("canvas");
  417. this._drawingCanvas.id = "DebugLayerDrawingCanvas";
  418. this._drawingCanvas.style.position = "absolute";
  419. this._drawingCanvas.style.pointerEvents = "none";
  420. this._drawingCanvas.style.backgroundColor = "transparent";
  421. this._drawingContext = this._drawingCanvas.getContext("2d");
  422. this._globalDiv.appendChild(this._drawingCanvas);
  423. if (this._showUI) {
  424. var background = "rgba(128, 128, 128, 0.4)";
  425. var border = "rgb(180, 180, 180) solid 1px";
  426. // Stats
  427. this._statsDiv = document.createElement("div");
  428. this._statsDiv.id = "DebugLayerStats";
  429. this._statsDiv.style.border = border;
  430. this._statsDiv.style.position = "absolute";
  431. this._statsDiv.style.background = background;
  432. this._statsDiv.style.padding = "0px 0px 0px 5px";
  433. this._generateheader(this._statsDiv, "STATISTICS");
  434. this._statsSubsetDiv = document.createElement("div");
  435. this._statsSubsetDiv.style.paddingTop = "5px";
  436. this._statsSubsetDiv.style.paddingBottom = "5px";
  437. this._statsSubsetDiv.style.overflowY = "auto";
  438. this._statsDiv.appendChild(this._statsSubsetDiv);
  439. // Tree
  440. this._treeDiv = document.createElement("div");
  441. this._treeDiv.id = "DebugLayerTree";
  442. this._treeDiv.style.border = border;
  443. this._treeDiv.style.position = "absolute";
  444. this._treeDiv.style.background = background;
  445. this._treeDiv.style.padding = "0px 0px 0px 5px";
  446. this._treeDiv.style.display = "none";
  447. this._generateheader(this._treeDiv, "MESHES TREE");
  448. this._treeSubsetDiv = document.createElement("div");
  449. this._treeSubsetDiv.style.paddingTop = "5px";
  450. this._treeSubsetDiv.style.paddingRight = "5px";
  451. this._treeSubsetDiv.style.overflowY = "auto";
  452. this._treeSubsetDiv.style.maxHeight = "300px";
  453. this._treeDiv.appendChild(this._treeSubsetDiv);
  454. this._needToRefreshMeshesTree = true;
  455. // Logs
  456. this._logDiv = document.createElement("div");
  457. this._logDiv.style.border = border;
  458. this._logDiv.id = "DebugLayerLogs";
  459. this._logDiv.style.position = "absolute";
  460. this._logDiv.style.background = background;
  461. this._logDiv.style.padding = "0px 0px 0px 5px";
  462. this._logDiv.style.display = "none";
  463. this._generateheader(this._logDiv, "LOGS");
  464. this._logSubsetDiv = document.createElement("div");
  465. this._logSubsetDiv.style.height = "127px";
  466. this._logSubsetDiv.style.paddingTop = "5px";
  467. this._logSubsetDiv.style.overflowY = "auto";
  468. this._logSubsetDiv.style.fontSize = "12px";
  469. this._logSubsetDiv.style.fontFamily = "consolas";
  470. this._logSubsetDiv.innerHTML = BABYLON.Tools.LogCache;
  471. this._logDiv.appendChild(this._logSubsetDiv);
  472. BABYLON.Tools.OnNewCacheEntry = function (entry) {
  473. _this._logSubsetDiv.innerHTML = entry + _this._logSubsetDiv.innerHTML;
  474. };
  475. // Options
  476. this._optionsDiv = document.createElement("div");
  477. this._optionsDiv.id = "DebugLayerOptions";
  478. this._optionsDiv.style.border = border;
  479. this._optionsDiv.style.position = "absolute";
  480. this._optionsDiv.style.background = background;
  481. this._optionsDiv.style.padding = "0px 0px 0px 5px";
  482. this._optionsDiv.style.overflowY = "auto";
  483. this._generateheader(this._optionsDiv, "OPTIONS");
  484. this._optionsSubsetDiv = document.createElement("div");
  485. this._optionsSubsetDiv.style.paddingTop = "5px";
  486. this._optionsSubsetDiv.style.paddingBottom = "5px";
  487. this._optionsSubsetDiv.style.overflowY = "auto";
  488. this._optionsSubsetDiv.style.maxHeight = "200px";
  489. this._optionsDiv.appendChild(this._optionsSubsetDiv);
  490. this._generateTexBox(this._optionsSubsetDiv, "<b>Windows:</b>", this.accentColor);
  491. this._generateCheckBox(this._optionsSubsetDiv, "Statistics", this._displayStatistics, function (element) { _this._displayStatistics = element.checked; });
  492. this._generateCheckBox(this._optionsSubsetDiv, "Logs", this._displayLogs, function (element) { _this._displayLogs = element.checked; });
  493. this._generateCheckBox(this._optionsSubsetDiv, "Meshes tree", this._displayTree, function (element) {
  494. _this._displayTree = element.checked;
  495. _this._needToRefreshMeshesTree = true;
  496. });
  497. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  498. this._generateTexBox(this._optionsSubsetDiv, "<b>General:</b>", this.accentColor);
  499. this._generateCheckBox(this._optionsSubsetDiv, "Bounding boxes", this._scene.forceShowBoundingBoxes, function (element) { _this._scene.forceShowBoundingBoxes = element.checked; });
  500. this._generateCheckBox(this._optionsSubsetDiv, "Clickable labels", this._labelsEnabled, function (element) {
  501. _this._labelsEnabled = element.checked;
  502. if (!_this._labelsEnabled) {
  503. _this._clearLabels();
  504. }
  505. });
  506. this._generateCheckBox(this._optionsSubsetDiv, "Generate user marks (F12)", BABYLON.Tools.PerformanceLogLevel === BABYLON.Tools.PerformanceUserMarkLogLevel, function (element) {
  507. if (element.checked) {
  508. BABYLON.Tools.PerformanceLogLevel = BABYLON.Tools.PerformanceUserMarkLogLevel;
  509. }
  510. else {
  511. BABYLON.Tools.PerformanceLogLevel = BABYLON.Tools.PerformanceNoneLogLevel;
  512. }
  513. });
  514. ;
  515. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  516. this._generateTexBox(this._optionsSubsetDiv, "<b>Rendering mode:</b>", this.accentColor);
  517. this._generateRadio(this._optionsSubsetDiv, "Solid", "renderMode", !this._scene.forceWireframe && !this._scene.forcePointsCloud, function (element) {
  518. if (element.checked) {
  519. _this._scene.forceWireframe = false;
  520. _this._scene.forcePointsCloud = false;
  521. }
  522. });
  523. this._generateRadio(this._optionsSubsetDiv, "Wireframe", "renderMode", this._scene.forceWireframe, function (element) {
  524. if (element.checked) {
  525. _this._scene.forceWireframe = true;
  526. _this._scene.forcePointsCloud = false;
  527. }
  528. });
  529. this._generateRadio(this._optionsSubsetDiv, "Point", "renderMode", this._scene.forcePointsCloud, function (element) {
  530. if (element.checked) {
  531. _this._scene.forceWireframe = false;
  532. _this._scene.forcePointsCloud = true;
  533. }
  534. });
  535. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  536. this._generateTexBox(this._optionsSubsetDiv, "<b>Texture channels:</b>", this.accentColor);
  537. this._generateCheckBox(this._optionsSubsetDiv, "Diffuse", BABYLON.StandardMaterial.DiffuseTextureEnabled, function (element) { BABYLON.StandardMaterial.DiffuseTextureEnabled = element.checked; });
  538. this._generateCheckBox(this._optionsSubsetDiv, "Ambient", BABYLON.StandardMaterial.AmbientTextureEnabled, function (element) { BABYLON.StandardMaterial.AmbientTextureEnabled = element.checked; });
  539. this._generateCheckBox(this._optionsSubsetDiv, "Specular", BABYLON.StandardMaterial.SpecularTextureEnabled, function (element) { BABYLON.StandardMaterial.SpecularTextureEnabled = element.checked; });
  540. this._generateCheckBox(this._optionsSubsetDiv, "Emissive", BABYLON.StandardMaterial.EmissiveTextureEnabled, function (element) { BABYLON.StandardMaterial.EmissiveTextureEnabled = element.checked; });
  541. this._generateCheckBox(this._optionsSubsetDiv, "Bump", BABYLON.StandardMaterial.BumpTextureEnabled, function (element) { BABYLON.StandardMaterial.BumpTextureEnabled = element.checked; });
  542. this._generateCheckBox(this._optionsSubsetDiv, "Opacity", BABYLON.StandardMaterial.OpacityTextureEnabled, function (element) { BABYLON.StandardMaterial.OpacityTextureEnabled = element.checked; });
  543. this._generateCheckBox(this._optionsSubsetDiv, "Reflection", BABYLON.StandardMaterial.ReflectionTextureEnabled, function (element) { BABYLON.StandardMaterial.ReflectionTextureEnabled = element.checked; });
  544. this._generateCheckBox(this._optionsSubsetDiv, "Refraction", BABYLON.StandardMaterial.RefractionTextureEnabled, function (element) { BABYLON.StandardMaterial.RefractionTextureEnabled = element.checked; });
  545. this._generateCheckBox(this._optionsSubsetDiv, "ColorGrading", BABYLON.StandardMaterial.ColorGradingTextureEnabled, function (element) { BABYLON.StandardMaterial.ColorGradingTextureEnabled = element.checked; });
  546. this._generateCheckBox(this._optionsSubsetDiv, "Lightmap", BABYLON.StandardMaterial.LightmapTextureEnabled, function (element) { BABYLON.StandardMaterial.LightmapTextureEnabled = element.checked; });
  547. this._generateCheckBox(this._optionsSubsetDiv, "Fresnel", BABYLON.StandardMaterial.FresnelEnabled, function (element) { BABYLON.StandardMaterial.FresnelEnabled = element.checked; });
  548. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  549. this._generateTexBox(this._optionsSubsetDiv, "<b>Options:</b>", this.accentColor);
  550. this._generateCheckBox(this._optionsSubsetDiv, "Animations", this._scene.animationsEnabled, function (element) { _this._scene.animationsEnabled = element.checked; });
  551. this._generateCheckBox(this._optionsSubsetDiv, "Collisions", this._scene.collisionsEnabled, function (element) { _this._scene.collisionsEnabled = element.checked; });
  552. this._generateCheckBox(this._optionsSubsetDiv, "Fog", this._scene.fogEnabled, function (element) { _this._scene.fogEnabled = element.checked; });
  553. this._generateCheckBox(this._optionsSubsetDiv, "Lens flares", this._scene.lensFlaresEnabled, function (element) { _this._scene.lensFlaresEnabled = element.checked; });
  554. this._generateCheckBox(this._optionsSubsetDiv, "Lights", this._scene.lightsEnabled, function (element) { _this._scene.lightsEnabled = element.checked; });
  555. this._generateCheckBox(this._optionsSubsetDiv, "Particles", this._scene.particlesEnabled, function (element) { _this._scene.particlesEnabled = element.checked; });
  556. this._generateCheckBox(this._optionsSubsetDiv, "Post-processes", this._scene.postProcessesEnabled, function (element) { _this._scene.postProcessesEnabled = element.checked; });
  557. this._generateCheckBox(this._optionsSubsetDiv, "Probes", this._scene.probesEnabled, function (element) { _this._scene.probesEnabled = element.checked; });
  558. this._generateCheckBox(this._optionsSubsetDiv, "Procedural textures", this._scene.proceduralTexturesEnabled, function (element) { _this._scene.proceduralTexturesEnabled = element.checked; });
  559. this._generateCheckBox(this._optionsSubsetDiv, "Render targets", this._scene.renderTargetsEnabled, function (element) { _this._scene.renderTargetsEnabled = element.checked; });
  560. this._generateCheckBox(this._optionsSubsetDiv, "Shadows", this._scene.shadowsEnabled, function (element) { _this._scene.shadowsEnabled = element.checked; });
  561. this._generateCheckBox(this._optionsSubsetDiv, "Skeletons", this._scene.skeletonsEnabled, function (element) { _this._scene.skeletonsEnabled = element.checked; });
  562. this._generateCheckBox(this._optionsSubsetDiv, "Sprites", this._scene.spritesEnabled, function (element) { _this._scene.spritesEnabled = element.checked; });
  563. this._generateCheckBox(this._optionsSubsetDiv, "Textures", this._scene.texturesEnabled, function (element) { _this._scene.texturesEnabled = element.checked; });
  564. if (BABYLON.AudioEngine && BABYLON.Engine.audioEngine.canUseWebAudio) {
  565. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  566. this._generateTexBox(this._optionsSubsetDiv, "<b>Audio:</b>", this.accentColor);
  567. this._generateRadio(this._optionsSubsetDiv, "Headphones", "panningModel", this._scene.headphone, function (element) {
  568. if (element.checked) {
  569. _this._scene.headphone = true;
  570. }
  571. });
  572. this._generateRadio(this._optionsSubsetDiv, "Normal Speakers", "panningModel", !this._scene.headphone, function (element) {
  573. if (element.checked) {
  574. _this._scene.headphone = false;
  575. }
  576. });
  577. this._generateCheckBox(this._optionsSubsetDiv, "Disable audio", !this._scene.audioEnabled, function (element) {
  578. _this._scene.audioEnabled = !element.checked;
  579. });
  580. }
  581. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  582. this._generateTexBox(this._optionsSubsetDiv, "<b>Viewers:</b>", this.accentColor);
  583. this._generateCheckBox(this._optionsSubsetDiv, "Skeletons", false, function (element) {
  584. if (!element.checked) {
  585. _this._clearSkeletonViewers();
  586. return;
  587. }
  588. for (var index = 0; index < _this._scene.meshes.length; index++) {
  589. var mesh = _this._scene.meshes[index];
  590. if (mesh.skeleton) {
  591. var found = false;
  592. for (var sIndex = 0; sIndex < _this._skeletonViewers.length; sIndex++) {
  593. if (_this._skeletonViewers[sIndex].skeleton === mesh.skeleton) {
  594. found = true;
  595. break;
  596. }
  597. }
  598. if (found) {
  599. continue;
  600. }
  601. var viewer = new BABYLON.Debug.SkeletonViewer(mesh.skeleton, mesh, _this._scene);
  602. viewer.isEnabled = true;
  603. _this._skeletonViewers.push(viewer);
  604. }
  605. }
  606. });
  607. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  608. this._generateTexBox(this._optionsSubsetDiv, "<b>Tools:</b>", this.accentColor);
  609. this._generateButton(this._optionsSubsetDiv, "Dump rendertargets", function (element) { _this._scene.dumpNextRenderTargets = true; });
  610. this._generateButton(this._optionsSubsetDiv, "Run SceneOptimizer", function (element) { BABYLON.SceneOptimizer.OptimizeAsync(_this._scene); });
  611. this._generateButton(this._optionsSubsetDiv, "Log camera object", function (element) {
  612. if (_this._camera) {
  613. console.log(_this._camera);
  614. }
  615. else {
  616. console.warn("No camera defined, or debug layer created before camera creation!");
  617. }
  618. });
  619. this._optionsSubsetDiv.appendChild(document.createElement("br"));
  620. this._globalDiv.appendChild(this._statsDiv);
  621. this._globalDiv.appendChild(this._logDiv);
  622. this._globalDiv.appendChild(this._optionsDiv);
  623. this._globalDiv.appendChild(this._treeDiv);
  624. }
  625. };
  626. DebugLayer.prototype._displayStats = function () {
  627. var scene = this._scene;
  628. var engine = scene.getEngine();
  629. var glInfo = engine.getGlInfo();
  630. this._statsSubsetDiv.innerHTML = "Babylon.js v" + BABYLON.Engine.Version + " - <b>" + BABYLON.Tools.Format(engine.getFps(), 0) + " fps</b><br><br>"
  631. + "<div style='column-count: 2;-moz-column-count:2;-webkit-column-count:2'>"
  632. + "<b>Count</b><br>"
  633. + "Total meshes: " + scene.meshes.length + "<br>"
  634. + "Total lights: " + scene.lights.length + "<br>"
  635. + "Total vertices: " + scene.getTotalVertices() + "<br>"
  636. + "Total materials: " + scene.materials.length + "<br>"
  637. + "Total textures: " + scene.textures.length + "<br>"
  638. + "Active meshes: " + scene.getActiveMeshes().length + "<br>"
  639. + "Active indices: " + scene.getActiveIndices() + "<br>"
  640. + "Active bones: " + scene.getActiveBones() + "<br>"
  641. + "Active particles: " + scene.getActiveParticles() + "<br>"
  642. + "<b>Draw calls: " + engine.drawCalls + "</b><br><br>"
  643. + "<b>Duration</b><br>"
  644. + "Meshes selection:</i> " + BABYLON.Tools.Format(scene.getEvaluateActiveMeshesDuration()) + " ms<br>"
  645. + "Render Targets: " + BABYLON.Tools.Format(scene.getRenderTargetsDuration()) + " ms<br>"
  646. + "Particles: " + BABYLON.Tools.Format(scene.getParticlesDuration()) + " ms<br>"
  647. + "Sprites: " + BABYLON.Tools.Format(scene.getSpritesDuration()) + " ms<br><br>"
  648. + "Render: <b>" + BABYLON.Tools.Format(scene.getRenderDuration()) + " ms</b><br>"
  649. + "Frame: " + BABYLON.Tools.Format(scene.getLastFrameDuration()) + " ms<br>"
  650. + "Potential FPS: " + BABYLON.Tools.Format(1000.0 / scene.getLastFrameDuration(), 0) + "<br>"
  651. + "Resolution: " + engine.getRenderWidth() + "x" + engine.getRenderHeight() + "<br><br>"
  652. + "</div>"
  653. + "<div style='column-count: 2;-moz-column-count:2;-webkit-column-count:2'>"
  654. + "<b>Extensions</b><br>"
  655. + "Std derivatives: " + (engine.getCaps().standardDerivatives ? "Yes" : "No") + "<br>"
  656. + "Compressed textures: " + (engine.getCaps().s3tc ? "Yes" : "No") + "<br>"
  657. + "Hardware instances: " + (engine.getCaps().instancedArrays ? "Yes" : "No") + "<br>"
  658. + "Texture float: " + (engine.getCaps().textureFloat ? "Yes" : "No") + "<br><br>"
  659. + "32bits indices: " + (engine.getCaps().uintIndices ? "Yes" : "No") + "<br>"
  660. + "Fragment depth: " + (engine.getCaps().fragmentDepthSupported ? "Yes" : "No") + "<br>"
  661. + "High precision shaders: " + (engine.getCaps().highPrecisionShaderSupported ? "Yes" : "No") + "<br>"
  662. + "Draw buffers: " + (engine.getCaps().drawBuffersExtension ? "Yes" : "No") + "<br>"
  663. + "</div><br>"
  664. + "<div style='column-count: 2;-moz-column-count:2;-webkit-column-count:2'>"
  665. + "<b>Caps.</b><br>"
  666. + "Max textures units: " + engine.getCaps().maxTexturesImageUnits + "<br>"
  667. + "Max textures size: " + engine.getCaps().maxTextureSize + "<br>"
  668. + "Max anisotropy: " + engine.getCaps().maxAnisotropy + "<br>"
  669. + "<b>Info</b><br>"
  670. + "WebGL feature level: " + engine.webGLVersion + "<br>"
  671. + glInfo.version + "<br>"
  672. + "</div><br>"
  673. + glInfo.renderer + "<br>";
  674. if (this.customStatsFunction) {
  675. this._statsSubsetDiv.innerHTML += this.customStatsFunction();
  676. }
  677. };
  678. return DebugLayer;
  679. }());
  680. BABYLON.DebugLayer = DebugLayer;
  681. })(BABYLON || (BABYLON = {}));