@needle-tools/engine 4.16.0-next.1243700 → 4.16.0-next.34e2848

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.
@@ -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 {
@@ -168,23 +168,33 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
168
168
  */
169
169
  public get context() { return this._context; }
170
170
 
171
- private _context: Context;
172
- private _overlay_ar: AROverlayHandler;
171
+ private _context!: Context;
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;
178
179
 
179
180
  constructor() {
180
181
  super();
181
- this._overlay_ar = new AROverlayHandler();
182
182
  // TODO: do we want to rename this event?
183
183
  this.addEventListener("ready", this.onReady);
184
+ }
185
+
186
+ private ensureInitialized() {
187
+ if (!this._didInitialize) {
188
+ this._didInitialize = true;
189
+ this.initializeDom();
190
+ }
191
+ }
192
+
193
+ private initializeDom() {
184
194
 
185
195
  ensureFonts();
186
196
 
187
- this.attachShadow({ mode: 'open', delegatesFocus: true });
197
+ const shadow = this.attachShadow({ mode: 'open', delegatesFocus: true });
188
198
  this.setAttribute("role", "application");
189
199
  this.setAttribute("aria-label", "Needle Engine 3D scene");
190
200
  const template = document.createElement('template');
@@ -269,10 +279,8 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
269
279
  `;
270
280
  // #endregion
271
281
 
272
- if (this.shadowRoot)
273
- this.shadowRoot.appendChild(template.content.cloneNode(true));
282
+ shadow.appendChild(template.content.cloneNode(true));
274
283
 
275
- this._context = new Context({ domElement: this });
276
284
  this.addEventListener("error", this.onError);
277
285
  }
278
286
 
@@ -280,11 +288,10 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
280
288
  /**
281
289
  * @internal
282
290
  */
283
- async connectedCallback() {
284
- if (debug) {
285
- console.log("<needle-engine> connected");
286
- }
291
+ connectedCallback() {
292
+ if (debug) console.log("<needle-engine> connected");
287
293
 
294
+ this.ensureInitialized();
288
295
  this.setPublicKey();
289
296
  this.setVersion();
290
297
 
@@ -293,9 +300,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
293
300
  this.setAttribute("tabindex", "0");
294
301
 
295
302
 
303
+ this._overlay_ar = new AROverlayHandler();
304
+ this._context ??= new Context({ domElement: this }); // we might have one already if onLoad is running
296
305
  this.addEventListener("xr-session-started", this.onXRSessionStarted);
297
306
  this.onSetupDesktop();
298
307
 
308
+
309
+
299
310
  if (!this.getAttribute("src")) {
300
311
  const global = (globalThis as any)["needle:codegen_files"] as unknown as string;
301
312
  if (debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
@@ -442,6 +453,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
442
453
  private async onLoad() {
443
454
 
444
455
  if (!this.isConnected) return;
456
+
445
457
  if (!this._context) {
446
458
  if (debug) console.warn("Create new context");
447
459
  this._context = new Context({ domElement: this });
@@ -901,7 +913,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
901
913
  setAttribute(name: 'ktx2DecoderPath', value: string): void;
902
914
  /** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
903
915
  setAttribute(name: 'keep-alive', value: 'true' | 'false'): void;
904
-
916
+
905
917
  /** @private Public key used for licensing and feature gating. */
906
918
  setAttribute(name: 'public-key', value: string): void;
907
919
  /** @private Engine version string — usually set by the build/runtime. */
@@ -909,7 +921,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
909
921
 
910
922
  // LoadingAttributes
911
923
  // ...
912
-
924
+
913
925
  // SkyboxAttributes
914
926
  /** URL to .exr, .hdr, .png, .jpg to be used as skybox */
915
927
  setAttribute(name: 'background-image', value: string): void;
@@ -930,7 +942,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
930
942
  * @example "background-color='#ff0000'" will set the background color to red.
931
943
  */
932
944
  setAttribute(name: 'background-color', value: string): void;
933
-
945
+
934
946
  // RenderingAttributes
935
947
  /** Enable/disable renderer canvas transparency. */
936
948
  setAttribute(name: 'transparent', value: 'true' | 'false'): void;
@@ -953,9 +965,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
953
965
  setAttribute(name: "autoplay", value: 'true' | 'false'): void;
954
966
  /** @private Used for switching the scene in SceneSwitcher */
955
967
  setAttribute(name: 'scene', value: string): void;
956
-
968
+
957
969
  // setAttribute(name: 'loadstart', value: string): void;
958
-
970
+
959
971
  /** @private Experimental.*/
960
972
  setAttribute(name: 'loading-blur', value: 'true' | 'false'): void;
961
973
  /** @private */
@@ -968,9 +980,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
968
980
  /** Generic typed setter for known Needle Engine attributes */
969
981
  // Comment out to see errors inside NE for undocumented attributes
970
982
  // setAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T, value: NeedleEngineAttributes[T]): void;
971
-
983
+
972
984
  setAttribute(qualifiedName: ({} & string), value: string): void;
973
-
985
+
974
986
  // The ones we're using internally:
975
987
  /*
976
988
  setAttribute(name: "tabindex", value: string): void;
@@ -999,7 +1011,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
999
1011
  getAttribute(name: 'ktx2DecoderPath'): string | null;
1000
1012
  /** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
1001
1013
  getAttribute(name: 'keep-alive'): string | null;
1002
-
1014
+
1003
1015
  /** @private Public key used for licensing and feature gating. */
1004
1016
  getAttribute(name: 'public-key'): string | null;
1005
1017
  /** @private Engine version string — usually set by the build/runtime. */
@@ -1070,13 +1082,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1070
1082
  /** Typed getter for known NeedleEngine attribute names; returns the typed shape declared in NeedleEngineAttributes or null. */
1071
1083
  // getAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T): NeedleEngineAttributes[T] | null;
1072
1084
  getAttribute(qualifiedName: ({} & string)): string | null;
1073
-
1085
+
1074
1086
  // The ones we're using interally:
1075
1087
  /*
1076
1088
  getAttribute(name: "autostart"): string | null;
1077
1089
  getAttribute(name: "tabindex"): string | null;
1078
1090
  */
1079
-
1091
+
1080
1092
  getAttribute(qualifiedName: string): string | null {
1081
1093
  return super.getAttribute(qualifiedName);
1082
1094
  }
@@ -1114,7 +1126,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1114
1126
  addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
1115
1127
  // This would be better but doesn't completely solve it
1116
1128
  // addEventListener(type: ({} & string), listener: any, options?: boolean | AddEventListenerOptions): void;
1117
-
1129
+
1118
1130
  // The ones we're using interally:
1119
1131
  /*
1120
1132
  addEventListener(type: "error", listener: (ev: ErrorEvent) => void, options?: boolean | AddEventListenerOptions): void;
@@ -1123,8 +1135,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
1123
1135
  addEventListener(type: "drop", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
1124
1136
  addEventListener(type: "dragover", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
1125
1137
  */
1126
- addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void
1127
- {
1138
+ addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void {
1128
1139
  return super.addEventListener(type, listener as EventListenerOrEventListenerObject, options);
1129
1140
  }
1130
1141
  }