@needle-tools/engine 5.1.14 → 5.1.15

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/gltf-progressive-4EjGCbsd.umd.cjs +10 -0
  3. package/dist/{gltf-progressive-DaeP5KBr.js → gltf-progressive-BidVoP6g.js} +205 -198
  4. package/dist/gltf-progressive-JsCmImqa.min.js +10 -0
  5. package/dist/{needle-engine.bundle-y1_E7Ovt.umd.cjs → needle-engine.bundle-BivRq9Io.umd.cjs} +143 -143
  6. package/dist/{needle-engine.bundle-BEa7CABw.js → needle-engine.bundle-ByEd2JMt.js} +5658 -5645
  7. package/dist/{needle-engine.bundle-mkmiuKZB.min.js → needle-engine.bundle-DiobwRVT.min.js} +146 -146
  8. package/dist/needle-engine.d.ts +29 -27
  9. package/dist/needle-engine.js +233 -233
  10. package/dist/needle-engine.min.js +1 -1
  11. package/dist/needle-engine.umd.cjs +1 -1
  12. package/lib/engine/api.d.ts +1 -1
  13. package/lib/engine/api.js +1 -1
  14. package/lib/engine/api.js.map +1 -1
  15. package/lib/engine/engine_context.js +3 -0
  16. package/lib/engine/engine_context.js.map +1 -1
  17. package/lib/engine/engine_init.js +2 -2
  18. package/lib/engine/engine_init.js.map +1 -1
  19. package/lib/engine/engine_license.d.ts +7 -7
  20. package/lib/engine/engine_license.js +74 -74
  21. package/lib/engine/engine_license.js.map +1 -1
  22. package/lib/engine/engine_loaders.gltf.d.ts +3 -1
  23. package/lib/engine/engine_loaders.gltf.js +6 -1
  24. package/lib/engine/engine_loaders.gltf.js.map +1 -1
  25. package/lib/engine/engine_networking_blob.js +3 -3
  26. package/lib/engine/engine_networking_blob.js.map +1 -1
  27. package/lib/engine/engine_physics.d.ts +2 -0
  28. package/lib/engine/engine_physics.js +23 -1
  29. package/lib/engine/engine_physics.js.map +1 -1
  30. package/lib/engine/engine_utils_qrcode.js +2 -2
  31. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  32. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  33. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  34. package/lib/engine/webcomponents/needle menu/needle-menu.js +5 -5
  35. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  36. package/lib/engine/webcomponents/needle-engine.js +2 -2
  37. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  38. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  39. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  40. package/lib/engine/xr/TempXRContext.js +2 -2
  41. package/lib/engine/xr/TempXRContext.js.map +1 -1
  42. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  43. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  44. package/package.json +2 -2
  45. package/plugins/common/license.js +4 -4
  46. package/plugins/vite/license.js +4 -4
  47. package/src/engine/api.ts +1 -1
  48. package/src/engine/engine_context.ts +3 -0
  49. package/src/engine/engine_init.ts +2 -2
  50. package/src/engine/engine_license.ts +71 -71
  51. package/src/engine/engine_loaders.gltf.ts +8 -2
  52. package/src/engine/engine_networking_blob.ts +3 -3
  53. package/src/engine/engine_physics.ts +22 -1
  54. package/src/engine/engine_utils_qrcode.ts +2 -2
  55. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  56. package/src/engine/webcomponents/needle menu/needle-menu.ts +5 -5
  57. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  58. package/src/engine/webcomponents/needle-engine.ts +2 -2
  59. package/src/engine/xr/TempXRContext.ts +2 -2
  60. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  61. package/dist/gltf-progressive-BnLTsXZw.umd.cjs +0 -10
  62. package/dist/gltf-progressive-D6RT9IkB.min.js +0 -10
