Sfoglia il codice sorgente

Merge pull request #3635 from RaananW/viewer-changes-new

Viewer changes
Raanan Weber 7 anni fa
parent
commit
6cacfc8046

File diff suppressed because it is too large
+ 53 - 35
Viewer/dist/viewer.js


File diff suppressed because it is too large
+ 53 - 35
Viewer/dist/viewer.min.js


+ 1 - 8
Viewer/package.json

@@ -32,12 +32,5 @@
         "uglifyjs-webpack-plugin": "^1.1.6",
         "webpack": "^3.10.0",
         "webpack-dev-server": "^2.11.0"
-    },
-    "dependencies": {
-        "babylonjs": "^3.2.0-alpha4",
-        "babylonjs-loaders": "^3.2.0-alpha4",
-        "deepmerge": "^2.0.1",
-        "es6-promise": "^4.2.2",
-        "handlebars": "^4.0.11"
     }
-}
+}

+ 14 - 0
Viewer/src/configuration/configuration.ts

@@ -173,6 +173,20 @@ export interface ViewerConfiguration {
             [key: string]: string;
         }
     }
+
+    // features that are being tested.
+    // those features' syntax will change and move out! 
+    // Don't use in production (or be ready to make the changes :) )
+    lab?: {
+        flashlight?: boolean | {
+            exponent?: number;
+            angle?: number;
+            intensity?: number;
+            diffuse?: { r: number, g: number, b: number };
+            specular?: { r: number, g: number, b: number };
+        }
+        hideLoadingDelay?: number;
+    }
 }
 
 export interface SceneOptimizerParameters {

+ 4 - 2
Viewer/src/templateManager.ts

@@ -110,7 +110,10 @@ export class TemplateManager {
      * @memberof TemplateManager
      */
     private buildHTMLTree(templates: { [key: string]: ITemplateConfiguration }): Promise<object> {
-        let promises = Object.keys(templates).map(name => {
+        let promises: Array<Promise<Template | boolean>> = Object.keys(templates).map(name => {
+            // if the template was overridden
+            if (!templates[name]) return Promise.resolve(false);
+            // else - we have a template, let's do our job!
             let template = new Template(name, templates[name]);
             // make sure the global onEventTriggered is called as well
             template.onEventTriggered.add(eventData => this.onEventTriggered.notifyObservers(eventData));
@@ -171,7 +174,6 @@ export class TemplateManager {
 
 
 import * as Handlebars from '../assets/handlebars.min.js';
-import { PromiseObservable } from './util/promiseObservable';
 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) {

+ 0 - 39
Viewer/src/util/promiseObservable.ts

@@ -1,39 +0,0 @@
-import { Observable } from 'babylonjs';
-
-export class PromiseObservable<T> extends Observable<T> {
-
-    public notifyWithPromise(eventData: T, mask: number = -1, target?: any, currentTarget?: any): Promise<any> {
-
-        let p = Promise.resolve();
-
-        if (!this._observers.length) {
-            return p;
-        }
-
-        let state = this['_eventState'];
-        state.mask = mask;
-        state.target = target;
-        state.currentTarget = currentTarget;
-        state.skipNextObservers = false;
-
-        this._observers.forEach(obs => {
-            if (state.skipNextObservers) {
-                return;
-            }
-            if (obs.mask & mask) {
-                if (obs.scope) {
-                    // TODO - I can add the variable from the last function here. Requires changing callback sig
-                    p = p.then(() => {
-                        return obs.callback.apply(obs.scope, [eventData, state]);
-                    });
-                } else {
-                    p = p.then(() => {
-                        return obs.callback(eventData, state);
-                    });
-                }
-            }
-        });
-
-        return p;
-    }
-}

+ 52 - 18
Viewer/src/viewer/defaultViewer.ts

@@ -3,7 +3,7 @@
 import { ViewerConfiguration } from './../configuration/configuration';
 import { Template, EventCallback } from './../templateManager';
 import { AbstractViewer } from './viewer';
-import { MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMaterial, Observable, ShadowLight, CubeTexture, BouncingBehavior, FramingBehavior, Behavior, Light, Engine, Scene, AutoRotationBehavior, AbstractMesh, Quaternion, StandardMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
+import { SpotLight, MirrorTexture, Plane, ShadowGenerator, Texture, BackgroundMaterial, Observable, ShadowLight, CubeTexture, BouncingBehavior, FramingBehavior, Behavior, Light, Engine, Scene, AutoRotationBehavior, AbstractMesh, Quaternion, StandardMaterial, ArcRotateCamera, ImageProcessingConfiguration, Color3, Vector3, SceneLoader, Mesh, HemisphericLight } from 'babylonjs';
 import { CameraBehavior } from '../interfaces';
 
 export class DefaultViewer extends AbstractViewer {
@@ -121,9 +121,13 @@ export class DefaultViewer extends AbstractViewer {
         this.setModelMetaData();
 
         // with a short timeout, making sure everything is there already.
+        let hideLoadingDelay = 500;
+        if (this.configuration.lab && this.configuration.lab.hideLoadingDelay !== undefined) {
+            hideLoadingDelay = this.configuration.lab.hideLoadingDelay;
+        }
         setTimeout(() => {
             this.hideLoadingScreen();
-        }, 500);
+        }, hideLoadingDelay);
 
 
         // recreate the camera
@@ -360,6 +364,52 @@ export class DefaultViewer extends AbstractViewer {
 
         let sceneConfig = this.configuration.scene || { defaultLight: true };
 
+        // labs feature - flashlight
+        if (this.configuration.lab && this.configuration.lab.flashlight) {
+            let pointerPosition = BABYLON.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;
+            }
+            var flashlight = new SpotLight("flashlight", Vector3.Zero(),
+                Vector3.Zero(), exponent, angle, this.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 (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;
+                }
+
+            }
+            this.scene.constantlyUpdateMeshUnderPointer = true;
+            this.scene.onPointerObservable.add((eventData, eventState) => {
+                if (eventData.type === 4 && eventData.pickInfo) {
+                    lightTarget = (eventData.pickInfo.pickedPoint);
+                } else {
+                    lightTarget = undefined;
+                }
+            });
+            let updateFlashlightFunction = () => {
+                if (this.camera && flashlight) {
+                    flashlight.position.copyFrom(this.camera.position);
+                    if (lightTarget) {
+                        lightTarget.subtractToRef(flashlight.position, flashlight.direction);
+                    }
+                }
+            }
+            this.scene.registerBeforeRender(updateFlashlightFunction);
+            this.registeredOnBeforerenderFunctions.push(updateFlashlightFunction);
+        }
+
         if (!sceneConfig.defaultLight && (this.configuration.lights && Object.keys(this.configuration.lights).length)) {
             // remove old lights
             this.scene.lights.forEach(l => {
@@ -395,22 +445,6 @@ export class DefaultViewer extends AbstractViewer {
                     }
                 }
             });
-        } else {
-            if (!this.configuration.lights && this.configuration.ground) {
-                let light = this.scene.lights[0];
-                if (light instanceof ShadowLight) {
-                    if (this.maxShadows) {
-                        var shadowGenerator = new ShadowGenerator(512, light);
-                        // add the focues meshes to the shadow list
-                        let shadownMap = shadowGenerator.getShadowMap();
-                        if (!shadownMap) return;
-                        let renderList = shadownMap.renderList;
-                        for (var index = 0; index < focusMeshes.length; index++) {
-                            renderList && renderList.push(focusMeshes[index]);
-                        }
-                    }
-                }
-            }
         }
     }
 

+ 22 - 16
Viewer/src/viewer/viewer.ts

@@ -3,7 +3,6 @@ import { TemplateManager } from './../templateManager';
 import configurationLoader from './../configuration/loader';
 import { CubeTexture, Color3, IEnvironmentHelperOptions, EnvironmentHelper, Effect, SceneOptimizer, SceneOptimizerOptions, Observable, Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, AbstractMesh, Mesh, HemisphericLight, Database, SceneLoaderProgressEvent, ISceneLoaderPlugin, ISceneLoaderPluginAsync } from 'babylonjs';
 import { ViewerConfiguration } from '../configuration/configuration';
-import { PromiseObservable } from '../util/promiseObservable';
 
 export abstract class AbstractViewer {
 
@@ -32,14 +31,17 @@ export abstract class AbstractViewer {
 
 
     // observables
-    public onSceneInitObservable: PromiseObservable<Scene>;
-    public onEngineInitObservable: PromiseObservable<Engine>;
-    public onModelLoadedObservable: PromiseObservable<AbstractMesh[]>;
-    public onModelLoadProgressObservable: PromiseObservable<SceneLoaderProgressEvent>;
-    public onInitDoneObservable: PromiseObservable<AbstractViewer>;
+    public onSceneInitObservable: Observable<Scene>;
+    public onEngineInitObservable: Observable<Engine>;
+    public onModelLoadedObservable: Observable<AbstractMesh[]>;
+    public onModelLoadProgressObservable: Observable<SceneLoaderProgressEvent>;
+    public onLoaderInitObservable: Observable<ISceneLoaderPlugin | ISceneLoaderPluginAsync>;
+    public onInitDoneObservable: Observable<AbstractViewer>;
 
     protected canvas: HTMLCanvasElement;
 
+    protected registeredOnBeforerenderFunctions: Array<() => void>;
+
     constructor(public containerElement: HTMLElement, initialConfiguration: ViewerConfiguration = {}) {
         // if exists, use the container id. otherwise, generate a random string.
         if (containerElement.id) {
@@ -48,11 +50,14 @@ export abstract class AbstractViewer {
             this.baseId = containerElement.id = 'bjs' + Math.random().toString(32).substr(2, 8);
         }
 
-        this.onSceneInitObservable = new PromiseObservable();
-        this.onEngineInitObservable = new PromiseObservable();
-        this.onModelLoadedObservable = new PromiseObservable();
-        this.onModelLoadProgressObservable = new PromiseObservable();
-        this.onInitDoneObservable = new PromiseObservable();
+        this.onSceneInitObservable = new Observable();
+        this.onEngineInitObservable = new Observable();
+        this.onModelLoadedObservable = new Observable();
+        this.onModelLoadProgressObservable = new Observable();
+        this.onInitDoneObservable = new Observable();
+        this.onLoaderInitObservable = new Observable();
+
+        this.registeredOnBeforerenderFunctions = [];
 
         // add this viewer to the viewer manager
         viewerManager.addViewer(this);
@@ -160,7 +165,7 @@ export abstract class AbstractViewer {
         return this.onTemplatesLoaded().then(() => {
             let autoLoadModel = !!this.configuration.model;
             return this.initEngine().then((engine) => {
-                return this.onEngineInitObservable.notifyWithPromise(engine);
+                return this.onEngineInitObservable.notifyObserversWithPromise(engine);
             }).then(() => {
                 if (autoLoadModel) {
                     return this.loadModel();
@@ -168,9 +173,9 @@ export abstract class AbstractViewer {
                     return this.scene || this.initScene();
                 }
             }).then((scene) => {
-                return this.onSceneInitObservable.notifyWithPromise(scene);
+                return this.onSceneInitObservable.notifyObserversWithPromise(scene);
             }).then(() => {
-                return this.onInitDoneObservable.notifyWithPromise(this);
+                return this.onInitDoneObservable.notifyObserversWithPromise(this);
             }).then(() => {
                 return this;
             });
@@ -289,14 +294,15 @@ export abstract class AbstractViewer {
                 this.lastUsedLoader = SceneLoader.ImportMesh(undefined, base, filename, this.scene, (meshes) => {
                     resolve(meshes);
                 }, (progressEvent) => {
-                    this.onModelLoadProgressObservable.notifyWithPromise(progressEvent);
+                    this.onModelLoadProgressObservable.notifyObserversWithPromise(progressEvent);
                 }, (e, m, exception) => {
                     // console.log(m, exception);
                     reject(m);
                 }, plugin)!;
+                this.onLoaderInitObservable.notifyObserversWithPromise(this.lastUsedLoader);
             });
         }).then((meshes: Array<AbstractMesh>) => {
-            return this.onModelLoadedObservable.notifyWithPromise(meshes)
+            return this.onModelLoadedObservable.notifyObserversWithPromise(meshes)
                 .then(() => {
                     this.initEnvironment();
                 }).then(() => {

+ 21 - 9
Viewer/tsconfig.json

@@ -2,25 +2,37 @@
     "compilerOptions": {
         "target": "es5",
         "module": "commonjs",
-        "noResolve": true,
+        "noResolve": false,
         "noImplicitAny": false, //mainly due to usage of external libs without typings.
         "strictNullChecks": true,
         "removeComments": true,
         "preserveConstEnums": true,
-        "sourceMap": true,
+        "sourceMap": false,
         "experimentalDecorators": true,
         "isolatedModules": false,
+        "declaration": false,
         "lib": [
             "dom",
             "es2015.promise",
             "es5"
         ],
-        //"declaration": true,
-        "outDir": "./temp/",
         "types": [
-            "node",
-            "babylonjs",
-            "babylonjs-loaders"
-        ]
-    }
+            "node"
+        ],
+        "baseUrl": ".",
+        "paths": {
+            "babylonjs": [
+                "../dist/preview release/babylon.max.js",
+                "../dist/preview release/babylon.d.ts"
+            ],
+            "babylonjs-loaders": [
+                "../dist/preview release/loaders/babylonjs.loaders.js",
+                "../dist/preview release/loaders/babylonjs.loaders.module.d.ts"
+            ]
+        }
+    },
+    "exclude": [
+        "node_modules",
+        "dist"
+    ]
 }

+ 13 - 9
Viewer/webpack.config.js

@@ -1,11 +1,9 @@
-const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
 const path = require('path');
 const webpack = require('webpack');
 
 module.exports = {
     entry: {
-        'viewer': './src/index.ts',
-        'viewer.min': './src/index.ts',
+        'viewer': './src/index.ts'
     },
     output: {
         path: path.resolve(__dirname, 'dist'),
@@ -16,17 +14,23 @@ module.exports = {
         devtoolModuleFilenameTemplate: '[absolute-resource-path]'
     },
     resolve: {
-        extensions: ['.ts', '.tsx', '.js']
+        extensions: ['.ts', '.js'],
+        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',
+            "deepmerge": __dirname + '/assets/deepmerge.min.js'
+        }
+    },
+    externals: {
+        // until physics will be integrated in the viewer, ignore cannon
+        cannon: 'CANNON'
     },
     devtool: 'source-map',
     plugins: [
         new webpack.WatchIgnorePlugin([
             /\.d\.ts$/
-        ]),
-        new UglifyJSPlugin({
-            parallel: true,
-            test: /\.min\.js$/i,
-        })
+        ])
     ],
     module: {
         loaders: [{

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

@@ -43,6 +43,7 @@
 - (Viewer) The viewer supports custom shaders in the configuration. ([RaananW](https://github.com/RaananW))
 - Documented PostProcessRenderEffect, DefaultRenderingPipeline, BlurPostProcess, DepthOfFieldEffect, PostProcess, PostProcessManager classes ([trevordev](https://github.com/trevordev))
 - SPS internal storage of each solid particle rotation matrix ([jbousquie](https://github.com/jbousquie)) 
+- (Viewer) Introducing the viewer labs - testing new features. ([RaananW](https://github.com/RaananW))
 
 ## Bug fixes
 - Texture extension detection in `Engine.CreateTexture` ([sebavan](https://github.com/sebavan))