@needle-tools/engine 4.15.0-next.f391a30 → 4.15.0

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 (150) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/{gltf-progressive-CTlvpS3A.js → gltf-progressive-Bm_6aEi4.js} +1 -1
  3. package/dist/{gltf-progressive-CMwJPwEt.umd.cjs → gltf-progressive-BttGBXw6.umd.cjs} +1 -1
  4. package/dist/{gltf-progressive-DYL3SLVb.min.js → gltf-progressive-T5WKTux5.min.js} +1 -1
  5. package/dist/materialx-CJyQZtjt.min.js +90 -0
  6. package/dist/materialx-DMs1E08Z.js +4636 -0
  7. package/dist/materialx-DaKKOoVk.umd.cjs +90 -0
  8. package/dist/{needle-engine.bundle-DsTdfmeb.min.js → needle-engine.bundle-CBq_OMnI.min.js} +122 -124
  9. package/dist/{needle-engine.bundle-DB4kLWO_.js → needle-engine.bundle-DGyiwNWR.js} +3226 -3232
  10. package/dist/{needle-engine.bundle-C1BFRZDF.umd.cjs → needle-engine.bundle-JN3eiiYc.umd.cjs} +113 -115
  11. package/dist/needle-engine.d.ts +52 -33
  12. package/dist/needle-engine.js +288 -287
  13. package/dist/needle-engine.min.js +1 -1
  14. package/dist/needle-engine.umd.cjs +1 -1
  15. package/dist/{postprocessing-BN-f4viE.min.js → postprocessing-06AXuvdv.min.js} +1 -1
  16. package/dist/{postprocessing-De9ZpJrk.js → postprocessing-CI2x8Cln.js} +1 -1
  17. package/dist/{postprocessing-DYmYOVm4.umd.cjs → postprocessing-CPDcA21P.umd.cjs} +1 -1
  18. package/dist/{three-examples-BHqRVpO_.umd.cjs → three-examples-BMmNgNCN.umd.cjs} +12 -12
  19. package/dist/{three-examples-C0ZCCA_K.js → three-examples-CMYCd5nH.js} +192 -182
  20. package/dist/{three-examples-DmTY8tGr.min.js → three-examples-CQl1fFZp.min.js} +14 -14
  21. package/lib/engine/api.d.ts +2 -0
  22. package/lib/engine/api.js +2 -0
  23. package/lib/engine/api.js.map +1 -1
  24. package/lib/engine/debug/debug.js +1 -1
  25. package/lib/engine/debug/debug.js.map +1 -1
  26. package/lib/engine/debug/debug_spatial_console.js +1 -1
  27. package/lib/engine/debug/debug_spatial_console.js.map +1 -1
  28. package/lib/engine/engine_accessibility.d.ts +1 -1
  29. package/lib/engine/engine_accessibility.js +1 -1
  30. package/lib/engine/engine_accessibility.js.map +1 -1
  31. package/lib/engine/engine_context.d.ts +1 -1
  32. package/lib/engine/engine_context.js +2 -2
  33. package/lib/engine/engine_context.js.map +1 -1
  34. package/lib/engine/engine_create_objects.js +1 -1
  35. package/lib/engine/engine_create_objects.js.map +1 -1
  36. package/lib/engine/engine_gizmos.js +1 -1
  37. package/lib/engine/engine_gizmos.js.map +1 -1
  38. package/lib/engine/engine_license.js +2 -7
  39. package/lib/engine/engine_license.js.map +1 -1
  40. package/lib/engine/engine_test_utils.d.ts +39 -0
  41. package/lib/engine/engine_test_utils.js +84 -0
  42. package/lib/engine/engine_test_utils.js.map +1 -0
  43. package/lib/engine/engine_utils.js +2 -2
  44. package/lib/engine/engine_utils.js.map +1 -1
  45. package/lib/engine/export/gltf/index.js +1 -1
  46. package/lib/engine/export/gltf/index.js.map +1 -1
  47. package/lib/engine/webcomponents/logo-element.d.ts +3 -6
  48. package/lib/engine/webcomponents/logo-element.js +0 -18
  49. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  50. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  51. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  52. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +7 -10
  53. package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -14
  54. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  55. package/lib/engine/webcomponents/needle-engine.ar-overlay.js +1 -10
  56. package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
  57. package/lib/engine/webcomponents/needle-engine.d.ts +0 -3
  58. package/lib/engine/webcomponents/needle-engine.js +0 -10
  59. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  60. package/lib/engine-components/Component.js +1 -0
  61. package/lib/engine-components/Component.js.map +1 -1
  62. package/lib/engine-components/ReflectionProbe.d.ts +2 -24
  63. package/lib/engine-components/ReflectionProbe.js +2 -28
  64. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  65. package/lib/engine-components/Skybox.js +2 -4
  66. package/lib/engine-components/Skybox.js.map +1 -1
  67. package/lib/engine-components/export/gltf/GltfExport.js +1 -1
  68. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  69. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +2 -2
  70. package/lib/engine-components/export/usdz/USDZExporter.js +1 -1
  71. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  72. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +2 -2
  73. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
  74. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  75. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
  76. package/package.json +14 -18
  77. package/plugins/common/buildinfo.js +10 -46
  78. package/plugins/common/files.js +1 -2
  79. package/plugins/common/license.js +69 -144
  80. package/plugins/common/logger.js +11 -172
  81. package/plugins/common/worker.js +4 -5
  82. package/plugins/types/userconfig.d.ts +2 -40
  83. package/plugins/vite/alias.js +5 -6
  84. package/plugins/vite/asap.js +5 -6
  85. package/plugins/vite/build-pipeline.js +41 -224
  86. package/plugins/vite/buildinfo.js +6 -66
  87. package/plugins/vite/copyfiles.js +12 -41
  88. package/plugins/vite/custom-element-data.js +16 -26
  89. package/plugins/vite/defines.js +5 -8
  90. package/plugins/vite/dependencies.js +10 -16
  91. package/plugins/vite/dependency-watcher.js +7 -35
  92. package/plugins/vite/drop-client.js +5 -7
  93. package/plugins/vite/drop.js +14 -16
  94. package/plugins/vite/editor-connection.js +16 -18
  95. package/plugins/vite/imports-logger.js +2 -12
  96. package/plugins/vite/index.js +3 -8
  97. package/plugins/vite/local-files.js +441 -2
  98. package/plugins/vite/logger.client.js +35 -45
  99. package/plugins/vite/logger.js +3 -6
  100. package/plugins/vite/meta.js +4 -18
  101. package/plugins/vite/needle-app.js +3 -4
  102. package/plugins/vite/peer.js +1 -2
  103. package/plugins/vite/pwa.js +17 -33
  104. package/plugins/vite/reload.js +2 -24
  105. package/src/engine/api.ts +3 -0
  106. package/src/engine/debug/debug.ts +1 -1
  107. package/src/engine/debug/debug_spatial_console.ts +1 -5
  108. package/src/engine/engine_accessibility.ts +1 -2
  109. package/src/engine/engine_context.ts +2 -2
  110. package/src/engine/engine_create_objects.ts +1 -1
  111. package/src/engine/engine_gizmos.ts +5 -9
  112. package/src/engine/engine_license.ts +2 -7
  113. package/src/engine/engine_test_utils.ts +109 -0
  114. package/src/engine/engine_utils.ts +2 -2
  115. package/src/engine/export/gltf/index.ts +1 -1
  116. package/src/engine/webcomponents/logo-element.ts +3 -20
  117. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -6
  118. package/src/engine/webcomponents/needle menu/needle-menu.ts +11 -23
  119. package/src/engine/webcomponents/needle-engine.ar-overlay.ts +2 -13
  120. package/src/engine/webcomponents/needle-engine.ts +1 -13
  121. package/src/engine-components/Component.ts +2 -1
  122. package/src/engine-components/ReflectionProbe.ts +9 -33
  123. package/src/engine-components/Skybox.ts +2 -4
  124. package/src/engine-components/export/gltf/GltfExport.ts +1 -1
  125. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
  126. package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
  127. package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +2 -2
  128. package/src/include/draco/draco_decoder.js +34 -0
  129. package/src/include/draco/draco_decoder.wasm +0 -0
  130. package/src/include/draco/draco_wasm_wrapper.js +117 -0
  131. package/src/include/ktx2/basis_transcoder.js +19 -0
  132. package/src/include/ktx2/basis_transcoder.wasm +0 -0
  133. package/src/include/needle/arial-msdf.json +1472 -0
  134. package/src/include/needle/arial.png +0 -0
  135. package/src/include/needle/poweredbyneedle.webp +0 -0
  136. package/dist/materialx-4jJLLe9Q.js +0 -4174
  137. package/dist/materialx-Bt9FHwco.min.js +0 -158
  138. package/dist/materialx-NDD0y4JY.umd.cjs +0 -158
  139. package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +0 -1
  140. package/plugins/common/needle-engine-skill.md +0 -175
  141. package/plugins/vite/ai.js +0 -71
  142. package/plugins/vite/local-files-analysis.js +0 -789
  143. package/plugins/vite/local-files-core.js +0 -992
  144. package/plugins/vite/local-files-internals.js +0 -28
  145. package/plugins/vite/local-files-types.d.ts +0 -111
  146. package/plugins/vite/local-files-utils.js +0 -359
  147. package/plugins/vite/logging.js +0 -129
  148. /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.d.ts +0 -0
  149. /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
  150. /package/src/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
