@combeenation/3d-viewer 4.0.0-beta3 → 4.0.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/README.md +3 -1
- package/dist/lib-cjs/api/classes/element.d.ts +14 -9
- package/dist/lib-cjs/api/classes/element.js +148 -87
- package/dist/lib-cjs/api/classes/element.js.map +1 -1
- package/dist/lib-cjs/api/classes/event.d.ts +15 -1
- package/dist/lib-cjs/api/classes/event.js +15 -1
- package/dist/lib-cjs/api/classes/event.js.map +1 -1
- package/dist/lib-cjs/api/classes/parameter.d.ts +101 -7
- package/dist/lib-cjs/api/classes/parameter.js +141 -21
- package/dist/lib-cjs/api/classes/parameter.js.map +1 -1
- package/dist/lib-cjs/api/classes/parameterObservable.js +11 -36
- package/dist/lib-cjs/api/classes/parameterObservable.js.map +1 -1
- package/dist/lib-cjs/api/classes/placementAnimation.d.ts +2 -2
- package/dist/lib-cjs/api/classes/placementAnimation.js +11 -0
- package/dist/lib-cjs/api/classes/placementAnimation.js.map +1 -1
- package/dist/lib-cjs/api/classes/variant.d.ts +48 -4
- package/dist/lib-cjs/api/classes/variant.js +320 -46
- package/dist/lib-cjs/api/classes/variant.js.map +1 -1
- package/dist/lib-cjs/api/classes/variantInstance.d.ts +5 -1
- package/dist/lib-cjs/api/classes/variantInstance.js +10 -0
- package/dist/lib-cjs/api/classes/variantInstance.js.map +1 -1
- package/dist/lib-cjs/api/classes/viewer.d.ts +6 -3
- package/dist/lib-cjs/api/classes/viewer.js +140 -59
- package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
- package/dist/lib-cjs/api/internal/sceneSetup.d.ts +5 -1
- package/dist/lib-cjs/api/internal/sceneSetup.js +75 -71
- package/dist/lib-cjs/api/internal/sceneSetup.js.map +1 -1
- package/dist/lib-cjs/api/util/babylonHelper.d.ts +54 -4
- package/dist/lib-cjs/api/util/babylonHelper.js +160 -8
- package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
- package/dist/lib-cjs/api/util/globalTypes.d.ts +62 -8
- package/dist/lib-cjs/api/util/resourceHelper.d.ts +13 -8
- package/dist/lib-cjs/api/util/resourceHelper.js +14 -14
- package/dist/lib-cjs/api/util/resourceHelper.js.map +1 -1
- package/dist/lib-cjs/index.d.ts +24 -22
- package/dist/lib-cjs/index.js +42 -38
- package/dist/lib-cjs/index.js.map +1 -1
- package/package.json +5 -5
- package/src/api/classes/element.ts +118 -91
- package/src/api/classes/event.ts +16 -1
- package/src/api/classes/parameter.ts +153 -22
- package/src/api/classes/parameterObservable.ts +9 -31
- package/src/api/classes/{elementParameterizable.ts → parameterizable.ts} +12 -1
- package/src/api/classes/placementAnimation.ts +10 -0
- package/src/api/classes/variant.ts +187 -40
- package/src/api/classes/variantInstance.ts +8 -1
- package/src/api/classes/variantParameterizable.ts +73 -0
- package/src/api/classes/viewer.ts +83 -17
- package/src/api/classes/viewerLight.ts +330 -0
- package/src/api/internal/sceneSetup.ts +99 -109
- package/src/api/util/babylonHelper.ts +173 -10
- package/src/api/util/globalTypes.ts +71 -10
- package/src/api/util/resourceHelper.ts +16 -16
- package/src/api/util/stringHelper.ts +26 -0
- package/src/dev.ts +3 -7
- package/src/index.ts +27 -23
- package/src/pagesconfig.json +4 -0
|
@@ -1,35 +1,40 @@
|
|
|
1
1
|
import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
|
|
2
|
+
import { Light } from '@babylonjs/core/Lights/light';
|
|
3
|
+
import { ShadowGenerator } from '@babylonjs/core/Lights/Shadows/shadowGenerator';
|
|
2
4
|
import { Material } from '@babylonjs/core/Materials/material';
|
|
3
5
|
import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
|
|
4
6
|
import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
|
|
5
|
-
import { Axis, Space } from '@babylonjs/core/Maths/math.axis';
|
|
6
7
|
import { Color3 } from '@babylonjs/core/Maths/math.color';
|
|
7
8
|
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
|
8
9
|
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
|
|
9
10
|
import { Mesh } from '@babylonjs/core/Meshes/mesh';
|
|
10
11
|
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
11
|
-
import {
|
|
12
|
+
import { has, isArray, isNumber, isPlainObject, merge, union } from 'lodash-es';
|
|
12
13
|
import {
|
|
13
14
|
activateTransformNode as activate,
|
|
14
15
|
addToHighlightLayer,
|
|
16
|
+
addToShadowGenerator,
|
|
15
17
|
assertTransformNode,
|
|
16
18
|
cloneTransformNode,
|
|
17
19
|
cloneTransformNodeMaterial,
|
|
18
20
|
deactivateTransformNode as deactivate,
|
|
19
21
|
getClientRectFromMesh,
|
|
20
|
-
|
|
22
|
+
injectNodeMetadata,
|
|
21
23
|
mapToDottedNodes,
|
|
24
|
+
moveTransformNode,
|
|
22
25
|
removeFromHighlightLayer,
|
|
26
|
+
removeFromShadowGenerator,
|
|
27
|
+
rotateTransformNode,
|
|
23
28
|
setMaterial,
|
|
24
29
|
setMaterialColor,
|
|
25
30
|
setMaterialMetallness,
|
|
26
31
|
setMaterialRoughness,
|
|
27
|
-
setMaterialTexture
|
|
32
|
+
setMaterialTexture,
|
|
33
|
+
setReceiveShadows
|
|
28
34
|
} from '../util/babylonHelper';
|
|
29
|
-
import {
|
|
35
|
+
import { createImageFromImgSrc, createImageFromSvg } from '../util/resourceHelper';
|
|
36
|
+
import { VariantParameterizable } from './../classes/variantParameterizable';
|
|
30
37
|
import { DottedPath } from './dottedPath';
|
|
31
|
-
import { ElementParameterizable } from './elementParameterizable';
|
|
32
|
-
import { Event } from './event';
|
|
33
38
|
import { Parameter } from './parameter';
|
|
34
39
|
import { Variant } from './variant';
|
|
35
40
|
|
|
@@ -40,22 +45,20 @@ import { Variant } from './variant';
|
|
|
40
45
|
* When used in typings, refer to via its alias {@link VariantElement} to prevent name clashes with the web APIs
|
|
41
46
|
* [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) class
|
|
42
47
|
*/
|
|
43
|
-
export class Element extends
|
|
48
|
+
export class Element extends VariantParameterizable {
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
public readonly nodes: TransformNode[] = [];
|
|
46
51
|
|
|
47
|
-
protected readonly
|
|
52
|
+
protected readonly _dottedNodes: Map<DottedPath, TransformNode> = new Map();
|
|
48
53
|
|
|
49
54
|
protected _highlightLayer?: HighlightLayer;
|
|
50
55
|
|
|
51
|
-
public readonly nodes: TransformNode[] = [];
|
|
52
|
-
|
|
53
56
|
/**
|
|
54
57
|
* Constructor.
|
|
55
58
|
*/
|
|
56
|
-
|
|
59
|
+
protected constructor( public readonly variant: Variant,
|
|
57
60
|
public readonly name: string ) {
|
|
58
|
-
super();
|
|
61
|
+
super( variant, name );
|
|
59
62
|
if ( process.env.NODE_ENV?.toLowerCase().includes('dev')) {
|
|
60
63
|
this.assertPathDefinitions();
|
|
61
64
|
}
|
|
@@ -70,6 +73,13 @@ export class Element extends ElementParameterizable {
|
|
|
70
73
|
this.addParameterObservers();
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Creates an {@link Element} with given name.
|
|
78
|
+
*/
|
|
79
|
+
public static async create( variant: Variant, name: string ): Promise<Element> {
|
|
80
|
+
return new Element( variant, name );
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
/**
|
|
74
84
|
* The {@link DottedPath} in the built tree of {@link Element}s.
|
|
75
85
|
* E.g. "_.top-1.sub-2.sub-sub-3.el-1"
|
|
@@ -212,41 +222,11 @@ export class Element extends ElementParameterizable {
|
|
|
212
222
|
}
|
|
213
223
|
|
|
214
224
|
/**
|
|
215
|
-
*
|
|
216
|
-
* {@link StructureJson} and broadcasts all {@link ParameterObserver}s.
|
|
217
|
-
*
|
|
225
|
+
* @see {@link VariantParameterizable.commitParameters}
|
|
218
226
|
* @emit {@link Event.ELEMENT_PARAMETER_COMMITTED}
|
|
219
227
|
*/
|
|
220
|
-
public async commitParameters( parameters?: ParameterBag ): Promise<
|
|
221
|
-
|
|
222
|
-
parameters = {};
|
|
223
|
-
}
|
|
224
|
-
const oldParameters = cloneDeep( this.parameters );
|
|
225
|
-
merge( this.parameters, parameters );
|
|
226
|
-
// handle parameter observers
|
|
227
|
-
let observerPromises: Promise<void | ParameterObserver>[] = [];
|
|
228
|
-
for( const parameter in this.parameters ) {
|
|
229
|
-
const oldParameterValue = oldParameters[parameter];
|
|
230
|
-
const newParameterValue = this.parameters[parameter];
|
|
231
|
-
this.variant.assertParameter( this.variant.inheritedParameterDeclaration, parameter, newParameterValue );
|
|
232
|
-
if( oldParameterValue === newParameterValue ) {
|
|
233
|
-
continue;
|
|
234
|
-
}
|
|
235
|
-
// parameter changed
|
|
236
|
-
const parameterObservers = mergeMaps( this._parameterObservers, this.parameterObservers );
|
|
237
|
-
if( parameterObservers.has( parameter ) ) {
|
|
238
|
-
const observers = parameterObservers.get( parameter )!;
|
|
239
|
-
observerPromises = concat(observerPromises, observers.map( observer => {
|
|
240
|
-
const observerResult = observer( this, oldParameterValue, newParameterValue );
|
|
241
|
-
return Promise.resolve( observerResult ).then( () => {
|
|
242
|
-
this.broadcastEvent( Event.ELEMENT_PARAMETER_COMMITTED,
|
|
243
|
-
this, parameter, oldParameterValue, newParameterValue );
|
|
244
|
-
} );
|
|
245
|
-
} ) );
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
await Promise.all( observerPromises );
|
|
249
|
-
return this;
|
|
228
|
+
public async commitParameters( parameters?: ParameterBag ): Promise<VariantParameterizable> {
|
|
229
|
+
return super.commitParameters( parameters );
|
|
250
230
|
}
|
|
251
231
|
|
|
252
232
|
/**
|
|
@@ -287,18 +267,18 @@ export class Element extends ElementParameterizable {
|
|
|
287
267
|
throw new Error( `The path must be an instance of "AbstractMesh" for paintable "${paintable}" ` +
|
|
288
268
|
`in element "${this.id}".` );
|
|
289
269
|
}
|
|
290
|
-
if( node.material && !
|
|
270
|
+
if( node.material && !has( node.metadata, 'dirty.material' ) ) {
|
|
291
271
|
cloneTransformNodeMaterial( node );
|
|
292
272
|
}
|
|
293
273
|
if( !node.material ) {
|
|
294
274
|
node.material = new StandardMaterial( `${this.id}.${paintable}.material`, this.variant.viewer.scene );
|
|
295
275
|
}
|
|
296
276
|
node.material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;
|
|
297
|
-
if( !
|
|
277
|
+
if( !has( node.metadata, 'dirty.material.texture' ) ) {
|
|
298
278
|
// inject initial value and mark as dirty
|
|
299
|
-
|
|
279
|
+
injectNodeMetadata( node, { dirty: { material: { texture: true } } } );
|
|
300
280
|
}
|
|
301
|
-
|
|
281
|
+
|
|
302
282
|
// consider width and height of the paintable
|
|
303
283
|
const widthAndHeight = {
|
|
304
284
|
width: imageSource.width,
|
|
@@ -328,7 +308,7 @@ export class Element extends ElementParameterizable {
|
|
|
328
308
|
|
|
329
309
|
// finally apply the texture on the desired node material
|
|
330
310
|
setMaterialTexture( node, texture, false );
|
|
331
|
-
|
|
311
|
+
|
|
332
312
|
return this;
|
|
333
313
|
}
|
|
334
314
|
|
|
@@ -362,12 +342,12 @@ export class Element extends ElementParameterizable {
|
|
|
362
342
|
}
|
|
363
343
|
if( visible === true ) {
|
|
364
344
|
element.nodes.forEach( node => {
|
|
365
|
-
|
|
345
|
+
injectNodeMetadata( node, { visibility: node.isEnabled() } );
|
|
366
346
|
activate( node );
|
|
367
347
|
} );
|
|
368
348
|
} else if( visible === false ) {
|
|
369
349
|
element.nodes.forEach( node => {
|
|
370
|
-
|
|
350
|
+
injectNodeMetadata( node, { visibility: node.isEnabled() } );
|
|
371
351
|
deactivate( node );
|
|
372
352
|
} );
|
|
373
353
|
}
|
|
@@ -383,7 +363,7 @@ export class Element extends ElementParameterizable {
|
|
|
383
363
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
384
364
|
const material = element.variant.getMaterial( newValue.toString() );
|
|
385
365
|
element.nodes.forEach( node => {
|
|
386
|
-
assertTransformNode(node, (node:
|
|
366
|
+
assertTransformNode(node, (node: AbstractMesh) => {
|
|
387
367
|
if( node instanceof InstancedMesh ) {
|
|
388
368
|
throw new Error( `Changing parameter "${Parameter.MATERIAL}" ` +
|
|
389
369
|
`of an InstancedMesh is not supported. ` +
|
|
@@ -398,19 +378,19 @@ export class Element extends ElementParameterizable {
|
|
|
398
378
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
399
379
|
const color = Parameter.parseColor( newValue );
|
|
400
380
|
element.nodes.forEach( node => {
|
|
401
|
-
assertTransformNode(node, (node:
|
|
381
|
+
assertTransformNode(node, (node: AbstractMesh) => {
|
|
402
382
|
if( node instanceof InstancedMesh ) {
|
|
403
383
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_COLOR}" ` +
|
|
404
384
|
`of an InstancedMesh is not supported. ` +
|
|
405
385
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
406
386
|
}
|
|
407
387
|
});
|
|
408
|
-
if( !
|
|
388
|
+
if( !has( node.metadata, 'dirty.material' ) ) {
|
|
409
389
|
cloneTransformNodeMaterial( node );
|
|
410
390
|
}
|
|
411
|
-
if( !
|
|
391
|
+
if( !has( node.metadata, 'dirty.material.color' ) ) {
|
|
412
392
|
// inject initial value and mark as dirty
|
|
413
|
-
|
|
393
|
+
injectNodeMetadata( node, { dirty: { material: { color: oldValue } } } );
|
|
414
394
|
}
|
|
415
395
|
setMaterialColor( node, color );
|
|
416
396
|
} );
|
|
@@ -420,19 +400,19 @@ export class Element extends ElementParameterizable {
|
|
|
420
400
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
421
401
|
const metallness = Parameter.parseNumber( newValue );
|
|
422
402
|
element.nodes.forEach( node => {
|
|
423
|
-
assertTransformNode(node, (node:
|
|
403
|
+
assertTransformNode(node, (node: AbstractMesh) => {
|
|
424
404
|
if( node instanceof InstancedMesh ) {
|
|
425
405
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_METALLNESS}" ` +
|
|
426
406
|
`of an InstancedMesh is not supported. ` +
|
|
427
407
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
428
408
|
}
|
|
429
409
|
});
|
|
430
|
-
if( !
|
|
410
|
+
if( !has( node.metadata, 'dirty.material' ) ) {
|
|
431
411
|
cloneTransformNodeMaterial( node );
|
|
432
412
|
}
|
|
433
|
-
if( !
|
|
413
|
+
if( !has( node.metadata, 'dirty.material.metallness' ) ) {
|
|
434
414
|
// inject initial value and mark as dirty
|
|
435
|
-
|
|
415
|
+
injectNodeMetadata( node, { dirty: { material: { metallness: oldValue } } } );
|
|
436
416
|
}
|
|
437
417
|
setMaterialMetallness( node, metallness );
|
|
438
418
|
} );
|
|
@@ -442,19 +422,19 @@ export class Element extends ElementParameterizable {
|
|
|
442
422
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
443
423
|
const roughness = Parameter.parseNumber( newValue );
|
|
444
424
|
element.nodes.forEach( node => {
|
|
445
|
-
assertTransformNode(node, (node:
|
|
425
|
+
assertTransformNode(node, (node: AbstractMesh) => {
|
|
446
426
|
if( node instanceof InstancedMesh ) {
|
|
447
427
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_ROUGHNESS}" ` +
|
|
448
428
|
`of an InstancedMesh is not supported. ` +
|
|
449
429
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
450
430
|
}
|
|
451
431
|
});
|
|
452
|
-
if( !
|
|
432
|
+
if( !has( node.metadata, 'dirty.material' ) ) {
|
|
453
433
|
cloneTransformNodeMaterial( node );
|
|
454
434
|
}
|
|
455
|
-
if( !
|
|
435
|
+
if( !has( node.metadata, 'dirty.material.roughness' ) ) {
|
|
456
436
|
// inject initial value and mark as dirty
|
|
457
|
-
|
|
437
|
+
injectNodeMetadata( node, { dirty: { material: { roughness: oldValue } } } );
|
|
458
438
|
}
|
|
459
439
|
setMaterialRoughness( node, roughness );
|
|
460
440
|
} );
|
|
@@ -510,7 +490,7 @@ export class Element extends ElementParameterizable {
|
|
|
510
490
|
// Add/Remove meshes to previously created highlight layers.
|
|
511
491
|
if( highlighted === true ) {
|
|
512
492
|
element.nodes.forEach( node => {
|
|
513
|
-
assertTransformNode(node, (node:
|
|
493
|
+
assertTransformNode(node, (node: AbstractMesh) => {
|
|
514
494
|
if( node instanceof InstancedMesh ) {
|
|
515
495
|
throw new Error( `Changing parameter "${Parameter.HIGHLIGHTED}" ` +
|
|
516
496
|
`of an InstancedMesh is not supported. ` +
|
|
@@ -537,35 +517,61 @@ export class Element extends ElementParameterizable {
|
|
|
537
517
|
this._parameterObservers.set( Parameter.POSITION, [
|
|
538
518
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
539
519
|
// we have to deal just with root nodes here due to relative impacts in a node tree
|
|
540
|
-
element.nodes.forEach( node =>
|
|
541
|
-
// remember absolute position and reset it before translating
|
|
542
|
-
if( !get( node.metadata, 'position' ) ) {
|
|
543
|
-
node.metadata.position = node.absolutePosition.clone();
|
|
544
|
-
}
|
|
545
|
-
node.setAbsolutePosition( node.metadata.position );
|
|
546
|
-
// move
|
|
547
|
-
const distance = Parameter.parseVector( newValue );
|
|
548
|
-
node.translate( Axis.X, distance.x, Space.WORLD );
|
|
549
|
-
node.translate( Axis.Y, distance.y, Space.WORLD );
|
|
550
|
-
node.translate( Axis.Z, distance.z, Space.WORLD );
|
|
551
|
-
} );
|
|
520
|
+
element.nodes.forEach( node => moveTransformNode( node, Parameter.parseVector( newValue ) ) );
|
|
552
521
|
}
|
|
553
522
|
] );
|
|
554
523
|
this._parameterObservers.set( Parameter.ROTATION, [
|
|
555
524
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
525
|
+
// The current implementation (rotating around coordinates 0,0,0) implicitly mutates the position of a node.
|
|
526
|
+
// Since a user expects the rotation after the positioning, we have to manually fire the position observers.
|
|
527
|
+
// Without calling these observers, the pivot and the position of a node is initially the same before rotating,
|
|
528
|
+
// so there is no rotation happening at all.
|
|
529
|
+
if( Parameter.POSITION in element.inheritedParameters ) {
|
|
530
|
+
await element.commitParameter( Parameter.POSITION, element.inheritedParameters[Parameter.POSITION] );
|
|
531
|
+
}
|
|
556
532
|
// we have to deal just with root nodes here due to relative impacts in a node tree
|
|
557
|
-
element.nodes.forEach( node =>
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
533
|
+
element.nodes.forEach( node => rotateTransformNode( node, Parameter.parseRotation( newValue ) ) );
|
|
534
|
+
}
|
|
535
|
+
] );
|
|
536
|
+
this._parameterObservers.set( Parameter.CAST_SHADOW, [
|
|
537
|
+
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
538
|
+
let castShadow;
|
|
539
|
+
try {
|
|
540
|
+
castShadow = Parameter.parseBoolean( newValue );
|
|
541
|
+
} catch( e ) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
let lightCsl = element.inheritedParameters[Parameter.CAST_SHADOW_FROM_LIGHTS];
|
|
545
|
+
if( ! lightCsl ) {
|
|
546
|
+
lightCsl = element.variant.inheritedViewerLights.map( l => l.name ).join( ',' );
|
|
547
|
+
}
|
|
548
|
+
if( castShadow === true ) {
|
|
549
|
+
await this.castShadowValueHandler( lightCsl, addToShadowGenerator );
|
|
550
|
+
}
|
|
551
|
+
if( castShadow === false ) {
|
|
552
|
+
await this.castShadowValueHandler( lightCsl, removeFromShadowGenerator );
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
] );
|
|
556
|
+
this._parameterObservers.set( Parameter.CAST_SHADOW_FROM_LIGHTS, [
|
|
557
|
+
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
558
|
+
// TODO: Possible performance issue in combination with CAST_SHADOW, since both observers are initially called
|
|
559
|
+
// when CAST_SHADOW and CAST_SHADOW_FROM_LIGHTS are defined in the spec.
|
|
560
|
+
const lightCsl = element.variant.inheritedViewerLights.map( l => l.name ).join( ',' );
|
|
561
|
+
// cleanup all shadow generators
|
|
562
|
+
await this.castShadowValueHandler( lightCsl, removeFromShadowGenerator );
|
|
563
|
+
if( element.castShadow === true ) {
|
|
564
|
+
// if newValue is undefined or '' then set newValue to lightCsl (use all lights)
|
|
565
|
+
if( !newValue ) {
|
|
566
|
+
newValue = lightCsl;
|
|
561
567
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
568
|
+
await this.castShadowValueHandler( newValue, addToShadowGenerator );
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
] );
|
|
572
|
+
this._parameterObservers.set( Parameter.RECEIVE_SHADOWS, [
|
|
573
|
+
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
574
|
+
element.nodes.forEach( node => setReceiveShadows( node, Parameter.parseBoolean( newValue ) ) );
|
|
569
575
|
}
|
|
570
576
|
] );
|
|
571
577
|
return this;
|
|
@@ -614,4 +620,25 @@ export class Element extends ElementParameterizable {
|
|
|
614
620
|
} );
|
|
615
621
|
}
|
|
616
622
|
|
|
623
|
+
/**
|
|
624
|
+
* Handles callback for given light parameter.
|
|
625
|
+
*/
|
|
626
|
+
private async castShadowValueHandler( lightCsl: ParameterValue, mutator: CallableFunction ) {
|
|
627
|
+
let lights: Light[] = [];
|
|
628
|
+
for( const lightName of Parameter.parseCommaSeparatedList( lightCsl ) ) {
|
|
629
|
+
const viewerLight = await this.variant.getViewerLight( lightName );
|
|
630
|
+
if( viewerLight ) {
|
|
631
|
+
lights.push( viewerLight.light );
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
const shadowGenerators = lights
|
|
635
|
+
.map( light => light?.getShadowGenerator() as ShadowGenerator )
|
|
636
|
+
.filter( Boolean );
|
|
637
|
+
shadowGenerators.forEach( generator => {
|
|
638
|
+
this.nodes.forEach( node => {
|
|
639
|
+
mutator( generator, node );
|
|
640
|
+
} );
|
|
641
|
+
} );
|
|
642
|
+
}
|
|
643
|
+
|
|
617
644
|
}
|
package/src/api/classes/event.ts
CHANGED
|
@@ -262,13 +262,28 @@ export class Event {
|
|
|
262
262
|
* * {@link Element}
|
|
263
263
|
*
|
|
264
264
|
* Payload:
|
|
265
|
-
* *
|
|
265
|
+
* * element: {@link Element}
|
|
266
266
|
* * parameter: string
|
|
267
267
|
* * oldValue: string
|
|
268
268
|
* * newValue: string
|
|
269
269
|
*/
|
|
270
270
|
public static readonly ELEMENT_PARAMETER_COMMITTED = 'elementParameterCommitted';
|
|
271
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Fired after a parameter on an {@link ViewerLight} has been committed.
|
|
274
|
+
*
|
|
275
|
+
* Scopes:
|
|
276
|
+
* * Global
|
|
277
|
+
* * {@link ViewerLight}
|
|
278
|
+
*
|
|
279
|
+
* Payload:
|
|
280
|
+
* * light: {@link ViewerLight}
|
|
281
|
+
* * parameter: string
|
|
282
|
+
* * oldValue: string
|
|
283
|
+
* * newValue: string
|
|
284
|
+
*/
|
|
285
|
+
public static readonly VIEWER_LIGHT_PARAMETER_COMMITTED = 'viewerLightParameterCommitted';
|
|
286
|
+
|
|
272
287
|
/**
|
|
273
288
|
* Fired after a parameter on an {@link SceneManager} has been committed.
|
|
274
289
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Color3 } from '@babylonjs/core/Maths/math.color';
|
|
2
2
|
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
|
|
3
|
-
import { isNumber, isString } from 'lodash-es';
|
|
3
|
+
import { get, isEmpty, isNumber, isString } from 'lodash-es';
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -16,19 +16,20 @@ export class Parameter {
|
|
|
16
16
|
private constructor() {}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Mutates the visibility. Helper methods are {@link
|
|
20
|
-
* {@link
|
|
19
|
+
* Mutates the visibility. Helper methods are {@link VariantParameterizable.show} and
|
|
20
|
+
* {@link VariantParameterizable.hide}. Getter and setter is {@link VariantParameterizable.visible}.
|
|
21
21
|
*
|
|
22
22
|
* Scopes:
|
|
23
23
|
* * {@link Element}
|
|
24
24
|
* * {@link Variant}
|
|
25
|
+
* * {@link ViewerLight} Available for all light types
|
|
25
26
|
*
|
|
26
27
|
* @parser {@link parseBoolean}
|
|
27
28
|
*/
|
|
28
29
|
public static readonly VISIBLE = 'visible';
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
* Stretches or compresses some meshes. Getter and setter is {@link
|
|
32
|
+
* Stretches or compresses some meshes. Getter and setter is {@link VariantParameterizable.scaling}.
|
|
32
33
|
*
|
|
33
34
|
* Scopes:
|
|
34
35
|
* * {@link Element}
|
|
@@ -39,7 +40,7 @@ export class Parameter {
|
|
|
39
40
|
public static readonly SCALING = 'scaling';
|
|
40
41
|
|
|
41
42
|
/**
|
|
42
|
-
* Mutates the material. Getter and setter is {@link
|
|
43
|
+
* Mutates the material. Getter and setter is {@link VariantParameterizable.material}. The value of this parameter
|
|
43
44
|
* represents the ID of a baked-in glTF or custom created material in the {@link Variant} tree.
|
|
44
45
|
*
|
|
45
46
|
* Scopes:
|
|
@@ -106,7 +107,7 @@ export class Parameter {
|
|
|
106
107
|
public static readonly HIGHLIGHT_COLOR = 'highlight.color';
|
|
107
108
|
|
|
108
109
|
/**
|
|
109
|
-
* Mutates the highlighted state. Getter and setter is {@link
|
|
110
|
+
* Mutates the highlighted state. Getter and setter is {@link VariantParameterizable.highlighted}.
|
|
110
111
|
*
|
|
111
112
|
* Scopes:
|
|
112
113
|
* * {@link Element}
|
|
@@ -117,18 +118,19 @@ export class Parameter {
|
|
|
117
118
|
public static readonly HIGHLIGHTED = 'highlighted';
|
|
118
119
|
|
|
119
120
|
/**
|
|
120
|
-
* Mutates the position relative to its origin position. Getter and setter is {@link
|
|
121
|
+
* Mutates the position relative to its origin position. Getter and setter is {@link VariantParameterizable.position}.
|
|
121
122
|
*
|
|
122
123
|
* Scopes:
|
|
123
124
|
* * {@link Element}
|
|
124
125
|
* * {@link Variant}
|
|
126
|
+
* * {@link ViewerLight} Available for [PointLight](https://doc.babylonjs.com/typedoc/classes/babylon.pointlight#position), [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#position), [DirectionalLight](https://doc.babylonjs.com/typedoc/classes/babylon.directionallight#position)
|
|
125
127
|
*
|
|
126
128
|
* @parser {@link parseVector}
|
|
127
129
|
*/
|
|
128
130
|
public static readonly POSITION = 'position';
|
|
129
131
|
|
|
130
132
|
/**
|
|
131
|
-
* Mutates the rotation relative to its origin rotation. Getter and setter is {@link
|
|
133
|
+
* Mutates the rotation relative to its origin rotation. Getter and setter is {@link VariantParameterizable.rotation}.
|
|
132
134
|
*
|
|
133
135
|
* Scopes:
|
|
134
136
|
* * {@link Element}
|
|
@@ -138,24 +140,126 @@ export class Parameter {
|
|
|
138
140
|
*/
|
|
139
141
|
public static readonly ROTATION = 'rotation';
|
|
140
142
|
|
|
143
|
+
/**
|
|
144
|
+
* Mutates whether a shadow should be casted or not.
|
|
145
|
+
*
|
|
146
|
+
* Scopes:
|
|
147
|
+
* * {@link Element}
|
|
148
|
+
* * {@link Variant}
|
|
149
|
+
*
|
|
150
|
+
* @parser {@link parseBoolean}
|
|
151
|
+
*/
|
|
152
|
+
public static readonly CAST_SHADOW = 'castShadow';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Mutates from which lights a shadow should be casted.
|
|
156
|
+
*
|
|
157
|
+
* Scopes:
|
|
158
|
+
* * {@link Element}
|
|
159
|
+
* * {@link Variant}
|
|
160
|
+
*
|
|
161
|
+
* @parser {@link parseCommaSeparatedList}
|
|
162
|
+
*/
|
|
163
|
+
public static readonly CAST_SHADOW_FROM_LIGHTS = 'castShadow.fromLights';
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Mutates whether to receive shadows or not.
|
|
167
|
+
*
|
|
168
|
+
* Scopes:
|
|
169
|
+
* * {@link Element}
|
|
170
|
+
* * {@link Variant}
|
|
171
|
+
*
|
|
172
|
+
* @parser {@link parseBoolean}
|
|
173
|
+
*/
|
|
174
|
+
public static readonly RECEIVE_SHADOWS = 'receiveShadows';
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Mutates the intensity of Lights.
|
|
178
|
+
*
|
|
179
|
+
* Scopes:
|
|
180
|
+
* * {@link ViewerLight} Available for [PointLight](https://doc.babylonjs.com/typedoc/classes/babylon.pointlight#intensity), [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#intensity), [DirectionalLight](https://doc.babylonjs.com/typedoc/classes/babylon.directionallight#intensity), [HemisphericLight](https://doc.babylonjs.com/typedoc/classes/babylon.hemisphericlight#intensity)
|
|
181
|
+
*
|
|
182
|
+
* @parser {@link parseNumber}
|
|
183
|
+
*/
|
|
184
|
+
public static readonly INTENSITY = 'intensity';
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Mutates the direction of Lights.
|
|
188
|
+
*
|
|
189
|
+
* Scopes:
|
|
190
|
+
* * {@link ViewerLight} Available for [PointLight](https://doc.babylonjs.com/typedoc/classes/babylon.pointlight#direction), [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#direction), [DirectionalLight](https://doc.babylonjs.com/typedoc/classes/babylon.directionallight#direction), [HemisphericLight](https://doc.babylonjs.com/typedoc/classes/babylon.hemisphericlight#direction)
|
|
191
|
+
*
|
|
192
|
+
* @parser {@link parseNumber}
|
|
193
|
+
*/
|
|
194
|
+
public static readonly DIRECTION = 'direction';
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Mutates the angle of Lights.
|
|
198
|
+
*
|
|
199
|
+
* Scopes:
|
|
200
|
+
* * {@link ViewerLight} Available for [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#angle)
|
|
201
|
+
*
|
|
202
|
+
* @parser {@link parseNumber}
|
|
203
|
+
*/
|
|
204
|
+
public static readonly ANGLE = 'angle';
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Mutates the exponent of Lights.
|
|
208
|
+
*
|
|
209
|
+
* Scopes:
|
|
210
|
+
* * {@link ViewerLight} Available for [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#exponent)
|
|
211
|
+
*
|
|
212
|
+
* @parser {@link parseNumber}
|
|
213
|
+
*/
|
|
214
|
+
public static readonly EXPONENT = 'exponent';
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Mutates the diffuse color of Lights.
|
|
218
|
+
*
|
|
219
|
+
* Scopes:
|
|
220
|
+
* * {@link ViewerLight} Available for [PointLight](https://doc.babylonjs.com/typedoc/classes/babylon.pointlight#diffuse), [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#diffuse), [DirectionalLight](https://doc.babylonjs.com/typedoc/classes/babylon.directionallight#diffuse), [HemisphericLight](https://doc.babylonjs.com/typedoc/classes/babylon.hemisphericlight#diffuse)
|
|
221
|
+
*
|
|
222
|
+
* @parser {@link parseNumber}
|
|
223
|
+
*/
|
|
224
|
+
public static readonly DIFFUSE = 'diffuse';
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Mutates the specular color of Lights.
|
|
228
|
+
*
|
|
229
|
+
* Scopes:
|
|
230
|
+
* * {@link ViewerLight} Available for [PointLight](https://doc.babylonjs.com/typedoc/classes/babylon.pointlight#specular), [SpotLight](https://doc.babylonjs.com/typedoc/classes/babylon.spotlight#specular), [DirectionalLight](https://doc.babylonjs.com/typedoc/classes/babylon.directionallight#specular), [HemisphericLight](https://doc.babylonjs.com/typedoc/classes/babylon.hemisphericlight#specular)
|
|
231
|
+
*
|
|
232
|
+
* @parser {@link parseNumber}
|
|
233
|
+
*/
|
|
234
|
+
public static readonly SPECULAR = 'specular';
|
|
235
|
+
|
|
141
236
|
/**
|
|
142
237
|
* The {@link ParameterDeclarations} for all parameters in this class.
|
|
143
238
|
*/
|
|
144
239
|
public static get declarations(): ParameterDeclarations {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
240
|
+
const declarations: ParameterDeclarations = {};
|
|
241
|
+
declarations[Parameter.VISIBLE] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
242
|
+
declarations[Parameter.SCALING] = { type: 'number', parser: Parameter.parseNumber };
|
|
243
|
+
declarations[Parameter.HIGHLIGHTED] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
244
|
+
declarations[Parameter.MATERIAL] = { type: 'string' };
|
|
245
|
+
declarations[Parameter.MATERIAL_COLOR] = { type: 'color', parser: Parameter.parseColor };
|
|
246
|
+
declarations[Parameter.MATERIAL_METALLNESS] = { type: 'number', parser: Parameter.parseNumber };
|
|
247
|
+
declarations[Parameter.MATERIAL_ROUGHNESS] = { type: 'number', parser: Parameter.parseNumber };
|
|
248
|
+
declarations[Parameter.HIGHLIGHT_ENABLED] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
249
|
+
declarations[Parameter.HIGHLIGHT_COLOR] = { type: 'color', parser: Parameter.parseColor };
|
|
250
|
+
declarations[Parameter.HIGHLIGHTED] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
251
|
+
declarations[Parameter.POSITION] = { type: 'vector', parser: Parameter.parseVector };
|
|
252
|
+
declarations[Parameter.ROTATION] = { type: 'vector', parser: Parameter.parseVector };
|
|
253
|
+
declarations[Parameter.CAST_SHADOW] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
254
|
+
declarations[Parameter.CAST_SHADOW_FROM_LIGHTS] = { type: 'csl', parser: Parameter.parseCommaSeparatedList };
|
|
255
|
+
declarations[Parameter.RECEIVE_SHADOWS] = { type: 'boolean', parser: Parameter.parseBoolean };
|
|
256
|
+
declarations[Parameter.INTENSITY] = { type: 'number', parser: Parameter.parseNumber };
|
|
257
|
+
declarations[Parameter.DIRECTION] = { type: 'vector', parser: Parameter.parseVector };
|
|
258
|
+
declarations[Parameter.ANGLE] = { type: 'number', parser: Parameter.parseNumber };
|
|
259
|
+
declarations[Parameter.EXPONENT] = { type: 'number', parser: Parameter.parseNumber };
|
|
260
|
+
declarations[Parameter.DIFFUSE] = { type: 'color', parser: Parameter.parseColor };
|
|
261
|
+
declarations[Parameter.SPECULAR] = { type: 'color', parser: Parameter.parseColor };
|
|
262
|
+
return declarations;
|
|
159
263
|
}
|
|
160
264
|
|
|
161
265
|
/**
|
|
@@ -179,6 +283,24 @@ export class Parameter {
|
|
|
179
283
|
return all;
|
|
180
284
|
}
|
|
181
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Parses given {@link ParameterBag} with given {@link ParameterDeclarations}.
|
|
288
|
+
*/
|
|
289
|
+
public static parseFromDeclarations( declarations: ParameterDeclarations, parameterBag: ParameterBag ): ParsedParameterBag {
|
|
290
|
+
const parameters: ParsedParameterBag = {};
|
|
291
|
+
for( const parameter in parameterBag ) {
|
|
292
|
+
const value = get( parameterBag, parameter );
|
|
293
|
+
parameters[parameter] = value;
|
|
294
|
+
const declaration: ParameterDeclaration = declarations[parameter];
|
|
295
|
+
if( declaration ) {
|
|
296
|
+
if( !isEmpty( value ) && declaration.parser ) {
|
|
297
|
+
parameters[parameter] = declaration.parser( value );
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return parameters;
|
|
302
|
+
}
|
|
303
|
+
|
|
182
304
|
/**
|
|
183
305
|
* Parses a string of format `'(x,y,z)'` to a `Vector3`.
|
|
184
306
|
*/
|
|
@@ -274,4 +396,13 @@ export class Parameter {
|
|
|
274
396
|
return parseFloat( value.toString() );
|
|
275
397
|
}
|
|
276
398
|
|
|
399
|
+
/**
|
|
400
|
+
* Parses a string with comma separated values to a list of strings.
|
|
401
|
+
*/
|
|
402
|
+
public static parseCommaSeparatedList( value: ParameterValue ): string[] {
|
|
403
|
+
return value.toString()
|
|
404
|
+
.split( ',' )
|
|
405
|
+
.map( s => s.trim() );
|
|
406
|
+
}
|
|
407
|
+
|
|
277
408
|
}
|