@plasius/gpu-shared 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plasius/gpu-shared",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Shared browser-safe demo runtime and asset helpers for the Plasius gpu-* package family.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -0,0 +1,10 @@
1
+ const INLINE_BRIGANTINE_GLTF_URL =
2
+ "data:application/json;base64,ewogICJhc3NldCI6IHsKICAgICJ2ZXJzaW9uIjogIjIuMCIsCiAgICAiZ2VuZXJhdG9yIjogIlBsYXNpdXMgZGVtbyBhc3NldCBnZW5lcmF0b3IiCiAgfSwKICAic2NlbmUiOiAwLAogICJzY2VuZXMiOiBbCiAgICB7CiAgICAgICJub2RlcyI6IFswXQogICAgfQogIF0sCiAgIm5vZGVzIjogWwogICAgewogICAgICAibWVzaCI6IDAsCiAgICAgICJuYW1lIjogImJyaWdhbnRpbmUiLAogICAgICAiZXh0cmFzIjogewogICAgICAgICJwaHlzaWNzIjogewogICAgICAgICAgInNoYXBlIjogImJveCIsCiAgICAgICAgICAiaGFsZkV4dGVudHMiOiBbMS4zNSwgMC45NSwgMy45XSwKICAgICAgICAgICJtYXNzIjogMzIwMCwKICAgICAgICAgICJyZXN0aXR1dGlvbiI6IDAuMjIsCiAgICAgICAgICAibGluZWFyRGFtcGluZyI6IDAuMDQsCiAgICAgICAgICAiYW5ndWxhckRhbXBpbmciOiAwLjA4LAogICAgICAgICAgIndhdGVybGluZSI6IDAuNDIKICAgICAgICB9CiAgICAgIH0KICAgIH0KICBdLAogICJtZXNoZXMiOiBbCiAgICB7CiAgICAgICJuYW1lIjogImJyaWdhbnRpbmUtaHVsbCIsCiAgICAgICJwcmltaXRpdmVzIjogWwogICAgICAgIHsKICAgICAgICAgICJhdHRyaWJ1dGVzIjogewogICAgICAgICAgICAiUE9TSVRJT04iOiAwCiAgICAgICAgICB9LAogICAgICAgICAgImluZGljZXMiOiAxLAogICAgICAgICAgIm1hdGVyaWFsIjogMAogICAgICAgIH0KICAgICAgXQogICAgfQogIF0sCiAgIm1hdGVyaWFscyI6IFsKICAgIHsKICAgICAgIm5hbWUiOiAicGFpbnRlZC1odWxsIiwKICAgICAgInBick1ldGFsbGljUm91Z2huZXNzIjogewogICAgICAgICJiYXNlQ29sb3JGYWN0b3IiOiBbMC41NiwgMC4zMywgMC4yMiwgMV0sCiAgICAgICAgIm1ldGFsbGljRmFjdG9yIjogMC4wOCwKICAgICAgICAicm91Z2huZXNzRmFjdG9yIjogMC45MgogICAgICB9CiAgICB9CiAgXSwKICAiYnVmZmVycyI6IFsKICAgIHsKICAgICAgInVyaSI6ICJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsbXBtWnZ3QUFBTC9OekV6QW1wbVpQd0FBQUwvTnpFekF6Y3lzdnpNenM3NHpNN08vemN5c1B6TXpzNzR6TTdPL0FBQ2d2ODNNVEwzTnpNdy9BQUNnUDgzTVRMM056TXcvQUFBQUFPeFJPTDR6TTROQUFBQUFBR1ptNWo0QUFIQkFNek56dnpNenN6NmFtUm5BTXpOelB6TXpzejZhbVJuQXpjeE12ejBLMXo3TnpFdy96Y3hNUHowSzF6N056RXcvQUFBQUFETXpjejltWm1hL0FBQUNBQU1BQUFBREFBRUFBZ0FFQUFVQUFnQUZBQU1BQkFBSEFBVUFCQUFHQUFjQUJRQUhBQVlBQUFBQkFBa0FBQUFKQUFnQUNBQUpBQXdBQWdBSUFBd0FBd0FNQUFrQUFnQU1BQW9BQXdBTEFBd0FBZ0FLQUFRQUF3QUZBQXNBQ2dBTUFBc0FBQUFJQUFJQUFRQURBQWtBQkFBS0FBWUFCUUFHQUFzQUFnQUtBQXNBQWdBTEFBTUEiLAogICAgICAiYnl0ZUxlbmd0aCI6IDI5NAogICAgfQogIF0sCiAgImJ1ZmZlclZpZXdzIjogWwogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiYnl0ZUxlbmd0aCI6IDE1NiwKICAgICAgInRhcmdldCI6IDM0OTYyCiAgICB9LAogICAgewogICAgICAiYnVmZmVyIjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAxNTYsCiAgICAgICJieXRlTGVuZ3RoIjogMTM4LAogICAgICAidGFyZ2V0IjogMzQ5NjMKICAgIH0KICBdLAogICJhY2Nlc3NvcnMiOiBbCiAgICB7CiAgICAgICJidWZmZXJWaWV3IjogMCwKICAgICAgImJ5dGVPZmZzZXQiOiAwLAogICAgICAiY29tcG9uZW50VHlwZSI6IDUxMjYsCiAgICAgICJjb3VudCI6IDEzLAogICAgICAidHlwZSI6ICJWRUMzIiwKICAgICAgIm1pbiI6IFstMS4zNSwgLTAuNSwgLTMuMl0sCiAgICAgICJtYXgiOiBbMS4zNSwgMC45NSwgNC4xXQogICAgfSwKICAgIHsKICAgICAgImJ1ZmZlclZpZXciOiAxLAogICAgICAiYnl0ZU9mZnNldCI6IDAsCiAgICAgICJjb21wb25lbnRUeXBlIjogNTEyMywKICAgICAgImNvdW50IjogNjksCiAgICAgICJ0eXBlIjogIlNDQUxBUiIsCiAgICAgICJtYXgiOiBbMTJdLAogICAgICAibWluIjogWzBdCiAgICB9CiAgXQp9Cg==";
3
+
4
+ export function resolveShowcaseAssetUrl(baseUrl = import.meta.url) {
5
+ try {
6
+ return new URL("../assets/brigantine.gltf", baseUrl);
7
+ } catch {
8
+ return new URL(INLINE_BRIGANTINE_GLTF_URL);
9
+ }
10
+ }
package/src/index.d.ts CHANGED
@@ -40,6 +40,7 @@ export interface MountGpuShowcaseResult {
40
40
  readonly state: Record<string, unknown>;
41
41
  readonly shipModel: GltfModel;
42
42
  readonly canvas: HTMLCanvasElement;
43
+ destroy(): void;
43
44
  }