@@ -0,0 +1,109 @@
1
+ import { DataTextureLoader,EquirectangularReflectionMapping, Object3D, PerspectiveCamera, Scene, Vector3 } from "three";
2
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
3
+
4
+ import { AssetReference } from "./engine_addressables.js";
5
+ import { getBoundingBox } from "./engine_three_utils.js";
6
+
7
+ declare type ComparisonSceneOptions = {
8
+ /**
9
+ * An array of model urls to load
10
+ */
11
+ files: string[];
12
+ /**
13
+ * Optional dom element to attach the orbit controls to. By default this should be the WebGLRenderer.domElement
14
+ */
15
+ domElement?: HTMLElement;
16
+ /**
17
+ * Can be a .hdr or .exr file url
18
+ */
19
+ environment?: string;
20
+ }
21
+
22
+ /**
23
+ * A collection of utility methods for quickly spinning up test environments
24
+ */
25
+ export class TestSceneUtils {
26
+
27
+ /**
28
+ * Use this method to quickly setup a scene to compare multiple models.
29
+ * @example
30
+ * ```ts
31
+ * const files = [
32
+ * "https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb",
33
+ * "https://threejs.org/examples/models/gltf/Lantern/glTF-Binary/Lantern.glb",
34
+ * ];
35
+ * const { scene, camera } = await TestUtils.createComparisonScene({ files });
36
+ * // this could now be assigned to the Needle Engine Context
37
+ * context.scene = scene;
38
+ * context.mainCamera = camera;
39
+ * ```
40
+ */
41
+ static async createComparisonScene(opts: ComparisonSceneOptions) {
42
+
43
+ const { files } = opts;
44
+
45
+ const promises = Promise.all(files.map(file => new AssetReference(file).loadAssetAsync()));
46
+ const results = await promises;
47
+ const scene = new Scene();
48
+
49
+ let offset = 0;
50
+ for (const result of results) {
51
+ if (result instanceof Object3D) {
52
+ result.position.y = offset;
53
+ scene.add(result);
54
+ const box = getBoundingBox([result]);
55
+ offset += box.getSize(new Vector3()).y;
56
+ offset += .1;
57
+ }
58
+ }
59
+ const camera = new PerspectiveCamera(20);
60
+ scene.add(camera);
61
+
62
+ // Load an environment map
63
+ const environmentUrl = opts.environment || "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/studio_small_09_1k.exr";
64
+ if (environmentUrl) {
65
+ let loader: DataTextureLoader | null = null;
66
+ if (environmentUrl.endsWith(".hdr")) {
67
+ const RGBELoader = (await import("three/examples/jsm/loaders/RGBELoader.js")).RGBELoader;
68
+ loader = new RGBELoader();
69
+ }
70
+ else if (environmentUrl.endsWith(".exr")) {
71
+ const EXRLoader = (await import("three/examples/jsm/loaders/EXRLoader.js")).EXRLoader;
72
+ loader = new EXRLoader();
73
+ }
74
+ if (loader) {
75
+ const envmap = await loader.loadAsync(environmentUrl).catch((e) => { console.error(e); return null; });
76
+ if (envmap) {
77
+ envmap.mapping = EquirectangularReflectionMapping;
78
+ envmap.needsUpdate = true;
79
+ scene.background = envmap;
80
+ scene.environment = envmap;
81
+ scene.backgroundBlurriness = .75;
82
+ }
83
+ }
84
+ else console.warn("Unsupported environment map format", environmentUrl);
85
+ }
86
+
87
+ const box = getBoundingBox(scene.children);
88
+ const center = box.getCenter(new Vector3());
89
+ const size = box.getSize(new Vector3());
90
+ const max = Math.max(size.x, size.y, size.z);
91
+ const distance = max / (2 * Math.tan(Math.PI * camera.fov / 360));
92
+ camera.position.set(center.x, center.y, distance);
93
+ camera.lookAt(center);
94
+
95
+ const orbit = new OrbitControls(camera, opts.domElement || document.body);
96
+ orbit.target = center;
97
+ orbit.update();
98
+
99
+
100
+ const element = (opts.domElement || document.body).getBoundingClientRect();
101
+ camera.aspect = element.width / element.height;
102
+ camera.updateProjectionMatrix();
103
+
104
+ return {
105
+ scene,
106
+ camera
107
+ }
108
+ }
109
+ }
@@ -607,7 +607,7 @@ export namespace DeviceUtilities {
607
607
  /** @returns `true` if it's a phone or tablet */
608
608
  export function isMobileDevice() {
609
609
  if (_ismobile !== undefined) return _ismobile;
610
- // eslint-disable-next-line @typescript-eslint/no-deprecated
610
+ // eslint-disable-next-line deprecation/deprecation
611
611
  if ((typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1)) {
612
612
  return _ismobile = true;
613
613
  }
@@ -677,7 +677,7 @@ export namespace DeviceUtilities {
677
677
  /** @returns `true` for mobile Apple devices like iPad, iPhone, iPod, Vision Pro, ... */
678
678
  export function isiOS() {
679
679
  if (__isiOS !== undefined) return __isiOS;
680
- // eslint-disable-next-line @typescript-eslint/no-deprecated
680
+ // eslint-disable-next-line deprecation/deprecation
681
681
  return __isiOS = iosDevices.includes(navigator.platform)
682
682
  // iPad on iOS 13 detection
683
683
  || (navigator.userAgent.includes("Mac") && "ontouchend" in document)
@@ -1,12 +1,12 @@
1
1
  import { AnimationClip, Object3D } from "three";
2
2
  import { GLTFExporter, GLTFExporterOptions } from "three/examples/jsm/exporters/GLTFExporter.js";
3
3
 
4
+ import GLTFMeshGPUInstancingExtension from "../../../include/three/EXT_mesh_gpu_instancing_exporter.js";
4
5
  import { AnimationUtils } from "../../engine_animation.js";
5
6
  import type { Context } from "../../engine_setup.js";
6
7
  import { registerExportExtensions } from "../../extensions/index.js";
7
8
  import { __isExporting } from "../state.js";
8
9
  import { shouldExport_HideFlags } from "../utils.js";
9
- import GLTFMeshGPUInstancingExtension from "./EXT_mesh_gpu_instancing_exporter.js";
10
10
  import { GizmoWriter as GLTFGizmoWriter, RenderTextureWriter as GLTFRenderTextureWriter } from "./Writers.js";
11
11
 
12
12
  declare type ExportOptions = {
@@ -20,13 +20,8 @@ export class NeedleLogoElement extends HTMLElement {
20
20
  return document.createElement(elementName) as NeedleLogoElement;
21
21
  }
22
22
 
23
- private _didInitialize = false;
24
-
25
23
  constructor() {
26
24
  super();
27
- }
28
-
29
- private initializeDom() {
30
25
  this._root = this.attachShadow({ mode: 'closed' });
31
26
  const template = document.createElement('template');
32
27
  template.innerHTML = `<style>
@@ -88,37 +83,25 @@ export class NeedleLogoElement extends HTMLElement {
88
83
  this.addEventListener("click", () => {
89
84
  globalThis.open("https://needle.tools", "_blank");
90
85
  });
91
- }
92
86
 
93
- ensureInitialized() {
94
- if (!this._didInitialize) {
95
- this._didInitialize = true;
96
- this.initializeDom();
97
- }
98
87
  }
99
88
 
100
89
  connectedCallback() {
101
- this.ensureInitialized();
102
- if (!this.wrapper) return;
103
90
  this.wrapper.setAttribute("title", "Made with Needle Engine");
104
91
  this.setAttribute("aria-label", "Needle Engine logo. Click to open the Needle Engine website.");
105
92
  }
106
93
 
107
- private _root!: ShadowRoot;
108
- private wrapper!: HTMLDivElement;
109
- private logoElement!: HTMLImageElement;
94
+ private readonly _root: ShadowRoot;
95
+ private readonly wrapper: HTMLDivElement;
96
+ private readonly logoElement: HTMLImageElement;
110
97
 
111
98
  /** Show or hide the logo element (used by the menu) */
112
99
  setLogoVisible(val: boolean) {
113
- this.ensureInitialized();
114
- if (!this.logoElement) return;
115
100
  this.logoElement.style.display = val ? "block" : "none";
116
101
  }
117
102
 
118
103
  /** Switch the logo between full and compact versions */
119
104
  setType(type: "full" | "compact") {
120
- this.ensureInitialized();
121
- if (!this.logoElement) return;
122
105
  if (type === "full") {
123
106
  this.logoElement.src = needleLogoSVG;
124
107
  this.logoElement.classList.remove("with-text");
@@ -302,7 +302,7 @@ export class NeedleSpatialMenu {
302
302
  // logoObject.position.y = 1;
303
303
  // this._context.scene.add(logoObject);
304
304
  const textureLoader = new TextureLoader();
305
- textureLoader.load("https://cdn.needle.tools/static/branding/poweredbyneedle.webp", (texture) => {
305
+ textureLoader.load("./include/needle/poweredbyneedle.webp", (texture) => {
306
306
  if (texture) {
307
307
  onClick.allowModifyUI = false;
308
308
  firstLabel.removeFromParent();
@@ -343,11 +343,7 @@ export class NeedleSpatialMenu {
343
343
 
344
344
  if (!fontFamily) {
345
345
  fontFamily = ThreeMeshUI.FontLibrary.addFontFamily(this.familyName);
346
- const normal = fontFamily.addVariant(
347
- "normal",
348
- "normal",
349
- "https://cdn.needle.tools/static/fonts/msdf/arial/arial-msdf.json",
350
- "https://cdn.needle.tools/static/fonts/msdf/arial/arial.png") as any as ThreeMeshUI.FontVariant;
346
+ const normal = fontFamily.addVariant("normal", "normal", "./include/needle/arial-msdf.json", "./include/needle/arial.png") as any as ThreeMeshUI.FontVariant;
351
347
  /** @ts-ignore */
352
348
  normal?.addEventListener('ready', () => {
353
349
  this.markDirty();
@@ -129,7 +129,6 @@ export class NeedleMenu {
129
129
 
130
130
  constructor(context: Context) {
131
131
  this._menu = NeedleMenuElement.getOrCreate(context.domElement, context);
132
- this._menu.ensureInitialized();
133
132
  this._context = context;
134
133
  this._spatialMenu = new NeedleSpatialMenu(context, this._menu);
135
134
  window.addEventListener("message", this.onPostMessage);
@@ -310,7 +309,8 @@ export class NeedleMenu {
310
309
  export class NeedleMenuElement extends HTMLElement {
311
310
 
312
311
  static create() {
313
- return document.createElement(elementName);
312
+ // https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement#is
313
+ return document.createElement(elementName, { is: elementName });
314
314
  }
315
315
 
316
316
  static getOrCreate(domElement: HTMLElement, context: Context) {
@@ -337,13 +337,9 @@ export class NeedleMenuElement extends HTMLElement {
337
337
 
338
338
  private _domElement: HTMLElement | null = null;
339
339
  private _context: Context | null = null;
340
- private _didInitialize = false;
341
340
 
342
341
  constructor() {
343
342
  super();
344
- }
345
-
346
- private initializeDom() {
347
343
 
348
344
  const template = document.createElement('template');
349
345
  // TODO: make host full size again and move the buttons to a wrapper so that we can later easily open e.g. foldouts/dropdowns / use the whole canvas space
@@ -799,7 +795,7 @@ export class NeedleMenuElement extends HTMLElement {
799
795
 
800
796
 
801
797
  let context = this._context;
802
- // we need to assign it in the timeout because the reference is set *after* the element is initialized
798
+ // we need to assign it in the timeout because the reference is set *after* the constructor did run
803
799
  setTimeout(() => context = this._context);
804
800
 
805
801
  // watch changes
@@ -868,21 +864,13 @@ export class NeedleMenuElement extends HTMLElement {
868
864
  }
869
865
  }
870
866
 
871
- ensureInitialized() {
872
- if (!this._didInitialize) {
873
- this._didInitialize = true;
874
- this.initializeDom();
875
- }
876
- }
877
-
878
867
  private _sizeChangeInterval;
879
868
 
880
869
  connectedCallback() {
881
- this.ensureInitialized();
882
870
  window.addEventListener("resize", this.handleSizeChange);
883
871
  this.handleMenuVisible();
884
872
  this._sizeChangeInterval = setInterval(() => this.handleSizeChange(undefined, false), 5000);
885
- // the dom element is set after initialization runs
873
+ // the dom element is set after the constructor runs
886
874
  setTimeout(() => {
887
875
  this._domElement?.addEventListener("resize", this.handleSizeChange);
888
876
  this._domElement?.addEventListener("click", this.#onClick);
@@ -970,19 +958,19 @@ export class NeedleMenuElement extends HTMLElement {
970
958
 
971
959
  // private _root: ShadowRoot | null = null;
972
960
  /** @private root container element inside shadow DOM */
973
- private root!: HTMLDivElement;
961
+ private readonly root: HTMLDivElement;
974
962
  /** @private wraps the whole content (internal layout) */
975
- private wrapper!: HTMLDivElement;
963
+ private readonly wrapper: HTMLDivElement;
976
964
  /** @private contains the buttons and dynamic elements */
977
- private options!: HTMLDivElement;
965
+ private readonly options: HTMLDivElement;
978
966
  /** @private contains options visible when in compact mode */
979
- private optionsCompactMode!: HTMLDivElement;
967
+ private readonly optionsCompactMode: HTMLDivElement;
980
968
  /** @private contains the needle-logo html element */
981
- private logoContainer!: HTMLDivElement;
969
+ private readonly logoContainer: HTMLDivElement;
982
970
  /** @private compact menu button element */
983
- private compactMenuButton!: HTMLButtonElement;
971
+ private readonly compactMenuButton: HTMLButtonElement;
984
972
  /** @private foldout container used in compact mode */
985
- private foldout!: HTMLDivElement;
973
+ private readonly foldout: HTMLDivElement;
986
974
 
987
975
 
988
976
  private readonly trackedElements: WeakSet<Node> = new WeakSet();
@@ -121,7 +121,7 @@ export class AROverlayHandler {
121
121
 
122
122
  const quitARSlot = document.createElement("slot");
123
123
  quitARSlot.style.display = "contents";
124
- quitARSlot.style.padding = "10px";
124
+ quitARSlot.style.padding = "10px";
125
125
  quitARSlot.setAttribute("name", "quit-ar");
126
126
  this.appendElement(quitARSlot, element);
127
127
  this._createdAROnlyElements.push(quitARSlot);
@@ -131,16 +131,7 @@ export class AROverlayHandler {
131
131
  // No default quit button in the top right corner in app clips
132
132
  // we provide one via the native UI
133
133
  if (DeviceUtilities.isNeedleAppClip()) {
134
-
135
- // quitARSlot.style.display = "none";
136
- globalThis["NEEDLE_ENGINE_APPCLIP_DISABLE_MENU"] = true;
137
-
138
- // respect the UI bar at the top of the screen and add some padding to the quit button container
139
- // @TODO: this should be done in CSS in one place and not here and in debug overlay
140
- const meta = document.querySelector('meta[name="viewport"]');
141
- if (meta && !meta.getAttribute("content")?.includes("viewport-fit=")) {
142
- meta.setAttribute("content", meta.getAttribute("content") + ",viewport-fit=cover");
143
- }
134
+ quitARSlot.style.display = "none";
144
135
  }
145
136
 
146
137
  // We want to search the document if there's a quit-ar button
@@ -164,8 +155,6 @@ export class AROverlayHandler {
164
155
  right: 0;
165
156
  z-index: 600;
166
157
  pointer-events: all;
167
- padding-top: env(safe-area-inset-top, 0px);
168
- padding-right: calc(env(safe-area-inset-right, 0px) + 10px);
169
158
  `;
170
159
  this.appendElement(fixedButtonContainer, quitARSlot);
171
160
 
@@ -168,30 +168,19 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
168
168
  */
169
169
  public get context() { return this._context; }
170
170
 
171
- private _context!: Context;
171
+ private _context: Context;
172
172
  private _overlay_ar: AROverlayHandler;
173
173
  private _loadingProgress01: number = 0;
174
174
  private _loadingView?: ILoadingViewHandler;
175
175
  private _previousSrc: string | null | string[] = null;
176
176
  /** @private set to true after <needle-engine> did load completely at least once. Set to false when < to false when <needle-engine> is removed from the document removed from the document */
177
177
  private _didFullyLoad: boolean = false;
178
- private _didInitialize = false;
179
178
 
180
179
  constructor() {
181
180
  super();
182
181
  this._overlay_ar = new AROverlayHandler();
183
182
  // TODO: do we want to rename this event?
184
183
  this.addEventListener("ready", this.onReady);
185
- }
186
-
187
- private ensureInitialized() {
188
- if (!this._didInitialize) {
189
- this._didInitialize = true;
190
- this.initializeDom();
191
- }
192
- }
193
-
194
- private initializeDom() {
195
184
 
196
185
  ensureFonts();
197
186
 
@@ -292,7 +281,6 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
292
281
  * @internal
293
282
  */
294
283
  async connectedCallback() {
295
- this.ensureInitialized();
296
284
  if (debug) {
297
285
  console.log("<needle-engine> connected");
298
286
  }
@@ -49,7 +49,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
49
49
  abstract activeSelf: boolean;
50
50
 
51
51
  /** @deprecated Use {@link addComponent} instead */
52
- // eslint-disable-next-line @typescript-eslint/no-deprecated
52
+ // eslint-disable-next-line deprecation/deprecation
53
53
  abstract addNewComponent<T extends IComponent>(type: ConstructorConcrete<T>, init?: ComponentInit<T>): T;
54
54
 
55
55
  /**
@@ -364,6 +364,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
364
364
  }
365
365
 
366
366
  /** @deprecated use `addComponent` */
367
+ // eslint-disable-next-line deprecation/deprecation
367
368
  public static addNewComponent<T extends IComponent>(go: IGameObject | Object3D, type: T | ConstructorConcrete<T>, init?: ComponentInit<T>, callAwake: boolean = true): T {
368
369
  return addComponent(go, type, init, { callAwake });
369
370
  }
@@ -1,13 +1,15 @@
1
- import { CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, Object3D, Texture, Vector3 } from "three";
1
+ import { Color, CubeReflectionMapping, CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, MeshBasicMaterial, MeshStandardMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
2
2
 
3
+ import { isDevEnvironment, showBalloonWarning } from "../engine/debug/index.js";
3
4
  import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
4
- import { loadPMREM } from "../engine/engine_pmrem.js";
5
5
  import { serializable } from "../engine/engine_serialization.js";
6
6
  import { Context } from "../engine/engine_setup.js";
7
+ import type { IRenderer } from "../engine/engine_types.js";
7
8
  import { getParam, resolveUrl } from "../engine/engine_utils.js";
8
9
  import { BoxHelperComponent } from "./BoxHelperComponent.js";
9
10
  import { Behaviour } from "./Component.js";
10
11
  import { EventList } from "./EventList.js";
12
+ import { loadPMREM } from "../engine/engine_pmrem.js";
11
13
 
12
14
  export const debug = getParam("debugreflectionprobe");
13
15
  const disable = getParam("noreflectionprobe");
@@ -40,11 +42,7 @@ const $reflectionProbeKey = Symbol("reflectionProbeKey");
40
42
  export class ReflectionProbe extends Behaviour {
41
43
 
42
44
  private static _probes: Map<Context, ReflectionProbe[]> = new Map();
43
-
44
-
45
- /**
46
- * Checks if the given material is currently using a reflection probe. This is determined by checking for an override on the material's "envMap" property, which is set by the Renderer component when applying a reflection probe.
47
- */
45
+
48
46
  static isUsingReflectionProbe(material: Material) {
49
47
  return !!(material as any)[$reflectionProbeKey];
50
48
  }
@@ -52,13 +50,8 @@ export class ReflectionProbe extends Behaviour {
52
50
 
53
51
  /**
54
52
  * Event invoked when a reflection probe is enabled. Used internally by Renderer components to update probes when they become active. Not recommended to call this directly in most cases.
55
- * @see {@link onDisabled} for the corresponding disable event.
56
53
  */
57
54
  static readonly onEnabled: EventList<ReflectionProbe> = new EventList();
58
- /**
59
- * Event invoked when a reflection probe is disabled. Used internally by Renderer components to update probes when they become inactive. Not recommended to call this directly in most cases.
60
- * @see {@link onEnabled} for the corresponding enable event.
61
- */
62
55
  static readonly onDisabled: EventList<ReflectionProbe> = new EventList();
63
56
 
64
57
  /**
@@ -97,14 +90,11 @@ export class ReflectionProbe extends Behaviour {
97
90
  return null;
98
91
  }
99
92
 
100
- private _texture!: Texture | null;
93
+ private _texture!: Texture;
101
94
  private _textureUrlInFlight?: string;
102
95
 
103
- /**
104
- * The cubemap or HDR texture used for reflections. Can be assigned directly or via a URL string. When assigning via URL, the texture will be loaded asynchronously and applied once ready.
105
- */
106
96
  @serializable([Texture, String])
107
- set texture(tex: Texture | null) {
97
+ set texture(tex: Texture) {
108
98
  if (this._texture === tex) return;
109
99
 
110
100
  if (typeof tex === "string") {
@@ -121,10 +111,7 @@ export class ReflectionProbe extends Behaviour {
121
111
  return;
122
112
  }
123
113
 
124
- // During deserialization / loading of the GLB the deserializer sets an empty DataTexture
125
- // But if the texture is serialized as a string (via Blender Reflection Probes) then the async loading above
126
- // Will abort IF textureInFlight is reset (here). That's why we do NOT reset textureInFlight during initialization (when __didAwake is false). Only after awake, when we are sure that the async loading is done, we reset the in-flight URL to allow new assignments.
127
- if(this.__didAwake) this._textureUrlInFlight = undefined;
114
+ this._textureUrlInFlight = undefined;
128
115
 
129
116
  this._texture = tex;
130
117
 
@@ -140,7 +127,7 @@ export class ReflectionProbe extends Behaviour {
140
127
  tex.needsUpdate = true;
141
128
  }
142
129
  }
143
- get texture(): Texture | null {
130
+ get texture(): Texture {
144
131
  return this._texture;
145
132
  }
146
133
 
@@ -178,7 +165,6 @@ export class ReflectionProbe extends Behaviour {
178
165
  ReflectionProbe._probes.get(this.context)?.push(this);
179
166
  }
180
167
 
181
- /** @internal */
182
168
  awake() {
183
169
  this._boxHelper = this.gameObject.addComponent(BoxHelperComponent) as BoxHelperComponent;
184
170
  this._boxHelper.updateBox(true);
@@ -192,24 +178,20 @@ export class ReflectionProbe extends Behaviour {
192
178
  }
193
179
  }
194
180
 
195
- /** @internal */
196
181
  onEnable(): void {
197
182
  ReflectionProbe.onEnabled?.invoke(this);
198
183
  }
199
184
 
200
- /** @internal */
201
185
  onDisable(): void {
202
186
  ReflectionProbe.onDisabled?.invoke(this);
203
187
  }
204
188
 
205
- /** @internal */
206
189
  start(): void {
207
190
  if (!this._texture) {
208
191
  console.warn(`[ReflectionProbe] Missing texture. Please assign a custom cubemap texture. To use reflection probes assign them to your renderer's "anchor" property.`);
209
192
  }
210
193
  }
211
194
 
212
- /** @internal */
213
195
  onDestroy() {
214
196
  const probes = ReflectionProbe._probes.get(this.context);
215
197
  if (probes) {
@@ -220,9 +202,6 @@ export class ReflectionProbe extends Behaviour {
220
202
  }
221
203
  }
222
204
 
223
- /**
224
- * Applies this reflection probe to the given object by setting material property overrides for "envMap", "envMapRotation", and "envMapIntensity". This is typically called by the Renderer component when determining which reflection probe to use for a given object.
225
- */
226
205
  apply(object: Object3D) {
227
206
  if (disable) return;
228
207
  if (!this.enabled) return;
@@ -239,9 +218,6 @@ export class ReflectionProbe extends Behaviour {
239
218
  propertyBlock.setOverride("envMapIntensity", intensity);
240
219
  }
241
220
 
242
- /**
243
- * Removes the reflection probe overrides from the given object. This is typically called by the Renderer component when an object is no longer influenced by this probe or when the probe is disabled.
244
- */
245
221
  unapply(obj: Object3D) {
246
222
  const block = MaterialPropertyBlock.get(obj);
247
223
  if (block) {
@@ -479,10 +479,8 @@ function tryParseMagicSkyboxName(str: string | null | undefined, environment: bo
479
479
  return useLowRes ? value.url_low : value.url;
480
480
  }
481
481
  else if (typeof str === "string" && str?.length && (isDevEnvironment() || debug)) {
482
- // Only warn if the string looks like it was meant to be a magic skybox name.
483
- // Strings that contain "/" or "." are paths or URLs, not magic names.
484
- const looksLikePath = str.includes("/") || str.includes(".");
485
- if(!looksLikePath) {
482
+ const noUrlOrFile = !str.startsWith("http") && !str.startsWith("file:") && !str.startsWith("blob:") && !str.startsWith("data:") && !str.startsWith("/")
483
+ if(noUrlOrFile) {
486
484
  console.warn(`RemoteSkybox: Unknown magic skybox name "${str}". Valid names are: ${Object.keys(MagicSkyboxNames).map(n => `"${n}"`).join(", ")}`);
487
485
  }
488
486
  }
@@ -6,11 +6,11 @@ import { SerializationContext } from "../../../engine/engine_serialization_core.
6
6
  import { serializable } from "../../../engine/engine_serialization_decorator.js";
7
7
  import { getWorldPosition } from "../../../engine/engine_three_utils.js";
8
8
  import { getParam } from "../../../engine/engine_utils.js";
9
- import GLTFMeshGPUInstancingExtension from '../../../engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js';
10
9
  import { RenderTextureWriter } from "../../../engine/export/gltf/Writers.js";
11
10
  import { shouldExport_HideFlags } from "../../../engine/export/utils.js";
12
11
  import { registerExportExtensions } from "../../../engine/extensions/index.js";
13
12
  import { NEEDLE_components } from "../../../engine/extensions/NEEDLE_components.js";
13
+ import GLTFMeshGPUInstancingExtension from '../../../include/three/EXT_mesh_gpu_instancing_exporter.js';
14
14
  import { BoxHelperComponent } from "../../BoxHelperComponent.js";
15
15
  import { Behaviour, GameObject } from "../../Component.js";
16
16
  import { Renderer } from "../../Renderer.js";
@@ -2457,7 +2457,7 @@ ${usedUVChannels.has(0) ? `
2457
2457
  def Shader "uvReader_st"
2458
2458
  {
2459
2459
  uniform token info:id = "UsdPrimvarReader_float2"
2460
- string inputs:varname = "st"
2460
+ token inputs:varname = "st"
2461
2461
  float2 inputs:fallback = (0.0, 0.0)
2462
2462
  float2 outputs:result
2463
2463
  }
@@ -2466,7 +2466,7 @@ ${usedUVChannels.has(1) ? `
2466
2466
  def Shader "uvReader_st1"
2467
2467
  {
2468
2468
  uniform token info:id = "UsdPrimvarReader_float2"
2469
- string inputs:varname = "st1"
2469
+ token inputs:varname = "st1"
2470
2470
  float2 inputs:fallback = (0.0, 0.0)
2471
2471
  float2 outputs:result
2472
2472
  }
@@ -740,7 +740,7 @@ export class USDZExporter extends Behaviour {
740
740
  }
741
741
  else if (sessionRoot) {
742
742
  arScale = sessionRoot.arScale;
743
- // eslint-disable-next-line @typescript-eslint/no-deprecated
743
+ // eslint-disable-next-line deprecation/deprecation
744
744
  _invertForward = sessionRoot.invertForward;
745
745
  }
746
746
 
@@ -62,9 +62,9 @@ export class PhysicsExtension implements IUSDExporterExtension {
62
62
  writer.appendLine(`double dynamicFriction = ${colliderSource.sharedMaterial?.dynamicFriction}`);
63
63
  if (mat && mat.bounciness !== undefined)
64
64
  writer.appendLine(`double restitution = ${colliderSource.sharedMaterial?.bounciness}`);
65
- // eslint-disable-next-line @typescript-eslint/no-deprecated
65
+ // eslint-disable-next-line deprecation/deprecation
66
66
  if (mat && mat.staticFriction !== undefined)
67
- // eslint-disable-next-line @typescript-eslint/no-deprecated
67
+ // eslint-disable-next-line deprecation/deprecation
68
68
  writer.appendLine(`double staticFriction = ${colliderSource.sharedMaterial?.staticFriction}`);
69
69
  writer.closeBlock( "}" );
70
70
  }