@needle-tools/engine 4.3.2-beta.2 → 4.3.2-beta.4
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.js +91 -90
- package/dist/gltf-progressive.light.js +91 -90
- package/dist/gltf-progressive.light.min.js +6 -6
- package/dist/gltf-progressive.light.umd.cjs +4 -4
- package/dist/gltf-progressive.min.js +6 -6
- package/dist/gltf-progressive.umd.cjs +4 -4
- package/dist/needle-engine.bundle.js +2999 -2990
- package/dist/needle-engine.bundle.light.js +3038 -3029
- package/dist/needle-engine.bundle.light.min.js +112 -112
- package/dist/needle-engine.bundle.light.umd.cjs +96 -96
- package/dist/needle-engine.bundle.min.js +112 -112
- package/dist/needle-engine.bundle.umd.cjs +99 -99
- package/dist/needle-engine.light.d.ts +9 -9
- package/lib/engine/engine_context.d.ts +3 -1
- package/lib/engine/engine_context.js +4 -1
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_context_registry.js +7 -0
- package/lib/engine/engine_context_registry.js.map +1 -1
- package/lib/engine/engine_texture.d.ts +2 -1
- package/lib/engine/engine_texture.js.map +1 -1
- package/lib/engine/engine_tonemapping.js +2 -2
- package/lib/engine/engine_utils_format.js +5 -1
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine-components/Skybox.js +9 -8
- package/lib/engine-components/Skybox.js.map +1 -1
- package/package.json +2 -2
- package/plugins/common/license.js +42 -32
- package/src/engine/engine_context.ts +7 -2
- package/src/engine/engine_context_registry.ts +5 -0
- package/src/engine/engine_texture.ts +3 -2
- package/src/engine/engine_tonemapping.ts +2 -2
- package/src/engine/engine_utils_format.ts +5 -1
- package/src/engine-components/Skybox.ts +8 -7
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { spawn } from "child_process";
|
|
2
|
-
import https from 'https';
|
|
3
|
-
import http from 'http';
|
|
4
2
|
|
|
5
3
|
const port = 8424;
|
|
4
|
+
const packageName = "needle-cloud@version-1";
|
|
6
5
|
const licenseServerUrl = `http://localhost:${port}/api/license`;
|
|
7
6
|
const projectIdentifierUrl = `http://localhost:${port}/api/public_key`;
|
|
8
7
|
|
|
@@ -55,15 +54,33 @@ export async function resolveLicense(args = null) {
|
|
|
55
54
|
console.log(`INFO: Fetching license...`);
|
|
56
55
|
const licenseResponse = await fetch(url.toString(), {
|
|
57
56
|
method: "GET",
|
|
58
|
-
}).catch(
|
|
57
|
+
}).catch(err => {
|
|
58
|
+
if (err.cause.code === "ECONNREFUSED") {
|
|
59
|
+
return { error: "ERR: Failed to connect to license server (ECONNREFUSED)" };
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
return { error: "ERR: Failed to fetch license." };
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
59
66
|
if (!licenseResponse) {
|
|
60
67
|
console.warn("WARN: Failed to fetch license");
|
|
61
68
|
return null;
|
|
62
69
|
}
|
|
70
|
+
else if ("error" in licenseResponse) {
|
|
71
|
+
console.error(licenseResponse.error);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
else if (!licenseResponse.ok) {
|
|
75
|
+
console.error("ERROR: Failed to fetch license");
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const text = await licenseResponse.text();
|
|
63
80
|
|
|
64
81
|
try {
|
|
65
82
|
/** @type {{needle_engine_license:string}} */
|
|
66
|
-
const licenseJson = JSON.parse(
|
|
83
|
+
const licenseJson = JSON.parse(text);
|
|
67
84
|
console.log("\n");
|
|
68
85
|
if (licenseJson.needle_engine_license) {
|
|
69
86
|
console.log(`INFO: Successfully received \"${licenseJson.needle_engine_license?.toUpperCase()}\" license`)
|
|
@@ -99,14 +116,15 @@ export async function getPublicIdentifier(project_id) {
|
|
|
99
116
|
method: "GET",
|
|
100
117
|
});
|
|
101
118
|
|
|
102
|
-
if (!res) {
|
|
119
|
+
if (!res || !res.ok) {
|
|
103
120
|
console.warn("WARN: Failed to fetch project identifier");
|
|
104
121
|
return null;
|
|
105
122
|
}
|
|
123
|
+
const text = await res.text();
|
|
106
124
|
|
|
107
125
|
try {
|
|
108
126
|
/** @type {{public_key:string}} */
|
|
109
|
-
const json = JSON.parse(
|
|
127
|
+
const json = JSON.parse(text);
|
|
110
128
|
return json.public_key;
|
|
111
129
|
}
|
|
112
130
|
catch (err) {
|
|
@@ -121,7 +139,7 @@ export async function getPublicIdentifier(project_id) {
|
|
|
121
139
|
// we need to to wait for the root URL to return a response
|
|
122
140
|
async function waitForLicenseServer() {
|
|
123
141
|
// Make sure the licensing server is running
|
|
124
|
-
runCommand("npx", ["--yes",
|
|
142
|
+
runCommand("npx", ["--yes", packageName, "start-server"]);
|
|
125
143
|
|
|
126
144
|
let attempts = 0;
|
|
127
145
|
while (attempts < 10) {
|
|
@@ -152,7 +170,7 @@ async function runCommand(processName, args) {
|
|
|
152
170
|
if (code === 0) {
|
|
153
171
|
resolve(true);
|
|
154
172
|
} else {
|
|
155
|
-
console.warn(`WARN: ${processName} exited with code ${code}`);
|
|
173
|
+
console.warn(`WARN: \"${processName}\" process exited with code ${code}\nProcess Arguments: ${args.join(" ")}`);
|
|
156
174
|
resolve(false);
|
|
157
175
|
}
|
|
158
176
|
});
|
|
@@ -163,29 +181,21 @@ async function runCommand(processName, args) {
|
|
|
163
181
|
}
|
|
164
182
|
|
|
165
183
|
|
|
166
|
-
/**
|
|
167
|
-
* @param {string} str
|
|
168
|
-
*/
|
|
169
|
-
function obscure(str) {
|
|
170
|
-
const start = str.substring(0, 3);
|
|
171
|
-
return start + "******";
|
|
172
|
-
}
|
|
173
|
-
|
|
174
184
|
|
|
175
185
|
// NODE 16 doesn't support fetch yet
|
|
176
|
-
function fetch(url, options) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
186
|
+
// function fetch(url, options) {
|
|
187
|
+
// const module = url.startsWith("https") ? https : http;
|
|
188
|
+
// return new Promise((resolve, reject) => {
|
|
189
|
+
// module.get(url, options, (res) => {
|
|
190
|
+
// let data = '';
|
|
191
|
+
// res.on('data', (chunk) => {
|
|
192
|
+
// data += chunk;
|
|
193
|
+
// });
|
|
194
|
+
// res.on('end', () => {
|
|
195
|
+
// resolve(data);
|
|
196
|
+
// });
|
|
197
|
+
// }).on("error", (err) => {
|
|
198
|
+
// reject(err);
|
|
199
|
+
// });
|
|
200
|
+
// });
|
|
201
|
+
// }
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
/** @ts-ignore (not yet in types?) */
|
|
11
11
|
import { BasicNodeLibrary } from "three";
|
|
12
12
|
import * as Stats from 'three/examples/jsm/libs/stats.module.js';
|
|
13
|
+
import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
|
|
13
14
|
import { nodeFrame } from "three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js";
|
|
14
15
|
|
|
15
16
|
import { isDevEnvironment, LogType, showBalloonError, showBalloonMessage } from './debug/index.js';
|
|
@@ -188,6 +189,10 @@ export class Context implements IContext {
|
|
|
188
189
|
ContextRegistry.Current = context;
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
static get All(): Context[] {
|
|
193
|
+
return ContextRegistry.All as Context[];
|
|
194
|
+
}
|
|
195
|
+
|
|
191
196
|
/** The name of the context */
|
|
192
197
|
name: string;
|
|
193
198
|
/** An alias for the context */
|
|
@@ -317,7 +322,7 @@ export class Context implements IContext {
|
|
|
317
322
|
|
|
318
323
|
scene: Scene;
|
|
319
324
|
renderer!: WebGLRenderer;
|
|
320
|
-
composer: EffectComposer | null = null;
|
|
325
|
+
composer: EffectComposer | ThreeEffectComposer | null = null;
|
|
321
326
|
|
|
322
327
|
// all scripts
|
|
323
328
|
readonly scripts: IComponent[] = [];
|
|
@@ -1450,7 +1455,7 @@ export class Context implements IContext {
|
|
|
1450
1455
|
|
|
1451
1456
|
if (this.composer && !this.isInXR) {
|
|
1452
1457
|
// if a camera is passed in we need to check if we need to update the composer's camera
|
|
1453
|
-
if (camera) {
|
|
1458
|
+
if (camera && "setMainCamera" in this.composer) {
|
|
1454
1459
|
const currentPassesCamera = this.composer.passes[0]?.mainCamera;
|
|
1455
1460
|
if (currentPassesCamera != camera)
|
|
1456
1461
|
this.composer.setMainCamera(camera);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type IComponent, type IContext, type LoadedModel } from "./engine_types.js";
|
|
2
2
|
|
|
3
|
+
const debug = typeof window !== undefined ? window.location.search.includes("debugcontext") : false;
|
|
4
|
+
|
|
3
5
|
/** The various events that can be dispatched by a Needle Engine {@link IContext} instance
|
|
4
6
|
*/
|
|
5
7
|
export enum ContextEvent {
|
|
@@ -62,6 +64,8 @@ export class ContextRegistry {
|
|
|
62
64
|
|
|
63
65
|
/** @internal Internal use only */
|
|
64
66
|
static register(ctx: IContext) {
|
|
67
|
+
if (this.Registered.indexOf(ctx) !== -1) return;
|
|
68
|
+
if (debug) console.warn("Registering context");
|
|
65
69
|
this.Registered.push(ctx);
|
|
66
70
|
this.dispatchCallback(ContextEvent.ContextRegistered, ctx);
|
|
67
71
|
}
|
|
@@ -70,6 +74,7 @@ export class ContextRegistry {
|
|
|
70
74
|
static unregister(ctx: IContext) {
|
|
71
75
|
const index = this.Registered.indexOf(ctx);
|
|
72
76
|
if (index === -1) return;
|
|
77
|
+
if (debug) console.warn("Unregistering context");
|
|
73
78
|
this.Registered.splice(index, 1);
|
|
74
79
|
}
|
|
75
80
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EffectComposer } from "postprocessing";
|
|
2
2
|
import { Camera, Mesh, Object3D, Texture, WebGLRenderer, WebGLRenderTarget } from "three";
|
|
3
|
+
import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
|
|
3
4
|
|
|
4
5
|
import { findResourceUsers } from "./engine_assetdatabase.js";
|
|
5
6
|
|
|
@@ -27,9 +28,9 @@ export class RenderTexture extends WebGLRenderTarget {
|
|
|
27
28
|
* @param camera The camera to render from
|
|
28
29
|
* @param renderer The renderer or effectcomposer to use
|
|
29
30
|
*/
|
|
30
|
-
render(scene: Object3D, camera: Camera, renderer: WebGLRenderer | EffectComposer) {
|
|
31
|
+
render(scene: Object3D, camera: Camera, renderer: WebGLRenderer | EffectComposer | ThreeEffectComposer) {
|
|
31
32
|
|
|
32
|
-
const composer = renderer as EffectComposer;
|
|
33
|
+
const composer = renderer as (EffectComposer | ThreeEffectComposer);
|
|
33
34
|
|
|
34
35
|
if ("addPass" in composer) {
|
|
35
36
|
if (!this["_unsupported_effectcomposer_warning"]) {
|
|
@@ -87,8 +87,8 @@ vec3 _agx(vec3 val) {
|
|
|
87
87
|
0.0784335999999992, 0.878468636469772, 0.0784336,
|
|
88
88
|
0.0792237451477643, 0.0791661274605434, 0.879142973793104);
|
|
89
89
|
|
|
90
|
-
const float min_ev = -12.
|
|
91
|
-
const float max_ev = 4.
|
|
90
|
+
const float min_ev = -12.47393;
|
|
91
|
+
const float max_ev = 4.026069;
|
|
92
92
|
|
|
93
93
|
// val = pow(val, vec3(2.2));
|
|
94
94
|
|
|
@@ -61,7 +61,11 @@ export async function tryDetermineFileTypeFromURL(url: string, useExtension: boo
|
|
|
61
61
|
|
|
62
62
|
// If the URL doesnt contain a filetype we need to check the header
|
|
63
63
|
// This is the case for example if we load a file from a data url
|
|
64
|
-
const
|
|
64
|
+
const newUrl = new URL(url);
|
|
65
|
+
// Adding a URL parameter to avoid the brower to bust the full cache
|
|
66
|
+
// If we don't do this the file that might already be disc cached will be deleted from the cache
|
|
67
|
+
newUrl.searchParams.append("range", "true");
|
|
68
|
+
const header = await fetch(newUrl, {
|
|
65
69
|
method: "GET",
|
|
66
70
|
headers: {
|
|
67
71
|
"range": "bytes=0-32"
|
|
@@ -5,7 +5,7 @@ import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader.js";
|
|
|
5
5
|
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js';
|
|
6
6
|
|
|
7
7
|
import { disposeObjectResources, setDisposable } from "../engine/engine_assetdatabase.js";
|
|
8
|
-
import { ContextRegistry } from "../engine/engine_context_registry.js";
|
|
8
|
+
import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
|
|
9
9
|
import { registerObservableAttribute } from "../engine/engine_element_extras.js";
|
|
10
10
|
import { syncField } from "../engine/engine_networking_auto.js";
|
|
11
11
|
import { serializable } from "../engine/engine_serialization_decorator.js";
|
|
@@ -39,11 +39,11 @@ function createRemoteSkyboxComponent(context: IContext, url: string, skybox: boo
|
|
|
39
39
|
return remote.setSkybox(url);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
const promises = new Array<Promise<any>>();
|
|
43
|
+
ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, (args) => {
|
|
43
44
|
const context = args.context;
|
|
44
45
|
const skyboxImage = context.domElement.getAttribute("skybox-image") || context.domElement.getAttribute("background-image");
|
|
45
46
|
const environmentImage = context.domElement.getAttribute("environment-image");
|
|
46
|
-
const promises = new Array<Promise<any>>();
|
|
47
47
|
if (skyboxImage) {
|
|
48
48
|
if (debug)
|
|
49
49
|
console.log("Creating remote skybox to load " + skyboxImage);
|
|
@@ -60,10 +60,11 @@ ContextRegistry.addContextCreatedCallback((args) => {
|
|
|
60
60
|
const promise = createRemoteSkyboxComponent(context, environmentImage, false, true, "environment-image");
|
|
61
61
|
promises.push(promise);
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
});
|
|
64
|
+
ContextRegistry.registerCallback(ContextEvent.ContextCreationStart, () => {
|
|
65
|
+
return Promise.all(promises).finally(() => {
|
|
66
|
+
promises.length = 0;
|
|
67
|
+
})
|
|
67
68
|
});
|
|
68
69
|
|
|
69
70
|
declare type SkyboxCacheEntry = { src: string, texture: Promise<Texture> };
|