@preference-sl/pref-viewer 2.13.0-beta.0 → 2.13.0-beta.1
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/package.json +5 -5
- package/src/babylonjs-animation-controller.js +2 -2
- package/src/babylonjs-controller.js +290 -175
- package/src/index.js +2 -0
- package/src/localization/i18n.js +94 -0
- package/src/localization/translations.js +104 -0
- package/src/pref-viewer-3d-data.js +28 -0
- package/src/pref-viewer-3d.js +46 -10
- package/src/pref-viewer-menu-3d.js +557 -0
- package/src/pref-viewer-task.js +1 -0
- package/src/pref-viewer.js +532 -200
- package/src/styles.js +302 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@preference-sl/pref-viewer",
|
|
3
|
-
"version": "2.13.0-beta.
|
|
3
|
+
"version": "2.13.0-beta.1",
|
|
4
4
|
"description": "Web Component to preview GLTF models with Babylon.js",
|
|
5
5
|
"author": "Alex Moreno Palacio <amoreno@preference.es>",
|
|
6
6
|
"scripts": {
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"index.d.ts"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@babylonjs/core": "^8.
|
|
39
|
-
"@babylonjs/loaders": "^8.
|
|
40
|
-
"@babylonjs/serializers": "^8.
|
|
38
|
+
"@babylonjs/core": "^8.47.0",
|
|
39
|
+
"@babylonjs/loaders": "^8.47.0",
|
|
40
|
+
"@babylonjs/serializers": "^8.47.0",
|
|
41
41
|
"@panzoom/panzoom": "^4.6.0",
|
|
42
|
-
"babylonjs-gltf2interface": "^8.
|
|
42
|
+
"babylonjs-gltf2interface": "^8.47.0",
|
|
43
43
|
"buffer": "^6.0.3",
|
|
44
44
|
"idb": "^8.0.3",
|
|
45
45
|
"is-svg": "^6.1.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AssetContainer, Color3, HighlightLayer, InstancedMesh, Mesh, PickingInfo, Quaternion, Scene, UtilityLayerRenderer, Vector3 } from "@babylonjs/core";
|
|
2
|
-
import {
|
|
2
|
+
import { PrefViewerStyleVariables } from "./styles.js";
|
|
3
3
|
import OpeningAnimation from "./babylonjs-animation-opening.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -32,7 +32,7 @@ export default class BabylonJSAnimationController {
|
|
|
32
32
|
#animatedNodes = [];
|
|
33
33
|
#openingAnimations = [];
|
|
34
34
|
|
|
35
|
-
#highlightColor = Color3.FromHexString(
|
|
35
|
+
#highlightColor = Color3.FromHexString(PrefViewerStyleVariables.colorPrimary);
|
|
36
36
|
#highlightLayer = null;
|
|
37
37
|
#overlayLayer = null;
|
|
38
38
|
#useHighlightLayer = false; // Set to true to use HighlightLayer (better performance) and false to use overlay meshes (UtilityLayerRenderer - always on top)
|
|
@@ -8,101 +8,71 @@ import JSZip from "jszip";
|
|
|
8
8
|
import GLTFResolver from "./gltf-resolver.js";
|
|
9
9
|
import { MaterialData } from "./pref-viewer-3d-data.js";
|
|
10
10
|
import BabylonJSAnimationController from "./babylonjs-animation-controller.js";
|
|
11
|
+
import { translate } from "./localization/i18n.js";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* BabylonJSController
|
|
14
|
+
* BabylonJSController is the PrefViewer 3D engine coordinator: it bootstraps Babylon.js, manages asset containers,
|
|
15
|
+
* rebuilds post-process pipelines on demand, brokers XR/download interactions, and persists user render toggles so UI
|
|
16
|
+
* components can stay declarative. Higher layers hand over container + option state, while this class turns it into a
|
|
17
|
+
* fully interactive scene with deterministic reloads and exports.
|
|
14
18
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
19
|
+
* Overview
|
|
20
|
+
* - Spins up the Babylon.js engine/scene/camera stack, configures Draco loaders, and wires resize + render loops.
|
|
21
|
+
* - Resolves GLTF/GLB sources through GLTFResolver, loads them into `AssetContainer`s, and toggles their visibility.
|
|
22
|
+
* - Applies render-setting switches (AA, SSAO, IBL, shadows), persists them in localStorage, and rehydrates on startup.
|
|
23
|
+
* - Rebuilds DefaultRenderingPipeline, SSAO, IBL, and shadow pipelines every time the active camera or assets change.
|
|
24
|
+
* - Connects keyboard, pointer, wheel, hover, and XR events so menus, animation controllers, and PrefViewer attributes stay in sync.
|
|
25
|
+
* - Generates GLB, glTF+ZIP, or USDZ exports with timestamped names and localized dialog copy.
|
|
26
|
+
* - Translates metadata (inner floor offsets, cast/receive shadows, camera locks) into scene adjustments after reloads.
|
|
18
27
|
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* - Applies metadata-driven scene adjustments (e.g., inner floor translation) after asset reloads.
|
|
28
|
-
* - Designed for integration with PrefViewer and GLTFResolver.
|
|
29
|
-
* - All resource management and rendering operations are performed asynchronously for performance.
|
|
28
|
+
* Runtime Flow
|
|
29
|
+
* 1. Instantiate with `new BabylonJSController(canvas, containers, options)`.
|
|
30
|
+
* 2. Call `enable()` to configure Draco, create the engine/scene, observers, and XR hooks.
|
|
31
|
+
* 3. Whenever PrefViewer marks containers/options pending, invoke `load()` to fetch sources and rebuild pipelines.
|
|
32
|
+
* 4. Use `applyRenderSettings` helpers (via menu events) to merge toggles, persist them, and trigger reloads when needed.
|
|
33
|
+
* 5. Respond to PrefViewer tasks by calling `showModel()/hideModel()` equivalents through container state changes.
|
|
34
|
+
* 6. Surface downloads through `downloadGLB/GLTF/USDZ` or the private `#openDownloadDialog()` triggered by keyboard shortcuts.
|
|
35
|
+
* 7. Invoke `disable()` when the element disconnects to teardown scenes, XR sessions, and listeners.
|
|
30
36
|
*
|
|
31
|
-
*
|
|
32
|
-
* -
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
37
|
-
* -
|
|
38
|
-
* - Disable rendering: controller.disable();
|
|
37
|
+
* Public API Highlights
|
|
38
|
+
* - constructor(canvas, containers, options)
|
|
39
|
+
* - enable() / disable()
|
|
40
|
+
* - load()
|
|
41
|
+
* - downloadGLB(content) / downloadGLTF(content) / downloadUSDZ(content)
|
|
42
|
+
* - getRenderSettings() / applyRenderSettings(partial)
|
|
43
|
+
* - setRenderSettings(settings) [via PrefViewer menu integration]
|
|
39
44
|
*
|
|
40
|
-
*
|
|
41
|
-
* -
|
|
42
|
-
* -
|
|
43
|
-
* -
|
|
44
|
-
*
|
|
45
|
-
* -
|
|
46
|
-
*
|
|
47
|
-
* -
|
|
48
|
-
*
|
|
49
|
-
* -
|
|
50
|
-
*
|
|
51
|
-
* - downloadUSDZ(content): Builds an Apple USDZ archive for the requested scope and downloads it via blob streaming.
|
|
45
|
+
* Key Subsystems
|
|
46
|
+
* - Persistence: #applyRenderSettings, #loadStoredRenderSettings, #saveRenderSettings keep AA/SSAO/IBL/shadow flags synced.
|
|
47
|
+
* - Loading pipeline: #markContainersForReload, #markOptionsForReload, #loadAssetContainer, #loadContainers orchestrate deterministic reloads.
|
|
48
|
+
* - Visual setup: #configureDracoCompression, #createCamera, #createLights, #initializeVisualImprovements, #initializeAmbientOcclussion,
|
|
49
|
+
* #initializeIBLShadows, #initializeDefaultLightShadows, #initializeEnvironmentShadows, #setMaxSimultaneousLights.
|
|
50
|
+
* - Interaction + XR: #bindHandlers, #enableInteraction, #onPointerObservable, #onMouseWheel, #onKeyUp, #createXRExperience,
|
|
51
|
+
* #addStylesToARButton, #disposeXRExperience.
|
|
52
|
+
* - Container helpers: #addContainer, #removeContainer, #replaceContainer, #setOptions_Materials, #setOptions_Camera,
|
|
53
|
+
* #setOptions_IBL, #setVisibilityOfWallAndFloorInModel, #getPrefViewerComponent.
|
|
54
|
+
* - Metadata + download utilities: #checkModelMetadata, #checkInnerFloorTranslation, #translateNodeY, #addDateToName,
|
|
55
|
+
* #downloadZip, #openDownloadDialog.
|
|
52
56
|
*
|
|
53
|
-
*
|
|
54
|
-
* -
|
|
55
|
-
* -
|
|
56
|
-
* -
|
|
57
|
-
* - #addStylesToARButton(): Styles AR button.
|
|
58
|
-
* - #createXRExperience(): Initializes WebXR AR experience.
|
|
59
|
-
* - #createCamera(): Creates and configures the main camera.
|
|
60
|
-
* - #createLights(): Creates and configures scene lights and shadows.
|
|
61
|
-
* - #initializeAmbientOcclussion(): Rebuilds the SSAO pipeline for the active camera.
|
|
62
|
-
* - #initializeVisualImprovements(): Reinstalls the default rendering pipeline (MSAA/FXAA/grain).
|
|
63
|
-
* - #initializeEnvironmentTexture(): Loads and sets the HDR environment texture.
|
|
64
|
-
* - #initializeIBLShadows(): Sets up IBL shadow pipeline and assigns meshes/materials.
|
|
65
|
-
* - #addMeshToShadowGenerator(shadowGenerator, mesh): Adds eligible meshes to the provided shadow generator while honoring GLTF metadata.
|
|
66
|
-
* - #initializeShadows(): Sets up standard or IBL shadows for meshes.
|
|
67
|
-
* - #initializeDefaultLightShadows(): Configures soft shadows when no HDR environment exists.
|
|
68
|
-
* - #initializeEnvironmentShadows(): Rebuilds environment-provided shadow generators.
|
|
69
|
-
* - #ensureMeshesReceiveShadows(): Ensures every non-root mesh receives shadows unless metadata opts out.
|
|
70
|
-
* - #setMaxSimultaneousLights(): Updates max simultaneous lights for all materials.
|
|
71
|
-
* - #onPointerObservable(info): Handles pointer events and dispatches to pointer/mouse handlers.
|
|
72
|
-
* - #onPointerUp(event, pickInfo): Handles pointer up events (e.g., right-click for animation menu).
|
|
73
|
-
* - #onPointerMove(event, pickInfo): Handles pointer move events (e.g., mesh highlighting).
|
|
74
|
-
* - #onMouseWheel(event, pickInfo): Handles mouse wheel events for camera zoom.
|
|
75
|
-
* - #onKeyUp(event): Handles keyup events for download dialog and shortcuts.
|
|
76
|
-
* - #enableInteraction(): Adds canvas and scene interaction event listeners.
|
|
77
|
-
* - #disableInteraction(): Removes canvas and scene interaction event listeners.
|
|
78
|
-
* - #disposeAnimationController(): Disposes the animation controller if it exists.
|
|
79
|
-
* - #disposeXRExperience(): Disposes the Babylon.js WebXR experience if it exists.
|
|
80
|
-
* - #disposeEngine(): Disposes engine and releases all resources.
|
|
81
|
-
* - #setOptionsMaterial(optionMaterial): Applies a material option to relevant meshes.
|
|
82
|
-
* - #setOptions_Materials(): Applies all material options from configuration.
|
|
83
|
-
* - #setOptions_Camera(): Applies camera options from configuration.
|
|
84
|
-
* - #setOptions_IBL(): Applies pending HDR/IBL option updates and refreshes lights.
|
|
85
|
-
* - #findContainerByName(name): Finds a container by its name.
|
|
86
|
-
* - #addContainer(container, updateVisibility): Adds a container to the scene and updates visibility.
|
|
87
|
-
* - #removeContainer(container, updateVisibility): Removes a container from the scene and updates visibility.
|
|
88
|
-
* - #replaceContainer(container, newAssetContainer): Replaces a container in the scene.
|
|
89
|
-
* - #getPrefViewer3DComponent(): Caches and retrieves the parent PREF-VIEWER-3D element.
|
|
90
|
-
* - #getPrefViewerComponent(): Caches and retrieves the parent PREF-VIEWER element.
|
|
91
|
-
* - #updateVisibilityAttributeInComponents(name, isVisible): Updates parent visibility attributes.
|
|
92
|
-
* - #setVisibilityOfWallAndFloorInModel(show): Controls wall/floor mesh visibility.
|
|
93
|
-
* - #stopRender(): Stops the Babylon.js render loop.
|
|
94
|
-
* - #startRender(): Starts the Babylon.js render loop.
|
|
95
|
-
* - #loadAssetContainer(container): Loads an asset container asynchronously.
|
|
96
|
-
* - #loadContainers(): Loads all asset containers and adds them to the scene.
|
|
97
|
-
* - #loadCameraDepentEffects(): Re-initializes camera-bound post-processes after reloads or option changes.
|
|
98
|
-
* - #checkModelMetadata(oldMetadata, newMetadata): Processes metadata changes after loading.
|
|
99
|
-
* - #checkInnerFloorTranslation(oldMetadata, newMetadata): Applies inner floor Y translations from metadata.
|
|
100
|
-
* - #translateNodeY(name, deltaY): Adjusts the Y position of a scene node.
|
|
101
|
-
* - #addDateToName(name): Appends the current date/time to a name string.
|
|
102
|
-
* - #downloadZip(files, name, comment, addDateInName): Generates and downloads a ZIP file.
|
|
103
|
-
* - #openDownloadDialog(): Opens the modal download dialog.
|
|
57
|
+
* Notes
|
|
58
|
+
* - Designed to be long-lived per PrefViewer instance; it caches parent components to reflect `show-model/show-scene` attributes.
|
|
59
|
+
* - All browser-only features guard against SSR/Node usage by checking `window` before touching localStorage or XR APIs.
|
|
60
|
+
* - Relies on PrefViewerMenu3D events to trigger render-setting updates, ensuring UI and persisted state never drift apart.
|
|
104
61
|
*/
|
|
105
62
|
export default class BabylonJSController {
|
|
63
|
+
|
|
64
|
+
#RENDER_SETTINGS_STORAGE_KEY = "pref-viewer/render-settings";
|
|
65
|
+
|
|
66
|
+
// Default render settings
|
|
67
|
+
// Add here new render toggles that require persistence here, and remember to update the matching labels
|
|
68
|
+
// under translations.prefViewer.menu3d.switches in ./localization/translations.js.
|
|
69
|
+
static DEFAULT_RENDER_SETTINGS = {
|
|
70
|
+
antiAliasingEnabled: true,
|
|
71
|
+
ambientOcclusionEnabled: true,
|
|
72
|
+
iblEnabled: true,
|
|
73
|
+
shadowsEnabled: false,
|
|
74
|
+
};
|
|
75
|
+
|
|
106
76
|
// Canvas HTML element
|
|
107
77
|
#canvas = null;
|
|
108
78
|
|
|
@@ -133,12 +103,7 @@ export default class BabylonJSController {
|
|
|
133
103
|
renderLoop: null,
|
|
134
104
|
};
|
|
135
105
|
|
|
136
|
-
#settings = {
|
|
137
|
-
antiAliasingEnabled: true,
|
|
138
|
-
ambientOcclusionEnabled: true,
|
|
139
|
-
iblEnabled: true,
|
|
140
|
-
shadowsEnabled: false,
|
|
141
|
-
};
|
|
106
|
+
#settings = { ...BabylonJSController.DEFAULT_RENDER_SETTINGS };
|
|
142
107
|
|
|
143
108
|
/**
|
|
144
109
|
* Constructs a new BabylonJSController instance.
|
|
@@ -162,6 +127,7 @@ export default class BabylonJSController {
|
|
|
162
127
|
};
|
|
163
128
|
});
|
|
164
129
|
this.#options = options;
|
|
130
|
+
this.#loadStoredRenderSettings();
|
|
165
131
|
this.#bindHandlers();
|
|
166
132
|
}
|
|
167
133
|
|
|
@@ -194,6 +160,114 @@ export default class BabylonJSController {
|
|
|
194
160
|
};
|
|
195
161
|
}
|
|
196
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Merges boolean render toggles into the current configuration, clearing the environment texture when IBL turns off
|
|
165
|
+
* and persisting the updated state when at least one flag changed.
|
|
166
|
+
* @private
|
|
167
|
+
* @param {object} [settings={}] - Partial map of render settings (AA, SSAO, IBL, shadows, etc.).
|
|
168
|
+
* @returns {boolean} True when any setting changed and was saved.
|
|
169
|
+
*/
|
|
170
|
+
#applyRenderSettings(settings = {}) {
|
|
171
|
+
if (!settings) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let changed = false;
|
|
176
|
+
Object.keys(settings).forEach((key) => {
|
|
177
|
+
if (typeof settings[key] === "boolean" && this.#settings[key] !== settings[key]) {
|
|
178
|
+
this.#settings[key] = settings[key];
|
|
179
|
+
changed = true;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
if (changed && settings.iblEnabled === false && this.#scene) {
|
|
184
|
+
this.#scene.environmentTexture = null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (changed) {
|
|
188
|
+
this.#saveRenderSettings();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return changed;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Restores previously persisted render toggles from localStorage, falling back to defaults when parsing fails or
|
|
196
|
+
* the browser environment is unavailable.
|
|
197
|
+
* @private
|
|
198
|
+
* @returns {void}
|
|
199
|
+
*/
|
|
200
|
+
#loadStoredRenderSettings() {
|
|
201
|
+
if (typeof window === "undefined" || !window?.localStorage) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const serialized = window.localStorage.getItem(this.#RENDER_SETTINGS_STORAGE_KEY);
|
|
206
|
+
if (!serialized) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const parsed = JSON.parse(serialized);
|
|
210
|
+
Object.keys(BabylonJSController.DEFAULT_RENDER_SETTINGS).forEach((key) => {
|
|
211
|
+
if (typeof parsed?.[key] === "boolean") {
|
|
212
|
+
this.#settings[key] = parsed[key];
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.warn("PrefViewer: unable to load render settings", error);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Serializes the current render toggle object to localStorage, ignoring non-browser contexts and logging warnings
|
|
222
|
+
* if persistence fails.
|
|
223
|
+
* @private
|
|
224
|
+
* @returns {void}
|
|
225
|
+
*/
|
|
226
|
+
#saveRenderSettings() {
|
|
227
|
+
if (typeof window === "undefined" || !window?.localStorage) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
window.localStorage.setItem(this.#RENDER_SETTINGS_STORAGE_KEY, JSON.stringify(this.#settings));
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.warn("PrefViewer: unable to save render settings", error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Walks every container state and marks it as pending using `setPendingWithCurrentStorage` so asset sources are
|
|
239
|
+
* re-requested on the next load cycle.
|
|
240
|
+
* @private
|
|
241
|
+
* @returns {boolean} True when at least one container flipped to pending.
|
|
242
|
+
*/
|
|
243
|
+
#markContainersForReload() {
|
|
244
|
+
let marked = false;
|
|
245
|
+
Object.values(this.#containers).forEach((container) => {
|
|
246
|
+
if (container?.state?.setPendingWithCurrentStorage && container.state.setPendingWithCurrentStorage()) {
|
|
247
|
+
marked = true;
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
return marked;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Re-schedules option-driven resources (camera, materials, IBL) for application by calling their respective
|
|
255
|
+
* `setPendingWithCurrent`/`setPending` helpers when available.
|
|
256
|
+
* @private
|
|
257
|
+
* @returns {void}
|
|
258
|
+
*/
|
|
259
|
+
#markOptionsForReload() {
|
|
260
|
+
if (this.#options?.camera?.setPendingWithCurrent) {
|
|
261
|
+
this.#options.camera.setPendingWithCurrent();
|
|
262
|
+
}
|
|
263
|
+
if (this.#options?.materials) {
|
|
264
|
+
Object.values(this.#options.materials).forEach((material) => material?.setPendingWithCurrent?.());
|
|
265
|
+
}
|
|
266
|
+
if (this.#options?.ibl?.setPending) {
|
|
267
|
+
this.#options.ibl.setPending();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
197
271
|
/**
|
|
198
272
|
* Render loop callback for Babylon.js.
|
|
199
273
|
* @private
|
|
@@ -1512,16 +1586,18 @@ export default class BabylonJSController {
|
|
|
1512
1586
|
return;
|
|
1513
1587
|
}
|
|
1514
1588
|
|
|
1515
|
-
const
|
|
1589
|
+
const locale = this.#prefViewer.culture;
|
|
1590
|
+
const texts = translate("prefViewer.downloadDialog", locale ? { locale } : undefined) || {};
|
|
1591
|
+
const header = texts.title || "Download 3D Scene";
|
|
1516
1592
|
const content = `
|
|
1517
1593
|
<form slot="content" id="download-dialog-form" style="display:flex;flex-direction:column;gap:16px;">
|
|
1518
|
-
<h4
|
|
1594
|
+
<h4>${texts.sections?.content || "Content"}</h4>
|
|
1519
1595
|
<div style="display:flex;flex-direction:row;gap:16px;margin:0 8px 0 8px;">
|
|
1520
|
-
<label><input type="radio" name="content" value="1"> Model</label>
|
|
1521
|
-
<label><input type="radio" name="content" value="2"> Scene</label>
|
|
1522
|
-
<label><input type="radio" name="content" value="0" checked> Both</label>
|
|
1596
|
+
<label><input type="radio" name="content" value="1"> ${texts.options?.model || "Model"}</label>
|
|
1597
|
+
<label><input type="radio" name="content" value="2"> ${texts.options?.scene || "Scene"}</label>
|
|
1598
|
+
<label><input type="radio" name="content" value="0" checked> ${texts.options?.both || "Both"}</label>
|
|
1523
1599
|
</div>
|
|
1524
|
-
<h4
|
|
1600
|
+
<h4>${texts.sections?.format || "Format"}</h4>
|
|
1525
1601
|
<div style="display:flex;flex-direction:row;gap:16px;margin:0 8px 0 8px;">
|
|
1526
1602
|
<label><input type="radio" name="format" value="gltf" checked> glTF (ZIP)</label>
|
|
1527
1603
|
<label><input type="radio" name="format" value="glb"> GLB</label>
|
|
@@ -1529,8 +1605,8 @@ export default class BabylonJSController {
|
|
|
1529
1605
|
</div>
|
|
1530
1606
|
</form>`;
|
|
1531
1607
|
const footer = `
|
|
1532
|
-
<button type="button" class="primary" id="download-dialog-download"
|
|
1533
|
-
<button type="button" id="download-dialog-cancel"
|
|
1608
|
+
<button type="button" class="primary" id="download-dialog-download">${texts.buttons?.download || "Download"}</button>
|
|
1609
|
+
<button type="button" id="download-dialog-cancel">${texts.buttons?.cancel || "Cancel"}</button>`;
|
|
1534
1610
|
|
|
1535
1611
|
const dialog = this.#prefViewer.openDialog(header, content, footer);
|
|
1536
1612
|
|
|
@@ -1617,81 +1693,6 @@ export default class BabylonJSController {
|
|
|
1617
1693
|
this.#disposeEngine();
|
|
1618
1694
|
}
|
|
1619
1695
|
|
|
1620
|
-
/**
|
|
1621
|
-
* Loads all asset containers (model, environment, materials, etc.) and adds them to the scene.
|
|
1622
|
-
* Applies material and camera options, sets visibility, and initializes lights and shadows.
|
|
1623
|
-
* @public
|
|
1624
|
-
* @returns {Promise<boolean>} Resolves to true if loading succeeds, false otherwise.
|
|
1625
|
-
*/
|
|
1626
|
-
async load() {
|
|
1627
|
-
return await this.#loadContainers();
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
|
-
/**
|
|
1631
|
-
* Applies camera options from the configuration to the active camera.
|
|
1632
|
-
* Stops and restarts the render loop to apply changes.
|
|
1633
|
-
* @public
|
|
1634
|
-
* @returns {boolean} True if camera options were set successfully, false otherwise.
|
|
1635
|
-
*/
|
|
1636
|
-
setCameraOptions() {
|
|
1637
|
-
this.#stopRender();
|
|
1638
|
-
const cameraOptionsSetted = this.#setOptions_Camera();
|
|
1639
|
-
this.#loadCameraDepentEffects();
|
|
1640
|
-
this.#startRender();
|
|
1641
|
-
return cameraOptionsSetted;
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
/**
|
|
1645
|
-
* Applies material options from the configuration to the relevant meshes.
|
|
1646
|
-
* Stops and restarts the render loop to apply changes.
|
|
1647
|
-
* @public
|
|
1648
|
-
* @returns {boolean} True if material options were set successfully, false otherwise.
|
|
1649
|
-
*/
|
|
1650
|
-
setMaterialOptions() {
|
|
1651
|
-
this.#stopRender();
|
|
1652
|
-
const materialsOptionsSetted = this.#setOptions_Materials();
|
|
1653
|
-
this.#startRender();
|
|
1654
|
-
return materialsOptionsSetted;
|
|
1655
|
-
}
|
|
1656
|
-
|
|
1657
|
-
/**
|
|
1658
|
-
* Reapplies image-based lighting configuration (HDR URL, intensity, shadow mode).
|
|
1659
|
-
* Stops rendering, pushes pending IBL state into the scene, rebuilds camera-dependent effects, then resumes rendering.
|
|
1660
|
-
* @public
|
|
1661
|
-
* @returns {void}
|
|
1662
|
-
*/
|
|
1663
|
-
setIBLOptions() {
|
|
1664
|
-
this.#stopRender();
|
|
1665
|
-
const IBLOptionsSetted = this.#setOptions_IBL();
|
|
1666
|
-
this.#loadCameraDepentEffects();
|
|
1667
|
-
this.#startRender();
|
|
1668
|
-
return IBLOptionsSetted;
|
|
1669
|
-
}
|
|
1670
|
-
|
|
1671
|
-
/**
|
|
1672
|
-
* Sets the visibility of a container (model, environment, etc.) by name.
|
|
1673
|
-
* Adds or removes the container from the scene and updates wall/floor visibility.
|
|
1674
|
-
* Restarts the render loop to apply changes.
|
|
1675
|
-
* @public
|
|
1676
|
-
* @param {string} name - The name of the container to show or hide.
|
|
1677
|
-
* @param {boolean} show - True to show the container, false to hide it.
|
|
1678
|
-
* @returns {void}
|
|
1679
|
-
*/
|
|
1680
|
-
setContainerVisibility(name, show) {
|
|
1681
|
-
const container = this.#findContainerByName(name);
|
|
1682
|
-
if (!container) {
|
|
1683
|
-
return;
|
|
1684
|
-
}
|
|
1685
|
-
if (container.state.show === show && container.state.visible === show) {
|
|
1686
|
-
return;
|
|
1687
|
-
}
|
|
1688
|
-
container.state.show = show;
|
|
1689
|
-
this.#stopRender();
|
|
1690
|
-
show ? this.#addContainer(container) : this.#removeContainer(container);
|
|
1691
|
-
this.#setVisibilityOfWallAndFloorInModel();
|
|
1692
|
-
this.#startRender();
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
1696
|
/**
|
|
1696
1697
|
* Downloads the current scene, model, or environment as a GLB file.
|
|
1697
1698
|
* @public
|
|
@@ -1794,4 +1795,118 @@ export default class BabylonJSController {
|
|
|
1794
1795
|
}
|
|
1795
1796
|
});
|
|
1796
1797
|
}
|
|
1798
|
+
|
|
1799
|
+
/**
|
|
1800
|
+
* Returns a shallow copy of the current render settings so callers can read the active state without mutating the controller internals.
|
|
1801
|
+
* @public
|
|
1802
|
+
* @returns {{antiAliasingEnabled:boolean, ambientOcclusionEnabled:boolean, iblEnabled:boolean, shadowsEnabled:boolean}}
|
|
1803
|
+
*/
|
|
1804
|
+
getRenderSettings() {
|
|
1805
|
+
return { ...this.#settings };
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
/**
|
|
1809
|
+
* Loads all asset containers (model, environment, materials, etc.) and adds them to the scene.
|
|
1810
|
+
* Applies material and camera options, sets visibility, and initializes lights and shadows.
|
|
1811
|
+
* @public
|
|
1812
|
+
* @returns {Promise<boolean>} Resolves to true if loading succeeds, false otherwise.
|
|
1813
|
+
*/
|
|
1814
|
+
async load() {
|
|
1815
|
+
return await this.#loadContainers();
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* Merges incoming render flags with the current configuration, persists them, and marks
|
|
1820
|
+
* all dependent loaders/options as pending when something actually changed.
|
|
1821
|
+
* @public
|
|
1822
|
+
* @param {{antiAliasingEnabled?:boolean, ambientOcclusionEnabled?:boolean, iblEnabled?:boolean, shadowsEnabled?:boolean}} settings Partial set of render toggles to apply.
|
|
1823
|
+
* @returns {{changed:boolean, settings:{antiAliasingEnabled:boolean, ambientOcclusionEnabled:boolean, iblEnabled:boolean, shadowsEnabled:boolean}}}
|
|
1824
|
+
* @description
|
|
1825
|
+
* Callers can inspect the `changed` flag to decide whether to trigger a reload with
|
|
1826
|
+
* `reloadWithCurrentSettings()` or simply reuse the returned snapshot.
|
|
1827
|
+
*/
|
|
1828
|
+
scheduleRenderSettingsReload(settings = {}) {
|
|
1829
|
+
const changed = this.#applyRenderSettings(settings);
|
|
1830
|
+
if (!changed) {
|
|
1831
|
+
return { changed: false, settings: this.getRenderSettings() };
|
|
1832
|
+
}
|
|
1833
|
+
this.#markContainersForReload();
|
|
1834
|
+
this.#markOptionsForReload();
|
|
1835
|
+
return { changed: true, settings: this.getRenderSettings() };
|
|
1836
|
+
}
|
|
1837
|
+
|
|
1838
|
+
/**
|
|
1839
|
+
* Applies camera options from the configuration to the active camera.
|
|
1840
|
+
* Stops and restarts the render loop to apply changes.
|
|
1841
|
+
* @public
|
|
1842
|
+
* @returns {boolean} True if camera options were set successfully, false otherwise.
|
|
1843
|
+
*/
|
|
1844
|
+
setCameraOptions() {
|
|
1845
|
+
this.#stopRender();
|
|
1846
|
+
const cameraOptionsSetted = this.#setOptions_Camera();
|
|
1847
|
+
this.#loadCameraDepentEffects();
|
|
1848
|
+
this.#startRender();
|
|
1849
|
+
return cameraOptionsSetted;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
/**
|
|
1853
|
+
* Applies material options from the configuration to the relevant meshes.
|
|
1854
|
+
* Stops and restarts the render loop to apply changes.
|
|
1855
|
+
* @public
|
|
1856
|
+
* @returns {boolean} True if material options were set successfully, false otherwise.
|
|
1857
|
+
*/
|
|
1858
|
+
setMaterialOptions() {
|
|
1859
|
+
this.#stopRender();
|
|
1860
|
+
const materialsOptionsSetted = this.#setOptions_Materials();
|
|
1861
|
+
this.#startRender();
|
|
1862
|
+
return materialsOptionsSetted;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
/**
|
|
1866
|
+
* Reapplies image-based lighting configuration (HDR URL, intensity, shadow mode).
|
|
1867
|
+
* Stops rendering, pushes pending IBL state into the scene, rebuilds camera-dependent effects, then resumes rendering.
|
|
1868
|
+
* @public
|
|
1869
|
+
* @returns {void}
|
|
1870
|
+
*/
|
|
1871
|
+
setIBLOptions() {
|
|
1872
|
+
this.#stopRender();
|
|
1873
|
+
const IBLOptionsSetted = this.#setOptions_IBL();
|
|
1874
|
+
this.#loadCameraDepentEffects();
|
|
1875
|
+
this.#startRender();
|
|
1876
|
+
return IBLOptionsSetted;
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Sets the visibility of a container (model, environment, etc.) by name.
|
|
1881
|
+
* Adds or removes the container from the scene and updates wall/floor visibility.
|
|
1882
|
+
* Restarts the render loop to apply changes.
|
|
1883
|
+
* @public
|
|
1884
|
+
* @param {string} name - The name of the container to show or hide.
|
|
1885
|
+
* @param {boolean} show - True to show the container, false to hide it.
|
|
1886
|
+
* @returns {void}
|
|
1887
|
+
*/
|
|
1888
|
+
setContainerVisibility(name, show) {
|
|
1889
|
+
const container = this.#findContainerByName(name);
|
|
1890
|
+
if (!container) {
|
|
1891
|
+
return;
|
|
1892
|
+
}
|
|
1893
|
+
if (container.state.show === show && container.state.visible === show) {
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
container.state.show = show;
|
|
1897
|
+
this.#stopRender();
|
|
1898
|
+
show ? this.#addContainer(container) : this.#removeContainer(container);
|
|
1899
|
+
this.#setVisibilityOfWallAndFloorInModel();
|
|
1900
|
+
this.#startRender();
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* Reloads every asset container using the latest staged render settings.
|
|
1905
|
+
* Intended to be called after `scheduleRenderSettingsReload()` marks data as pending.
|
|
1906
|
+
* @public
|
|
1907
|
+
* @returns {Promise<{success:boolean,error:any}>} Resolves with the same status object returned by `load()`.
|
|
1908
|
+
*/
|
|
1909
|
+
async reloadWithCurrentSettings() {
|
|
1910
|
+
return await this.#loadContainers();
|
|
1911
|
+
}
|
|
1797
1912
|
}
|
package/src/index.js
CHANGED
|
@@ -3,11 +3,13 @@ import PrefViewer from "./pref-viewer.js";
|
|
|
3
3
|
import PrefViewer2D from "./pref-viewer-2d.js";
|
|
4
4
|
import PrefViewer3D from "./pref-viewer-3d.js";
|
|
5
5
|
import PrefViewerDialog from "./pref-viewer-dialog.js";
|
|
6
|
+
import PrefViewerMenu3D from "./pref-viewer-menu-3d.js";
|
|
6
7
|
|
|
7
8
|
// Defines custom elements for use as HTML tags in the application.
|
|
8
9
|
customElements.define("pref-viewer-2d", PrefViewer2D);
|
|
9
10
|
customElements.define("pref-viewer-3d", PrefViewer3D);
|
|
10
11
|
customElements.define("pref-viewer-dialog", PrefViewerDialog);
|
|
12
|
+
customElements.define("pref-viewer-menu-3d", PrefViewerMenu3D);
|
|
11
13
|
customElements.define("pref-viewer", PrefViewer);
|
|
12
14
|
|
|
13
15
|
// Exposes selected PrefViewer classes globally for external JavaScript use.
|