@needle-tools/engine 4.5.0-alpha → 4.5.0-alpha.2
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 +16 -1
- package/dist/{needle-engine.bundle-a2aadea9.light.js → needle-engine.bundle-1526f05b.light.js} +4883 -4855
- package/dist/{needle-engine.bundle-ff2e699c.light.min.js → needle-engine.bundle-15b19b2c.light.min.js} +122 -116
- package/dist/{needle-engine.bundle-19ca6713.min.js → needle-engine.bundle-2024e2b3.min.js} +122 -116
- package/dist/{needle-engine.bundle-916d62ca.js → needle-engine.bundle-53f80c62.js} +4887 -4859
- package/dist/{needle-engine.bundle-8bee539f.umd.cjs → needle-engine.bundle-a52706c5.umd.cjs} +120 -114
- package/dist/{needle-engine.bundle-032ef70a.light.umd.cjs → needle-engine.bundle-f3c8cffc.light.umd.cjs} +131 -125
- package/dist/needle-engine.js +467 -470
- package/dist/needle-engine.light.js +467 -470
- package/dist/needle-engine.light.min.js +1 -1
- package/dist/needle-engine.light.umd.cjs +1 -1
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- 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.js +5 -1
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_gltf.d.ts +2 -2
- package/lib/engine/engine_gltf_builtin_components.d.ts +5 -1
- package/lib/engine/engine_gltf_builtin_components.js +2 -2
- package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
- package/lib/engine/engine_hot_reload.d.ts +1 -0
- package/lib/engine/engine_hot_reload.js +16 -3
- package/lib/engine/engine_hot_reload.js.map +1 -1
- package/lib/engine/engine_loaders.callbacks.d.ts +62 -0
- package/lib/engine/engine_loaders.callbacks.js +56 -0
- package/lib/engine/engine_loaders.callbacks.js.map +1 -0
- package/lib/engine/engine_loaders.d.ts +44 -9
- package/lib/engine/engine_loaders.gltf.d.ts +13 -0
- package/lib/engine/engine_loaders.gltf.js +63 -0
- package/lib/engine/engine_loaders.gltf.js.map +1 -0
- package/lib/engine/engine_loaders.js +305 -48
- package/lib/engine/engine_loaders.js.map +1 -1
- package/lib/engine/engine_types.d.ts +7 -1
- package/lib/engine/engine_types.js +7 -0
- package/lib/engine/engine_types.js.map +1 -1
- package/lib/engine/engine_utils_format.d.ts +5 -3
- package/lib/engine/engine_utils_format.js +26 -10
- package/lib/engine/engine_utils_format.js.map +1 -1
- package/lib/engine/extensions/extensions.d.ts +3 -2
- package/lib/engine/extensions/extensions.js +10 -6
- package/lib/engine/extensions/extensions.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.attributes.d.ts +3 -6
- 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 +26 -34
- package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
- package/lib/engine-components/AvatarLoader.js +1 -1
- package/lib/engine-components/AvatarLoader.js.map +1 -1
- package/lib/engine-components/Component.js +5 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/webxr/controllers/XRControllerModel.js +4 -3
- package/lib/engine-components/webxr/controllers/XRControllerModel.js.map +1 -1
- package/package.json +1 -1
- package/plugins/vite/reload.js +8 -20
- package/src/engine/api.ts +2 -1
- package/src/engine/engine_context.ts +5 -1
- package/src/engine/engine_gltf.ts +2 -2
- package/src/engine/engine_gltf_builtin_components.ts +7 -7
- package/src/engine/engine_hot_reload.ts +16 -4
- package/src/engine/engine_loaders.callbacks.ts +88 -0
- package/src/engine/engine_loaders.gltf.ts +82 -0
- package/src/engine/engine_loaders.ts +332 -54
- package/src/engine/engine_types.ts +34 -18
- package/src/engine/engine_utils_format.ts +32 -14
- package/src/engine/extensions/extensions.ts +12 -7
- package/src/engine/webcomponents/needle-engine.attributes.ts +3 -6
- package/src/engine/webcomponents/needle-engine.loading.ts +28 -36
- package/src/engine/webcomponents/needle-engine.ts +2 -2
- package/src/engine-components/AvatarLoader.ts +1 -1
- package/src/engine-components/Component.ts +51 -48
- package/src/engine-components/webxr/controllers/XRControllerModel.ts +4 -3
- package/src/engine/engine_scenetools.ts +0 -379
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isDevEnvironment } from "./debug/index.js";
|
|
2
|
+
import { NeedleEngineModelLoader, registeredFileTypeCallbacks } from "./engine_loaders.callbacks.js";
|
|
2
3
|
import { getParam } from "./engine_utils.js";
|
|
3
4
|
|
|
4
5
|
const debug = getParam("debugfileformat");
|
|
@@ -6,7 +7,7 @@ const debug = getParam("debugfileformat");
|
|
|
6
7
|
/**
|
|
7
8
|
* The supported file types that can be determined by the engine. Used in {@link tryDetermineFileTypeFromURL} and {@link tryDetermineFileTypeFromBinary}
|
|
8
9
|
*/
|
|
9
|
-
export declare type FileType = "gltf" | "glb" | "vrm" | "fbx" | "obj" | "usdz" | "usd" | "usda" | "unknown";
|
|
10
|
+
export declare type FileType = "gltf" | "glb" | "vrm" | "fbx" | "obj" | "usdz" | "usd" | "usda" | "unknown" | ({} & string);
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Tries to determine the file type of a file from its URL
|
|
@@ -20,7 +21,9 @@ export declare type FileType = "gltf" | "glb" | "vrm" | "fbx" | "obj" | "usdz" |
|
|
|
20
21
|
* const fileType = await tryDetermineFileTypeFromURL(url);
|
|
21
22
|
* console.log(fileType); // "glb"
|
|
22
23
|
*/
|
|
23
|
-
export async function tryDetermineFileTypeFromURL(url: string, useExtension: boolean
|
|
24
|
+
export async function tryDetermineFileTypeFromURL(url: string, opts: { useExtension: boolean }): Promise<FileType> {
|
|
25
|
+
|
|
26
|
+
const { useExtension = true } = opts;
|
|
24
27
|
|
|
25
28
|
if (useExtension) {
|
|
26
29
|
// We want to save on requests so we first check the file extension if there's any
|
|
@@ -59,11 +62,12 @@ export async function tryDetermineFileTypeFromURL(url: string, useExtension: boo
|
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
|
|
63
66
|
// If the URL doesnt contain a filetype we need to check the header
|
|
64
67
|
// This is the case for example if we load a file from a data url
|
|
68
|
+
const originalUrl = url;
|
|
65
69
|
|
|
66
|
-
if(url.startsWith("blob:")) {
|
|
70
|
+
if (url.startsWith("blob:")) {
|
|
67
71
|
// We can't modify the blob URL
|
|
68
72
|
}
|
|
69
73
|
else {
|
|
@@ -84,7 +88,7 @@ export async function tryDetermineFileTypeFromURL(url: string, useExtension: boo
|
|
|
84
88
|
|
|
85
89
|
if (header?.ok) {
|
|
86
90
|
const data = await header.arrayBuffer();
|
|
87
|
-
const res = tryDetermineFileTypeFromBinary(data, header);
|
|
91
|
+
const res = tryDetermineFileTypeFromBinary(originalUrl, data, header);
|
|
88
92
|
if (debug) console.log("Determined file type from header: " + res);
|
|
89
93
|
return res;
|
|
90
94
|
}
|
|
@@ -96,7 +100,7 @@ export async function tryDetermineFileTypeFromURL(url: string, useExtension: boo
|
|
|
96
100
|
/** Attempts to determine the file type of a binary file by looking at the first few bytes of the file.
|
|
97
101
|
* @hidden
|
|
98
102
|
*/
|
|
99
|
-
export function tryDetermineFileTypeFromBinary(data: ArrayBuffer, response: Response): FileType {
|
|
103
|
+
export function tryDetermineFileTypeFromBinary(url: string, data: ArrayBuffer, response: Response): FileType {
|
|
100
104
|
|
|
101
105
|
if (data.byteLength < 4) {
|
|
102
106
|
return "unknown";
|
|
@@ -193,14 +197,6 @@ export function tryDetermineFileTypeFromBinary(data: ArrayBuffer, response: Resp
|
|
|
193
197
|
console.debug("OBJ detected (mtllib)");
|
|
194
198
|
return "obj";
|
|
195
199
|
}
|
|
196
|
-
|
|
197
|
-
if (isDevEnvironment() || debug) {
|
|
198
|
-
const text = new TextDecoder().decode(data.slice(0, 16));
|
|
199
|
-
console.debug("Could not determine file type from binary data: \"" + text + "...\"", bytes);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
console.debug("Could not determine file type from binary data", bytes);
|
|
203
|
-
}
|
|
204
200
|
// const text = new TextDecoder().decode(data);
|
|
205
201
|
// if (text.startsWith("Kaydara FBX")) {
|
|
206
202
|
// return "fbx";
|
|
@@ -209,5 +205,27 @@ export function tryDetermineFileTypeFromBinary(data: ArrayBuffer, response: Resp
|
|
|
209
205
|
// return "gltf";
|
|
210
206
|
// }
|
|
211
207
|
|
|
208
|
+
for (const callback of registeredFileTypeCallbacks) {
|
|
209
|
+
const mimetype = callback({
|
|
210
|
+
url: url,
|
|
211
|
+
response: response,
|
|
212
|
+
contentType: response.headers.get("content-type"),
|
|
213
|
+
bytes: bytes
|
|
214
|
+
})
|
|
215
|
+
if (mimetype) {
|
|
216
|
+
if (debug) console.debug(`Mimetype callback returned: ${mimetype}`);
|
|
217
|
+
return mimetype;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
if (isDevEnvironment() || debug) {
|
|
223
|
+
const text = new TextDecoder().decode(data.slice(0, Math.min(data.byteLength, 32)));
|
|
224
|
+
console.warn(`Could not determine file type.\n\nConsider registering a custom loader via the 'onCreateCustomModelLoader' callback: 'NeedleEngineModelLoader.onCreateCustomModelLoader(args => { })'\n\nContent-Type: \"${response.headers.get("content-type")}\n\"Text: \"${text}\"\nBinary:`, bytes);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
console.debug(`Could not determine file type from binary data`);
|
|
228
|
+
}
|
|
229
|
+
|
|
212
230
|
return "unknown";
|
|
213
231
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Loader } from "three";
|
|
1
2
|
import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
2
3
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
3
4
|
|
|
@@ -66,13 +67,17 @@ export function removeCustomImportExtensionType(ext: INeedleGLTFExtensionPlugin)
|
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
/** Registers the Needle Engine components extension */
|
|
69
|
-
export function registerComponentExtension(loader: GLTFLoader): NEEDLE_components {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
export function registerComponentExtension(loader: GLTFLoader | Loader | object): NEEDLE_components | null {
|
|
71
|
+
if (loader instanceof GLTFLoader) {
|
|
72
|
+
const ext = new NEEDLE_components();
|
|
73
|
+
loader.register(p => {
|
|
74
|
+
ext.parser = p;
|
|
75
|
+
return ext;
|
|
76
|
+
});
|
|
73
77
|
return ext;
|
|
74
|
-
}
|
|
75
|
-
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return null;
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
|
|
@@ -130,7 +135,7 @@ export function registerExportExtensions(exp: GLTFExporter, context: Context) {
|
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
/** @internal */
|
|
133
|
-
export function
|
|
138
|
+
export function invokeLoadedImportPluginHooks(url: string, gltf: GLTF, context: Context) {
|
|
134
139
|
for (const ext of _plugins)
|
|
135
140
|
if (ext.onLoaded) ext.onLoaded(url, gltf, context);
|
|
136
141
|
}
|
|
@@ -31,19 +31,16 @@ type MainAttributes = {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
type LoadingAttributes = {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
/** Set a custom loading background color (e.g. "red" or "#dd00ff" or "rgba(18, 224, 224, 0.5)") */
|
|
35
|
+
"loading-background"?: string,
|
|
36
|
+
/** Pro features */
|
|
36
37
|
"hide-loading-overlay"?: boolean,
|
|
37
38
|
/** Pro feature */
|
|
38
|
-
"loading-background-color"?: string,
|
|
39
|
-
/** Pro feature */
|
|
40
39
|
"loading-logo-src"?: string,
|
|
41
40
|
/** Pro feature */
|
|
42
41
|
"primary-color"?: string,
|
|
43
42
|
/** Pro feature */
|
|
44
43
|
"secondary-color"?: string,
|
|
45
|
-
/** Pro feature */
|
|
46
|
-
"loading-text-color"?: string,
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
type SkyboxAttributes = {
|
|
@@ -197,10 +197,12 @@ export class EngineLoadingView implements ILoadingViewHandler {
|
|
|
197
197
|
this._loadingElement.style.height = "100%";
|
|
198
198
|
this._loadingElement.style.left = "0";
|
|
199
199
|
this._loadingElement.style.top = "0";
|
|
200
|
-
|
|
201
|
-
|
|
200
|
+
const loadingBackgroundColor = this._element.getAttribute("loading-background");
|
|
201
|
+
if (loadingBackgroundColor) {
|
|
202
|
+
this._loadingElement.style.background = loadingBackgroundColor;
|
|
203
|
+
}
|
|
202
204
|
else
|
|
203
|
-
this._loadingElement.style.backgroundColor = "
|
|
205
|
+
this._loadingElement.style.backgroundColor = "transparent";
|
|
204
206
|
this._loadingElement.style.display = "flex";
|
|
205
207
|
this._loadingElement.style.alignItems = "center";
|
|
206
208
|
this._loadingElement.style.justifyContent = "center";
|
|
@@ -214,16 +216,6 @@ export class EngineLoadingView implements ILoadingViewHandler {
|
|
|
214
216
|
this._loadingElement.style.color = "rgba(0,0,0,.6)";
|
|
215
217
|
else
|
|
216
218
|
this._loadingElement.style.color = "rgba(255,255,255,.3)";
|
|
217
|
-
if (hasLicense && this._element) {
|
|
218
|
-
const loadingBackgroundColor = this._element.getAttribute("loading-background-color");
|
|
219
|
-
if (loadingBackgroundColor) {
|
|
220
|
-
this._loadingElement.style.backgroundColor = loadingBackgroundColor;
|
|
221
|
-
}
|
|
222
|
-
const textColor = this._element.getAttribute("loading-text-color");
|
|
223
|
-
if (textColor) {
|
|
224
|
-
this._loadingElement.style.color = textColor;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
219
|
}
|
|
228
220
|
|
|
229
221
|
const className = this._loadingElementOptions?.className ?? EngineLoadingView.LoadingContainerClassName;
|
|
@@ -302,8 +294,8 @@ export class EngineLoadingView implements ILoadingViewHandler {
|
|
|
302
294
|
const getGradientPos = function (t: number): string {
|
|
303
295
|
return Mathf.lerp(0, maxWidth, t) + "%";
|
|
304
296
|
}
|
|
305
|
-
this._loadingBar.style.background =
|
|
306
|
-
`linear-gradient(90deg, #204f49 ${getGradientPos(0)}, #0BA398 ${getGradientPos(.3)}, #66A22F ${getGradientPos(.6)}, #D7DB0A ${getGradientPos(1)})`;
|
|
297
|
+
this._loadingBar.style.background = "#66A22F";
|
|
298
|
+
// `linear-gradient(90deg, #204f49 ${getGradientPos(0)}, #0BA398 ${getGradientPos(.3)}, #66A22F ${getGradientPos(.6)}, #D7DB0A ${getGradientPos(1)})`;
|
|
307
299
|
this._loadingBar.style.backgroundAttachment = "fixed";
|
|
308
300
|
this._loadingBar.style.width = "0%";
|
|
309
301
|
this._loadingBar.style.height = "100%";
|
|
@@ -321,27 +313,27 @@ export class EngineLoadingView implements ILoadingViewHandler {
|
|
|
321
313
|
}
|
|
322
314
|
}
|
|
323
315
|
|
|
324
|
-
this._loadingTextContainer = document.createElement("div");
|
|
325
|
-
this._loadingTextContainer.style.display = "flex";
|
|
326
|
-
this._loadingTextContainer.style.justifyContent = "center";
|
|
327
|
-
this._loadingTextContainer.style.marginTop = ".2rem";
|
|
328
|
-
details.appendChild(this._loadingTextContainer);
|
|
329
|
-
|
|
330
|
-
const messageContainer = document.createElement("div");
|
|
331
|
-
this._messageContainer = messageContainer;
|
|
332
|
-
messageContainer.style.display = "flex";
|
|
333
|
-
messageContainer.style.fontSize = ".8rem";
|
|
334
|
-
messageContainer.style.paddingTop = ".1rem";
|
|
335
|
-
// messageContainer.style.border = "1px solid rgba(255,255,255,.1)";
|
|
336
|
-
messageContainer.style.justifyContent = "center";
|
|
337
|
-
details.appendChild(messageContainer);
|
|
338
|
-
|
|
339
|
-
if (hasLicense && this._element) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
316
|
+
// this._loadingTextContainer = document.createElement("div");
|
|
317
|
+
// this._loadingTextContainer.style.display = "flex";
|
|
318
|
+
// this._loadingTextContainer.style.justifyContent = "center";
|
|
319
|
+
// this._loadingTextContainer.style.marginTop = ".2rem";
|
|
320
|
+
// details.appendChild(this._loadingTextContainer);
|
|
321
|
+
|
|
322
|
+
// const messageContainer = document.createElement("div");
|
|
323
|
+
// this._messageContainer = messageContainer;
|
|
324
|
+
// messageContainer.style.display = "flex";
|
|
325
|
+
// messageContainer.style.fontSize = ".8rem";
|
|
326
|
+
// messageContainer.style.paddingTop = ".1rem";
|
|
327
|
+
// // messageContainer.style.border = "1px solid rgba(255,255,255,.1)";
|
|
328
|
+
// messageContainer.style.justifyContent = "center";
|
|
329
|
+
// details.appendChild(messageContainer);
|
|
330
|
+
|
|
331
|
+
// if (hasLicense && this._element) {
|
|
332
|
+
// const loadingTextColor = this._element.getAttribute("loading-text-color");
|
|
333
|
+
// if (loadingTextColor) {
|
|
334
|
+
// messageContainer.style.color = loadingTextColor;
|
|
335
|
+
// }
|
|
336
|
+
// }
|
|
345
337
|
|
|
346
338
|
this.handleRuntimeLicense(this._loadingElement);
|
|
347
339
|
|
|
@@ -4,8 +4,8 @@ import { isDevEnvironment, showBalloonWarning } from "../debug/index.js";
|
|
|
4
4
|
import { PUBLIC_KEY, VERSION } from "../engine_constants.js";
|
|
5
5
|
import { registerLoader } from "../engine_gltf.js";
|
|
6
6
|
import { hasCommercialLicense } from "../engine_license.js";
|
|
7
|
-
import { setDracoDecoderPath, setDracoDecoderType, setKtx2TranscoderPath } from "../engine_loaders.js";
|
|
8
|
-
import { NeedleLoader } from "../
|
|
7
|
+
import { setDracoDecoderPath, setDracoDecoderType, setKtx2TranscoderPath } from "../engine_loaders.gltf.js";
|
|
8
|
+
import { NeedleLoader } from "../engine_loaders.js";
|
|
9
9
|
import { Context, ContextCreateArgs } from "../engine_setup.js";
|
|
10
10
|
import { type INeedleEngineComponent, type LoadedModel } from "../engine_types.js";
|
|
11
11
|
import { getParam } from "../engine_utils.js";
|
|
@@ -3,7 +3,7 @@ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
|
3
3
|
|
|
4
4
|
import { InstantiateOptions } from "../engine/engine_gameobject.js";
|
|
5
5
|
import { getLoader } from "../engine/engine_gltf.js";
|
|
6
|
-
import * as loaders from "../engine/engine_loaders.js"
|
|
6
|
+
import * as loaders from "../engine/engine_loaders.gltf.js"
|
|
7
7
|
import { Context } from "../engine/engine_setup.js";
|
|
8
8
|
import * as utils from "../engine/engine_utils.js"
|
|
9
9
|
import { GameObject } from "./Component.js";
|