Browse Source

Merge branch 'master' of https://github.com/BabylonJS/Babylon.js

David Catuhe 7 years ago
parent
commit
3093b63110

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


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


+ 10 - 10
Viewer/package.json

@@ -23,21 +23,21 @@
     },
     },
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "homepage": "https://github.com/BabylonJS/Babylon.js#readme",
     "devDependencies": {
     "devDependencies": {
-        "@types/node": "^8.0.53",
-        "base64-image-loader": "^1.2.0",
-        "html-loader": "^0.5.1",
+        "@types/node": "^8.5.8",
+        "base64-image-loader": "^1.2.1",
+        "html-loader": "^0.5.4",
         "json-loader": "^0.5.7",
         "json-loader": "^0.5.7",
         "ts-loader": "^2.3.7",
         "ts-loader": "^2.3.7",
         "typescript": "^2.6.2",
         "typescript": "^2.6.2",
-        "uglifyjs-webpack-plugin": "^1.1.1",
-        "webpack": "^3.8.1",
-        "webpack-dev-server": "^2.9.5"
+        "uglifyjs-webpack-plugin": "^1.1.6",
+        "webpack": "^3.10.0",
+        "webpack-dev-server": "^2.11.0"
     },
     },
     "dependencies": {
     "dependencies": {
-        "babylonjs": "^3.1.0-beta6",
-        "babylonjs-loaders": "^3.1.0-beta6",
+        "babylonjs": "^3.2.0-alpha4",
+        "babylonjs-loaders": "^3.2.0-alpha4",
         "deepmerge": "^2.0.1",
         "deepmerge": "^2.0.1",
-        "es6-promise": "^4.1.1",
+        "es6-promise": "^4.2.2",
         "handlebars": "^4.0.11"
         "handlebars": "^4.0.11"
     }
     }
-}
+}

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

@@ -13,20 +13,6 @@ export interface ViewerConfiguration {
         mapper?: string; // json (default), html, yaml, xml, etc'. if not provided, file extension will be used.
         mapper?: string; // json (default), html, yaml, xml, etc'. if not provided, file extension will be used.
     };
     };
 
 
