Explorar o código

Merge pull request #4409 from RaananW/viewer-modules

minimizing dependencies for the viewer
Raanan Weber %!s(int64=7) %!d(string=hai) anos
pai
achega
4d618f26a0
Modificáronse 61 ficheiros con 1462 adicións e 1238 borrados
  1. 1 1
      .gitignore
  2. 1 1
      Tools/Gulp/config.json
  3. 2 2
      Tools/Gulp/package.json
  4. 0 97
      Viewer/assets/deepmerge.min.js
  5. 0 1
      Viewer/assets/es6-promise.min.js
  6. 0 29
      Viewer/assets/handlebars.min.js
  7. 0 210
      Viewer/assets/pep.min.js
  8. 6 1
      Viewer/package.json
  9. 1 431
      Viewer/src/configuration/configuration.ts
  10. 1 1
      Viewer/src/configuration/configurationCompatibility.ts
  11. 12 0
      Viewer/src/configuration/configurationContainer.ts
  12. 6 0
      Viewer/src/configuration/globals.ts
  13. 2 1
      Viewer/src/configuration/index.ts
  14. 24 0
      Viewer/src/configuration/interfaces/cameraConfiguration.ts
  15. 101 0
      Viewer/src/configuration/interfaces/colorGradingConfiguration.ts
  16. 21 0
      Viewer/src/configuration/interfaces/defaultRenderingPipelineConfiguration.ts
  17. 20 0
      Viewer/src/configuration/interfaces/groundConfiguration.ts
  18. 38 0
      Viewer/src/configuration/interfaces/imageProcessingConfiguration.ts
  19. 13 0
      Viewer/src/configuration/interfaces/index.ts
  20. 42 0
      Viewer/src/configuration/interfaces/lightConfiguration.ts
  21. 29 0
      Viewer/src/configuration/interfaces/modelAnimationConfiguration.ts
  22. 63 0
      Viewer/src/configuration/interfaces/modelConfiguration.ts
  23. 5 0
      Viewer/src/configuration/interfaces/observersConfiguration.ts
  24. 40 0
      Viewer/src/configuration/interfaces/sceneConfiguration.ts
  25. 24 0
      Viewer/src/configuration/interfaces/sceneOptimizerConfiguration.ts
  26. 19 0
      Viewer/src/configuration/interfaces/skyboxConfiguration.ts
  27. 46 0
      Viewer/src/configuration/interfaces/templateConfiguration.ts
  28. 1 1
      Viewer/src/configuration/loader.ts
  29. 1 1
      Viewer/src/configuration/mappers.ts
  30. 1 1
      Viewer/src/configuration/types/index.ts
  31. 1 0
      Viewer/src/externalModules.d.ts
  32. 11 0
      Viewer/src/helper/deepmerge.d.ts
  33. 5 0
      Viewer/src/helper.ts
  34. 2 3
      Viewer/src/index.ts
  35. 17 15
      Viewer/src/labs/texture.ts
  36. 12 14
      Viewer/src/labs/viewerLabs.ts
  37. 17 10
      Viewer/src/loader/modelLoader.ts
  38. 1 1
      Viewer/src/loader/plugins/applyMaterialConfig.ts
  39. 1 1
      Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts
  40. 13 0
      Viewer/src/loader/plugins/index.ts
  41. 1 1
      Viewer/src/loader/plugins/msftLodLoaderPlugin.ts
  42. 7 7
      Viewer/src/loader/plugins/telemetryLoaderPlugin.ts
  43. 77 0
      Viewer/src/managers/observablesManager.ts
  44. 87 66
      Viewer/src/viewer/sceneManager.ts
  45. 25 27
      Viewer/src/model/viewerModel.ts
  46. 42 42
      Viewer/src/optimizer/custom/extended.ts
  47. 2 2
      Viewer/src/optimizer/custom/index.ts
  48. 6 8
      Viewer/src/telemetryManager.ts
  49. 0 0
      Viewer/src/templating/eventManager.ts
  50. 343 0
      Viewer/src/templating/handlebars.d.ts
  51. 6 52
      Viewer/src/templateManager.ts
  52. 49 21
      Viewer/src/viewer/defaultViewer.ts
  53. 110 109
      Viewer/src/viewer/viewer.ts
  54. 10 4
      Viewer/tests/commons/helper.ts
  55. 42 28
      Viewer/tests/unit/src/viewer/sceneManager.ts
  56. 1 2
      Viewer/tests/unit/src/viewer/viewer.ts
  57. 26 15
      Viewer/tsconfig-gulp.json
  58. 23 23
      Viewer/tsconfig.json
  59. 2 4
      Viewer/webpack.config.js
  60. 1 5
      Viewer/webpack.gulp.config.js
  61. 2 0
      dist/preview release/what's new.md

+ 1 - 1
.gitignore

@@ -178,7 +178,7 @@ dist/preview release/viewer/babylon.d.ts
 dist/preview release/viewer/babylonjs.loaders.d.ts
 dist/preview release/viewer/babylon.glTF2Interface.d.ts
 Viewer/dist/viewer.max.js
-!Viewer/src/externalModules.d.ts
+!Viewer/src/**/*.d.ts
 Viewer/tests/unit/src/**/*.js
 Viewer/tests/Lib/**/*.js
 Viewer/tests/commons/**/*.js

+ 1 - 1
Tools/Gulp/config.json

@@ -1834,7 +1834,7 @@
             "srcOutputDirectory": "../../Viewer/",
             "dtsBundle": {
                 "name": "babylonjs-viewer",
-                "main": "../../Viewer/src/index.d.ts",
+                "main": "../../Viewer/dist/build/src/index.d.ts",
                 "out": "../../dist/preview release/viewer/babylon.viewer.module.d.ts",
                 "prependText": "/// <reference path=\"./babylon.d.ts\"/>\n/// <reference path=\"./babylon.glTF2Interface.d.ts\"/>\n/// <reference path=\"./babylonjs.loaders.d.ts\"/>\ndeclare module \"babylonjs-loaders\"{ export=BABYLON;}\n"
             },

+ 2 - 2
Tools/Gulp/package.json

@@ -62,11 +62,11 @@
         "webpack-stream": "^4.0.1"
     },
     "scripts": {
-        "install": "npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && gulp deployLocalDev"
+        "install": "npm --prefix ../../Playground/ install ../../Playground/ && npm --prefix ../../tests/unit/ install ../../tests/unit/ && npm --prefix ../../Viewer/tests/ install ../../Viewer/tests/ && npm --prefix ../../Viewer/ install ../../Viewer/ && gulp deployLocalDev"
     },
     "dependencies": {
         "dts-bundle": "^0.7.3",
         "gulp-clean": "^0.4.0",
         "npm": "^5.8.0"
     }
-}
+}

+ 0 - 97
Viewer/assets/deepmerge.min.js

@@ -1,97 +0,0 @@
-(function (global, factory) {
-	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
-	typeof define === 'function' && define.amd ? define(factory) :
-	(global.deepmerge = factory());
-}(this, (function () { 'use strict';
-
-var isMergeableObject = function isMergeableObject(value) {
-	return isNonNullObject(value)
-		&& !isSpecial(value)
-};
-
-function isNonNullObject(value) {
-	return !!value && typeof value === 'object'
-}
-
-function isSpecial(value) {
-	var stringValue = Object.prototype.toString.call(value);
-
-	return stringValue === '[object RegExp]'
-		|| stringValue === '[object Date]'
-		|| isReactElement(value)
-}
-
-// see https://github.com/facebook/react/blob/b5ac963fb791d1298e7f396236383bc955f916c1/src/isomorphic/classic/element/ReactElement.js#L21-L25
-var canUseSymbol = typeof Symbol === 'function' && Symbol.for;
-var REACT_ELEMENT_TYPE = canUseSymbol ? Symbol.for('react.element') : 0xeac7;
-
-function isReactElement(value) {
-	return value.$$typeof === REACT_ELEMENT_TYPE
-}
-
-function emptyTarget(val) {
-	return Array.isArray(val) ? [] : {}
-}
-
-function cloneUnlessOtherwiseSpecified(value, optionsArgument) {
-	var clone = !optionsArgument || optionsArgument.clone !== false;
-
-	return (clone && isMergeableObject(value))
-		? deepmerge(emptyTarget(value), value, optionsArgument)
-		: value
-}
-
-function defaultArrayMerge(target, source, optionsArgument) {
-	return target.concat(source).map(function(element) {
-		return cloneUnlessOtherwiseSpecified(element, optionsArgument)
-	})
-}
-
-function mergeObject(target, source, optionsArgument) {
-	var destination = {};
-	if (isMergeableObject(target)) {
-		Object.keys(target).forEach(function(key) {
-			destination[key] = cloneUnlessOtherwiseSpecified(target[key], optionsArgument);
-		});
-	}
-	Object.keys(source).forEach(function(key) {
-		if (!isMergeableObject(source[key]) || !target[key]) {
-			destination[key] = cloneUnlessOtherwiseSpecified(source[key], optionsArgument);
-		} else {
-			destination[key] = deepmerge(target[key], source[key], optionsArgument);
-		}
-	});
-	return destination
-}
-
-function deepmerge(target, source, optionsArgument) {
-	var sourceIsArray = Array.isArray(source);
-	var targetIsArray = Array.isArray(target);
-	var options = optionsArgument || { arrayMerge: defaultArrayMerge };
-	var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
-
-	if (!sourceAndTargetTypesMatch) {
-		return cloneUnlessOtherwiseSpecified(source, optionsArgument)
-	} else if (sourceIsArray) {
-		var arrayMerge = options.arrayMerge || defaultArrayMerge;
-		return arrayMerge(target, source, optionsArgument)
-	} else {
-		return mergeObject(target, source, optionsArgument)
-	}
-}
-
-deepmerge.all = function deepmergeAll(array, optionsArgument) {
-	if (!Array.isArray(array)) {
-		throw new Error('first argument should be an array')
-	}
-
-	return array.reduce(function(prev, next) {
-		return deepmerge(prev, next, optionsArgument)
-	}, {})
-};
-
-var deepmerge_1 = deepmerge;
-
-return deepmerge_1;
-
-})));

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 1
Viewer/assets/es6-promise.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 29
Viewer/assets/handlebars.min.js


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 210
Viewer/assets/pep.min.js


+ 6 - 1
Viewer/package.json

@@ -23,9 +23,12 @@
     },
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
+        "@types/handlebars": "^4.0.37",
         "@types/node": "^8.9.4",
         "base64-font-loader": "0.0.4",
         "base64-image-loader": "^1.2.1",
+        "deepmerge": "^2.1.1",
+        "handlebars": "^4.0.11",
         "html-loader": "^0.5.5",
         "json-loader": "^0.5.7",
         "ts-loader": "^2.3.7",
@@ -34,5 +37,7 @@
         "webpack": "^3.11.0",
         "webpack-dev-server": "^2.11.2"
     },
-    "dependencies": {}
+    "dependencies": {
+        "pepjs": "^0.4.3"
+    }
 }

+ 1 - 431
Viewer/src/configuration/configuration.ts

@@ -1,5 +1,5 @@
-import { ITemplateConfiguration } from './../templateManager';
 import { EngineOptions, IGlowLayerOptions, DepthOfFieldEffectBlurLevel } from 'babylonjs';
