@needle-tools/engine 4.12.0-next.ca2cebd → 4.12.0-next.da19dd0
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 +1 -1
- package/components.needle.json +1 -1
- package/dist/generateMeshBVH.worker-iyfPIK6R.js +21 -0
- package/dist/{gltf-progressive-DZrY8VT6.min.js → gltf-progressive-BmSygnAC.min.js} +2 -2
- package/dist/{gltf-progressive-DgYz5BYa.js → gltf-progressive-DnLBuGK5.js} +24 -24
- package/dist/{gltf-progressive-DWcmTMCh.umd.cjs → gltf-progressive-Rs-ojtXy.umd.cjs} +1 -1
- package/dist/{loader.worker-Dip-PthR.js → loader.worker-DWzfDpAl.js} +4 -4
- package/dist/needle-engine.bundle-BoOkD4mG.umd.cjs +1647 -0
- package/dist/needle-engine.bundle-DDdH38o3.min.js +1647 -0
- package/dist/{needle-engine.bundle-CFkbGdL5.js → needle-engine.bundle-DeqWDtMx.js} +9105 -8761
- package/dist/needle-engine.d.ts +93 -28
- package/dist/needle-engine.js +48 -48
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-DYDtB188.min.js → postprocessing-B5ksn9-G.min.js} +54 -54
- package/dist/{postprocessing-CMgoN5t5.umd.cjs → postprocessing-DZtb9Nnn.umd.cjs} +81 -81
- package/dist/{postprocessing-BTW9pD_s.js → postprocessing-__7s9wON.js} +450 -441
- package/dist/{three-DfMvBzXi.js → three-BCCkyCA5.js} +1 -7
- package/dist/{three-qj71I7J3.umd.cjs → three-Bf2NBxAw.umd.cjs} +2 -2
- package/dist/{three-B7CT31Bt.min.js → three-W7zWTcfP.min.js} +1 -1
- package/dist/{three-examples-CsW4_6LI.umd.cjs → three-examples-Dho7cuu4.umd.cjs} +4 -4
- package/dist/{three-examples-D1P7eEhn.min.js → three-examples-MsJjauyk.min.js} +10 -10
- package/dist/{three-examples-D1SK93ek.js → three-examples-y2GeYlze.js} +2 -20
- package/dist/{three-mesh-ui-C_uSB5dD.js → three-mesh-ui-3nSSizT4.js} +1 -1
- package/dist/{three-mesh-ui-LQ44s0AL.min.js → three-mesh-ui-CIez6qJQ.min.js} +1 -1
- package/dist/{three-mesh-ui-DpATDXwU.umd.cjs → three-mesh-ui-zsOOA5Pq.umd.cjs} +1 -1
- package/dist/{vendor-D0zoswDa.js → vendor-DMZcbVO1.js} +3707 -3527
- package/dist/vendor-sURMCFSI.min.js +1116 -0
- package/dist/{vendor-UCpFAwt1.umd.cjs → vendor-tyBvnMF-.umd.cjs} +39 -39
- package/lib/engine/codegen/register_types.js +0 -2
- package/lib/engine/codegen/register_types.js.map +1 -1
- package/lib/engine/debug/debug_console.js +403 -1
- package/lib/engine/debug/debug_console.js.map +1 -1
- package/lib/engine/engine_components.js +3 -3
- package/lib/engine/engine_components.js.map +1 -1
- package/lib/engine/engine_context.js +2 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_input.d.ts +5 -0
- package/lib/engine/engine_input.js +6 -0
- package/lib/engine/engine_input.js.map +1 -1
- package/lib/engine/engine_license.d.ts +18 -0
- package/lib/engine/engine_license.js +158 -18
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_networking.js +5 -5
- package/lib/engine/engine_networking.js.map +1 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_physics_rapier.js +1 -1
- package/lib/engine/engine_physics_rapier.js.map +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js +1 -1
- package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
- package/lib/engine/engine_utils.d.ts +4 -1
- package/lib/engine/engine_utils.js +28 -4
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/extensions/extensions.d.ts +29 -7
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine/webcomponents/WebXRButtons.js +13 -5
- package/lib/engine/webcomponents/WebXRButtons.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +2 -0
- package/lib/engine/webcomponents/needle menu/needle-menu.js +37 -6
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +4 -0
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.js +1 -1
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/xr/NeedleXRSession.d.ts +1 -1
- package/lib/engine/xr/NeedleXRSession.js +106 -22
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine/xr/TempXRContext.js +12 -2
- package/lib/engine/xr/TempXRContext.js.map +1 -1
- package/lib/engine/xr/usdz.js +6 -2
- package/lib/engine/xr/usdz.js.map +1 -1
- package/lib/engine-components/AlignmentConstraint.d.ts +1 -1
- package/lib/engine-components/AlignmentConstraint.js +1 -1
- package/lib/engine-components/Animation.d.ts +1 -1
- package/lib/engine-components/Animation.js +1 -1
- package/lib/engine-components/Animator.d.ts +1 -1
- package/lib/engine-components/Animator.js +1 -1
- package/lib/engine-components/AudioListener.d.ts +1 -1
- package/lib/engine-components/AudioListener.js +1 -1
- package/lib/engine-components/AudioSource.d.ts +1 -1
- package/lib/engine-components/AudioSource.js +1 -1
- package/lib/engine-components/Camera.d.ts +1 -1
- package/lib/engine-components/Camera.js +5 -2
- package/lib/engine-components/Camera.js.map +1 -1
- package/lib/engine-components/CharacterController.d.ts +6 -2
- package/lib/engine-components/CharacterController.js +6 -2
- package/lib/engine-components/CharacterController.js.map +1 -1
- package/lib/engine-components/Collider.d.ts +1 -1
- package/lib/engine-components/Collider.js.map +1 -1
- package/lib/engine-components/Component.d.ts +2 -1
- package/lib/engine-components/Component.js +3 -2
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/DragControls.js +4 -1
- package/lib/engine-components/DragControls.js.map +1 -1
- package/lib/engine-components/Joints.d.ts +14 -0
- package/lib/engine-components/Joints.js +14 -0
- package/lib/engine-components/Joints.js.map +1 -1
- package/lib/engine-components/LookAtConstraint.d.ts +1 -1
- package/lib/engine-components/LookAtConstraint.js +1 -1
- package/lib/engine-components/OrbitControls.d.ts +1 -1
- package/lib/engine-components/OrbitControls.js +1 -1
- package/lib/engine-components/Renderer.d.ts +6 -0
- package/lib/engine-components/Renderer.js +6 -0
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/RendererInstancing.js +5 -3
- package/lib/engine-components/RendererInstancing.js.map +1 -1
- package/lib/engine-components/SceneSwitcher.js +18 -14
- package/lib/engine-components/SceneSwitcher.js.map +1 -1
- package/lib/engine-components/SpectatorCamera.js +15 -7
- package/lib/engine-components/SpectatorCamera.js.map +1 -1
- package/lib/engine-components/SpriteRenderer.d.ts +2 -1
- package/lib/engine-components/SpriteRenderer.js +2 -1
- package/lib/engine-components/SpriteRenderer.js.map +1 -1
- package/lib/engine-components/api.d.ts +1 -0
- package/lib/engine-components/api.js +1 -0
- package/lib/engine-components/api.js.map +1 -1
- package/lib/engine-components/codegen/components.d.ts +0 -1
- package/lib/engine-components/codegen/components.js +0 -1
- package/lib/engine-components/codegen/components.js.map +1 -1
- package/lib/engine-components/timeline/SignalAsset.d.ts +1 -1
- package/lib/engine-components/timeline/SignalAsset.js +1 -1
- package/lib/engine-components/ui/Raycaster.d.ts +3 -2
- package/lib/engine-components/ui/Raycaster.js +3 -2
- package/lib/engine-components/ui/Raycaster.js.map +1 -1
- package/lib/engine-components/ui/RectTransform.d.ts +6 -0
- package/lib/engine-components/ui/RectTransform.js +6 -0
- package/lib/engine-components/ui/RectTransform.js.map +1 -1
- package/lib/engine-components/utils/LookAt.d.ts +2 -1
- package/lib/engine-components/utils/LookAt.js +2 -1
- package/lib/engine-components/utils/LookAt.js.map +1 -1
- package/lib/engine-components/web/CursorFollow.d.ts +1 -1
- package/lib/engine-components/web/CursorFollow.js +1 -1
- package/lib/engine-components/web/HoverAnimation.d.ts +1 -1
- package/lib/engine-components/web/HoverAnimation.js +1 -1
- package/lib/engine-components/web/ViewBox.d.ts +1 -1
- package/lib/engine-components/web/ViewBox.js +1 -1
- package/lib/engine-components/webxr/Avatar.js +2 -0
- package/lib/engine-components/webxr/Avatar.js.map +1 -1
- package/lib/engine-components/webxr/WebXR.js +18 -12
- package/lib/engine-components/webxr/WebXR.js.map +1 -1
- package/package.json +5 -5
- package/plugins/vite/poster-client.js +8 -1
- package/src/engine/codegen/register_types.ts +0 -2
- package/src/engine/debug/debug_console.ts +449 -1
- package/src/engine/engine_components.ts +4 -4
- package/src/engine/engine_context.ts +2 -0
- package/src/engine/engine_input.ts +7 -0
- package/src/engine/engine_license.ts +174 -17
- package/src/engine/engine_networking.ts +5 -5
- package/src/engine/engine_physics.ts +3 -3
- package/src/engine/engine_physics_rapier.ts +1 -1
- package/src/engine/engine_serialization_builtin_serializer.ts +1 -1
- package/src/engine/engine_utils.ts +23 -4
- package/src/engine/extensions/extensions.ts +30 -6
- package/src/engine/webcomponents/WebXRButtons.ts +15 -5
- package/src/engine/webcomponents/needle menu/needle-menu.ts +39 -7
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +6 -0
- package/src/engine/webcomponents/needle-engine.ts +2 -2
- package/src/engine/xr/NeedleXRSession.ts +120 -24
- package/src/engine/xr/TempXRContext.ts +12 -2
- package/src/engine/xr/usdz.ts +6 -1
- package/src/engine-components/AlignmentConstraint.ts +1 -1
- package/src/engine-components/Animation.ts +1 -1
- package/src/engine-components/Animator.ts +1 -1
- package/src/engine-components/AudioListener.ts +1 -1
- package/src/engine-components/AudioSource.ts +1 -1
- package/src/engine-components/Camera.ts +5 -2
- package/src/engine-components/CharacterController.ts +6 -2
- package/src/engine-components/Collider.ts +1 -1
- package/src/engine-components/Component.ts +5 -4
- package/src/engine-components/DragControls.ts +5 -1
- package/src/engine-components/Joints.ts +14 -0
- package/src/engine-components/LookAtConstraint.ts +1 -1
- package/src/engine-components/OrbitControls.ts +1 -1
- package/src/engine-components/Renderer.ts +6 -0
- package/src/engine-components/RendererInstancing.ts +6 -3
- package/src/engine-components/SceneSwitcher.ts +17 -17
- package/src/engine-components/SpectatorCamera.ts +21 -10
- package/src/engine-components/SpriteRenderer.ts +2 -1
- package/src/engine-components/api.ts +2 -1
- package/src/engine-components/codegen/components.ts +0 -1
- package/src/engine-components/timeline/SignalAsset.ts +1 -1
- package/src/engine-components/ui/Raycaster.ts +3 -2
- package/src/engine-components/ui/RectTransform.ts +6 -0
- package/src/engine-components/utils/LookAt.ts +2 -1
- package/src/engine-components/web/CursorFollow.ts +1 -1
- package/src/engine-components/web/HoverAnimation.ts +1 -1
- package/src/engine-components/web/ViewBox.ts +1 -1
- package/src/engine-components/webxr/Avatar.ts +4 -0
- package/src/engine-components/webxr/WebXR.ts +19 -11
- package/dist/generateMeshBVH.worker-mO20N_b8.js +0 -21
- package/dist/needle-engine.bundle-4A5NjznD.min.js +0 -1647
- package/dist/needle-engine.bundle-BJg4_HhU.umd.cjs +0 -1647
- package/dist/vendor-BKGa4GE0.min.js +0 -1116
|
@@ -6,6 +6,7 @@ import { Context, FrameEvent } from "../engine_context.js";
|
|
|
6
6
|
import { ContextEvent, ContextRegistry } from "../engine_context_registry.js";
|
|
7
7
|
import { isDestroyed } from "../engine_gameobject.js";
|
|
8
8
|
import { Gizmos } from "../engine_gizmos.js";
|
|
9
|
+
import { Telemetry } from "../engine_license.js";
|
|
9
10
|
import { registerFrameEventCallback, unregisterFrameEventCallback } from "../engine_lifecycle_functions_internal.js";
|
|
10
11
|
import { getBoundingBox, getTempQuaternion, getTempVector, getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../engine_three_utils.js";
|
|
11
12
|
import type { ICamera, IComponent, INeedleXRSession } from "../engine_types.js";
|
|
@@ -82,6 +83,34 @@ function getDOMOverlayElement(domElement: HTMLElement) {
|
|
|
82
83
|
handleSessionGranted();
|
|
83
84
|
async function handleSessionGranted() {
|
|
84
85
|
|
|
86
|
+
// await delay(400);
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
let defaultMode: XRSessionMode = "immersive-vr";
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
// In app clips we default to AR
|
|
93
|
+
if (DeviceUtilities.isNeedleAppClip()) {
|
|
94
|
+
defaultMode = "immersive-ar";
|
|
95
|
+
}
|
|
96
|
+
// Check if VR is even supported, otherwise try AR
|
|
97
|
+
else if (!(await navigator.xr?.isSessionSupported("immersive-vr"))) {
|
|
98
|
+
defaultMode = "immersive-ar";
|
|
99
|
+
}
|
|
100
|
+
// Check if AR is supported, otherwise we can't do anything
|
|
101
|
+
if (!(await navigator.xr?.isSessionSupported("immersive-ar")) && defaultMode === "immersive-ar") {
|
|
102
|
+
// console.warn("[NeedleXRSession:granted] Neither VR nor AR supported, aborting session start.");
|
|
103
|
+
// showBalloonMessage("NeidleXRSession: Neither VR nor AR supported, aborting session start.");
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.debug("[NeedleXRSession:granted] Error while checking XR support:", e);
|
|
108
|
+
// showBalloonWarning("NeedleXRSession: Error while checking XR support: " + (e as Error).message);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// showBalloonMessage("sessiongranted: " + defaultMode);
|
|
113
|
+
|
|
85
114
|
// TODO: asap session granted doesnt handle the pre-room yet
|
|
86
115
|
if (getParam("debugasap")) {
|
|
87
116
|
let asapSession = globalThis["needle:XRSession"] as XRSession | undefined | Promise<XRSession>;
|
|
@@ -94,11 +123,11 @@ async function handleSessionGranted() {
|
|
|
94
123
|
enableSpatialConsole(true);
|
|
95
124
|
const session = await asapSession;
|
|
96
125
|
if (session) {
|
|
97
|
-
const sessionInit = NeedleXRSession.getDefaultSessionInit(
|
|
98
|
-
NeedleXRSession.setSession(
|
|
126
|
+
const sessionInit = NeedleXRSession.getDefaultSessionInit(defaultMode);
|
|
127
|
+
NeedleXRSession.setSession(defaultMode, session, sessionInit, cb.context);
|
|
99
128
|
}
|
|
100
129
|
else {
|
|
101
|
-
console.error("NeedleXRSession: ASAP session was rejected");
|
|
130
|
+
console.error("[NeedleXRSession:granted] ASAP session was rejected");
|
|
102
131
|
}
|
|
103
132
|
asapSession = undefined;
|
|
104
133
|
});
|
|
@@ -106,6 +135,9 @@ async function handleSessionGranted() {
|
|
|
106
135
|
}
|
|
107
136
|
}
|
|
108
137
|
|
|
138
|
+
// console.log("Attaching sessiongranted handler...", { haveXR: 'xr' in navigator });
|
|
139
|
+
// setTimeout(() => console.log("Session Granted handler attached.", { haveXR: 'xr' in navigator }), 1000);
|
|
140
|
+
|
|
109
141
|
if ('xr' in navigator) {
|
|
110
142
|
// WebXRViewer (based on Firefox) has a bug where addEventListener
|
|
111
143
|
// throws a silent exception and aborts execution entirely.
|
|
@@ -115,10 +147,8 @@ async function handleSessionGranted() {
|
|
|
115
147
|
}
|
|
116
148
|
|
|
117
149
|
navigator.xr?.addEventListener('sessiongranted', async () => {
|
|
118
|
-
enableSpatialConsole(true);
|
|
150
|
+
// enableSpatialConsole(true);
|
|
119
151
|
|
|
120
|
-
console.log("Received Session Granted...")
|
|
121
|
-
await delay(100);
|
|
122
152
|
|
|
123
153
|
const lastSessionMode = sessionStorage.getItem("needle_xr_session_mode") as XRSessionMode;
|
|
124
154
|
const lastSessionInit = sessionStorage.getItem("needle_xr_session_init") ?? null;
|
|
@@ -126,7 +156,8 @@ async function handleSessionGranted() {
|
|
|
126
156
|
|
|
127
157
|
let info: SessionInfo | null = null;
|
|
128
158
|
if (contextIsLoading()) {
|
|
129
|
-
await TemporaryXRContext.start(lastSessionMode ||
|
|
159
|
+
await TemporaryXRContext.start(lastSessionMode || defaultMode, init || NeedleXRSession.getDefaultSessionInit(defaultMode))
|
|
160
|
+
.catch(e => console.warn("[NeedleXRSession:granted] TemporaryXRContext start failed:", e));
|
|
130
161
|
await waitForContextLoadingFinished();
|
|
131
162
|
info = await TemporaryXRContext.handoff();
|
|
132
163
|
}
|
|
@@ -134,17 +165,19 @@ async function handleSessionGranted() {
|
|
|
134
165
|
NeedleXRSession.setSession(info.mode, info.session, info.init, Context.Current);
|
|
135
166
|
}
|
|
136
167
|
else if (lastSessionMode && lastSessionInit) {
|
|
137
|
-
console.log("
|
|
168
|
+
console.log("[NeedleXRSession:granted] Restore last session")
|
|
138
169
|
const init = JSON.parse(lastSessionInit);
|
|
139
170
|
NeedleXRSession.start(lastSessionMode as XRSessionMode, init).catch(e => console.warn(e));
|
|
140
171
|
}
|
|
141
172
|
else {
|
|
142
173
|
// if no session was found we start VR by default
|
|
143
|
-
NeedleXRSession.start(
|
|
174
|
+
NeedleXRSession.start(defaultMode).catch(e => console.warn("[NeedleXRSession:granted] failed:", e));
|
|
144
175
|
}
|
|
145
176
|
// make sure we only subscribe to the event once
|
|
146
177
|
}, { once: true });
|
|
147
|
-
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// showBalloonWarning("NeedleXRSession: WebXR not available in this browser.");
|
|
148
181
|
}
|
|
149
182
|
}
|
|
150
183
|
function saveSessionInfo(mode: XRSessionMode, init: XRSessionInit) {
|
|
@@ -419,27 +452,78 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
419
452
|
* @param init The XRSessionInit to use (optional), docs: https://developer.mozilla.org/en-US/docs/Web/API/XRSessionInit
|
|
420
453
|
* @param context The Needle Engine context to use
|
|
421
454
|
*/
|
|
422
|
-
static async start(mode: XRSessionMode | "ar", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null> {
|
|
455
|
+
static async start(mode: XRSessionMode | "ar" | "quicklook", init?: XRSessionInit, context?: Context): Promise<NeedleXRSession | null> {
|
|
423
456
|
|
|
424
|
-
// handle iOS platform where "immersive-ar" is
|
|
457
|
+
// handle iOS platform where "immersive-ar" is special:
|
|
458
|
+
// - we either launch QuickLook
|
|
459
|
+
// - or forward to the Needle App Clip experience for WebXR AR
|
|
425
460
|
// TODO: should we add a separate mode (e.g. "AR")? https://linear.app/needle/issue/NE-5303
|
|
426
461
|
if (DeviceUtilities.isiOS()) {
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
462
|
+
|
|
463
|
+
const arSupported = await this.isARSupported().catch(() => false);
|
|
464
|
+
|
|
465
|
+
// On VisionOS, we use QuickLook for AR experiences; no AppClip support for now.
|
|
466
|
+
if (DeviceUtilities.isVisionOS() && !arSupported && (mode === "ar" || mode === "immersive-ar")) {
|
|
467
|
+
mode = "quicklook";
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (mode === "quicklook") {
|
|
471
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
472
|
+
action: "quicklook_export",
|
|
473
|
+
source: "NeedleXRSession.start",
|
|
474
|
+
});
|
|
475
|
+
InternalUSDZRegistry.exportAndOpen();
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (!arSupported && (mode === "immersive-ar" || mode === "ar")) {
|
|
480
|
+
// const debugAppClip = getParam("debugappclip")
|
|
481
|
+
// Forward to the AppClip experience (Using the apple.com url the appclip overlay shows immediately)
|
|
482
|
+
// const url =`https://appclip.needle.tools/ar?url=${(location.href)}`;
|
|
483
|
+
const url = new URL("https://appclip.apple.com/id?p=tools.needle.launch-app.Clip");
|
|
484
|
+
url.searchParams.set("url", location.href);
|
|
485
|
+
|
|
486
|
+
const urlStr = url.toString();
|
|
487
|
+
|
|
488
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
489
|
+
action: "app_clip_launch",
|
|
490
|
+
source: "NeedleXRSession.start",
|
|
491
|
+
url: urlStr,
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
// if we are in an iframe, we need to navigate the top window
|
|
495
|
+
const topWindow = window.top || window;
|
|
496
|
+
try {
|
|
497
|
+
console.debug("iOS device detected - opening Needle App Clip for AR experience", { mode, init, url });
|
|
498
|
+
// navigate to app clip url but keep the current url in history, open in same tab
|
|
499
|
+
// eslint-disable-next-line xss/no-location-href-assign
|
|
500
|
+
topWindow.location.href = urlStr;
|
|
432
501
|
}
|
|
433
|
-
|
|
434
|
-
|
|
502
|
+
catch (e) {
|
|
503
|
+
console.warn("Error navigating to AppClip " + urlStr + "\n", e);
|
|
504
|
+
// if top window navigation fails and we are in an iframe, we try to navigate the top window directly
|
|
505
|
+
const weAreInIframe = window !== window.top;
|
|
506
|
+
if (weAreInIframe) {
|
|
507
|
+
// we can try to open a new tab as a fallback
|
|
508
|
+
window.open(urlStr, "_blank");
|
|
509
|
+
}
|
|
510
|
+
// eslint-disable-next-line xss/no-location-href-assign
|
|
511
|
+
else window.location.href = urlStr;
|
|
435
512
|
}
|
|
513
|
+
|
|
514
|
+
return null;
|
|
436
515
|
}
|
|
437
516
|
}
|
|
438
|
-
else if (mode == "ar") {
|
|
439
|
-
mode = "immersive-ar";
|
|
440
|
-
}
|
|
441
517
|
|
|
518
|
+
if (mode === "quicklook") {
|
|
519
|
+
console.warn("QuickLook mode is only supported on iOS devices");
|
|
520
|
+
return null;
|
|
521
|
+
}
|
|
442
522
|
|
|
523
|
+
// Since we now know we are not on iOS, ar mode becomes "immersive-ar"
|
|
524
|
+
if (mode == "ar") {
|
|
525
|
+
mode = "immersive-ar";
|
|
526
|
+
}
|
|
443
527
|
|
|
444
528
|
if (isDevEnvironment() && getParam("debugxrpreroom")) {
|
|
445
529
|
console.warn("Debug: Starting temporary XR session");
|
|
@@ -535,12 +619,18 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
535
619
|
listener({ mode, init });
|
|
536
620
|
}
|
|
537
621
|
if (debug) showBalloonMessage("Requesting " + mode + " session (" + Date.now() + ")");
|
|
622
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
623
|
+
action: "session_request",
|
|
624
|
+
mode: mode,
|
|
625
|
+
features: ((init.requiredFeatures ?? []).concat(init.optionalFeatures ?? [])).join(","),
|
|
626
|
+
source: "NeedleXRSession.start",
|
|
627
|
+
});
|
|
538
628
|
this._currentSessionRequest = navigator?.xr?.requestSession(mode, init);
|
|
539
629
|
this._currentSessionRequestMode = mode;
|
|
540
630
|
/**@type {XRSystem} */
|
|
541
631
|
const newSession = await (this._currentSessionRequest)?.catch(e => {
|
|
542
|
-
console.error(e, "Code: " + e
|
|
543
|
-
if (e
|
|
632
|
+
console.error(e, "Code: " + e?.code);
|
|
633
|
+
if (e?.code === 9) showBalloonWarning("Couldn't start XR session. Make sure you allow the required permissions.")
|
|
544
634
|
console.log("If the specified XR configuration is not supported (e.g. entering AR doesnt work) - make sure you access the website on a secure connection (HTTPS) and your device has the required permissions (e.g. camera access)");
|
|
545
635
|
const notSecure = location.protocol === 'http:';
|
|
546
636
|
if (notSecure) showBalloonWarning("XR requires a secure connection (HTTPS)");
|
|
@@ -1111,6 +1201,12 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
1111
1201
|
|
|
1112
1202
|
console.debug("XR Session ended");
|
|
1113
1203
|
|
|
1204
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
1205
|
+
action: "session_end",
|
|
1206
|
+
mode: this.mode,
|
|
1207
|
+
source: "NeedleXRSession.onEnd",
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1114
1210
|
deleteSessionInfo();
|
|
1115
1211
|
|
|
1116
1212
|
this.onAfterRender();
|
|
@@ -32,7 +32,13 @@ export class TemporaryXRContext {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
this._requestInFlight = true;
|
|
35
|
-
const session = await navigator.xr.requestSession(mode, init)
|
|
35
|
+
const session = await navigator.xr.requestSession(mode, init).catch(err => {
|
|
36
|
+
console.error("Failed to start temporary XR session:", err);
|
|
37
|
+
});
|
|
38
|
+
if (!session) {
|
|
39
|
+
this._requestInFlight = false;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
36
42
|
session.addEventListener("end", () => {
|
|
37
43
|
this._active = null;
|
|
38
44
|
});
|
|
@@ -82,10 +88,14 @@ export class TemporaryXRContext {
|
|
|
82
88
|
this._session = session;
|
|
83
89
|
this._session.addEventListener("end", this.onEnd);
|
|
84
90
|
|
|
85
|
-
this._renderer = new WebGLRenderer({ alpha: true });
|
|
91
|
+
this._renderer = new WebGLRenderer({ alpha: true, antialias: true });
|
|
92
|
+
this._renderer.outputColorSpace = 'srgb';
|
|
86
93
|
this._renderer.setAnimationLoop(this.onFrame);
|
|
87
94
|
this._renderer.xr.setSession(session);
|
|
88
95
|
this._renderer.xr.enabled = true;
|
|
96
|
+
// Set pixel ratio and size
|
|
97
|
+
this._renderer.setPixelRatio(Math.min(2, window.devicePixelRatio));
|
|
98
|
+
this._renderer.setSize(window.innerWidth, window.innerHeight);
|
|
89
99
|
this._camera = new PerspectiveCamera();
|
|
90
100
|
this._scene = new Scene();
|
|
91
101
|
this._scene.fog = new Fog(0x444444, 10, 250);
|
package/src/engine/xr/usdz.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDevEnvironment } from "../debug/index.js";
|
|
1
2
|
|
|
2
3
|
declare type USDZExporter = {
|
|
3
4
|
exportAndOpen(): Promise<any>,
|
|
@@ -11,7 +12,11 @@ export namespace InternalUSDZRegistry {
|
|
|
11
12
|
const usdzExporter: USDZExporter[] = [];
|
|
12
13
|
|
|
13
14
|
export function exportAndOpen(): boolean {
|
|
14
|
-
if (!usdzExporter?.length)
|
|
15
|
+
if (!usdzExporter?.length) {
|
|
16
|
+
if (isDevEnvironment()) {
|
|
17
|
+
console.warn("No USDZ exporters found – cannot export USDZ for QuickLook.");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
15
20
|
for (const exp of usdzExporter) {
|
|
16
21
|
exp.exportAndOpen();
|
|
17
22
|
}
|
|
@@ -9,7 +9,7 @@ import { Behaviour, GameObject } from "./Component.js";
|
|
|
9
9
|
* You can use this to create dynamic beams or connectors between objects.
|
|
10
10
|
*
|
|
11
11
|
* @summary Aligns and scales the object between two target GameObjects
|
|
12
|
-
* @category
|
|
12
|
+
* @category Constraints
|
|
13
13
|
* @group Components
|
|
14
14
|
**/
|
|
15
15
|
export class AlignmentConstraint extends Behaviour {
|
|
@@ -60,7 +60,7 @@ class Vec2 { x!: number; y!: number }
|
|
|
60
60
|
/**
|
|
61
61
|
* Animation component to play animations on a GameObject.
|
|
62
62
|
*
|
|
63
|
-
* @summary
|
|
63
|
+
* @summary Plays animations from AnimationClips
|
|
64
64
|
* @category Animation and Sequencing
|
|
65
65
|
* @group Components
|
|
66
66
|
*/
|
|
@@ -43,7 +43,7 @@ export declare class PlayOptions {
|
|
|
43
43
|
* It works with an {@link AnimatorController} to handle state transitions and animation blending.
|
|
44
44
|
* A new AnimatorController can be created from code via `AnimatorController.createFromClips`.
|
|
45
45
|
*
|
|
46
|
-
* @summary
|
|
46
|
+
* @summary Plays and manages animations on a GameObject based on an AnimatorController
|
|
47
47
|
* @category Animation and Sequencing
|
|
48
48
|
* @group Components
|
|
49
49
|
*/
|
|
@@ -9,7 +9,7 @@ import { Behaviour, GameObject } from "./Component.js";
|
|
|
9
9
|
* This component creates and manages a Three.js {@link three#AudioListener}, automatically connecting it
|
|
10
10
|
* to the main camera or a Camera in the parent hierarchy.
|
|
11
11
|
*
|
|
12
|
-
* @summary
|
|
12
|
+
* @summary Receives audio in the scene and outputs it to speakers
|
|
13
13
|
* @category Multimedia
|
|
14
14
|
* @group Components
|
|
15
15
|
*/
|
|
@@ -52,7 +52,7 @@ export enum AudioRolloffMode {
|
|
|
52
52
|
* is muted, the volume is set to 0. When unmuted, the volume
|
|
53
53
|
* returns to its previous value.
|
|
54
54
|
*
|
|
55
|
-
* @summary
|
|
55
|
+
* @summary Plays audio clips from files or media streams
|
|
56
56
|
* @category Multimedia
|
|
57
57
|
* @group Components
|
|
58
58
|
*/
|
|
@@ -8,7 +8,7 @@ import { Context } from "../engine/engine_setup.js";
|
|
|
8
8
|
import { RenderTexture } from "../engine/engine_texture.js";
|
|
9
9
|
import { getTempColor, getWorldPosition } from "../engine/engine_three_utils.js";
|
|
10
10
|
import type { ICamera } from "../engine/engine_types.js"
|
|
11
|
-
import { getParam } from "../engine/engine_utils.js";
|
|
11
|
+
import { DeviceUtilities, getParam } from "../engine/engine_utils.js";
|
|
12
12
|
import { NeedleXREventArgs } from "../engine/engine_xr.js";
|
|
13
13
|
import { RGBAColor } from "../engine/js-extensions/index.js";
|
|
14
14
|
import { Behaviour, GameObject } from "./Component.js";
|
|
@@ -37,7 +37,7 @@ const debugscreenpointtoray = getParam("debugscreenpointtoray");
|
|
|
37
37
|
* Internally, this component uses {@link PerspectiveCamera} and {@link OrthographicCamera} three.js objects.
|
|
38
38
|
*
|
|
39
39
|
* @summary Rendering scenes from a specific viewpoint
|
|
40
|
-
* @category Camera
|
|
40
|
+
* @category Camera and Controls
|
|
41
41
|
* @group Components
|
|
42
42
|
*/
|
|
43
43
|
export class Camera extends Behaviour implements ICamera {
|
|
@@ -664,6 +664,9 @@ export class Camera extends Behaviour implements ICamera {
|
|
|
664
664
|
else if (navigator.userAgent?.includes("Mozilla") && navigator.userAgent?.includes("Mobile WebXRViewer/v2")) {
|
|
665
665
|
transparent = true;
|
|
666
666
|
}
|
|
667
|
+
else if(DeviceUtilities.isNeedleAppClip()) {
|
|
668
|
+
return true;
|
|
669
|
+
}
|
|
667
670
|
}
|
|
668
671
|
}
|
|
669
672
|
|
|
@@ -110,8 +110,12 @@ export class CharacterController extends Behaviour {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
113
|
+
* CharacterControllerInput handles user input to control a CharacterController.
|
|
114
|
+
* It supports movement, looking around, jumping, and double jumping.
|
|
115
|
+
* You can customize movement speed, rotation speed, and jump forces.
|
|
116
|
+
* It also integrates with an Animator component for character animations.
|
|
117
|
+
* @summary User Input for Character Controller
|
|
118
|
+
* @category Character
|
|
115
119
|
* @group Components
|
|
116
120
|
*/
|
|
117
121
|
export class CharacterControllerInput extends Behaviour {
|
|
@@ -26,7 +26,7 @@ import { Rigidbody } from "./RigidBody.js";
|
|
|
26
26
|
* @category Physics
|
|
27
27
|
* @group Components
|
|
28
28
|
*/
|
|
29
|
-
export class Collider extends Behaviour implements ICollider {
|
|
29
|
+
export abstract class Collider extends Behaviour implements ICollider {
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Identifies this component as a collider.
|
|
@@ -476,10 +476,11 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
|
|
|
476
476
|
* Gets a component of the specified type in the gameObject's children hierarchy
|
|
477
477
|
* @param go GameObject to search in
|
|
478
478
|
* @param typeName Constructor of the component type
|
|
479
|
+
* @param includeInactive Whether to include inactive objects in the search
|
|
479
480
|
* @returns The first matching component if found, otherwise null
|
|
480
481
|
*/
|
|
481
|
-
public static getComponentInChildren<T extends IComponent>(go: IGameObject | Object3D, typeName: Constructor<T
|
|
482
|
-
return getComponentInChildren(go, typeName);
|
|
482
|
+
public static getComponentInChildren<T extends IComponent>(go: IGameObject | Object3D, typeName: Constructor<T>, includeInactive: boolean = false): T | null {
|
|
483
|
+
return getComponentInChildren(go, typeName, includeInactive);
|
|
483
484
|
}
|
|
484
485
|
|
|
485
486
|
/**
|
|
@@ -588,7 +589,7 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
588
589
|
*/
|
|
589
590
|
get [$componentName]() { return TypeStore.getKey(this.constructor as any) || undefined; }
|
|
590
591
|
|
|
591
|
-
|
|
592
|
+
|
|
592
593
|
private __context: Context | undefined;
|
|
593
594
|
|
|
594
595
|
/**
|
|
@@ -1106,7 +1107,7 @@ export abstract class Component implements IComponent, EventTarget,
|
|
|
1106
1107
|
this.dispatchEvent(new CustomEvent("destroyed", { detail: this }));
|
|
1107
1108
|
}
|
|
1108
1109
|
destroyComponentInstance(this as any);
|
|
1109
|
-
if(isHotReloadEnabled()) unregisterHotReloadType(this);
|
|
1110
|
+
if (isHotReloadEnabled()) unregisterHotReloadType(this);
|
|
1110
1111
|
}
|
|
1111
1112
|
|
|
1112
1113
|
/**
|
|
@@ -447,7 +447,7 @@ export class DragControls extends Behaviour implements IPointerEventHandler {
|
|
|
447
447
|
if (!this || !this._isDragging) return;
|
|
448
448
|
this._isDragging = false;
|
|
449
449
|
for (const rb of this._draggingRigidbodies) {
|
|
450
|
-
rb.setVelocity(rb.smoothedVelocity);
|
|
450
|
+
rb.setVelocity(rb.smoothedVelocity.multiplyScalar(this.context.time.deltaTime));
|
|
451
451
|
}
|
|
452
452
|
this._draggingRigidbodies.length = 0;
|
|
453
453
|
this._targetObject = null;
|
|
@@ -485,6 +485,8 @@ interface IDragHandler {
|
|
|
485
485
|
onDragUpdate?(numberOfPointers: number): void;
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
+
|
|
489
|
+
// #region MultiTouchDragHandler
|
|
488
490
|
/**
|
|
489
491
|
* Handles two touch points affecting one object.
|
|
490
492
|
* Enables multi-touch interactions that allow movement, scaling, and rotation of objects.
|
|
@@ -734,6 +736,7 @@ class MultiTouchDragHandler implements IDragHandler {
|
|
|
734
736
|
}
|
|
735
737
|
|
|
736
738
|
|
|
739
|
+
// #region DragPointerHandler
|
|
737
740
|
/**
|
|
738
741
|
* Handles a single pointer on an object.
|
|
739
742
|
* DragPointerHandlers manage determining if a drag operation has started, tracking pointer movement,
|
|
@@ -1335,6 +1338,7 @@ class DragPointerHandler implements IDragHandler {
|
|
|
1335
1338
|
}
|
|
1336
1339
|
}
|
|
1337
1340
|
|
|
1341
|
+
// #region LegacyDragVisualsHelper
|
|
1338
1342
|
/**
|
|
1339
1343
|
* Provides visual helper elements for DragControls.
|
|
1340
1344
|
* Shows where objects will be placed and their relation to surfaces below them.
|
|
@@ -36,6 +36,12 @@ export abstract class Joint extends Behaviour {
|
|
|
36
36
|
protected abstract createJoint(self: Rigidbody, other: Rigidbody);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* The FixedJoint groups together 2 rigidbodies, making them stick together in their bound position
|
|
41
|
+
* @summary Connect two Rigidbodies and make them stick together
|
|
42
|
+
* @category Physics
|
|
43
|
+
* @group Components
|
|
44
|
+
*/
|
|
39
45
|
export class FixedJoint extends Joint {
|
|
40
46
|
|
|
41
47
|
protected createJoint(self: Rigidbody, other: Rigidbody) {
|
|
@@ -43,6 +49,14 @@ export class FixedJoint extends Joint {
|
|
|
43
49
|
}
|
|
44
50
|
}
|
|
45
51
|
|
|
52
|
+
/**
|
|
53
|
+
* The HingeJoint groups together 2 rigid bodies, constraining them to move like connected by a hinge.
|
|
54
|
+
*
|
|
55
|
+
* You can specify the anchor point and axis of rotation for the hinge.
|
|
56
|
+
* @summary Connect two Rigidbodies with a hinge
|
|
57
|
+
* @category Physics
|
|
58
|
+
* @group Components
|
|
59
|
+
*/
|
|
46
60
|
export class HingeJoint extends Joint {
|
|
47
61
|
|
|
48
62
|
@serializable(Vector3)
|
|
@@ -9,7 +9,7 @@ import type { OrbitControls } from "./OrbitControls.js";
|
|
|
9
9
|
* This component is used by {@link OrbitControls} internally.
|
|
10
10
|
*
|
|
11
11
|
* @summary Look At Constraint for OrbitControls
|
|
12
|
-
* @category Camera Controls
|
|
12
|
+
* @category Camera and Controls
|
|
13
13
|
* @group Components
|
|
14
14
|
*/
|
|
15
15
|
export class LookAtConstraint extends Behaviour {
|
|
@@ -64,7 +64,7 @@ declare module 'three/examples/jsm/controls/OrbitControls.js' {
|
|
|
64
64
|
* The three OrbitControls object can be accessed via the `controls` property.
|
|
65
65
|
* The object being controlled by the OrbitControls (usually the camera) can be accessed via the `controllerObject` property.
|
|
66
66
|
* @summary Camera controller using three.js OrbitControls
|
|
67
|
-
* @category Camera
|
|
67
|
+
* @category Camera and Controls
|
|
68
68
|
* @group Components
|
|
69
69
|
*/
|
|
70
70
|
export class OrbitControls extends Behaviour implements ICameraController {
|
|
@@ -805,6 +805,12 @@ export class Renderer extends Behaviour implements IRenderer {
|
|
|
805
805
|
export class MeshRenderer extends Renderer {
|
|
806
806
|
}
|
|
807
807
|
|
|
808
|
+
/**
|
|
809
|
+
* Renders deformable meshes that deform via bones and/or blend shapes.
|
|
810
|
+
* @summary Renderer for deformable meshes
|
|
811
|
+
* @category Rendering
|
|
812
|
+
* @group Components
|
|
813
|
+
**/
|
|
808
814
|
export class SkinnedMeshRenderer extends MeshRenderer {
|
|
809
815
|
|
|
810
816
|
private _needUpdateBoundingSphere = false;
|
|
@@ -669,14 +669,17 @@ class InstancedMeshRenderer {
|
|
|
669
669
|
private grow(geometry: BufferGeometry) {
|
|
670
670
|
const id = ++this._growId;
|
|
671
671
|
const growFactor = 2;
|
|
672
|
-
|
|
672
|
+
|
|
673
|
+
const growInstances = this.count >= this._maxInstanceCount;
|
|
674
|
+
const newSize = growInstances ? Math.ceil(this._maxInstanceCount * growFactor) : this._maxInstanceCount;
|
|
673
675
|
|
|
674
676
|
// create a new BatchedMesh instance
|
|
675
677
|
// TODO: we should keep track of how many instances for each geometry we have and consider that when estimating new space
|
|
676
678
|
const estimatedSpace = this.tryEstimateVertexCountSize(newSize, [geometry]);// geometry.attributes.position.count;
|
|
677
679
|
// const indices = geometry.index ? geometry.index.count : 0;
|
|
678
|
-
const
|
|
679
|
-
const
|
|
680
|
+
const vertexGrowFactor = 1.25;
|
|
681
|
+
const newMaxVertexCount = Math.max(this._maxVertexCount, Math.ceil(estimatedSpace.vertexCount * vertexGrowFactor));
|
|
682
|
+
const newMaxIndexCount = Math.max(this._maxIndexCount, Math.ceil(estimatedSpace.indexCount * vertexGrowFactor));
|
|
680
683
|
|
|
681
684
|
if (debugInstancing) {
|
|
682
685
|
const geometryInfo = getMeshInformation(geometry);
|