@needle-tools/engine 4.16.0-next.bc4d35d → 4.16.1-next.98e87e6

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 (100) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/dist/{needle-engine.bundle-DT0VwGmo.umd.cjs → needle-engine.bundle-B2rk-2Z5.umd.cjs} +108 -108
  3. package/dist/{needle-engine.bundle-KyGODqE9.js → needle-engine.bundle-DdPHeBrV.js} +2885 -2877
  4. package/dist/{needle-engine.bundle-Cqmarm0m.min.js → needle-engine.bundle-_tTBG92u.min.js} +104 -104
  5. package/dist/needle-engine.d.ts +9 -3
  6. package/dist/needle-engine.js +2 -2
  7. package/dist/needle-engine.min.js +1 -1
  8. package/dist/needle-engine.umd.cjs +1 -1
  9. package/lib/engine/engine_context.js +2 -0
  10. package/lib/engine/engine_context.js.map +1 -1
  11. package/lib/engine/webcomponents/logo-element.d.ts +1 -1
  12. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  13. package/lib/engine/webcomponents/needle-engine.d.ts +1 -1
  14. package/lib/engine/webcomponents/needle-engine.js +21 -23
  15. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  16. package/lib/engine-components/ReflectionProbe.d.ts +10 -3
  17. package/lib/engine-components/ReflectionProbe.js +34 -10
  18. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  19. package/package.json +7 -6
  20. package/plugins/next/next.d.ts +8 -0
  21. package/plugins/next/next.js +7 -6
  22. package/plugins/vite/ai.d.ts +17 -0
  23. package/plugins/vite/ai.js +2 -2
  24. package/plugins/vite/alias.d.ts +8 -0
  25. package/plugins/vite/alias.js +5 -2
  26. package/plugins/vite/asap.d.ts +7 -0
  27. package/plugins/vite/asap.js +3 -3
  28. package/plugins/vite/build-pipeline.d.ts +15 -0
  29. package/plugins/vite/build-pipeline.js +5 -6
  30. package/plugins/vite/build.d.ts +7 -0
  31. package/plugins/vite/build.js +5 -2
  32. package/plugins/vite/buildinfo.d.ts +7 -0
  33. package/plugins/vite/buildinfo.js +4 -2
  34. package/plugins/vite/config.d.ts +13 -0
  35. package/plugins/vite/config.js +1 -1
  36. package/plugins/vite/copyfiles.d.ts +7 -0
  37. package/plugins/vite/copyfiles.js +4 -2
  38. package/plugins/vite/custom-element-data.d.ts +25 -0
  39. package/plugins/vite/custom-element-data.js +2 -1
  40. package/plugins/vite/defines.d.ts +10 -0
  41. package/plugins/vite/defines.js +4 -3
  42. package/plugins/vite/dependencies.d.ts +21 -0
  43. package/plugins/vite/dependencies.js +3 -1
  44. package/plugins/vite/dependency-watcher.d.ts +11 -0
  45. package/plugins/vite/dependency-watcher.js +2 -1
  46. package/plugins/vite/drop-client.d.ts +1 -0
  47. package/plugins/vite/drop.d.ts +7 -0
  48. package/plugins/vite/drop.js +4 -4
  49. package/plugins/vite/editor-connection.d.ts +8 -0
  50. package/plugins/vite/editor-connection.js +6 -2
  51. package/plugins/vite/facebook-instant-games.d.ts +7 -0
  52. package/plugins/vite/facebook-instant-games.js +4 -2
  53. package/plugins/vite/gzip.d.ts +6 -0
  54. package/plugins/vite/gzip.js +5 -0
  55. package/plugins/vite/imports-logger.d.ts +13 -0
  56. package/plugins/vite/imports-logger.js +2 -1
  57. package/plugins/vite/index.d.ts +54 -0
  58. package/plugins/vite/index.js +16 -15
  59. package/plugins/vite/license.d.ts +7 -0
  60. package/plugins/vite/license.js +6 -6
  61. package/plugins/vite/local-files-analysis.d.ts +95 -0
  62. package/plugins/vite/local-files-analysis.js +2 -1
  63. package/plugins/vite/local-files-core.d.ts +51 -0
  64. package/plugins/vite/local-files-core.js +2 -2
  65. package/plugins/vite/local-files-internals.d.ts +3 -0
  66. package/plugins/vite/local-files-utils.d.ts +77 -0
  67. package/plugins/vite/local-files.d.ts +2 -0
  68. package/plugins/vite/logger.d.ts +8 -0
  69. package/plugins/vite/logger.js +1 -1
  70. package/plugins/vite/logging.d.ts +31 -0
  71. package/plugins/vite/meta.d.ts +7 -0
  72. package/plugins/vite/meta.js +4 -3
  73. package/plugins/vite/needle-app.d.ts +7 -0
  74. package/plugins/vite/needle-app.js +1 -1
  75. package/plugins/vite/npm.d.ts +4 -0
  76. package/plugins/vite/npm.js +1 -1
  77. package/plugins/vite/peer.d.ts +7 -0
  78. package/plugins/vite/peer.js +3 -1
  79. package/plugins/vite/poster-client.d.ts +1 -0
  80. package/plugins/vite/poster.d.ts +8 -0
  81. package/plugins/vite/poster.js +5 -2
  82. package/plugins/vite/pwa.d.ts +7 -0
  83. package/plugins/vite/pwa.js +4 -4
  84. package/plugins/vite/reload-client.d.ts +1 -0
  85. package/plugins/vite/reload.d.ts +7 -0
  86. package/plugins/vite/reload.js +7 -6
  87. package/plugins/vite/server.d.ts +7 -0
  88. package/plugins/vite/server.js +5 -5
  89. package/plugins/vite/transform-codegen.d.ts +8 -0
  90. package/plugins/vite/transform-codegen.js +6 -4
  91. package/plugins/vite/transform.d.ts +5 -0
  92. package/plugins/vite/transform.js +1 -1
  93. package/plugins/vite/vite-4.4-hack.d.ts +8 -0
  94. package/plugins/vite/vite-4.4-hack.js +1 -1
  95. package/src/engine/engine_context.ts +1 -0
  96. package/src/engine/webcomponents/logo-element.ts +1 -1
  97. package/src/engine/webcomponents/needle-engine.ts +41 -47
  98. package/src/engine-components/ReflectionProbe.ts +38 -11
  99. package/plugins/types/next.d.ts +0 -3
  100. package/plugins/types/vite.d.ts +0 -14