+import { IObserversConfiguration, IModelConfiguration, ISceneConfiguration, ISceneOptimizerConfiguration, ICameraConfiguration, ISkyboxConfiguration, IGroundConfiguration, ILightConfiguration, IDefaultRenderingPipelineConfiguration, ITemplateConfiguration } from './interfaces';
 
 export function getConfigurationKey(key: string, configObject: any) {
     let splits = key.split('.');
@@ -112,434 +112,4 @@ export interface ViewerConfiguration {
         defaultRenderingPipelines?: boolean | IDefaultRenderingPipelineConfiguration;
         globalLightRotation?: number;
     }
-}
-
-/**
- * Defines an animation to be applied to a model (translation, scale or rotation).
- */
-export interface IModelAnimationConfiguration {
-    /**
-     * Time of animation, in seconds
-     */
-    time?: number;
-
-    /**
-     * Scale to apply
-     */
-    scaling?: {
-        x: number;
-        y: number;
-        z: number;
-    };
-
-    /**
-     * Easing function to apply
-     * See SPECTRE.EasingFunction
-     */
-    easingFunction?: number;
-
-    /**
-     * An Easing mode to apply to the easing function
-     * See BABYLON.EasingFunction
-     */
-    easingMode?: number;
-}
-
-
-export interface IDefaultRenderingPipelineConfiguration {
-    sharpenEnabled?: boolean;
-    bloomEnabled?: boolean;
-    bloomThreshold?: number;
-    depthOfFieldEnabled?: boolean;
-    depthOfFieldBlurLevel?: DepthOfFieldEffectBlurLevel;
-    fxaaEnabled?: boolean;
-    imageProcessingEnabled?: boolean;
-    defaultPipelineTextureType?: number;
-    bloomScale?: number;
-    chromaticAberrationEnabled?: boolean;
-    grainEnabled?: boolean;
-    bloomKernel?: number;
-    hardwareScaleLevel?: number;
-    bloomWeight?: number;
-    hdr?: boolean;
-    samples?: number;
-    glowLayerEnabled?: boolean;
-}
-
-export interface IModelConfiguration {
-    id?: string;
-    url?: string;
-    root?: string; //optional
-    file?: string | File; // is a file being loaded? root and url ignored
-    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.
-
-    castShadow?: boolean;
-    receiveShadows?: boolean;
-    normalize?: boolean | {
-        center?: boolean;
-        unitSize?: boolean;
-        parentIndex?: number;
-    }; // should the model be scaled to unit-size
-
-    title?: string;
-    subtitle?: string;
-    thumbnail?: string; // URL or data-url
-
-    animation?: {
-        autoStart?: boolean | string;
-        playOnce?: boolean;
-        autoStartIndex?: number;
-    }
-
-    entryAnimation?: IModelAnimationConfiguration;
-    exitAnimation?: IModelAnimationConfiguration;
-
-    material?: {
-        directEnabled?: boolean;
-        directIntensity?: number;
-        emissiveIntensity?: number;
-        environmentIntensity?: number;
-        [propName: string]: any;
-    }
-
-    /** 
-     * Rotation offset axis definition
-     */
-    rotationOffsetAxis?: {
-        x: number;
-        y: number;
-        z: number;
-    };
-
-    /**
-     * the offset angle
-     */
-    rotationOffsetAngle?: number;
-
-    loaderConfiguration?: {
-        maxLODsToLoad?: number;
-        progressiveLoading?: boolean;
-    }
-
-    // [propName: string]: any; // further configuration, like title and creator
-}
-
-export interface ISkyboxConfiguration {
-    cubeTexture?: {
-        noMipMap?: boolean;
-        gammaSpace?: boolean;
-        url?: string | Array<string>;
-    };
-    color?: { r: number, g: number, b: number };
-    pbr?: boolean; // deprecated
-    scale?: number;
-    blur?: number; // deprecated
-    material?: {
-        imageProcessingConfiguration?: IImageProcessingConfiguration;
-        [propName: string]: any;
-    };
-    infiniteDistance?: boolean;
-
-}
-
-export interface IGroundConfiguration {
-    size?: number;
-    receiveShadows?: boolean;
-    shadowLevel?: number;
-    shadowOnly?: boolean; // deprecated
-    mirror?: boolean | {
-        sizeRatio?: number;
-        blurKernel?: number;
-        amount?: number;
-        fresnelWeight?: number;
-        fallOffDistance?: number;
-        textureType?: number;
-    };
-    texture?: string;
-    color?: { r: number, g: number, b: number };
-    opacity?: number;
-    material?: {
-        [propName: string]: any;
-    };
-}
-
-export interface ISceneConfiguration {
-    debug?: boolean;
-    clearColor?: { r: number, g: number, b: number, a: number };
-    mainColor?: { r?: number, g?: number, b?: number };
-    imageProcessingConfiguration?: IImageProcessingConfiguration;
-    environmentTexture?: string;
-    colorGrading?: IColorGradingConfiguration;
-    environmentRotationY?: number;
-    /**
-     * Deprecated, please use default rendering pipeline
-     */
-    glow?: boolean | IGlowLayerOptions;
-    disableHdr?: boolean;
-    renderInBackground?: boolean;
-    disableCameraControl?: boolean;
-    animationPropertiesOverride?: {
-        [propName: string]: any;
-    };
-    defaultMaterial?: {
-        materialType: "standard" | "pbr";
-        [propName: string]: any;
-    };
-    flags?: {
-        shadowsEnabled?: boolean;
-        particlesEnabled?: boolean;
-        collisionsEnabled?: boolean;
-        lightsEnabled?: boolean;
-        texturesEnabled?: boolean;
-        lensFlaresEnabled?: boolean;
-        proceduralTexturesEnabled?: boolean;
-        renderTargetsEnabled?: boolean;
-        spritesEnabled?: boolean;
-        skeletonsEnabled?: boolean;
-        audioEnabled?: boolean;
-    }
-}
-
-/**
- * The Color Grading Configuration groups the different settings used to define the color grading used in the viewer.
- */
-export interface IColorGradingConfiguration {
-
-    /**
-     * Transform data string, encoded as determined by transformDataFormat.
-     */
-    transformData: string;
-
-    /**
-     * The encoding format of TransformData (currently only raw-base16 is supported).
-     */
-    transformDataFormat: string;
-
-    /**
-     * The weight of the transform
-     */
-    transformWeight: number;
-
-    /**
-     * Color curve colorFilterHueGlobal value
-     */
-    colorFilterHueGlobal: number;
-
-    /**
-     * Color curve colorFilterHueShadows value
-     */
-    colorFilterHueShadows: number;
-
-    /**
-     * Color curve colorFilterHueMidtones value
-     */
-    colorFilterHueMidtones: number;
-
-    /**
-     * Color curve colorFilterHueHighlights value
-     */
-    colorFilterHueHighlights: number;
-
-    /**
-     * Color curve colorFilterDensityGlobal value
-     */
-    colorFilterDensityGlobal: number;
-
-    /**
-     * Color curve colorFilterDensityShadows value
-     */
-    colorFilterDensityShadows: number;
-
-    /**
-     * Color curve colorFilterDensityMidtones value
-     */
-    colorFilterDensityMidtones: number;
-
-    /**
-     * Color curve colorFilterDensityHighlights value
-     */
-    colorFilterDensityHighlights: number;
-
-    /**
-     * Color curve saturationGlobal value
-     */
-    saturationGlobal: number;
-
-    /**
-     * Color curve saturationShadows value
-     */
-    saturationShadows: number;
-
-    /**
-     * Color curve saturationMidtones value
-     */
-    saturationMidtones: number;
-
-    /**
-     * Color curve saturationHighlights value
-     */
-    saturationHighlights: number;
-
-    /**
-     * Color curve exposureGlobal value
-     */
-    exposureGlobal: number;
-
-    /**
-     * Color curve exposureShadows value
-     */
-    exposureShadows: number;
-
-    /**
-     * Color curve exposureMidtones value
-     */
-    exposureMidtones: number;
-
-    /**
-     * Color curve exposureHighlights value
-     */
-    exposureHighlights: number;
-
-}
-
-export interface ISceneOptimizerConfiguration {
-    targetFrameRate?: number;
-    trackerDuration?: number;
-    autoGeneratePriorities?: boolean;
-    improvementMode?: boolean;
-    degradation?: string; // low, moderate, high
-    types?: {
-        texture?: ISceneOptimizerParameters;
-        hardwareScaling?: ISceneOptimizerParameters;
-        shadow?: ISceneOptimizerParameters;
-        postProcess?: ISceneOptimizerParameters;
-        lensFlare?: ISceneOptimizerParameters;
-        particles?: ISceneOptimizerParameters;
-        renderTarget?: ISceneOptimizerParameters;
-        mergeMeshes?: ISceneOptimizerParameters;
-    }
-    custom?: string;
-}
-
-export interface IObserversConfiguration {
-    onEngineInit?: string;
-    onSceneInit?: string;
-    onModelLoaded?: string;
-}
-
-export interface ICameraConfiguration {
-    position?: { x: number, y: number, z: number };
-    rotation?: { x: number, y: number, z: number, w: number };
-    fov?: number;
-    fovMode?: number;
-    minZ?: number;
-    maxZ?: number;
-    inertia?: number;
-    exposure?: number;
-    pinchPrecision?: number;
-    behaviors?: {
-        [name: string]: boolean | number | ICameraBehaviorConfiguration;
-    };
-    disableCameraControl?: boolean;
-    disableCtrlForPanning?: boolean;
-    disableAutoFocus?: boolean;
-
-    [propName: string]: any;
-}
-
-export interface ICameraBehaviorConfiguration {
-    type: number;
-    [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;
-    intensityMode?: number;
-    radius?: number;
-    shadownEnabled?: boolean; // only on specific lights!
-    shadowConfig?: {
-        useBlurExponentialShadowMap?: boolean;
-        useBlurCloseExponentialShadowMap?: boolean;
-        useKernelBlur?: boolean;
-        blurKernel?: number;
-        blurScale?: number;
-        minZ?: number;
-        maxZ?: number;
-        frustumSize?: number;
-        angleScale?: number;
-        frustumEdgeFalloff?: number;
-        [propName: string]: any;
-    };
-    spotAngle?: number;
-    shadowFieldOfView?: number;
-    shadowBufferSize?: number;
-    shadowFrustumSize?: number;
-    shadowMinZ?: number;
-    shadowMaxZ?: number;
-    [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;
-    step?: number;
-}
-
-export interface IImageProcessingConfiguration {
-    colorGradingEnabled?: boolean;
-    colorCurvesEnabled?: boolean;
-    colorCurves?: {
-        globalHue?: number;
-        globalDensity?: number;
-        globalSaturation?: number;
-        globalExposure?: number;
-        highlightsHue?: number;
-        highlightsDensity?: number;
-        highlightsSaturation?: number;
-        highlightsExposure?: number;
-        midtonesHue?: number;
-        midtonesDensity?: number;
-        midtonesSaturation?: number;
-        midtonesExposure?: number;
-        shadowsHue?: number;
-        shadowsDensity?: number;
-        shadowsSaturation?: number;
-        shadowsExposure?: number;
-    };
-    colorGradingWithGreenDepth?: boolean;
-    colorGradingBGR?: boolean;
-    exposure?: number;
-    toneMappingEnabled?: boolean;
-    contrast?: number;
-    vignetteEnabled?: boolean;
-    vignetteStretch?: number;
-    vignetteCentreX?: number;
-    vignetteCentreY?: number;
-    vignetteWeight?: number;
-    vignetteColor?: { r: number, g: number, b: number, a?: number };
-    vignetteCameraFov?: number;
-    vignetteBlendMode?: number;
-    vignetteM?: boolean;
-    applyByPostProcess?: boolean;
-    isEnabled?: boolean;
 }

+ 1 - 1
Viewer/src/configuration/configurationCompatibility.ts

@@ -1,4 +1,4 @@
-import { ViewerConfiguration, getConfigurationKey } from './'
+import { ViewerConfiguration, getConfigurationKey } from './configuration'
 /**
  * This function will make sure the configuration file is taking deprecated fields into account
  * and is setting them to the correct keys and values.

+ 12 - 0
Viewer/src/configuration/configurationContainer.ts

@@ -0,0 +1,12 @@
+import { ViewerConfiguration } from './configuration';
+import { Color3 } from 'babylonjs';
+
+export class ConfigurationContainer {
+
+    public configuration: ViewerConfiguration;
+
+    public viewerId: string;
+
+    public mainColor: Color3 = Color3.White();
+    public reflectionColor: Color3 = Color3.White();
+}

+ 6 - 0
Viewer/src/configuration/globals.ts

@@ -1,8 +1,14 @@
+import { Engine } from "babylonjs";
+
 export class ViewerGlobals {
 
     public disableInit: boolean = false;
     public disableWebGL2Support: boolean = false;
 
+    public get version(): string {
+        return Engine.Version;
+    }
+
 }
 
 export let viewerGlobals: ViewerGlobals = new ViewerGlobals();

+ 2 - 1
Viewer/src/configuration/index.ts

@@ -1 +1,2 @@
-export * from './configuration';
+export * from './configuration';
+export * from './interfaces';

+ 24 - 0
Viewer/src/configuration/interfaces/cameraConfiguration.ts

@@ -0,0 +1,24 @@
+export interface ICameraConfiguration {
+    position?: { x: number, y: number, z: number };
+    rotation?: { x: number, y: number, z: number, w: number };
+    fov?: number;
+    fovMode?: number;
+    minZ?: number;
+    maxZ?: number;
+    inertia?: number;
+    exposure?: number;
+    pinchPrecision?: number;
+    behaviors?: {
+        [name: string]: boolean | number | ICameraBehaviorConfiguration;
+    };
+    disableCameraControl?: boolean;
+    disableCtrlForPanning?: boolean;
+    disableAutoFocus?: boolean;
+
+    [propName: string]: any;
+}
+
+export interface ICameraBehaviorConfiguration {
+    type: number;
+    [propName: string]: any;
+}

+ 101 - 0
Viewer/src/configuration/interfaces/colorGradingConfiguration.ts

@@ -0,0 +1,101 @@
+/**
+ * The Color Grading Configuration groups the different settings used to define the color grading used in the viewer.
+ */
+export interface IColorGradingConfiguration {
+
+    /**
+     * Transform data string, encoded as determined by transformDataFormat.
+     */
+    transformData: string;
+
+    /**
+     * The encoding format of TransformData (currently only raw-base16 is supported).
+     */
+    transformDataFormat: string;
+
+    /**
+     * The weight of the transform
+     */
+    transformWeight: number;
+
+    /**
+     * Color curve colorFilterHueGlobal value
+     */
+    colorFilterHueGlobal: number;
+
+    /**
+     * Color curve colorFilterHueShadows value
+     */
+    colorFilterHueShadows: number;
+
+    /**
+     * Color curve colorFilterHueMidtones value
+     */
+    colorFilterHueMidtones: number;
+
+    /**
+     * Color curve colorFilterHueHighlights value
+     */
+    colorFilterHueHighlights: number;
+
+    /**
+     * Color curve colorFilterDensityGlobal value
+     */
+    colorFilterDensityGlobal: number;
+
+    /**
+     * Color curve colorFilterDensityShadows value
+     */
+    colorFilterDensityShadows: number;
+
+    /**
+     * Color curve colorFilterDensityMidtones value
+     */
+    colorFilterDensityMidtones: number;
+
+    /**
+     * Color curve colorFilterDensityHighlights value
+     */
+    colorFilterDensityHighlights: number;
+
+    /**
+     * Color curve saturationGlobal value
+     */
+    saturationGlobal: number;
+
+    /**
+     * Color curve saturationShadows value
+     */
+    saturationShadows: number;
+
+    /**
+     * Color curve saturationMidtones value
+     */
+    saturationMidtones: number;
+
+    /**
+     * Color curve saturationHighlights value
+     */
+    saturationHighlights: number;
+
+    /**
+     * Color curve exposureGlobal value
+     */
+    exposureGlobal: number;
+
+    /**
+     * Color curve exposureShadows value
+     */
+    exposureShadows: number;
+
+    /**
+     * Color curve exposureMidtones value
+     */
+    exposureMidtones: number;
+
+    /**
+     * Color curve exposureHighlights value
+     */
+    exposureHighlights: number;
+
+}

+ 21 - 0
Viewer/src/configuration/interfaces/defaultRenderingPipelineConfiguration.ts

@@ -0,0 +1,21 @@
+import { DepthOfFieldEffectBlurLevel } from 'babylonjs';
+
+export interface IDefaultRenderingPipelineConfiguration {
+    sharpenEnabled?: boolean;
+    bloomEnabled?: boolean;
+    bloomThreshold?: number;
+    depthOfFieldEnabled?: boolean;
+    depthOfFieldBlurLevel?: DepthOfFieldEffectBlurLevel;
+    fxaaEnabled?: boolean;
+    imageProcessingEnabled?: boolean;
+    defaultPipelineTextureType?: number;
+    bloomScale?: number;
+    chromaticAberrationEnabled?: boolean;
+    grainEnabled?: boolean;
+    bloomKernel?: number;
+    hardwareScaleLevel?: number;
+    bloomWeight?: number;
+    hdr?: boolean;
+    samples?: number;
+    glowLayerEnabled?: boolean;
+}

+ 20 - 0
Viewer/src/configuration/interfaces/groundConfiguration.ts

@@ -0,0 +1,20 @@
+export interface IGroundConfiguration {
+    size?: number;
+    receiveShadows?: boolean;
+    shadowLevel?: number;
+    shadowOnly?: boolean; // deprecated
+    mirror?: boolean | {
+        sizeRatio?: number;
+        blurKernel?: number;
+        amount?: number;
+        fresnelWeight?: number;
+        fallOffDistance?: number;
+        textureType?: number;
+    };
+    texture?: string;
+    color?: { r: number, g: number, b: number };
+    opacity?: number;
+    material?: {
+        [propName: string]: any;
+    };
+}

+ 38 - 0
Viewer/src/configuration/interfaces/imageProcessingConfiguration.ts

@@ -0,0 +1,38 @@
+export interface IImageProcessingConfiguration {
+    colorGradingEnabled?: boolean;
+    colorCurvesEnabled?: boolean;
+    colorCurves?: {
+        globalHue?: number;
+        globalDensity?: number;
+        globalSaturation?: number;
+        globalExposure?: number;
+        highlightsHue?: number;
+        highlightsDensity?: number;
+        highlightsSaturation?: number;
+        highlightsExposure?: number;
+        midtonesHue?: number;
+        midtonesDensity?: number;
+        midtonesSaturation?: number;
+        midtonesExposure?: number;
+        shadowsHue?: number;
+        shadowsDensity?: number;
+        shadowsSaturation?: number;
+        shadowsExposure?: number;
+    };
+    colorGradingWithGreenDepth?: boolean;
+    colorGradingBGR?: boolean;
+    exposure?: number;
+    toneMappingEnabled?: boolean;
+    contrast?: number;
+    vignetteEnabled?: boolean;
+    vignetteStretch?: number;
+    vignetteCentreX?: number;
+    vignetteCentreY?: number;
+    vignetteWeight?: number;
+    vignetteColor?: { r: number, g: number, b: number, a?: number };
+    vignetteCameraFov?: number;
+    vignetteBlendMode?: number;
+    vignetteM?: boolean;
+    applyByPostProcess?: boolean;
+    isEnabled?: boolean;
+}

+ 13 - 0
Viewer/src/configuration/interfaces/index.ts

@@ -0,0 +1,13 @@
+export * from './cameraConfiguration';
+export * from './colorGradingConfiguration';
+export * from './defaultRenderingPipelineConfiguration';
+export * from './groundConfiguration';
+export * from './imageProcessingConfiguration';
+export * from './lightConfiguration';
+export * from './modelAnimationConfiguration';
+export * from './modelConfiguration';
+export * from './observersConfiguration';
+export * from './sceneConfiguration';
+export * from './sceneOptimizerConfiguration';
+export * from './skyboxConfiguration';
+export * from './templateConfiguration';

+ 42 - 0
Viewer/src/configuration/interfaces/lightConfiguration.ts

@@ -0,0 +1,42 @@
+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;
+    intensityMode?: number;
+    radius?: number;
+    shadownEnabled?: boolean; // only on specific lights!
+    shadowConfig?: {
+        useBlurExponentialShadowMap?: boolean;
+        useBlurCloseExponentialShadowMap?: boolean;
+        useKernelBlur?: boolean;
+        blurKernel?: number;
+        blurScale?: number;
+        minZ?: number;
+        maxZ?: number;
+        frustumSize?: number;
+        angleScale?: number;
+        frustumEdgeFalloff?: number;
+        [propName: string]: any;
+    };
+    spotAngle?: number;
+    shadowFieldOfView?: number;
+    shadowBufferSize?: number;
+    shadowFrustumSize?: number;
+    shadowMinZ?: number;
+    shadowMaxZ?: number;
+    [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;
+        };
+    };
+}