@@ -41,19 +41,19 @@ function setLicenseTimeout(ctx: IContext, callback: () => void, delay: number) {
41
41
 
42
42
  const debug = getParam("__debuglic__");
43
43
 
44
- const hfq: ((result: boolean) => void)[] = [];
44
+ const _qmF: ((result: boolean) => void)[] = [];
45
45
 
46
46
  // DO NOT EDIT MANUALLY
47
- let _QsjWa: string = "";
47
+ let __bhYI: string = "";
48
48
  // eslint-disable-next-line prefer-const
49
- let _puYWsjJC: string = "";
49
+ let _$bNaUjux: string = "";
50
50
 
51
51
  if (debug) {
52
- console.log("License Type: " + _QsjWa);
53
- if (_puYWsjJC) {
54
- console.log("License JWT: " + _puYWsjJC);
52
+ console.log("License Type: " + __bhYI);
53
+ if (_$bNaUjux) {
54
+ console.log("License JWT: " + _$bNaUjux);
55
55
  try {
56
- const payload = JSON.parse(atob(_puYWsjJC.split(".")[1].replace(/-/g, '+').replace(/_/g, '/')));
56
+ const payload = JSON.parse(atob(_$bNaUjux.split(".")[1].replace(/-/g, '+').replace(/_/g, '/')));
57
57
  console.log("License JWT payload:", payload);
58
58
  }
59
59
  catch { console.log("License JWT payload: (failed to decode)"); }
@@ -64,8 +64,8 @@ if (debug) {
64
64
  }
65
65
 
66
66
  /** @internal */
67
- export function _$xBhfh() {
68
- switch (_QsjWa) {
67
+ export function __iOMsPxgl() {
68
+ switch (__bhYI) {
69
69
  case "pro":
70
70
  case "enterprise":
71
71
  return true;
@@ -74,8 +74,8 @@ export function _$xBhfh() {
74
74
  }
75
75
 
76
76
  /** @internal */
77
- export function __YFTdTh() {
78
- switch (_QsjWa) {
77
+ export function NrbElgld() {
78
+ switch (__bhYI) {
79
79
  case "indie":
80
80
  return true;
81
81
  }
@@ -83,8 +83,8 @@ export function __YFTdTh() {
83
83
  }
84
84
 
85
85
  /** @internal */
86
- export function _$qEBaEKr() {
87
- switch (_QsjWa) {
86
+ export function _$PFtkm() {
87
+ switch (__bhYI) {
88
88
  case "edu":
89
89
  return true;
90
90
  }
@@ -92,26 +92,26 @@ export function _$qEBaEKr() {
92
92
  }
93
93
 
94
94
  /** @internal */
95
- export function __alnviAJA() {
96
- return _$xBhfh() || __YFTdTh() || _$qEBaEKr();
95
+ export function _RUUSWrG() {
96
+ return __iOMsPxgl() || NrbElgld() || _$PFtkm();
97
97
  }
98
98
 
99
99
 
100
100
  /** @internal */
101
- export function dRcEhn(cb: (result: boolean) => void) {
102
- if (_$xBhfh() || __YFTdTh() || _$qEBaEKr()) {
101
+ export function FgW(cb: (result: boolean) => void) {
102
+ if (__iOMsPxgl() || NrbElgld() || _$PFtkm()) {
103
103
  cb(true);
104
104
  return () => {};
105
105
  }
106
- hfq.push(cb);
106
+ _qmF.push(cb);
107
107
  return () => {
108
- const index = hfq.indexOf(cb);
109
- if (index >= 0) hfq.splice(index, 1);
108
+ const index = _qmF.indexOf(cb);
109
+ if (index >= 0) _qmF.splice(index, 1);
110
110
  };
111
111
  }
112
112
 
113
- function $rpNGR(result: boolean) {
114
- for (const cb of hfq) {
113
+ function ZJOi(result: boolean) {
114
+ for (const cb of _qmF) {
115
115
  try {
116
116
  cb(result);
117
117
  }
@@ -126,7 +126,7 @@ function $rpNGR(result: boolean) {
126
126
 
127
127
  // ECDSA P-256 public key for verifying license JWTs (verification-only, safe to ship)
128
128
  /* eslint-disable no-secrets/no-secrets -- public key, not a secret */
129
- const $jkMSKnw = {
129
+ const _$xBsMkBZS = {
130
130
  kty: "EC",
131
131
  crv: "P-256",
132
132
  x: "A34nyKMjhQYVgzeE4tyLUYdx34TAKogDa7v7PRaO9Lg",
@@ -150,7 +150,7 @@ function base64urlDecode(str: string): Uint8Array {
150
150
  * Verify a JWT license token and return the `type` claim if valid.
151
151
  * Returns null if the JWT is missing, malformed, or has an invalid signature.
152
152
  */
153
- async function Twm(jwt: string): Promise<string | null> {
153
+ async function __UxqnXD(jwt: string): Promise<string | null> {
154
154
  if (!jwt) return null;
155
155
  try {
156
156
  const parts = jwt.split(".");
@@ -160,7 +160,7 @@ async function Twm(jwt: string): Promise<string | null> {
160
160
 
161
161
  const key = await crypto.subtle.importKey(
162
162
  "jwk",
163
- $jkMSKnw,
163
+ _$xBsMkBZS,
164
164
  { name: "ECDSA", namedCurve: "P-256" },
165
165
  false,
166
166
  ["verify"]
@@ -220,24 +220,24 @@ async function Twm(jwt: string): Promise<string | null> {
220
220
  }
221
221
 
222
222
  /** Verify the injected JWT and update the license type if valid.
223
- * The engine ONLY trusts the JWT — the plain _QsjWa string is ignored. */
223
+ * The engine ONLY trusts the JWT — the plain __bhYI string is ignored. */
224
224
  let _jwtVerificationPromise: Promise<void> | undefined = undefined;
225
- async function _$qGmvPvr(): Promise<void> {
226
- // NOTE: do NOT add an `if (!_puYWsjJC) return` guard here.
225
+ async function _JkIK(): Promise<void> {
226
+ // NOTE: do NOT add an `if (!_$bNaUjux) return` guard here.
227
227
  // esbuild (Vite dependency pre-bundling) would see the variable as constant ""
228
228
  // and tree-shake the entire JWT verification code path.
229
- const jwt = _puYWsjJC;
229
+ const jwt = _$bNaUjux;
230
230
  // Clear after reading — this reassignment also prevents esbuild from
231
231
  // constant-folding the variable (it now has multiple assignment sites).
232
- _puYWsjJC = "";
233
- const verifiedType = await Twm(jwt);
232
+ _$bNaUjux = "";
233
+ const verifiedType = await __UxqnXD(jwt);
234
234
  if (verifiedType) {
235
- _QsjWa = verifiedType;
235
+ __bhYI = verifiedType;
236
236
  if (debug) console.log("License type set from verified JWT: " + verifiedType);
237
- $rpNGR(__alnviAJA());
237
+ ZJOi(_RUUSWrG());
238
238
  }
239
239
  else {
240
- _QsjWa = "basic";
240
+ __bhYI = "basic";
241
241
  if (debug && jwt) console.warn("JWT verification failed — license reset to basic");
242
242
  }
243
243
  }
@@ -360,7 +360,7 @@ export namespace Telemetry {
360
360
  // NOTE: this does NOT affect license enforcement — the /check call, the "forbidden"
361
361
  // overlay and the watermark/logo run on separate, ungated code paths.
362
362
  const attribute = domElement?.getAttribute("no-telemetry");
363
- if (_$xBhfh() && (attribute === "" || attribute === "true" || attribute === "1")) {
363
+ if (__iOMsPxgl() && (attribute === "" || attribute === "true" || attribute === "1")) {
364
364
  if (debug) console.debug("Telemetry is disabled via no-telemetry attribute");
365
365
  return false;
366
366
  }
@@ -688,18 +688,18 @@ export namespace Telemetry {
688
688
  }
689
689
 
690
690
 
691
- export function $tbhNjEbR() {
691
+ export function ZsdhPc() {
692
692
 
693
- if(_QsjWa === "") _QsjWa = "basic";
693
+ if(__bhYI === "") __bhYI = "basic";
694
694
 
695
695
  // Start JWT verification — must be here (not top-level) to avoid tree-shaking
696
- _jwtVerificationPromise = _$qGmvPvr();
696
+ _jwtVerificationPromise = _JkIK();
697
697
 
698
698
  Telemetry.init();
699
699
  ContextRegistry.registerCallback(ContextEvent.ContextRegistered, evt => {
700
- _$toCs(evt.context);
701
- $DAPYU(evt.context);
702
- setLicenseTimeout(evt.context, () => _qzMSGyVj(evt.context), 2000);
700
+ FNu(evt.context);
701
+ $JnhyfUqd(evt.context);
702
+ setLicenseTimeout(evt.context, () => __IZGhoUdm(evt.context), 2000);
703
703
  });
704
704
  // ContextCreated fires after the renderer exists, so the canvas is available for context-loss monitoring
705
705
  ContextRegistry.registerCallback(ContextEvent.ContextCreated, evt => {
@@ -708,17 +708,17 @@ export function $tbhNjEbR() {
708
708
  });
709
709
  }
710
710
 
711
- export let _$bDVSQf: Promise<void> | undefined = undefined;
711
+ export let __aBnVBrH: Promise<void> | undefined = undefined;
712
712
  let applicationIsForbidden = false;
713
713
  let applicationForbiddenText = "";
714
- async function $TPLZ() {
714
+ async function _YDj() {
715
715
  // Only perform the runtime license check once
716
- if (_$bDVSQf) return _$bDVSQf;
716
+ if (__aBnVBrH) return __aBnVBrH;
717
717
  // Wait for JWT verification to complete first (if running)
718
718
  if (_jwtVerificationPromise) {
719
719
  await _jwtVerificationPromise;
720
720
  }
721
- if (_QsjWa === "basic") {
721
+ if (__bhYI === "basic") {
722
722
  try {
723
723
  const licenseUrl = "https://needle.tools/api/v1/needle-engine/check?location=" + encodeURIComponent(window.location.href) + "&version=" + VERSION + "&generator=" + encodeURIComponent(GENERATOR);
724
724
  const res = await fetch(licenseUrl, {
@@ -730,29 +730,29 @@ async function $TPLZ() {
730
730
  if (res?.status === 200) {
731
731
  applicationIsForbidden = false;
732
732
  if (debug) console.log("License check succeeded");
733
- _QsjWa = "pro";
734
- $rpNGR(true);
733
+ __bhYI = "pro";
734
+ ZJOi(true);
735
735
  }
736
736
  else if (res?.status === 403) {
737
- $rpNGR(false);
737
+ ZJOi(false);
738
738
  applicationIsForbidden = true;
739
739
  applicationForbiddenText = await res.text();
740
740
  }
741
741
  else {
742
- $rpNGR(false);
742
+ ZJOi(false);
743
743
  if (debug) console.log("License check failed with status " + res?.status);
744
744
  }
745
745
  }
746
746
  catch (err) {
747
- $rpNGR(false);
747
+ ZJOi(false);
748
748
  if (debug) console.error("License check failed", err);
749
749
  }
750
750
  }
751
- else if (debug) console.log("Runtime license check is skipped because license is already applied as \"" + _QsjWa + "\"");
751
+ else if (debug) console.log("Runtime license check is skipped because license is already applied as \"" + __bhYI + "\"");
752
752
  }
753
- _$bDVSQf = $TPLZ();
753
+ __aBnVBrH = _YDj();
754
754
 
755
- async function $DAPYU(ctx: IContext) {
755
+ async function $JnhyfUqd(ctx: IContext) {
756
756
  function createForbiddenElement() {
757
757
  const div = document.createElement("div");
758
758
  div.className = "needle-forbidden";
@@ -817,40 +817,40 @@ async function $DAPYU(ctx: IContext) {
817
817
  }, 500)
818
818
  }
819
819
 
820
- async function _$toCs(ctx: IContext) {
820
+ async function FNu(ctx: IContext) {
821
821
  try {
822
- if (!_$xBhfh() && !__YFTdTh()) {
823
- return $BkPUwzsT(ctx);
822
+ if (!__iOMsPxgl() && !NrbElgld()) {
823
+ return __DodRJYRG(ctx);
824
824
  }
825
825
  }
826
826
  catch (err) {
827
827
  if (debug) console.log("License check failed", err)
828
- return $BkPUwzsT(ctx)
828
+ return __DodRJYRG(ctx)
829
829
  }
830
- if (debug) $BkPUwzsT(ctx)
830
+ if (debug) __DodRJYRG(ctx)
831
831
  }
832
832
 
833
833
 
834
834
 
835
- async function $BkPUwzsT(ctx: IContext) {
835
+ async function __DodRJYRG(ctx: IContext) {
836
836
 
837
837
  // if the engine loads faster than the license check, we need to capture the ready event here
838
838
  let isReady = false;
839
839
  ctx.domElement.addEventListener("ready", () => isReady = true);
840
840
 
841
- await _$bDVSQf?.catch(() => { });
841
+ await __aBnVBrH?.catch(() => { });
842
842
 
843
843
 
844
- if (_$xBhfh() || __YFTdTh()) return;
845
- if (__alnviAJA() === false) EyGW();
844
+ if (__iOMsPxgl() || NrbElgld()) return;
845
+ if (_RUUSWrG() === false) $nPPWwJeH();
846
846
 
847
847
  // check if the engine is already ready (meaning has finished loading)
848
848
  if (isReady) {
849
- __vrAZI(ctx);
849
+ __vpC(ctx);
850
850
  }
851
851
  else {
852
852
  ctx.domElement.addEventListener("ready", () => {
853
- __vrAZI(ctx);
853
+ __vpC(ctx);
854
854
  });
855
855
  }
856
856
  }
@@ -858,7 +858,7 @@ async function $BkPUwzsT(ctx: IContext) {
858
858
  // const licenseElementIdentifier = "needle-license-element";
859
859
  // const licenseDuration = 10000;
860
860
  // const licenseDelay = 1200;
861
- function __vrAZI(ctx: IContext) {
861
+ function __vpC(ctx: IContext) {
862
862
 
863
863
  const style = `
864
864
  position: relative;
@@ -871,7 +871,7 @@ function __vrAZI(ctx: IContext) {
871
871
  padding: 10px;
872
872
  padding-left: 30px;
873
873
  `;
874
- if (_QsjWa === "edu") {
874
+ if (__bhYI === "edu") {
875
875
  if (navigator.webdriver) {
876
876
  console.log("This project is supported by Needle for Education – https://needle.tools");
877
877
  }
@@ -928,7 +928,7 @@ function __vrAZI(ctx: IContext) {
928
928
  }
929
929
  }, 1000);
930
930
 
931
- if (_$qEBaEKr()) {
931
+ if (_$PFtkm()) {
932
932
  const removeDelay = 20_000;
933
933
  setLicenseTimeout(ctx, () => {
934
934
  clearInterval(interval);
@@ -937,7 +937,7 @@ function __vrAZI(ctx: IContext) {
937
937
  const intervalInMinutes = 5;
938
938
  setLicenseTimeout(ctx, () => {
939
939
  if (ctx.domElement.parentNode)
940
- __vrAZI(ctx);
940
+ __vpC(ctx);
941
941
  }, 1000 * 60 * intervalInMinutes)
942
942
  }, removeDelay);
943
943
  }
@@ -948,7 +948,7 @@ function __vrAZI(ctx: IContext) {
948
948
  const base64Logo = "data:image/webp;base64,UklGRrABAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSKEAAAARN6CmbSM4WR7vdARON11EBDq3fLiNbVtVzpMCPlKAEzsx0Y/x+Ovuv4dn0EFE/ydAvz6YggXzgh5sVgXM/zOC/4sii7qgGvB5N7hmuQYwkvazWAu1JPW41FXSHq6pnaQWvqYH18Fc0j1hO/BFTtIeSBlJi5w6qIIO7IOrwhFsB2Yxukif0FTRLpXswHR8MxbslKe9VZsn/Ub5C7YFOpqSTABWUDgg6AAAAFAGAJ0BKiAAIAA+7VyoTqmkpCI3+qgBMB2JbACdMt69DwMIQBLhkTO6XwY00UEDK6cNIDnuNibPf0EgAP7Y1myuiQHLDsF/0h5unrGh6WAbv7aegg2ZMd3uRKfT/3SJztcaujYfTvMXspfCTmYcoO6a+vhC3ss4M8uM58t4siiu59I4aOl59e9Sr6xoxYlHf2v+NnBNpJYeJf8jABQAId/PXuBkLEFkiCucgSGEcfhvajql/j3reCGl0M5/9gQWy7ayNPs+wlvIxFnNfSlfuND4CZOCyxOHhRqOmHN4ULHo3tCSrUNvgAA=";
949
949
 
950
950
  let lastLogTime = 0;
951
- async function EyGW(_logo?: string) {
951
+ async function $nPPWwJeH(_logo?: string) {
952
952
  const now = Date.now();
953
953
  if (now - lastLogTime < 2000) return;
954
954
  lastLogTime = now;
@@ -981,7 +981,7 @@ async function EyGW(_logo?: string) {
981
981
  }
982
982
 
983
983
 
984
- async function _qzMSGyVj(context: IContext) {
984
+ async function __IZGhoUdm(context: IContext) {
985
985
  // isAllowed() now also covers cross-origin-isolated pages (where beacons can't be sent)
986
986
  // and Do Not Track / GPC.
987
987
  if (!Telemetry.isAllowed(context)) {
@@ -995,7 +995,7 @@ async function _qzMSGyVj(context: IContext) {
995
995
 
996
996
  // current url without query parameters
997
997
  const currentUrl = window.location.href.split("?")[0];
998
- const license = _QsjWa;
998
+ const license = __bhYI;
999
999
 
1000
1000
  const beaconData = {
1001
1001
  license,
@@ -1,11 +1,11 @@
1
1
 
2
- import { addDracoAndKTX2Loaders as addDracoAndKTX2LoadersGLTFProgressive, configureLoader, createLoaders, setDracoDecoderLocation, setKTX2TranscoderLocation } from '@needle-tools/gltf-progressive';
2
+ import { addDracoAndKTX2Loaders as addDracoAndKTX2LoadersGLTFProgressive, configureLoader, createLoaders, disposeLoaders, setDracoDecoderLocation, setKTX2TranscoderLocation } from '@needle-tools/gltf-progressive';
3
3
  import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
4
4
  import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
5
5
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
6
6
  import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
7
7
 
8
- import { Context } from "./engine_setup.js"
8
+ import type { Context } from "./engine_setup.js"
9
9
  import { getParam } from "./engine_utils.js";
10
10
 
11
11
  const debug = getParam("debugdecoders");
@@ -20,6 +20,12 @@ function ensureLoaders() {
20
20
  return loaders;
21
21
  }
22
22
 
23
+ /** Release shared decoder workers after the last engine context is destroyed. */
24
+ export function disposeGLTFLoaders() {
25
+ disposeLoaders();
26
+ loaders = null;
27
+ }
28
+
23
29
  export function setDracoDecoderPath(path: string | undefined) {
24
30
  if (path !== undefined && typeof path === "string") {
25
31
  setDracoDecoderLocation(path);
@@ -1,7 +1,7 @@
1
1
  import { FileLoader } from "three";
2
2
 
3
3
  import { showBalloonWarning } from "./debug/index.js";
4
- import { __alnviAJA } from "./engine_license.js";
4
+ import { _RUUSWrG } from "./engine_license.js";
5
5
  import { delay } from "./engine_utils.js";
6
6
  import { md5AsBytes, md5Hex, sha256Base64 } from "./engine_utils_hash.js";
7
7
 
@@ -45,7 +45,7 @@ export namespace BlobStorage {
45
45
  */
46
46
  export function canUpload(info: { filesize: number }) {
47
47
  const sizeInMB = info.filesize / 1024 / 1024;
48
- if (__alnviAJA()) {
48
+ if (_RUUSWrG()) {
49
49
  return sizeInMB < maxSizeInMB;
50
50
  }
51
51
  return sizeInMB < maxFreeSizeInMB;
@@ -100,7 +100,7 @@ export namespace BlobStorage {
100
100
  console.warn(`Your file is too large for uploading (${filesizeInMB.toFixed(1)}MB). Max allowed size is ${maxSizeInMB}MB`);
101
101
  return null;
102
102
  }
103
- else if (!__alnviAJA() && filesizeInMB > maxFreeSizeInMB) {
103
+ else if (!_RUUSWrG() && filesizeInMB > maxFreeSizeInMB) {
104
104
  if (opts?.silent !== true) showBalloonWarning(`File is too large for uploading. Please get a <a href=\"https://needle.tools/pricing\" target=\"_blank\">commercial license</a> to upload files larger than 5MB`);
105
105
  console.warn(`Your file is too large for uploading (${filesizeInMB.toFixed(1)}MB). Max size is 5MB for non-commercial users. Please get a commercial license at https://needle.tools/pricing for larger files (up to 50MB)`);
106
106
  return null;
@@ -175,6 +175,11 @@ export class SphereIntersection implements Intersection {
175
175
  */
176
176
  export class Physics {
177
177
 
178
+ /** Release the shared BVH worker pool after the last engine context is destroyed. */
179
+ static disposeMeshBVHWorkers() {
180
+ NEMeshBVH.disposeWorkers();
181
+ }
182
+
178
183
  private static _raycasting: number = 0;
179
184
  /**
180
185
  * Returns true if raycasting is currently in progress
@@ -738,7 +743,13 @@ namespace NEMeshBVH {
738
743
  })
739
744
  .finally(() => {
740
745
  if (debugPhysics) console.log(">>>>> worker done", name, { hasBoundsTre: geom.boundsTree != undefined });
741
- availableWorkers.push(workerInstance);
746
+ if (retiredWorkers.has(workerInstance)) {
747
+ retiredWorkers.delete(workerInstance);
748
+ workerInstance.dispose();
749
+ }
750
+ else {
751
+ availableWorkers.push(workerInstance);
752
+ }
742
753
  copy.dispose();
743
754
  performance.mark("bvh.create.end");
744
755
  performance.measure("bvh.create (worker)", "bvh.create.start", "bvh.create.end");
@@ -859,6 +870,16 @@ namespace NEMeshBVH {
859
870
  const canUseWorkerSymbol = Symbol("Needle:MeshBVH-CanUseWorker");
860
871
  const workerInstances: GenerateMeshBVHWorker[] = [];
861
872
  const availableWorkers: GenerateMeshBVHWorker[] = [];
873
+ const retiredWorkers = new Set<GenerateMeshBVHWorker>();
874
+
875
+ export function disposeWorkers() {
876
+ for (const worker of workerInstances) {
877
+ if (worker.running) retiredWorkers.add(worker);
878
+ else worker.dispose();
879
+ }
880
+ workerInstances.length = 0;
881
+ availableWorkers.length = 0;
882
+ }
862
883
 
863
884
  function internalSetupWorker() {
864
885
  didSetupWorker = true;
@@ -4,7 +4,7 @@ import { Quaternion, Vector2, Vector3, Vector4 } from "three";
4
4
 
5
5
  import { needleLogoOnlySVG } from "./assets/index.js";
6
6
  import { isDevEnvironment } from "./debug/debug.js";
7
- import { __alnviAJA } from "./engine_license.js";
7
+ import { _RUUSWrG } from "./engine_license.js";
8
8
  import { InternalAttributeUtils } from "./engine_utils_attributes.js";
9
9
  import type { NeedleEngineWebComponent } from "./webcomponents/needle-engine.js";
10
10
 
@@ -135,7 +135,7 @@ async function internalRenderQRCodeOverlays(canvas: HTMLCanvasElement, args: { s
135
135
  console.debug("[QR Code] No web component found")
136
136
  }
137
137
 
138
- const canUseCustomLogo = __alnviAJA();
138
+ const canUseCustomLogo = _RUUSWrG();
139
139
 
140
140
  // Query logo src from needle-engine attribute.
141
141
  // For any supported attribute it's possible to use "falsey" values (e.g. "0" or "false" to disable the logo in the QR code)
@@ -2,7 +2,7 @@ import { Mesh, Object3D, TextureLoader, Vector4 } from "three";
2
2
  import ThreeMeshUI from "three-mesh-ui";
3
3
 
4
4
  import { addNewComponent } from "../../engine_components.js";
5
- import { __alnviAJA } from "../../engine_license.js";
5
+ import { _RUUSWrG } from "../../engine_license.js";
6
6
  import { OneEuroFilterXYZ } from "../../engine_math.js";
7
7
  import type { Context } from "../../engine_setup.js";
8
8
  import { lookAtObject } from "../../engine_three_utils.js";
@@ -321,7 +321,7 @@ export class NeedleSpatialMenu {
321
321
  }
322
322
  if (this.menu) {
323
323
  const index = this.menu.children.indexOf(this._poweredByNeedleElement as any);
324
- if (!this._showNeedleLogo && __alnviAJA()) {
324
+ if (!this._showNeedleLogo && _RUUSWrG()) {
325
325
  if (index >= 0) {
326
326
  this._poweredByNeedleElement.removeFromParent();
327
327
  this.markDirty();
@@ -1,6 +1,6 @@
1
1
  import { showBalloonMessage } from "../../debug/debug.js";
2
2
  import type { Context } from "../../engine_context.js";
3
- import { __alnviAJA, dRcEhn, Telemetry } from "../../engine_license.js";
3
+ import { _RUUSWrG, FgW, Telemetry } from "../../engine_license.js";
4
4
  import { isLocalNetwork } from "../../engine_networking_utils.js";
5
5
  import { HTMLElementBase } from "../../engine_ssr.js";
6
6
  import { DeviceUtilities, getParam } from "../../engine_utils.js";
@@ -801,8 +801,8 @@ export class NeedleMenuElement extends HTMLElementBase {
801
801
  // calling this method immediately will cause an issue with vite bundling tho
802
802
  this._licenseFrame = window.requestAnimationFrame(() => {
803
803
  this._licenseFrame = undefined;
804
- this._unsubscribeLicense = dRcEhn(res => {
805
- if (res == true && __alnviAJA() && !debugNonCommercial) {
804
+ this._unsubscribeLicense = FgW(res => {
805
+ if (res == true && _RUUSWrG() && !debugNonCommercial) {
806
806
  let visible = this._userRequestedLogoVisible;
807
807
  if (visible === undefined) visible = false;
808
808
  this.___onSetLogoVisible(visible);
@@ -854,7 +854,7 @@ export class NeedleMenuElement extends HTMLElementBase {
854
854
  // ensure the menu is not hidden or removed
855
855
  const requiredParent = this?.parentNode;
856
856
  if (this.style.display != "flex" || this.style.visibility != "visible" || this.style.opacity != "1" || requiredParent != this._domElement?.shadowRoot) {
857
- if (!__alnviAJA()) {
857
+ if (!_RUUSWrG()) {
858
858
  const change = changeEventCounter++;
859
859
  // if a user doesn't have a local pro license *but* for development the menu is hidden then we show a warning
860
860
  if (isLocalNetwork() && this._userRequestedMenuVisible === false) {
@@ -950,7 +950,7 @@ export class NeedleMenuElement extends HTMLElementBase {
950
950
  showNeedleLogo(visible: boolean) {
951
951
  this._userRequestedLogoVisible = visible;
952
952
  if (!visible) {
953
- if (!__alnviAJA() || debugNonCommercial) {
953
+ if (!_RUUSWrG() || debugNonCommercial) {
954
954
  console.warn("[Needle Engine] You need a commercial license to hide the Needle Engine logo in production.");
955
955
  const localNetwork = isLocalNetwork()
956
956
  if (!localNetwork) return;
@@ -1,6 +1,6 @@
1
1
  import { needleLogoOnlySVG } from "../assets/index.js"
2
2
  import { isDevEnvironment, showBalloonWarning } from "../debug/index.js";
3
- import { __alnviAJA, _$xBhfh, _$bDVSQf } from "../engine_license.js";
3
+ import { _RUUSWrG, __iOMsPxgl, __aBnVBrH } from "../engine_license.js";
4
4
  import { Mathf } from "../engine_math.js";
5
5
  import { LoadingProgressArgs } from "../engine_setup.js";
6
6
  import { getParam } from "../engine_utils.js";
@@ -217,7 +217,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
217
217
  }
218
218
 
219
219
 
220
- const hasLicense = _$xBhfh();
220
+ const hasLicense = __iOMsPxgl();
221
221
  if (!existing) {
222
222
  this._loadingElement.style.position = "absolute";
223
223
  this._loadingElement.style.width = "100%";
@@ -385,7 +385,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
385
385
 
386
386
  // private async handleRuntimeLicense(loadingElement: HTMLElement) {
387
387
  // // First check if we have a commercial license
388
- // let commercialLicense = __alnviAJA();
388
+ // let commercialLicense = _RUUSWrG();
389
389
  // // if it's the case then we don't need to perform a runtime check
390
390
  // if (commercialLicense) return;
391
391
 
@@ -405,10 +405,10 @@ export class EngineLoadingView implements ILoadingViewHandler {
405
405
  // loadingElement.appendChild(nonCommercialContainer);
406
406
 
407
407
  // // Use the runtime license check
408
- // if (!isDevEnvironment() && _$bDVSQf) {
408
+ // if (!isDevEnvironment() && __aBnVBrH) {
409
409
  // if (debugLicense) console.log("Waiting for runtime license check");
410
- // await _$bDVSQf;
411
- // commercialLicense = __alnviAJA();
410
+ // await __aBnVBrH;
411
+ // commercialLicense = _RUUSWrG();
412
412
  // }
413
413
  // if (commercialLicense) return;
414
414
  // nonCommercialContainer.style.transition = "opacity .5s ease-in-out";
@@ -3,7 +3,7 @@ import type { Texture } from "three";
3
3
  import { isDevEnvironment, showBalloonWarning } from "../debug/index.js";
4
4
  import { PUBLIC_KEY, VERSION } from "../engine_constants.js";
5
5
  import { ContextEvent, ContextRegistry } from "../engine_context_registry.js";
6
- import { __alnviAJA, Telemetry } from "../engine_license.js";
6
+ import { _RUUSWrG, Telemetry } from "../engine_license.js";
7
7
  import { onStart } from "../engine_lifecycle_api.js";
8
8
  import { setDracoDecoderPath, setDracoDecoderType, setKtx2TranscoderPath } from "../engine_loaders.gltf.js";
9
9
  import { Context, ContextCreateArgs } from "../engine_setup.js";
@@ -583,7 +583,7 @@ export class NeedleEngineWebComponent extends HTMLElementBase implements INeedle
583
583
 
584
584
 
585
585
  // Loading start events
586
- const allowOverridingDefaultLoading = __alnviAJA();
586
+ const allowOverridingDefaultLoading = _RUUSWrG();
587
587
  // default loading can be overriden by calling preventDefault in the onload start event
588
588
  this.ensureLoadStartIsRegistered();
589
589
  let useDefaultLoading = this.dispatchEvent(new CustomEvent("loadstart", {
@@ -3,7 +3,7 @@ import { ArrayCamera, AxesHelper, Camera, Color, DirectionalLight, Fog, GridHelp
3
3
  import { needleLogoOnlySVG } from "../assets/index.js";
4
4
  import { isDevEnvironment } from "../debug/index.js";
5
5
  import { ObjectUtils, PrimitiveType } from "../engine_create_objects.js";
6
- import { __alnviAJA } from "../engine_license.js";
6
+ import { _RUUSWrG } from "../engine_license.js";
7
7
  import { Mathf } from "../engine_math.js";
8
8
  import { delay, DeviceUtilities } from "../engine_utils.js";
9
9
 
@@ -215,7 +215,7 @@ export class TemporaryXRContext {
215
215
  this._scene.background = new Color(0x000000);
216
216
 
217
217
  let logoSrc = needleLogoOnlySVG;
218
- if (__alnviAJA()) {
218
+ if (_RUUSWrG()) {
219
219
  const htmlComponent = document.querySelector("needle-engine");
220
220
  if (htmlComponent) {
221
221
  const licenseLogo = htmlComponent.getAttribute("logo-src");
@@ -3,7 +3,7 @@ import { Euler, Material, Matrix4, Mesh, Object3D, Quaternion, Vector3 } from "t
3
3
 
4
4
  import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../../engine/debug/index.js";
5
5
  import { findObjectOfType } from "../../../engine/engine_components.js";
6
- import { _$xBhfh } from "../../../engine/engine_license.js";
6
+ import { __iOMsPxgl } from "../../../engine/engine_license.js";
7
7
  import { serializable } from "../../../engine/engine_serialization.js";
8
8
  import { getFormattedDate, Progress } from "../../../engine/engine_time_utils.js";
9
9
  import { DeviceUtilities, getParam } from "../../../engine/engine_utils.js";
@@ -277,7 +277,7 @@ export class USDZExporter extends Behaviour {
277
277
  let name = this.exportFileName ?? this.objectToExport?.name ?? this.name;
278
278
  name += "-" + getFormattedDate(); // seems iOS caches the file in some cases, this ensures we always have a fresh file
279
279
 
280
- if (!_$xBhfh()) {
280
+ if (!__iOMsPxgl()) {
281
281
  if (name !== "") name += "-";
282
282
  name += "MadeWithNeedle";
283
283
  }
@@ -682,7 +682,7 @@ export class USDZExporter extends Behaviour {
682
682
  if (debug)
683
683
  showBalloonMessage("Quicklook url: " + callToActionURL);
684
684
  if (callToActionURL) {
685
- if (!_$xBhfh()) {
685
+ if (!__iOMsPxgl()) {
686
686
  console.warn("Quicklook closed: custom redirects require a Needle Engine Pro license: https://needle.tools/pricing", callToActionURL)
687
687
  }
688
688
  else {
@@ -697,7 +697,7 @@ export class USDZExporter extends Behaviour {
697
697
  private buildQuicklookOverlay(): CustomBranding {
698
698
  const obj: CustomBranding = {};
699
699
  if (this.customBranding) Object.assign(obj, this.customBranding);
700
- if (!_$xBhfh()) {
700
+ if (!__iOMsPxgl()) {
701
701
  console.log("Custom Quicklook banner text requires pro license: https://needle.tools/pricing");
702
702
  obj.callToAction = "Close";
703
703
  obj.checkoutTitle = "🌵 Made with Needle";