@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.
Files changed (57) hide show
  1. package/README.md +1 -0
  2. package/dist/lib-cjs/api/classes/element.d.ts +12 -16
  3. package/dist/lib-cjs/api/classes/element.js +129 -194
  4. package/dist/lib-cjs/api/classes/element.js.map +1 -1
  5. package/dist/lib-cjs/api/classes/event.d.ts +1 -15
  6. package/dist/lib-cjs/api/classes/event.js +1 -15
  7. package/dist/lib-cjs/api/classes/event.js.map +1 -1
  8. package/dist/lib-cjs/api/classes/parameter.d.ts +7 -101
  9. package/dist/lib-cjs/api/classes/parameter.js +21 -141
  10. package/dist/lib-cjs/api/classes/parameter.js.map +1 -1
  11. package/dist/lib-cjs/api/classes/parameterObservable.js +36 -11
  12. package/dist/lib-cjs/api/classes/parameterObservable.js.map +1 -1
  13. package/dist/lib-cjs/api/classes/placementAnimation.d.ts +2 -2
  14. package/dist/lib-cjs/api/classes/placementAnimation.js +0 -11
  15. package/dist/lib-cjs/api/classes/placementAnimation.js.map +1 -1
  16. package/dist/lib-cjs/api/classes/variant.d.ts +14 -48
  17. package/dist/lib-cjs/api/classes/variant.js +56 -320
  18. package/dist/lib-cjs/api/classes/variant.js.map +1 -1
  19. package/dist/lib-cjs/api/classes/variantInstance.d.ts +1 -5
  20. package/dist/lib-cjs/api/classes/variantInstance.js +0 -10
  21. package/dist/lib-cjs/api/classes/variantInstance.js.map +1 -1
  22. package/dist/lib-cjs/api/classes/viewer.d.ts +3 -6
  23. package/dist/lib-cjs/api/classes/viewer.js +59 -133
  24. package/dist/lib-cjs/api/classes/viewer.js.map +1 -1
  25. package/dist/lib-cjs/api/internal/sceneSetup.d.ts +1 -5
  26. package/dist/lib-cjs/api/internal/sceneSetup.js +71 -75
  27. package/dist/lib-cjs/api/internal/sceneSetup.js.map +1 -1
  28. package/dist/lib-cjs/api/util/babylonHelper.d.ts +4 -54
  29. package/dist/lib-cjs/api/util/babylonHelper.js +8 -160
  30. package/dist/lib-cjs/api/util/babylonHelper.js.map +1 -1
  31. package/dist/lib-cjs/api/util/globalTypes.d.ts +12 -62
  32. package/dist/lib-cjs/api/util/resourceHelper.d.ts +8 -8
  33. package/dist/lib-cjs/api/util/resourceHelper.js +24 -63
  34. package/dist/lib-cjs/api/util/resourceHelper.js.map +1 -1
  35. package/dist/lib-cjs/index.d.ts +22 -24
  36. package/dist/lib-cjs/index.js +38 -42
  37. package/dist/lib-cjs/index.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/api/classes/element.ts +117 -146
  40. package/src/api/classes/{parameterizable.ts → elementParameterizable.ts} +1 -12
  41. package/src/api/classes/event.ts +1 -16
  42. package/src/api/classes/parameter.ts +22 -153
  43. package/src/api/classes/parameterObservable.ts +31 -9
  44. package/src/api/classes/placementAnimation.ts +0 -10
  45. package/src/api/classes/variant.ts +51 -187
  46. package/src/api/classes/variantInstance.ts +1 -8
  47. package/src/api/classes/viewer.ts +11 -68
  48. package/src/api/internal/sceneSetup.ts +109 -99
  49. package/src/api/util/babylonHelper.ts +10 -171
  50. package/src/api/util/globalTypes.ts +14 -71
  51. package/src/api/util/resourceHelper.ts +23 -31
  52. package/src/dev.ts +6 -2
  53. package/src/index.ts +23 -27
  54. package/src/pagesconfig.json +13 -8
  55. package/src/api/classes/variantParameterizable.ts +0 -73
  56. package/src/api/classes/viewerLight.ts +0 -330
  57. package/src/api/util/stringHelper.ts +0 -26
