@combeenation/3d-viewer 17.0.0 → 17.1.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/dist/lib-cjs/buildinfo.json +1 -1
- package/dist/lib-cjs/commonjs.tsconfig.tsbuildinfo +1 -1
- package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js +1 -1
- package/dist/lib-cjs/internal/cbn-custom-babylon-loader-plugin.js.map +1 -1
- package/dist/lib-cjs/internal/cloning-helper.js +4 -4
- package/dist/lib-cjs/internal/cloning-helper.js.map +1 -1
- package/dist/lib-cjs/internal/geometry-helper.d.ts +1 -1
- package/dist/lib-cjs/internal/geometry-helper.js +1 -2
- package/dist/lib-cjs/internal/geometry-helper.js.map +1 -1
- package/dist/lib-cjs/internal/metadata-helper.js +8 -3
- package/dist/lib-cjs/internal/metadata-helper.js.map +1 -1
- package/dist/lib-cjs/internal/paintable-helper.js +4 -1
- package/dist/lib-cjs/internal/paintable-helper.js.map +1 -1
- package/dist/lib-cjs/internal/tags-helper.d.ts +3 -4
- package/dist/lib-cjs/internal/tags-helper.js +6 -10
- package/dist/lib-cjs/internal/tags-helper.js.map +1 -1
- package/dist/lib-cjs/internal/texture-parameter-helper.js +9 -3
- package/dist/lib-cjs/internal/texture-parameter-helper.js.map +1 -1
- package/dist/lib-cjs/manager/camera-manager.js +8 -2
- package/dist/lib-cjs/manager/camera-manager.js.map +1 -1
- package/dist/lib-cjs/manager/gltf-export-manager.d.ts +1 -2
- package/dist/lib-cjs/manager/gltf-export-manager.js +3 -19
- package/dist/lib-cjs/manager/gltf-export-manager.js.map +1 -1
- package/dist/lib-cjs/manager/model-manager.js +13 -1
- package/dist/lib-cjs/manager/model-manager.js.map +1 -1
- package/dist/lib-cjs/manager/parameter-manager.d.ts +13 -4
- package/dist/lib-cjs/manager/parameter-manager.js +97 -25
- package/dist/lib-cjs/manager/parameter-manager.js.map +1 -1
- package/dist/lib-cjs/viewer-error.d.ts +2 -1
- package/dist/lib-cjs/viewer-error.js +2 -1
- package/dist/lib-cjs/viewer-error.js.map +1 -1
- package/package.json +11 -11
- package/src/internal/cbn-custom-babylon-loader-plugin.ts +2 -2
- package/src/internal/cloning-helper.ts +5 -5
- package/src/internal/geometry-helper.ts +3 -3
- package/src/internal/metadata-helper.ts +8 -6
- package/src/internal/paintable-helper.ts +4 -1
- package/src/internal/tags-helper.ts +4 -8
- package/src/internal/texture-parameter-helper.ts +9 -3
- package/src/manager/camera-manager.ts +10 -2
- package/src/manager/gltf-export-manager.ts +8 -27
- package/src/manager/model-manager.ts +15 -1
- package/src/manager/parameter-manager.ts +108 -29
- package/src/viewer-error.ts +2 -1
|
@@ -96,7 +96,7 @@ export function createBuiltInTextureParameter(parameterManager: ParameterManager
|
|
|
96
96
|
|
|
97
97
|
if (!newTexture) {
|
|
98
98
|
throw new ViewerError({
|
|
99
|
-
id: ViewerErrorIds.
|
|
99
|
+
id: ViewerErrorIds.InvalidParameterValue,
|
|
100
100
|
message: `Texture with url "${url}" could not be parsed`,
|
|
101
101
|
});
|
|
102
102
|
}
|
|
@@ -251,7 +251,10 @@ export function createBuiltInTextureParameter(parameterManager: ParameterManager
|
|
|
251
251
|
for (const material of materials) {
|
|
252
252
|
const materialCls = material.getClassName();
|
|
253
253
|
if (materialCls !== 'PBRMaterial') {
|
|
254
|
-
throw new
|
|
254
|
+
throw new ViewerError({
|
|
255
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
256
|
+
message: `Enabling detailmap for material of instance "${materialCls}" not implemented`,
|
|
257
|
+
});
|
|
255
258
|
}
|
|
256
259
|
|
|
257
260
|
const pbrMaterial = material as PBRMaterial;
|
|
@@ -270,7 +273,10 @@ export function createBuiltInTextureParameter(parameterManager: ParameterManager
|
|
|
270
273
|
function _assertAndConvertPBRMaterial(material: Material, channel: string, parameter: string): PBRMaterial {
|
|
271
274
|
const materialCls = material.getClassName();
|
|
272
275
|
if (materialCls !== 'PBRMaterial') {
|
|
273
|
-
throw new
|
|
276
|
+
throw new ViewerError({
|
|
277
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
278
|
+
message: `Setting ${channel} ${parameter} for material of instance "${materialCls}" not implemented`,
|
|
279
|
+
});
|
|
274
280
|
}
|
|
275
281
|
|
|
276
282
|
return material as PBRMaterial;
|
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
ScreenshotTools,
|
|
9
9
|
Vector3,
|
|
10
10
|
Viewer,
|
|
11
|
+
ViewerError,
|
|
12
|
+
ViewerErrorIds,
|
|
11
13
|
ViewerEvent,
|
|
12
14
|
} from '../index';
|
|
13
15
|
import { isNodeExcluded } from '../internal/geometry-helper';
|
|
@@ -122,7 +124,10 @@ export class CameraManager {
|
|
|
122
124
|
const activeCamera = this.viewer.scene.activeCamera;
|
|
123
125
|
|
|
124
126
|
if (!(activeCamera instanceof ArcRotateCamera)) {
|
|
125
|
-
throw new
|
|
127
|
+
throw new ViewerError({
|
|
128
|
+
id: ViewerErrorIds.InvalidCameraType,
|
|
129
|
+
message: `"autofocusActiveCamera" function is not implemented for camera type "${activeCamera?.getClassName()}"`,
|
|
130
|
+
});
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
// get bounding box of all visible meshes, this is the base for the autofocus algorithm
|
|
@@ -176,7 +181,10 @@ export class CameraManager {
|
|
|
176
181
|
const activeCamera = this.viewer.scene.activeCamera;
|
|
177
182
|
|
|
178
183
|
if (!(activeCamera instanceof ArcRotateCamera)) {
|
|
179
|
-
throw new
|
|
184
|
+
throw new ViewerError({
|
|
185
|
+
id: ViewerErrorIds.InvalidCameraType,
|
|
186
|
+
message: `"moveActiveCameraTo" function is not implemented for camera type "${activeCamera?.getClassName()}"`,
|
|
187
|
+
});
|
|
180
188
|
}
|
|
181
189
|
|
|
182
190
|
if (durationMs === 0) {
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
PBRMaterial,
|
|
12
12
|
RenderTargetTexture,
|
|
13
13
|
TransformNode,
|
|
14
|
-
Vector3,
|
|
15
14
|
Viewer,
|
|
16
15
|
} from '../index';
|
|
17
16
|
import { getIsScaledDownDevice } from '../internal/device-helper';
|
|
@@ -28,8 +27,6 @@ import {
|
|
|
28
27
|
* Manager for gltf export and augmented reality features
|
|
29
28
|
*/
|
|
30
29
|
export class GltfExportManager {
|
|
31
|
-
protected static readonly _EXPORT_ROOT_NAME = '__export_root__';
|
|
32
|
-
|
|
33
30
|
protected _maxTextureSize: number;
|
|
34
31
|
|
|
35
32
|
/**
|
|
@@ -234,24 +231,11 @@ export class GltfExportManager {
|
|
|
234
231
|
.forEach(material => GltfExportManager._exchangeMaterial(material as PBRMaterial));
|
|
235
232
|
}
|
|
236
233
|
|
|
237
|
-
// since Babylon.js v6 the conversion to right handed GLB coordinate system is done differently
|
|
238
|
-
// previously the geometry itself has been altered, now they negate the scaling of all root nodes
|
|
239
|
-
// this is an issue for us, since we will receive this negated scalings in the exported GLB, which leads to issues
|
|
240
|
-
// on iOS devices
|
|
241
|
-
// we fix that by adding a top level root node with a negative scaling as well
|
|
242
|
-
// the exporter just removes this node as he detects a "noop root node" (implementation details of Babylon.js)
|
|
243
|
-
// everything beneath this node remains untouched
|
|
244
|
-
// TODO BJS Update: Test AR export on iPhones as well and double check if we still need this special logic
|
|
245
|
-
const exportRootNode = new TransformNode(GltfExportManager._EXPORT_ROOT_NAME, this.viewer.scene);
|
|
246
|
-
exportRootNode.scaling = new Vector3(-1, 1, 1);
|
|
247
|
-
setInternalMetadataValue(exportRootNode, 'exportNode', true);
|
|
248
|
-
setInternalMetadataValue(exportRootNode, 'deleteAfterExport', true);
|
|
249
|
-
|
|
250
234
|
// create clones of each node (recursively), optionally exchange with cloned materials and mark these nodes for the
|
|
251
235
|
// export
|
|
252
236
|
this.viewer.scene.rootNodes
|
|
253
|
-
.filter(rootNode => rootNode.name !== GltfExportManager._EXPORT_ROOT_NAME)
|
|
254
|
-
.forEach(rootNode => this._prepareNodeForExport(rootNode,
|
|
237
|
+
// .filter(rootNode => rootNode.name !== GltfExportManager._EXPORT_ROOT_NAME)
|
|
238
|
+
.forEach(rootNode => this._prepareNodeForExport(rootNode, null, excluded));
|
|
255
239
|
|
|
256
240
|
// bake transformation of all meshes, so that no negative scalings are left
|
|
257
241
|
// it's important that this is done AFTER instanced meshes have been converted (_prepareNodeForExport)
|
|
@@ -295,7 +279,11 @@ export class GltfExportManager {
|
|
|
295
279
|
* Creates a clone of the node which should be used for the export.
|
|
296
280
|
* Also switches to the cloned material if required.
|
|
297
281
|
*/
|
|
298
|
-
protected _prepareNodeForExport(
|
|
282
|
+
protected _prepareNodeForExport(
|
|
283
|
+
node: Node,
|
|
284
|
+
clonedParent: TransformNode | null,
|
|
285
|
+
excluded?: ExcludedGeometryList
|
|
286
|
+
): void {
|
|
299
287
|
if (!GltfExportManager._shouldExportNode(node, excluded)) {
|
|
300
288
|
return;
|
|
301
289
|
}
|
|
@@ -338,14 +326,7 @@ export class GltfExportManager {
|
|
|
338
326
|
nodes.push(...this.viewer.scene.transformNodes);
|
|
339
327
|
}
|
|
340
328
|
|
|
341
|
-
const filteredNodes = nodes.filter(
|
|
342
|
-
node =>
|
|
343
|
-
getInternalMetadataValue(node, 'exportNode') &&
|
|
344
|
-
// in the desired use cases we want to exclude the export root node
|
|
345
|
-
// maybe add a parameter if we have to include it in certain scenarios in the future
|
|
346
|
-
node.name !== GltfExportManager._EXPORT_ROOT_NAME
|
|
347
|
-
);
|
|
348
|
-
|
|
329
|
+
const filteredNodes = nodes.filter(node => getInternalMetadataValue(node, 'exportNode'));
|
|
349
330
|
return filteredNodes;
|
|
350
331
|
}
|
|
351
332
|
}
|
|
@@ -426,12 +426,26 @@ export class ModelManager {
|
|
|
426
426
|
const curEnvTexture = this.viewer.scene.environmentTexture;
|
|
427
427
|
const curEnvIntensity = this.viewer.scene.environmentIntensity;
|
|
428
428
|
|
|
429
|
+
// CB-9240: Babylon.js doesn't recognize gzipped babylon files (`.babylon.gz`) as such, leading to a warning
|
|
430
|
+
// message, therefore we overwrite the plugin extension actively for such files
|
|
431
|
+
let pluginExtension;
|
|
432
|
+
try {
|
|
433
|
+
// URL constructor can throw for "valid" URL, which happened to be the case for the test asset environment where
|
|
434
|
+
// the urls are relative (starting with ".")
|
|
435
|
+
const urlObj = new URL(model.url);
|
|
436
|
+
if (urlObj.pathname.endsWith('.babylon.gz')) {
|
|
437
|
+
pluginExtension = '.babylon';
|
|
438
|
+
}
|
|
439
|
+
} catch (e) {}
|
|
440
|
+
|
|
429
441
|
let assetContainer;
|
|
430
442
|
try {
|
|
431
443
|
const fullContainer = (await SceneLoader.LoadAssetContainerAsync(
|
|
432
444
|
'',
|
|
433
445
|
model.url,
|
|
434
|
-
this.viewer.scene
|
|
446
|
+
this.viewer.scene,
|
|
447
|
+
undefined,
|
|
448
|
+
pluginExtension
|
|
435
449
|
)) as ExtendedAssetContainer;
|
|
436
450
|
|
|
437
451
|
// crop and store custom cbn data from .babylon file
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
Material,
|
|
6
6
|
PBRMaterial,
|
|
7
7
|
StandardMaterial,
|
|
8
|
+
Tags,
|
|
8
9
|
TransformNode,
|
|
9
10
|
Vector3,
|
|
10
11
|
Viewer,
|
|
@@ -13,14 +14,14 @@ import {
|
|
|
13
14
|
} from '../index';
|
|
14
15
|
import { getInternalMetadataValue, setInternalMetadataValue } from '../internal/metadata-helper';
|
|
15
16
|
import { paintableParameterObserver } from '../internal/paintable-helper';
|
|
16
|
-
import {
|
|
17
|
+
import { getTagsAsStrArr } from '../internal/tags-helper';
|
|
17
18
|
import {
|
|
18
19
|
BuiltInTextureParameter,
|
|
19
20
|
BuiltInTextureParameterKeys,
|
|
20
21
|
ParameterTextureChannelsKeys,
|
|
21
22
|
createBuiltInTextureParameter,
|
|
22
23
|
} from '../internal/texture-parameter-helper';
|
|
23
|
-
import { capitalize, isString } from 'lodash-es';
|
|
24
|
+
import { capitalize, isNumber, isString } from 'lodash-es';
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Parameters with a built in observer implementation
|
|
@@ -34,6 +35,7 @@ export const BuiltInParameter = {
|
|
|
34
35
|
Color: 'color',
|
|
35
36
|
Roughness: 'roughness',
|
|
36
37
|
Metallic: 'metallic',
|
|
38
|
+
Influence: 'influence',
|
|
37
39
|
/**
|
|
38
40
|
* Texture parameters are always a combination of the channel (e.g. `albedoTexture`) and a sub parameter
|
|
39
41
|
* (e.g. `uScale`). Use this function to create the parameter accordingly
|
|
@@ -49,8 +51,10 @@ export const LegacyParameter = {
|
|
|
49
51
|
Paintable: 'paintable',
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
export type MorphTargetParameterValue = { name: string; value: number };
|
|
55
|
+
|
|
52
56
|
export type ParameterName = string;
|
|
53
|
-
export type ParameterValue = string | number | boolean;
|
|
57
|
+
export type ParameterValue = string | number | boolean | Vector3 | Color3 | MorphTargetParameterValue;
|
|
54
58
|
|
|
55
59
|
export type TagParameterSubject = { tagName: string; nodeName?: never; materialName?: never };
|
|
56
60
|
export type NodeParameterSubject = { tagName?: never; nodeName: string; materialName?: never };
|
|
@@ -133,7 +137,16 @@ export class ParameterManager {
|
|
|
133
137
|
* Parses and converts input to a number value
|
|
134
138
|
*/
|
|
135
139
|
public static parseNumber(value: ParameterValue): number {
|
|
136
|
-
|
|
140
|
+
const parsedNumber = parseFloat(value.toString());
|
|
141
|
+
|
|
142
|
+
if (isNaN(parsedNumber)) {
|
|
143
|
+
throw new ViewerError({
|
|
144
|
+
id: ViewerErrorIds.InvalidParameterValue,
|
|
145
|
+
message: `Unable to parse "${value}" to a number`,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return parsedNumber;
|
|
137
150
|
}
|
|
138
151
|
|
|
139
152
|
/**
|
|
@@ -143,11 +156,15 @@ export class ParameterManager {
|
|
|
143
156
|
return value.toString();
|
|
144
157
|
}
|
|
145
158
|
|
|
146
|
-
// TODO WTT: enable setting Vector3 on the input directly
|
|
147
159
|
/**
|
|
148
|
-
* Parses a string of format "(x,y,z)"" to a "Vector3"
|
|
160
|
+
* Parses a string of format "(x,y,z)"" to a "Vector3".\
|
|
161
|
+
* Passing a Vector3 object directly is also valid.
|
|
149
162
|
*/
|
|
150
163
|
public static parseVector(value: ParameterValue): Vector3 {
|
|
164
|
+
if (value instanceof Vector3) {
|
|
165
|
+
return value.clone();
|
|
166
|
+
}
|
|
167
|
+
|
|
151
168
|
if (!isString(value)) {
|
|
152
169
|
throw new ViewerError({
|
|
153
170
|
id: ViewerErrorIds.InvalidParameterValue,
|
|
@@ -167,26 +184,35 @@ export class ParameterManager {
|
|
|
167
184
|
}
|
|
168
185
|
}
|
|
169
186
|
|
|
170
|
-
// TODO WTT: enable setting Vector3 on the input directly (maybe quaternion as well)
|
|
171
187
|
/**
|
|
172
|
-
* Parses a string of format `'(x,y,z)'` with angular degrees to a `Vector3` with rotation information in radians
|
|
188
|
+
* Parses a string of format `'(x,y,z)'` with angular degrees to a `Vector3` with rotation information in radians.\
|
|
189
|
+
* Passing a Vector3 object directly is also valid, in this case no degrees to radians conversion is made.
|
|
173
190
|
*/
|
|
174
191
|
public static parseRotation(value: ParameterValue): Vector3 {
|
|
175
192
|
const rotation = ParameterManager.parseVector(value);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
|
|
194
|
+
if (isString(value)) {
|
|
195
|
+
const deg2rad = (deg: number): number => {
|
|
196
|
+
return (deg * Math.PI) / 180;
|
|
197
|
+
};
|
|
198
|
+
return rotation.set(deg2rad(rotation.x), deg2rad(rotation.y), deg2rad(rotation.z));
|
|
199
|
+
} else {
|
|
200
|
+
return rotation;
|
|
201
|
+
}
|
|
180
202
|
}
|
|
181
203
|
|
|
182
|
-
// TODO WTT: enable setting Color3 on the input directly
|
|
183
204
|
/**
|
|
184
|
-
* Parses a string of format `'#rrggbb'` or `'(r,g,b)'` to a `Color3
|
|
205
|
+
* Parses a string of format `'#rrggbb'` or `'(r,g,b)'` to a `Color3`.\
|
|
206
|
+
* Passing a Color3 object directly is also valid.
|
|
185
207
|
*/
|
|
186
208
|
public static parseColor(value: ParameterValue): Color3 {
|
|
209
|
+
if (value instanceof Color3) {
|
|
210
|
+
return value.clone();
|
|
211
|
+
}
|
|
212
|
+
|
|
187
213
|
const cleanedValue = value.toString().split(' ').join('');
|
|
188
214
|
if (cleanedValue.startsWith('#')) {
|
|
189
|
-
return Color3.FromHexString(
|
|
215
|
+
return Color3.FromHexString(cleanedValue);
|
|
190
216
|
}
|
|
191
217
|
if (cleanedValue.startsWith('(') && cleanedValue.endsWith(')')) {
|
|
192
218
|
const rgb = cleanedValue.substring(1, cleanedValue.length - 1);
|
|
@@ -204,6 +230,31 @@ export class ParameterManager {
|
|
|
204
230
|
});
|
|
205
231
|
}
|
|
206
232
|
|
|
233
|
+
public static parseMorphTarget(value: ParameterValue): MorphTargetParameterValue {
|
|
234
|
+
let objValue;
|
|
235
|
+
if (isString(value)) {
|
|
236
|
+
try {
|
|
237
|
+
objValue = JSON.parse(value);
|
|
238
|
+
} catch {
|
|
239
|
+
throw new ViewerError({
|
|
240
|
+
id: ViewerErrorIds.InvalidParameterValue,
|
|
241
|
+
message: `Unable to parse "${value}" to a morph target parameter value: not a parseable string`,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
objValue = value;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (isString(objValue.name) && isNumber(objValue.value)) {
|
|
249
|
+
return { name: objValue.name, value: objValue.value };
|
|
250
|
+
} else {
|
|
251
|
+
throw new ViewerError({
|
|
252
|
+
id: ViewerErrorIds.InvalidParameterValue,
|
|
253
|
+
message: `Unable to parse "${value}" to a morph target parameter value: wrong format`,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
207
258
|
protected _parameterEntries: ParameterEntry[] = [];
|
|
208
259
|
protected _parameterObserver: { [parameterName: ParameterName]: ParameterObserver } = {};
|
|
209
260
|
|
|
@@ -352,7 +403,7 @@ export class ParameterManager {
|
|
|
352
403
|
* @internal
|
|
353
404
|
*/
|
|
354
405
|
public async applyParameterValuesToMaterial(material: Material): Promise<void> {
|
|
355
|
-
const tags =
|
|
406
|
+
const tags = getTagsAsStrArr(material);
|
|
356
407
|
|
|
357
408
|
const parameterEntriesToApply: ParameterEntry[] = [];
|
|
358
409
|
tags.forEach(tagName => {
|
|
@@ -383,7 +434,7 @@ export class ParameterManager {
|
|
|
383
434
|
material: PBRMaterial,
|
|
384
435
|
channel: ParameterTextureChannelsKeys
|
|
385
436
|
): Promise<void> {
|
|
386
|
-
const tags =
|
|
437
|
+
const tags = getTagsAsStrArr(material);
|
|
387
438
|
|
|
388
439
|
const parameterEntriesToApply: ParameterEntry[] = [];
|
|
389
440
|
tags.forEach(tagName => {
|
|
@@ -419,7 +470,7 @@ export class ParameterManager {
|
|
|
419
470
|
return nodeParamValue;
|
|
420
471
|
}
|
|
421
472
|
|
|
422
|
-
const tags =
|
|
473
|
+
const tags = getTagsAsStrArr(node);
|
|
423
474
|
const tagParamValue = tags.reduce<ParameterValue | undefined>((accValue, curTag) => {
|
|
424
475
|
// NOTE: it is possible that values are available for multiple tags
|
|
425
476
|
// in this case the resulting parameter value is quite "random" as the last tag in the tag string of the node has
|
|
@@ -444,7 +495,7 @@ export class ParameterManager {
|
|
|
444
495
|
return materialParamValue;
|
|
445
496
|
}
|
|
446
497
|
|
|
447
|
-
const tags =
|
|
498
|
+
const tags = getTagsAsStrArr(material);
|
|
448
499
|
const tagParamValue = tags.reduce<ParameterValue | undefined>((accValue, curTag) => {
|
|
449
500
|
const tagParamValue = this.getParameterValue({ tagName: curTag }, parameterName);
|
|
450
501
|
return accValue ?? tagParamValue;
|
|
@@ -487,6 +538,13 @@ export class ParameterManager {
|
|
|
487
538
|
const material = ParameterManager.parseString(newValue);
|
|
488
539
|
|
|
489
540
|
for (const node of nodes) {
|
|
541
|
+
if (!(node instanceof AbstractMesh)) {
|
|
542
|
+
throw new ViewerError({
|
|
543
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
544
|
+
message: `Material can't be set, as the target node "${node.name}" is not a mesh`,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
|
|
490
548
|
// NOTE: don't use node.isEnabled() as visibility observer is probably called in same cycle but later
|
|
491
549
|
// however the parameter value is already correct at this stage
|
|
492
550
|
// we have to go through all parents as well, because a parent may have been set to false, which also disables
|
|
@@ -501,14 +559,10 @@ export class ParameterManager {
|
|
|
501
559
|
curNode = curNode.parent as TransformNode;
|
|
502
560
|
}
|
|
503
561
|
|
|
504
|
-
// parameter visibility has priority, but if the visiblity is not controlled by the parameter use the plain
|
|
505
|
-
// Babylon.js isEnabled() check
|
|
506
562
|
const visible =
|
|
507
563
|
visibleByParameter !== undefined ? ParameterManager.parseBoolean(visibleByParameter) : node.isEnabled();
|
|
508
564
|
if (visible) {
|
|
509
|
-
|
|
510
|
-
// think of creating a framework with type guards (isMesh, canHaveMaterial, ...) around this
|
|
511
|
-
await this.viewer.materialManager.setMaterialOnMesh(material, node as AbstractMesh);
|
|
565
|
+
await this.viewer.materialManager.setMaterialOnMesh(material, node);
|
|
512
566
|
} else {
|
|
513
567
|
setInternalMetadataValue(node, 'deferredMaterial', material);
|
|
514
568
|
}
|
|
@@ -548,7 +602,10 @@ export class ParameterManager {
|
|
|
548
602
|
(material as StandardMaterial).diffuseColor = color;
|
|
549
603
|
break;
|
|
550
604
|
default:
|
|
551
|
-
throw new
|
|
605
|
+
throw new ViewerError({
|
|
606
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
607
|
+
message: `Setting color for material of instance "${materialCls}" not implemented`,
|
|
608
|
+
});
|
|
552
609
|
}
|
|
553
610
|
}
|
|
554
611
|
});
|
|
@@ -565,7 +622,10 @@ export class ParameterManager {
|
|
|
565
622
|
(material as StandardMaterial).roughness = roughness;
|
|
566
623
|
break;
|
|
567
624
|
default:
|
|
568
|
-
throw new
|
|
625
|
+
throw new ViewerError({
|
|
626
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
627
|
+
message: `Setting rougness for material of instance "${materialCls}" not implemented`,
|
|
628
|
+
});
|
|
569
629
|
}
|
|
570
630
|
}
|
|
571
631
|
});
|
|
@@ -579,7 +639,26 @@ export class ParameterManager {
|
|
|
579
639
|
(material as PBRMaterial).metallic = metallic;
|
|
580
640
|
break;
|
|
581
641
|
default:
|
|
582
|
-
throw new
|
|
642
|
+
throw new ViewerError({
|
|
643
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
644
|
+
message: `Setting metallic for material of instance "${materialCls}" not implemented`,
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
this.setParameterObserver(BuiltInParameter.Influence, async ({ nodes, newValue }) => {
|
|
650
|
+
const morphTargetValue = ParameterManager.parseMorphTarget(newValue);
|
|
651
|
+
|
|
652
|
+
for (const node of nodes) {
|
|
653
|
+
const target = node instanceof AbstractMesh && node.morphTargetManager?.getTargetByName(morphTargetValue.name);
|
|
654
|
+
|
|
655
|
+
if (target) {
|
|
656
|
+
target.influence = morphTargetValue.value;
|
|
657
|
+
} else {
|
|
658
|
+
throw new ViewerError({
|
|
659
|
+
id: ViewerErrorIds.InvalidParameterSubject,
|
|
660
|
+
message: `Morph target couldn't be found, node: ${node.name} / morph target: ${morphTargetValue.name}`,
|
|
661
|
+
});
|
|
583
662
|
}
|
|
584
663
|
}
|
|
585
664
|
});
|
|
@@ -679,7 +758,7 @@ export class ParameterManager {
|
|
|
679
758
|
console.warn(`Multiple materials for material name "${subject.materialName}" have been found`);
|
|
680
759
|
}
|
|
681
760
|
} else if (isTagParameterSubject(subject)) {
|
|
682
|
-
materials = assetContainer.materials.filter(material =>
|
|
761
|
+
materials = assetContainer.materials.filter(material => Tags.MatchesQuery(material, subject.tagName));
|
|
683
762
|
}
|
|
684
763
|
|
|
685
764
|
return materials;
|
|
@@ -697,7 +776,7 @@ export class ParameterManager {
|
|
|
697
776
|
console.warn(`Multiple nodes for node name "${subject.nodeName}" have been found`);
|
|
698
777
|
}
|
|
699
778
|
} else if (isTagParameterSubject(subject)) {
|
|
700
|
-
nodes = allNodes.filter(node =>
|
|
779
|
+
nodes = allNodes.filter(node => Tags.MatchesQuery(node, subject.tagName));
|
|
701
780
|
}
|
|
702
781
|
|
|
703
782
|
return nodes;
|
package/src/viewer-error.ts
CHANGED
|
@@ -21,14 +21,15 @@ type ViewerErrorData = {
|
|
|
21
21
|
*/
|
|
22
22
|
export const ViewerErrorIds = {
|
|
23
23
|
InvalidParameterValue: 'InvalidParameterValue',
|
|
24
|
+
InvalidParameterSubject: 'InvalidParameterSubject',
|
|
24
25
|
ModelNotRegistered: 'ModelNotRegistered',
|
|
25
26
|
ModelAlreadyExists: 'ModelAlreadyExists',
|
|
26
27
|
ModelIsNotAClone: 'ModelIsNotAClone',
|
|
27
28
|
AssetLoadingFailed: 'AssetLoadingFailed',
|
|
28
|
-
TextureCouldNotBeParsed: 'TextureCouldNotBeParsed',
|
|
29
29
|
MaterialAlreadyExists: 'MaterialAlreadyExists',
|
|
30
30
|
NotAClonedMaterial: 'NotAClonedMaterial',
|
|
31
31
|
InvalidDecalConfiguration: 'InvalidDecalConfiguration',
|
|
32
|
+
InvalidCameraType: 'InvalidCameraType',
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
/** @internal */
|