@needle-tools/engine 4.12.0-next.5d44f6c → 4.12.0-next.99c3b94
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-3hSMBtBM.umd.cjs → needle-engine.bundle-DQC2R6JE.umd.cjs} +142 -142
- package/dist/{needle-engine.bundle-By-ZxucN.js → needle-engine.bundle-DYZirog_.js} +6678 -6547
- package/dist/{needle-engine.bundle-DLa-Vhrd.min.js → needle-engine.bundle-DgGjo5dC.min.js} +145 -145
- 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/engine_license.d.ts +18 -0
- package/lib/engine/engine_license.js +151 -9
- package/lib/engine/engine_license.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/xr/NeedleXRSession.js +23 -2
- package/lib/engine/xr/NeedleXRSession.js.map +1 -1
- package/lib/engine-components/DragControls.js +1 -1
- package/lib/engine-components/DragControls.js.map +1 -1
- package/package.json +1 -1
- package/src/engine/engine_context.ts +2 -0
- package/src/engine/engine_license.ts +167 -9
- package/src/engine/engine_serialization_builtin_serializer.ts +1 -1
- package/src/engine/xr/NeedleXRSession.ts +27 -2
- package/src/engine-components/DragControls.ts +1 -1
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { dof } from "three/src/nodes/TSL.js";
|
|
1
2
|
import { isDevEnvironment } from "./debug/index.js";
|
|
2
3
|
import { BUILD_TIME, GENERATOR, PUBLIC_KEY, VERSION } from "./engine_constants.js";
|
|
3
4
|
import { ContextEvent, ContextRegistry } from "./engine_context_registry.js";
|
|
5
|
+
import { onInitialized } from "./engine_lifecycle_api.js";
|
|
4
6
|
import { Context } from "./engine_setup.js";
|
|
5
7
|
import type { IContext } from "./engine_types.js";
|
|
6
8
|
import { getParam } from "./engine_utils.js";
|
|
9
|
+
import { InternalAttributeUtils } from "./engine_utils_attributes.js";
|
|
7
10
|
|
|
8
11
|
const debug = getParam("debuglicense");
|
|
9
12
|
|
|
@@ -67,6 +70,166 @@ function invokeLicenseCheckResultChanged(result: boolean) {
|
|
|
67
70
|
}
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
// #region Telemetry
|
|
76
|
+
export namespace Telemetry {
|
|
77
|
+
|
|
78
|
+
window.addEventListener("error", (event: ErrorEvent) => {
|
|
79
|
+
sendError(Context.Current, "unhandled_error", event);
|
|
80
|
+
});
|
|
81
|
+
window.addEventListener("unhandledrejection", (event: PromiseRejectionEvent) => {
|
|
82
|
+
sendError(Context.Current, "unhandled_promise_rejection", {
|
|
83
|
+
message: event.reason?.message,
|
|
84
|
+
stack: event.reason?.stack,
|
|
85
|
+
timestamp: Date.now(),
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
onInitialized((ctx => sendPageViewEvent(ctx)), { once: true });
|
|
90
|
+
|
|
91
|
+
function sendPageViewEvent(ctx: IContext) {
|
|
92
|
+
if (!isAllowed(ctx)) {
|
|
93
|
+
if (debug) console.debug("Telemetry is disabled via no-telemetry attribute");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
return doFetch({
|
|
97
|
+
site_id: "dabb8317376f",
|
|
98
|
+
type: "pageview",
|
|
99
|
+
pathname: window.location.pathname,
|
|
100
|
+
hostname: window.location.hostname,
|
|
101
|
+
page_title: document.title,
|
|
102
|
+
referrer: document.referrer,
|
|
103
|
+
user_agent: navigator.userAgent,
|
|
104
|
+
querystring: window.location.search,
|
|
105
|
+
language: navigator.language,
|
|
106
|
+
screenWidth: window.screen.width,
|
|
107
|
+
screenHeight: window.screen.height,
|
|
108
|
+
event_name: "page_view",
|
|
109
|
+
properties: JSON.stringify({
|
|
110
|
+
version: VERSION,
|
|
111
|
+
generator: GENERATOR,
|
|
112
|
+
build_time: BUILD_TIME,
|
|
113
|
+
public_key: PUBLIC_KEY,
|
|
114
|
+
src: ctx.domElement?.getAttribute("src") || "",
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function isAllowed(context: IContext | null | undefined): boolean {
|
|
120
|
+
let domElement = context?.domElement as HTMLElement | null;
|
|
121
|
+
if (!domElement) domElement = document.querySelector<HTMLElement>("needle-engine");
|
|
122
|
+
if (!domElement && !context) return false;
|
|
123
|
+
|
|
124
|
+
const attribute = domElement?.getAttribute("no-telemetry");
|
|
125
|
+
if (attribute === "" || attribute === "true" || attribute === "1") {
|
|
126
|
+
if (NEEDLE_ENGINE_LICENSE_TYPE === "pro" || NEEDLE_ENGINE_LICENSE_TYPE === "enterprise") {
|
|
127
|
+
if (debug) console.debug("Telemetry is disabled via no-telemetry attribute");
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const id = "dabb8317376f";
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Sends a telemetry event
|
|
138
|
+
*/
|
|
139
|
+
export async function sendEvent(context: IContext | null | undefined, eventName: string, properties?: Record<string, any>) {
|
|
140
|
+
if (!isAllowed(context)) {
|
|
141
|
+
if (debug) console.debug("Telemetry is disabled");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const body = {
|
|
145
|
+
site_id: id,
|
|
146
|
+
type: "custom_event",
|
|
147
|
+
pathname: window.location.pathname,
|
|
148
|
+
event_name: eventName,
|
|
149
|
+
properties: properties ? JSON.stringify(properties) : undefined,
|
|
150
|
+
}
|
|
151
|
+
return doFetch(body);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
type ErrorData = {
|
|
155
|
+
message?: string;
|
|
156
|
+
stack?: string;
|
|
157
|
+
filename?: string;
|
|
158
|
+
lineno?: number;
|
|
159
|
+
colno?: number;
|
|
160
|
+
timestamp?: number;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export async function sendError(context: IContext, errorName: string, error: ErrorData | ErrorEvent | Error) {
|
|
164
|
+
|
|
165
|
+
if (!isAllowed(context)) {
|
|
166
|
+
if (debug) console.debug("Telemetry is disabled");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (error instanceof ErrorEvent) {
|
|
171
|
+
error = {
|
|
172
|
+
message: error.message,
|
|
173
|
+
stack: error.error?.stack,
|
|
174
|
+
filename: error.filename,
|
|
175
|
+
lineno: error.lineno,
|
|
176
|
+
colno: error.colno,
|
|
177
|
+
timestamp: error.timeStamp || Date.now(),
|
|
178
|
+
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
else if (error instanceof Error) {
|
|
182
|
+
error = {
|
|
183
|
+
message: error.message,
|
|
184
|
+
stack: error.stack,
|
|
185
|
+
timestamp: Date.now(),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const body = {
|
|
189
|
+
site_id: id,
|
|
190
|
+
type: "error",
|
|
191
|
+
event_name: errorName || "error",
|
|
192
|
+
properties: JSON.stringify({
|
|
193
|
+
error_name: errorName,
|
|
194
|
+
message: error.message,
|
|
195
|
+
stack: error.stack,
|
|
196
|
+
filename: error.filename,
|
|
197
|
+
lineno: error.lineno,
|
|
198
|
+
colno: error.colno,
|
|
199
|
+
timestamp: error.timestamp,
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
return doFetch(body);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function doFetch(body: Record<string, any>) {
|
|
206
|
+
try {
|
|
207
|
+
const url = "https://needle.tools/api/v1/rum/t";
|
|
208
|
+
return fetch(url, {
|
|
209
|
+
method: "POST",
|
|
210
|
+
body: JSON.stringify(body),
|
|
211
|
+
headers: {
|
|
212
|
+
'Content-Type': 'application/json'
|
|
213
|
+
},
|
|
214
|
+
// Ensures request completes even if page unloads
|
|
215
|
+
keepalive: true,
|
|
216
|
+
// Allow CORS requests
|
|
217
|
+
mode: 'cors',
|
|
218
|
+
// Low priority to avoid blocking other requests
|
|
219
|
+
// @ts-ignore
|
|
220
|
+
priority: 'low',
|
|
221
|
+
}).catch(e => {
|
|
222
|
+
if (debug) console.error("Failed to send telemetry", e);
|
|
223
|
+
})
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
if (debug) console.error(err);
|
|
227
|
+
}
|
|
228
|
+
return Promise.resolve();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
|
|
70
233
|
ContextRegistry.registerCallback(ContextEvent.ContextRegistered, evt => {
|
|
71
234
|
showLicenseInfo(evt.context);
|
|
72
235
|
handleForbidden(evt.context);
|
|
@@ -341,14 +504,9 @@ async function sendUsageMessageToAnalyticsBackend(context: IContext) {
|
|
|
341
504
|
// We can't send beacons from cross-origin isolated pages
|
|
342
505
|
if (window.crossOriginIsolated) return;
|
|
343
506
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if (attribute === "" || attribute === "true" || attribute === "1") {
|
|
348
|
-
if (debug) console.debug("Telemetry is disabled");
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
if (debug) console.debug("Telemetry attribute: " + attribute);
|
|
507
|
+
if (!Telemetry.isAllowed(context)) {
|
|
508
|
+
if (debug) console.debug("Telemetry is disabled via no-telemetry attribute");
|
|
509
|
+
return;
|
|
352
510
|
}
|
|
353
511
|
|
|
354
512
|
try {
|
|
@@ -379,4 +537,4 @@ async function sendUsageMessageToAnalyticsBackend(context: IContext) {
|
|
|
379
537
|
if (debug)
|
|
380
538
|
console.log("Failed to send non-commercial usage message to analytics backend", err);
|
|
381
539
|
}
|
|
382
|
-
}
|
|
540
|
+
}
|
|
@@ -337,7 +337,7 @@ class EventListSerializer extends TypeSerializer {
|
|
|
337
337
|
args = call.arguments.map(deserializeArgument);
|
|
338
338
|
}
|
|
339
339
|
const method = target[call.method];
|
|
340
|
-
if (
|
|
340
|
+
if (method === undefined) {
|
|
341
341
|
console.warn(`EventList method not found: \"${call.method}\" on ${target?.name}`);
|
|
342
342
|
}
|
|
343
343
|
else {
|
|
@@ -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";
|
|
@@ -98,12 +99,12 @@ async function handleSessionGranted() {
|
|
|
98
99
|
}
|
|
99
100
|
// Check if AR is supported, otherwise we can't do anything
|
|
100
101
|
if (!(await navigator.xr?.isSessionSupported("immersive-ar")) && defaultMode === "immersive-ar") {
|
|
101
|
-
console.warn("[NeedleXRSession:granted] Neither VR nor AR supported, aborting session start.");
|
|
102
|
+
// console.warn("[NeedleXRSession:granted] Neither VR nor AR supported, aborting session start.");
|
|
102
103
|
// showBalloonMessage("NeidleXRSession: Neither VR nor AR supported, aborting session start.");
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
} catch (e) {
|
|
106
|
-
console.
|
|
107
|
+
console.debug("[NeedleXRSession:granted] Error while checking XR support:", e);
|
|
107
108
|
// showBalloonWarning("NeedleXRSession: Error while checking XR support: " + (e as Error).message);
|
|
108
109
|
return;
|
|
109
110
|
}
|
|
@@ -148,6 +149,7 @@ async function handleSessionGranted() {
|
|
|
148
149
|
navigator.xr?.addEventListener('sessiongranted', async () => {
|
|
149
150
|
// enableSpatialConsole(true);
|
|
150
151
|
|
|
152
|
+
|
|
151
153
|
const lastSessionMode = sessionStorage.getItem("needle_xr_session_mode") as XRSessionMode;
|
|
152
154
|
const lastSessionInit = sessionStorage.getItem("needle_xr_session_init") ?? null;
|
|
153
155
|
const init = lastSessionInit ? JSON.parse(lastSessionInit) : null;
|
|
@@ -466,6 +468,10 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
466
468
|
}
|
|
467
469
|
|
|
468
470
|
if (mode === "quicklook") {
|
|
471
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
472
|
+
action: "quicklook_export",
|
|
473
|
+
source: "NeedleXRSession.start",
|
|
474
|
+
});
|
|
469
475
|
InternalUSDZRegistry.exportAndOpen();
|
|
470
476
|
return null;
|
|
471
477
|
}
|
|
@@ -478,6 +484,13 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
478
484
|
url.searchParams.set("url", location.href);
|
|
479
485
|
|
|
480
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
|
+
|
|
481
494
|
// if we are in an iframe, we need to navigate the top window
|
|
482
495
|
const topWindow = window.top || window;
|
|
483
496
|
try {
|
|
@@ -606,6 +619,12 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
606
619
|
listener({ mode, init });
|
|
607
620
|
}
|
|
608
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
|
+
});
|
|
609
628
|
this._currentSessionRequest = navigator?.xr?.requestSession(mode, init);
|
|
610
629
|
this._currentSessionRequestMode = mode;
|
|
611
630
|
/**@type {XRSystem} */
|
|
@@ -1182,6 +1201,12 @@ export class NeedleXRSession implements INeedleXRSession {
|
|
|
1182
1201
|
|
|
1183
1202
|
console.debug("XR Session ended");
|
|
1184
1203
|
|
|
1204
|
+
Telemetry.sendEvent(Context.Current, "xr", {
|
|
1205
|
+
action: "session_end",
|
|
1206
|
+
mode: this.mode,
|
|
1207
|
+
source: "NeedleXRSession.onEnd",
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1185
1210
|
deleteSessionInfo();
|
|
1186
1211
|
|
|
1187
1212
|
this.onAfterRender();
|
|
@@ -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;
|