@@ -1,5 +1,4 @@
1
1
  import { AssetContainer } from '@babylonjs/core/assetContainer';
2
- import { Light } from '@babylonjs/core/Lights/light';
3
2
  import '@babylonjs/core/Loading/Plugins/babylonFileLoader';
4
3
  import { SceneLoader } from '@babylonjs/core/Loading/sceneLoader';
5
4
  import { Material } from '@babylonjs/core/Materials/material';
@@ -8,30 +7,40 @@ import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
8
7
  import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_draco_mesh_compression';
9
8
  import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_texture_transform';
10
9
  import '@babylonjs/loaders/glTF/2.0/glTFLoader';
11
- import { cloneDeep, concat, get, isEmpty, isEqual, isString, merge, set } from 'lodash-es';
12
- import { deactivateTransformNode, getDottedPathForNode, injectNodeMetadata } from '../util/babylonHelper';
10
+ import { cloneDeep, concat, isEmpty, isEqual, isString, merge } from 'lodash-es';
11
+ import {
12
+ deactivateTransformNode,
13
+ getDottedPathForTransformNode,
14
+ injectTransformNodeMetadata
15
+ } from '../util/babylonHelper';
13
16
  import { loadJson, mergeMaps } from '../util/resourceHelper';
14
17
  import { DottedPath } from './dottedPath';
15
18
  import { Element } from './element';
19
+ import { ElementParameterizable } from './elementParameterizable';
16
20
  import { Event } from './event';
17
21
  import { Parameter } from './parameter';
18
- import { Parameterizable } from './parameterizable';
19
- import { ParameterObservable } from './parameterObservable';
20
- import { VariantParameterizable } from './variantParameterizable';
21
22
  import { Viewer } from './viewer';
22
- import { ViewerLight } from './viewerLight';
23
+
24
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_texture_basisu';
25
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_clearcoat';
26
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_sheen';
27
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_ior';
28
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness';
29
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_specular';
30
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_translucency';
31
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_transmission';
32
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_unlit';
33
+ import '@babylonjs/loaders/glTF/2.0/Extensions/KHR_materials_variants';
23
34
 
24
35
  /**
25
36
  * A concrete "Variant". Most of these are handled by either the {@link Viewer} or {@link VariantInstance}.
26
37
  */
