@needle-tools/engine 4.16.0-next.1243700 → 4.16.0-next.1c21170
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{needle-engine.bundle-BxcA4M_7.js → needle-engine.bundle-BJCM8ElV.js} +630 -609
- package/dist/{needle-engine.bundle-DfedaKz7.umd.cjs → needle-engine.bundle-BKDgRygk.umd.cjs} +21 -21
- package/dist/{needle-engine.bundle-4BVa8WTG.min.js → needle-engine.bundle-DKqwSAXw.min.js} +20 -20
- package/dist/needle-engine.d.ts +3 -0
- package/dist/needle-engine.js +2 -2
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/engine_context.js +2 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/webcomponents/logo-element.d.ts +6 -3
- package/lib/engine/webcomponents/logo-element.js +18 -0
- package/lib/engine/webcomponents/logo-element.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +10 -7
- package/lib/engine/webcomponents/needle menu/needle-menu.js +13 -2
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +4 -1
- package/lib/engine/webcomponents/needle-engine.js +22 -15
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_context.ts +1 -0
- package/src/engine/webcomponents/logo-element.ts +20 -3
- package/src/engine/webcomponents/needle menu/needle-menu.ts +22 -9
- package/src/engine/webcomponents/needle-engine.ts +42 -35
|
@@ -129,6 +129,7 @@ export class NeedleMenu {
|
|
|
129
129
|
|
|
130
130
|
constructor(context: Context) {
|
|
131
131
|
this._menu = NeedleMenuElement.getOrCreate(context.domElement, context);
|
|
132
|
+
this._menu.ensureInitialized();
|
|
132
133
|
this._context = context;
|
|
133
134
|
this._spatialMenu = new NeedleSpatialMenu(context, this._menu);
|
|
134
135
|
window.addEventListener("message", this.onPostMessage);
|
|
@@ -337,9 +338,13 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
337
338
|
|
|
338
339
|
private _domElement: HTMLElement | null = null;
|
|
339
340
|
private _context: Context | null = null;
|
|
341
|
+
private _didInitialize = false;
|
|
340
342
|
|
|
341
343
|
constructor() {
|
|
342
344
|
super();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
private initializeDom() {
|
|
343
348
|
|
|
344
349
|
const template = document.createElement('template');
|
|
345
350
|
// 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
|
|
@@ -793,7 +798,7 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
793
798
|
|
|
794
799
|
|
|
795
800
|
let context = this._context;
|
|
796
|
-
// we need to assign it in the timeout because the reference is set *after* the
|
|
801
|
+
// we need to assign it in the timeout because the reference is set *after* the element is initialized
|
|
797
802
|
setTimeout(() => context = this._context);
|
|
798
803
|
|
|
799
804
|
// watch changes
|
|
@@ -862,13 +867,21 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
862
867
|
}
|
|
863
868
|
}
|
|
864
869
|
|
|
870
|
+
ensureInitialized() {
|
|
871
|
+
if (!this._didInitialize) {
|
|
872
|
+
this._didInitialize = true;
|
|
873
|
+
this.initializeDom();
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
865
877
|
private _sizeChangeInterval;
|
|
866
878
|
|
|
867
879
|
connectedCallback() {
|
|
880
|
+
this.ensureInitialized();
|
|
868
881
|
window.addEventListener("resize", this.handleSizeChange);
|
|
869
882
|
this.handleMenuVisible();
|
|
870
883
|
this._sizeChangeInterval = setInterval(() => this.handleSizeChange(undefined, false), 5000);
|
|
871
|
-
// the dom element is set after
|
|
884
|
+
// the dom element is set after initialization runs
|
|
872
885
|
setTimeout(() => {
|
|
873
886
|
this._domElement?.addEventListener("resize", this.handleSizeChange);
|
|
874
887
|
this._domElement?.addEventListener("click", this.#onClick);
|
|
@@ -956,19 +969,19 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
956
969
|
|
|
957
970
|
// private _root: ShadowRoot | null = null;
|
|
958
971
|
/** @private root container element inside shadow DOM */
|
|
959
|
-
private
|
|
972
|
+
private root!: HTMLDivElement;
|
|
960
973
|
/** @private wraps the whole content (internal layout) */
|
|
961
|
-
private
|
|
974
|
+
private wrapper!: HTMLDivElement;
|
|
962
975
|
/** @private contains the buttons and dynamic elements */
|
|
963
|
-
private
|
|
976
|
+
private options!: HTMLDivElement;
|
|
964
977
|
/** @private contains options visible when in compact mode */
|
|
965
|
-
private
|
|
978
|
+
private optionsCompactMode!: HTMLDivElement;
|
|
966
979
|
/** @private contains the needle-logo html element */
|
|
967
|
-
private
|
|
980
|
+
private logoContainer!: HTMLDivElement;
|
|
968
981
|
/** @private compact menu button element */
|
|
969
|
-
private
|
|
982
|
+
private compactMenuButton!: HTMLButtonElement;
|
|
970
983
|
/** @private foldout container used in compact mode */
|
|
971
|
-
private
|
|
984
|
+
private foldout!: HTMLDivElement;
|
|
972
985
|
|
|
973
986
|
|
|
974
987
|
private readonly trackedElements: WeakSet<Node> = new WeakSet();
|
|
@@ -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,27 +168,19 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
168
168
|
*/
|
|
169
169
|
public get context() { return this._context; }
|
|
170
170
|
|
|
171
|
-
private _context
|
|
172
|
-
private _overlay_ar
|
|
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
|
-
// TODO: do we want to rename this event?
|
|
183
|
-
this.addEventListener("ready", this.onReady);
|
|
184
|
-
|
|
185
|
-
ensureFonts();
|
|
186
|
-
|
|
187
182
|
this.attachShadow({ mode: 'open', delegatesFocus: true });
|
|
188
|
-
this.setAttribute("role", "application");
|
|
189
|
-
this.setAttribute("aria-label", "Needle Engine 3D scene");
|
|
190
183
|
const template = document.createElement('template');
|
|
191
|
-
// #region CSS
|
|
192
184
|
template.innerHTML = `<style>
|
|
193
185
|
@import url('https://fonts.googleapis.com/css2?family=Roboto+Flex:opsz,wght@8..144,100..1000&display=swap');
|
|
194
186
|
|
|
@@ -254,7 +246,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
254
246
|
}
|
|
255
247
|
:host .quit-ar-button {
|
|
256
248
|
position: absolute;
|
|
257
|
-
|
|
249
|
+
/** top: env(titlebar-area-y); this doesnt work **/
|
|
258
250
|
top: 60px; /** camera access needs a bit more space **/
|
|
259
251
|
right: 20px;
|
|
260
252
|
z-index: 9999;
|
|
@@ -267,24 +259,36 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
267
259
|
<slot class="overlay-content" style="display: contents;"></slot>
|
|
268
260
|
</div>
|
|
269
261
|
`;
|
|
270
|
-
// #endregion
|
|
271
262
|
|
|
272
|
-
|
|
273
|
-
this.shadowRoot.appendChild(template.content.cloneNode(true));
|
|
263
|
+
this.shadowRoot!.appendChild(template.content.cloneNode(true));
|
|
274
264
|
|
|
275
|
-
|
|
265
|
+
// TODO: do we want to rename this event?
|
|
266
|
+
this.addEventListener("ready", this.onReady);
|
|
276
267
|
this.addEventListener("error", this.onError);
|
|
277
268
|
}
|
|
278
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
|
+
|
|
279
284
|
|
|
280
285
|
/**
|
|
281
286
|
* @internal
|
|
282
287
|
*/
|
|
283
|
-
|
|
284
|
-
if (debug)
|
|
285
|
-
console.log("<needle-engine> connected");
|
|
286
|
-
}
|
|
288
|
+
connectedCallback() {
|
|
289
|
+
if (debug) console.log("<needle-engine> connected");
|
|
287
290
|
|
|
291
|
+
this.ensureInitialized();
|
|
288
292
|
this.setPublicKey();
|
|
289
293
|
this.setVersion();
|
|
290
294
|
|
|
@@ -293,9 +297,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
293
297
|
this.setAttribute("tabindex", "0");
|
|
294
298
|
|
|
295
299
|
|
|
300
|
+
this._overlay_ar = new AROverlayHandler();
|
|
301
|
+
this._context ??= new Context({ domElement: this }); // we might have one already if onLoad is running
|
|
296
302
|
this.addEventListener("xr-session-started", this.onXRSessionStarted);
|
|
297
303
|
this.onSetupDesktop();
|
|
298
304
|
|
|
305
|
+
|
|
306
|
+
|
|
299
307
|
if (!this.getAttribute("src")) {
|
|
300
308
|
const global = (globalThis as any)["needle:codegen_files"] as unknown as string;
|
|
301
309
|
if (debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
|
|
@@ -442,6 +450,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
442
450
|
private async onLoad() {
|
|
443
451
|
|
|
444
452
|
if (!this.isConnected) return;
|
|
453
|
+
|
|
445
454
|
if (!this._context) {
|
|
446
455
|
if (debug) console.warn("Create new context");
|
|
447
456
|
this._context = new Context({ domElement: this });
|
|
@@ -476,7 +485,6 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
476
485
|
this.classList.add("loading");
|
|
477
486
|
|
|
478
487
|
|
|
479
|
-
|
|
480
488
|
// Loading start events
|
|
481
489
|
const allowOverridingDefaultLoading = hasCommercialLicense();
|
|
482
490
|
// default loading can be overriden by calling preventDefault in the onload start event
|
|
@@ -901,7 +909,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
901
909
|
setAttribute(name: 'ktx2DecoderPath', value: string): void;
|
|
902
910
|
/** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
|
|
903
911
|
setAttribute(name: 'keep-alive', value: 'true' | 'false'): void;
|
|
904
|
-
|
|
912
|
+
|
|
905
913
|
/** @private Public key used for licensing and feature gating. */
|
|
906
914
|
setAttribute(name: 'public-key', value: string): void;
|
|
907
915
|
/** @private Engine version string — usually set by the build/runtime. */
|
|
@@ -909,7 +917,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
909
917
|
|
|
910
918
|
// LoadingAttributes
|
|
911
919
|
// ...
|
|
912
|
-
|
|
920
|
+
|
|
913
921
|
// SkyboxAttributes
|
|
914
922
|
/** URL to .exr, .hdr, .png, .jpg to be used as skybox */
|
|
915
923
|
setAttribute(name: 'background-image', value: string): void;
|
|
@@ -930,7 +938,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
930
938
|
* @example "background-color='#ff0000'" will set the background color to red.
|
|
931
939
|
*/
|
|
932
940
|
setAttribute(name: 'background-color', value: string): void;
|
|
933
|
-
|
|
941
|
+
|
|
934
942
|
// RenderingAttributes
|
|
935
943
|
/** Enable/disable renderer canvas transparency. */
|
|
936
944
|
setAttribute(name: 'transparent', value: 'true' | 'false'): void;
|
|
@@ -953,9 +961,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
953
961
|
setAttribute(name: "autoplay", value: 'true' | 'false'): void;
|
|
954
962
|
/** @private Used for switching the scene in SceneSwitcher */
|
|
955
963
|
setAttribute(name: 'scene', value: string): void;
|
|
956
|
-
|
|
964
|
+
|
|
957
965
|
// setAttribute(name: 'loadstart', value: string): void;
|
|
958
|
-
|
|
966
|
+
|
|
959
967
|
/** @private Experimental.*/
|
|
960
968
|
setAttribute(name: 'loading-blur', value: 'true' | 'false'): void;
|
|
961
969
|
/** @private */
|
|
@@ -968,9 +976,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
968
976
|
/** Generic typed setter for known Needle Engine attributes */
|
|
969
977
|
// Comment out to see errors inside NE for undocumented attributes
|
|
970
978
|
// setAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T, value: NeedleEngineAttributes[T]): void;
|
|
971
|
-
|
|
979
|
+
|
|
972
980
|
setAttribute(qualifiedName: ({} & string), value: string): void;
|
|
973
|
-
|
|
981
|
+
|
|
974
982
|
// The ones we're using internally:
|
|
975
983
|
/*
|
|
976
984
|
setAttribute(name: "tabindex", value: string): void;
|
|
@@ -999,7 +1007,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
999
1007
|
getAttribute(name: 'ktx2DecoderPath'): string | null;
|
|
1000
1008
|
/** Prevent Needle Engine context from being disposed when the element is removed from the DOM */
|
|
1001
1009
|
getAttribute(name: 'keep-alive'): string | null;
|
|
1002
|
-
|
|
1010
|
+
|
|
1003
1011
|
/** @private Public key used for licensing and feature gating. */
|
|
1004
1012
|
getAttribute(name: 'public-key'): string | null;
|
|
1005
1013
|
/** @private Engine version string — usually set by the build/runtime. */
|
|
@@ -1070,13 +1078,13 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
1070
1078
|
/** Typed getter for known NeedleEngine attribute names; returns the typed shape declared in NeedleEngineAttributes or null. */
|
|
1071
1079
|
// getAttribute<T extends keyof NeedleEngineAttributes>(qualifiedName: T): NeedleEngineAttributes[T] | null;
|
|
1072
1080
|
getAttribute(qualifiedName: ({} & string)): string | null;
|
|
1073
|
-
|
|
1081
|
+
|
|
1074
1082
|
// The ones we're using interally:
|
|
1075
1083
|
/*
|
|
1076
1084
|
getAttribute(name: "autostart"): string | null;
|
|
1077
1085
|
getAttribute(name: "tabindex"): string | null;
|
|
1078
1086
|
*/
|
|
1079
|
-
|
|
1087
|
+
|
|
1080
1088
|
getAttribute(qualifiedName: string): string | null {
|
|
1081
1089
|
return super.getAttribute(qualifiedName);
|
|
1082
1090
|
}
|
|
@@ -1114,7 +1122,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
1114
1122
|
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
1115
1123
|
// This would be better but doesn't completely solve it
|
|
1116
1124
|
// addEventListener(type: ({} & string), listener: any, options?: boolean | AddEventListenerOptions): void;
|
|
1117
|
-
|
|
1125
|
+
|
|
1118
1126
|
// The ones we're using interally:
|
|
1119
1127
|
/*
|
|
1120
1128
|
addEventListener(type: "error", listener: (ev: ErrorEvent) => void, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -1123,8 +1131,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
1123
1131
|
addEventListener(type: "drop", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
|
|
1124
1132
|
addEventListener(type: "dragover", listener: (ev: DragEvent) => void, options?: boolean | AddEventListenerOptions): void;
|
|
1125
1133
|
*/
|
|
1126
|
-
addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void
|
|
1127
|
-
{
|
|
1134
|
+
addEventListener(type: string, listener: any, options?: boolean | AddEventListenerOptions): void {
|
|
1128
1135
|
return super.addEventListener(type, listener as EventListenerOrEventListenerObject, options);
|
|
1129
1136
|
}
|
|
1130
1137
|
}
|