Home Reference Source

cables_dev/cables_ui/src/ui/components/canvas/canvasui.js

  1. import { ele } from "cables-shared-client";
  2. import { gui } from "../../gui.js";
  3. import { UserSettings, userSettings } from "../usersettings.js";
  4. /**
  5. * the icon bar below the renderer canvas
  6. */
  7. export default class CanvasUi
  8. {
  9. #cg;
  10. #canvasEle;
  11. /**
  12. * @param {import("cables-corelibs").CgContext} [_cg]
  13. * @param {HTMLCanvasElement} [_canvEle]
  14. */
  15. constructor(_cg = null, _canvEle)
  16. {
  17. this.#cg = _cg;
  18. this.#canvasEle = _canvEle || _cg?.canvas;
  19. this.isCanvasFocussed = false;
  20. this.minimized = false;
  21. this._elCanvasIconbarContainer = this._elCanvasIconbarContainer || ele.byId("canvasicons");
  22. this._elCanvasIconbar = this._elCanvasIconbar || ele.byId("canvasIconBar");
  23. this._elcanvasCtxSwitcher = this._elcanvasCtxSwitcher || ele.byId("canvasCtxSwitcher");
  24. this._elCanvasInfoSize = this._elCanvasInfoSize || ele.byId("canvasInfoSize");
  25. this._elSplitterRightPanel = this._elSplitterRightPanel || ele.byId("splitterRightPanel");
  26. this._elCanvasInfoFps = this._elCanvasInfoFps || document.getElementById("canvasInfoFPS");
  27. this._elCtxSwitcher = this._elCtxSwitcher || document.getElementById("canvasCtxSwitcher");
  28. this._elCanvasInfoMs = this._elCanvasInfoMs || document.getElementById("canvasInfoMS");
  29. this._elInfoVersion = ele.byId("canvasInfoVersion");
  30. this._elCanvasInfoSizeOverlay = ele.byId("canvasInfoOverlay");
  31. this._elCanvasIconbarContainer.addEventListener("click", () =>
  32. {
  33. this.#canvasEle.focus();
  34. });
  35. this._elCanvasInfoSize.addEventListener("pointerenter", () =>
  36. {
  37. this._elCanvasInfoSizeOverlay.style.top = this._elCanvasInfoSize.getBoundingClientRect().y + 30 + "px";
  38. this._elCanvasInfoSizeOverlay.style.left = this._elCanvasInfoSize.getBoundingClientRect().x + "px";
  39. // this._elCanvasInfoSizeOverlay.innerHTML = "";
  40. this._elCanvasInfoSizeOverlay.classList.remove("hidden");
  41. });
  42. this._elCanvasInfoSize.addEventListener("pointerleave", () =>
  43. {
  44. this._elCanvasInfoSizeOverlay.classList.add("hidden");
  45. });
  46. if (this._elInfoVersion)
  47. {
  48. if (this.#cg && this.#cg.glVersion == 1)
  49. {
  50. this._elCanvasInfoVer = this._elCanvasInfoVer || document.getElementById("canvasInfoVersion");
  51. this._elCanvasInfoVer.innerHTML = "WebGL 1";
  52. }
  53. else this._elInfoVersion.remove();
  54. }
  55. if (this.#cg)
  56. {
  57. if (this.#cg && this.#cg.on)
  58. this.#cg.on("resize", () =>
  59. {
  60. this.updateSizeDisplay();
  61. });
  62. if (this.#cg)
  63. this.#cg.fpsCounter?.on("performance", (perf) =>
  64. {
  65. const p = gui.uiProfiler.start("[canvasUi] on performance");
  66. // if (this.isCanvasFocussed)
  67. // {
  68. if (this._oldFps != perf.fps) this._elCanvasInfoFps.innerHTML = perf.fps + " FPS";
  69. this._oldFps = perf.fps;
  70. if (this.#cg.profileData)
  71. {
  72. let ms = ((Math.round(this.#cg.profileData.profileOnAnimFrameOps * 100) / 100) || "0.0") + "ms";
  73. if (window.gui && gui.patchView.patchRenderer.vizLayer && gui.patchView.patchRenderer.vizLayer.renderMs > 3)
  74. {
  75. ms += " vizLayer: " + Math.round(gui.patchView.patchRenderer.vizLayer.renderMs) + "ms";
  76. }
  77. if (this._oldMs != ms) this._elCanvasInfoMs.innerHTML = ms;
  78. this._oldMs = ms;
  79. }
  80. // }
  81. p.finish();
  82. });
  83. }
  84. else
  85. {
  86. setInterval(() =>
  87. {
  88. const canvas = this.#canvasEle;
  89. if (canvas.dataset.perfms) this._elCanvasInfoMs.innerHTML = canvas.dataset.perfms + " ms";
  90. if (canvas.dataset.perfms) this._elCanvasInfoFps.innerHTML = canvas.dataset.perffps + " fps";
  91. }, 1000);
  92. }
  93. this.#canvasEle.setAttribute("tabindex", 0);
  94. this.#canvasEle.addEventListener("focus", () =>
  95. {
  96. const p = gui.uiProfiler.start("[canvasUi] on focus");
  97. this.showCanvasModal(true);
  98. gui.canvasManager.setCurrentCanvas(this.#canvasEle);
  99. p.finish();
  100. });
  101. document.body.addEventListener("pointerdown",
  102. (e) =>
  103. {
  104. if (this.isCanvasFocussed &&
  105. !e.target.classList.contains("item") &&
  106. !e.target.classList.contains("icon") &&
  107. e.target != this.#canvasEle
  108. ) this.showCanvasModal(false);
  109. },
  110. true);
  111. }
  112. updateCanvasIconBar()
  113. {
  114. if (!this._elCanvasIconbarContainer) return;
  115. const perf = gui.uiProfiler.start("[canvasUi] updateCanvasIconBar");
  116. const splitterPatchRect = this._elSplitterRightPanel.getBoundingClientRect();
  117. const bodyRect = document.body.getBoundingClientRect();
  118. perf.finish();
  119. }
  120. updateSizeDisplay()
  121. {
  122. if (!gui.corePatch().cgl) return;
  123. const canvas = this.#canvasEle;
  124. const ctx = gui.canvasManager.currentContextCg();
  125. this._elCanvasInfoAspect = this._elCanvasInfoAspect || document.getElementById("canvasInfoAspect");
  126. let sizeStr = canvas.width + "x" + canvas.height;
  127. if (ctx && ctx.pixelDensity != 1) sizeStr += " (" + Math.round(ctx.pixelDensity * 100) / 100 + "x)";
  128. gui.canvasManager.updateCanvasUi();
  129. if (this._oldSizeStr != sizeStr) this._elCanvasInfoSize.innerHTML = sizeStr;
  130. this._oldSizeStr = sizeStr;
  131. this.updateIconState();
  132. let str = "<table>";
  133. if (ctx) str += "<tr><td>Canvas API</td><td>" + ctx.getGApiName() + "</td></tr>";
  134. str += "<tr><td>Canvas id</td><td>" + canvas.id + "</td></tr>";
  135. str += "<tr><td>Canvas CSS Size:</td><td><code>" + canvas.clientWidth + "&nbsp;x&nbsp;" + canvas.clientHeight + "</td></tr>";
  136. str += "<tr><td>Canvas Pixel Size:</td><td><code>" + canvas.width + " x " + canvas.height + "</td></tr>";
  137. str += "<tr><td>Device Pixel Ratio/Density:</td><td><code>" + window.devicePixelRatio + "</td></tr>";
  138. if (ctx) str += "<tr><td>Canvas Pixel Ratio/Density:</td><td><code>" + ctx.pixelDensity + "</td></tr>";
  139. str += "</table>";
  140. this._elCanvasInfoSizeOverlay.innerHTML = str;
  141. return sizeStr;
  142. }
  143. updateIconState()
  144. {
  145. const act = userSettings.get(UserSettings.PREF_OVERLAYS_SHOW);
  146. const icon = ele.byId("canvUitoggleOverlay");
  147. if (icon)
  148. if (act)icon.classList.add("icon-highlight");
  149. else icon.classList.remove("icon-highlight");
  150. }
  151. /**
  152. * @param {boolean} show
  153. */
  154. showCanvasModal(show)
  155. {
  156. if (userSettings.get(UserSettings.PREF_HIDE_CANVAS_UI)) return;
  157. const perf = gui.uiProfiler.start("[canvasUi] showCanvasModal");
  158. this._elCanvasModalDarkener = this._elCanvasModalDarkener || document.getElementById("canvasmodal");
  159. this.updateSizeDisplay();
  160. this.updateCanvasIconBar();
  161. this.isCanvasFocussed = show;
  162. if (this.isCanvasFocussed) this._elCanvasIconbar.classList.add("focussed");
  163. else this._elCanvasIconbar.classList.remove("focussed");
  164. if (show)
  165. {
  166. if (gui.canvasManager.mode == gui.canvasManager.CANVASMODE_PATCHBG)
  167. {
  168. ele.hide(this._elCanvasModalDarkener);
  169. }
  170. else
  171. {
  172. if (!this._showing) ele.show(this._elCanvasModalDarkener);
  173. }
  174. }
  175. else
  176. {
  177. setTimeout(() =>
  178. {
  179. // ele.hide(this._elCanvasIconbarContainer);
  180. ele.hide(this._elCanvasModalDarkener);
  181. }, 100);
  182. }
  183. this._showing = show;
  184. perf.finish();
  185. }
  186. }