+ 29 - 0
Viewer/src/configuration/interfaces/modelAnimationConfiguration.ts

@@ -0,0 +1,29 @@
+/**
+ * Defines an animation to be applied to a model (translation, scale or rotation).
+ */
+export interface IModelAnimationConfiguration {
+    /**
+     * Time of animation, in seconds
+     */
+    time?: number;
+
+    /**
+     * Scale to apply
+     */
+    scaling?: {
+        x: number;
+        y: number;
+        z: number;
+    };
+
+    /**
+     * Easing function to apply
+     */
+    easingFunction?: number;
+
+    /**
+     * An Easing mode to apply to the easing function
+     * See BABYLON.EasingFunction
+     */
+    easingMode?: number;
+}

+ 63 - 0
Viewer/src/configuration/interfaces/modelConfiguration.ts

@@ -0,0 +1,63 @@
+import { IModelAnimationConfiguration } from "./modelAnimationConfiguration";
+
+export interface IModelConfiguration {
+    id?: string;
+    url?: string;
+    root?: string; //optional
+    file?: string | File; // is a file being loaded? root and url ignored
+    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.
+
+    castShadow?: boolean;
+    receiveShadows?: boolean;
+    normalize?: boolean | {
+        center?: boolean;
+        unitSize?: boolean;
+        parentIndex?: number;
+    }; // should the model be scaled to unit-size
+
+    title?: string;
+    subtitle?: string;
+    thumbnail?: string; // URL or data-url
+
+    animation?: {
+        autoStart?: boolean | string;
+        playOnce?: boolean;
+        autoStartIndex?: number;
+    }
+
+    entryAnimation?: IModelAnimationConfiguration;
+    exitAnimation?: IModelAnimationConfiguration;
+
+    material?: {
+        directEnabled?: boolean;
+        directIntensity?: number;
+        emissiveIntensity?: number;
+        environmentIntensity?: number;
+        [propName: string]: any;
+    }
+
+    /** 
+     * Rotation offset axis definition
+     */
+    rotationOffsetAxis?: {
+        x: number;
+        y: number;
+        z: number;
+    };
+
+    /**
+     * the offset angle
+     */
+    rotationOffsetAngle?: number;
+
+    loaderConfiguration?: {
+        maxLODsToLoad?: number;
+        progressiveLoading?: boolean;
+    }
+
+    // [propName: string]: any; // further configuration, like title and creator
+}

+ 5 - 0
Viewer/src/configuration/interfaces/observersConfiguration.ts

@@ -0,0 +1,5 @@
+export interface IObserversConfiguration {
+    onEngineInit?: string;
+    onSceneInit?: string;
+    onModelLoaded?: string;
+}

+ 40 - 0
Viewer/src/configuration/interfaces/sceneConfiguration.ts

@@ -0,0 +1,40 @@
+import { IImageProcessingConfiguration } from "./imageProcessingConfiguration";
+import { IColorGradingConfiguration } from "./colorGradingConfiguration";
+import { IGlowLayerOptions } from "babylonjs";
+
+export interface ISceneConfiguration {
+    debug?: boolean;
+    clearColor?: { r: number, g: number, b: number, a: number };
+    mainColor?: { r?: number, g?: number, b?: number };
+    imageProcessingConfiguration?: IImageProcessingConfiguration;
+    environmentTexture?: string;
+    colorGrading?: IColorGradingConfiguration;
+    environmentRotationY?: number;
+    /**
+     * Deprecated, please use default rendering pipeline
+     */
+    glow?: boolean | IGlowLayerOptions;
+    disableHdr?: boolean;
+    renderInBackground?: boolean;
+    disableCameraControl?: boolean;
+    animationPropertiesOverride?: {
+        [propName: string]: any;
+    };
+    defaultMaterial?: {
+        materialType: "standard" | "pbr";
+        [propName: string]: any;
+    };
+    flags?: {
+        shadowsEnabled?: boolean;
+        particlesEnabled?: boolean;
+        collisionsEnabled?: boolean;
+        lightsEnabled?: boolean;
+        texturesEnabled?: boolean;
+        lensFlaresEnabled?: boolean;
+        proceduralTexturesEnabled?: boolean;
+        renderTargetsEnabled?: boolean;
+        spritesEnabled?: boolean;
+        skeletonsEnabled?: boolean;
+        audioEnabled?: boolean;
+    }
+}

+ 24 - 0
Viewer/src/configuration/interfaces/sceneOptimizerConfiguration.ts

@@ -0,0 +1,24 @@
+export interface ISceneOptimizerConfiguration {
+    targetFrameRate?: number;
+    trackerDuration?: number;
+    autoGeneratePriorities?: boolean;
+    improvementMode?: boolean;
+    degradation?: string; // low, moderate, high
+    types?: {
+        texture?: ISceneOptimizerParameters;
+        hardwareScaling?: ISceneOptimizerParameters;
+        shadow?: ISceneOptimizerParameters;
+        postProcess?: ISceneOptimizerParameters;
+        lensFlare?: ISceneOptimizerParameters;
+        particles?: ISceneOptimizerParameters;
+        renderTarget?: ISceneOptimizerParameters;
+        mergeMeshes?: ISceneOptimizerParameters;
+    }
+    custom?: string;
+}
+
+export interface ISceneOptimizerParameters {
+    priority?: number;
+    maximumSize?: number;
+    step?: number;
+}

+ 19 - 0
Viewer/src/configuration/interfaces/skyboxConfiguration.ts

@@ -0,0 +1,19 @@
+import { IImageProcessingConfiguration } from "./imageProcessingConfiguration";
+
+export interface ISkyboxConfiguration {
+    cubeTexture?: {
+        noMipMap?: boolean;
+        gammaSpace?: boolean;
+        url?: string | Array<string>;
+    };
+    color?: { r: number, g: number, b: number };
+    pbr?: boolean; // deprecated
+    scale?: number;
+    blur?: number; // deprecated
+    material?: {
+        imageProcessingConfiguration?: IImageProcessingConfiguration;
+        [propName: string]: any;
+    };
+    infiniteDistance?: boolean;
+
+}

+ 46 - 0
Viewer/src/configuration/interfaces/templateConfiguration.ts

@@ -0,0 +1,46 @@
+/**
+ * A single template configuration object
+ */
+export interface ITemplateConfiguration {
+    /**
+     * can be either the id of the template's html element or a URL.
+     * See - http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+     */
+    location?: string; // #template-id OR http://example.com/loading.html
+    /**
+     * If no location is provided you can provide here the raw html of this template.
+     * See http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
+     */
+    html?: string; // raw html string
+    id?: string;
+    /**
+     * Parameters that will be delivered to the template and will render it accordingly.
+     */
+    params?: { [key: string]: string | number | boolean | object };
+    /**
+     * Events to attach to this template.
+     * event name is the key. the value can either be a boolean (attach to the parent element)
+     * or a map of html id elements.
+     * 
+     * See - http://doc.babylonjs.com/extensions/the_templating_system#event-binding
+     */
+    events?: {
+        // pointer events
+        pointerdown?: boolean | { [id: string]: boolean; };
+        pointerup?: boolean | { [id: string]: boolean; };
+        pointermove?: boolean | { [id: string]: boolean; };
+        pointerover?: boolean | { [id: string]: boolean; };
+        pointerout?: boolean | { [id: string]: boolean; };
+        pointerenter?: boolean | { [id: string]: boolean; };
+        pointerleave?: boolean | { [id: string]: boolean; };
+        pointercancel?: boolean | { [id: string]: boolean; };
+        //click, just in case
+        click?: boolean | { [id: string]: boolean; };
+        // drag and drop
+        dragstart?: boolean | { [id: string]: boolean; };
+        drop?: boolean | { [id: string]: boolean; };
+
+
+        [key: string]: boolean | { [id: string]: boolean; } | undefined;
+    }
+}

+ 1 - 1
Viewer/src/configuration/loader.ts

@@ -3,7 +3,7 @@ import { ViewerConfiguration } from './configuration';
 import { getConfigurationType } from './types';
 import { processConfigurationCompatibility } from './configurationCompatibility';
 
-import * as deepmerge from '../../assets/deepmerge.min.js';
+import { deepmerge } from '../helper/';
 import { Tools, IFileRequest } from 'babylonjs';
 
 /**

+ 1 - 1
Viewer/src/configuration/mappers.ts

@@ -1,7 +1,7 @@
 import { Tools } from 'babylonjs';
 import { ViewerConfiguration } from './configuration';
 
-import { kebabToCamel } from '../helper';
+import { kebabToCamel } from '../helper/';
 
 /**
  * This is the mapper's interface. Implement this function to create your own mapper and register it at the mapper manager

+ 1 - 1
Viewer/src/configuration/types/index.ts

@@ -4,7 +4,7 @@ import { extendedConfiguration } from './extended';
 import { ViewerConfiguration } from '../configuration';
 import { shadowDirectionalLightConfiguration, shadowSpotlLightConfiguration } from './shadowLight';
 import { environmentMapConfiguration } from './environmentMap';
-import * as deepmerge from '../../../assets/deepmerge.min.js';
+import { deepmerge } from '../../helper/';
 
 /**
  * Get the configuration type you need to use as the base for your viewer.

+ 1 - 0
Viewer/src/externalModules.d.ts

@@ -1,3 +1,4 @@
+/// <reference path="../../dist/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../dist/preview release/loaders/babylonjs.loaders.d.ts"/>
 
 declare module "babylonjs-loaders" {

+ 11 - 0
Viewer/src/helper/deepmerge.d.ts

@@ -0,0 +1,11 @@
+interface Ideepmerge {
+    (a: any, b: any, options?: any): any;
+    all(array: Array<any>, options?: any): any;
+    default: Ideepmerge;
+}
+declare const deepmerge: Ideepmerge;
+
+declare module "deepmerge" {
+    export default deepmerge;
+    export = deepmerge;
+}

+ 5 - 0
Viewer/src/helper.ts

@@ -1,3 +1,8 @@
+import * as deepmerge from 'deepmerge';
+
+let expDm = deepmerge['default'];
+export { expDm as deepmerge };
+
 /**
  * Is the provided string a URL?
  * 

+ 2 - 3
Viewer/src/index.ts

@@ -1,4 +1,3 @@
-/// <reference path="../../dist/babylon.glTF2Interface.d.ts"/>
 import { mapperManager } from './configuration/mappers';
 import { viewerGlobals } from './configuration/globals';
 import { viewerManager } from './viewer/viewerManager';
@@ -20,7 +19,7 @@ import * as BABYLON from 'babylonjs';
 
 // load needed modules.
 import 'babylonjs-loaders';
-import 'pep';
+import 'pepjs';
 
 import { initListeners, InitTags } from './initializer';
 
@@ -40,7 +39,7 @@ function disposeAll() {
     telemetryManager.dispose();
 }
 
-const Version = BABYLON.Engine.Version;
+const Version = viewerGlobals.version;
 
 console.log("Babylon.js viewer (v" + Version + ")");
 

+ 17 - 15
Viewer/src/labs/texture.ts

@@ -1,3 +1,5 @@
+import { Scene, CubeTexture, InternalTexture, Scalar, BaseTexture, Texture } from "babylonjs";
+
 /**
  * WebGL Pixel Formats
  */
