Browse Source

Configure modelModel configuration can be updated

Raanan Weber 7 years ago
parent
commit
7d4d8467d7

+ 47 - 43
Viewer/src/configuration/configuration.ts

@@ -19,20 +19,7 @@ export interface ViewerConfiguration {
 
     canvasElement?: string; // if there is a need to override the standard implementation - ID of HTMLCanvasElement
 
-    model?: {
-        url?: string;
-        loader?: string; // obj, gltf?
-        position?: { x: number, y: number, z: number };
-        rotation?: { x: number, y: number, z: number, w: number };
-        scaling?: { x: number, y: number, z: number };
-        parentObjectIndex?: number; // the index of the parent object of the model in the loaded meshes array.
-
-        title: string;
-        subtitle?: string;
-        thumbnail?: string; // URL or data-url
-
-        [propName: string]: any; // further configuration, like title and creator
-    } | string;
+    model?: IModelConfiguration | string;
 
     scene?: ISceneConfiguration;
     optimizer?: ISceneOptimizerConfiguration | boolean;
@@ -77,35 +64,7 @@ export interface ViewerConfiguration {
 
     };
     lights?: {
-        [name: string]: {
-            type: number;
-            name?: string;
-            disabled?: boolean;
-            position?: { x: number, y: number, z: number };
-            target?: { x: number, y: number, z: number };
-            direction?: { x: number, y: number, z: number };
-            diffuse?: { r: number, g: number, b: number };
-            specular?: { r: number, g: number, b: number };
-            intensity?: number;
-            radius?: number;
-            shadownEnabled?: boolean; // only on specific lights!
-            shadowConfig?: {
-                useBlurExponentialShadowMap?: boolean;
-                useKernelBlur?: boolean;
-                blurKernel?: number;
-                blurScale?: number;
-                [propName: string]: any;
-            }
-            [propName: string]: any;
-
-            // no behaviors for light at the moment, but allowing configuration for future reference.
-            behaviors?: {
-                [name: string]: number | {
-                    type: number;
-                    [propName: string]: any;
-                };
-            };
-        }
+        [name: string]: ILightConfiguration
     },
     // engine configuration. optional!
     engine?: {
@@ -144,6 +103,21 @@ export interface ViewerConfiguration {
     }
 }
 
+export interface IModelConfiguration {
+    url: string;
+    loader?: string; // obj, gltf?
+    position?: { x: number, y: number, z: number };
+    rotation?: { x: number, y: number, z: number, w?: number };
+    scaling?: { x: number, y: number, z: number };
+    parentObjectIndex?: number; // the index of the parent object of the model in the loaded meshes array.
+
+    title: string;
+    subtitle?: string;
+    thumbnail?: string; // URL or data-url
+
+    // [propName: string]: any; // further configuration, like title and creator
+}
+
 export interface ISceneConfiguration {
     debug?: boolean;
     autoRotate?: boolean; // deprecated
@@ -197,6 +171,36 @@ export interface ICameraConfiguration {
     [propName: string]: any;
 }
 
+export interface ILightConfiguration {
+    type: number;
+    name?: string;
+    disabled?: boolean;
+    position?: { x: number, y: number, z: number };
+    target?: { x: number, y: number, z: number };
+    direction?: { x: number, y: number, z: number };
+    diffuse?: { r: number, g: number, b: number };
+    specular?: { r: number, g: number, b: number };
+    intensity?: number;
+    radius?: number;
+    shadownEnabled?: boolean; // only on specific lights!
+    shadowConfig?: {
+        useBlurExponentialShadowMap?: boolean;
+        useKernelBlur?: boolean;
+        blurKernel?: number;
+        blurScale?: number;
+        [propName: string]: any;
+    }
+    [propName: string]: any;
+
+    // no behaviors for light at the moment, but allowing configuration for future reference.
+    behaviors?: {
+        [name: string]: number | {
+            type: number;
+            [propName: string]: any;
+        };
+    };
+}
+
 export interface ISceneOptimizerParameters {
     priority?: number;
     maximumSize?: number;

+ 30 - 31
Viewer/src/viewer/defaultViewer.ts

@@ -1,6 +1,6 @@
 
 
-import { ViewerConfiguration } from './../configuration/configuration';
+import { ViewerConfiguration, IModelConfiguration } from './../configuration/configuration';
 import { Template, EventCallback } from './../templateManager';
 import { AbstractViewer } from './viewer';
 import { SpotLight, MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMaterial, Observable, ShadowLight, CubeTexture, BouncingBehavior, FramingBehavior, Behavior, Light, Engine, Scene, AutoRotationBehavior, AbstractMesh, Quaternion, StandardMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
@@ -105,6 +105,34 @@ export class DefaultViewer extends AbstractViewer {
         this.containerElement.style.display = 'flex';
     }
 
+    protected configureModel(modelConfiguration: Partial<IModelConfiguration>) {
+        super.configureModel(modelConfiguration);
+
+        let navbar = this.templateManager.getTemplate('navBar');
+        if (!navbar) return;
+
+        let metadataContainer = navbar.parent.querySelector('#model-metadata');
+        if (metadataContainer) {
+            if (modelConfiguration.title !== undefined) {
+                let element = metadataContainer.querySelector('span.model-title');
+                if (element) {
+                    element.innerHTML = modelConfiguration.title;
+                }
+            }
+
+            if (modelConfiguration.subtitle !== undefined) {
+                let element = metadataContainer.querySelector('span.model-subtitle');
+                if (element) {
+                    element.innerHTML = modelConfiguration.subtitle;
+                }
+            }
+
+            if (modelConfiguration.thumbnail !== undefined) {
+                (<HTMLDivElement>metadataContainer.querySelector('.thumbnail')).style.backgroundImage = `url('${modelConfiguration.thumbnail}')`;
+            }
+        }
+    }
+
     public loadModel(model: any = this.configuration.model): Promise<Scene> {
         this.showLoadingScreen();
         return super.loadModel(model, true).catch((error) => {
@@ -118,7 +146,7 @@ export class DefaultViewer extends AbstractViewer {
     private onModelLoaded = (meshes: Array<AbstractMesh>) => {
 
         // here we could set the navbar's model information:
-        this.setModelMetaData();
+        this.configureModel(this.configuration.model || {});
 
         // with a short timeout, making sure everything is there already.
         let hideLoadingDelay = 500;
@@ -142,35 +170,6 @@ export class DefaultViewer extends AbstractViewer {
         return; //this.initEnvironment(meshes);
     }
 
-    private setModelMetaData() {
-        let navbar = this.templateManager.getTemplate('navBar');
-        if (!navbar) return;
-
-        let metadataContainer = navbar.parent.querySelector('#model-metadata');
-
-        //title
-        if (metadataContainer && typeof this.configuration.model === 'object') {
-            if (this.configuration.model.title) {
-                let element = metadataContainer.querySelector('span.model-title');
-                if (element) {
-                    element.innerHTML = this.configuration.model.title;
-                }
-            }
-
-            if (this.configuration.model.subtitle) {
-                let element = metadataContainer.querySelector('span.model-subtitle');
-                if (element) {
-                    element.innerHTML = this.configuration.model.subtitle;
-                }
-            }
-
-            if (this.configuration.model.thumbnail) {
-                (<HTMLDivElement>metadataContainer.querySelector('.thumbnail')).style.backgroundImage = `url('${this.configuration.model.thumbnail}')`;
-            }
-        }
-
-    }
-
     /*protected initEnvironment(focusMeshes: Array<AbstractMesh> = []): Promise<Scene> {
         if (this.configuration.skybox) {
             // Define a general environment textue

+ 53 - 2
Viewer/src/viewer/viewer.ts

@@ -1,8 +1,8 @@
 import { viewerManager } from './viewerManager';
 import { TemplateManager } from './../templateManager';
 import configurationLoader from './../configuration/loader';
-import { CubeTexture, Color3, IEnvironmentHelperOptions, EnvironmentHelper, Effect, SceneOptimizer, SceneOptimizerOptions, Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, AbstractMesh, Mesh, HemisphericLight, Database, SceneLoaderProgressEvent, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from 'babylonjs';
-import { ViewerConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, IObserversConfiguration } from '../configuration/configuration';
+import { CubeTexture, Color3, IEnvironmentHelperOptions, EnvironmentHelper, Effect, SceneOptimizer, SceneOptimizerOptions, Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, AbstractMesh, Mesh, HemisphericLight, Database, SceneLoaderProgressEvent, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Quaternion } from 'babylonjs';
+import { ViewerConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, IObserversConfiguration, IModelConfiguration } from '../configuration/configuration';
 
 import * as deepmerge from '../../assets/deepmerge.min.js';
 
@@ -138,6 +138,11 @@ export abstract class AbstractViewer {
             this.configureObservers(newConfiguration.observers);
         }
 
+        // configure model
+        if (newConfiguration.model && typeof newConfiguration.model === 'object') {
+            this.configureModel(newConfiguration.model);
+        }
+
         // update this.configuration with the new data
         this.configuration = deepmerge(this.configuration || {}, newConfiguration);
     }
@@ -246,6 +251,52 @@ export abstract class AbstractViewer {
         }
     }
 
+    protected configureModel(modelConfiguration: Partial<IModelConfiguration>) {
+        let meshesWithNoParent: Array<AbstractMesh> = this.scene.meshes.filter(m => !m.parent);
+        let updateMeshesWithNoParent = (variable: string, value: any, param?: string) => {
+            meshesWithNoParent.forEach(mesh => {
+                if (param) {
+                    mesh[variable][param] = value;
+                } else {
+                    mesh[variable] = value;
+                }
+            });
+        }
+        let updateXYZ = (variable: string, configValues: { x: number, y: number, z: number, w?: number }) => {
+            if (configValues.x !== undefined) {
+                updateMeshesWithNoParent(variable, configValues.x, 'x');
+            }
+            if (configValues.y !== undefined) {
+                updateMeshesWithNoParent(variable, configValues.y, 'y');
+            }
+            if (configValues.z !== undefined) {
+                updateMeshesWithNoParent(variable, configValues.z, 'z');
+            }
+            if (configValues.w !== undefined) {
+                updateMeshesWithNoParent(variable, configValues.w, 'w');
+            }
+        }
+        // position?
+        if (modelConfiguration.position) {
+            updateXYZ('position', modelConfiguration.position);
+        }
+        if (modelConfiguration.rotation) {
+            if (modelConfiguration.rotation.w) {
+                meshesWithNoParent.forEach(mesh => {
+                    if (!mesh.rotationQuaternion) {
+                        mesh.rotationQuaternion = new Quaternion();
+                    }
+                })
+                updateXYZ('rotationQuaternion', modelConfiguration.rotation);
+            } else {
+                updateXYZ('rotation', modelConfiguration.rotation);
+            }
+        }
+        if (modelConfiguration.scaling) {
+            updateXYZ('scaling', modelConfiguration.scaling);
+        }
+    }
+
     public dispose() {
         window.removeEventListener('resize', this.resize);