27
- export class Variant extends Parameterizable {
38
+ export class Variant extends ElementParameterizable {
28
39
 
29
40
  public assetContainer: AssetContainer;
30
41
 
31
42
  public readonly elements: Element[] = [];
32
43
 
33
- public readonly viewerLights: ViewerLight[] = [];
34
-
35
44
  public structureJson: StructureJson;
36
45
 
37
46
  protected _dottedNodes: Map<DottedPath, TransformNode> | undefined;
@@ -166,13 +175,6 @@ export class Variant extends Parameterizable {
166
175
  return rootNodes;
167
176
  }
168
177
 
169
- /**
170
- * The {@link ViewerLight}s of the {@link Variant}.
171
- */
172
- get lights(): Light[] {
173
- return this.assetContainer.lights;
174
- }
175
-
176
178
  /**
177
179
  * All TransformNodes of the {@link Variant} mapped flat with a {@link DottedPath}.
178
180
  */
@@ -206,17 +208,6 @@ export class Variant extends Parameterizable {
206
208
  return concat( elements, this.elements );
207
209
  }
208
210
 
209
- /**
210
- * All {@link ViewerLight}s inherited from this {@link Variant}'s parents.
211
- */
212
- get inheritedViewerLights(): ViewerLight[] {
213
- let viewerLights: ViewerLight[] = [];
214
- this.ancestors.forEach( ancestor => {
215
- viewerLights = concat( viewerLights, ancestor.viewerLights );
216
- } );
217
- return concat( viewerLights, this.viewerLights );
218
- }
219
-
220
211
  /**
221
212
  * All TransformNodes inherited from this {@link Variant}'s parents.
222
213
  */
@@ -239,17 +230,6 @@ export class Variant extends Parameterizable {
239
230
  return dottedNodes;
240
231
  }
241
232
 
242
- /**
243
- * All Lights inherited from this {@link Variant}'s parents.
244
- */
245
- get inheritedLights(): Light[] {
246
- let lights: Light[] = [];
247
- this.ancestors.forEach( ancestor => {
248
- lights = concat( lights, ancestor.lights );
249
- } );
250
- return concat( lights, this.lights );
251
- }
252
-
253
233
  /**
254
234
  * The {@link ParameterDeclarations} inherited from this {@link Variant}'s parents.
255
235
  */
@@ -357,33 +337,6 @@ export class Variant extends Parameterizable {
357
337
  return element;
358
338
  }
359
339
 
360
- /**
361
- * Gets the desired {@link ViewerLight} of the current {@link Variant} relative to its {@link DottedPath}.
362
- * Uses the mechanism of {@link getDescendant} to resolve the appropriate variant in tree.
363
- */
364
- public async getViewerLight( dottedPath: DottedPathArgument ): Promise<ViewerLight> {
365
- const _dottedPath = DottedPath.create( dottedPath );
366
- const viewerLightName = _dottedPath.popPart();
367
- let variant: Variant = this;
368
- if( _dottedPath.parts.length > 0 ) {
369
- variant = await this.getDescendant( _dottedPath );
370
- }
371
- if( variant.inheritedViewerLights.length === 0 ) {
372
- throw new Error( `No viewerLights for variant "${variant.id}" found. ` +
373
- `Either none are defined or they are not initialized (are you operating on the appropriate living?).` );
374
- }
375
- let viewerLight;
376
- variant.inheritedViewerLights.forEach( _viewerLight => {
377
- if( _viewerLight.name === viewerLightName ) {
378
- viewerLight = _viewerLight;
379
- }
380
- } );
381
- if( !viewerLight ) {
382
- throw new Error( `ViewerLight with name "${viewerLightName}" does not exist for variant "${variant.id}".` );
383
- }
384
- return viewerLight;
385
- }
386
-
387
340
  /**
388
341
  * A proxy for directly getting a Node from an {@link Element} by its {@link DottedPath}s.
389
342
  */
@@ -430,8 +383,7 @@ export class Variant extends Parameterizable {
430
383
  parent?._children.set( variant.name, variant );
431
384
  variant.assetContainer = this.assetContainer;
432
385
  variant.parameterObservers = cloneDeep( this.parameterObservers );
433
- await variant.createElements();
434
- await variant.createViewerLights();
386
+ variant.createElements();
435
387
  variant.addParameterObservers();
436
388
  await variant.bootstrapParameters( parameters );
437
389
  this.broadcastEvent( Event.VARIANT_CREATED, variant );
@@ -537,10 +489,31 @@ export class Variant extends Parameterizable {
537
489
  this.broadcastEvent(Event.VARIANT_PARAMETER_BAG_COMMITTED, this, oldParameters, newParameters);
538
490
 
539
491
  // commit parameters to elements
540
- await this.commitParametersToElements( newParameters );
541
-
542
- // commit parameters to lights
543
- await this.commitParametersToViewerLights( newParameters );
492
+ const elementPromises: Promise<Element>[] = this.elements.map( element => {
493
+ let _elementDefinition = JSON.stringify( this._structureJson.elements![element.name] );
494
+ const elementParameters: ParameterBag = {};
495
+ for( const parameter in newParameters ) {
496
+ if( DottedPath.create( parameter ).firstPart !== element.name ) {
497
+ continue;
498
+ }
499
+ // we got an element parameter
500
+ let newParameterValue = newParameters[parameter];
501
+ const elementParameter = parameter.replace( `${element.name}.`, '' );
502
+ // If the variant is explicitly hidden, we must not override the visibility with element parameters. We need
503
+ // an exception for visibility to avoid overloading already applied element parameters with element parameters
504
+ // defined in the variant spec ("dotted parameters").
505
+ // @see https://github.com/Combeenation/3d-viewer/issues/44
506
+ if( elementParameter === Parameter.VISIBLE && newParameters[Parameter.VISIBLE] === false ) {
507
+ newParameterValue = false;
508
+ }
509
+ elementParameters[elementParameter] = newParameterValue;
510
+ const search = new RegExp( `\\$\\{${elementParameter}\\}`, 'g' );
511
+ _elementDefinition = _elementDefinition.replace( search, newParameterValue.toString() );
512
+ }
513
+ this.structureJson.elements![this.name] = JSON.parse( _elementDefinition );
514
+ return element.commitParameters( elementParameters );
515
+ } );
516
+ await Promise.all( elementPromises );
544
517
 
545
518
  // propagate parameters to parent
546
519
  if( this.parent ) {
@@ -589,17 +562,7 @@ export class Variant extends Parameterizable {
589
562
  const nodes = this.assetContainer.getNodes().filter( n => n instanceof TransformNode ) as TransformNode[];
590
563
  nodes.forEach( node => {
591
564
  deactivateTransformNode( node, false );
592
- injectNodeMetadata( node, { dottedPath: getDottedPathForNode( node ) }, false );
593
- } );
594
- this.assetContainer.lights.forEach( light => {
595
- light.setEnabled( false );
596
- injectNodeMetadata( light, { dottedPath: getDottedPathForNode( light ) }, false );
597
- this.viewer.scene.addLight( light );
598
- } );
599
- this.assetContainer.cameras.forEach( camera => {
600
- camera.setEnabled( false );
601
- injectNodeMetadata( camera, { dottedPath: getDottedPathForNode( camera ) }, false );
602
- this.viewer.scene.addCamera( camera );
565
+ injectTransformNodeMetadata( node, { dottedPath: getDottedPathForTransformNode( node ) }, false );
603
566
  } );
604
567
  this.broadcastEvent( Event.ASSET_LOADING_END, this );
605
568
  resolve( this );
@@ -610,82 +573,15 @@ export class Variant extends Parameterizable {
610
573
  } );
611
574
  }
612
575
 
613
- /**
614
- * Commits given parameters to all {@link Element}s.
615
- */
616
- protected async commitParametersToElements( parameters: ParameterBag ) {
617
- await Promise.all( this.elements.map(
618
- element => this.commitParametersToVariantParameterizable(parameters, element, 'elements')
619
- ) );
620
- }
621
-
622
- /**
623
- * Commits given parameters to all {@link ViewerLight}s.
624
- */
625
- protected async commitParametersToViewerLights( parameters: ParameterBag ) {
626
- await Promise.all( this.viewerLights.map(
627
- viewerLight => this.commitParametersToVariantParameterizable(parameters, viewerLight, 'lights')
628
- ) );
629
- }
630
-
631
- /**
632
- * Commits given parameters to a {@link VariantParameterizable} and updates the according definition with given
633
- * key in the {@link StructureJson}. The `definitionKey` "elements" for example will update the definition in
634
- * `this.structureJson.elements`.
635
- */
636
- protected async commitParametersToVariantParameterizable( parameters: ParameterBag,
637
- parameterizable: VariantParameterizable,
638
- definitionKey: string ): Promise<ParameterObservable> {
639
- const initialDefinition = get( this._structureJson, definitionKey )[parameterizable.name];
640
- let initialDefinitionStr = JSON.stringify( initialDefinition );
641
- const _parameters: ParameterBag = {};
642
- for( const parameter in parameters ) {
643
- const dpp = DottedPath.create( parameter );
644
- if( dpp.shiftPart() !== parameterizable.name ) {
645
- continue;
646
- }
647
- // we got a parameterizable ("element") parameter
648
- let parameterValue = parameters[parameter];
649
- const parameterizableParameter = dpp.path;
650
- // If the variant is explicitly hidden, we must not override the visibility with element parameters. We need
651
- // an exception for visibility to avoid overloading already applied element parameters with element parameters
652
- // defined in the variant spec ("dotted parameters").
653
- // @see https://github.com/Combeenation/3d-viewer/issues/44
654
- if( parameterizableParameter === Parameter.VISIBLE && parameters[Parameter.VISIBLE] === false ) {
655
- parameterValue = false;
656
- }
657
- _parameters[parameterizableParameter] = parameterValue;
658
- const search = new RegExp( `\\$\\{${parameterizableParameter}\\}`, 'g' );
659
- initialDefinitionStr = initialDefinitionStr.replace( search, parameterValue.toString() );
660
- }
661
- const definition = get( this.structureJson, definitionKey );
662
- definition[this.name] = JSON.parse( initialDefinitionStr );
663
- set( this.structureJson, definitionKey, definition );
664
- return await parameterizable.commitParameters( _parameters );
665
- }
666
-
667
576
  /**
668
577
  * Commits given {@link Parameter} to the {@link Variant}'s {@link Element}s.
669
578
  */
670
- protected async commitParameterToElements( parameter: string, value: ParameterValue ): Promise<Variant> {
579
+ protected async commitParameterToElements( parameter: string, value: ParameterValue ) {
671
580
  const promises = [];
672
581
  for( const element of this.elements ) {
673
582
  promises.push( element.commitParameter( parameter, value ) );
674
583
  }
675
584
  await Promise.all( promises );
676
- return this;
677
- }
678
-
679
- /**
680
- * Commits given {@link Parameter} to the {@link Variant}'s {@link Element}s.
681
- */
682
- protected async commitParameterToViewerLights( parameter: string, value: ParameterValue ): Promise<Variant> {
683
- const promises = [];
684
- for( const viewerLight of this.viewerLights ) {
685
- promises.push( viewerLight.commitParameter( parameter, value ) );
686
- }
687
- await Promise.all( promises );
688
- return this;
689
585
  }
690
586
 
691
587
  /**
@@ -695,13 +591,11 @@ export class Variant extends Parameterizable {
695
591
  this._parameterObservers.set( Parameter.VISIBLE, [
696
592
  async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
697
593
  await variant.commitParameterToElements( Parameter.VISIBLE, newValue );
698
- await variant.commitParameterToViewerLights( Parameter.VISIBLE, newValue );
699
594
  }
700
595
  ] );
701
596
  this._parameterObservers.set( Parameter.SCALING, [
702
597
  async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
703
598
  await variant.commitParameterToElements( Parameter.SCALING, newValue );
704
- await variant.commitParameterToViewerLights( Parameter.SCALING, newValue );
705
599
  }
706
600
  ] );
707
601
  this._parameterObservers.set( Parameter.MATERIAL, [
@@ -737,28 +631,11 @@ export class Variant extends Parameterizable {
737
631
  this._parameterObservers.set( Parameter.POSITION, [
738
632
  async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
739
633
  await variant.commitParameterToElements( Parameter.POSITION, newValue );
740
- await variant.commitParameterToViewerLights( Parameter.POSITION, newValue );
741
634
  }
742
635
  ] );
743
636
  this._parameterObservers.set( Parameter.ROTATION, [
744
637
  async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
745
638
  await variant.commitParameterToElements( Parameter.ROTATION, newValue );
746
- await variant.commitParameterToViewerLights( Parameter.ROTATION, newValue );
747
- }
748
- ] );
749
- this._parameterObservers.set( Parameter.CAST_SHADOW, [
750
- async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
751
- await variant.commitParameterToElements( Parameter.CAST_SHADOW, newValue );
752
- }
753
- ] );
754
- this._parameterObservers.set( Parameter.CAST_SHADOW_FROM_LIGHTS, [
755
- async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
756
- await variant.commitParameterToElements( Parameter.CAST_SHADOW_FROM_LIGHTS, newValue );
757
- }
758
- ] );
759
- this._parameterObservers.set( Parameter.RECEIVE_SHADOWS, [
760
- async ( variant: Variant, oldValue: ParameterValue, newValue: ParameterValue ) => {
761
- await variant.commitParameterToElements( Parameter.RECEIVE_SHADOWS, newValue );
762
639
  }
763
640
  ] );
764
641
  return this;
@@ -767,33 +644,20 @@ export class Variant extends Parameterizable {
767
644
  /**
768
645
  * Creates {@link Element}s and clones nodes into them.
769
646
  */
770
- protected async createElements(): Promise<Variant> {
771
- for( const name in this.structureJson.elements || {} ) {
772
- this.elements.push( await Element.create( this, name ) );
647
+ protected createElements(): Variant {
648
+ for( const elementName in this.structureJson.elements || {} ) {
649
+ this.elements.push( new Element( this, elementName ) );
773
650
  }
774
651
  // inject node meta to all inherited elements
775
652
  // we do this to inject the deepest and most concrete variant information to all cloned nodes in the tree
776
653
  this.inheritedElements.forEach( element => {
777
654
  element.nodes.forEach( node => {
778
- injectNodeMetadata( node, { variant: this, variantParameterizable: element } );
655
+ injectTransformNodeMetadata( node, { variant: this, element: element } );
779
656
  } );
780
657
  } );
781
658
  return this;
782
659
  }
783
660
 
784
- /**
785
- * Creates {@link ViewerLight}s.
786
- */
787
- protected async createViewerLights(): Promise<Variant> {
788
- for( const name in this.structureJson.lights || {} ) {
789
- this.viewerLights.push( await ViewerLight.create( this, name ) );
790
- }
791
- this.inheritedViewerLights.forEach( viewerLight => {
792
- injectNodeMetadata( viewerLight.light, { variant: this, variantParameterizable: viewerLight } );
793
- } );
794
- return this;
795
- }
796
-
797
661
  /**
798
662
  * Bootstrapping for parameters. It sets the `parametersInitialized` to true for all ancestors.
799
663
  */
@@ -1,6 +1,6 @@
1
1
  import { Mesh } from '@babylonjs/core/Meshes/mesh';
2
+ import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
2
3
  import { Element } from './element';
3
- import { ViewerLight } from './viewerLight';
4
4
  import { EventBroadcaster } from './eventBroadcaster';
5
5
  import { ParameterObservable } from './parameterObservable';
6
6
  import { Variant } from './variant';
@@ -51,13 +51,6 @@ export class VariantInstance extends EventBroadcaster {
51
51
  return this.variant.getElement( dottedPath );
52
52
  }
53
53
 
54
- /**
55
- * A proxy for {@link Variant.getViewerLight}.
56
- */
57
- public async getViewerLight( dottedPath: DottedPathArgument ): Promise<ViewerLight> {
58
- return this.variant.getViewerLight( dottedPath );
59
- }
60
-
61
54
  /**
62
55
  * A proxy for {@link Variant.getNode}.
63
56
  */
@@ -3,11 +3,9 @@ import { PickingInfo } from '@babylonjs/core/Collisions/pickingInfo';
3
3
  import { BoundingInfo } from '@babylonjs/core/Culling/boundingInfo';
4
4
  import { Engine } from '@babylonjs/core/Engines/engine';
5
5
  import { HighlightLayer } from '@babylonjs/core/Layers/highlightLayer';
6
- import { StandardMaterial } from '@babylonjs/core/Materials/standardMaterial';
7
- import { DynamicTexture } from '@babylonjs/core/Materials/Textures/dynamicTexture';
8
- import { Color3 } from '@babylonjs/core/Maths/math.color';
9
6
  import { Vector3 } from '@babylonjs/core/Maths/math.vector';
10
7
  import { Mesh } from '@babylonjs/core/Meshes/mesh';
8
+ import { TransformNode } from '@babylonjs/core/Meshes/transformNode';
11
9
  import { ScreenshotTools } from '@babylonjs/core/Misc/screenshotTools';
12
10
  import { Scene } from '@babylonjs/core/scene';
13
11
  import { isString } from 'lodash-es';
@@ -17,7 +15,7 @@ import { AnimationManager } from '../manager/animationManager';
17
15
  import { SceneManager } from '../manager/sceneManager';
18
16
  import { VariantInstanceManager } from '../manager/variantInstanceManager';
19
17
  import { SpecStorage } from '../store/specStorage';
20
- import { debounce, loadJson, sleep } from '../util/resourceHelper';
18
+ import { debounce, loadJson } from '../util/resourceHelper';
21
19
  import { Event } from './event';
22
20
  import { EventBroadcaster } from './eventBroadcaster';
23
21
  import { Parameter } from './parameter';
@@ -147,14 +145,8 @@ export class Viewer extends EventBroadcaster {
147
145
  }
148
146
  // resize handler
149
147
  window.addEventListener( 'resize', debounce( this.resize.bind( this ), 100 ) );
150
- // wait until scene is completely ready
151
- await this.scene.whenReadyAsync();
152
148
  // event broadcasting
153
149
  this.broadcastEvent( Event.BOOTSTRAP_END, this );
154
- // render loop
155
- this.engine.runRenderLoop( () => {
156
- this.scene.render();
157
- } );
158
150
  return this;
159
151
  }
160
152
 
@@ -272,21 +264,19 @@ export class Viewer extends EventBroadcaster {
272
264
  /**
273
265
  * Calculates the bounding box from all visible meshes on the scene.
274
266
  */
275
- public async calculateBoundingBox(): Promise<Mesh> {
267
+ public calculateBoundingBox(): Mesh {
276
268
  if( this.scene.meshes.length === 0 ) {
277
269
  throw new Error( 'There are currently no meshes on the scene.' );
278
270
  }
279
- this.scene.render(); // XXX: workaround for BoundingBox not respecting render loop
280
- const bbName = '__bounding_box__';
281
271
  let max = new Vector3( 0, 0, 0 );
282
272
  let min = new Vector3( 0, 0, 0 );
283
- this.scene.meshes.filter( mesh => bbName !== mesh.id && mesh.isEnabled() ).forEach( mesh => {
273
+ this.scene.meshes.filter( mesh => mesh.isVisible ).forEach( mesh => {
284
274
  max = Vector3.Maximize( max, mesh.getBoundingInfo().boundingBox.maximumWorld );
285
275
  min = Vector3.Minimize( min, mesh.getBoundingInfo().boundingBox.minimumWorld );
286
276
  } );
287
- let boundingBox = this.scene.getMeshByName( bbName ) as Mesh;
277
+ let boundingBox = this.scene.getMeshByName( '__bounding_box__' ) as Mesh;
288
278
  if( !boundingBox ) {
289
- boundingBox = new Mesh( bbName, this.scene );
279
+ boundingBox = new Mesh( '__bounding_box__', this.scene );
290
280
  }
291
281
  boundingBox.setBoundingInfo( new BoundingInfo( min, max ) );
292
282
  //boundingBox.showBoundingBox = true;
@@ -296,14 +286,14 @@ export class Viewer extends EventBroadcaster {
296
286
  /**
297
287
  * Focuses the camera to see every visible mesh in scene and tries to optimize wheel precision and panning.
298
288
  */
299
- public async autofocusActiveCamera( settings?: AutofocusSettings ) {
289
+ public autofocusActiveCamera( settings?: AutofocusSettings ) {
300
290
  const activeCamera = this.scene.activeCamera;
301
291
  if( !activeCamera ) {
302
292
  throw new Error( 'No active camera found when using autofocus feature.' );
303
293
  }
304
294
  if( activeCamera instanceof ArcRotateCamera ) {
305
295
  // calculate some values
306
- const boundingBox = await this.calculateBoundingBox();
296
+ const boundingBox = this.calculateBoundingBox();
307
297
  const size = boundingBox.getBoundingInfo().maximum.subtract( boundingBox.getBoundingInfo().minimum );
308
298
  let radius = size.length() * (settings?.radiusFactor ?? 1.5);
309
299
  if( !isFinite( radius ) ) {
@@ -368,56 +358,6 @@ export class Viewer extends EventBroadcaster {
368
358
  return this;
369
359
  }
370
360
 
371
- /**
372
- * Show coordinate system with given dimension (for debugging purpose).
373
- */
374
- public showWorldCoordinates( dimension: number ) {
375
- const scene = this.scene;
376
- const makeTextPlane = function( text: string, color: string, size: number ) {
377
- const dynamicTexture = new DynamicTexture( 'DynamicTexture', 50, scene, true );
378
- dynamicTexture.hasAlpha = true;
379
- dynamicTexture.drawText( text, 5, 40, 'bold 36px Arial', color, 'transparent', true );
380
- const plane = Mesh.CreatePlane( 'TextPlane', size, scene, true );
381
- plane.material = new StandardMaterial( 'TextPlaneMaterial', scene );
382
- plane.material.backFaceCulling = false;
383
- // @ts-ignore
384
- plane.material.specularColor = new Color3( 0, 0, 0 );
385
- // @ts-ignore
386
- plane.material.diffuseTexture = dynamicTexture;
387
- return plane;
388
- };
389
- const axisX = Mesh.CreateLines( 'axisX', [
390
- Vector3.Zero(),
391
- new Vector3( dimension, 0, 0 ),
392
- new Vector3( dimension * 0.95, 0.05 * dimension, 0 ),
393
- new Vector3( dimension, 0, 0 ),
394
- new Vector3( dimension * 0.95, -0.05 * dimension, 0 )
395
- ], scene );
396
- axisX.color = new Color3( 1, 0, 0 );
397
- const xChar = makeTextPlane( 'X', 'red', dimension / 10 );
398
- xChar.position = new Vector3( 0.9 * dimension, -0.05 * dimension, 0 );
399
- const axisY = Mesh.CreateLines( 'axisY', [
400
- Vector3.Zero(),
401
- new Vector3( 0, dimension, 0 ),
402
- new Vector3( -0.05 * dimension, dimension * 0.95, 0 ),
403
- new Vector3( 0, dimension, 0 ),
404
- new Vector3( 0.05 * dimension, dimension * 0.95, 0 )
405
- ], scene );
406
- axisY.color = new Color3( 0, 1, 0 );
407
- const yChar = makeTextPlane( 'Y', 'green', dimension / 10 );
408
- yChar.position = new Vector3( 0, 0.9 * dimension, -0.05 * dimension );
409
- const axisZ = Mesh.CreateLines( 'axisZ', [
410
- Vector3.Zero(),
411
- new Vector3( 0, 0, dimension ),
412
- new Vector3( 0, -0.05 * dimension, dimension * 0.95 ),
413
- new Vector3( 0, 0, dimension ),
414
- new Vector3( 0, 0.05 * dimension, dimension * 0.95 )
415
- ], scene );
416
- axisZ.color = new Color3( 0, 0, 1 );
417
- const zChar = makeTextPlane( 'Z', 'blue', dimension / 10 );
418
- zChar.position = new Vector3( 0, 0.05 * dimension, 0.9 * dimension );
419
- }
420
-
421
361
  /**
422
362
  * @emits {@link Event.SCENE_PROCESSING_START}
423
363
  * @emits {@link Event.SCENE_PROCESSING_END}
@@ -453,6 +393,9 @@ export class Viewer extends EventBroadcaster {
453
393
  this._sceneManager = await SceneManager.create( scene );
454
394
  this._animationManager = await AnimationManager.create( scene );
455
395
  this.broadcastEvent( Event.SCENE_PROCESSING_END, scene );
396
+ engine.runRenderLoop( () => {
397
+ scene.render();
398
+ } );
456
399
  return scene;
457
400
  }
458
401