@needle-tools/engine 4.15.0-next.f391a30 → 4.15.0
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/components.needle.json +1 -1
- package/dist/{gltf-progressive-CTlvpS3A.js → gltf-progressive-Bm_6aEi4.js} +1 -1
- package/dist/{gltf-progressive-CMwJPwEt.umd.cjs → gltf-progressive-BttGBXw6.umd.cjs} +1 -1
- package/dist/{gltf-progressive-DYL3SLVb.min.js → gltf-progressive-T5WKTux5.min.js} +1 -1
- package/dist/materialx-CJyQZtjt.min.js +90 -0
- package/dist/materialx-DMs1E08Z.js +4636 -0
- package/dist/materialx-DaKKOoVk.umd.cjs +90 -0
- package/dist/{needle-engine.bundle-DsTdfmeb.min.js → needle-engine.bundle-CBq_OMnI.min.js} +122 -124
- package/dist/{needle-engine.bundle-DB4kLWO_.js → needle-engine.bundle-DGyiwNWR.js} +3226 -3232
- package/dist/{needle-engine.bundle-C1BFRZDF.umd.cjs → needle-engine.bundle-JN3eiiYc.umd.cjs} +113 -115
- package/dist/needle-engine.d.ts +52 -33
- package/dist/needle-engine.js +288 -287
- package/dist/needle-engine.min.js +1 -1
- package/dist/needle-engine.umd.cjs +1 -1
- package/dist/{postprocessing-BN-f4viE.min.js → postprocessing-06AXuvdv.min.js} +1 -1
- package/dist/{postprocessing-De9ZpJrk.js → postprocessing-CI2x8Cln.js} +1 -1
- package/dist/{postprocessing-DYmYOVm4.umd.cjs → postprocessing-CPDcA21P.umd.cjs} +1 -1
- package/dist/{three-examples-BHqRVpO_.umd.cjs → three-examples-BMmNgNCN.umd.cjs} +12 -12
- package/dist/{three-examples-C0ZCCA_K.js → three-examples-CMYCd5nH.js} +192 -182
- package/dist/{three-examples-DmTY8tGr.min.js → three-examples-CQl1fFZp.min.js} +14 -14
- package/lib/engine/api.d.ts +2 -0
- package/lib/engine/api.js +2 -0
- package/lib/engine/api.js.map +1 -1
- package/lib/engine/debug/debug.js +1 -1
- package/lib/engine/debug/debug.js.map +1 -1
- package/lib/engine/debug/debug_spatial_console.js +1 -1
- package/lib/engine/debug/debug_spatial_console.js.map +1 -1
- package/lib/engine/engine_accessibility.d.ts +1 -1
- package/lib/engine/engine_accessibility.js +1 -1
- package/lib/engine/engine_accessibility.js.map +1 -1
- package/lib/engine/engine_context.d.ts +1 -1
- package/lib/engine/engine_context.js +2 -2
- package/lib/engine/engine_context.js.map +1 -1
- package/lib/engine/engine_create_objects.js +1 -1
- package/lib/engine/engine_create_objects.js.map +1 -1
- package/lib/engine/engine_gizmos.js +1 -1
- package/lib/engine/engine_gizmos.js.map +1 -1
- package/lib/engine/engine_license.js +2 -7
- package/lib/engine/engine_license.js.map +1 -1
- package/lib/engine/engine_test_utils.d.ts +39 -0
- package/lib/engine/engine_test_utils.js +84 -0
- package/lib/engine/engine_test_utils.js.map +1 -0
- package/lib/engine/engine_utils.js +2 -2
- package/lib/engine/engine_utils.js.map +1 -1
- package/lib/engine/export/gltf/index.js +1 -1
- package/lib/engine/export/gltf/index.js.map +1 -1
- package/lib/engine/webcomponents/logo-element.d.ts +3 -6
- package/lib/engine/webcomponents/logo-element.js +0 -18
- package/lib/engine/webcomponents/logo-element.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.d.ts +7 -10
- package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -14
- package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js +1 -10
- package/lib/engine/webcomponents/needle-engine.ar-overlay.js.map +1 -1
- package/lib/engine/webcomponents/needle-engine.d.ts +0 -3
- package/lib/engine/webcomponents/needle-engine.js +0 -10
- package/lib/engine/webcomponents/needle-engine.js.map +1 -1
- package/lib/engine-components/Component.js +1 -0
- package/lib/engine-components/Component.js.map +1 -1
- package/lib/engine-components/ReflectionProbe.d.ts +2 -24
- package/lib/engine-components/ReflectionProbe.js +2 -28
- package/lib/engine-components/ReflectionProbe.js.map +1 -1
- package/lib/engine-components/Skybox.js +2 -4
- package/lib/engine-components/Skybox.js.map +1 -1
- package/lib/engine-components/export/gltf/GltfExport.js +1 -1
- package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
- package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +2 -2
- package/lib/engine-components/export/usdz/USDZExporter.js +1 -1
- package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +2 -2
- package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js.map +1 -1
- package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
- package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
- package/package.json +14 -18
- package/plugins/common/buildinfo.js +10 -46
- package/plugins/common/files.js +1 -2
- package/plugins/common/license.js +69 -144
- package/plugins/common/logger.js +11 -172
- package/plugins/common/worker.js +4 -5
- package/plugins/types/userconfig.d.ts +2 -40
- package/plugins/vite/alias.js +5 -6
- package/plugins/vite/asap.js +5 -6
- package/plugins/vite/build-pipeline.js +41 -224
- package/plugins/vite/buildinfo.js +6 -66
- package/plugins/vite/copyfiles.js +12 -41
- package/plugins/vite/custom-element-data.js +16 -26
- package/plugins/vite/defines.js +5 -8
- package/plugins/vite/dependencies.js +10 -16
- package/plugins/vite/dependency-watcher.js +7 -35
- package/plugins/vite/drop-client.js +5 -7
- package/plugins/vite/drop.js +14 -16
- package/plugins/vite/editor-connection.js +16 -18
- package/plugins/vite/imports-logger.js +2 -12
- package/plugins/vite/index.js +3 -8
- package/plugins/vite/local-files.js +441 -2
- package/plugins/vite/logger.client.js +35 -45
- package/plugins/vite/logger.js +3 -6
- package/plugins/vite/meta.js +4 -18
- package/plugins/vite/needle-app.js +3 -4
- package/plugins/vite/peer.js +1 -2
- package/plugins/vite/pwa.js +17 -33
- package/plugins/vite/reload.js +2 -24
- package/src/engine/api.ts +3 -0
- package/src/engine/debug/debug.ts +1 -1
- package/src/engine/debug/debug_spatial_console.ts +1 -5
- package/src/engine/engine_accessibility.ts +1 -2
- package/src/engine/engine_context.ts +2 -2
- package/src/engine/engine_create_objects.ts +1 -1
- package/src/engine/engine_gizmos.ts +5 -9
- package/src/engine/engine_license.ts +2 -7
- package/src/engine/engine_test_utils.ts +109 -0
- package/src/engine/engine_utils.ts +2 -2
- package/src/engine/export/gltf/index.ts +1 -1
- package/src/engine/webcomponents/logo-element.ts +3 -20
- package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -6
- package/src/engine/webcomponents/needle menu/needle-menu.ts +11 -23
- package/src/engine/webcomponents/needle-engine.ar-overlay.ts +2 -13
- package/src/engine/webcomponents/needle-engine.ts +1 -13
- package/src/engine-components/Component.ts +2 -1
- package/src/engine-components/ReflectionProbe.ts +9 -33
- package/src/engine-components/Skybox.ts +2 -4
- package/src/engine-components/export/gltf/GltfExport.ts +1 -1
- package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2 -2
- package/src/engine-components/export/usdz/USDZExporter.ts +1 -1
- package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +2 -2
- package/src/include/draco/draco_decoder.js +34 -0
- package/src/include/draco/draco_decoder.wasm +0 -0
- package/src/include/draco/draco_wasm_wrapper.js +117 -0
- package/src/include/ktx2/basis_transcoder.js +19 -0
- package/src/include/ktx2/basis_transcoder.wasm +0 -0
- package/src/include/needle/arial-msdf.json +1472 -0
- package/src/include/needle/arial.png +0 -0
- package/src/include/needle/poweredbyneedle.webp +0 -0
- package/dist/materialx-4jJLLe9Q.js +0 -4174
- package/dist/materialx-Bt9FHwco.min.js +0 -158
- package/dist/materialx-NDD0y4JY.umd.cjs +0 -158
- package/lib/engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js.map +0 -1
- package/plugins/common/needle-engine-skill.md +0 -175
- package/plugins/vite/ai.js +0 -71
- package/plugins/vite/local-files-analysis.js +0 -789
- package/plugins/vite/local-files-core.js +0 -992
- package/plugins/vite/local-files-internals.js +0 -28
- package/plugins/vite/local-files-types.d.ts +0 -111
- package/plugins/vite/local-files-utils.js +0 -359
- package/plugins/vite/logging.js +0 -129
- /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.d.ts +0 -0
- /package/lib/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
- /package/src/{engine/export/gltf → include/three}/EXT_mesh_gpu_instancing_exporter.js +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { DataTextureLoader,EquirectangularReflectionMapping, Object3D, PerspectiveCamera, Scene, Vector3 } from "three";
|
|
2
|
+
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
3
|
+
|
|
4
|
+
import { AssetReference } from "./engine_addressables.js";
|
|
5
|
+
import { getBoundingBox } from "./engine_three_utils.js";
|
|
6
|
+
|
|
7
|
+
declare type ComparisonSceneOptions = {
|
|
8
|
+
/**
|
|
9
|
+
* An array of model urls to load
|
|
10
|
+
*/
|
|
11
|
+
files: string[];
|
|
12
|
+
/**
|
|
13
|
+
* Optional dom element to attach the orbit controls to. By default this should be the WebGLRenderer.domElement
|
|
14
|
+
*/
|
|
15
|
+
domElement?: HTMLElement;
|
|
16
|
+
/**
|
|
17
|
+
* Can be a .hdr or .exr file url
|
|
18
|
+
*/
|
|
19
|
+
environment?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A collection of utility methods for quickly spinning up test environments
|
|
24
|
+
*/
|
|
25
|
+
export class TestSceneUtils {
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Use this method to quickly setup a scene to compare multiple models.
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const files = [
|
|
32
|
+
* "https://threejs.org/examples/models/gltf/RobotExpressive/RobotExpressive.glb",
|
|
33
|
+
* "https://threejs.org/examples/models/gltf/Lantern/glTF-Binary/Lantern.glb",
|
|
34
|
+
* ];
|
|
35
|
+
* const { scene, camera } = await TestUtils.createComparisonScene({ files });
|
|
36
|
+
* // this could now be assigned to the Needle Engine Context
|
|
37
|
+
* context.scene = scene;
|
|
38
|
+
* context.mainCamera = camera;
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
static async createComparisonScene(opts: ComparisonSceneOptions) {
|
|
42
|
+
|
|
43
|
+
const { files } = opts;
|
|
44
|
+
|
|
45
|
+
const promises = Promise.all(files.map(file => new AssetReference(file).loadAssetAsync()));
|
|
46
|
+
const results = await promises;
|
|
47
|
+
const scene = new Scene();
|
|
48
|
+
|
|
49
|
+
let offset = 0;
|
|
50
|
+
for (const result of results) {
|
|
51
|
+
if (result instanceof Object3D) {
|
|
52
|
+
result.position.y = offset;
|
|
53
|
+
scene.add(result);
|
|
54
|
+
const box = getBoundingBox([result]);
|
|
55
|
+
offset += box.getSize(new Vector3()).y;
|
|
56
|
+
offset += .1;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const camera = new PerspectiveCamera(20);
|
|
60
|
+
scene.add(camera);
|
|
61
|
+
|
|
62
|
+
// Load an environment map
|
|
63
|
+
const environmentUrl = opts.environment || "https://dl.polyhaven.org/file/ph-assets/HDRIs/exr/1k/studio_small_09_1k.exr";
|
|
64
|
+
if (environmentUrl) {
|
|
65
|
+
let loader: DataTextureLoader | null = null;
|
|
66
|
+
if (environmentUrl.endsWith(".hdr")) {
|
|
67
|
+
const RGBELoader = (await import("three/examples/jsm/loaders/RGBELoader.js")).RGBELoader;
|
|
68
|
+
loader = new RGBELoader();
|
|
69
|
+
}
|
|
70
|
+
else if (environmentUrl.endsWith(".exr")) {
|
|
71
|
+
const EXRLoader = (await import("three/examples/jsm/loaders/EXRLoader.js")).EXRLoader;
|
|
72
|
+
loader = new EXRLoader();
|
|
73
|
+
}
|
|
74
|
+
if (loader) {
|
|
75
|
+
const envmap = await loader.loadAsync(environmentUrl).catch((e) => { console.error(e); return null; });
|
|
76
|
+
if (envmap) {
|
|
77
|
+
envmap.mapping = EquirectangularReflectionMapping;
|
|
78
|
+
envmap.needsUpdate = true;
|
|
79
|
+
scene.background = envmap;
|
|
80
|
+
scene.environment = envmap;
|
|
81
|
+
scene.backgroundBlurriness = .75;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else console.warn("Unsupported environment map format", environmentUrl);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const box = getBoundingBox(scene.children);
|
|
88
|
+
const center = box.getCenter(new Vector3());
|
|
89
|
+
const size = box.getSize(new Vector3());
|
|
90
|
+
const max = Math.max(size.x, size.y, size.z);
|
|
91
|
+
const distance = max / (2 * Math.tan(Math.PI * camera.fov / 360));
|
|
92
|
+
camera.position.set(center.x, center.y, distance);
|
|
93
|
+
camera.lookAt(center);
|
|
94
|
+
|
|
95
|
+
const orbit = new OrbitControls(camera, opts.domElement || document.body);
|
|
96
|
+
orbit.target = center;
|
|
97
|
+
orbit.update();
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
const element = (opts.domElement || document.body).getBoundingClientRect();
|
|
101
|
+
camera.aspect = element.width / element.height;
|
|
102
|
+
camera.updateProjectionMatrix();
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
scene,
|
|
106
|
+
camera
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -607,7 +607,7 @@ export namespace DeviceUtilities {
|
|
|
607
607
|
/** @returns `true` if it's a phone or tablet */
|
|
608
608
|
export function isMobileDevice() {
|
|
609
609
|
if (_ismobile !== undefined) return _ismobile;
|
|
610
|
-
// eslint-disable-next-line
|
|
610
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
611
611
|
if ((typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1)) {
|
|
612
612
|
return _ismobile = true;
|
|
613
613
|
}
|
|
@@ -677,7 +677,7 @@ export namespace DeviceUtilities {
|
|
|
677
677
|
/** @returns `true` for mobile Apple devices like iPad, iPhone, iPod, Vision Pro, ... */
|
|
678
678
|
export function isiOS() {
|
|
679
679
|
if (__isiOS !== undefined) return __isiOS;
|
|
680
|
-
// eslint-disable-next-line
|
|
680
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
681
681
|
return __isiOS = iosDevices.includes(navigator.platform)
|
|
682
682
|
// iPad on iOS 13 detection
|
|
683
683
|
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document)
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { AnimationClip, Object3D } from "three";
|
|
2
2
|
import { GLTFExporter, GLTFExporterOptions } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
3
3
|
|
|
4
|
+
import GLTFMeshGPUInstancingExtension from "../../../include/three/EXT_mesh_gpu_instancing_exporter.js";
|
|
4
5
|
import { AnimationUtils } from "../../engine_animation.js";
|
|
5
6
|
import type { Context } from "../../engine_setup.js";
|
|
6
7
|
import { registerExportExtensions } from "../../extensions/index.js";
|
|
7
8
|
import { __isExporting } from "../state.js";
|
|
8
9
|
import { shouldExport_HideFlags } from "../utils.js";
|
|
9
|
-
import GLTFMeshGPUInstancingExtension from "./EXT_mesh_gpu_instancing_exporter.js";
|
|
10
10
|
import { GizmoWriter as GLTFGizmoWriter, RenderTextureWriter as GLTFRenderTextureWriter } from "./Writers.js";
|
|
11
11
|
|
|
12
12
|
declare type ExportOptions = {
|
|
@@ -20,13 +20,8 @@ export class NeedleLogoElement extends HTMLElement {
|
|
|
20
20
|
return document.createElement(elementName) as NeedleLogoElement;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
private _didInitialize = false;
|
|
24
|
-
|
|
25
23
|
constructor() {
|
|
26
24
|
super();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
private initializeDom() {
|
|
30
25
|
this._root = this.attachShadow({ mode: 'closed' });
|
|
31
26
|
const template = document.createElement('template');
|
|
32
27
|
template.innerHTML = `<style>
|
|
@@ -88,37 +83,25 @@ export class NeedleLogoElement extends HTMLElement {
|
|
|
88
83
|
this.addEventListener("click", () => {
|
|
89
84
|
globalThis.open("https://needle.tools", "_blank");
|
|
90
85
|
});
|
|
91
|
-
}
|
|
92
86
|
|
|
93
|
-
ensureInitialized() {
|
|
94
|
-
if (!this._didInitialize) {
|
|
95
|
-
this._didInitialize = true;
|
|
96
|
-
this.initializeDom();
|
|
97
|
-
}
|
|
98
87
|
}
|
|
99
88
|
|
|
100
89
|
connectedCallback() {
|
|
101
|
-
this.ensureInitialized();
|
|
102
|
-
if (!this.wrapper) return;
|
|
103
90
|
this.wrapper.setAttribute("title", "Made with Needle Engine");
|
|
104
91
|
this.setAttribute("aria-label", "Needle Engine logo. Click to open the Needle Engine website.");
|
|
105
92
|
}
|
|
106
93
|
|
|
107
|
-
private _root
|
|
108
|
-
private wrapper
|
|
109
|
-
private logoElement
|
|
94
|
+
private readonly _root: ShadowRoot;
|
|
95
|
+
private readonly wrapper: HTMLDivElement;
|
|
96
|
+
private readonly logoElement: HTMLImageElement;
|
|
110
97
|
|
|
111
98
|
/** Show or hide the logo element (used by the menu) */
|
|
112
99
|
setLogoVisible(val: boolean) {
|
|
113
|
-
this.ensureInitialized();
|
|
114
|
-
if (!this.logoElement) return;
|
|
115
100
|
this.logoElement.style.display = val ? "block" : "none";
|
|
116
101
|
}
|
|
117
102
|
|
|
118
103
|
/** Switch the logo between full and compact versions */
|
|
119
104
|
setType(type: "full" | "compact") {
|
|
120
|
-
this.ensureInitialized();
|
|
121
|
-
if (!this.logoElement) return;
|
|
122
105
|
if (type === "full") {
|
|
123
106
|
this.logoElement.src = needleLogoSVG;
|
|
124
107
|
this.logoElement.classList.remove("with-text");
|
|
@@ -302,7 +302,7 @@ export class NeedleSpatialMenu {
|
|
|
302
302
|
// logoObject.position.y = 1;
|
|
303
303
|
// this._context.scene.add(logoObject);
|
|
304
304
|
const textureLoader = new TextureLoader();
|
|
305
|
-
textureLoader.load("
|
|
305
|
+
textureLoader.load("./include/needle/poweredbyneedle.webp", (texture) => {
|
|
306
306
|
if (texture) {
|
|
307
307
|
onClick.allowModifyUI = false;
|
|
308
308
|
firstLabel.removeFromParent();
|
|
@@ -343,11 +343,7 @@ export class NeedleSpatialMenu {
|
|
|
343
343
|
|
|
344
344
|
if (!fontFamily) {
|
|
345
345
|
fontFamily = ThreeMeshUI.FontLibrary.addFontFamily(this.familyName);
|
|
346
|
-
const normal = fontFamily.addVariant(
|
|
347
|
-
"normal",
|
|
348
|
-
"normal",
|
|
349
|
-
"https://cdn.needle.tools/static/fonts/msdf/arial/arial-msdf.json",
|
|
350
|
-
"https://cdn.needle.tools/static/fonts/msdf/arial/arial.png") as any as ThreeMeshUI.FontVariant;
|
|
346
|
+
const normal = fontFamily.addVariant("normal", "normal", "./include/needle/arial-msdf.json", "./include/needle/arial.png") as any as ThreeMeshUI.FontVariant;
|
|
351
347
|
/** @ts-ignore */
|
|
352
348
|
normal?.addEventListener('ready', () => {
|
|
353
349
|
this.markDirty();
|
|
@@ -129,7 +129,6 @@ export class NeedleMenu {
|
|
|
129
129
|
|
|
130
130
|
constructor(context: Context) {
|
|
131
131
|
this._menu = NeedleMenuElement.getOrCreate(context.domElement, context);
|
|
132
|
-
this._menu.ensureInitialized();
|
|
133
132
|
this._context = context;
|
|
134
133
|
this._spatialMenu = new NeedleSpatialMenu(context, this._menu);
|
|
135
134
|
window.addEventListener("message", this.onPostMessage);
|
|
@@ -310,7 +309,8 @@ export class NeedleMenu {
|
|
|
310
309
|
export class NeedleMenuElement extends HTMLElement {
|
|
311
310
|
|
|
312
311
|
static create() {
|
|
313
|
-
|
|
312
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement#is
|
|
313
|
+
return document.createElement(elementName, { is: elementName });
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
static getOrCreate(domElement: HTMLElement, context: Context) {
|
|
@@ -337,13 +337,9 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
337
337
|
|
|
338
338
|
private _domElement: HTMLElement | null = null;
|
|
339
339
|
private _context: Context | null = null;
|
|
340
|
-
private _didInitialize = false;
|
|
341
340
|
|
|
342
341
|
constructor() {
|
|
343
342
|
super();
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
private initializeDom() {
|
|
347
343
|
|
|
348
344
|
const template = document.createElement('template');
|
|
349
345
|
// TODO: make host full size again and move the buttons to a wrapper so that we can later easily open e.g. foldouts/dropdowns / use the whole canvas space
|
|
@@ -799,7 +795,7 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
799
795
|
|
|
800
796
|
|
|
801
797
|
let context = this._context;
|
|
802
|
-
// we need to assign it in the timeout because the reference is set *after* the
|
|
798
|
+
// we need to assign it in the timeout because the reference is set *after* the constructor did run
|
|
803
799
|
setTimeout(() => context = this._context);
|
|
804
800
|
|
|
805
801
|
// watch changes
|
|
@@ -868,21 +864,13 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
868
864
|
}
|
|
869
865
|
}
|
|
870
866
|
|
|
871
|
-
ensureInitialized() {
|
|
872
|
-
if (!this._didInitialize) {
|
|
873
|
-
this._didInitialize = true;
|
|
874
|
-
this.initializeDom();
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
|
|
878
867
|
private _sizeChangeInterval;
|
|
879
868
|
|
|
880
869
|
connectedCallback() {
|
|
881
|
-
this.ensureInitialized();
|
|
882
870
|
window.addEventListener("resize", this.handleSizeChange);
|
|
883
871
|
this.handleMenuVisible();
|
|
884
872
|
this._sizeChangeInterval = setInterval(() => this.handleSizeChange(undefined, false), 5000);
|
|
885
|
-
// the dom element is set after
|
|
873
|
+
// the dom element is set after the constructor runs
|
|
886
874
|
setTimeout(() => {
|
|
887
875
|
this._domElement?.addEventListener("resize", this.handleSizeChange);
|
|
888
876
|
this._domElement?.addEventListener("click", this.#onClick);
|
|
@@ -970,19 +958,19 @@ export class NeedleMenuElement extends HTMLElement {
|
|
|
970
958
|
|
|
971
959
|
// private _root: ShadowRoot | null = null;
|
|
972
960
|
/** @private root container element inside shadow DOM */
|
|
973
|
-
private root
|
|
961
|
+
private readonly root: HTMLDivElement;
|
|
974
962
|
/** @private wraps the whole content (internal layout) */
|
|
975
|
-
private wrapper
|
|
963
|
+
private readonly wrapper: HTMLDivElement;
|
|
976
964
|
/** @private contains the buttons and dynamic elements */
|
|
977
|
-
private options
|
|
965
|
+
private readonly options: HTMLDivElement;
|
|
978
966
|
/** @private contains options visible when in compact mode */
|
|
979
|
-
private optionsCompactMode
|
|
967
|
+
private readonly optionsCompactMode: HTMLDivElement;
|
|
980
968
|
/** @private contains the needle-logo html element */
|
|
981
|
-
private logoContainer
|
|
969
|
+
private readonly logoContainer: HTMLDivElement;
|
|
982
970
|
/** @private compact menu button element */
|
|
983
|
-
private compactMenuButton
|
|
971
|
+
private readonly compactMenuButton: HTMLButtonElement;
|
|
984
972
|
/** @private foldout container used in compact mode */
|
|
985
|
-
private foldout
|
|
973
|
+
private readonly foldout: HTMLDivElement;
|
|
986
974
|
|
|
987
975
|
|
|
988
976
|
private readonly trackedElements: WeakSet<Node> = new WeakSet();
|
|
@@ -121,7 +121,7 @@ export class AROverlayHandler {
|
|
|
121
121
|
|
|
122
122
|
const quitARSlot = document.createElement("slot");
|
|
123
123
|
quitARSlot.style.display = "contents";
|
|
124
|
-
quitARSlot.style.padding = "10px";
|
|
124
|
+
quitARSlot.style.padding = "10px";
|
|
125
125
|
quitARSlot.setAttribute("name", "quit-ar");
|
|
126
126
|
this.appendElement(quitARSlot, element);
|
|
127
127
|
this._createdAROnlyElements.push(quitARSlot);
|
|
@@ -131,16 +131,7 @@ export class AROverlayHandler {
|
|
|
131
131
|
// No default quit button in the top right corner in app clips
|
|
132
132
|
// we provide one via the native UI
|
|
133
133
|
if (DeviceUtilities.isNeedleAppClip()) {
|
|
134
|
-
|
|
135
|
-
// quitARSlot.style.display = "none";
|
|
136
|
-
globalThis["NEEDLE_ENGINE_APPCLIP_DISABLE_MENU"] = true;
|
|
137
|
-
|
|
138
|
-
// respect the UI bar at the top of the screen and add some padding to the quit button container
|
|
139
|
-
// @TODO: this should be done in CSS in one place and not here and in debug overlay
|
|
140
|
-
const meta = document.querySelector('meta[name="viewport"]');
|
|
141
|
-
if (meta && !meta.getAttribute("content")?.includes("viewport-fit=")) {
|
|
142
|
-
meta.setAttribute("content", meta.getAttribute("content") + ",viewport-fit=cover");
|
|
143
|
-
}
|
|
134
|
+
quitARSlot.style.display = "none";
|
|
144
135
|
}
|
|
145
136
|
|
|
146
137
|
// We want to search the document if there's a quit-ar button
|
|
@@ -164,8 +155,6 @@ export class AROverlayHandler {
|
|
|
164
155
|
right: 0;
|
|
165
156
|
z-index: 600;
|
|
166
157
|
pointer-events: all;
|
|
167
|
-
padding-top: env(safe-area-inset-top, 0px);
|
|
168
|
-
padding-right: calc(env(safe-area-inset-right, 0px) + 10px);
|
|
169
158
|
`;
|
|
170
159
|
this.appendElement(fixedButtonContainer, quitARSlot);
|
|
171
160
|
|
|
@@ -168,30 +168,19 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
168
168
|
*/
|
|
169
169
|
public get context() { return this._context; }
|
|
170
170
|
|
|
171
|
-
private _context
|
|
171
|
+
private _context: Context;
|
|
172
172
|
private _overlay_ar: AROverlayHandler;
|
|
173
173
|
private _loadingProgress01: number = 0;
|
|
174
174
|
private _loadingView?: ILoadingViewHandler;
|
|
175
175
|
private _previousSrc: string | null | string[] = null;
|
|
176
176
|
/** @private set to true after <needle-engine> did load completely at least once. Set to false when < to false when <needle-engine> is removed from the document removed from the document */
|
|
177
177
|
private _didFullyLoad: boolean = false;
|
|
178
|
-
private _didInitialize = false;
|
|
179
178
|
|
|
180
179
|
constructor() {
|
|
181
180
|
super();
|
|
182
181
|
this._overlay_ar = new AROverlayHandler();
|
|
183
182
|
// TODO: do we want to rename this event?
|
|
184
183
|
this.addEventListener("ready", this.onReady);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
private ensureInitialized() {
|
|
188
|
-
if (!this._didInitialize) {
|
|
189
|
-
this._didInitialize = true;
|
|
190
|
-
this.initializeDom();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
private initializeDom() {
|
|
195
184
|
|
|
196
185
|
ensureFonts();
|
|
197
186
|
|
|
@@ -292,7 +281,6 @@ export class NeedleEngineWebComponent extends HTMLElement implements INeedleEngi
|
|
|
292
281
|
* @internal
|
|
293
282
|
*/
|
|
294
283
|
async connectedCallback() {
|
|
295
|
-
this.ensureInitialized();
|
|
296
284
|
if (debug) {
|
|
297
285
|
console.log("<needle-engine> connected");
|
|
298
286
|
}
|
|
@@ -49,7 +49,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
|
|
|
49
49
|
abstract activeSelf: boolean;
|
|
50
50
|
|
|
51
51
|
/** @deprecated Use {@link addComponent} instead */
|
|
52
|
-
// eslint-disable-next-line
|
|
52
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
53
53
|
abstract addNewComponent<T extends IComponent>(type: ConstructorConcrete<T>, init?: ComponentInit<T>): T;
|
|
54
54
|
|
|
55
55
|
/**
|
|
@@ -364,6 +364,7 @@ export abstract class GameObject extends Object3D implements Object3D, IGameObje
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
/** @deprecated use `addComponent` */
|
|
367
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
367
368
|
public static addNewComponent<T extends IComponent>(go: IGameObject | Object3D, type: T | ConstructorConcrete<T>, init?: ComponentInit<T>, callAwake: boolean = true): T {
|
|
368
369
|
return addComponent(go, type, init, { callAwake });
|
|
369
370
|
}
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, Object3D, Texture, Vector3 } from "three";
|
|
1
|
+
import { Color, CubeReflectionMapping, CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, MeshBasicMaterial, MeshStandardMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
|
|
2
2
|
|
|
3
|
+
import { isDevEnvironment, showBalloonWarning } from "../engine/debug/index.js";
|
|
3
4
|
import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
|
|
4
|
-
import { loadPMREM } from "../engine/engine_pmrem.js";
|
|
5
5
|
import { serializable } from "../engine/engine_serialization.js";
|
|
6
6
|
import { Context } from "../engine/engine_setup.js";
|
|
7
|
+
import type { IRenderer } from "../engine/engine_types.js";
|
|
7
8
|
import { getParam, resolveUrl } from "../engine/engine_utils.js";
|
|
8
9
|
import { BoxHelperComponent } from "./BoxHelperComponent.js";
|
|
9
10
|
import { Behaviour } from "./Component.js";
|
|
10
11
|
import { EventList } from "./EventList.js";
|
|
12
|
+
import { loadPMREM } from "../engine/engine_pmrem.js";
|
|
11
13
|
|
|
12
14
|
export const debug = getParam("debugreflectionprobe");
|
|
13
15
|
const disable = getParam("noreflectionprobe");
|
|
@@ -40,11 +42,7 @@ const $reflectionProbeKey = Symbol("reflectionProbeKey");
|
|
|
40
42
|
export class ReflectionProbe extends Behaviour {
|
|
41
43
|
|
|
42
44
|
private static _probes: Map<Context, ReflectionProbe[]> = new Map();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Checks if the given material is currently using a reflection probe. This is determined by checking for an override on the material's "envMap" property, which is set by the Renderer component when applying a reflection probe.
|
|
47
|
-
*/
|
|
45
|
+
|
|
48
46
|
static isUsingReflectionProbe(material: Material) {
|
|
49
47
|
return !!(material as any)[$reflectionProbeKey];
|
|
50
48
|
}
|
|
@@ -52,13 +50,8 @@ export class ReflectionProbe extends Behaviour {
|
|
|
52
50
|
|
|
53
51
|
/**
|
|
54
52
|
* Event invoked when a reflection probe is enabled. Used internally by Renderer components to update probes when they become active. Not recommended to call this directly in most cases.
|
|
55
|
-
* @see {@link onDisabled} for the corresponding disable event.
|
|
56
53
|
*/
|
|
57
54
|
static readonly onEnabled: EventList<ReflectionProbe> = new EventList();
|
|
58
|
-
/**
|
|
59
|
-
* Event invoked when a reflection probe is disabled. Used internally by Renderer components to update probes when they become inactive. Not recommended to call this directly in most cases.
|
|
60
|
-
* @see {@link onEnabled} for the corresponding enable event.
|
|
61
|
-
*/
|
|
62
55
|
static readonly onDisabled: EventList<ReflectionProbe> = new EventList();
|
|
63
56
|
|
|
64
57
|
/**
|
|
@@ -97,14 +90,11 @@ export class ReflectionProbe extends Behaviour {
|
|
|
97
90
|
return null;
|
|
98
91
|
}
|
|
99
92
|
|
|
100
|
-
private _texture!: Texture
|
|
93
|
+
private _texture!: Texture;
|
|
101
94
|
private _textureUrlInFlight?: string;
|
|
102
95
|
|
|
103
|
-
/**
|
|
104
|
-
* The cubemap or HDR texture used for reflections. Can be assigned directly or via a URL string. When assigning via URL, the texture will be loaded asynchronously and applied once ready.
|
|
105
|
-
*/
|
|
106
96
|
@serializable([Texture, String])
|
|
107
|
-
set texture(tex: Texture
|
|
97
|
+
set texture(tex: Texture) {
|
|
108
98
|
if (this._texture === tex) return;
|
|
109
99
|
|
|
110
100
|
if (typeof tex === "string") {
|
|
@@ -121,10 +111,7 @@ export class ReflectionProbe extends Behaviour {
|
|
|
121
111
|
return;
|
|
122
112
|
}
|
|
123
113
|
|
|
124
|
-
|
|
125
|
-
// But if the texture is serialized as a string (via Blender Reflection Probes) then the async loading above
|
|
126
|
-
// Will abort IF textureInFlight is reset (here). That's why we do NOT reset textureInFlight during initialization (when __didAwake is false). Only after awake, when we are sure that the async loading is done, we reset the in-flight URL to allow new assignments.
|
|
127
|
-
if(this.__didAwake) this._textureUrlInFlight = undefined;
|
|
114
|
+
this._textureUrlInFlight = undefined;
|
|
128
115
|
|
|
129
116
|
this._texture = tex;
|
|
130
117
|
|
|
@@ -140,7 +127,7 @@ export class ReflectionProbe extends Behaviour {
|
|
|
140
127
|
tex.needsUpdate = true;
|
|
141
128
|
}
|
|
142
129
|
}
|
|
143
|
-
get texture(): Texture
|
|
130
|
+
get texture(): Texture {
|
|
144
131
|
return this._texture;
|
|
145
132
|
}
|
|
146
133
|
|
|
@@ -178,7 +165,6 @@ export class ReflectionProbe extends Behaviour {
|
|
|
178
165
|
ReflectionProbe._probes.get(this.context)?.push(this);
|
|
179
166
|
}
|
|
180
167
|
|
|
181
|
-
/** @internal */
|
|
182
168
|
awake() {
|
|
183
169
|
this._boxHelper = this.gameObject.addComponent(BoxHelperComponent) as BoxHelperComponent;
|
|
184
170
|
this._boxHelper.updateBox(true);
|
|
@@ -192,24 +178,20 @@ export class ReflectionProbe extends Behaviour {
|
|
|
192
178
|
}
|
|
193
179
|
}
|
|
194
180
|
|
|
195
|
-
/** @internal */
|
|
196
181
|
onEnable(): void {
|
|
197
182
|
ReflectionProbe.onEnabled?.invoke(this);
|
|
198
183
|
}
|
|
199
184
|
|
|
200
|
-
/** @internal */
|
|
201
185
|
onDisable(): void {
|
|
202
186
|
ReflectionProbe.onDisabled?.invoke(this);
|
|
203
187
|
}
|
|
204
188
|
|
|
205
|
-
/** @internal */
|
|
206
189
|
start(): void {
|
|
207
190
|
if (!this._texture) {
|
|
208
191
|
console.warn(`[ReflectionProbe] Missing texture. Please assign a custom cubemap texture. To use reflection probes assign them to your renderer's "anchor" property.`);
|
|
209
192
|
}
|
|
210
193
|
}
|
|
211
194
|
|
|
212
|
-
/** @internal */
|
|
213
195
|
onDestroy() {
|
|
214
196
|
const probes = ReflectionProbe._probes.get(this.context);
|
|
215
197
|
if (probes) {
|
|
@@ -220,9 +202,6 @@ export class ReflectionProbe extends Behaviour {
|
|
|
220
202
|
}
|
|
221
203
|
}
|
|
222
204
|
|
|
223
|
-
/**
|
|
224
|
-
* Applies this reflection probe to the given object by setting material property overrides for "envMap", "envMapRotation", and "envMapIntensity". This is typically called by the Renderer component when determining which reflection probe to use for a given object.
|
|
225
|
-
*/
|
|
226
205
|
apply(object: Object3D) {
|
|
227
206
|
if (disable) return;
|
|
228
207
|
if (!this.enabled) return;
|
|
@@ -239,9 +218,6 @@ export class ReflectionProbe extends Behaviour {
|
|
|
239
218
|
propertyBlock.setOverride("envMapIntensity", intensity);
|
|
240
219
|
}
|
|
241
220
|
|
|
242
|
-
/**
|
|
243
|
-
* Removes the reflection probe overrides from the given object. This is typically called by the Renderer component when an object is no longer influenced by this probe or when the probe is disabled.
|
|
244
|
-
*/
|
|
245
221
|
unapply(obj: Object3D) {
|
|
246
222
|
const block = MaterialPropertyBlock.get(obj);
|
|
247
223
|
if (block) {
|
|
@@ -479,10 +479,8 @@ function tryParseMagicSkyboxName(str: string | null | undefined, environment: bo
|
|
|
479
479
|
return useLowRes ? value.url_low : value.url;
|
|
480
480
|
}
|
|
481
481
|
else if (typeof str === "string" && str?.length && (isDevEnvironment() || debug)) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const looksLikePath = str.includes("/") || str.includes(".");
|
|
485
|
-
if(!looksLikePath) {
|
|
482
|
+
const noUrlOrFile = !str.startsWith("http") && !str.startsWith("file:") && !str.startsWith("blob:") && !str.startsWith("data:") && !str.startsWith("/")
|
|
483
|
+
if(noUrlOrFile) {
|
|
486
484
|
console.warn(`RemoteSkybox: Unknown magic skybox name "${str}". Valid names are: ${Object.keys(MagicSkyboxNames).map(n => `"${n}"`).join(", ")}`);
|
|
487
485
|
}
|
|
488
486
|
}
|
|
@@ -6,11 +6,11 @@ import { SerializationContext } from "../../../engine/engine_serialization_core.
|
|
|
6
6
|
import { serializable } from "../../../engine/engine_serialization_decorator.js";
|
|
7
7
|
import { getWorldPosition } from "../../../engine/engine_three_utils.js";
|
|
8
8
|
import { getParam } from "../../../engine/engine_utils.js";
|
|
9
|
-
import GLTFMeshGPUInstancingExtension from '../../../engine/export/gltf/EXT_mesh_gpu_instancing_exporter.js';
|
|
10
9
|
import { RenderTextureWriter } from "../../../engine/export/gltf/Writers.js";
|
|
11
10
|
import { shouldExport_HideFlags } from "../../../engine/export/utils.js";
|
|
12
11
|
import { registerExportExtensions } from "../../../engine/extensions/index.js";
|
|
13
12
|
import { NEEDLE_components } from "../../../engine/extensions/NEEDLE_components.js";
|
|
13
|
+
import GLTFMeshGPUInstancingExtension from '../../../include/three/EXT_mesh_gpu_instancing_exporter.js';
|
|
14
14
|
import { BoxHelperComponent } from "../../BoxHelperComponent.js";
|
|
15
15
|
import { Behaviour, GameObject } from "../../Component.js";
|
|
16
16
|
import { Renderer } from "../../Renderer.js";
|
|
@@ -2457,7 +2457,7 @@ ${usedUVChannels.has(0) ? `
|
|
|
2457
2457
|
def Shader "uvReader_st"
|
|
2458
2458
|
{
|
|
2459
2459
|
uniform token info:id = "UsdPrimvarReader_float2"
|
|
2460
|
-
|
|
2460
|
+
token inputs:varname = "st"
|
|
2461
2461
|
float2 inputs:fallback = (0.0, 0.0)
|
|
2462
2462
|
float2 outputs:result
|
|
2463
2463
|
}
|
|
@@ -2466,7 +2466,7 @@ ${usedUVChannels.has(1) ? `
|
|
|
2466
2466
|
def Shader "uvReader_st1"
|
|
2467
2467
|
{
|
|
2468
2468
|
uniform token info:id = "UsdPrimvarReader_float2"
|
|
2469
|
-
|
|
2469
|
+
token inputs:varname = "st1"
|
|
2470
2470
|
float2 inputs:fallback = (0.0, 0.0)
|
|
2471
2471
|
float2 outputs:result
|
|
2472
2472
|
}
|
|
@@ -740,7 +740,7 @@ export class USDZExporter extends Behaviour {
|
|
|
740
740
|
}
|
|
741
741
|
else if (sessionRoot) {
|
|
742
742
|
arScale = sessionRoot.arScale;
|
|
743
|
-
// eslint-disable-next-line
|
|
743
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
744
744
|
_invertForward = sessionRoot.invertForward;
|
|
745
745
|
}
|
|
746
746
|
|
|
@@ -62,9 +62,9 @@ export class PhysicsExtension implements IUSDExporterExtension {
|
|
|
62
62
|
writer.appendLine(`double dynamicFriction = ${colliderSource.sharedMaterial?.dynamicFriction}`);
|
|
63
63
|
if (mat && mat.bounciness !== undefined)
|
|
64
64
|
writer.appendLine(`double restitution = ${colliderSource.sharedMaterial?.bounciness}`);
|
|
65
|
-
// eslint-disable-next-line
|
|
65
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
66
66
|
if (mat && mat.staticFriction !== undefined)
|
|
67
|
-
// eslint-disable-next-line
|
|
67
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
68
68
|
writer.appendLine(`double staticFriction = ${colliderSource.sharedMaterial?.staticFriction}`);
|
|
69
69
|
writer.closeBlock( "}" );
|
|
70
70
|
}
|