@needle-tools/engine 6.0.0-alpha.5 → 6.0.0-alpha.7
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 +9 -0
- package/dist/gltf-progressive-CRdzVlSY.umd.cjs +10 -0
- package/dist/gltf-progressive-OBdIERAY.min.js +10 -0
- package/dist/{gltf-progressive-B7lOWdLe.js → gltf-progressive-ZuAsp3FE.js} +237 -231
- package/dist/{materialx-CTPhpPxI.min.js → materialx-Bd0NThHa.min.js} +1 -1
- package/dist/{materialx-BwYvA-4x.umd.cjs → materialx-Clep-Dc8.umd.cjs} +2 -2
- package/dist/{materialx-B3qY8vPU.js → materialx-m9EM4lhZ.js} +1 -1
- package/dist/{needle-engine.bundle-_kAszB-k.min.js → needle-engine.bundle-B2_-yVCX.min.js} +148 -148
- package/dist/{needle-engine.bundle-D3nBMgfk.umd.cjs → needle-engine.bundle-BOs3iHUC.umd.cjs} +147 -147
- package/dist/{needle-engine.bundle-4xlWxOTF.js → needle-engine.bundle-hBHg3HuX.js} +7092 -7023
- package/dist/needle-engine.d.ts +49 -28
- package/dist/needle-engine.js +604 -603
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{vendor-BJviq-Oq.umd.cjs → vendor-Bb_SUKxZ.umd.cjs} +92 -92
- package/dist/{vendor-CdNldo8c.min.js → vendor-D1vc0sOe.min.js} +100 -100
- package/dist/{vendor-BQUQwut5.js → vendor-ipoLrKAE.js} +3466 -3320
- package/lib/engine/api.d.ts +2 -1
- package/lib/engine/api.js +2 -1
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/engine_context.d.ts +2 -0
- package/lib/engine/engine_context.js +14 -0
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_init.js +2 -2
- package/lib/engine/engine_init.js.map +1 -1
- package/lib/engine/engine_license.d.ts +7 -7
- package/lib/engine/engine_license.js +73 -73
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_loaders.gltf.d.ts +3 -1
- package/lib/engine/engine_loaders.gltf.js +6 -1
- package/lib/engine/engine_loaders.gltf.js.map +1 -1
- package/lib/engine/engine_networking_blob.js +3 -3
- package/lib/engine/engine_networking_blob.js.map +1 -1
- package/lib/engine/engine_physics.d.ts +2 -0
- package/lib/engine/engine_physics.js +23 -1
- package/lib/engine/engine_physics.js.map +1 -1
- package/lib/engine/engine_utils_qrcode.js +2 -2
- package/lib/engine/engine_utils_qrcode.js.map +1 -1
- package/lib/engine/project-document/engine_document_extensions.d.ts +16 -0
- package/lib/engine/project-document/engine_document_extensions.js +29 -0
- package/lib/engine/project-document/engine_document_extensions.js.map +1 -0
- package/lib/engine/project-document/engine_document_runtime.js +1 -1
- package/lib/engine/project-document/engine_document_runtime.js.map +1 -1
- package/lib/engine/project-document/engine_project_document.js +39 -3
- package/lib/engine/project-document/engine_project_document.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
- package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
- package/lib/engine/webcomponents/needle menu/needle-menu.js +5 -5
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.js +2 -2
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
- package/lib/engine/xr/TempXRContext.js +2 -2
- package/lib/engine/xr/TempXRContext.js.map +1 -1
- package/lib/engine-components/Renderer.d.ts +1 -1
- package/lib/engine-components/Renderer.js +2 -11
- package/lib/engine-components/Renderer.js.map +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
- package/package.json +4 -4
- package/plugins/common/license.js +4 -4
- package/plugins/license/cli.js +7 -4
- package/plugins/vite/build-pipeline.js +6 -1
- package/plugins/vite/license.js +4 -4
- package/plugins/vite/logger.client.js +21 -8
- package/src/engine/api.ts +2 -1
- package/src/engine/engine_context.ts +11 -0
- package/src/engine/engine_init.ts +2 -2
- package/src/engine/engine_license.ts +70 -70
- package/src/engine/engine_loaders.gltf.ts +8 -2
- package/src/engine/engine_networking_blob.ts +3 -3
- package/src/engine/engine_physics.ts +22 -1
- package/src/engine/engine_utils_qrcode.ts +2 -2
- package/src/engine/project-document/engine_document_extensions.ts +39 -0
- package/src/engine/project-document/engine_document_runtime.ts +1 -1
- package/src/engine/project-document/engine_project_document.ts +46 -3
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
- package/src/engine/webcomponents/needle menu/needle-menu.ts +5 -5
- package/src/engine/webcomponents/needle-engine.loading.ts +2 -2
- package/src/engine/webcomponents/needle-engine.ts +2 -2
- package/src/engine/xr/TempXRContext.ts +2 -2
- package/src/engine-components/Renderer.ts +4 -13
- package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
- package/dist/gltf-progressive-BpT9M5Mt.umd.cjs +0 -10
- package/dist/gltf-progressive-D0rzvhNG.min.js +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needle-tools/engine",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.7",
|
|
4
4
|
"description": "Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.",
|
|
5
5
|
"main": "dist/needle-engine.min.js",
|
|
6
6
|
"exports": {
|
|
@@ -105,10 +105,10 @@
|
|
|
105
105
|
],
|
|
106
106
|
"dependencies": {
|
|
107
107
|
"@dimforge/rapier3d-compat": "0.19.3",
|
|
108
|
-
"@needle-tools/addressing": "0.
|
|
109
|
-
"@needle-tools/gltf-progressive": "4.0.0-alpha.
|
|
108
|
+
"@needle-tools/addressing": "0.4.0-1791547125.jolly-gregor-mendel.6047e58",
|
|
109
|
+
"@needle-tools/gltf-progressive": "4.0.0-alpha.6",
|
|
110
110
|
"@needle-tools/materialx": "1.7.4",
|
|
111
|
-
"@needle-tools/three-animation-pointer": "1.1.
|
|
111
|
+
"@needle-tools/three-animation-pointer": "1.1.3",
|
|
112
112
|
"@sparkjsdev/spark": "npm:@needle-tools/spark@2.1.0-needle.3",
|
|
113
113
|
"@webxr-input-profiles/motion-controllers": "1.0.0",
|
|
114
114
|
"flatbuffers": "2.0.4",
|
|
@@ -127,7 +127,7 @@ async function requestNeedleCloud(path, options) {
|
|
|
127
127
|
* @param {DefaultOptions & {accessToken?:string, team:string|undefined}} opts
|
|
128
128
|
*/
|
|
129
129
|
export async function replaceLicense(code, opts) {
|
|
130
|
-
const index = code?.indexOf("
|
|
130
|
+
const index = code?.indexOf("yBXL");
|
|
131
131
|
if (index >= 0) {
|
|
132
132
|
const licenseResult = await resolveLicense(opts);
|
|
133
133
|
if (!licenseResult) {
|
|
@@ -136,18 +136,18 @@ export async function replaceLicense(code, opts) {
|
|
|
136
136
|
const end = code.indexOf(";", index);
|
|
137
137
|
if (end >= 0) {
|
|
138
138
|
const line = code.substring(index, end);
|
|
139
|
-
const replaced = "
|
|
139
|
+
const replaced = "yBXL = \"" + licenseResult.type + "\"";
|
|
140
140
|
code = code.replace(line, replaced);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
// Also inject JWT if available
|
|
144
144
|
if (licenseResult.jwt) {
|
|
145
|
-
const jwtIndex = code.indexOf("
|
|
145
|
+
const jwtIndex = code.indexOf("VkS");
|
|
146
146
|
if (jwtIndex >= 0) {
|
|
147
147
|
const jwtEnd = code.indexOf(";", jwtIndex);
|
|
148
148
|
if (jwtEnd >= 0) {
|
|
149
149
|
const jwtLine = code.substring(jwtIndex, jwtEnd);
|
|
150
|
-
const jwtReplaced = "
|
|
150
|
+
const jwtReplaced = "VkS = \"" + licenseResult.jwt + "\"";
|
|
151
151
|
code = code.replace(jwtLine, jwtReplaced);
|
|
152
152
|
}
|
|
153
153
|
}
|
package/plugins/license/cli.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { generateLicenseFile } from "./index.js";
|
|
3
|
+
import { needleGreenBold, needleLog, resetLastLoggedPlugin } from "../vite/logging.js";
|
|
3
4
|
|
|
4
5
|
let out;
|
|
5
6
|
let team;
|
|
@@ -25,19 +26,21 @@ for (let i = 0; i < args.length; i++) {
|
|
|
25
26
|
team = arg.slice(7);
|
|
26
27
|
}
|
|
27
28
|
else {
|
|
28
|
-
|
|
29
|
+
needleLog("needle-license", `Unknown argument: ${arg}`, "error", { dimBody: false });
|
|
29
30
|
process.exit(1);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
if (requestedOut && (!out || out.startsWith("--")) || requestedTeam && (!team || team.startsWith("--"))) {
|
|
33
|
-
|
|
34
|
+
needleLog("needle-license", "--out and --team require a value.", "error", { dimBody: false });
|
|
34
35
|
process.exit(1);
|
|
35
36
|
}
|
|
36
37
|
try {
|
|
37
38
|
const result = await generateLicenseFile({ out, team });
|
|
38
|
-
|
|
39
|
+
resetLastLoggedPlugin();
|
|
40
|
+
const status = result.signed ? needleGreenBold("Signed license") : "Basic fallback";
|
|
41
|
+
needleLog("needle-license", `${status} written to ${result.output}`, "log", { dimBody: false });
|
|
39
42
|
}
|
|
40
43
|
catch (error) {
|
|
41
|
-
|
|
44
|
+
needleLog("needle-license", error instanceof Error ? error.stack ?? error.message : String(error), "error", { dimBody: false });
|
|
42
45
|
process.exitCode = 1;
|
|
43
46
|
}
|
|
@@ -557,7 +557,7 @@ async function invokeBuildPipeline(opts, options = {}) {
|
|
|
557
557
|
else {
|
|
558
558
|
// First check if the user passed in a specific version to use via the vite config
|
|
559
559
|
let version = opts.buildPipeline?.version;
|
|
560
|
-
let versionSource = version ? "vite" : "";
|
|
560
|
+
let versionSource = version ? "vite" : "default";
|
|
561
561
|
// If not, check env var (set by Unity/Blender integrations)
|
|
562
562
|
if (!version && process.env.NEEDLE_BUILD_PIPELINE_VERSION) {
|
|
563
563
|
version = process.env.NEEDLE_BUILD_PIPELINE_VERSION;
|
|
@@ -767,6 +767,11 @@ async function invokeBuildPipeline(opts, options = {}) {
|
|
|
767
767
|
const success = code === 0;
|
|
768
768
|
if (!success) {
|
|
769
769
|
log(`Process failed with exit code ${code}`);
|
|
770
|
+
if (resolvedPipelineVersion) {
|
|
771
|
+
needleLog("needle-buildpipeline",
|
|
772
|
+
"To override the pipeline version, set buildPipeline.version in your Vite config or NEEDLE_BUILD_PIPELINE_VERSION when running npm.",
|
|
773
|
+
"log", { dimBody: false, showHeader: false, leadingNewline: true });
|
|
774
|
+
}
|
|
770
775
|
if (pipelineReportedUnknownOption) {
|
|
771
776
|
const pinned = resolvedPipelineVersion ? `@${resolvedPipelineVersion}` : "";
|
|
772
777
|
needleLog("needle-buildpipeline",
|
package/plugins/vite/license.js
CHANGED
|
@@ -49,12 +49,12 @@ export function needleLicense(command, config, userSettings) {
|
|
|
49
49
|
let modified = false;
|
|
50
50
|
|
|
51
51
|
// Replace license type
|
|
52
|
-
const index = src.indexOf("
|
|
52
|
+
const index = src.indexOf("yBXL");
|
|
53
53
|
if (index >= 0) {
|
|
54
54
|
const end = src.indexOf(";", index);
|
|
55
55
|
if (end >= 0) {
|
|
56
56
|
const line = src.substring(index, end);
|
|
57
|
-
const replaced = "
|
|
57
|
+
const replaced = "yBXL = \"" + licenseResult.type + "\"";
|
|
58
58
|
src = src.replace(line, replaced);
|
|
59
59
|
modified = true;
|
|
60
60
|
}
|
|
@@ -62,12 +62,12 @@ export function needleLicense(command, config, userSettings) {
|
|
|
62
62
|
|
|
63
63
|
// Replace license JWT (same pattern)
|
|
64
64
|
if (licenseResult.jwt) {
|
|
65
|
-
const jwtIndex = src.indexOf("
|
|
65
|
+
const jwtIndex = src.indexOf("VkS");
|
|
66
66
|
if (jwtIndex >= 0) {
|
|
67
67
|
const jwtEnd = src.indexOf(";", jwtIndex);
|
|
68
68
|
if (jwtEnd >= 0) {
|
|
69
69
|
const jwtLine = src.substring(jwtIndex, jwtEnd);
|
|
70
|
-
const jwtReplaced = "
|
|
70
|
+
const jwtReplaced = "VkS = \"" + licenseResult.jwt + "\"";
|
|
71
71
|
src = src.replace(jwtLine, jwtReplaced);
|
|
72
72
|
modified = true;
|
|
73
73
|
}
|
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
3
|
let isStringifying = false;
|
|
4
|
+
let isSocketConnected = false;
|
|
5
|
+
/** @type {Array<{level: string, message: string}>} */
|
|
6
|
+
const pendingLogs = [];
|
|
7
|
+
|
|
8
|
+
if (import.meta.hot) {
|
|
9
|
+
import.meta.hot.on("vite:ws:connect", () => {
|
|
10
|
+
isSocketConnected = true;
|
|
11
|
+
for (const log of pendingLogs.splice(0)) {
|
|
12
|
+
import.meta.hot?.send("needle:client-log", log);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
import.meta.hot.on("vite:ws:disconnect", () => {
|
|
16
|
+
isSocketConnected = false;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
4
19
|
|
|
5
20
|
/**
|
|
6
21
|
* Patches console methods to capture log messages and send them to the server.
|
|
@@ -17,16 +32,14 @@ function sendLogToServer(level, ...message) {
|
|
|
17
32
|
if (msg.length > 100_000) {
|
|
18
33
|
msg = msg.slice(0, 100_000) + "... <truncated>";
|
|
19
34
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
} catch (/** @type {any} */ e) {
|
|
23
|
-
// silently fail but send a message
|
|
24
|
-
try {
|
|
25
|
-
import.meta.hot?.send("needle:client-log", { level: "error", message: `Error during logging: ${e?.message ?? String(e)}` });
|
|
35
|
+
if (isSocketConnected && import.meta.hot) {
|
|
36
|
+
import.meta.hot.send("needle:client-log", { level, message: msg });
|
|
26
37
|
}
|
|
27
|
-
|
|
28
|
-
|
|
38
|
+
else if (pendingLogs.length < 100) {
|
|
39
|
+
pendingLogs.push({ level, message: msg });
|
|
29
40
|
}
|
|
41
|
+
} catch (/** @type {any} */ e) {
|
|
42
|
+
// Logging must not break the page if serialization or HMR fails.
|
|
30
43
|
}
|
|
31
44
|
finally {
|
|
32
45
|
isStringifying = false;
|
package/src/engine/api.ts
CHANGED
|
@@ -237,7 +237,7 @@ export * from "./engine_input.js";
|
|
|
237
237
|
export { InstancingUtil } from "./engine_instancing.js";
|
|
238
238
|
|
|
239
239
|
/** License checking utilities */
|
|
240
|
-
export {
|
|
240
|
+
export { _yActo, $TiDhB, __mor } from "./engine_license.js";
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
// ============================================================================
|
|
@@ -293,6 +293,7 @@ export {
|
|
|
293
293
|
* decorator-wrapped ("_DragControls"); document writers need the wire name */
|
|
294
294
|
export { originalComponentNameKey } from "./engine_instantiate_resolve.js";
|
|
295
295
|
export { enableProjectDocumentInspection, getProjectDocumentInspection, type ProjectInspectionTarget } from "./project-document/engine_project_document_inspection.js";
|
|
296
|
+
export { registerDocumentExtensionProvider, type DocumentExtensionRegistration } from './project-document/engine_document_extensions.js';
|
|
296
297
|
|
|
297
298
|
|
|
298
299
|
// ============================================================================
|
|
@@ -35,6 +35,7 @@ import { Input } from './engine_input.js';
|
|
|
35
35
|
import { Telemetry } from './engine_license.js';
|
|
36
36
|
import { invokeLifecycleFunctions } from './engine_lifecycle_functions_internal.js';
|
|
37
37
|
import { type ILightDataRegistry, LightDataRegistry } from './engine_lightdata.js';
|
|
38
|
+
import { disposeGLTFLoaders } from './engine_loaders.gltf.js';
|
|
38
39
|
import { LODsManager } from "./engine_lods.js";
|
|
39
40
|
import * as looputils from './engine_mainloop_utils.js';
|
|
40
41
|
import { NetworkConnection } from './engine_networking.js';
|
|
@@ -303,6 +304,14 @@ export class Context implements IContext {
|
|
|
303
304
|
}
|
|
304
305
|
private _lifecycle: ContextLifecycleMode = "running";
|
|
305
306
|
|
|
307
|
+
/** Completes queued loading/setup callbacks without rendering or stepping simulation. */
|
|
308
|
+
flushPendingSceneSetup(): void {
|
|
309
|
+
const previous = Context.Current;
|
|
310
|
+
Context.Current = this;
|
|
311
|
+
try { looputils.processPreSetupCallbacks(this); }
|
|
312
|
+
finally { Context.Current = previous; }
|
|
313
|
+
}
|
|
314
|
+
|
|
306
315
|
/**
|
|
307
316
|
* Called when switching from "held" back to "running": while held, hierarchy active
|
|
308
317
|
* flags keep updating but activation callbacks are gated. Components that were never
|
|
@@ -1169,6 +1178,8 @@ export class Context implements IContext {
|
|
|
1169
1178
|
// this they are never emptied: a SPA that repeatedly creates and destroys <needle-engine>
|
|
1170
1179
|
// elements keeps every loaded file and image alive for the lifetime of the document.
|
|
1171
1180
|
if (ContextRegistry.Registered.length === 0) {
|
|
1181
|
+
Physics.disposeMeshBVHWorkers();
|
|
1182
|
+
disposeGLTFLoaders();
|
|
1172
1183
|
clearAssetCaches();
|
|
1173
1184
|
// Progressive geometry promises strongly retain meshes and their textures
|
|
1174
1185
|
// through resource-user tracking. The cache is shared by all contexts.
|
|
@@ -8,7 +8,7 @@ import { initBuiltinTypes } from "./codegen/register_types.js";
|
|
|
8
8
|
import { initSpatialConsole } from "./debug/debug_spatial_console.js";
|
|
9
9
|
import { initAddressableSerializers } from "./engine_addressables.js";
|
|
10
10
|
import { ensureAudioContextIsResumed } from "./engine_audio.js";
|
|
11
|
-
import {
|
|
11
|
+
import { _htxWDE } from "./engine_license.js";
|
|
12
12
|
import { initNeedleLoader } from "./engine_loaders.js";
|
|
13
13
|
import { initPhysics } from "./engine_physics_rapier.js";
|
|
14
14
|
import { initBuiltinSerializers } from "./engine_serialization_builtin_serializer.js";
|
|
@@ -59,7 +59,7 @@ export function initEngine() {
|
|
|
59
59
|
initPhysics();
|
|
60
60
|
initXR();
|
|
61
61
|
initSpatialConsole();
|
|
62
|
-
|
|
62
|
+
_htxWDE();
|
|
63
63
|
|
|
64
64
|
// Must be last. customElements.define() upgrades existing <needle-engine>
|
|
65
65
|
// elements synchronously, which can trigger context.create() and dispatch
|
|
@@ -42,19 +42,19 @@ function setLicenseTimeout(ctx: IContext, callback: () => void, delay: number) {
|
|
|
42
42
|
return timer;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
const $
|
|
45
|
+
const $bvy: ((result: boolean) => void)[] = [];
|
|
46
46
|
|
|
47
47
|
// DO NOT EDIT MANUALLY
|
|
48
|
-
let
|
|
48
|
+
let yBXL: string = "";
|
|
49
49
|
// eslint-disable-next-line prefer-const
|
|
50
|
-
let
|
|
50
|
+
let VkS: string = "";
|
|
51
51
|
|
|
52
52
|
if (debug) {
|
|
53
|
-
console.log("License Type: " +
|
|
54
|
-
if (
|
|
55
|
-
console.log("License JWT: " +
|
|
53
|
+
console.log("License Type: " + yBXL);
|
|
54
|
+
if (VkS) {
|
|
55
|
+
console.log("License JWT: " + VkS);
|
|
56
56
|
try {
|
|
57
|
-
const payload = JSON.parse(atob(
|
|
57
|
+
const payload = JSON.parse(atob(VkS.split(".")[1].replace(/-/g, '+').replace(/_/g, '/')));
|
|
58
58
|
console.log("License JWT payload:", payload);
|
|
59
59
|
}
|
|
60
60
|
catch { console.log("License JWT payload: (failed to decode)"); }
|
|
@@ -65,8 +65,8 @@ if (debug) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/** @internal */
|
|
68
|
-
export function
|
|
69
|
-
switch (
|
|
68
|
+
export function __mor() {
|
|
69
|
+
switch (yBXL) {
|
|
70
70
|
case "pro":
|
|
71
71
|
case "enterprise":
|
|
72
72
|
return true;
|
|
@@ -75,8 +75,8 @@ export function _fncZ() {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/** @internal */
|
|
78
|
-
export function
|
|
79
|
-
switch (
|
|
78
|
+
export function $TiDhB() {
|
|
79
|
+
switch (yBXL) {
|
|
80
80
|
case "indie":
|
|
81
81
|
return true;
|
|
82
82
|
}
|
|
@@ -84,8 +84,8 @@ export function sUknx() {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
/** @internal */
|
|
87
|
-
export function
|
|
88
|
-
switch (
|
|
87
|
+
export function __cshwS() {
|
|
88
|
+
switch (yBXL) {
|
|
89
89
|
case "edu":
|
|
90
90
|
return true;
|
|
91
91
|
}
|
|
@@ -93,26 +93,26 @@ export function $QiwPI() {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/** @internal */
|
|
96
|
-
export function
|
|
97
|
-
return
|
|
96
|
+
export function _yActo() {
|
|
97
|
+
return __mor() || $TiDhB() || __cshwS();
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
/** @internal */
|
|
102
|
-
export function
|
|
103
|
-
if (
|
|
102
|
+
export function _PvsqpIB(cb: (result: boolean) => void) {
|
|
103
|
+
if (__mor() || $TiDhB() || __cshwS()) {
|
|
104
104
|
cb(true);
|
|
105
105
|
return () => {};
|
|
106
106
|
}
|
|
107
|
-
$
|
|
107
|
+
$bvy.push(cb);
|
|
108
108
|
return () => {
|
|
109
|
-
const index = $
|
|
110
|
-
if (index >= 0) $
|
|
109
|
+
const index = $bvy.indexOf(cb);
|
|
110
|
+
if (index >= 0) $bvy.splice(index, 1);
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
function
|
|
115
|
-
for (const cb of $
|
|
114
|
+
function GuxGgwYi(result: boolean) {
|
|
115
|
+
for (const cb of $bvy) {
|
|
116
116
|
try {
|
|
117
117
|
cb(result);
|
|
118
118
|
}
|
|
@@ -127,7 +127,7 @@ function _VnbrRHk(result: boolean) {
|
|
|
127
127
|
|
|
128
128
|
// ECDSA P-256 public key for verifying license JWTs (verification-only, safe to ship)
|
|
129
129
|
/* eslint-disable no-secrets/no-secrets -- public key, not a secret */
|
|
130
|
-
const
|
|
130
|
+
const $xvChBB = {
|
|
131
131
|
kty: "EC",
|
|
132
132
|
crv: "P-256",
|
|
133
133
|
x: "A34nyKMjhQYVgzeE4tyLUYdx34TAKogDa7v7PRaO9Lg",
|
|
@@ -151,7 +151,7 @@ function base64urlDecode(str: string): Uint8Array {
|
|
|
151
151
|
* Verify a JWT license token and return the `type` claim if valid.
|
|
152
152
|
* Returns null if the JWT is missing, malformed, or has an invalid signature.
|
|
153
153
|
*/
|
|
154
|
-
async function
|
|
154
|
+
async function _yCe(jwt: string): Promise<string | null> {
|
|
155
155
|
if (!jwt) return null;
|
|
156
156
|
try {
|
|
157
157
|
const parts = jwt.split(".");
|
|
@@ -161,7 +161,7 @@ async function $DgqUv(jwt: string): Promise<string | null> {
|
|
|
161
161
|
|
|
162
162
|
const key = await crypto.subtle.importKey(
|
|
163
163
|
"jwk",
|
|
164
|
-
|
|
164
|
+
$xvChBB,
|
|
165
165
|
{ name: "ECDSA", namedCurve: "P-256" },
|
|
166
166
|
false,
|
|
167
167
|
["verify"]
|
|
@@ -221,16 +221,16 @@ async function $DgqUv(jwt: string): Promise<string | null> {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
/** Verify the injected JWT and update the license type if valid.
|
|
224
|
-
* The engine ONLY trusts the JWT — the plain
|
|
224
|
+
* The engine ONLY trusts the JWT — the plain yBXL string is ignored. */
|
|
225
225
|
let _jwtVerificationPromise: Promise<void> | undefined = undefined;
|
|
226
|
-
async function
|
|
226
|
+
async function uztEyYP(): Promise<void> {
|
|
227
227
|
// The bundled JWT may be empty when a build supplies a signed license file.
|
|
228
228
|
// Do not return early: the meta tag below may provide the JWT instead.
|
|
229
229
|
// Keep the bundled binding mutable so Vite's esbuild pre-bundling does not
|
|
230
230
|
// treat its initial empty value as constant and remove JWT verification.
|
|
231
|
-
let jwt =
|
|
231
|
+
let jwt = VkS;
|
|
232
232
|
// Clear the bundled JWT after reading it; this assignment keeps the binding mutable.
|
|
233
|
-
|
|
233
|
+
VkS = "";
|
|
234
234
|
if (!jwt && typeof document !== "undefined") {
|
|
235
235
|
const licenseFile = document.querySelector('meta[name="needle-license"]')?.getAttribute("content");
|
|
236
236
|
if (licenseFile) {
|
|
@@ -247,14 +247,14 @@ async function __sXiZ(): Promise<void> {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
|
-
const verifiedType = await
|
|
250
|
+
const verifiedType = await _yCe(jwt);
|
|
251
251
|
if (verifiedType) {
|
|
252
|
-
|
|
252
|
+
yBXL = verifiedType;
|
|
253
253
|
if (debug) console.log("License type set from verified JWT: " + verifiedType);
|
|
254
|
-
|
|
254
|
+
GuxGgwYi(_yActo());
|
|
255
255
|
}
|
|
256
256
|
else {
|
|
257
|
-
|
|
257
|
+
yBXL = "basic";
|
|
258
258
|
if (debug && jwt) console.warn("JWT verification failed — license reset to basic");
|
|
259
259
|
}
|
|
260
260
|
}
|
|
@@ -377,7 +377,7 @@ export namespace Telemetry {
|
|
|
377
377
|
// NOTE: this does NOT affect license enforcement — the /check call, the "forbidden"
|
|
378
378
|
// overlay and the watermark/logo run on separate, ungated code paths.
|
|
379
379
|
const attribute = domElement?.getAttribute("no-telemetry");
|
|
380
|
-
if (
|
|
380
|
+
if (__mor() && (attribute === "" || attribute === "true" || attribute === "1")) {
|
|
381
381
|
if (debug) console.debug("Telemetry is disabled via no-telemetry attribute");
|
|
382
382
|
return false;
|
|
383
383
|
}
|
|
@@ -705,21 +705,21 @@ export namespace Telemetry {
|
|
|
705
705
|
}
|
|
706
706
|
|
|
707
707
|
|
|
708
|
-
export function
|
|
708
|
+
export function _htxWDE() {
|
|
709
709
|
|
|
710
|
-
if(
|
|
710
|
+
if(yBXL === "") yBXL = "basic";
|
|
711
711
|
|
|
712
712
|
// Start JWT verification — must be here (not top-level) to avoid tree-shaking
|
|
713
|
-
_jwtVerificationPromise =
|
|
713
|
+
_jwtVerificationPromise = uztEyYP();
|
|
714
714
|
// Start after setting the initial type. At module scope the type was still "",
|
|
715
715
|
// so Basic builds skipped the runtime check entirely.
|
|
716
|
-
|
|
716
|
+
eNaXOZj = __mTgB();
|
|
717
717
|
|
|
718
718
|
Telemetry.init();
|
|
719
719
|
ContextRegistry.registerCallback(ContextEvent.ContextRegistered, evt => {
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
setLicenseTimeout(evt.context, () =>
|
|
720
|
+
__vTpQGDw(evt.context);
|
|
721
|
+
_$ygon(evt.context);
|
|
722
|
+
setLicenseTimeout(evt.context, () => NNhYdA(evt.context), 2000);
|
|
723
723
|
});
|
|
724
724
|
// ContextCreated fires after the renderer exists, so the canvas is available for context-loss monitoring
|
|
725
725
|
ContextRegistry.registerCallback(ContextEvent.ContextCreated, evt => {
|
|
@@ -728,17 +728,17 @@ export function _BQhd() {
|
|
|
728
728
|
});
|
|
729
729
|
}
|
|
730
730
|
|
|
731
|
-
export let
|
|
731
|
+
export let eNaXOZj: Promise<void> | undefined = undefined;
|
|
732
732
|
let applicationIsForbidden = false;
|
|
733
733
|
let applicationForbiddenText = "";
|
|
734
|
-
async function
|
|
734
|
+
async function __mTgB() {
|
|
735
735
|
// Only perform the runtime license check once
|
|
736
|
-
if (
|
|
736
|
+
if (eNaXOZj) return eNaXOZj;
|
|
737
737
|
// Wait for JWT verification to complete first (if running)
|
|
738
738
|
if (_jwtVerificationPromise) {
|
|
739
739
|
await _jwtVerificationPromise;
|
|
740
740
|
}
|
|
741
|
-
if (
|
|
741
|
+
if (yBXL === "basic") {
|
|
742
742
|
try {
|
|
743
743
|
const licenseUrl = "https://needle.tools/api/v1/needle-engine/check?location=" + encodeURIComponent(window.location.href) + "&version=" + VERSION + "&generator=" + encodeURIComponent(GENERATOR);
|
|
744
744
|
const res = await fetch(licenseUrl, {
|
|
@@ -750,27 +750,27 @@ async function __IdN() {
|
|
|
750
750
|
if (res?.status === 200) {
|
|
751
751
|
applicationIsForbidden = false;
|
|
752
752
|
if (debug) console.log("License check succeeded");
|
|
753
|
-
|
|
754
|
-
|
|
753
|
+
yBXL = "pro";
|
|
754
|
+
GuxGgwYi(true);
|
|
755
755
|
}
|
|
756
756
|
else if (res?.status === 403) {
|
|
757
|
-
|
|
757
|
+
GuxGgwYi(false);
|
|
758
758
|
applicationIsForbidden = true;
|
|
759
759
|
applicationForbiddenText = await res.text();
|
|
760
760
|
}
|
|
761
761
|
else {
|
|
762
|
-
|
|
762
|
+
GuxGgwYi(false);
|
|
763
763
|
if (debug) console.log("License check failed with status " + res?.status);
|
|
764
764
|
}
|
|
765
765
|
}
|
|
766
766
|
catch (err) {
|
|
767
|
-
|
|
767
|
+
GuxGgwYi(false);
|
|
768
768
|
if (debug) console.error("License check failed", err);
|
|
769
769
|
}
|
|
770
770
|
}
|
|
771
|
-
else if (debug) console.log("Runtime license check is skipped because license is already applied as \"" +
|
|
771
|
+
else if (debug) console.log("Runtime license check is skipped because license is already applied as \"" + yBXL + "\"");
|
|
772
772
|
}
|
|
773
|
-
async function
|
|
773
|
+
async function _$ygon(ctx: IContext) {
|
|
774
774
|
function createForbiddenElement() {
|
|
775
775
|
const div = document.createElement("div");
|
|
776
776
|
div.className = "needle-forbidden";
|
|
@@ -835,40 +835,40 @@ async function gpJbHEa(ctx: IContext) {
|
|
|
835
835
|
}, 500)
|
|
836
836
|
}
|
|
837
837
|
|
|
838
|
-
async function
|
|
838
|
+
async function __vTpQGDw(ctx: IContext) {
|
|
839
839
|
try {
|
|
840
|
-
if (!
|
|
841
|
-
return
|
|
840
|
+
if (!__mor() && !$TiDhB()) {
|
|
841
|
+
return OGuHjhL(ctx);
|
|
842
842
|
}
|
|
843
843
|
}
|
|
844
844
|
catch (err) {
|
|
845
845
|
if (debug) console.log("License check failed", err)
|
|
846
|
-
return
|
|
846
|
+
return OGuHjhL(ctx)
|
|
847
847
|
}
|
|
848
|
-
if (debug)
|
|
848
|
+
if (debug) OGuHjhL(ctx)
|
|
849
849
|
}
|
|
850
850
|
|
|
851
851
|
|
|
852
852
|
|
|
853
|
-
async function
|
|
853
|
+
async function OGuHjhL(ctx: IContext) {
|
|
854
854
|
|
|
855
855
|
// if the engine loads faster than the license check, we need to capture the ready event here
|
|
856
856
|
let isReady = false;
|
|
857
857
|
ctx.domElement.addEventListener("ready", () => isReady = true);
|
|
858
858
|
|
|
859
|
-
await
|
|
859
|
+
await eNaXOZj?.catch(() => { });
|
|
860
860
|
|
|
861
861
|
|
|
862
|
-
if (
|
|
863
|
-
if (
|
|
862
|
+
if (__mor() || $TiDhB()) return;
|
|
863
|
+
if (_yActo() === false) $xSLUxq();
|
|
864
864
|
|
|
865
865
|
// check if the engine is already ready (meaning has finished loading)
|
|
866
866
|
if (isReady) {
|
|
867
|
-
|
|
867
|
+
_$EZMmp(ctx);
|
|
868
868
|
}
|
|
869
869
|
else {
|
|
870
870
|
ctx.domElement.addEventListener("ready", () => {
|
|
871
|
-
|
|
871
|
+
_$EZMmp(ctx);
|
|
872
872
|
});
|
|
873
873
|
}
|
|
874
874
|
}
|
|
@@ -876,7 +876,7 @@ async function _$SggUg(ctx: IContext) {
|
|
|
876
876
|
// const licenseElementIdentifier = "needle-license-element";
|
|
877
877
|
// const licenseDuration = 10000;
|
|
878
878
|
// const licenseDelay = 1200;
|
|
879
|
-
function
|
|
879
|
+
function _$EZMmp(ctx: IContext) {
|
|
880
880
|
|
|
881
881
|
const style = `
|
|
882
882
|
position: relative;
|
|
@@ -889,7 +889,7 @@ function _pphXrOg(ctx: IContext) {
|
|
|
889
889
|
padding: 10px;
|
|
890
890
|
padding-left: 30px;
|
|
891
891
|
`;
|
|
892
|
-
if (
|
|
892
|
+
if (yBXL === "edu") {
|
|
893
893
|
if (navigator.webdriver) {
|
|
894
894
|
console.log("This project is supported by Needle for Education – https://needle.tools");
|
|
895
895
|
}
|
|
@@ -946,7 +946,7 @@ function _pphXrOg(ctx: IContext) {
|
|
|
946
946
|
}
|
|
947
947
|
}, 1000);
|
|
948
948
|
|
|
949
|
-
if (
|
|
949
|
+
if (__cshwS()) {
|
|
950
950
|
const removeDelay = 20_000;
|
|
951
951
|
setLicenseTimeout(ctx, () => {
|
|
952
952
|
clearInterval(interval);
|
|
@@ -955,7 +955,7 @@ function _pphXrOg(ctx: IContext) {
|
|
|
955
955
|
const intervalInMinutes = 5;
|
|
956
956
|
setLicenseTimeout(ctx, () => {
|
|
957
957
|
if (ctx.domElement.parentNode)
|
|
958
|
-
|
|
958
|
+
_$EZMmp(ctx);
|
|
959
959
|
}, 1000 * 60 * intervalInMinutes)
|
|
960
960
|
}, removeDelay);
|
|
961
961
|
}
|
|
@@ -966,7 +966,7 @@ function _pphXrOg(ctx: IContext) {
|
|
|
966
966
|
const base64Logo = "data:image/webp;base64,UklGRrABAABXRUJQVlA4WAoAAAAQAAAAHwAAHwAAQUxQSKEAAAARN6CmbSM4WR7vdARON11EBDq3fLiNbVtVzpMCPlKAEzsx0Y/x+Ovuv4dn0EFE/ydAvz6YggXzgh5sVgXM/zOC/4sii7qgGvB5N7hmuQYwkvazWAu1JPW41FXSHq6pnaQWvqYH18Fc0j1hO/BFTtIeSBlJi5w6qIIO7IOrwhFsB2Yxukif0FTRLpXswHR8MxbslKe9VZsn/Ub5C7YFOpqSTABWUDgg6AAAAFAGAJ0BKiAAIAA+7VyoTqmkpCI3+qgBMB2JbACdMt69DwMIQBLhkTO6XwY00UEDK6cNIDnuNibPf0EgAP7Y1myuiQHLDsF/0h5unrGh6WAbv7aegg2ZMd3uRKfT/3SJztcaujYfTvMXspfCTmYcoO6a+vhC3ss4M8uM58t4siiu59I4aOl59e9Sr6xoxYlHf2v+NnBNpJYeJf8jABQAId/PXuBkLEFkiCucgSGEcfhvajql/j3reCGl0M5/9gQWy7ayNPs+wlvIxFnNfSlfuND4CZOCyxOHhRqOmHN4ULHo3tCSrUNvgAA=";
|
|
967
967
|
|
|
968
968
|
let lastLogTime = 0;
|
|
969
|
-
async function
|
|
969
|
+
async function $xSLUxq(_logo?: string) {
|
|
970
970
|
const now = Date.now();
|
|
971
971
|
if (now - lastLogTime < 2000) return;
|
|
972
972
|
lastLogTime = now;
|
|
@@ -999,7 +999,7 @@ async function __cOTtAEOb(_logo?: string) {
|
|
|
999
999
|
}
|
|
1000
1000
|
|
|
1001
1001
|
|
|
1002
|
-
async function
|
|
1002
|
+
async function NNhYdA(context: IContext) {
|
|
1003
1003
|
// isAllowed() now also covers cross-origin-isolated pages (where beacons can't be sent)
|
|
1004
1004
|
// and Do Not Track / GPC.
|
|
1005
1005
|
if (!Telemetry.isAllowed(context)) {
|
|
@@ -1013,7 +1013,7 @@ async function _$qviwgZA(context: IContext) {
|
|
|
1013
1013
|
|
|
1014
1014
|
// current url without query parameters
|
|
1015
1015
|
const currentUrl = window.location.href.split("?")[0];
|
|
1016
|
-
const license =
|
|
1016
|
+
const license = yBXL;
|
|
1017
1017
|
|
|
1018
1018
|
const beaconData = {
|
|
1019
1019
|
license,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
|
|
2
|
-
import { addDracoAndKTX2Loaders as addDracoAndKTX2LoadersGLTFProgressive, configureLoader, createLoaders, setDracoDecoderLocation, setKTX2TranscoderLocation } from '@needle-tools/gltf-progressive';
|
|
2
|
+
import { addDracoAndKTX2Loaders as addDracoAndKTX2LoadersGLTFProgressive, configureLoader, createLoaders, disposeLoaders, setDracoDecoderLocation, setKTX2TranscoderLocation } from '@needle-tools/gltf-progressive';
|
|
3
3
|
import { MeshoptDecoder } from 'three/examples/jsm/libs/meshopt_decoder.module.js';
|
|
4
4
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
5
5
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
|
6
6
|
import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader.js';
|
|
7
7
|
|
|
8
|
-
import { Context } from "./engine_setup.js"
|
|
8
|
+
import type { Context } from "./engine_setup.js"
|
|
9
9
|
import { getParam } from "./engine_utils.js";
|
|
10
10
|
|
|
11
11
|
const debug = getParam("debugdecoders");
|
|
@@ -20,6 +20,12 @@ function ensureLoaders() {
|
|
|
20
20
|
return loaders;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
/** Release shared decoder workers after the last engine context is destroyed. */
|
|
24
|
+
export function disposeGLTFLoaders() {
|
|
25
|
+
disposeLoaders();
|
|
26
|
+
loaders = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
export function setDracoDecoderPath(path: string | undefined) {
|
|
24
30
|
if (path !== undefined && typeof path === "string") {
|
|
25
31
|
setDracoDecoderLocation(path);
|