-    // Deprecated
-    /*// native (!!!) javascript events. Mainly used in the JSON-format.
-    // those events will be triggered by the container element (the <babylon> tag);
-    events?: {
-        load: boolean | string;
-        init: boolean | string;
-        meshselected: boolean | string;
-        pointerdown: boolean | string;
-        pointerup: boolean | string;
-        pointermove: boolean | string;
-        // load: 'onViewerLoaded' // will trigger the event prefix-onViewerLoaded instead of prefix-onLoad (and ONLY this event).
-    } | boolean; //events: true - fire all events*/
-    //eventPrefix?: string;
-
     // names of functions in the window context.
     // names of functions in the window context.
     observers?: {
     observers?: {
         onEngineInit?: string;
         onEngineInit?: string;

+ 7 - 1
Viewer/src/configuration/types/default.ts

@@ -17,6 +17,11 @@ export let defaultConfiguration: ViewerConfiguration = {
         },
         },
         viewer: {
         viewer: {
             html: require("../../../assets/templates/default/defaultViewer.html"),
             html: require("../../../assets/templates/default/defaultViewer.html"),
+            events: {
+                pointerout: true,
+                pointerdown: true,
+                pointerup: true
+            }
         },
         },
         navBar: {
         navBar: {
             html: require("../../../assets/templates/default/navbar.html"),
             html: require("../../../assets/templates/default/navbar.html"),
@@ -34,7 +39,8 @@ export let defaultConfiguration: ViewerConfiguration = {
                 visibilityTimeout: 2000
                 visibilityTimeout: 2000
             },
             },
             events: {
             events: {
-                pointerdown: { 'fullscreen-button': true/*, '#help-button': true*/ }
+                pointerdown: { 'fullscreen-button': true/*, '#help-button': true*/ },
+                pointerover: true
             }
             }
         },
         },
         overlay: {
         overlay: {

+ 40 - 0
Viewer/src/eventManager.ts

@@ -0,0 +1,40 @@
+import { EventCallback, TemplateManager } from "./templateManager";
+
+
+export class EventManager {
+
+    private callbacksContainer: { [key: string]: Array<{ eventType?: string, selector?: string, callback: (eventData: EventCallback) => void }> }
+
+    constructor(private templateManager: TemplateManager) {
+        this.callbacksContainer = {};
+        this.templateManager.onEventTriggered.add(eventData => {
+            this.eventTriggered(eventData);
+        })
+    }
+
+    public registerCallback(templateName: string, callback: (eventData: EventCallback) => void, eventType?: string, selector?: string) {
+        if (!this.callbacksContainer[templateName]) {
+            this.callbacksContainer[templateName] = [];
+        }
+        this.callbacksContainer[templateName].push({
+            eventType: eventType,
+            callback: callback
+        });
+    }
+
+    public unregisterCallback(templateName: string, callback?: (eventData: EventCallback) => void, eventType?: string, selector?: string) {
+        let callbackDefs = this.callbacksContainer[templateName] || [];
+        this.callbacksContainer[templateName] = callbackDefs.filter(callbackDef => (!callbackDef.eventType || callbackDef.eventType === eventType) && (!callbackDef.selector || callbackDef.selector === selector));
+    }
+
+    private eventTriggered(data: EventCallback) {
+        let templateName = data.template.name;
+        let eventType = data.event.type;
+        let selector = data.selector;
+
+        let callbackDefs = this.callbacksContainer[templateName] || [];
+        callbackDefs.filter(callbackDef => (!callbackDef.eventType || callbackDef.eventType === eventType) && (!callbackDef.selector || callbackDef.selector === selector)).forEach(callbackDef => {
+            callbackDef.callback(data);
+        });
+    }
+}

+ 49 - 18
Viewer/src/templateManager.ts

@@ -40,6 +40,9 @@ export class TemplateManager {
     public onLoaded: Observable<Template>;
     public onLoaded: Observable<Template>;
     public onStateChange: Observable<Template>;
     public onStateChange: Observable<Template>;
     public onAllLoaded: Observable<TemplateManager>;
     public onAllLoaded: Observable<TemplateManager>;
+    public onEventTriggered: Observable<EventCallback>;
+
+    public eventManager: EventManager;
 
 
     private templates: { [name: string]: Template };
     private templates: { [name: string]: Template };
 
 
@@ -50,6 +53,9 @@ export class TemplateManager {
         this.onLoaded = new Observable<Template>();
         this.onLoaded = new Observable<Template>();
         this.onStateChange = new Observable<Template>();
         this.onStateChange = new Observable<Template>();
         this.onAllLoaded = new Observable<TemplateManager>();
         this.onAllLoaded = new Observable<TemplateManager>();
+        this.onEventTriggered = new Observable<EventCallback>();
+
+        this.eventManager = new EventManager(this);
     }
     }
 
 
     public initTemplate(templates: { [key: string]: ITemplateConfiguration }) {
     public initTemplate(templates: { [key: string]: ITemplateConfiguration }) {
@@ -101,6 +107,8 @@ export class TemplateManager {
     private buildHTMLTree(templates: { [key: string]: ITemplateConfiguration }): Promise<object> {
     private buildHTMLTree(templates: { [key: string]: ITemplateConfiguration }): Promise<object> {
         let promises = Object.keys(templates).map(name => {
         let promises = Object.keys(templates).map(name => {
             let template = new Template(name, templates[name]);
             let template = new Template(name, templates[name]);
+            // make sure the global onEventTriggered is called as well
+            template.onEventTriggered.add(eventData => this.onEventTriggered.notifyObservers(eventData));
             this.templates[name] = template;
             this.templates[name] = template;
             return template.initPromise;
             return template.initPromise;
         });
         });
@@ -144,6 +152,8 @@ export class TemplateManager {
 
 
 
 
 import * as Handlebars from '../assets/handlebars.min.js';
 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
 // 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) {
 Handlebars.registerHelper('eachInMap', function (map, block) {
     var out = '';
     var out = '';
@@ -168,6 +178,11 @@ export class Template {
     public onEventTriggered: Observable<EventCallback>;
     public onEventTriggered: Observable<EventCallback>;
 
 
     public isLoaded: boolean;
     public isLoaded: boolean;
+    /**
+     * This is meant to be used to track the show and hide functions.
+     * This is NOT (!!) a flag to check if the element is actually visible to the user.
+     */
+    public isShown: boolean;
 
 
     public parent: HTMLElement;
     public parent: HTMLElement;
 
 
@@ -183,6 +198,7 @@ export class Template {
         this.onEventTriggered = new Observable<EventCallback>();
         this.onEventTriggered = new Observable<EventCallback>();
 
 
         this.isLoaded = false;
         this.isLoaded = false;
+        this.isShown = false;
         /*
         /*
         if (configuration.id) {
         if (configuration.id) {
             this.parent.id = configuration.id;
             this.parent.id = configuration.id;
@@ -199,6 +215,7 @@ export class Template {
                 let rawHtml = compiledTemplate(config);
                 let rawHtml = compiledTemplate(config);
                 this.fragment = document.createRange().createContextualFragment(rawHtml);
                 this.fragment = document.createRange().createContextualFragment(rawHtml);
                 this.isLoaded = true;
                 this.isLoaded = true;
+                this.isShown = true;
                 this.onLoaded.notifyObservers(this);
                 this.onLoaded.notifyObservers(this);
             }
             }
             return this;
             return this;
@@ -243,30 +260,44 @@ export class Template {
     }
     }
 
 
     public show(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
     public show(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
-        if (visibilityFunction) {
-            return visibilityFunction(this).then(() => {
-                this.onStateChange.notifyObservers(this);
+        return Promise.resolve().then(() => {
+            if (visibilityFunction) {
+                return visibilityFunction(this);
+            } else {
+                // flex? box? should this be configurable easier than the visibilityFunction?
+                this.parent.style.display = 'flex';
                 return this;
                 return this;
-            });
-        } else {
-            // flex? box? should this be configurable easier than the visibilityFunction?
-            this.parent.style.display = 'flex';
+            }
+        }).then(() => {
+            this.isShown = true;
             this.onStateChange.notifyObservers(this);
             this.onStateChange.notifyObservers(this);
-            return Promise.resolve(this);
-        }
+            return this;
+        });
     }
     }
 
 
     public hide(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
     public hide(visibilityFunction?: (template: Template) => Promise<Template>): Promise<Template> {
-        if (visibilityFunction) {
-            return visibilityFunction(this).then(() => {
-                this.onStateChange.notifyObservers(this);
+        return Promise.resolve().then(() => {
+            if (visibilityFunction) {
+                return visibilityFunction(this);
+            } else {
+                // flex? box? should this be configurable easier than the visibilityFunction?
+                this.parent.style.display = 'hide';
                 return this;
                 return this;
-            });
-        } else {
-            this.parent.style.display = 'none';
+            }
+        }).then(() => {
+            this.isShown = false;
             this.onStateChange.notifyObservers(this);
             this.onStateChange.notifyObservers(this);
-            return Promise.resolve(this);
-        }
+            return this;
+        });
+    }
+
+    public dispose() {
+        this.onAppended.clear();
+        this.onEventTriggered.clear();
+        this.onInit.clear();
+        this.onLoaded.clear();
+        this.onStateChange.clear();
+        this.isLoaded = false;
     }
     }
 
 
     // TODO - Should events be removed as well? when are templates disposed?
     // TODO - Should events be removed as well? when are templates disposed?
@@ -286,7 +317,7 @@ export class Template {
                         // strict null checl is working incorrectly, must override:
                         // strict null checl is working incorrectly, must override:
                         let event = this._configuration.events[eventName] || {};
                         let event = this._configuration.events[eventName] || {};
                         selectorsArray.filter(selector => event[selector]).forEach(selector => {
                         selectorsArray.filter(selector => event[selector]).forEach(selector => {
-                            if (selector.indexOf('#') !== 0) {
+                            if (selector && selector.indexOf('#') !== 0) {
                                 selector = '#' + selector;
                                 selector = '#' + selector;
                             }
                             }
                             let htmlElement = <HTMLElement>this.parent.querySelector(selector);
                             let htmlElement = <HTMLElement>this.parent.querySelector(selector);

+ 42 - 59
Viewer/src/viewer/defaultViewer.ts

@@ -1,7 +1,7 @@
 
 
 
 
 import { ViewerConfiguration } from './../configuration/configuration';
 import { ViewerConfiguration } from './../configuration/configuration';
-import { Template } from './../templateManager';
+import { Template, EventCallback } from './../templateManager';
 import { AbstractViewer } from './viewer';
 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 { 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';
 import { CameraBehavior } from '../interfaces';
@@ -27,9 +27,22 @@ export class DefaultViewer extends AbstractViewer {
         this.showLoadingScreen();
         this.showLoadingScreen();
 
 
         // navbar
         // navbar
-        let viewerElement = this.templateManager.getTemplate('viewer');
+        this.initNavbar();
+
+        // close overlay button
+        let closeButton = document.getElementById('close-button');
+        if (closeButton) {
+            closeButton.addEventListener('pointerdown', () => {
+                this.hideOverlayScreen();
+            })
+        }
+
+        return super.onTemplatesLoaded();
+    }
+
+    private initNavbar() {
         let navbar = this.templateManager.getTemplate('navBar');
         let navbar = this.templateManager.getTemplate('navBar');
-        if (viewerElement && navbar) {
+        if (navbar) {
             let navbarHeight = navbar.parent.clientHeight + 'px';
             let navbarHeight = navbar.parent.clientHeight + 'px';
 
 
             let navbarShown: boolean = true;
             let navbarShown: boolean = true;
@@ -61,64 +74,30 @@ export class DefaultViewer extends AbstractViewer {
                 }
                 }
             }
             }
 
 
-
-
-            viewerElement.parent.addEventListener('pointerout', triggerNavbar.bind(this, false));
-            viewerElement.parent.addEventListener('pointerdown', triggerNavbar.bind(this, true));
-            viewerElement.parent.addEventListener('pointerup', triggerNavbar.bind(this, false));
-            navbar.parent.addEventListener('pointerover', triggerNavbar.bind(this, true))
-            // triggerNavbar(false);
-
-            // events registration
-            this.registerNavbarButtons();
-        }
-
-        // close overlay button
-        let closeButton = document.getElementById('close-button');
-        if (closeButton) {
-            closeButton.addEventListener('pointerdown', () => {
-                this.hideOverlayScreen();
-            })
-        }
-
-        return super.onTemplatesLoaded();
-    }
-
-    private registerNavbarButtons() {
-        let isFullscreen = false;
-
-        let navbar = this.templateManager.getTemplate('navBar');
-        let viewerTemplate = this.templateManager.getTemplate('viewer');
-        if (!navbar || !viewerTemplate) return;
-
-        let viewerElement = viewerTemplate.parent;
-
-
-        navbar.onEventTriggered.add((data) => {
-            switch (data.event.type) {
-                case 'pointerdown':
-                    let event: PointerEvent = <PointerEvent>data.event;
-                    if (event.button === 0) {
-                        switch (data.selector) {
-                            case '#fullscreen-button':
-                                if (!isFullscreen) {
-                                    let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
-                                    requestFullScreen.call(viewerElement);
-                                } else {
-                                    let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || (<any>document).mozCancelFullScreen
-                                    exitFullscreen.call(document);
-                                }
-
-                                isFullscreen = !isFullscreen;
-                                break;
-                            case '#help-button':
-                                this.showOverlayScreen('help');
-                                break;
-                        }
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, false), 'pointerout');
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, true), 'pointerdown');
+            this.templateManager.eventManager.registerCallback('viewer', triggerNavbar.bind(this, false), 'pointerup');
+            this.templateManager.eventManager.registerCallback('navBar', triggerNavbar.bind(this, true), 'pointerover');
+
+            // other events
+            let viewerTemplate = this.templateManager.getTemplate('viewer');
+            let viewerElement = viewerTemplate && viewerTemplate.parent;
+            // full screen
+            let triggerFullscren = (eventData: EventCallback) => {
+                if (viewerElement) {
+                    let fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || (<any>document).mozFullScreenElement || (<any>document).msFullscreenElement;
+                    if (!fullscreenElement) {
+                        let requestFullScreen = viewerElement.requestFullscreen || viewerElement.webkitRequestFullscreen || (<any>viewerElement).msRequestFullscreen || (<any>viewerElement).mozRequestFullScreen;
+                        requestFullScreen.call(viewerElement);
+                    } else {
+                        let exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || (<any>document).msExitFullscreen || (<any>document).mozCancelFullScreen
+                        exitFullscreen.call(document);
                     }
                     }
-                    break;
+                }
             }
             }
-        });
+
+            this.templateManager.eventManager.registerCallback('navBar', triggerFullscren, 'pointerdown', '#fullscreen-button');
+        }
     }
     }
 
 
     protected prepareContainerElement() {
     protected prepareContainerElement() {
@@ -228,6 +207,10 @@ export class DefaultViewer extends AbstractViewer {
             ground.rotation.x = Math.PI / 2; // Face up by default.
             ground.rotation.x = Math.PI / 2; // Face up by default.
             ground.receiveShadows = groundConfig.receiveShadows || false;
             ground.receiveShadows = groundConfig.receiveShadows || false;
 
 
+            // position the ground correctly
+            let groundPosition = focusMeshes[0].getHierarchyBoundingVectors().min.y;
+            ground.position.y = groundPosition;
+
             // default values
             // default values
             backgroundMaterial.alpha = 0.9;
             backgroundMaterial.alpha = 0.9;
             backgroundMaterial.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;
             backgroundMaterial.alphaMode = Engine.ALPHA_PREMULTIPLIED_PORTERDUFF;

+ 1 - 0
Viewer/src/viewer/viewer.ts

@@ -145,6 +145,7 @@ export abstract class AbstractViewer {
     }
     }
 
 
     public loadModel(model: any = this.configuration.model, clearScene: boolean = true): Promise<Scene> {
     public loadModel(model: any = this.configuration.model, clearScene: boolean = true): Promise<Scene> {
+        this.configuration.model = model;
         let modelUrl = (typeof model === 'string') ? model : model.url;
         let modelUrl = (typeof model === 'string') ? model : model.url;
         let parts = modelUrl.split('/');
         let parts = modelUrl.split('/');
         let filename = parts.pop();
         let filename = parts.pop();

+ 8 - 2
src/Layer/babylon.highlightlayer.ts

@@ -6,7 +6,7 @@
     class GlowBlurPostProcess extends PostProcess {
     class GlowBlurPostProcess extends PostProcess {
         constructor(name: string, public direction: Vector2, public kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode: number = Texture.BILINEAR_SAMPLINGMODE, engine?: Engine, reusable?: boolean) {
         constructor(name: string, public direction: Vector2, public kernel: number, options: number | PostProcessOptions, camera: Nullable<Camera>, samplingMode: number = Texture.BILINEAR_SAMPLINGMODE, engine?: Engine, reusable?: boolean) {
             super(name, "glowBlurPostProcess", ["screenSize", "direction", "blurWidth"], null, options, camera, samplingMode, engine, reusable);
             super(name, "glowBlurPostProcess", ["screenSize", "direction", "blurWidth"], null, options, camera, samplingMode, engine, reusable);
-
+            
             this.onApplyObservable.add((effect: Effect) => {
             this.onApplyObservable.add((effect: Effect) => {
                 effect.setFloat2("screenSize", this.width, this.height);
                 effect.setFloat2("screenSize", this.width, this.height);
                 effect.setVector2("direction", this.direction);
                 effect.setVector2("direction", this.direction);
@@ -56,6 +56,11 @@
          * The camera attached to the layer.
          * The camera attached to the layer.
          */
          */
         camera: Nullable<Camera>;
         camera: Nullable<Camera>;
+
+        /**
+         * Should we display highlight as a solid stroke?
+         */
+        isStroke?: boolean;
     }
     }
 
 
     /**
     /**
@@ -289,7 +294,8 @@
             this._glowMapMergeEffect = engine.createEffect("glowMapMerge",
             this._glowMapMergeEffect = engine.createEffect("glowMapMerge",
                 [VertexBuffer.PositionKind],
                 [VertexBuffer.PositionKind],
                 ["offset"],
                 ["offset"],
-                ["textureSampler"], "");
+                ["textureSampler"],
+                this._options.isStroke ? "#define STROKE \n" : undefined);
 
 
             // Render target
             // Render target
             this.setMainTextureSize();
             this.setMainTextureSize();

+ 6 - 0
src/Shaders/glowMapMerge.fragment.fx

@@ -10,5 +10,11 @@ void main(void) {
 
 
 	baseColor.a = abs(offset - baseColor.a);
 	baseColor.a = abs(offset - baseColor.a);
 
 
+	#ifdef STROKE
+        float alpha = smoothstep(.0, .1, baseColor.a);
+        baseColor.a = alpha;
+        baseColor.rgb = baseColor.rgb * alpha;
+    #endif
+
 	gl_FragColor = baseColor;
 	gl_FragColor = baseColor;
 }
 }