@@ -10,9 +10,12 @@ export function getPosterPath() {
10
10
  }
11
11
 
12
12
  /**
13
+ * @param {"build" | "serve"} command
14
+ * @param {import('../types/needleConfig').needleMeta | null | undefined} config
13
15
  * @param {import('../types').userSettings} userSettings
16
+ * @returns {import('vite').Plugin | undefined}
14
17
  */
15
- export const needlePoster = (command, config, userSettings) => {
18
+ export function needlePoster(command, config, userSettings) {
16
19
  // only relevant for local development
17
20
  if (command === 'build') return [];
18
21
 
@@ -76,4 +79,4 @@ export const needlePoster = (command, config, userSettings) => {
76
79
  },
77
80
  },
78
81
  }
79
- };
82
+ }
@@ -0,0 +1,7 @@
1
+ /** Provides reasonable defaults for a PWA manifest and workbox settings.
2
+ * @param {"build" | "serve"} command
3
+ * @param {import("../types/needleConfig").needleMeta | null} config
4
+ * @param {import('../types').userSettings} userSettings
5
+ * @returns {import('vite').Plugin | undefined}
6
+ */
7
+ export function needlePWA(command: "build" | "serve", config: import("../types/needleConfig").needleMeta | null, userSettings: import("../types").userSettings): import("vite").Plugin | undefined;
@@ -8,12 +8,12 @@ import { needleLog } from './logging.js';
8
8
  const pwaErrorWithInstructions = "It seems that you're trying to build a PWA using 'vite-plugin-pwa'!\nNeedle can manage PWA settings for you – just pass the same 'pwaOptions' to the needlePlugins and VitePWA plugins:\n\n1. Install the vite PWA plugin: npm install vite-plugin-pwa --save-dev\n\n2. Then update your vite.config.js:\n\n import { VitePWA } from 'vite-plugin-pwa';\n ...\n needlePlugins(command, needleConfig, { pwa: pwaOptions }),\n VitePWA(pwaOptions),\n\nIf you want to manage PWA building yourself and skip this check, please pass '{ pwa: false }' to needlePlugins.";
