@needle-tools/engine 4.16.4-next.25d6ead → 4.16.4-next.2cea5b7
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/CHANGELOG.md +5 -0
- package/dist/{gltf-progressive-LOFTyzy4.umd.cjs → gltf-progressive-BacJPTD6.umd.cjs} +8 -8
- package/dist/{gltf-progressive-DQa78GTA.min.js → gltf-progressive-BmXoz_HR.min.js} +8 -8
- package/dist/{gltf-progressive-_wvokUUu.js → gltf-progressive-CzxjNmG6.js} +116 -107
- package/dist/{needle-engine.bundle-CAIr8Hz9.umd.cjs → needle-engine.bundle-9ZlmXJ92.umd.cjs} +141 -141
- package/dist/{needle-engine.bundle-CC-oMhHW.js → needle-engine.bundle-B48_Odba.js} +5912 -5898
- package/dist/{needle-engine.bundle-Cmi3snfO.min.js → needle-engine.bundle-BLua7xvv.min.js} +142 -142
- package/dist/needle-engine.d.ts +15 -4
- package/dist/needle-engine.js +3 -3
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/lib/engine/debug/debug.d.ts +4 -1
- package/lib/engine/debug/debug.js +25 -1
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.js +1 -1
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_components.js +3 -6
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_lods.d.ts +9 -1
- package/lib/engine/engine_lods.js +9 -1
- package/lib/engine/engine_lods.js.map +1 -1
- package/lib/engine/engine_mainloop_utils.js +49 -60
- package/lib/engine/engine_mainloop_utils.js.map +1 -1
- package/lib/engine/engine_three_utils.js +7 -13
- package/lib/engine/engine_three_utils.js.map +1 -1
- package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +1 -1
- package/lib/engine/webcomponents/WebXRButtons.js +13 -11
- package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
- package/lib/engine/webcomponents/buttons.js +4 -4
- package/lib/engine/webcomponents/buttons.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js +8 -3
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +6 -2
- package/lib/engine/webcomponents/needle-engine.js +56 -41
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine-components/AnimatorController.d.ts +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +0 -7
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/timeline/TimelineTracks.d.ts +1 -1
- package/lib/engine-components/timeline/TimelineTracks.js +2 -4
- package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
- package/package.json +4 -6
- package/src/engine/debug/debug.ts +26 -1
- package/src/engine/debug/debug_spatial_console.ts +1 -1
- package/src/engine/engine_components.ts +3 -6
- package/src/engine/engine_lods.ts +10 -2
- package/src/engine/engine_mainloop_utils.ts +54 -62
- package/src/engine/engine_three_utils.ts +7 -15
- package/src/engine/extensions/NEEDLE_animator_controller_model.ts +1 -1
- package/src/engine/webcomponents/WebXRButtons.ts +13 -12
- package/src/engine/webcomponents/buttons.ts +4 -4
- package/src/engine/webcomponents/needle menu/needle-menu.ts +7 -3
- package/src/engine/webcomponents/needle-engine.ts +62 -47
- package/src/engine-components/AnimatorController.ts +1 -1
- package/src/engine-components/export/usdz/USDZExporter.ts +0 -8
- package/src/engine-components/timeline/TimelineTracks.ts +2 -6
- package/lib/engine/debug/debug_environment.d.ts +0 -4
- package/lib/engine/debug/debug_environment.js +0 -26
- package/lib/engine/debug/debug_environment.js.map +0 -1
- package/lib/engine/webcomponents/needle menu/menu-priority.d.ts +0 -10
- package/lib/engine/webcomponents/needle menu/menu-priority.js +0 -21
- package/lib/engine/webcomponents/needle menu/menu-priority.js.map +0 -1
- package/lib/engine/webcomponents/quicklook-handler.d.ts +0 -29
- package/lib/engine/webcomponents/quicklook-handler.js +0 -21
- package/lib/engine/webcomponents/quicklook-handler.js.map +0 -1
- package/src/engine/debug/debug_environment.ts +0 -26
- package/src/engine/webcomponents/needle menu/menu-priority.ts +0 -20
- package/src/engine/webcomponents/quicklook-handler.ts +0 -37
|
@@ -586,17 +586,12 @@ export class Graphics {
|
|
|
586
586
|
this.scene.children.length = 0;
|
|
587
587
|
this.scene.add(mesh);
|
|
588
588
|
|
|
589
|
-
// Save state
|
|
590
589
|
const renderTarget = renderer.getRenderTarget();
|
|
591
|
-
const gl = renderer.getContext();
|
|
592
|
-
const depthTestEnabled = gl.getParameter(gl.DEPTH_TEST);
|
|
593
|
-
const depthWriteMask = gl.getParameter(gl.DEPTH_WRITEMASK);
|
|
594
|
-
const depthFunc = gl.getParameter(gl.DEPTH_FUNC);
|
|
595
|
-
|
|
596
590
|
|
|
597
591
|
// Set state
|
|
598
|
-
|
|
599
|
-
|
|
592
|
+
const gl = renderer.getContext();
|
|
593
|
+
if (depthTest) gl.enable(gl.DEPTH_TEST);
|
|
594
|
+
else gl.disable(gl.DEPTH_TEST);
|
|
600
595
|
renderer.state.buffers.depth.setMask(depthWrite);
|
|
601
596
|
|
|
602
597
|
renderer.setClearColor(new Color(0, 0, 0), 0);
|
|
@@ -608,13 +603,10 @@ export class Graphics {
|
|
|
608
603
|
renderer.clear();
|
|
609
604
|
renderer.render(this.scene, this.perspectiveCam);
|
|
610
605
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
depthBuffer.setTest(depthTestEnabled);
|
|
616
|
-
depthBuffer.setMask(depthWriteMask);
|
|
617
|
-
depthBuffer.setFunc(depthFunc);
|
|
606
|
+
// Restore defaults (not using gl.getParameter to save/restore — it causes a synchronous GPU-CPU stall)
|
|
607
|
+
renderer.setRenderTarget(renderTarget);
|
|
608
|
+
gl.enable(gl.DEPTH_TEST);
|
|
609
|
+
renderer.state.buffers.depth.setMask(true);
|
|
618
610
|
}
|
|
619
611
|
|
|
620
612
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AnimationAction, AnimationClip, MathUtils, Object3D } from "three"
|
|
2
2
|
|
|
3
3
|
import { InstantiateIdProvider } from "../../engine/engine_networking_instantiate.js";
|
|
4
|
-
import
|
|
4
|
+
import { Animator } from "../../engine-components/Animator.js";
|
|
5
5
|
import { Context } from "../engine_setup.js";
|
|
6
6
|
|
|
7
7
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { USDZExporter } from "../../engine-components/export/usdz/USDZExporter.js";
|
|
1
2
|
import { isDevEnvironment, showBalloonMessage } from "../debug/index.js";
|
|
3
|
+
import { findObjectOfType } from "../engine_components.js";
|
|
2
4
|
import { Context } from "../engine_setup.js";
|
|
3
5
|
import { DeviceUtilities } from "../engine_utils.js";
|
|
4
6
|
import { NeedleXRSession } from "../engine_xr.js";
|
|
@@ -6,7 +8,6 @@ import { onXRSessionEnd, onXRSessionStart } from "../xr/events.js";
|
|
|
6
8
|
import { ButtonsFactory } from "./buttons.js";
|
|
7
9
|
import { getIconElement } from "./icons.js";
|
|
8
10
|
import { NeedleMenu } from "./needle menu/needle-menu.js";
|
|
9
|
-
import { getOrCreateQuicklookHandler,type IQuicklookHandler } from "./quicklook-handler.js";
|
|
10
11
|
|
|
11
12
|
// TODO: move these buttons into their own web components so their logic is encapsulated (e.g. the CSS animation when a xr session is requested)
|
|
12
13
|
|
|
@@ -75,22 +76,22 @@ export class WebXRButtonFactory {
|
|
|
75
76
|
NeedleMenu.setElementPriority(button, quicklookButtonPriority);
|
|
76
77
|
|
|
77
78
|
let createdExporter = false;
|
|
78
|
-
let
|
|
79
|
+
let usdzExporter: USDZExporter | null = null;
|
|
79
80
|
button.addEventListener("click", () => {
|
|
80
|
-
|
|
81
|
+
usdzExporter = findObjectOfType(USDZExporter);
|
|
81
82
|
|
|
82
|
-
if
|
|
83
|
-
|
|
84
|
-
createdExporter =
|
|
83
|
+
// if the scene doesnt have an USDZExporter component, create one
|
|
84
|
+
if (!usdzExporter) {
|
|
85
|
+
createdExporter = true;
|
|
86
|
+
usdzExporter = new USDZExporter();
|
|
85
87
|
}
|
|
88
|
+
// if we have created a USDZExporter
|
|
89
|
+
if (createdExporter)
|
|
90
|
+
usdzExporter.objectToExport = Context.Current.scene;
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
if (createdExporter && quicklookHandler)
|
|
89
|
-
quicklookHandler.objectToExport = Context.Current.scene;
|
|
90
|
-
|
|
91
|
-
if (quicklookHandler) {
|
|
92
|
+
if (usdzExporter) {
|
|
92
93
|
button.classList.add("this-mode-is-requested");
|
|
93
|
-
|
|
94
|
+
usdzExporter.exportAndOpen().then(() => {
|
|
94
95
|
button.classList.remove("this-mode-is-requested");
|
|
95
96
|
}).catch(err => {
|
|
96
97
|
button.classList.remove("this-mode-is-requested");
|
|
@@ -3,7 +3,7 @@ import { IContext } from "../engine_types.js";
|
|
|
3
3
|
import { generateQRCode } from "../engine_utils_qrcode.js";
|
|
4
4
|
import { onXRSessionEnd, onXRSessionStart } from "../xr/events.js";
|
|
5
5
|
import { getIconElement } from "./icons.js";
|
|
6
|
-
import {
|
|
6
|
+
import { NeedleMenu } from "./needle menu/needle-menu.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Use the ButtonsFactory to create buttons with icons and functionality
|
|
@@ -67,7 +67,7 @@ export class ButtonsFactory {
|
|
|
67
67
|
this._fullscreenButton = button;
|
|
68
68
|
button.classList.add("fullscreen-button");
|
|
69
69
|
button.title = "Click to enter fullscreen mode";
|
|
70
|
-
setElementPriority(button, 3);
|
|
70
|
+
NeedleMenu.setElementPriority(button, 3);
|
|
71
71
|
const enterFullscreenIcon = getIconElement("fullscreen");
|
|
72
72
|
const exitFullscreenIcon = getIconElement("fullscreen_exit");
|
|
73
73
|
button.appendChild(enterFullscreenIcon);
|
|
@@ -119,7 +119,7 @@ export class ButtonsFactory {
|
|
|
119
119
|
const muteIcon = getIconElement("volume_off");
|
|
120
120
|
const unmuteIcon = getIconElement("volume_up");
|
|
121
121
|
|
|
122
|
-
setElementPriority(button, 1);
|
|
122
|
+
NeedleMenu.setElementPriority(button, 1);
|
|
123
123
|
|
|
124
124
|
// save state in session storage (this needs consent)
|
|
125
125
|
// if (sessionStorage.getItem("muted") === "true") {
|
|
@@ -191,7 +191,7 @@ export class ButtonsFactory {
|
|
|
191
191
|
qrCodeButton.prepend(getIconElement("qr_code"));
|
|
192
192
|
qrCodeButton.title = "Scan this QR code with your phone to open this page";
|
|
193
193
|
this.hideElementDuringXRSession(qrCodeButton);
|
|
194
|
-
setElementPriority(this._qrButton, 20);
|
|
194
|
+
NeedleMenu.setElementPriority(this._qrButton, 20);
|
|
195
195
|
|
|
196
196
|
const qrCodeContainer = document.createElement("div");
|
|
197
197
|
qrCodeContainer.style.cssText = `
|
|
@@ -8,7 +8,6 @@ import { ButtonsFactory } from "../buttons.js";
|
|
|
8
8
|
import { ensureFonts, iconFontUrl, loadFont } from "../fonts.js";
|
|
9
9
|
import { getIconElement } from "../icons.js";
|
|
10
10
|
import { NeedleLogoElement } from "../logo-element.js";
|
|
11
|
-
import { getElementPriority, setElementPriority as _setElementPriority } from "./menu-priority.js";
|
|
12
11
|
import { NeedleSpatialMenu } from "./needle-menu-spatial.js";
|
|
13
12
|
|
|
14
13
|
declare global {
|
|
@@ -112,11 +111,16 @@ export declare type ButtonInfo = {
|
|
|
112
111
|
export class NeedleMenu {
|
|
113
112
|
|
|
114
113
|
static setElementPriority(button: HTMLElement, priority: number) {
|
|
115
|
-
|
|
114
|
+
button.setAttribute("priority", String(priority));
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
static getElementPriority(button: HTMLElement): number | undefined {
|
|
119
|
-
|
|
118
|
+
const priority = button.getAttribute("priority");
|
|
119
|
+
if (priority) {
|
|
120
|
+
const val = Number.parseFloat(priority);
|
|
121
|
+
if (!Number.isNaN(val)) return val;
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
120
124
|
}
|
|
121
125
|
|
|
122
126
|
private readonly _context: Context;
|
|
@@ -168,7 +168,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
168
168
|
*/
|
|
169
169
|
public get context() { return this._context; }
|
|
170
170
|
|
|
171
|
-
private _context
|
|
171
|
+
private _context?: Context;
|
|
172
172
|
private _overlay_ar!: AROverlayHandler;
|
|
173
173
|
private _loadingProgress01: number = 0;
|
|
174
174
|
private _loadingView?: ILoadingViewHandler;
|
|
@@ -298,12 +298,10 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
298
298
|
|
|
299
299
|
|
|
300
300
|
this._overlay_ar = new AROverlayHandler();
|
|
301
|
-
this.
|
|
301
|
+
this.getOrCreateContext();
|
|
302
302
|
this.addEventListener("xr-session-started", this.onXRSessionStarted);
|
|
303
303
|
this.onSetupDesktop();
|
|
304
304
|
|
|
305
|
-
|
|
306
|
-
|
|
307
305
|
if (!this.getAttribute("src")) {
|
|
308
306
|
const global = (globalThis as any)["needle:codegen_files"] as unknown as string;
|
|
309
307
|
if (debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
|
|
@@ -418,18 +416,23 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
418
416
|
case "focus-rect":
|
|
419
417
|
{
|
|
420
418
|
const focus_rect = this.getAttribute("focus-rect") as HTMLElement | string | null;
|
|
421
|
-
if (focus_rect
|
|
419
|
+
if (focus_rect) {
|
|
420
|
+
const context = this.getOrCreateContext();
|
|
421
|
+
|
|
422
422
|
if (focus_rect === null) {
|
|
423
|
-
|
|
423
|
+
context.setCameraFocusRect(null);
|
|
424
424
|
}
|
|
425
425
|
else if (typeof focus_rect === "string" && focus_rect.length > 0) {
|
|
426
426
|
const element = document.querySelector(focus_rect);
|
|
427
|
-
|
|
427
|
+
if (!element) console.warn(`No element found for focus-rect selector: ${focus_rect}`);
|
|
428
|
+
context.setCameraFocusRect(element instanceof HTMLElement ? element : null);
|
|
428
429
|
}
|
|
429
430
|
else if (focus_rect instanceof HTMLElement) {
|
|
430
|
-
|
|
431
|
+
context.setCameraFocusRect(focus_rect);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
console.warn("Invalid focus-rect value. Expected a CSS selector string or an HTMLElement.", focus_rect);
|
|
431
435
|
}
|
|
432
|
-
|
|
433
436
|
}
|
|
434
437
|
}
|
|
435
438
|
break;
|
|
@@ -447,19 +450,22 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
447
450
|
private _lastSourceFiles: Array<string> | null = null;
|
|
448
451
|
private _createContextPromise: Promise<boolean> | null = null;
|
|
449
452
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
453
|
+
/**
|
|
454
|
+
* Check if we have a context. If not a new one is created.
|
|
455
|
+
*/
|
|
456
|
+
private getOrCreateContext() {
|
|
454
457
|
if (!this._context) {
|
|
455
458
|
if (debug) console.warn("Create new context");
|
|
456
459
|
this._context = new Context({ domElement: this });
|
|
457
460
|
}
|
|
461
|
+
return this._context;
|
|
462
|
+
}
|
|
458
463
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
464
|
+
private async onLoad() {
|
|
465
|
+
|
|
466
|
+
if (!this.isConnected) return;
|
|
467
|
+
|
|
468
|
+
const context = this.getOrCreateContext();
|
|
463
469
|
|
|
464
470
|
const filesToLoad = this.getSourceFiles();
|
|
465
471
|
if (!this.checkIfSourceHasChanged(filesToLoad, this._lastSourceFiles)) {
|
|
@@ -477,7 +483,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
477
483
|
|
|
478
484
|
if (filesToLoad === null || filesToLoad === undefined || filesToLoad.length <= 0) {
|
|
479
485
|
if (debug) console.warn("Clear scene", filesToLoad);
|
|
480
|
-
|
|
486
|
+
context.clear();
|
|
481
487
|
if (loadId !== this._loadId) return;
|
|
482
488
|
}
|
|
483
489
|
|
|
@@ -491,7 +497,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
491
497
|
this.ensureLoadStartIsRegistered();
|
|
492
498
|
let useDefaultLoading = this.dispatchEvent(new CustomEvent("loadstart", {
|
|
493
499
|
detail: {
|
|
494
|
-
context:
|
|
500
|
+
context: context,
|
|
495
501
|
alias: alias
|
|
496
502
|
},
|
|
497
503
|
cancelable: true
|
|
@@ -581,9 +587,9 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
581
587
|
|
|
582
588
|
const currentHash = this.getAttribute("hash");
|
|
583
589
|
if (currentHash !== null && currentHash !== undefined)
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
this._createContextPromise =
|
|
590
|
+
context.hash = currentHash;
|
|
591
|
+
context.alias = alias;
|
|
592
|
+
this._createContextPromise = context.create(args);
|
|
587
593
|
const success = await this._createContextPromise;
|
|
588
594
|
this.applyAttributes();
|
|
589
595
|
|
|
@@ -615,42 +621,45 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
615
621
|
|
|
616
622
|
// #region applyAttributes
|
|
617
623
|
private applyAttributes() {
|
|
624
|
+
|
|
625
|
+
const context = this.getOrCreateContext();
|
|
626
|
+
|
|
618
627
|
// set tonemapping if configured
|
|
619
|
-
if (
|
|
628
|
+
if (context.renderer) {
|
|
620
629
|
const threeTonemapping = nameToThreeTonemapping(this.toneMapping);
|
|
621
630
|
if (threeTonemapping !== undefined) {
|
|
622
|
-
|
|
631
|
+
context.renderer.toneMapping = threeTonemapping;
|
|
623
632
|
}
|
|
624
633
|
const exposure = this.getAttribute("tone-mapping-exposure");
|
|
625
634
|
if (exposure !== null && exposure !== undefined) {
|
|
626
635
|
const value = parseFloat(exposure);
|
|
627
636
|
if (!isNaN(value))
|
|
628
|
-
|
|
637
|
+
context.renderer.toneMappingExposure = value;
|
|
629
638
|
}
|
|
630
639
|
}
|
|
631
640
|
|
|
632
641
|
const backgroundBlurriness = this.getAttribute("background-blurriness");
|
|
633
642
|
if (backgroundBlurriness !== null && backgroundBlurriness !== undefined) {
|
|
634
643
|
const value = parseFloat(backgroundBlurriness);
|
|
635
|
-
if (!isNaN(value)
|
|
636
|
-
|
|
644
|
+
if (!isNaN(value)) {
|
|
645
|
+
context.scene.backgroundBlurriness = value;
|
|
637
646
|
}
|
|
638
647
|
}
|
|
639
648
|
|
|
640
649
|
const environmentIntensity = this.getAttribute("environment-intensity");
|
|
641
|
-
if (environmentIntensity != undefined
|
|
650
|
+
if (environmentIntensity != undefined) {
|
|
642
651
|
const value = parseFloat(environmentIntensity);
|
|
643
|
-
if (!isNaN(value)
|
|
644
|
-
|
|
652
|
+
if (!isNaN(value))
|
|
653
|
+
context.scene.environmentIntensity = value;
|
|
645
654
|
}
|
|
646
655
|
|
|
647
656
|
const backgroundColor = this.getAttribute("background-color");
|
|
648
|
-
if (
|
|
657
|
+
if (context.renderer) {
|
|
649
658
|
if (typeof backgroundColor === "string" && backgroundColor.length > 0) {
|
|
650
659
|
const rgbaColor = RGBAColor.fromColorRepresentation(backgroundColor);
|
|
651
660
|
if (debug) console.debug("<needle-engine> background-color changed, str:", backgroundColor, "→", rgbaColor)
|
|
652
|
-
|
|
653
|
-
|
|
661
|
+
context.renderer.setClearColor(rgbaColor, rgbaColor.alpha);
|
|
662
|
+
context.scene.background = null;
|
|
654
663
|
}
|
|
655
664
|
// HACK: if we set background-color to a color and then back to null we want the background-image attribute to re-apply
|
|
656
665
|
else if (this.getAttribute("background-image")) {
|
|
@@ -660,19 +669,21 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
660
669
|
}
|
|
661
670
|
|
|
662
671
|
private onXRSessionStarted = () => {
|
|
663
|
-
const
|
|
672
|
+
const context = this.getOrCreateContext();
|
|
673
|
+
|
|
674
|
+
const xrSessionMode = context.xrSessionMode;
|
|
664
675
|
if (xrSessionMode === "immersive-ar")
|
|
665
|
-
this.onEnterAR(
|
|
676
|
+
this.onEnterAR(context.xrSession!);
|
|
666
677
|
else if (xrSessionMode === "immersive-vr")
|
|
667
|
-
this.onEnterVR(
|
|
678
|
+
this.onEnterVR(context.xrSession!);
|
|
668
679
|
|
|
669
680
|
// handle session end:
|
|
670
|
-
|
|
671
|
-
this.dispatchEvent(new CustomEvent("xr-session-ended", { detail: { session:
|
|
681
|
+
context.xrSession?.addEventListener("end", () => {
|
|
682
|
+
this.dispatchEvent(new CustomEvent("xr-session-ended", { detail: { session: context.xrSession, context: this._context, sessionMode: xrSessionMode } }));
|
|
672
683
|
if (xrSessionMode === "immersive-ar")
|
|
673
|
-
this.onExitAR(
|
|
684
|
+
this.onExitAR(context.xrSession!);
|
|
674
685
|
else if (xrSessionMode === "immersive-vr")
|
|
675
|
-
this.onExitVR(
|
|
686
|
+
this.onExitVR(context.xrSession!);
|
|
676
687
|
});
|
|
677
688
|
};
|
|
678
689
|
|
|
@@ -741,7 +752,7 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
741
752
|
if (typeof fn === "function") {
|
|
742
753
|
this._previouslyRegisteredMap.set(eventName, fn);
|
|
743
754
|
// @ts-ignore // not sure how to type this properly
|
|
744
|
-
this.addEventListener(eventName, evt => fn?.call(globalThis, this.
|
|
755
|
+
this.addEventListener(eventName, evt => fn?.call(globalThis, this.getOrCreateContext(), evt));
|
|
745
756
|
}
|
|
746
757
|
}
|
|
747
758
|
catch (err) {
|
|
@@ -783,35 +794,39 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
783
794
|
* @internal
|
|
784
795
|
*/
|
|
785
796
|
onEnterAR(session: XRSession) {
|
|
797
|
+
const context = this.getOrCreateContext();
|
|
786
798
|
this.onSetupAR();
|
|
787
799
|
const overlayContainer = this.getAROverlayContainer();
|
|
788
|
-
this._overlay_ar.onBegin(
|
|
789
|
-
this.dispatchEvent(new CustomEvent("enter-ar", { detail: { session: session, context:
|
|
800
|
+
this._overlay_ar.onBegin(context, overlayContainer, session);
|
|
801
|
+
this.dispatchEvent(new CustomEvent("enter-ar", { detail: { session: session, context: context, htmlContainer: this._overlay_ar?.ARContainer } }));
|
|
790
802
|
}
|
|
791
803
|
|
|
792
804
|
/**
|
|
793
805
|
* @internal
|
|
794
806
|
*/
|
|
795
807
|
onExitAR(session: XRSession) {
|
|
796
|
-
this.
|
|
808
|
+
const context = this.getOrCreateContext();
|
|
809
|
+
this._overlay_ar.onEnd(context);
|
|
797
810
|
this.onSetupDesktop();
|
|
798
|
-
this.dispatchEvent(new CustomEvent("exit-ar", { detail: { session: session, context:
|
|
811
|
+
this.dispatchEvent(new CustomEvent("exit-ar", { detail: { session: session, context: context, htmlContainer: this._overlay_ar?.ARContainer } }));
|
|
799
812
|
}
|
|
800
813
|
|
|
801
814
|
/**
|
|
802
815
|
* @internal
|
|
803
816
|
*/
|
|
804
817
|
onEnterVR(session: XRSession) {
|
|
818
|
+
const context = this.getOrCreateContext();
|
|
805
819
|
this.onSetupVR();
|
|
806
|
-
this.dispatchEvent(new CustomEvent("enter-vr", { detail: { session: session, context:
|
|
820
|
+
this.dispatchEvent(new CustomEvent("enter-vr", { detail: { session: session, context: context } }));
|
|
807
821
|
}
|
|
808
822
|
|
|
809
823
|
/**
|
|
810
824
|
* @internal
|
|
811
825
|
*/
|
|
812
826
|
onExitVR(session: XRSession) {
|
|
827
|
+
const context = this.getOrCreateContext();
|
|
813
828
|
this.onSetupDesktop();
|
|
814
|
-
this.dispatchEvent(new CustomEvent("exit-vr", { detail: { session: session, context:
|
|
829
|
+
this.dispatchEvent(new CustomEvent("exit-vr", { detail: { session: session, context: context } }));
|
|
815
830
|
}
|
|
816
831
|
|
|
817
832
|
private onSetupAR() {
|
|
@@ -11,7 +11,7 @@ import { TypeStore } from "../engine/engine_typestore.js";
|
|
|
11
11
|
import { deepClone, getParam } from "../engine/engine_utils.js";
|
|
12
12
|
import type { AnimatorControllerModel, Condition, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
13
13
|
import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model.js";
|
|
14
|
-
import
|
|
14
|
+
import { Animator } from "./Animator.js";
|
|
15
15
|
|
|
16
16
|
const debug = getParam("debuganimatorcontroller");
|
|
17
17
|
const debugRootMotion = getParam("debugrootmotion");
|
|
@@ -6,7 +6,6 @@ import { hasProLicense } from "../../../engine/engine_license.js";
|
|
|
6
6
|
import { serializable } from "../../../engine/engine_serialization.js";
|
|
7
7
|
import { getFormattedDate, Progress } from "../../../engine/engine_time_utils.js";
|
|
8
8
|
import { DeviceUtilities, getParam } from "../../../engine/engine_utils.js";
|
|
9
|
-
import { registerQuicklookHandlerFactory } from "../../../engine/webcomponents/quicklook-handler.js";
|
|
10
9
|
import { WebXRButtonFactory } from "../../../engine/webcomponents/WebXRButtons.js";
|
|
11
10
|
import { InternalUSDZRegistry } from "../../../engine/xr/usdz.js"
|
|
12
11
|
import { InstancingHandler } from "../../../engine-components/RendererInstancing.js";
|
|
@@ -794,10 +793,3 @@ export class USDZExporter extends Behaviour {
|
|
|
794
793
|
return button;
|
|
795
794
|
}
|
|
796
795
|
}
|
|
797
|
-
|
|
798
|
-
// Register USDZExporter as the quicklook handler so that WebXRButtons
|
|
799
|
-
// can create/find exporters without a direct import (avoids circular dependency).
|
|
800
|
-
registerQuicklookHandlerFactory({
|
|
801
|
-
find: () => GameObject.findObjectOfType(USDZExporter),
|
|
802
|
-
create: () => new USDZExporter(),
|
|
803
|
-
});
|
|
@@ -2,13 +2,12 @@ import { AnimationAction, AnimationClip, AnimationMixer, Audio, AudioListener, A
|
|
|
2
2
|
|
|
3
3
|
import { isDevEnvironment } from "../../engine/debug/index.js";
|
|
4
4
|
import { Context } from "../../engine/engine_setup.js";
|
|
5
|
-
import type { Constructor } from "../../engine/engine_types.js";
|
|
6
5
|
import { getParam, resolveUrl } from "../../engine/engine_utils.js";
|
|
7
6
|
import { setObjectAnimated } from "../AnimationUtils.js";
|
|
8
7
|
import { Animator } from "../Animator.js"
|
|
9
8
|
import { AudioSource } from "../AudioSource.js";
|
|
10
9
|
import { GameObject } from "../Component.js";
|
|
11
|
-
import
|
|
10
|
+
import { PlayableDirector } from "./PlayableDirector.js";
|
|
12
11
|
import { SignalReceiver } from "./SignalAsset.js";
|
|
13
12
|
import * as Models from "./TimelineModels.js";
|
|
14
13
|
|
|
@@ -941,10 +940,7 @@ export class ControlTrackHandler extends TrackHandler {
|
|
|
941
940
|
continue;
|
|
942
941
|
}
|
|
943
942
|
else {
|
|
944
|
-
|
|
945
|
-
// without a runtime import, avoiding a circular dependency.
|
|
946
|
-
const DirectorType = this.director.constructor as Constructor<PlayableDirector>;
|
|
947
|
-
const timeline = GameObject.getComponent(asset.sourceObject, DirectorType)!;
|
|
943
|
+
const timeline = GameObject.getComponent(asset.sourceObject, PlayableDirector)!;
|
|
948
944
|
// always add it to keep size of timelines and models in sync (index of model is index of timeline)
|
|
949
945
|
this.timelines.push(timeline);
|
|
950
946
|
if (timeline) {
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { isLocalNetwork } from "../engine_networking_utils.js";
|
|
2
|
-
import { getParam } from "../engine_utils.js";
|
|
3
|
-
const noDevLogs = getParam("nodevlogs");
|
|
4
|
-
let _manuallySetDevEnvironment;
|
|
5
|
-
let _cachedDevEnvironment;
|
|
6
|
-
/** True when the application runs on a local url */
|
|
7
|
-
export function isDevEnvironment() {
|
|
8
|
-
if (noDevLogs)
|
|
9
|
-
return false;
|
|
10
|
-
if (_manuallySetDevEnvironment !== undefined)
|
|
11
|
-
return _manuallySetDevEnvironment;
|
|
12
|
-
if (_cachedDevEnvironment !== undefined)
|
|
13
|
-
return _cachedDevEnvironment;
|
|
14
|
-
let res = isLocalNetwork();
|
|
15
|
-
if (!res) {
|
|
16
|
-
// is stackblitz?
|
|
17
|
-
res = window.location.hostname.endsWith(".local-credentialless.webcontainer.io");
|
|
18
|
-
}
|
|
19
|
-
_cachedDevEnvironment = res;
|
|
20
|
-
return res;
|
|
21
|
-
}
|
|
22
|
-
/** Enforce the dev environment flag to be true or false */
|
|
23
|
-
export function setDevEnvironment(val) {
|
|
24
|
-
_manuallySetDevEnvironment = val;
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=debug_environment.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"debug_environment.js","sourceRoot":"","sources":["../../../src/engine/debug/debug_environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,SAAS,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;AAExC,IAAI,0BAA+C,CAAC;AACpD,IAAI,qBAA0C,CAAC;AAE/C,oDAAoD;AACpD,MAAM,UAAU,gBAAgB;IAC5B,IAAI,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,0BAA0B,KAAK,SAAS;QAAE,OAAO,0BAA0B,CAAC;IAChF,IAAI,qBAAqB,KAAK,SAAS;QAAE,OAAO,qBAAqB,CAAC;IAEtE,IAAI,GAAG,GAAG,cAAc,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;QACP,iBAAiB;QACjB,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,uCAAuC,CAAC,CAAC;IACrF,CAAC;IACD,qBAAqB,GAAG,GAAG,CAAC;IAC5B,OAAO,GAAG,CAAC;AACf,CAAC;AACD,2DAA2D;AAC3D,MAAM,UAAU,iBAAiB,CAAC,GAAY;IAC1C,0BAA0B,GAAG,GAAG,CAAC;AACrC,CAAC"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sets the priority attribute on a menu element, determining its position in the menu.
|
|
3
|
-
* Lower priority elements appear on the left, higher priority on the right.
|
|
4
|
-
*/
|
|
5
|
-
export declare function setElementPriority(button: HTMLElement, priority: number): void;
|
|
6
|
-
/**
|
|
7
|
-
* Gets the priority attribute from a menu element.
|
|
8
|
-
* @returns The priority value, or undefined if not set or not a valid number.
|
|
9
|
-
*/
|
|
10
|
-
export declare function getElementPriority(button: HTMLElement): number | undefined;
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sets the priority attribute on a menu element, determining its position in the menu.
|
|
3
|
-
* Lower priority elements appear on the left, higher priority on the right.
|
|
4
|
-
*/
|
|
5
|
-
export function setElementPriority(button, priority) {
|
|
6
|
-
button.setAttribute("priority", String(priority));
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Gets the priority attribute from a menu element.
|
|
10
|
-
* @returns The priority value, or undefined if not set or not a valid number.
|
|
11
|
-
*/
|
|
12
|
-
export function getElementPriority(button) {
|
|
13
|
-
const priority = button.getAttribute("priority");
|
|
14
|
-
if (priority) {
|
|
15
|
-
const val = Number.parseFloat(priority);
|
|
16
|
-
if (!Number.isNaN(val))
|
|
17
|
-
return val;
|
|
18
|
-
}
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=menu-priority.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"menu-priority.js","sourceRoot":"","sources":["../../../../src/engine/webcomponents/needle menu/menu-priority.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB,EAAE,QAAgB;IACpE,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAmB;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,QAAQ,EAAE,CAAC;QACX,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IACvC,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Interface for a quicklook handler that can export and open a USDZ file.
|
|
3
|
-
* Used as an abstraction layer to break the circular dependency between
|
|
4
|
-
* WebXRButtons and USDZExporter.
|
|
5
|
-
*/
|
|
6
|
-
export interface IQuicklookHandler {
|
|
7
|
-
objectToExport: any;
|
|
8
|
-
exportAndOpen(): Promise<any>;
|
|
9
|
-
}
|
|
10
|
-
type QuicklookHandlerFactory = {
|
|
11
|
-
/** Find an existing quicklook handler in the scene */
|
|
12
|
-
find(): IQuicklookHandler | null;
|
|
13
|
-
/** Create a new quicklook handler instance */
|
|
14
|
-
create(): IQuicklookHandler;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Register a factory for creating quicklook handlers.
|
|
18
|
-
* Called by USDZExporter to register itself as the handler.
|
|
19
|
-
*/
|
|
20
|
-
export declare function registerQuicklookHandlerFactory(factory: QuicklookHandlerFactory): void;
|
|
21
|
-
/**
|
|
22
|
-
* Find an existing quicklook handler in the scene, or create a new one if none exists.
|
|
23
|
-
* @returns A quicklook handler, or null if no factory has been registered.
|
|
24
|
-
*/
|
|
25
|
-
export declare function getOrCreateQuicklookHandler(): {
|
|
26
|
-
handler: IQuicklookHandler;
|
|
27
|
-
created: boolean;
|
|
28
|
-
} | null;
|
|
29
|
-
export {};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
let _factory;
|
|
2
|
-
/**
|
|
3
|
-
* Register a factory for creating quicklook handlers.
|
|
4
|
-
* Called by USDZExporter to register itself as the handler.
|
|
5
|
-
*/
|
|
6
|
-
export function registerQuicklookHandlerFactory(factory) {
|
|
7
|
-
_factory = factory;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Find an existing quicklook handler in the scene, or create a new one if none exists.
|
|
11
|
-
* @returns A quicklook handler, or null if no factory has been registered.
|
|
12
|
-
*/
|
|
13
|
-
export function getOrCreateQuicklookHandler() {
|
|
14
|
-
if (!_factory)
|
|
15
|
-
return null;
|
|
16
|
-
const existing = _factory.find();
|
|
17
|
-
if (existing)
|
|
18
|
-
return { handler: existing, created: false };
|
|
19
|
-
return { handler: _factory.create(), created: true };
|
|
20
|
-
}
|
|
21
|
-
//# sourceMappingURL=quicklook-handler.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"quicklook-handler.js","sourceRoot":"","sources":["../../../src/engine/webcomponents/quicklook-handler.ts"],"names":[],"mappings":"AAiBA,IAAI,QAA6C,CAAC;AAElD;;;GAGG;AACH,MAAM,UAAU,+BAA+B,CAAC,OAAgC;IAC5E,QAAQ,GAAG,OAAO,CAAC;AACvB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,2BAA2B;IACvC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IACjC,IAAI,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC3D,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACzD,CAAC"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { isLocalNetwork } from "../engine_networking_utils.js";
|
|
2
|
-
import { getParam } from "../engine_utils.js";
|
|
3
|
-
|
|
4
|
-
const noDevLogs = getParam("nodevlogs");
|
|
5
|
-
|
|
6
|
-
let _manuallySetDevEnvironment: boolean | undefined;
|
|
7
|
-
let _cachedDevEnvironment: boolean | undefined;
|
|
8
|
-
|
|
9
|
-
/** True when the application runs on a local url */
|
|
10
|
-
export function isDevEnvironment(): boolean {
|
|
11
|
-
if (noDevLogs) return false;
|
|
12
|
-
if (_manuallySetDevEnvironment !== undefined) return _manuallySetDevEnvironment;
|
|
13
|
-
if (_cachedDevEnvironment !== undefined) return _cachedDevEnvironment;
|
|
14
|
-
|
|
15
|
-
let res = isLocalNetwork();
|
|
16
|
-
if (!res) {
|
|
17
|
-
// is stackblitz?
|
|
18
|
-
res = window.location.hostname.endsWith(".local-credentialless.webcontainer.io");
|
|
19
|
-
}
|
|
20
|
-
_cachedDevEnvironment = res;
|
|
21
|
-
return res;
|
|
22
|
-
}
|
|
23
|
-
/** Enforce the dev environment flag to be true or false */
|
|
24
|
-
export function setDevEnvironment(val: boolean): void {
|
|
25
|
-
_manuallySetDevEnvironment = val;
|
|
26
|
-
}
|