瀏覽代碼

Add glTF loader extension settings to GLTF tab in inspector

Gary Hsu 7 年之前
父節點
當前提交
1cb983726d
共有 4 個文件被更改,包括 207 次插入20 次删除
  1. 38 0
      inspector/sass/tabs/_gltfTab.scss
  2. 159 9
      inspector/src/tabs/GLTFTab.ts
  3. 4 3
      inspector/src/tsconfig.json
  4. 6 8
      sandbox/index.js

+ 38 - 0
inspector/sass/tabs/_gltfTab.scss

@@ -10,6 +10,44 @@
             margin        : 10px 0 10px 0;
             margin        : 10px 0 10px 0;
         }
         }
 
 
+        .gltf-action {
+            height     : 20px;
+            line-height: 20px;
+            width      : 100%;
+            cursor     : pointer;
+            white-space: nowrap;
+
+            &:hover {
+                background-color: $background-lighter;
+            }
+        }
+
+        .gltf-checkbox {
+            @extend .gltf-action;
+            &:before {
+                width      : 1em;
+                height     : 1em;
+                line-height: 1em;
+                display    : inline-block;
+                font-family: 'FontAwesome', sans-serif;
+                content    : "\f096";
+                margin-right:10px;
+            }
+
+            &.active {
+                &:before {
+                    width      : 1em;
+                    height     : 1em;
+                    line-height: 1em;
+                    display    : inline-block;
+                    font-family: 'FontAwesome', sans-serif;
+                    content    : "\f14a";
+                    color      : $color-bot;
+                    margin-right:10px;
+                }
+            }
+        }
+
         .gltf-input {
         .gltf-input {
             background-color: $background-lighter;
             background-color: $background-lighter;
             border          : none;
             border          : none;

+ 159 - 9
inspector/src/tabs/GLTFTab.ts

@@ -1,32 +1,182 @@
 /// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
 /// <reference path="../../../dist/preview release/gltf2Interface/babylon.glTF2Interface.d.ts"/>
+/// <reference path="../../../dist/preview release/loaders/babylon.glTF2FileLoader.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 /// <reference path="../../../dist/preview release/serializers/babylon.glTF2Serializer.d.ts"/>
 
 
+declare function Split(elements: HTMLElement[], options: any): any;
+
 module INSPECTOR {
 module INSPECTOR {
     export class GLTFTab extends Tab {
     export class GLTFTab extends Tab {
+        private static _LoaderExtensionSettings: {
+            [extensionName: string]: {
+                [propertyName: string]: any
+            }
+        };
+
+        private _inspector: Inspector;
+        private _actions: HTMLDivElement;
+        private _detailsPanel: DetailPanel | null = null;
+        private _split: any;
+
         constructor(tabbar: TabBar, inspector: Inspector) {
         constructor(tabbar: TabBar, inspector: Inspector) {
             super(tabbar, 'GLTF');
             super(tabbar, 'GLTF');
 
 
+            this._inspector = inspector;
             this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
             this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
-            const actions = Helpers.CreateDiv('gltf-actions', this._panel) as HTMLDivElement;
-            this._addExport(inspector, actions);
+            this._actions = Helpers.CreateDiv('gltf-actions', this._panel) as HTMLDivElement;
+            this._actions.addEventListener('click', event => {
+                this._closeDetailsPanel();
+            });
+
+            this._addImport();
+            this._addExport();
         }
         }
 
 
         public dispose() {
         public dispose() {
-            // Nothing to dispose
+            if (this._detailsPanel) {
+                this._detailsPanel.dispose();
+            }
+        }
+
+        private _addImport() {
+            if (!GLTFTab._LoaderExtensionSettings) {
+                BABYLON.SceneLoader.OnPluginActivatedObservable.add(plugin => {
+                    if (plugin.name === "gltf") {
+                        const loader = plugin as BABYLON.GLTFFileLoader;
+                        loader.onExtensionLoadedObservable.add(extension => {
+                            const settings = GLTFTab._LoaderExtensionSettings[extension.name];
+                            for (const key in settings) {
+                                (extension as any)[key] = settings[key];
+                            }
+                        });
+                    }
+                });
+            }
+
+            const importActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+
+            this._ensureLoaderExtensionSettingsAsync().then(() => {
+                const title = Helpers.CreateDiv('gltf-title', importActions);
+                title.textContent = 'Import';
+
+                const extensionActions = Helpers.CreateDiv('gltf-actions', importActions) as HTMLDivElement;
+
+                const extensionsTitle = Helpers.CreateDiv('gltf-title', extensionActions) as HTMLDivElement;
+                extensionsTitle.textContent = "Extensions";
+
+                for (const name in GLTFTab._LoaderExtensionSettings) {
+                    const settings = GLTFTab._LoaderExtensionSettings[name];
+
+                    const extensionAction = Helpers.CreateDiv('gltf-action', extensionActions);
+                    extensionAction.addEventListener('click', event => {
+                        if (this._updateLoaderExtensionDetails(name)) {
+                            event.stopPropagation();
+                        }
+                    });
+
+                    const checkbox = Helpers.CreateElement('span', 'gltf-checkbox', extensionAction);
+
+                    if (settings.enabled) {
+                        checkbox.classList.add('action', 'active');
+                    }
+
+                    checkbox.addEventListener('click', () => {
+                        checkbox.classList.toggle('active');
+                        settings.enabled = checkbox.classList.contains('active');
+                    });
+
+                    const label = Helpers.CreateElement('span', null, extensionAction);
+                    label.textContent = name;
+                }
+            });
         }
         }
 
 
-        private _addExport(inspector: Inspector, actions: HTMLDivElement) {
-            const title = Helpers.CreateDiv('gltf-title', actions);
+        private _ensureLoaderExtensionSettingsAsync(): Promise<void> {
+            if (GLTFTab._LoaderExtensionSettings) {
+                return Promise.resolve();
+            }
+
+            GLTFTab._LoaderExtensionSettings = {};
+
+            const engine = new BABYLON.NullEngine();
+            const scene = new BABYLON.Scene(engine);
+            const loader = new BABYLON.GLTF2.GLTFLoader();
+            loader.onExtensionLoadedObservable.add(extension => {
+                const settings: { [propertyName: string]: any } = {};
+                for (const key of Object.keys(extension)) {
+                    if (key !== "name" && key[0] !== '_') {
+                        const value = (extension as any)[key];
+                        if (typeof value !== "object") {
+                            settings[key] = value;
+                        }
+                    }
+                }
+
+                GLTFTab._LoaderExtensionSettings[extension.name] = settings;
+            });
+
+            const data = { json: {}, bin: null };
+            return loader.importMeshAsync([], scene, data, "").then(() => {
+                scene.dispose();
+                engine.dispose();
+            });
+        }
+
+        private _updateLoaderExtensionDetails(name: string): boolean {
+            const settings = GLTFTab._LoaderExtensionSettings[name];
+            if (Object.keys(settings).length === 1) {
+                return false;
+            }
+
+            if (!this._detailsPanel) {
+                this._detailsPanel = new DetailPanel();
+                this._panel.appendChild(this._detailsPanel.toHtml());
+
+                this._split = Split([this._actions, this._detailsPanel.toHtml()], {
+                    blockDrag: this._inspector.popupMode,
+                    sizes: [50, 50],
+                    direction: 'vertical'
+                });
+            }
+
+            this._detailsPanel.clean();
+
+            const details = new Array<PropertyLine>();
+            for (const key in settings) {
+                if (key !== "enabled") {
+                    details.push(new PropertyLine(new Property(key, settings)));
+                }
+            }
+            this._detailsPanel.details = details;
+
+            return true;
+        }
+
+        private _closeDetailsPanel(): void {
+            if (this._detailsPanel) {
+                this._detailsPanel.toHtml().remove();
+                this._detailsPanel.dispose();
+                this._detailsPanel = null;
+            }
+
+            if (this._split) {
+                this._split.destroy();
+                delete this._split;
+            }
+        }
+
+        private _addExport() {
+            const exportActions = Helpers.CreateDiv(null, this._actions) as HTMLDivElement;
+
+            const title = Helpers.CreateDiv('gltf-title', exportActions);
             title.textContent = 'Export';
             title.textContent = 'Export';
 
 
-            const name = Helpers.CreateInput('gltf-input', actions);
+            const name = Helpers.CreateInput('gltf-input', exportActions);
             name.placeholder = "File name...";
             name.placeholder = "File name...";
 
 
-            const button = Helpers.CreateElement('button', 'gltf-button', actions) as HTMLButtonElement;
+            const button = Helpers.CreateElement('button', 'gltf-button', exportActions) as HTMLButtonElement;
             button.innerText = 'Export GLB';
             button.innerText = 'Export GLB';
-
             button.addEventListener('click', () => {
             button.addEventListener('click', () => {
-                BABYLON.GLTF2Export.GLBAsync(inspector.scene, name.value || "scene", {
+                BABYLON.GLTF2Export.GLBAsync(this._inspector.scene, name.value || "scene", {
                     shouldExportTransformNode: transformNode => !GLTFTab._IsSkyBox(transformNode)
                     shouldExportTransformNode: transformNode => !GLTFTab._IsSkyBox(transformNode)
                 }).then((glb) => {
                 }).then((glb) => {
                     glb.downloadFiles();
                     glb.downloadFiles();

+ 4 - 3
inspector/src/tsconfig.json

@@ -1,12 +1,13 @@
 {
 {
     "compilerOptions": {
     "compilerOptions": {
         "experimentalDecorators": true,
         "experimentalDecorators": true,
-        "module": "commonjs", 
+        "module": "commonjs",
         "target": "es5",
         "target": "es5",
         "noImplicitAny": true,
         "noImplicitAny": true,
         "noImplicitReturns": true,
         "noImplicitReturns": true,
         "noImplicitThis": true,
         "noImplicitThis": true,
-        "noUnusedLocals": true,    
-        "strictNullChecks": true
+        "noUnusedLocals": true,
+        "strictNullChecks": true,
+        "lib": ["dom", "es2015.promise", "es5"]
     }
     }
 }
 }

+ 6 - 8
sandbox/index.js

@@ -83,17 +83,15 @@ if (BABYLON.Engine.isSupported()) {
 
 
     var sceneLoaded = function (sceneFile, babylonScene) {
     var sceneLoaded = function (sceneFile, babylonScene) {
         function displayDebugLayerAndLogs() {
         function displayDebugLayerAndLogs() {
-            currentScene.debugLayer._displayLogs = true;
             enableDebugLayer = true;
             enableDebugLayer = true;
             currentScene.debugLayer.show();
             currentScene.debugLayer.show();
         };
         };
         function hideDebugLayerAndLogs() {
         function hideDebugLayerAndLogs() {
-            currentScene.debugLayer._displayLogs = false;
             enableDebugLayer = false;
             enableDebugLayer = false;
             currentScene.debugLayer.hide();
             currentScene.debugLayer.hide();
         };
         };
-    
-            if (enableDebugLayer) {
+
+        if (enableDebugLayer) {
             hideDebugLayerAndLogs();
             hideDebugLayerAndLogs();
         }
         }
 
 
@@ -248,9 +246,9 @@ if (BABYLON.Engine.isSupported()) {
         }).bind(this);
         }).bind(this);
         filesInput.monitorElementForDragNDrop(canvas);
         filesInput.monitorElementForDragNDrop(canvas);
 
 
-        window.addEventListener("keydown", function (evt) {
+        window.addEventListener("keydown", function (event) {
             // Press R to reload
             // Press R to reload
-            if (evt.keyCode === 82 && !enableDebugLayer) {
+            if (event.keyCode === 82 && event.target.nodeName !== "INPUT") {
                 filesInput.reload();
                 filesInput.reload();
             }
             }
         });
         });
@@ -290,9 +288,9 @@ if (BABYLON.Engine.isSupported()) {
         }
         }
     }, false);
     }, false);
 
 
-    window.addEventListener("keydown", function (evt) {
+    window.addEventListener("keydown", function (event) {
         // Press space to toggle footer
         // Press space to toggle footer
-        if (evt.keyCode === 32 && !enableDebugLayer) {
+        if (event.keyCode === 32 && event.target.nodeName !== "INPUT") {
             if (footer.style.display === "none") {
             if (footer.style.display === "none") {
                 footer.style.display = "block";
                 footer.style.display = "block";
             }
             }