9
9
 
10
10
  /** Provides reasonable defaults for a PWA manifest and workbox settings.
11
- * @param {string} command
12
- * @param {import('../types').userSettings} userSettings
11
+ * @param {"build" | "serve"} command
13
12
  * @param {import("../types/needleConfig").needleMeta | null} config
14
- * @returns {import('vite').Plugin | void}
13
+ * @param {import('../types').userSettings} userSettings
14
+ * @returns {import('vite').Plugin | undefined}
15
15
  */
16
- export const needlePWA = (command, config, userSettings) => {
16
+ export function needlePWA(command, config, userSettings) {
17
17
  // @ts-ignore // TODO correctly type the userSettings.pwaOptions object
18
18
  /** @type {import("vite-plugin-pwa").VitePWAOptions | false} */
19
19
  const pwaOptions = userSettings.pwa === true
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @param {"build" | "serve"} command
3
+ * @param {import('../types/needleConfig').needleMeta | null} config
4
+ * @param {import('../types').userSettings} userSettings
5
+ * @returns {import('vite').Plugin | undefined}
6
+ */
7
+ export function needleReload(command: "build" | "serve", config: import("../types/needleConfig").needleMeta | null, userSettings: import("../types").userSettings): import("vite").Plugin | undefined;
@@ -16,10 +16,11 @@ let assetsDirectory = "";
16
16
 
17
17
  /**
18
18
  * @param {"build" | "serve"} command
19
- * @param {import('../types').userSettings | null} config
19
+ * @param {import('../types/needleConfig').needleMeta | null} config
20
20
  * @param {import('../types').userSettings} userSettings
21
+ * @returns {import('vite').Plugin | undefined}
21
22
  */
22
- export const needleReload = (command, config, userSettings) => {
23
+ export function needleReload(command, config, userSettings) {
23
24
  if (command === "build") return undefined;
24
25
 
25
26
  if (userSettings?.noReload === true) return undefined;
@@ -31,7 +32,7 @@ export const needleReload = (command, config, userSettings) => {
31
32
  isUpdatingConfig = true;
32
33
  const res = await loadConfig();
33
34
  isUpdatingConfig = false;
34
- if (res) config = /** @type {import('../types').userSettings} */ (res);
35
+ if (res) config = /** @type {import('../types/needleConfig').needleMeta} */ (res);
35
36
  }
36
37
 
37
38
  const projectConfig = tryLoadProjectConfig();
@@ -61,7 +62,7 @@ export const needleReload = (command, config, userSettings) => {
61
62
  if (userSettings?.debug === true)
62
63
  setTimeout(() => needleLog("needle-reload", "Updated server ignore patterns: " + JSON.stringify(config.server?.watch?.ignored)), 100);
63
64
  },
64
- /** @param {{file: string, server: import('vite').ViteDevServer, modules: unknown[], read: (file?: string) => Promise<string>, buildDirectory?: string}} args */
65
+ /** @param {import('vite').HmrContext & {buildDirectory?: string}} args */
65
66
  handleHotUpdate(args) {
66
67
  args.buildDirectory = buildDirectory;
67
68
  return handleReload(args);
@@ -118,7 +119,7 @@ function notifyClientWillReload(server, file) {
118
119
  }
119
120
 
120
121
  /**
121
- * @param {{file: string, server: import('vite').ViteDevServer, modules: unknown[], read: (file?: string) => Promise<string>, buildDirectory?: string}} param0
122
+ * @param {import('vite').HmrContext & {buildDirectory?: string}} param0
122
123
  * @returns {Promise<any>}
123
124
  */
124
125
  async function handleReload({ file, server, modules: _modules, read, buildDirectory }) {
@@ -255,7 +256,7 @@ function getFileNameLog(file) {
255
256
  const hashes = new Map();
256
257
  const hash256 = crypto.createHash('sha256');
257
258
 
258
- /** @param {string} file @param {(file?: string) => Promise<string>} read @returns {Promise<boolean>} */
259
+ /** @param {string} file @param {(file?: string) => string | Promise<string>} read @returns {Promise<boolean>} */
259
260
  async function testIfFileContentChanged(file, read) {
260
261
  let content = await read(file);
261
262
  content = removeVersionQueryArgument(content);
@@ -0,0 +1,7 @@
1
+ /** Can open the network server in the browser.
2
+ * @param {"build" | "serve"} command
3
+ * @param {import('../types').needleMeta | null} config
4
+ * @param {import('../types').userSettings} userSettings
5
+ * @returns {import('vite').Plugin}
6
+ */
7
+ export function needleServer(command: "build" | "serve", config: import("../types").needleMeta | null, userSettings: import("../types").userSettings): import("vite").Plugin;
@@ -1,10 +1,10 @@
1
- /**
2
- * Can open the network server in the browser
3
- * @param {string} command
1
+ /** Can open the network server in the browser.
2
+ * @param {"build" | "serve"} command
4
3
  * @param {import('../types').needleMeta | null} config
5
4
  * @param {import('../types').userSettings} userSettings
5
+ * @returns {import('vite').Plugin}
6
6
  */
7
- export const needleServer = (command, config, userSettings) => {
7
+ export function needleServer(command, config, userSettings) {
8
8
 
9
9
  const shouldOpenBrowser = userSettings.openBrowser === true;
10
10
 
@@ -64,4 +64,4 @@ export const needleServer = (command, config, userSettings) => {
64
64
  }
65
65
  },
66
66
  }
67
- };
67
+ }
@@ -0,0 +1,8 @@
1
+ /** Modify the glb load path in codegen files.
2
+ * This is necessary if the assets directory is not the default (changed by the user in needle.config.json).
3
+ * @param {"build" | "serve"} command
4
+ * @param {import('../types/needleConfig').needleMeta | null | undefined} config
5
+ * @param {import('../types').userSettings} userSettings
6
+ * @returns {import('vite').Plugin | undefined}
7
+ */
8
+ export function needleTransformCodegen(command: "build" | "serve", config: import("../types/needleConfig").needleMeta | null | undefined, userSettings: import("../types").userSettings): import("vite").Plugin | undefined;
@@ -1,11 +1,13 @@
1
1
  import { builtAssetsDirectory, tryLoadProjectConfig } from './config.js';
2
2
 
3
- /**
4
- * modify the glb load path in codegen files
5
- * this is necessary if the assets directory is not the default (changed by the user in needle.config.json)
3
+ /** Modify the glb load path in codegen files.
4
+ * This is necessary if the assets directory is not the default (changed by the user in needle.config.json).
5
+ * @param {"build" | "serve"} command
6
+ * @param {import('../types/needleConfig').needleMeta | null | undefined} config
6
7
  * @param {import('../types').userSettings} userSettings
8
+ * @returns {import('vite').Plugin | undefined}
7
9
  */
8
- export const needleTransformCodegen = (command, config, userSettings) => {
10
+ export function needleTransformCodegen(command, config, userSettings) {
9
11
 
10
12
  if (config?.noCodegenTransform === true || userSettings?.noCodegenTransform === true) {
11
13
  return;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param {import('../types').userSettings} userSettings
3
+ * @returns {import('vite').Plugin[]}
4
+ */
5
+ export function needleTransformCode(command: any, config: any, userSettings: import("../types").userSettings): import("vite").Plugin[];
@@ -5,7 +5,7 @@
5
5
  * @param {import('../types').userSettings} userSettings
6
6
  * @returns {import('vite').Plugin[]}
7
7
  */
8
- export const needleTransformCode = (command, config, userSettings) => {
8
+ export function needleTransformCode(command, config, userSettings) {
9
9
 
10
10
  return [
11
11
  {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Make sure we dont have vite 4.4.x installed when needle engine is used locally
3
+ * @param {import('../types').userSettings} userSettings
4
+ */
5
+ export function vite_4_4_hack(command: any, config: any, userSettings: import("../types").userSettings): {
6
+ name: string;
7
+ configureServer(server: any): Promise<void>;
8
+ };
@@ -6,7 +6,7 @@ import { execSync } from 'child_process';
6
6
  * Make sure we dont have vite 4.4.x installed when needle engine is used locally
7
7
  * @param {import('../types').userSettings} userSettings
8
8
  */
9
- export const vite_4_4_hack = (command, config, userSettings) => {
9
+ export function vite_4_4_hack(command, config, userSettings) {
10
10
  if (userSettings.vite44Hack === false) return;
11
11
  return {
12
12
  name: "needle-vite-4.4-hack",
@@ -613,6 +613,7 @@ export class Context implements IContext {
613
613
  console.log("Using canvas from shadow root", canvas);
614
614
  }
615
615
  }
616
+ else if(debug) console.warn("No canvas found in shadow root, creating new canvas. This may cause input events to not work correctly. To fix this, make sure to use the canvas provided by the Needle Engine Web Component (e.g. by using context.createNewRenderer() without parameters or passing the canvas from the shadow root explicitly).")
616
617
  }
617
618
  if (debug) console.log("Using Renderer Parameters:", params, this.domElement)
618
619
 
@@ -90,7 +90,7 @@ export class NeedleLogoElement extends HTMLElement {
90
90
  });
91
91
  }
92
92
 
93
- ensureInitialized() {
93
+ private ensureInitialized() {
94
94
  if (!this._didInitialize) {
95
95
  this._didInitialize = true;
96
96
  this.initializeDom();
@@ -14,7 +14,7 @@ import { getParam } from "../engine_utils.js";
14
14
  import { RGBAColor } from "../js-extensions/RGBAColor.js";
15
15
  import { ensureFonts } from "./fonts.js";
16
16
  import { arContainerClassName, AROverlayHandler } from "./needle-engine.ar-overlay.js";
17
- import type { registerObservableAttribute} from "./needle-engine.extras.js";
17
+ import type { registerObservableAttribute } from "./needle-engine.extras.js";
18
18
  import { calculateProgress01, EngineLoadingView, type ILoadingViewHandler } from "./needle-engine.loading.js";
19
19
 
20
20
  declare global {
@@ -169,7 +169,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
169
169
  public get context() { return this._context; }
170
170
 
171
171
  private _context!: Context;
172
- private _overlay_ar: AROverlayHandler;
172
+ private _overlay_ar!: AROverlayHandler;
173
173
  private _loadingProgress01: number = 0;
174
174
  private _loadingView?: ILoadingViewHandler;
175
175
  private _previousSrc: string | null | string[] = null;
@@ -179,28 +179,8 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
179
179
 
180
180
  constructor() {
181
181
  super();
182
- // TODO: do we want to rename this event?
183
- this.addEventListener("ready", this.onReady);
184
- this._overlay_ar = new AROverlayHandler();
185
- this._context = new Context({ domElement: this });
186
- }
187
-
188
- private ensureInitialized() {
189
- if (!this._didInitialize) {
190
- this._didInitialize = true;
191
- this.initializeDom();
192
- }
193
- }
194
-
195
- private initializeDom() {
196
-
197
- ensureFonts();
198
-
199
- const shadow = this.attachShadow({ mode: 'open', delegatesFocus: true });
200
- this.setAttribute("role", "application");
201
- this.setAttribute("aria-label", "Needle Engine 3D scene");
182
+ this.attachShadow({ mode: 'open', delegatesFocus: true });
202
183
  const template = document.createElement('template');
203
- // #region CSS
204
184
  template.innerHTML = `<style>
205
185
  @import url('https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght@8..144,100..1000&display=swap');
206
186
 
@@ -266,7 +246,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
266
246
  }
267
247
  :host .quit-ar-button {
268
248
  position: absolute;
269
- // top: env(titlebar-area-y); /** this doesnt work **/
249
+ /** top: env(titlebar-area-y); this doesnt work **/
270
250
  top: 60px; /** camera access needs a bit more space **/
271
251
  right: 20px;
272
252
  z-index: 9999;
@@ -279,25 +259,36 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
279
259
  <slot class="overlay-content" style="display: contents;"></slot>
280
260
  </div>
281
261
  `;
282
- // #endregion
283
262
 
284
- shadow.appendChild(template.content.cloneNode(true));
263
+ this.shadowRoot!.appendChild(template.content.cloneNode(true));
285
264
 
265
+ // TODO: do we want to rename this event?
266
+ this.addEventListener("ready", this.onReady);
286
267
  this.addEventListener("error", this.onError);
287
268
  }
288
269
 
270
+ private ensureInitialized() {
271
+ if (!this._didInitialize) {
272
+ this._didInitialize = true;
273
+ this.initializeDom();
274
+ }
275
+ }
276
+
277
+ // #region Init DOM
278
+ private initializeDom() {
279
+ ensureFonts();
280
+ this.setAttribute("role", "application");
281
+ this.setAttribute("aria-label", "Needle Engine 3D scene");
282
+ }
283
+
289
284
 
290
285
  /**
291
286
  * @internal
292
287
  */
293
- async connectedCallback() {
294
-
295
- if (debug) {
296
- console.log("<needle-engine> connected");
297
- }
298
-
299
- this.ensureInitialized();
288
+ connectedCallback() {
289
+ if (debug) console.log("<needle-engine> connected");
300
290
 
291
+ this.ensureInitialized();
301
292
  this.setPublicKey();
302
293
  this.setVersion();
303
294
 
@@ -306,9 +297,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
306
297
  this.setAttribute("tabindex", "0");
307
298
 
308
299
 
300
+ this._overlay_ar = new AROverlayHandler();
301
+ this._context ??= new Context({ domElement: this }); // we might have one already if onLoad is running
309
302
  this.addEventListener("xr-session-started", this.onXRSessionStarted);
310
303
  this.onSetupDesktop();
311
304
 
305
+
306
+
312
307
  if (!this.getAttribute("src")) {
313
308
  const global = (globalThis as any)["needle:codegen_files"] as unknown as string;
314
309
  if (debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
@@ -455,6 +450,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
455
450
  private async onLoad() {
456
451
 
457
452
  if (!this.isConnected) return;
453
+
458
454
  if (!this._context) {
459
455
  if (debug) console.warn("Create new context");
460
456
  this._context = new Context({ domElement: this });
@@ -489,7 +485,6 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
489
485
  this.classList.add("loading");
490
486
 
491
487
 
492
-
493
488
  // Loading start events
494
489
  const allowOverridingDefaultLoading = hasCommercialLicense();
495
490
  // default loading can be overriden by calling preventDefault in the onload start event
@@ -914,7 +909,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
914
909
  setAttribute(name: 'ktx2DecoderPath', value: string): void;
915
910
  /** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
916
911
  setAttribute(name: 'keep-alive', value: 'true' | 'false'): void;
917
-
912
+
918
913
  /** @private Public key used for licensing and feature gating. */
919
914
  setAttribute(name: 'public-key', value: string): void;
920
915
  /** @private Engine version string — usually set by the build/runtime. */
@@ -922,7 +917,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
922
917
 
923
918
  // LoadingAttributes
924
919
  // ...
925
-
920
+
926
921
  // SkyboxAttributes
927
922
  /** URL to .exr, .hdr, .png, .jpg to be used as skybox */
928
923
  setAttribute(name: 'background-image', value: string): void;
@@ -943,7 +938,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
943
938
  * @example "background-color='#ff0000'" will set the background color to red.
944
939
  */
945
940
  setAttribute(name: 'background-color', value: string): void;
946
-
941
+
947
942
  // RenderingAttributes
948
943
  /** Enable/disable renderer canvas transparency. */
949
944
  setAttribute(name: 'transparent', value: 'true' | 'false'): void;
@@ -966,9 +961,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
966
961
  setAttribute(name: "autoplay", value: 'true' | 'false'): void;
967
962
  /** @private Used for switching the scene in SceneSwitcher */
968
963
  setAttribute(name: 'scene', value: string): void;
969
-
964
+
970
965
  // setAttribute(name: 'loadstart', value: string): void;
971
-
966
+
972
967
  /** @private Experimental.*/
973
968
  setAttribute(name: 'loading-blur', value: 'true' | 'false'): void;
974
969
  /** @private */
@@ -981,9 +976,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
981
976
  /** Generic typed setter for known Needle Engine attributes */
982
977
  // Comment out to see errors inside NE for undocumented attributes
983
978
  // setAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T, value: NeedleEngineAttributes[T]): void;
984
-
979
+
985
980
  setAttribute(qualifiedName: ({} & string), value: string): void;
986
-
981
+
987
982
  // The ones we're using internally:
988
983
  /*
989
984
  setAttribute(name: "tabindex", value: string): void;
@@ -1012,7 +1007,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1012
1007
  getAttribute(name: 'ktx2DecoderPath'): string | null;
1013
1008
  /** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
1014
1009
  getAttribute(name: 'keep-alive'): string | null;
1015
-
1010
+
1016
1011
  /** @private Public key used for licensing and feature gating. */
1017
1012
  getAttribute(name: 'public-key'): string | null;
1018
1013
  /** @private Engine version string — usually set by the build/runtime. */
@@ -1083,13 +1078,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1083
1078
  /** Typed getter for known NeedleEngine attribute names; returns the typed shape declared in NeedleEngineAttributes or null. */
1084
1079
  // getAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T): NeedleEngineAttributes[T] | null;
1085
1080
  getAttribute(qualifiedName: ({} & string)): string | null;
1086
-
1081
+
1087
1082
  // The ones we're using interally:
1088
1083
  /*
1089
1084
  getAttribute(name: "autostart"): string | null;
1090
1085
  getAttribute(name: "tabindex"): string | null;
1091
1086
  */
1092
-
1087
+
1093
1088
  getAttribute(qualifiedName: string): string | null {
1094
1089
  return super.getAttribute(qualifiedName);
1095
1090
  }
@@ -1127,7 +1122,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1127
1122
  addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
1128
1123
  // This would be better but doesn't completely solve it
1129
1124
  // addEventListener(type: ({} & string), listener: any, options?: boolean | AddEventListenerOptions): void;
1130
-
1125
+
1131
1126
  // The ones we're using interally:
1132
1127
  /*
1133
1128
  addEventListener(type: "error", listener: (ev: ErrorEvent) => void, options?: boolean | AddEventListenerOptions): void;
@@ -1136,8 +1131,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1136
1131
  addEventListener(type: "drop", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
1137
1132
  addEventListener(type: "dragover", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
1138
1133
  */
1139
- addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void
1140
- {
1134
+ addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void {
1141
1135
  return super.addEventListener(type, listener as EventListenerOrEventListenerObject, options);
1142
1136
  }
1143
1137
  }
@@ -1,4 +1,4 @@
1
- import { CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, Object3D, Texture, Vector3 } from "three";
1
+ import { Box3, Color, CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, LineSegments, Material, Object3D, Quaternion, Texture, Vector3 } from "three";
2
2
 
3
3
  import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
4
4
  import { loadPMREM } from "../engine/engine_pmrem.js";
@@ -8,6 +8,8 @@ import { getParam, resolveUrl } from "../engine/engine_utils.js";
8
8
  import { BoxHelperComponent } from "./BoxHelperComponent.js";
9
9
  import { Behaviour } from "./Component.js";
10
10
  import { EventList } from "./EventList.js";
11
+ import { getBoundingBox, getWorldPosition } from "../engine/engine_three_utils.js";
12
+ import { CreateWireCube } from "../engine/engine_gizmos.js";
11
13
 
12
14
  export const debug = getParam("debugreflectionprobe");
13
15
  const disable = getParam("noreflectionprobe");
@@ -40,8 +42,11 @@ 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
+ /** The bounding box for this component */
46
+ private box: Box3 | null = null;
47
+ private static testBox: Box3 = new Box3();
48
+ private static _identityRotation: Quaternion = new Quaternion();
49
+
45
50
  /**
46
51
  * 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
52
  */
@@ -151,23 +156,33 @@ export class ReflectionProbe extends Behaviour {
151
156
  * Defines the center and size of the reflection probe's influence area.
152
157
  */
153
158
  @serializable(Vector3)
154
- center?: Vector3;
159
+ center: Vector3 = new Vector3();
155
160
 
156
161
  /**
157
162
  * Defines the size of the reflection probe's influence area. Objects within this box will be affected by the probe's reflections.
158
163
  */
159
164
  @serializable(Vector3)
160
- size?: Vector3;
165
+ size: Vector3 = new Vector3(1, 1, 1);
161
166
 
162
167
  /**
163
168
  * Workaround for lightmap. Compensates for the fact that lightmaps are pre-multiplied by intensity, while reflection probes are not. This means that if you use both lightmaps and reflection probes, you may need to adjust this value to get the correct balance between them. The default value of `Math.PI` is a good starting point for most cases, but you may need to tweak it based on your specific lighting setup and artistic needs.
164
169
  */
165
170
  __lightmapIntensityScale: boolean = true;
166
171
 
167
- private _boxHelper?: BoxHelperComponent;
168
172
 
169
173
  private isInBox(obj: Object3D) {
170
- return this._boxHelper?.isInBox(obj);
174
+
175
+ this.box ??= new Box3();
176
+ this.box!.setFromCenterAndSize(this.gameObject.worldPosition.add(this.center), this.gameObject.worldScale.multiply(this.size));
177
+
178
+ getBoundingBox([obj], undefined, undefined, ReflectionProbe.testBox);
179
+
180
+ if (ReflectionProbe.testBox.isEmpty()) {
181
+ return this.box.containsPoint(obj.worldPosition);
182
+ }
183
+ else {
184
+ return this.box?.intersectsBox(ReflectionProbe.testBox);
185
+ }
171
186
  }
172
187
 
173
188
  constructor() {
@@ -178,12 +193,15 @@ export class ReflectionProbe extends Behaviour {
178
193
  ReflectionProbe._probes.get(this.context)?.push(this);
179
194
  }
180
195
 
196
+ private _gizmo: LineSegments | null = null;
197
+ private _color: Color | null = null;
198
+
181
199
  /** @internal */
182
200
  awake() {
183
- this._boxHelper = this.gameObject.addComponent(BoxHelperComponent) as BoxHelperComponent;
184
- this._boxHelper.updateBox(true);
185
- if (debug)
186
- this._boxHelper.showHelper(0x555500, true);
201
+ if (debug) {
202
+ this._gizmo = CreateWireCube(0x555500);
203
+ this.gameObject.add(this._gizmo);
204
+ }
187
205
 
188
206
  if (this._texture) {
189
207
  this._texture.mapping = EquirectangularReflectionMapping;
@@ -192,6 +210,15 @@ export class ReflectionProbe extends Behaviour {
192
210
  }
193
211
  }
194
212
 
213
+ /** @internal */
214
+ update(): void {
215
+ if (this._gizmo) {
216
+ if (this.center) this._gizmo.position.copy(this.center);
217
+ if (this.size) this._gizmo.scale.copy(this.size);
218
+ this._gizmo.worldQuaternion = ReflectionProbe._identityRotation;
219
+ }
220
+ }
221
+
195
222
  /** @internal */
196
223
  onEnable(): void {
197
224
  ReflectionProbe.onEnabled?.invoke(this);
@@ -1,3 +0,0 @@
1
- import { userSettings } from './userconfig.js';
2
-
3
- export declare function needleNext(nextConfig?: import('next').NextConfig, userSettings?: userSettings): Promise<import('next').NextConfig>;
@@ -1,14 +0,0 @@
1
- import { needleConfig, needleMeta } from "./needleConfig.d.ts";
2
- import { userSettings } from "./userconfig.d.ts";
3
-
4
- export declare function needlePlugins(command: import("vite").ConfigEnv["command"], meta?: needleMeta | null, userSettings?: userSettings): Promise<any>;
5
-
6
- /**
7
- * Loads the generated needle meta file
8
- */
9
- export declare function loadConfig(path: string | null = null): Promise<needleMeta | null>;
10
-
11
- /**
12
- * Returns true if the project is configured to use gzip compression
13
- */
14
- export declare function useGzip(config?: needleConfig): boolean;