@@ -181,7 +183,7 @@ export class TextureUtils {
      * @param singleLod Specifies that the texture will be a singleLod (for environment)
      * @return Babylon cube texture
      */
-    public static GetBabylonCubeTexture(scene: BABYLON.Scene, textureCube: TextureCube, automaticMipmaps: boolean, environment = false, singleLod = false): BABYLON.CubeTexture {
+    public static GetBabylonCubeTexture(scene: Scene, textureCube: TextureCube, automaticMipmaps: boolean, environment = false, singleLod = false): CubeTexture {
         if (!textureCube) throw new Error("no texture cube provided");
 
         var parameters: SamplingParameters;
@@ -199,12 +201,12 @@ export class TextureUtils {
 
         let key = TextureUtils.BabylonTextureKeyPrefix + parameters.magFilter + '' + parameters.minFilter + '' + parameters.wrapS + '' + parameters.wrapT;
 
-        let babylonTexture: BABYLON.CubeTexture = (<any>textureCube)[key];
+        let babylonTexture: CubeTexture = (<any>textureCube)[key];
 
         if (!babylonTexture) {
 
             //initialize babylon texture
-            babylonTexture = new BABYLON.CubeTexture('', scene);
+            babylonTexture = new CubeTexture('', scene);
             if (environment) {
                 babylonTexture.lodGenerationOffset = TextureUtils.EnvironmentLODOffset;
                 babylonTexture.lodGenerationScale = TextureUtils.EnvironmentLODScale;
@@ -212,7 +214,7 @@ export class TextureUtils {
 
             babylonTexture.gammaSpace = false;
 
-            let internalTexture = new BABYLON.InternalTexture(scene.getEngine(), BABYLON.InternalTexture.DATASOURCE_CUBERAW);
+            let internalTexture = new InternalTexture(scene.getEngine(), InternalTexture.DATASOURCE_CUBERAW);
             let glTexture = internalTexture._webGLTexture;
             //babylon properties
             internalTexture.isCube = true;
@@ -265,7 +267,7 @@ export class TextureUtils {
                         const mipSlices = 3;
                         for (let i = 0; i < mipSlices; i++) {
                             let lodKey = TextureUtils.BabylonTextureKeyPrefix + 'lod' + i;
-                            let lod: BABYLON.CubeTexture = (<any>textureCube)[lodKey];
+                            let lod: CubeTexture = (<any>textureCube)[lodKey];
 
                             //initialize lod texture if it doesn't already exist
                             if (lod == null && textureCube.Width) {
@@ -276,7 +278,7 @@ export class TextureUtils {
                                 let alphaG = roughness * roughness + kMinimumVariance;
                                 let microsurfaceAverageSlopeTexels = alphaG * textureCube.Width;
 
-                                let environmentSpecularLOD = TextureUtils.EnvironmentLODScale * (BABYLON.Scalar.Log2(microsurfaceAverageSlopeTexels)) + TextureUtils.EnvironmentLODOffset;
+                                let environmentSpecularLOD = TextureUtils.EnvironmentLODScale * (Scalar.Log2(microsurfaceAverageSlopeTexels)) + TextureUtils.EnvironmentLODOffset;
 
                                 let maxLODIndex = textureCube.source.length - 1;
                                 let mipmapIndex = Math.min(Math.max(Math.round(environmentSpecularLOD), 0), maxLODIndex);
@@ -336,7 +338,7 @@ export class TextureUtils {
      * @param babylonTexture Babylon texture to apply texture to (requires the Babylon texture has an initialize _texture field)
      * @param parameters Spectre SamplingParameters to apply
      */
-    public static ApplySamplingParameters(babylonTexture: BABYLON.BaseTexture, parameters: SamplingParameters) {
+    public static ApplySamplingParameters(babylonTexture: BaseTexture, parameters: SamplingParameters) {
         let scene = babylonTexture.getScene();
         if (!scene) return;
         let gl = (<any>(scene.getEngine()))._gl;
@@ -355,17 +357,17 @@ export class TextureUtils {
 
         //set babylon wrap modes from sampling parameter
         switch (parameters.wrapS) {
-            case TextureWrapMode.REPEAT: babylonTexture.wrapU = BABYLON.Texture.WRAP_ADDRESSMODE; break;
-            case TextureWrapMode.CLAMP_TO_EDGE: babylonTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE; break;
-            case TextureWrapMode.MIRRORED_REPEAT: babylonTexture.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE; break;
-            default: babylonTexture.wrapU = BABYLON.Texture.CLAMP_ADDRESSMODE;
+            case TextureWrapMode.REPEAT: babylonTexture.wrapU = Texture.WRAP_ADDRESSMODE; break;
+            case TextureWrapMode.CLAMP_TO_EDGE: babylonTexture.wrapU = Texture.CLAMP_ADDRESSMODE; break;
+            case TextureWrapMode.MIRRORED_REPEAT: babylonTexture.wrapU = Texture.MIRROR_ADDRESSMODE; break;
+            default: babylonTexture.wrapU = Texture.CLAMP_ADDRESSMODE;
         }
 
         switch (parameters.wrapT) {
-            case TextureWrapMode.REPEAT: babylonTexture.wrapV = BABYLON.Texture.WRAP_ADDRESSMODE; break;
-            case TextureWrapMode.CLAMP_TO_EDGE: babylonTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE; break;
-            case TextureWrapMode.MIRRORED_REPEAT: babylonTexture.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE; break;
-            default: babylonTexture.wrapV = BABYLON.Texture.CLAMP_ADDRESSMODE;
+            case TextureWrapMode.REPEAT: babylonTexture.wrapV = Texture.WRAP_ADDRESSMODE; break;
+            case TextureWrapMode.CLAMP_TO_EDGE: babylonTexture.wrapV = Texture.CLAMP_ADDRESSMODE; break;
+            case TextureWrapMode.MIRRORED_REPEAT: babylonTexture.wrapV = Texture.MIRROR_ADDRESSMODE; break;
+            default: babylonTexture.wrapV = Texture.CLAMP_ADDRESSMODE;
         }
 
         if (parameters.maxAnisotropy != null && parameters.maxAnisotropy > 1) {

+ 12 - 14
Viewer/src/labs/viewerLabs.ts

@@ -1,8 +1,6 @@
 import { PBREnvironment, EnvironmentDeserializer } from "./environmentSerializer";
-import { SceneManager } from '../viewer/sceneManager';
 
-import { Tools, Quaternion, ShadowLight, Vector3, Axis, Matrix, SphericalPolynomial, Tmp } from 'babylonjs';
-import { ViewerConfiguration } from "../configuration/configuration";
+import { Tools, Quaternion, ShadowLight, Vector3, Axis, Matrix, SphericalPolynomial, Tmp, Scene } from 'babylonjs';
 import { TextureUtils } from "./texture";
 
 /**
@@ -12,7 +10,7 @@ import { TextureUtils } from "./texture";
  */
 export class ViewerLabs {
 
-    constructor(private _sceneManager: SceneManager) { }
+    constructor(private _scene: Scene) { }
 
     public assetsRootURL: string;
     public environment: PBREnvironment = {
@@ -63,7 +61,7 @@ export class ViewerLabs {
             if (onSuccess) onSuccess(this.environment);
         } else if (typeof data === 'string') {
             let url = this.getAssetUrl(data);
-            this._sceneManager.scene._loadFile(
+            this._scene._loadFile(
                 url,
                 (arrayBuffer: ArrayBuffer) => {
                     this.environment = EnvironmentDeserializer.Parse(arrayBuffer);
@@ -98,15 +96,15 @@ export class ViewerLabs {
         // Add env texture to the scene.
         if (this.environment.specularTexture) {
             // IE crashes when disposing the old texture and setting a new one
-            if (!this._sceneManager.scene.environmentTexture) {
-                this._sceneManager.scene.environmentTexture = TextureUtils.GetBabylonCubeTexture(this._sceneManager.scene, this.environment.specularTexture, false, true);
+            if (!this._scene.environmentTexture) {
+                this._scene.environmentTexture = TextureUtils.GetBabylonCubeTexture(this._scene, this.environment.specularTexture, false, true);
             }
-            if (this._sceneManager.scene.environmentTexture) {
-                this._sceneManager.scene.environmentTexture.level = this.environment.textureIntensityScale;
-                this._sceneManager.scene.environmentTexture.invertZ = true;
-                this._sceneManager.scene.environmentTexture.lodLevelInAlpha = true;
+            if (this._scene.environmentTexture) {
+                this._scene.environmentTexture.level = this.environment.textureIntensityScale;
+                this._scene.environmentTexture.invertZ = true;
+                this._scene.environmentTexture.lodLevelInAlpha = true;
 
-                var poly = this._sceneManager.scene.environmentTexture.sphericalPolynomial || new SphericalPolynomial();
+                var poly = this._scene.environmentTexture.sphericalPolynomial || new SphericalPolynomial();
                 poly.x = this.environment.irradiancePolynomialCoefficients.x;
                 poly.y = this.environment.irradiancePolynomialCoefficients.y;
                 poly.z = this.environment.irradiancePolynomialCoefficients.z;
@@ -116,10 +114,10 @@ export class ViewerLabs {
                 poly.yz = this.environment.irradiancePolynomialCoefficients.yz;
                 poly.zx = this.environment.irradiancePolynomialCoefficients.zx;
                 poly.zz = this.environment.irradiancePolynomialCoefficients.zz;
-                this._sceneManager.scene.environmentTexture.sphericalPolynomial = poly;
+                this._scene.environmentTexture.sphericalPolynomial = poly;
 
                 //set orientation
-                Matrix.FromQuaternionToRef(rotatquatRotationionY, this._sceneManager.scene.environmentTexture.getReflectionTextureMatrix());
+                Matrix.FromQuaternionToRef(rotatquatRotationionY, this._scene.environmentTexture.getReflectionTextureMatrix());
             }
         }
     }

+ 17 - 10
Viewer/src/loader/modelLoader.ts

@@ -1,11 +1,11 @@
-import { AbstractViewer } from "../viewer/viewer";
 import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, Tools, SceneLoader, Tags } from "babylonjs";
 import { GLTFFileLoader, GLTFLoaderAnimationStartMode } from "babylonjs-loaders";
-import { IModelConfiguration } from "../configuration/configuration";
+import { ViewerConfiguration } from "../configuration/configuration";
+import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
 import { ViewerModel, ModelState } from "../model/viewerModel";
-import { ILoaderPlugin } from './plugins/loaderPlugin';
-import { TelemetryLoaderPlugin } from './plugins/telemetryLoaderPlugin';
-import { getLoaderPluginByName } from './plugins/';
+import { getLoaderPluginByName, TelemetryLoaderPlugin, ILoaderPlugin } from './plugins/';
+import { ObservablesManager } from "../managers/observablesManager";
+import { ConfigurationContainer } from "../configuration/configurationContainer";
 
 /**
  * An instance of the class is in charge of loading the model correctly.
@@ -26,7 +26,7 @@ export class ModelLoader {
      * Create a new Model loader
      * @param _viewer the viewer using this model loader
      */
-    constructor(private _viewer: AbstractViewer) {
+    constructor(private _observablesManager: ObservablesManager, private _configurationContainer?: ConfigurationContainer) {
         this._loaders = [];
         this._loadId = 0;
         this._plugins = [];
@@ -58,7 +58,7 @@ export class ModelLoader {
      */
     public load(modelConfiguration: IModelConfiguration): ViewerModel {
 
-        const model = new ViewerModel(this._viewer, modelConfiguration);
+        const model = new ViewerModel(this._observablesManager, modelConfiguration);
 
         model.loadId = this._loadId++;
 
@@ -69,6 +69,7 @@ export class ModelLoader {
         }
 
         let base: string;
+
         let filename: any;
         if (modelConfiguration.file) {
             base = "file:";
@@ -82,7 +83,9 @@ export class ModelLoader {
 
         let plugin = modelConfiguration.loader;
 
-        model.loader = SceneLoader.ImportMesh(undefined, base, filename, this._viewer.sceneManager.scene, (meshes, particleSystems, skeletons, animationGroups) => {
+        let scene = model.rootMesh.getScene();
+
+        model.loader = SceneLoader.ImportMesh(undefined, base, filename, scene, (meshes, particleSystems, skeletons, animationGroups) => {
             meshes.forEach(mesh => {
                 Tags.AddTagsTo(mesh, "viewerMesh");
                 model.addMesh(mesh);
@@ -95,7 +98,7 @@ export class ModelLoader {
             }
 
             this._checkAndRun("onLoaded", model);
-            this._viewer.sceneManager.scene.executeWhenReady(() => {
+            scene.executeWhenReady(() => {
                 model.onLoadedObservable.notifyObservers(model);
             });
         }, (progressEvent) => {
@@ -119,7 +122,11 @@ export class ModelLoader {
                 };
             }
             // if ground is set to "mirror":
-            if (this._viewer.configuration.ground && typeof this._viewer.configuration.ground === 'object' && this._viewer.configuration.ground.mirror) {
+            if (this._configurationContainer
+                && this._configurationContainer.configuration
+                && this._configurationContainer.configuration.ground
+                && typeof this._configurationContainer.configuration.ground === 'object'
+                && this._configurationContainer.configuration.ground.mirror) {
                 gltfLoader.useClipPlane = true;
             }
             Object.keys(gltfLoader).filter(name => name.indexOf('on') === 0 && name.indexOf('Observable') !== -1).forEach(functionName => {

+ 1 - 1
Viewer/src/loader/plugins/applyMaterialConfig.ts

@@ -1,6 +1,6 @@
 import { ILoaderPlugin } from "./loaderPlugin";
 import { telemetryManager } from "../../telemetryManager";
-import { ViewerModel } from "../..";
+import { ViewerModel } from "../../model/viewerModel";
 import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material } from "babylonjs";
 import { IGLTFLoaderData, GLTF2 } from "babylonjs-loaders";
 

+ 1 - 1
Viewer/src/loader/plugins/extendedMaterialLoaderPlugin.ts

@@ -1,6 +1,6 @@
 import { ILoaderPlugin } from "./loaderPlugin";
 import { telemetryManager } from "../../telemetryManager";
-import { ViewerModel } from "../..";
+import { ViewerModel } from "../../model/viewerModel";
 import { Color3, Texture, BaseTexture, Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync, Material, PBRMaterial, Engine } from "babylonjs";
 
 /**

+ 13 - 0
Viewer/src/loader/plugins/index.ts

@@ -3,9 +3,12 @@ import { ILoaderPlugin } from "./loaderPlugin";
 import { MSFTLodLoaderPlugin } from './msftLodLoaderPlugin';
 import { ApplyMaterialConfigPlugin } from './applyMaterialConfig';
 import { ExtendedMaterialLoaderPlugin } from './extendedMaterialLoaderPlugin';
+import { Tools } from "babylonjs";
 
 const pluginCache: { [key: string]: ILoaderPlugin } = {};
 
+export { TelemetryLoaderPlugin, ILoaderPlugin, MSFTLodLoaderPlugin, ApplyMaterialConfigPlugin, ExtendedMaterialLoaderPlugin };
+
 /**
  * Get a loader plugin according to its name.
  * The plugin will be cached and will be reused if called for again.
@@ -31,4 +34,14 @@ export function getLoaderPluginByName(name: string) {
     }
 
     return pluginCache[name];
+}
+
+/**
+ * 
+ */
+export function addLoaderPlugin(name: string, plugin: ILoaderPlugin) {
+    if (pluginCache[name]) {
+        Tools.Warn("Overwriting plugin with the same name - " + name);
+    }
+    pluginCache[name] = plugin;
 }

+ 1 - 1
Viewer/src/loader/plugins/msftLodLoaderPlugin.ts

@@ -1,6 +1,6 @@
 import { ILoaderPlugin } from "./loaderPlugin";
 import { telemetryManager } from "../../telemetryManager";
-import { ViewerModel } from "../..";
+import { ViewerModel } from "../../model/viewerModel";
 import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
 import { IGLTFLoaderExtension, GLTF2 } from "babylonjs-loaders";
 

+ 7 - 7
Viewer/src/loader/plugins/telemetryLoaderPlugin.ts

@@ -1,6 +1,6 @@
 import { ILoaderPlugin } from "./loaderPlugin";
 import { telemetryManager } from "../../telemetryManager";
-import { ViewerModel } from "../..";
+import { ViewerModel } from "../../model/viewerModel";
 import { Tools, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
 
 
@@ -17,30 +17,30 @@ export class TelemetryLoaderPlugin implements ILoaderPlugin {
     }
 
     public onLoaded(model: ViewerModel) {
-        telemetryManager.broadcast("Model Loaded", model.getViewer(), {
+        telemetryManager.broadcast("Model Loaded", model.getViewerId(), {
             model: model,
             loadTime: Tools.Now - this._loadStart
         });
-        telemetryManager.flushWebGLErrors(this._model.getViewer());
+        telemetryManager.flushWebGLErrors(model.rootMesh.getEngine(), model.getViewerId());
     }
 
     public onError(message: string, exception: any) {
         this._loadEnd = Tools.Now;
-        telemetryManager.broadcast("Load Error", this._model.getViewer(), {
+        telemetryManager.broadcast("Load Error", this._model.getViewerId(), {
             model: this._model,
             loadTime: this._loadEnd - this._loadStart
         });
 
-        telemetryManager.flushWebGLErrors(this._model.getViewer());
+        telemetryManager.flushWebGLErrors(this._model.rootMesh.getEngine(), this._model.getViewerId());
     }
 
     public onComplete() {
         this._loadEnd = Tools.Now;
-        telemetryManager.broadcast("Load Complete", this._model.getViewer(), {
+        telemetryManager.broadcast("Load Complete", this._model.getViewerId(), {
             model: this._model,
             loadTime: this._loadEnd - this._loadStart
         });
 
-        telemetryManager.flushWebGLErrors(this._model.getViewer());
+        telemetryManager.flushWebGLErrors(this._model.rootMesh.getEngine(), this._model.getViewerId());
     }
 }

+ 77 - 0
Viewer/src/managers/observablesManager.ts

@@ -0,0 +1,77 @@
+import { Observable, Scene, Engine, SceneLoaderProgressEvent, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from "babylonjs";
+import { ViewerModel } from "../model/viewerModel";
+
+export class ObservablesManager {
+
+    /**
+     * Will notify when the scene was initialized
+     */
+    public onSceneInitObservable: Observable<Scene>;
+    /**
+     * will notify when the engine was initialized
+     */
+    public onEngineInitObservable: Observable<Engine>;
+
+    /**
+     * Will notify when a new model was added to the scene.
+     * Note that added does not neccessarily mean loaded!
+     */
+    public onModelAddedObservable: Observable<ViewerModel>;
+    /**
+     * will notify after every model load
+     */
+    public onModelLoadedObservable: Observable<ViewerModel>;
+    /**
+     * will notify when any model notify of progress
+     */
+    public onModelLoadProgressObservable: Observable<SceneLoaderProgressEvent>;
+    /**
+     * will notify when any model load failed.
+     */
+    public onModelLoadErrorObservable: Observable<{ message: string; exception: any }>;
+    /**
+     * Will notify when a model was removed from the scene;
+     */
+    public onModelRemovedObservable: Observable<ViewerModel>;
+    /**
+     * will notify when a new loader was initialized.
+     * Used mainly to know when a model starts loading.
+     */
+    public onLoaderInitObservable: Observable<ISceneLoaderPlugin | ISceneLoaderPluginAsync>;
+    /**
+     * Observers registered here will be executed when the entire load process has finished.
+     */
+    public onViewerInitDoneObservable: Observable<any>;
+
+    /**
+     * Functions added to this observable will be executed on each frame rendered.
+     */
+    public onFrameRenderedObservable: Observable<any>;
+
+    constructor() {
+        this.onSceneInitObservable = new Observable();
+        this.onEngineInitObservable = new Observable();
+        this.onModelLoadedObservable = new Observable();
+        this.onModelLoadProgressObservable = new Observable();
+        this.onModelLoadErrorObservable = new Observable();
+        this.onModelAddedObservable = new Observable();
+        this.onModelRemovedObservable = new Observable();
+        this.onViewerInitDoneObservable = new Observable();
+        this.onLoaderInitObservable = new Observable();
+        this.onFrameRenderedObservable = new Observable();
+    }
+
+    dispose() {
+        this.onSceneInitObservable.clear();
+        this.onEngineInitObservable.clear();
+        this.onModelLoadedObservable.clear();
+        this.onModelLoadProgressObservable.clear();
+        this.onModelLoadErrorObservable.clear();
+        this.onModelAddedObservable.clear();
+        this.onModelRemovedObservable.clear();
+        this.onViewerInitDoneObservable.clear();
+        this.onLoaderInitObservable.clear();
+        this.onFrameRenderedObservable.clear();
+    }
+
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 87 - 66
Viewer/src/viewer/sceneManager.ts


+ 25 - 27
Viewer/src/model/viewerModel.ts

@@ -1,11 +1,12 @@
 import { ISceneLoaderPlugin, ISceneLoaderPluginAsync, AnimationGroup, Animatable, AbstractMesh, Tools, Scene, SceneLoader, Observable, SceneLoaderProgressEvent, Tags, ParticleSystem, Skeleton, IDisposable, Nullable, Animation, Quaternion, Material, Vector3, AnimationPropertiesOverride, QuinticEase, SineEase, CircleEase, BackEase, BounceEase, CubicEase, ElasticEase, ExponentialEase, PowerEase, QuadraticEase, QuarticEase, PBRMaterial, MultiMaterial } from "babylonjs";
 import { GLTFFileLoader, GLTF2 } from "babylonjs-loaders";
-import { IModelConfiguration, IModelAnimationConfiguration } from "../configuration/configuration";
+import { IModelConfiguration } from "../configuration/interfaces/modelConfiguration";
+import { IModelAnimationConfiguration } from "../configuration/interfaces/modelAnimationConfiguration";
 import { IModelAnimation, GroupModelAnimation, AnimationPlayMode, ModelAnimationConfiguration, EasingFunction, AnimationState } from "./modelAnimation";
 
-import * as deepmerge from '../../assets/deepmerge.min.js';
-import { AbstractViewer } from "..";
-import { extendClassWithConfig } from "../helper";
+import { deepmerge, extendClassWithConfig } from '../helper/';
+import { ObservablesManager } from "../managers/observablesManager";
+import { ConfigurationContainer } from "../configuration/configurationContainer";
 
 
 /**
@@ -104,7 +105,7 @@ export class ViewerModel implements IDisposable {
 
     private _shadowsRenderedAfterLoad: boolean = false;
 
-    constructor(protected _viewer: AbstractViewer, modelConfiguration: IModelConfiguration) {
+    constructor(private _observablesManager: ObservablesManager, modelConfiguration: IModelConfiguration, private _configurationContainer?: ConfigurationContainer) {
         this.onLoadedObservable = new Observable();
         this.onLoadErrorObservable = new Observable();
         this.onLoadProgressObservable = new Observable();
@@ -113,8 +114,8 @@ export class ViewerModel implements IDisposable {
 
         this.state = ModelState.INIT;
 
-        this.rootMesh = new AbstractMesh("modelRootMesh", this._viewer.sceneManager.scene);
-        this._pivotMesh = new AbstractMesh("pivotMesh", this._viewer.sceneManager.scene);
+        this.rootMesh = new AbstractMesh("modelRootMesh");
+        this._pivotMesh = new AbstractMesh("pivotMesh");
         this._pivotMesh.parent = this.rootMesh;
         // rotate 180, gltf fun
         this._pivotMesh.rotation.y += Math.PI;
@@ -123,10 +124,9 @@ export class ViewerModel implements IDisposable {
 
         this._animations = [];
         //create a copy of the configuration to make sure it doesn't change even after it is changed in the viewer
-        this._modelConfiguration = deepmerge(this._viewer.configuration.model || {}, modelConfiguration);
+        this._modelConfiguration = deepmerge((this._configurationContainer && this._configurationContainer.configuration.model) || {}, modelConfiguration);
 
-        this._viewer.sceneManager.models.push(this);
-        this._viewer.onModelAddedObservable.notifyObservers(this);
+        if (this._observablesManager) { this._observablesManager.onModelAddedObservable.notifyObservers(this); }
 
         if (this._modelConfiguration.entryAnimation) {
             this.rootMesh.setEnabled(false);
@@ -134,7 +134,7 @@ export class ViewerModel implements IDisposable {
 
         this.onLoadedObservable.add(() => {
             this.updateConfiguration(this._modelConfiguration);
-            this._viewer.onModelLoadedObservable.notifyObservers(this);
+            if (this._observablesManager) { this._observablesManager.onModelLoadedObservable.notifyObservers(this); }
             this._initAnimations();
         });
 
@@ -155,6 +155,10 @@ export class ViewerModel implements IDisposable {
         }
     }
 
+    public getViewerId() {
+        return this._configurationContainer && this._configurationContainer.viewerId;
+    }
+
     /**
      * Is this model enabled?
      */
@@ -181,13 +185,6 @@ export class ViewerModel implements IDisposable {
     }
 
     /**
-     * Get the viewer showing this model
-     */
-    public getViewer() {
-        return this._viewer;
-    }
-
-    /**
      * Add a mesh to this model.
      * Any mesh that has no parent will be provided with the root mesh as its new parent.
      * 
@@ -244,7 +241,7 @@ export class ViewerModel implements IDisposable {
         // check if this is not a gltf loader and init the animations
         if (this.skeletons.length) {
             this.skeletons.forEach((skeleton, idx) => {
-                let ag = new AnimationGroup("animation-" + idx, this._viewer.sceneManager.scene);
+                let ag = new AnimationGroup("animation-" + idx);
                 skeleton.getAnimatables().forEach(a => {
                     if (a.animations[0]) {
                         ag.addTargetedAnimation(a.animations[0], a);
@@ -282,9 +279,10 @@ export class ViewerModel implements IDisposable {
      * @param completeCallback A function to call when the animation has completed
      */
     private _enterScene(completeCallback?: () => void): void {
+        const scene = this.rootMesh.getScene();
         let callback = () => {
             this.state = ModelState.ENTRYDONE;
-            this._viewer.sceneManager.animationBlendingEnabled = true;
+            scene.animationPropertiesOverride!.enableBlending = true;
             this._checkCompleteState();
             if (completeCallback) completeCallback();
         }
@@ -294,7 +292,7 @@ export class ViewerModel implements IDisposable {
         }
         this.rootMesh.setEnabled(true);
         // disable blending for the sake of the entry animation;
-        this._viewer.sceneManager.animationBlendingEnabled = false;
+        scene.animationPropertiesOverride!.enableBlending = false;
         this._applyAnimation(this._entryAnimation, true, callback);
     }
 
@@ -553,8 +551,8 @@ export class ViewerModel implements IDisposable {
             if (this._modelConfiguration.material.directEnabled !== undefined) {
                 material.disableLighting = !this._modelConfiguration.material.directEnabled;
             }
-            if (this._viewer.sceneManager.reflectionColor) {
-                material.reflectionColor = this._viewer.sceneManager.reflectionColor;
+            if (this._configurationContainer && this._configurationContainer.reflectionColor) {
+                material.reflectionColor = this._configurationContainer.reflectionColor;
             }
         }
         else if (material instanceof MultiMaterial) {
@@ -631,8 +629,8 @@ export class ViewerModel implements IDisposable {
 
         this.rootMesh.animations = animations;
 
-        if (this._viewer.sceneManager.scene.beginAnimation) {
-            let animatable: Animatable = this._viewer.sceneManager.scene.beginAnimation(this.rootMesh, 0, this._frameRate * duration, false, 1, () => {
+        if (this.rootMesh.getScene().beginAnimation) {
+            let animatable: Animatable = this.rootMesh.getScene().beginAnimation(this.rootMesh, 0, this._frameRate * duration, false, 1, () => {
                 if (onAnimationEnd) {
                     onAnimationEnd();
                 }
@@ -733,10 +731,10 @@ export class ViewerModel implements IDisposable {
      */
     public remove() {
         this.stopAllAnimations();
-        this._viewer.sceneManager.models.splice(this._viewer.sceneManager.models.indexOf(this), 1);
+
         // hide it
         this.rootMesh.isVisible = false;
-        this._viewer.onModelRemovedObservable.notifyObservers(this);
+        if (this._observablesManager) { this._observablesManager.onModelRemovedObservable.notifyObservers(this); }
     }
 
     /**

+ 42 - 42
Viewer/src/optimizer/custom/extended.ts

@@ -1,52 +1,52 @@
-import { AbstractViewer } from '../../viewer/viewer';
-import { Scalar, DefaultRenderingPipeline } from 'babylonjs';
+import { Scalar, DefaultRenderingPipeline, Scene } from 'babylonjs';
+import { SceneManager } from '../../managers/sceneManager';
 
 /**
  * A custom upgrade-oriented function configuration for the scene optimizer.
  * 
  * @param viewer the viewer to optimize
  */
-export function extendedUpgrade(viewer: AbstractViewer): boolean {
-    let defaultPipeline = <DefaultRenderingPipeline>viewer.sceneManager.defaultRenderingPipeline;
+export function extendedUpgrade(sceneManager: SceneManager): boolean {
+    let defaultPipeline = <DefaultRenderingPipeline>sceneManager.defaultRenderingPipeline;
     // if (!this.Scene.BackgroundHelper) {
     // 	this.Scene.EngineScene.autoClear = false;
     // this.Scene.BackgroundHelper = true;
     // Would require a dedicated clear color;
     // return false;
     // }
-    if (viewer.engine.getHardwareScalingLevel() > 1) {
-        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() - 0.25, 0, 1);
-        viewer.engine.setHardwareScalingLevel(scaling);
+    if (sceneManager.scene.getEngine().getHardwareScalingLevel() > 1) {
+        let scaling = Scalar.Clamp(sceneManager.scene.getEngine().getHardwareScalingLevel() - 0.25, 0, 1);
+        sceneManager.scene.getEngine().setHardwareScalingLevel(scaling);
         return false;
     }
-    if (!viewer.sceneManager.scene.postProcessesEnabled) {
-        viewer.sceneManager.scene.postProcessesEnabled = true;
+    if (!sceneManager.scene.postProcessesEnabled) {
+        sceneManager.scene.postProcessesEnabled = true;
         return false;
     }
-    if (!viewer.sceneManager.groundEnabled) {
-        viewer.sceneManager.groundEnabled = true;
+    if (!sceneManager.groundEnabled) {
+        sceneManager.groundEnabled = true;
         return false;
     }
-    if (defaultPipeline && !viewer.sceneManager.fxaaEnabled) {
-        viewer.sceneManager.fxaaEnabled = true
+    if (defaultPipeline && !sceneManager.fxaaEnabled) {
+        sceneManager.fxaaEnabled = true
         return false;
     }
     var hardwareScalingLevel = Math.max(1 / 2, 1 / (window.devicePixelRatio || 2));
-    if (viewer.engine.getHardwareScalingLevel() > hardwareScalingLevel) {
-        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() - 0.25, 0, hardwareScalingLevel);
-        viewer.engine.setHardwareScalingLevel(scaling);
+    if (sceneManager.scene.getEngine().getHardwareScalingLevel() > hardwareScalingLevel) {
+        let scaling = Scalar.Clamp(sceneManager.scene.getEngine().getHardwareScalingLevel() - 0.25, 0, hardwareScalingLevel);
+        sceneManager.scene.getEngine().setHardwareScalingLevel(scaling);
         return false;
     }
-    if (!viewer.sceneManager.processShadows) {
-        viewer.sceneManager.processShadows = true;
+    if (!sceneManager.processShadows) {
+        sceneManager.processShadows = true;
         return false;
     }
-    if (defaultPipeline && !viewer.sceneManager.bloomEnabled) {
-        viewer.sceneManager.bloomEnabled = true
+    if (defaultPipeline && !sceneManager.bloomEnabled) {
+        sceneManager.bloomEnabled = true
         return false;
     }
-    if (!viewer.sceneManager.groundMirrorEnabled) {
-        viewer.sceneManager.groundMirrorEnabled = true;
+    if (!sceneManager.groundMirrorEnabled) {
+        sceneManager.groundMirrorEnabled = true;
         return false;
     }
     return true;
@@ -57,41 +57,41 @@ export function extendedUpgrade(viewer: AbstractViewer): boolean {
  * 
  * @param viewer the viewer to optimize
  */
-export function extendedDegrade(viewer: AbstractViewer): boolean {
-    let defaultPipeline = <DefaultRenderingPipeline>viewer.sceneManager.defaultRenderingPipeline;
+export function extendedDegrade(sceneManager: SceneManager): boolean {
+    let defaultPipeline = <DefaultRenderingPipeline>sceneManager.defaultRenderingPipeline;
 
-    if (viewer.sceneManager.groundMirrorEnabled) {
-        viewer.sceneManager.groundMirrorEnabled = false;
+    if (sceneManager.groundMirrorEnabled) {
+        sceneManager.groundMirrorEnabled = false;
         return false;
     }
-    if (defaultPipeline && viewer.sceneManager.bloomEnabled) {
-        viewer.sceneManager.bloomEnabled = false;
+    if (defaultPipeline && sceneManager.bloomEnabled) {
+        sceneManager.bloomEnabled = false;
         return false;
     }
-    if (viewer.sceneManager.processShadows) {
-        viewer.sceneManager.processShadows = false;
+    if (sceneManager.processShadows) {
+        sceneManager.processShadows = false;
         return false;
     }
-    if (viewer.engine.getHardwareScalingLevel() < 1) {
-        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() + 0.25, 0, 1);
-        viewer.engine.setHardwareScalingLevel(scaling);
+    if (sceneManager.scene.getEngine().getHardwareScalingLevel() < 1) {
+        let scaling = Scalar.Clamp(sceneManager.scene.getEngine().getHardwareScalingLevel() + 0.25, 0, 1);
+        sceneManager.scene.getEngine().setHardwareScalingLevel(scaling);
         return false;
     }
-    if (defaultPipeline && viewer.sceneManager.fxaaEnabled) {
-        viewer.sceneManager.fxaaEnabled = false;
+    if (defaultPipeline && sceneManager.fxaaEnabled) {
+        sceneManager.fxaaEnabled = false;
         return false;
     }
-    if (viewer.sceneManager.groundEnabled) {
-        viewer.sceneManager.groundEnabled = false;
+    if (sceneManager.groundEnabled) {
+        sceneManager.groundEnabled = false;
         return false;
     }
-    if (viewer.sceneManager.scene.postProcessesEnabled) {
-        viewer.sceneManager.scene.postProcessesEnabled = false;
+    if (sceneManager.scene.postProcessesEnabled) {
+        sceneManager.scene.postProcessesEnabled = false;
         return false;
     }
-    if (viewer.engine.getHardwareScalingLevel() < 1.25) {
-        let scaling = Scalar.Clamp(viewer.engine.getHardwareScalingLevel() + 0.25, 0, 1.25);
-        viewer.engine.setHardwareScalingLevel(scaling);
+    if (sceneManager.scene.getEngine().getHardwareScalingLevel() < 1.25) {
+        let scaling = Scalar.Clamp(sceneManager.scene.getEngine().getHardwareScalingLevel() + 0.25, 0, 1.25);
+        sceneManager.scene.getEngine().setHardwareScalingLevel(scaling);
         return false;
     }
     // if (this.Scene.BackgroundHelper) {

+ 2 - 2
Viewer/src/optimizer/custom/index.ts

@@ -1,7 +1,7 @@
-import { AbstractViewer } from "../../viewer/viewer";
 import { extendedUpgrade, extendedDegrade } from "./extended";
+import { SceneManager } from "../../managers/sceneManager";
 
-const cache: { [key: string]: (viewer: AbstractViewer) => boolean } = {};
+const cache: { [key: string]: (sceneManager: SceneManager) => boolean } = {};
 
 /**
  * 

+ 6 - 8
Viewer/src/telemetryManager.ts

@@ -1,5 +1,4 @@
 import { Engine, Observable } from "babylonjs";
-import { AbstractViewer } from "./viewer/viewer";
 
 /**
  * The data structure of a telemetry event.
@@ -9,7 +8,7 @@ export interface TelemetryData {
     session: string;
     date: Date;
     now: number;
-    viewer?: AbstractViewer
+    viewerId?: string;
     detail: any;
 }
 
@@ -22,7 +21,7 @@ export class TelemetryManager {
 
     private _currentSessionId: string;
 
-    private _event: (event: string, viewer: AbstractViewer, details?: any) => void = this._eventEnabled;
+    private _event: (event: string, viewerId?: string, details?: any) => void = this._eventEnabled;
 
     /**
      * Receives a telemetry event
@@ -37,8 +36,7 @@ export class TelemetryManager {
      * Log a Telemetry event for errors raised on the WebGL context.
      * @param engine The Babylon engine with the WebGL context.
      */
-    public flushWebGLErrors(viewer: AbstractViewer) {
-        const engine = viewer.engine;
+    public flushWebGLErrors(engine: Engine, viewerId?: string) {
         if (!engine) {
             return;
         }
@@ -51,7 +49,7 @@ export class TelemetryManager {
                 if (error === gl.NO_ERROR) {
                     logErrors = false;
                 } else {
-                    this.broadcast("WebGL Error", viewer, { error: error });
+                    this.broadcast("WebGL Error", viewerId, { error: error });
                 }
             } else {
                 logErrors = false;
@@ -83,9 +81,9 @@ export class TelemetryManager {
      * @param event - The name of the Telemetry event
      * @param details An additional value, or an object containing a list of property/value pairs
      */
-    private _eventEnabled(event: string, viewer?: AbstractViewer, details?: any): void {
+    private _eventEnabled(event: string, viewerId?: string, details?: any): void {
         let telemetryData: TelemetryData = {
-            viewer,
+            viewerId,
             event: event,
             session: this.session,
             date: new Date(),

Viewer/src/eventManager.ts → Viewer/src/templating/eventManager.ts


+ 343 - 0
Viewer/src/templating/handlebars.d.ts

@@ -0,0 +1,343 @@
+// Type definitions for Handlebars v4.0.11
+// Project: http://handlebarsjs.com/
+// Definitions by: Boris Yankov <https://github.com/borisyankov>, Sergei Dorogin <https://github.com/evil-shrike>
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.3
+
+declare namespace Handlebars {
+    export interface TemplateDelegate<T = any> {
+        (context: T, options?: RuntimeOptions): string;
+    }
+
+    export type Template<T = any> = TemplateDelegate<T> | string;
+
+    export interface RuntimeOptions {
+        partial?: boolean;
+        depths?: any[];
+        helpers?: { [name: string]: Function };
+        partials?: { [name: string]: HandlebarsTemplateDelegate };
+        decorators?: { [name: string]: Function };
+        data?: any;
+        blockParams?: any[];
+    }
+
+    export interface HelperOptions {
+        fn: TemplateDelegate;
+        inverse: TemplateDelegate;
+        hash: any;
+        data?: any;
+    }
+
+    export interface HelperDelegate {
+        (context?: any, arg1?: any, arg2?: any, arg3?: any, arg4?: any, arg5?: any, options?: HelperOptions): any;
+    }
+    export interface HelperDeclareSpec {
+        [key: string]: HelperDelegate;
+    }
+
+    export function registerHelper(name: string, fn: HelperDelegate): void;
+    export function registerHelper(name: HelperDeclareSpec): void;
+    export function unregisterHelper(name: string): void;
+
+    export function registerPartial(name: string, fn: Template): void;
+    export function unregisterPartial(name: string): void;
+
+    // TODO: replace Function with actual signature
+    export function registerDecorator(name: string, fn: Function): void;
+    export function unregisterDecorator(name: string): void;
+
+    export function K(): void;
+    export function createFrame(object: any): any;
+    export function blockParams(obj: any[], ids: any[]): any[];
+    export function Exception(message: string): void;
+    export function log(level: number, obj: any): void;
+    export function parse(input: string): hbs.AST.Program;
+    export function compile<T = any>(input: any, options?: CompileOptions): HandlebarsTemplateDelegate<T>;
+    export function precompile(input: any, options?: PrecompileOptions): TemplateSpecification;
+    export function template<T = any>(precompilation: TemplateSpecification): HandlebarsTemplateDelegate<T>;
+
+    export function create(): typeof Handlebars;
+
+    export const escapeExpression: typeof Utils.escapeExpression;
+    //export const Utils: typeof hbs.Utils;
+    export const logger: Logger;
+    export const templates: HandlebarsTemplates;
+    export const helpers: { [name: string]: HelperDelegate };
+    export const partials: { [name: string]: any };
+    // TODO: replace Function with actual signature
+    export const decorators: { [name: string]: Function };
+
+    export function noConflict(): typeof Handlebars;
+
+    export class SafeString {
+        constructor(str: string);
+        toString(): string;
+        toHTML(): string;
+    }
+
+    export namespace Utils {
+        export function escapeExpression(str: string): string;
+        export function createFrame(object: any): any;
+        export function blockParams(obj: any[], ids: any[]): any[];
+        export function isEmpty(obj: any): boolean;
+        export function extend(obj: any, ...source: any[]): any;
+        export function toString(obj: any): string;
+        export function isArray(obj: any): boolean;
+        export function isFunction(obj: any): boolean;
+    }
+
+    export namespace AST {
+        export const helpers: hbs.AST.helpers;
+    }
+
+    interface ICompiler {
+        accept(node: hbs.AST.Node): void;
+        Program(program: hbs.AST.Program): void;
+        BlockStatement(block: hbs.AST.BlockStatement): void;
+        PartialStatement(partial: hbs.AST.PartialStatement): void;
+        PartialBlockStatement(partial: hbs.AST.PartialBlockStatement): void;
+        DecoratorBlock(decorator: hbs.AST.DecoratorBlock): void;
+        Decorator(decorator: hbs.AST.Decorator): void;
+        MustacheStatement(mustache: hbs.AST.MustacheStatement): void;
+        ContentStatement(content: hbs.AST.ContentStatement): void;
+        CommentStatement(comment?: hbs.AST.CommentStatement): void;
+        SubExpression(sexpr: hbs.AST.SubExpression): void;
+        PathExpression(path: hbs.AST.PathExpression): void;
+        StringLiteral(str: hbs.AST.StringLiteral): void;
+        NumberLiteral(num: hbs.AST.NumberLiteral): void;
+        BooleanLiteral(bool: hbs.AST.BooleanLiteral): void;
+        UndefinedLiteral(): void;
+        NullLiteral(): void;
+        Hash(hash: hbs.AST.Hash): void;
+    }
+
+    export class Visitor implements ICompiler {
+        accept(node: hbs.AST.Node): void;
+        acceptKey(node: hbs.AST.Node, name: string): void;
+        acceptArray(arr: hbs.AST.Expression[]): void;
+        Program(program: hbs.AST.Program): void;
+        BlockStatement(block: hbs.AST.BlockStatement): void;
+        PartialStatement(partial: hbs.AST.PartialStatement): void;
+        PartialBlockStatement(partial: hbs.AST.PartialBlockStatement): void;
+        DecoratorBlock(decorator: hbs.AST.DecoratorBlock): void;
+        Decorator(decorator: hbs.AST.Decorator): void;
+        MustacheStatement(mustache: hbs.AST.MustacheStatement): void;
+        ContentStatement(content: hbs.AST.ContentStatement): void;
+        CommentStatement(comment?: hbs.AST.CommentStatement): void;
+        SubExpression(sexpr: hbs.AST.SubExpression): void;
+        PathExpression(path: hbs.AST.PathExpression): void;
+        StringLiteral(str: hbs.AST.StringLiteral): void;
+        NumberLiteral(num: hbs.AST.NumberLiteral): void;
+        BooleanLiteral(bool: hbs.AST.BooleanLiteral): void;
+        UndefinedLiteral(): void;
+        NullLiteral(): void;
+        Hash(hash: hbs.AST.Hash): void;
+    }
+}
+
+/**
+* Implement this interface on your MVW/MVVM/MVC views such as Backbone.View
+**/
+interface HandlebarsTemplatable {
+    template: HandlebarsTemplateDelegate;
+}
+
+// NOTE: for backward compatibility of this typing
+type HandlebarsTemplateDelegate<T = any> = Handlebars.TemplateDelegate<T>;
+
+interface HandlebarsTemplates {
+    [index: string]: HandlebarsTemplateDelegate;
+}
+
+interface TemplateSpecification {
+
+}
+
+// for backward compatibility of this typing
+type RuntimeOptions = Handlebars.RuntimeOptions;
+
+interface CompileOptions {
+    data?: boolean;
+    compat?: boolean;
+    knownHelpers?: {
+        helperMissing?: boolean;
+        blockHelperMissing?: boolean;
+        each?: boolean;
+        if?: boolean;
+        unless?: boolean;
+        with?: boolean;
+        log?: boolean;
+        lookup?: boolean;
+    };
+    knownHelpersOnly?: boolean;
+    noEscape?: boolean;
+    strict?: boolean;
+    assumeObjects?: boolean;
+    preventIndent?: boolean;
+    ignoreStandalone?: boolean;
+    explicitPartialContext?: boolean;
+}
+
+interface PrecompileOptions extends CompileOptions {
+    srcName?: string;
+    destName?: string;
+}
+
+declare namespace hbs {
+    // for backward compatibility of this typing
+    type SafeString = Handlebars.SafeString;
+
+    type Utils = typeof Handlebars.Utils;
+}
+
+interface Logger {
+    DEBUG: number;
+    INFO: number;
+    WARN: number;
+    ERROR: number;
+    level: number;
+
+    methodMap: { [level: number]: string };
+
+    log(level: number, obj: string): void;
+}
+
+declare namespace hbs {
+    namespace AST {
+        interface Node {
+            type: string;
+            loc: SourceLocation;
+        }
+
+        interface SourceLocation {
+            source: string;
+            start: Position;
+            end: Position;
+        }
+
+        interface Position {
+            line: number;
+            column: number;
+        }
+
+        interface Program extends Node {
+            body: Statement[];
+            blockParams: string[];
+        }
+
+        interface Statement extends Node { }
+
+        interface MustacheStatement extends Statement {
+            path: PathExpression | Literal;
+            params: Expression[];
+            hash: Hash;
+            escaped: boolean;
+            strip: StripFlags;
+        }
+
+        interface Decorator extends MustacheStatement { }
+
+        interface BlockStatement extends Statement {
+            path: PathExpression;
+            params: Expression[];
+            hash: Hash;
+            program: Program;
+            inverse: Program;
+            openStrip: StripFlags;
+            inverseStrip: StripFlags;
+            closeStrip: StripFlags;
+        }
+
+        interface DecoratorBlock extends BlockStatement { }
+
+        interface PartialStatement extends Statement {
+            name: PathExpression | SubExpression;
+            params: Expression[];
+            hash: Hash;
+            indent: string;
+            strip: StripFlags;
+        }
+
+        interface PartialBlockStatement extends Statement {
+            name: PathExpression | SubExpression;
+            params: Expression[];
+            hash: Hash;
+            program: Program;
+            openStrip: StripFlags;
+            closeStrip: StripFlags;
+        }
+
+        interface ContentStatement extends Statement {
+            value: string;
+            original: StripFlags;
+        }
+
+        interface CommentStatement extends Statement {
+            value: string;
+            strip: StripFlags;
+        }
+
+        interface Expression extends Node { }
+
+        interface SubExpression extends Expression {
+            path: PathExpression;
+            params: Expression[];
+            hash: Hash;
+        }
+
+        interface PathExpression extends Expression {
+            data: boolean;
+            depth: number;
+            parts: string[];
+            original: string;
+        }
+
+        interface Literal extends Expression { }
+        interface StringLiteral extends Literal {
+            value: string;
+            original: string;
+        }
+
+        interface BooleanLiteral extends Literal {
+            value: boolean;
+            original: boolean;
+        }
+
+        interface NumberLiteral extends Literal {
+            value: number;
+            original: number;
+        }
+
+        interface UndefinedLiteral extends Literal { }
+
+        interface NullLiteral extends Literal { }
+
+        interface Hash extends Node {
+            pairs: HashPair[];
+        }
+
+        interface HashPair extends Node {
+            key: string;
+            value: Expression;
+        }
+
+        interface StripFlags {
+            open: boolean;
+            close: boolean;
+        }
+
+        interface helpers {
+            helperExpression(node: Node): boolean;
+            scopeId(path: PathExpression): boolean;
+            simpleId(path: PathExpression): boolean;
+        }
+    }
+}
+
+declare module "handlebars" {
+    export = Handlebars;
+}
+
+declare module "handlebars/runtime" {
+    export = Handlebars;
+}

+ 6 - 52
Viewer/src/templateManager.ts

@@ -1,54 +1,11 @@
 
 import { Observable, IFileRequest, Tools } from 'babylonjs';
-import { isUrl, camelToKebab, kebabToCamel } from './helper';
-import * as deepmerge from '../assets/deepmerge.min.js';
+import { isUrl, camelToKebab, kebabToCamel } from '../helper';
 
-/**
- * A single template configuration object
- */
-export interface ITemplateConfiguration {
-    /**
-     * can be either the id of the template's html element or a URL.
-     * See - http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
-     */
-    location?: string; // #template-id OR http://example.com/loading.html
-    /**
-     * If no location is provided you can provide here the raw html of this template.
-     * See http://doc.babylonjs.com/extensions/the_templating_system#location-vs-html
-     */
-    html?: string; // raw html string
-    id?: string;
-    /**
-     * Parameters that will be delivered to the template and will render it accordingly.
-     */
-    params?: { [key: string]: string | number | boolean | object };
-    /**
-     * Events to attach to this template.
-     * event name is the key. the value can either be a boolean (attach to the parent element)
-     * or a map of html id elements.
-     * 
-     * See - http://doc.babylonjs.com/extensions/the_templating_system#event-binding
-     */
-    events?: {
-        // pointer events
-        pointerdown?: boolean | { [id: string]: boolean; };
-        pointerup?: boolean | { [id: string]: boolean; };
-        pointermove?: boolean | { [id: string]: boolean; };
-        pointerover?: boolean | { [id: string]: boolean; };
-        pointerout?: boolean | { [id: string]: boolean; };
-        pointerenter?: boolean | { [id: string]: boolean; };
-        pointerleave?: boolean | { [id: string]: boolean; };
-        pointercancel?: boolean | { [id: string]: boolean; };
-        //click, just in case
-        click?: boolean | { [id: string]: boolean; };
-        // drag and drop
-        dragstart?: boolean | { [id: string]: boolean; };
-        drop?: boolean | { [id: string]: boolean; };
-
-
-        [key: string]: boolean | { [id: string]: boolean; } | undefined;
-    }
-}
+import * as Handlebars from 'handlebars/dist/handlebars';
+import { EventManager } from './eventManager';
+import { ITemplateConfiguration } from '../configuration/interfaces';
+import { deepmerge } from '../helper/';
 
 /**
  * The object sent when an event is triggered
@@ -242,9 +199,6 @@ export class TemplateManager {
 
 }
 
-
-import * as Handlebars from '../assets/handlebars.min.js';
-import { EventManager } from './eventManager';
 // register a new helper. modified https://stackoverflow.com/questions/9838925/is-there-any-method-to-iterate-a-map-with-handlebars-js
 Handlebars.registerHelper('eachInMap', function (map, block) {
     var out = '';
@@ -367,7 +321,7 @@ export class Template {
         this.initPromise = htmlContentPromise.then(htmlTemplate => {
             if (htmlTemplate) {
                 this._htmlTemplate = htmlTemplate;
-                let compiledTemplate = Handlebars.compile(htmlTemplate, { noEscape: (this._configuration.params && this._configuration.params.noEscape) });
+                let compiledTemplate = Handlebars.compile(htmlTemplate, { noEscape: (this._configuration.params && !!this._configuration.params.noEscape) });
                 let config = this._configuration.params || {};
                 this._rawHtml = compiledTemplate(config);
                 try {

+ 49 - 21
Viewer/src/viewer/defaultViewer.ts

@@ -1,7 +1,7 @@
 
 
-import { ViewerConfiguration, IModelConfiguration, ILightConfiguration } from './../configuration/configuration';
-import { Template, EventCallback } from './../templateManager';
+import { ViewerConfiguration, IModelConfiguration, ILightConfiguration } from './../configuration';
+import { Template, EventCallback, TemplateManager } from '../templating/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, FilesInput } from 'babylonjs';
 import { CameraBehavior } from '../interfaces';
@@ -15,6 +15,8 @@ import { IModelAnimation, AnimationState } from '../model/modelAnimation';
  */
 export class DefaultViewer extends AbstractViewer {
 
+
+
     /**
      * Create a new default viewer
      * @param containerElement the element in which the templates will be rendered
@@ -22,11 +24,14 @@ export class DefaultViewer extends AbstractViewer {
      */
     constructor(public containerElement: HTMLElement, initialConfiguration: ViewerConfiguration = { extends: 'default' }) {
         super(containerElement, initialConfiguration);
+
         this.onModelLoadedObservable.add(this._onModelLoaded);
 
-        this.sceneManager.onLightsConfiguredObservable.add((data) => {
-            this._configureLights(data.newConfiguration, data.model!);
-        })
+        this.onEngineInitObservable.add(() => {
+            this.sceneManager.onLightsConfiguredObservable.add((data) => {
+                this._configureLights(data.newConfiguration, data.model!);
+            })
+        });
     }
 
     /**
@@ -148,6 +153,7 @@ export class DefaultViewer extends AbstractViewer {
                 break;
             case "fullscreen-button":
                 this.toggleFullscreen();
+                break;
             default:
                 return;
         }
@@ -339,8 +345,8 @@ export class DefaultViewer extends AbstractViewer {
         this._configureTemplate(model);
         // with a short timeout, making sure everything is there already.
         let hideLoadingDelay = 20;
-        if (this._configuration.lab && this._configuration.lab.hideLoadingDelay !== undefined) {
-            hideLoadingDelay = this._configuration.lab.hideLoadingDelay;
+        if (this.configuration.lab && this.configuration.lab.hideLoadingDelay !== undefined) {
+            hideLoadingDelay = this.configuration.lab.hideLoadingDelay;
         }
         setTimeout(() => {
             this.sceneManager.scene.executeWhenReady(() => {
@@ -476,6 +482,28 @@ export class DefaultViewer extends AbstractViewer {
         }));
     }
 
+    public dispose() {
+        this.templateManager.dispose();
+        super.dispose();
+    }
+
+    protected _onConfigurationLoaded(configuration: ViewerConfiguration) {
+        super._onConfigurationLoaded(configuration);
+
+        // initialize the templates
+        let templateConfiguration = this.configuration.templates || {};
+
+        this.templateManager.initTemplate(templateConfiguration);
+        // when done, execute onTemplatesLoaded()
+        this.templateManager.onAllLoaded.add(() => {
+            let canvas = this.templateManager.getCanvas();
+            if (canvas) {
+                this._canvas = canvas;
+            }
+            this._onTemplateLoaded();
+        });
+    }
+
     /**
      * An extension of the light configuration of the abstract viewer.
      * @param lightsConfiguration the light configuration to use
@@ -483,28 +511,28 @@ export class DefaultViewer extends AbstractViewer {
      */
     private _configureLights(lightsConfiguration: { [name: string]: ILightConfiguration | boolean | number } = {}, model?: ViewerModel) {
         // labs feature - flashlight
-        if (this._configuration.lab && this._configuration.lab.flashlight) {
+        if (this.configuration.lab && this.configuration.lab.flashlight) {
             let pointerPosition = Vector3.Zero();
             let lightTarget;
             let angle = 0.5;
             let exponent = Math.PI / 2;
-            if (typeof this._configuration.lab.flashlight === "object") {
-                exponent = this._configuration.lab.flashlight.exponent || exponent;
-                angle = this._configuration.lab.flashlight.angle || angle;
+            if (typeof this.configuration.lab.flashlight === "object") {
+                exponent = this.configuration.lab.flashlight.exponent || exponent;
+                angle = this.configuration.lab.flashlight.angle || angle;
             }
             var flashlight = new SpotLight("flashlight", Vector3.Zero(),
                 Vector3.Zero(), exponent, angle, this.sceneManager.scene);
-            if (typeof this._configuration.lab.flashlight === "object") {
-                flashlight.intensity = this._configuration.lab.flashlight.intensity || flashlight.intensity;
-                if (this._configuration.lab.flashlight.diffuse) {
-                    flashlight.diffuse.r = this._configuration.lab.flashlight.diffuse.r;
-                    flashlight.diffuse.g = this._configuration.lab.flashlight.diffuse.g;
-                    flashlight.diffuse.b = this._configuration.lab.flashlight.diffuse.b;
+            if (typeof this.configuration.lab.flashlight === "object") {
+                flashlight.intensity = this.configuration.lab.flashlight.intensity || flashlight.intensity;
+                if (this.configuration.lab.flashlight.diffuse) {
+                    flashlight.diffuse.r = this.configuration.lab.flashlight.diffuse.r;
+                    flashlight.diffuse.g = this.configuration.lab.flashlight.diffuse.g;
+                    flashlight.diffuse.b = this.configuration.lab.flashlight.diffuse.b;
                 }
-                if (this._configuration.lab.flashlight.specular) {
-                    flashlight.specular.r = this._configuration.lab.flashlight.specular.r;
-                    flashlight.specular.g = this._configuration.lab.flashlight.specular.g;
-                    flashlight.specular.b = this._configuration.lab.flashlight.specular.b;
+                if (this.configuration.lab.flashlight.specular) {
+                    flashlight.specular.r = this.configuration.lab.flashlight.specular.r;
+                    flashlight.specular.g = this.configuration.lab.flashlight.specular.g;
+                    flashlight.specular.b = this.configuration.lab.flashlight.specular.b;
                 }
 
             }

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 110 - 109
Viewer/src/viewer/viewer.ts


+ 10 - 4
Viewer/tests/commons/helper.ts

@@ -1,6 +1,7 @@
 import { BABYLON, AbstractViewer, DefaultViewer, ViewerModel, viewerGlobals, AnimationPlayMode, AnimationState } from "../../src";
 import { ViewerConfiguration } from "../../src/configuration/configuration";
 import { IModelAnimation } from "../../src/model/modelAnimation";
+import { SceneManager } from "../../src/managers/sceneManager";
 
 export const useNullEngine = true;
 
@@ -116,7 +117,8 @@ export class NullEngineAbstractViewer extends AbstractViewer {
     }
 
     protected _initEngine() {
-        let config: any = this._configuration.engine || {};
+        let config: any = this.configuration.engine || {};
+
         // TDO enable further configuration
         config.engineOptions = config.engineOptions || {};
 
@@ -134,6 +136,8 @@ export class NullEngineAbstractViewer extends AbstractViewer {
             return this.canvas;
         }
 
+        this.sceneManager = new SceneManager(this.engine, this.configurationContainer, this.observablesManager);
+
         // Disable manifest checking
         BABYLON.Database.IDBStorageEnabled = false;
 
@@ -141,7 +145,7 @@ export class NullEngineAbstractViewer extends AbstractViewer {
             window.addEventListener('resize', this._resize);
         }
 
-        if (this._configuration.engine && this._configuration.engine.adaptiveQuality) {
+        if (this.configuration.engine && this.configuration.engine.adaptiveQuality) {
             var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
             this.engine.setHardwareScalingLevel(scale);
         }
@@ -157,7 +161,7 @@ export class NullEngineAbstractViewer extends AbstractViewer {
 export class NullEngineDefaultViewer extends DefaultViewer {
 
     protected _initEngine() {
-        let config: any = this._configuration.engine || {};
+        let config: any = this.configuration.engine || {};
         // TDO enable further configuration
         config.engineOptions = config.engineOptions || {};
 
@@ -174,6 +178,8 @@ export class NullEngineDefaultViewer extends DefaultViewer {
             return this.canvas;
         }
 
+        this.sceneManager = new SceneManager(this.engine, this.configurationContainer, this.observablesManager);
+
         // Disable manifest checking
         BABYLON.Database.IDBStorageEnabled = false;
 
@@ -181,7 +187,7 @@ export class NullEngineDefaultViewer extends DefaultViewer {
             window.addEventListener('resize', this._resize);
         }
 
-        if (this._configuration.engine && this._configuration.engine.adaptiveQuality) {
+        if (this.configuration.engine && this.configuration.engine.adaptiveQuality) {
             var scale = Math.max(0.5, 1 / (window.devicePixelRatio || 2));
             this.engine.setHardwareScalingLevel(scale);
         }

+ 42 - 28
Viewer/tests/unit/src/viewer/sceneManager.ts

@@ -6,11 +6,16 @@ export let name = "scene manager";
 
 describe(name, function () {
 
-    it("should be initialized when a viewer is created", (done) => {
+    it("should be initialized when an engine is created", (done) => {
         let viewer = Helper.getNewViewerInstance();
-        assert.isDefined(viewer.sceneManager, "scene manager should be defined");
-        viewer.dispose();
-        done();
+
+        viewer.onEngineInitObservable.add(() => {
+            assert.isDefined(viewer.sceneManager, "scene manager should be defined");
+        });
+        viewer.onInitDoneObservable.add(() => {
+            viewer.dispose();
+            done();
+        });
     })
 
     it("should have objects initialized after init", (done) => {
@@ -49,30 +54,36 @@ describe(name, function () {
         let viewer = Helper.getNewViewerInstance(undefined, { extends: "none" });
         let sceneInitCalled = false;
         viewer.runRenderLoop = false;
-        viewer.sceneManager.onSceneInitObservable.clear();
-        viewer.sceneManager.onSceneInitObservable.add(() => {
-            assert.isDefined(viewer.sceneManager.scene);
-            assert.isUndefined(viewer.sceneManager.camera);
-            sceneInitCalled = true;
-        });
 
         const s: string[] = [];
 
-        let update = (str: string, data) => {
-            if (s.indexOf(str) !== -1) {
-                assert.fail(false, true, str + " observer already called");
-                return false;
-            } else {
-                s.push(str);
-                return true;
+        viewer.onEngineInitObservable.add(() => {
+            viewer.sceneManager.onSceneInitObservable.clear();
+            viewer.sceneManager.onSceneInitObservable.add(() => {
+                assert.isDefined(viewer.sceneManager.scene);
+                assert.isUndefined(viewer.sceneManager.camera);
+                sceneInitCalled = true;
+            });
+
+
+
+            let update = (str: string, data) => {
+                if (s.indexOf(str) !== -1) {
+                    assert.fail(false, true, str + " observer already called");
+                    return false;
+                } else {
+                    s.push(str);
+                    return true;
+                }
             }
-        }
 
-        viewer.sceneManager.onCameraConfiguredObservable.add(update.bind(null, "camera"));
-        viewer.sceneManager.onLightsConfiguredObservable.add(update.bind(null, "light"));
-        viewer.sceneManager.onEnvironmentConfiguredObservable.add(update.bind(null, "env"));
-        viewer.sceneManager.onSceneConfiguredObservable.add(update.bind(null, "scene"));
-        viewer.sceneManager.onSceneOptimizerConfiguredObservable.add(update.bind(null, "optimizer"));
+            viewer.sceneManager.onCameraConfiguredObservable.add(update.bind(null, "camera"));
+            viewer.sceneManager.onLightsConfiguredObservable.add(update.bind(null, "light"));
+            viewer.sceneManager.onEnvironmentConfiguredObservable.add(update.bind(null, "env"));
+            viewer.sceneManager.onSceneConfiguredObservable.add(update.bind(null, "scene"));
+            viewer.sceneManager.onSceneOptimizerConfiguredObservable.add(update.bind(null, "optimizer"));
+
+        });
 
         viewer.onInitDoneObservable.add(() => {
             viewer.updateConfiguration({
@@ -99,11 +110,14 @@ describe(name, function () {
             }
         });
 
-        viewer.runRenderLoop = false;
-        viewer.sceneManager.onSceneInitObservable.clear();
-        viewer.sceneManager.onSceneInitObservable.add((scene) => {
-            viewer.onSceneInitObservable.notifyObserversWithPromise(scene);
-        })
+        viewer.onEngineInitObservable.add(() => {
+
+            viewer.runRenderLoop = false;
+            viewer.sceneManager.onSceneInitObservable.clear();
+            viewer.sceneManager.onSceneInitObservable.add((scene) => {
+                viewer.onSceneInitObservable.notifyObserversWithPromise(scene);
+            });
+        });
 
         viewer.onInitDoneObservable.add(() => {
             assert.isDefined(viewer.sceneManager.defaultRenderingPipeline);

+ 1 - 2
Viewer/tests/unit/src/viewer/viewer.ts

@@ -12,11 +12,10 @@ describe('Viewer', function () {
     it('should initialize a new viewer and its internal variables', (done) => {
         let viewer = Helper.getNewViewerInstance();
         assert.isDefined(viewer.baseId, "base id should be defined");
-        assert.isDefined(viewer.templateManager, "template manager should be defined");
-        assert.isDefined(viewer.sceneManager, "scene manager should be defined");
         assert.isDefined(viewer.modelLoader, "model loader should be defined");
         viewer.onInitDoneObservable.add(() => {
             assert.isDefined(viewer, "Viewer can not be instantiated.");
+            assert.isDefined(viewer.sceneManager, "scene manager should be defined");
             viewer.dispose();
             done();
         });

+ 26 - 15
Viewer/tsconfig-gulp.json

@@ -2,32 +2,43 @@
     "compilerOptions": {
         "target": "es5",
         "module": "commonjs",
-        "noResolve": false,
-        "noImplicitAny": false,
-        "strictNullChecks": true,
-        "removeComments": false,
-        "preserveConstEnums": true,
-        "sourceMap": false,
-        "experimentalDecorators": true,
-        "isolatedModules": false,
         "declaration": true,
+        "experimentalDecorators": true,
+        "emitDecoratorMetadata": true,
+        "moduleResolution": "node",
+        "strictNullChecks": true,
+        "noImplicitAny": false,
+        "noFallthroughCasesInSwitch": true,
+        "inlineSourceMap": true,
         "lib": [
+            "es5",
             "dom",
             "es2015.promise",
-            "es5"
-        ],
-        "types": [
-            "node"
+            "es2015.collection",
+            "es2015.iterable"
         ],
-        "baseUrl": "./",
+        "skipDefaultLibCheck": true,
+        "skipLibCheck": true,
+        "baseUrl": "./src/",
+        "rootDir": "./",
         "paths": {
             "babylonjs": [
-                "../dist/preview release/babylon.d.ts"
+                "../../dist/preview release/babylon.d.ts"
             ],
             "babylonjs-loaders": [
                 "externalModules.d.ts"
+            ],
+            "babylonjs-gltf2interface": [
+                "../../dist/babylon.glTF2Interface.d.ts"
+            ],
+            "deepmerge": [
+                "./helper/deepmerge.d.ts"
+            ],
+            "handlebars": [
+                "./templates/handlebars.d.ts"
             ]
-        }
+        },
+        "outDir": "./dist/build"
     },
     "exclude": [
         "node_modules",

+ 23 - 23
Viewer/tsconfig.json

@@ -1,25 +1,26 @@
 {
     "compilerOptions": {
-        "target": "es5",
-        "module": "commonjs",
-        "noResolve": false,
-        "noImplicitAny": false, //mainly due to usage of external libs without typings.
-        "strictNullChecks": true,
-        "removeComments": true,
-        "preserveConstEnums": true,
-        "sourceMap": true,
+        "target": "es2015",
+        "module": "es2015",
+        "declaration": true,
         "experimentalDecorators": true,
-        "isolatedModules": false,
-        "declaration": false,
+        "emitDecoratorMetadata": true,
+        "moduleResolution": "node",
+        "strictNullChecks": true,
+        "noImplicitAny": false,
+        "noFallthroughCasesInSwitch": true,
+        "inlineSourceMap": true,
         "lib": [
+            "es5",
             "dom",
             "es2015.promise",
-            "es5"
-        ],
-        "types": [
-            "node"
+            "es2015.collection",
+            "es2015.iterable"
         ],
+        "skipDefaultLibCheck": true,
+        "skipLibCheck": true,
         "baseUrl": "./src/",
+        "rootDir": "./",
         "paths": {
             "babylonjs": [
                 "../../dist/preview release/babylon.d.ts"
@@ -29,15 +30,14 @@
             ],
             "babylonjs-gltf2interface": [
                 "../../dist/babylon.glTF2Interface.d.ts"
+            ],
+            "deepmerge": [
+                "./helper/deepmerge.d.ts"
+            ],
+            "handlebars": [
+                "./templates/handlebars.d.ts"
             ]
         },
-        //"outDir": "./dist/build"
-    },
-    "files": [
-        "./src/index.ts"
-    ],
-    "exclude": [
-        "node_modules",
-        "dist"
-    ]
+        "outDir": "./dist/build"
+    }
 }

+ 2 - 4
Viewer/webpack.config.js

@@ -18,16 +18,14 @@ module.exports = {
         alias: {
             "babylonjs": __dirname + '/../dist/preview release/babylon.max.js',
             "babylonjs-materials": __dirname + '/../dist/preview release/materialsLibrary/babylonjs.materials.js',
-            "babylonjs-loaders": __dirname + '/../dist/preview release/loaders/babylonjs.loaders.js',
-            "pep": __dirname + '/assets/pep.min.js'
+            "babylonjs-loaders": __dirname + '/../dist/preview release/loaders/babylonjs.loaders.js'
         }
     },
     externals: {
         // until physics will be integrated in the viewer, ignore cannon
         cannon: 'CANNON',
         oimo: 'OIMO',
-        './Oimo': 'OIMO',
-        "earcut": true
+        earcut: true
     },
     devtool: 'source-map',
     plugins: [

+ 1 - 5
Viewer/webpack.gulp.config.js

@@ -12,8 +12,6 @@ module.exports = {
     externals: {
         cannon: 'CANNON',
         oimo: 'OIMO',
-        vertx: true,
-        "./Oimo": "OIMO",
         "earcut": true
     },
     resolve: {
@@ -21,9 +19,7 @@ module.exports = {
         alias: {
             "babylonjs": __dirname + '/../dist/preview release/babylon.max.js',
             "babylonjs-materials": __dirname + '/../dist/preview release/materialsLibrary/babylonjs.materials.js',
-            "babylonjs-loaders": __dirname + '/../dist/preview release/loaders/babylonjs.loaders.js',
-            // "es6-promise": __dirname + '/assets/es6-promise.min.js',
-            "pep": __dirname + '/assets/pep.min.js',
+            "babylonjs-loaders": __dirname + '/../dist/preview release/loaders/babylonjs.loaders.js'
         }
     },
     module: {

+ 2 - 0
dist/preview release/what's new.md

@@ -46,6 +46,7 @@
 - Added all code comments for GUI
 
 ## Bug fixes
+
 - VR experience helper will now fire pointer events even when no mesh is currently hit ([TrevorDev](https://github.com/TrevorDev))
 - RawTexture.CreateAlphaTexture no longer fails to create a usable texture ([TrevorDev](https://github.com/TrevorDev))
 
@@ -69,4 +70,5 @@
 - It wasn't possible to disable camera behavior(s) using configuration  [#4348](https://github.com/BabylonJS/Babylon.js/issues/4348) ([RaananW](https://github.com/RaananW))
 
 ## Breaking changes
+
 - Fixing support for R and RG texture formats made us remove TextureFormat_R32F and TextureFormat_RG32F as they were mixing formats and types. Please, use the respective TextureFormat_R and TextureFormat_RG with the Float types ([sebavan](http://www.github.com/sebavan))