44
45
 
45
46
  export const showcaseFocusModes: readonly ShowcaseFocusMode[];
package/src/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ export { resolveShowcaseAssetUrl } from "./asset-url.js";
2
+
1
3
  export const showcaseFocusModes = Object.freeze([
2
4
  "integrated",
3
5
  "lighting",
@@ -8,10 +10,6 @@ export const showcaseFocusModes = Object.freeze([
8
10
  "debug",
9
11
  ]);
10
12
 
11
- export function resolveShowcaseAssetUrl(baseUrl = import.meta.url) {
12
- return new URL("../assets/brigantine.gltf", baseUrl);
13
- }
14
-
15
13
  export async function loadGltfModel(url) {
16
14
  const module = await import("./gltf-loader.js");
17
15
  return module.loadGltfModel(url);
@@ -31,6 +31,7 @@ import {
31
31
  getPhysicsWorkerManifest,
32
32
  } from "@plasius/gpu-physics/browser";
33
33
 
34
+ import { resolveShowcaseAssetUrl } from "./asset-url.js";
34
35
  import { loadGltfModel } from "./gltf-loader.js";
35
36
 
36
37
  const STYLE_ID = "plasius-shared-3d-showcase-style";
@@ -76,10 +77,6 @@ const UNIT_BOX_MESH = Object.freeze({
76
77
  ]),
77
78
  });
78
79
 
79
- export function resolveShowcaseAssetUrl(baseUrl = import.meta.url) {
80
- return new URL("../assets/brigantine.gltf", baseUrl);
81
- }
82
-
83
80
  function injectStyles() {
84
81
  if (document.getElementById(STYLE_ID)) {
85
82
  return;
@@ -1794,6 +1791,9 @@ function syncTextState(state, shipModel) {
1794
1791
  export async function mountGpuShowcase(options = {}) {
1795
1792
  injectStyles();
1796
1793
  const root = options.root ?? document.body;
1794
+ const previousMarkup = root.innerHTML;
1795
+ const previousRenderGameToText = window.render_game_to_text;
1796
+ const previousAdvanceTime = window.advanceTime;
1797
1797
  const focus = options.focus ?? new URLSearchParams(window.location.search).get("focus") ?? "integrated";
1798
1798
  const dom = buildDemoDom(root, {
1799
1799
  packageName: options.packageName ?? "@plasius/gpu-demo-viewer",
@@ -1813,7 +1813,14 @@ export async function mountGpuShowcase(options = {}) {
1813
1813
  syncTextState(state, shipModel);
1814
1814
 
1815
1815
  const ctx = dom.canvas.getContext("2d");
1816
+ let destroyed = false;
1817
+ let frameHandle = null;
1818
+
1816
1819
  const renderFrame = (nowMs) => {
1820
+ if (destroyed) {
1821
+ return;
1822
+ }
1823
+
1817
1824
  if (!state.paused) {
1818
1825
  if (state.lastTimeMs == null) {
1819
1826
  state.lastTimeMs = nowMs;
@@ -1831,29 +1838,59 @@ export async function mountGpuShowcase(options = {}) {
1831
1838
  state.demoDescription = resolveSceneDescription(state, options, shipModel).description;
1832
1839
  renderScene(ctx, dom.canvas, state, shipModel, dom);
1833
1840
  syncTextState(state, shipModel);
1834
- requestAnimationFrame(renderFrame);
1841
+ frameHandle = requestAnimationFrame(renderFrame);
1835
1842
  };
1836
1843
 
1837
- dom.pauseButton.addEventListener("click", () => {
1844
+ const handlePauseClick = () => {
1838
1845
  state.paused = !state.paused;
1839
1846
  dom.pauseButton.textContent = state.paused ? "Resume" : "Pause";
1840
- });
1841
- dom.stressToggle.addEventListener("change", () => {
1847
+ };
1848
+ const handleStressChange = () => {
1842
1849
  state.stress = dom.stressToggle.checked;
1843
- });
1844
- dom.focusMode.addEventListener("change", () => {
1850
+ };
1851
+ const handleFocusChange = () => {
1845
1852
  state.focus = dom.focusMode.value;
1846
1853
  Object.assign(state.camera, {
1847
1854
  ...CAMERA_PRESETS[state.focus],
1848
1855
  target: vec3(...CAMERA_PRESETS[state.focus].target),
1849
1856
  });
1850
- });
1857
+ };
1851
1858
 
1852
- requestAnimationFrame(renderFrame);
1859
+ dom.pauseButton.addEventListener("click", handlePauseClick);
1860
+ dom.stressToggle.addEventListener("change", handleStressChange);
1861
+ dom.focusMode.addEventListener("change", handleFocusChange);
1862
+
1863
+ frameHandle = requestAnimationFrame(renderFrame);
1853
1864
  return {
1854
1865
  state,
1855
1866
  shipModel,
1856
1867
  canvas: dom.canvas,
1868
+ destroy() {
1869
+ if (destroyed) {
1870
+ return;
1871
+ }
1872
+
1873
+ destroyed = true;
1874
+ if (frameHandle != null) {
1875
+ cancelAnimationFrame(frameHandle);
1876
+ }
1877
+ dom.pauseButton.removeEventListener("click", handlePauseClick);
1878
+ dom.stressToggle.removeEventListener("change", handleStressChange);
1879
+ dom.focusMode.removeEventListener("change", handleFocusChange);
1880
+ root.innerHTML = previousMarkup;
1881
+
1882
+ if (typeof previousRenderGameToText === "function") {
1883
+ window.render_game_to_text = previousRenderGameToText;
1884
+ } else {
1885
+ delete window.render_game_to_text;
1886
+ }
1887
+
1888
+ if (typeof previousAdvanceTime === "function") {
1889
+ window.advanceTime = previousAdvanceTime;
1890
+ } else {
1891
+ delete window.advanceTime;
1892
+ }
1893
+ },
1857
1894
  };
1858
1895
  }
1859
1896