@combeenation/3d-viewer 4.0.0-beta1 → 4.0.0-beta2
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 +1 -0
- package/dist/lib-cjs/api/classes/element.d.ts +12 -16
- package/dist/lib-cjs/api/classes/element.js +129 -194
- package/dist/lib-cjs/api/classes/element.js.map +1 -1
- package/dist/lib-cjs/api/classes/event.d.ts +1 -15
- package/dist/lib-cjs/api/classes/event.js +1 -15
- package/dist/lib-cjs/api/classes/event.js.map +1 -1
- package/dist/lib-cjs/api/classes/parameter.d.ts +7 -101
- package/dist/lib-cjs/api/classes/parameter.js +21 -141
- package/dist/lib-cjs/api/classes/parameter.js.map +1 -1
- package/dist/lib-cjs/api/classes/parameterObservable.js +36 -11
- 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 +0 -11
- package/dist/lib-cjs/api/classes/placementAnimation.js.map +1 -1
- package/dist/lib-cjs/api/classes/variant.d.ts +14 -48
- package/dist/lib-cjs/api/classes/variant.js +56 -320
- package/dist/lib-cjs/api/classes/variant.js.map +1 -1
- package/dist/lib-cjs/api/classes/variantInstance.d.ts +1 -5
- package/dist/lib-cjs/api/classes/variantInstance.js +0 -10
- package/dist/lib-cjs/api/classes/variantInstance.js.map +1 -1
- package/dist/lib-cjs/api/classes/viewer.d.ts +3 -6
- package/dist/lib-cjs/api/classes/viewer.js +59 -133
- package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
- package/dist/lib-cjs/api/internal/sceneSetup.d.ts +1 -5
- package/dist/lib-cjs/api/internal/sceneSetup.js +71 -75
- package/dist/lib-cjs/api/internal/sceneSetup.js.map +1 -1
- package/dist/lib-cjs/api/util/babylonHelper.d.ts +4 -54
- package/dist/lib-cjs/api/util/babylonHelper.js +8 -160
- package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
- package/dist/lib-cjs/api/util/globalTypes.d.ts +12 -62
- package/dist/lib-cjs/api/util/resourceHelper.d.ts +8 -8
- package/dist/lib-cjs/api/util/resourceHelper.js +24 -63
- package/dist/lib-cjs/api/util/resourceHelper.js.map +1 -1
- package/dist/lib-cjs/index.d.ts +22 -24
- package/dist/lib-cjs/index.js +38 -42
- package/dist/lib-cjs/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/classes/element.ts +117 -146
- package/src/api/classes/{parameterizable.ts → elementParameterizable.ts} +1 -12
- package/src/api/classes/event.ts +1 -16
- package/src/api/classes/parameter.ts +22 -153
- package/src/api/classes/parameterObservable.ts +31 -9
- package/src/api/classes/placementAnimation.ts +0 -10
- package/src/api/classes/variant.ts +51 -187
- package/src/api/classes/variantInstance.ts +1 -8
- package/src/api/classes/viewer.ts +11 -68
- package/src/api/internal/sceneSetup.ts +109 -99
- package/src/api/util/babylonHelper.ts +10 -171
- package/src/api/util/globalTypes.ts +14 -71
- package/src/api/util/resourceHelper.ts +23 -31
- package/src/dev.ts +6 -2
- package/src/index.ts +23 -27
- package/src/pagesconfig.json +13 -8
- package/src/api/classes/variantParameterizable.ts +0 -73
- package/src/api/classes/viewerLight.ts +0 -330
- package/src/api/util/stringHelper.ts +0 -26
|
@@ -1,40 +1,35 @@
|
|
|
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';
|
|
4
2
|
import { Material } from '@babylonjs/core/Materials/material';
|
|
5
3
|
import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
|
|
6
|
-
import {
|
|
4
|
+
import { Axis, Space } from '@babylonjs/core/Maths/math.axis';
|
|
7
5
|
import { Color3 } from '@babylonjs/core/Maths/math.color';
|
|
8
6
|
import { AbstractMesh } from '@babylonjs/core/Meshes/abstractMesh';
|
|
9
7
|
import { InstancedMesh } from '@babylonjs/core/Meshes/instancedMesh';
|
|
10
8
|
import { Mesh } from '@babylonjs/core/Meshes/mesh';
|
|
11
9
|
import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
|
|
12
|
-
import {
|
|
10
|
+
import { Texture } from '@babylonjs/core/Materials/Textures/texture';
|
|
11
|
+
import { cloneDeep, concat, get, isArray, merge, union } from 'lodash-es';
|
|
13
12
|
import {
|
|
14
13
|
activateTransformNode as activate,
|
|
15
14
|
addToHighlightLayer,
|
|
16
|
-
addToShadowGenerator,
|
|
17
15
|
assertTransformNode,
|
|
18
16
|
cloneTransformNode,
|
|
19
17
|
cloneTransformNodeMaterial,
|
|
20
18
|
deactivateTransformNode as deactivate,
|
|
21
19
|
getClientRectFromMesh,
|
|
22
|
-
|
|
20
|
+
injectTransformNodeMetadata,
|
|
23
21
|
mapToDottedNodes,
|
|
24
|
-
moveTransformNode,
|
|
25
22
|
removeFromHighlightLayer,
|
|
26
|
-
removeFromShadowGenerator,
|
|
27
|
-
rotateTransformNode,
|
|
28
23
|
setMaterial,
|
|
29
24
|
setMaterialColor,
|
|
30
25
|
setMaterialMetallness,
|
|
31
26
|
setMaterialRoughness,
|
|
32
|
-
setMaterialTexture
|
|
33
|
-
setReceiveShadows
|
|
27
|
+
setMaterialTexture
|
|
34
28
|
} from '../util/babylonHelper';
|
|
35
|
-
import {
|
|
36
|
-
import { VariantParameterizable } from './../classes/variantParameterizable';
|
|
29
|
+
import { createImageUrlFromSvg, mergeMaps } from '../util/resourceHelper';
|
|
37
30
|
import { DottedPath } from './dottedPath';
|
|
31
|
+
import { ElementParameterizable } from './elementParameterizable';
|
|
32
|
+
import { Event } from './event';
|
|
38
33
|
import { Parameter } from './parameter';
|
|
39
34
|
import { Variant } from './variant';
|
|
40
35
|
|
|
@@ -45,20 +40,24 @@ import { Variant } from './variant';
|
|
|
45
40
|
* When used in typings, refer to via its alias {@link VariantElement} to prevent name clashes with the web APIs
|
|
46
41
|
* [Element](https://developer.mozilla.org/en-US/docs/Web/API/Element) class
|
|
47
42
|
*/
|
|
48
|
-
export class Element extends
|
|
49
|
-
|
|
50
|
-
public readonly nodes: TransformNode[] = [];
|
|
43
|
+
export class Element extends ElementParameterizable {
|
|
51
44
|
|
|
52
45
|
protected readonly _dottedNodes: Map<DottedPath, TransformNode> = new Map();
|
|
53
46
|
|
|
47
|
+
protected readonly _parameterObservers: Map<string, ParameterObserver[]> = new Map();
|
|
48
|
+
|
|
54
49
|
protected _highlightLayer?: HighlightLayer;
|
|
55
50
|
|
|
51
|
+
protected _paintableTextureId: number = 0;
|
|
52
|
+
|
|
53
|
+
public readonly nodes: TransformNode[] = [];
|
|
54
|
+
|
|
56
55
|
/**
|
|
57
56
|
* Constructor.
|
|
58
57
|
*/
|
|
59
|
-
|
|
58
|
+
public constructor( public readonly variant: Variant,
|
|
60
59
|
public readonly name: string ) {
|
|
61
|
-
super(
|
|
60
|
+
super();
|
|
62
61
|
if ( process.env.NODE_ENV?.toLowerCase().includes('dev')) {
|
|
63
62
|
this.assertPathDefinitions();
|
|
64
63
|
}
|
|
@@ -73,13 +72,6 @@ export class Element extends VariantParameterizable {
|
|
|
73
72
|
this.addParameterObservers();
|
|
74
73
|
}
|
|
75
74
|
|
|
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
|
-
|
|
83
75
|
/**
|
|
84
76
|
* The {@link DottedPath} in the built tree of {@link Element}s.
|
|
85
77
|
* E.g. "_.top-1.sub-2.sub-sub-3.el-1"
|
|
@@ -222,11 +214,41 @@ export class Element extends VariantParameterizable {
|
|
|
222
214
|
}
|
|
223
215
|
|
|
224
216
|
/**
|
|
225
|
-
* @
|
|
217
|
+
* Places the given {@link ParameterBag} in the {@link Element}'s parameters, replaces all patterns in the
|
|
218
|
+
* {@link StructureJson} and broadcasts all {@link ParameterObserver}s.
|
|
219
|
+
*
|
|
226
220
|
* @emit {@link Event.ELEMENT_PARAMETER_COMMITTED}
|
|
227
221
|
*/
|
|
228
|
-
public async commitParameters( parameters?: ParameterBag ): Promise<
|
|
229
|
-
|
|
222
|
+
public async commitParameters( parameters?: ParameterBag ): Promise<Element> {
|
|
223
|
+
if( !parameters ) {
|
|
224
|
+
parameters = {};
|
|
225
|
+
}
|
|
226
|
+
const oldParameters = cloneDeep( this.parameters );
|
|
227
|
+
merge( this.parameters, parameters );
|
|
228
|
+
// handle parameter observers
|
|
229
|
+
let observerPromises: Promise<void | ParameterObserver>[] = [];
|
|
230
|
+
for( const parameter in this.parameters ) {
|
|
231
|
+
const oldParameterValue = oldParameters[parameter];
|
|
232
|
+
const newParameterValue = this.parameters[parameter];
|
|
233
|
+
this.variant.assertParameter( this.variant.inheritedParameterDeclaration, parameter, newParameterValue );
|
|
234
|
+
if( oldParameterValue === newParameterValue ) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
// parameter changed
|
|
238
|
+
const parameterObservers = mergeMaps( this._parameterObservers, this.parameterObservers );
|
|
239
|
+
if( parameterObservers.has( parameter ) ) {
|
|
240
|
+
const observers = parameterObservers.get( parameter )!;
|
|
241
|
+
observerPromises = concat(observerPromises, observers.map( observer => {
|
|
242
|
+
const observerResult = observer( this, oldParameterValue, newParameterValue );
|
|
243
|
+
return Promise.resolve( observerResult ).then( () => {
|
|
244
|
+
this.broadcastEvent( Event.ELEMENT_PARAMETER_COMMITTED,
|
|
245
|
+
this, parameter, oldParameterValue, newParameterValue );
|
|
246
|
+
} );
|
|
247
|
+
} ) );
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
await Promise.all( observerPromises );
|
|
251
|
+
return this;
|
|
230
252
|
}
|
|
231
253
|
|
|
232
254
|
/**
|
|
@@ -258,48 +280,45 @@ export class Element extends VariantParameterizable {
|
|
|
258
280
|
}
|
|
259
281
|
|
|
260
282
|
/**
|
|
261
|
-
* Draws a
|
|
283
|
+
* Draws a image onto a `paintable` defined via {@link PaintableDefinition}.
|
|
262
284
|
*/
|
|
263
|
-
public drawPaintable( paintable: string, imageSource:
|
|
264
|
-
const paintableDefinition = this.getPaintableDefinition( paintable );
|
|
285
|
+
public async drawPaintable( paintable: string, imageSource: string ): Promise<Element> {
|
|
265
286
|
const node = this.getPaintableNode( paintable );
|
|
266
287
|
if( !(node instanceof AbstractMesh) ) {
|
|
267
288
|
throw new Error( `The path must be an instance of "AbstractMesh" for paintable "${paintable}" ` +
|
|
268
289
|
`in element "${this.id}".` );
|
|
269
290
|
}
|
|
270
|
-
if( node.material && !
|
|
291
|
+
if( node.material && !get( node.metadata, 'dirty.material' ) ) {
|
|
271
292
|
cloneTransformNodeMaterial( node );
|
|
272
293
|
}
|
|
273
294
|
if( !node.material ) {
|
|
274
295
|
node.material = new StandardMaterial( `${this.id}.${paintable}.material`, this.variant.viewer.scene );
|
|
275
296
|
}
|
|
276
297
|
node.material.transparencyMode = Material.MATERIAL_ALPHATESTANDBLEND;
|
|
277
|
-
if( !
|
|
298
|
+
if( !get( node.metadata, 'dirty.material.texture' ) ) {
|
|
278
299
|
// inject initial value and mark as dirty
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
const widthAndHeight = {
|
|
282
|
-
width: imageSource.width,
|
|
283
|
-
height: imageSource.height
|
|
284
|
-
};
|
|
285
|
-
if( isNumber( paintableDefinition.textureOptions ) ) {
|
|
286
|
-
widthAndHeight.width = paintableDefinition.textureOptions;
|
|
287
|
-
widthAndHeight.height = paintableDefinition.textureOptions;
|
|
288
|
-
} else if( isPlainObject( paintableDefinition.textureOptions ) ) {
|
|
289
|
-
widthAndHeight.width = paintableDefinition.textureOptions.width;
|
|
290
|
-
widthAndHeight.height = paintableDefinition.textureOptions.height;
|
|
300
|
+
injectTransformNodeMetadata( node, { dirty: { material: { texture: true } } }, false );
|
|
291
301
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
302
|
+
|
|
303
|
+
await new Promise<void>(resolve => {
|
|
304
|
+
const paintableTexture = Texture.CreateFromBase64String(
|
|
305
|
+
imageSource,
|
|
306
|
+
`${this.id}.${paintable}.texture.${this._paintableTextureId}`,
|
|
307
|
+
this.variant.viewer.scene,
|
|
308
|
+
undefined,
|
|
309
|
+
false,
|
|
310
|
+
undefined,
|
|
311
|
+
() => {
|
|
312
|
+
setMaterialTexture( node, paintableTexture, false );
|
|
313
|
+
resolve();
|
|
314
|
+
}
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
// NOTE: Paintable texture need an individual id, otherwise the already existing texture on this id does not get overwritten
|
|
318
|
+
// Maybe think of a disposal logic here in the future
|
|
319
|
+
this._paintableTextureId++;
|
|
320
|
+
});
|
|
321
|
+
|
|
303
322
|
return this;
|
|
304
323
|
}
|
|
305
324
|
|
|
@@ -307,16 +326,15 @@ export class Element extends VariantParameterizable {
|
|
|
307
326
|
* Draws a SVG string onto a `paintable` defined via {@link PaintableDefinition}.
|
|
308
327
|
*/
|
|
309
328
|
public async drawPaintableFromSvg( paintable: string, svgSource: string ): Promise<Element> {
|
|
310
|
-
const
|
|
311
|
-
return this.drawPaintable( paintable,
|
|
329
|
+
const imageUrl = await createImageUrlFromSvg( svgSource );
|
|
330
|
+
return this.drawPaintable( paintable, imageUrl );
|
|
312
331
|
}
|
|
313
332
|
|
|
314
333
|
/**
|
|
315
334
|
* Draws an Image from source (URL/URI) onto a `paintable` defined via {@link PaintableDefinition}.
|
|
316
335
|
*/
|
|
317
336
|
public async drawPaintableFromImgSrc( paintable: string, imgSource: string ): Promise<Element> {
|
|
318
|
-
|
|
319
|
-
return this.drawPaintable( paintable, source );
|
|
337
|
+
return this.drawPaintable( paintable, imgSource );
|
|
320
338
|
}
|
|
321
339
|
|
|
322
340
|
/**
|
|
@@ -333,12 +351,12 @@ export class Element extends VariantParameterizable {
|
|
|
333
351
|
}
|
|
334
352
|
if( visible === true ) {
|
|
335
353
|
element.nodes.forEach( node => {
|
|
336
|
-
|
|
354
|
+
injectTransformNodeMetadata( node, { visibility: node.isEnabled() } );
|
|
337
355
|
activate( node );
|
|
338
356
|
} );
|
|
339
357
|
} else if( visible === false ) {
|
|
340
358
|
element.nodes.forEach( node => {
|
|
341
|
-
|
|
359
|
+
injectTransformNodeMetadata( node, { visibility: node.isEnabled() } );
|
|
342
360
|
deactivate( node );
|
|
343
361
|
} );
|
|
344
362
|
}
|
|
@@ -354,7 +372,7 @@ export class Element extends VariantParameterizable {
|
|
|
354
372
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
355
373
|
const material = element.variant.getMaterial( newValue.toString() );
|
|
356
374
|
element.nodes.forEach( node => {
|
|
357
|
-
assertTransformNode(node, (node:
|
|
375
|
+
assertTransformNode(node, (node: TransformNode) => {
|
|
358
376
|
if( node instanceof InstancedMesh ) {
|
|
359
377
|
throw new Error( `Changing parameter "${Parameter.MATERIAL}" ` +
|
|
360
378
|
`of an InstancedMesh is not supported. ` +
|
|
@@ -369,19 +387,19 @@ export class Element extends VariantParameterizable {
|
|
|
369
387
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
370
388
|
const color = Parameter.parseColor( newValue );
|
|
371
389
|
element.nodes.forEach( node => {
|
|
372
|
-
assertTransformNode(node, (node:
|
|
390
|
+
assertTransformNode(node, (node: TransformNode) => {
|
|
373
391
|
if( node instanceof InstancedMesh ) {
|
|
374
392
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_COLOR}" ` +
|
|
375
393
|
`of an InstancedMesh is not supported. ` +
|
|
376
394
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
377
395
|
}
|
|
378
396
|
});
|
|
379
|
-
if( !
|
|
397
|
+
if( !get( node.metadata, 'dirty.material' ) ) {
|
|
380
398
|
cloneTransformNodeMaterial( node );
|
|
381
399
|
}
|
|
382
|
-
if( !
|
|
400
|
+
if( !get( node.metadata, 'dirty.material.color' ) ) {
|
|
383
401
|
// inject initial value and mark as dirty
|
|
384
|
-
|
|
402
|
+
injectTransformNodeMetadata( node, { dirty: { material: { color: oldValue } } } );
|
|
385
403
|
}
|
|
386
404
|
setMaterialColor( node, color );
|
|
387
405
|
} );
|
|
@@ -391,19 +409,19 @@ export class Element extends VariantParameterizable {
|
|
|
391
409
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
392
410
|
const metallness = Parameter.parseNumber( newValue );
|
|
393
411
|
element.nodes.forEach( node => {
|
|
394
|
-
assertTransformNode(node, (node:
|
|
412
|
+
assertTransformNode(node, (node: TransformNode) => {
|
|
395
413
|
if( node instanceof InstancedMesh ) {
|
|
396
414
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_METALLNESS}" ` +
|
|
397
415
|
`of an InstancedMesh is not supported. ` +
|
|
398
416
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
399
417
|
}
|
|
400
418
|
});
|
|
401
|
-
if( !
|
|
419
|
+
if( !get( node.metadata, 'dirty.material' ) ) {
|
|
402
420
|
cloneTransformNodeMaterial( node );
|
|
403
421
|
}
|
|
404
|
-
if( !
|
|
422
|
+
if( !get( node.metadata, 'dirty.material.metallness' ) ) {
|
|
405
423
|
// inject initial value and mark as dirty
|
|
406
|
-
|
|
424
|
+
injectTransformNodeMetadata( node, { dirty: { material: { metallness: oldValue } } } );
|
|
407
425
|
}
|
|
408
426
|
setMaterialMetallness( node, metallness );
|
|
409
427
|
} );
|
|
@@ -413,19 +431,19 @@ export class Element extends VariantParameterizable {
|
|
|
413
431
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
414
432
|
const roughness = Parameter.parseNumber( newValue );
|
|
415
433
|
element.nodes.forEach( node => {
|
|
416
|
-
assertTransformNode(node, (node:
|
|
434
|
+
assertTransformNode(node, (node: TransformNode) => {
|
|
417
435
|
if( node instanceof InstancedMesh ) {
|
|
418
436
|
throw new Error( `Changing parameter "${Parameter.MATERIAL_ROUGHNESS}" ` +
|
|
419
437
|
`of an InstancedMesh is not supported. ` +
|
|
420
438
|
`Tried to change node "${node.id}" on element "${element.id}".` );
|
|
421
439
|
}
|
|
422
440
|
});
|
|
423
|
-
if( !
|
|
441
|
+
if( !get( node.metadata, 'dirty.material' ) ) {
|
|
424
442
|
cloneTransformNodeMaterial( node );
|
|
425
443
|
}
|
|
426
|
-
if( !
|
|
444
|
+
if( !get( node.metadata, 'dirty.material.roughness' ) ) {
|
|
427
445
|
// inject initial value and mark as dirty
|
|
428
|
-
|
|
446
|
+
injectTransformNodeMetadata( node, { dirty: { material: { roughness: oldValue } } } );
|
|
429
447
|
}
|
|
430
448
|
setMaterialRoughness( node, roughness );
|
|
431
449
|
} );
|
|
@@ -481,7 +499,7 @@ export class Element extends VariantParameterizable {
|
|
|
481
499
|
// Add/Remove meshes to previously created highlight layers.
|
|
482
500
|
if( highlighted === true ) {
|
|
483
501
|
element.nodes.forEach( node => {
|
|
484
|
-
assertTransformNode(node, (node:
|
|
502
|
+
assertTransformNode(node, (node: TransformNode) => {
|
|
485
503
|
if( node instanceof InstancedMesh ) {
|
|
486
504
|
throw new Error( `Changing parameter "${Parameter.HIGHLIGHTED}" ` +
|
|
487
505
|
`of an InstancedMesh is not supported. ` +
|
|
@@ -508,61 +526,35 @@ export class Element extends VariantParameterizable {
|
|
|
508
526
|
this._parameterObservers.set( Parameter.POSITION, [
|
|
509
527
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
510
528
|
// we have to deal just with root nodes here due to relative impacts in a node tree
|
|
511
|
-
element.nodes.forEach( node =>
|
|
529
|
+
element.nodes.forEach( node => {
|
|
530
|
+
// remember absolute position and reset it before translating
|
|
531
|
+
if( !get( node.metadata, 'position' ) ) {
|
|
532
|
+
node.metadata.position = node.absolutePosition.clone();
|
|
533
|
+
}
|
|
534
|
+
node.setAbsolutePosition( node.metadata.position );
|
|
535
|
+
// move
|
|
536
|
+
const distance = Parameter.parseVector( newValue );
|
|
537
|
+
node.translate( Axis.X, distance.x, Space.WORLD );
|
|
538
|
+
node.translate( Axis.Y, distance.y, Space.WORLD );
|
|
539
|
+
node.translate( Axis.Z, distance.z, Space.WORLD );
|
|
540
|
+
} );
|
|
512
541
|
}
|
|
513
542
|
] );
|
|
514
543
|
this._parameterObservers.set( Parameter.ROTATION, [
|
|
515
544
|
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
516
|
-
// The current implementation (rotating around coordinates 0,0,0) implicitly mutates the position of a node.
|
|
517
|
-
// Since a user expects the rotation after the positioning, we have to manually fire the position observers.
|
|
518
|
-
// Without calling these observers, the pivot and the position of a node is initially the same before rotating,
|
|
519
|
-
// so there is no rotation happening at all.
|
|
520
|
-
if( Parameter.POSITION in element.inheritedParameters ) {
|
|
521
|
-
await element.commitParameter( Parameter.POSITION, element.inheritedParameters[Parameter.POSITION] );
|
|
522
|
-
}
|
|
523
545
|
// we have to deal just with root nodes here due to relative impacts in a node tree
|
|
524
|
-
element.nodes.forEach( node =>
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
529
|
-
let castShadow;
|
|
530
|
-
try {
|
|
531
|
-
castShadow = Parameter.parseBoolean( newValue );
|
|
532
|
-
} catch( e ) {
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
let lightCsl = element.inheritedParameters[Parameter.CAST_SHADOW_FROM_LIGHTS];
|
|
536
|
-
if( ! lightCsl ) {
|
|
537
|
-
lightCsl = element.variant.inheritedViewerLights.map( l => l.name ).join( ',' );
|
|
538
|
-
}
|
|
539
|
-
if( castShadow === true ) {
|
|
540
|
-
await this.castShadowValueHandler( lightCsl, addToShadowGenerator );
|
|
541
|
-
}
|
|
542
|
-
if( castShadow === false ) {
|
|
543
|
-
await this.castShadowValueHandler( lightCsl, removeFromShadowGenerator );
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
] );
|
|
547
|
-
this._parameterObservers.set( Parameter.CAST_SHADOW_FROM_LIGHTS, [
|
|
548
|
-
async ( element: Element, oldValue: ParameterValue, newValue: ParameterValue ) => {
|
|
549
|
-
// TODO: Possible performance issue in combination with CAST_SHADOW, since both observers are initially called
|
|
550
|
-
// when CAST_SHADOW and CAST_SHADOW_FROM_LIGHTS are defined in the spec.
|
|
551
|
-
const lightCsl = element.variant.inheritedViewerLights.map( l => l.name ).join( ',' );
|
|
552
|
-
// cleanup all shadow generators
|
|
553
|
-
await this.castShadowValueHandler( lightCsl, removeFromShadowGenerator );
|
|
554
|
-
if( element.castShadow === true ) {
|
|
555
|
-
// if newValue is undefined or '' then set newValue to lightCsl (use all lights)
|
|
556
|
-
if( !newValue ) {
|
|
557
|
-
newValue = lightCsl;
|
|
546
|
+
element.nodes.forEach( node => {
|
|
547
|
+
// remember absolute rotation and reset it before translating
|
|
548
|
+
if(!get( node.metadata, 'rotation' ) ) {
|
|
549
|
+
node.metadata.rotation = node.rotation.clone();
|
|
558
550
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
551
|
+
node.rotation = node.metadata.rotation;
|
|
552
|
+
// rotate
|
|
553
|
+
const rotation = Parameter.parseRotation( newValue );
|
|
554
|
+
node.rotate( Axis.X, rotation.x, Space.WORLD );
|
|
555
|
+
node.rotate( Axis.Y, rotation.y, Space.WORLD );
|
|
556
|
+
node.rotate( Axis.Z, rotation.z, Space.WORLD );
|
|
557
|
+
} );
|
|
566
558
|
}
|
|
567
559
|
] );
|
|
568
560
|
return this;
|
|
@@ -611,25 +603,4 @@ export class Element extends VariantParameterizable {
|
|
|
611
603
|
} );
|
|
612
604
|
}
|
|
613
605
|
|
|
614
|
-
/**
|
|
615
|
-
* Handles callback for given light parameter.
|
|
616
|
-
*/
|
|
617
|
-
private async castShadowValueHandler( lightCsl: ParameterValue, mutator: CallableFunction ) {
|
|
618
|
-
let lights: Light[] = [];
|
|
619
|
-
for( const lightName of Parameter.parseCommaSeparatedList( lightCsl ) ) {
|
|
620
|
-
const viewerLight = await this.variant.getViewerLight( lightName );
|
|
621
|
-
if( viewerLight ) {
|
|
622
|
-
lights.push( viewerLight.light );
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
const shadowGenerators = lights
|
|
626
|
-
.map( light => light?.getShadowGenerator() as ShadowGenerator )
|
|
627
|
-
.filter( Boolean );
|
|
628
|
-
shadowGenerators.forEach( generator => {
|
|
629
|
-
this.nodes.forEach( node => {
|
|
630
|
-
mutator( generator, node );
|
|
631
|
-
} );
|
|
632
|
-
} );
|
|
633
|
-
}
|
|
634
|
-
|
|
635
606
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Parameter } from './parameter';
|
|
2
2
|
import { ParameterObservable } from './parameterObservable';
|
|
3
3
|
|
|
4
|
-
export abstract class
|
|
4
|
+
export abstract class ElementParameterizable extends ParameterObservable {
|
|
5
5
|
|
|
6
6
|
protected parameterDeclaration: ParameterDeclarations = Parameter.declarations;
|
|
7
7
|
|
|
@@ -55,17 +55,6 @@ export abstract class Parameterizable extends ParameterObservable {
|
|
|
55
55
|
return this.parameters[Parameter.ROTATION].toString();
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
get castShadow(): boolean | undefined {
|
|
59
|
-
if( !(Parameter.CAST_SHADOW in this.parameters) ) {
|
|
60
|
-
return undefined;
|
|
61
|
-
}
|
|
62
|
-
try {
|
|
63
|
-
return Parameter.parseBoolean( this.parameters[Parameter.CAST_SHADOW] );
|
|
64
|
-
} catch( e ) {
|
|
65
|
-
return undefined;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
58
|
public async show(): Promise<ParameterObservable> {
|
|
70
59
|
await this.commitParameter( Parameter.VISIBLE, true );
|
|
71
60
|
return this;
|
package/src/api/classes/event.ts
CHANGED
|
@@ -262,28 +262,13 @@ export class Event {
|
|
|
262
262
|
* * {@link Element}
|
|
263
263
|
*
|
|
264
264
|
* Payload:
|
|
265
|
-
* *
|
|
265
|
+
* * variant: {@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
|
-
|
|
287
272
|
/**
|
|
288
273
|
* Fired after a parameter on an {@link SceneManager} has been committed.
|
|
289
274
|
*
|