瀏覽代碼

Merge pull request #1899 from Temechon/master

Inspector - new tab (textures)
Temechon 8 年之前
父節點
當前提交
3aa62f6bd8

+ 2 - 0
Tools/Gulp/config.json

@@ -578,6 +578,7 @@
                     "../../inspector/src/gui/BasicElement.ts",
                     "../../inspector/src/adapters/Adapter.ts",
                     "../../inspector/src/adapters/CameraAdapter.ts",
+                    "../../inspector/src/adapters/TextureAdapter.ts",
                     "../../inspector/src/adapters/Canvas2DAdapter.ts",
                     "../../inspector/src/adapters/LightAdapter.ts",
                     "../../inspector/src/adapters/MaterialAdapter.ts",
@@ -596,6 +597,7 @@
                     "../../inspector/src/tabs/Tab.ts",
                     "../../inspector/src/tabs/PropertyTab.ts",
                     "../../inspector/src/tabs/CameraTab.ts",
+                    "../../inspector/src/tabs/TextureTab.ts",
                     "../../inspector/src/tabs/Canvas2DTab.ts",
                     "../../inspector/src/tabs/LightTab.ts",
                     "../../inspector/src/tabs/MaterialTab.ts",

File diff suppressed because it is too large
+ 6 - 6
dist/preview release/inspector/babylon.inspector.bundle.js


+ 1 - 0
dist/preview release/inspector/babylon.inspector.css

@@ -243,6 +243,7 @@
     overflow-x: hidden;
     height: calc(50% - 32px - 30px); }
     .insp-wrapper .insp-tree .line {
+      padding: 3px;
       cursor: pointer; }
       .insp-wrapper .insp-tree .line:hover {
         background-color: #2c2c2c; }

+ 88 - 1
dist/preview release/inspector/babylon.inspector.d.ts

@@ -94,6 +94,10 @@ declare module INSPECTOR {
             type: typeof BABYLON.ArcRotateCamera;
             properties: string[];
         };
+        'FreeCamera': {
+            type: typeof BABYLON.FreeCamera;
+            properties: string[];
+        };
         'Scene': {
             type: typeof BABYLON.Scene;
             properties: string[];
@@ -177,6 +181,10 @@ declare module INSPECTOR {
         correspondsTo(obj: any): boolean;
         /** Returns the adapter unique name */
         readonly name: string;
+        /**
+         * Returns the actual object used for this adapter
+         */
+        readonly object: any;
         /** Returns the list of tools available for this adapter */
         abstract getTools(): Array<AbstractTreeTool>;
         /** Should be overriden in subclasses */
@@ -185,6 +193,33 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class CameraAdapter extends Adapter implements ICameraPOV {
+        constructor(obj: BABYLON.Camera);
+        /** Returns the name displayed in the tree */
+        id(): string;
+        /** Returns the type of this object - displayed in the tree */
+        type(): string;
+        /** Returns the list of properties to be displayed for this adapter */
+        getProperties(): Array<PropertyLine>;
+        getTools(): Array<AbstractTreeTool>;
+        setPOV(): void;
+    }
+}
+
+declare module INSPECTOR {
+    class TextureAdapter extends Adapter {
+        constructor(obj: BABYLON.BaseTexture);
+        /** Returns the name displayed in the tree */
+        id(): string;
+        /** Returns the type of this object - displayed in the tree */
+        type(): string;
+        /** Returns the list of properties to be displayed for this adapter */
+        getProperties(): Array<PropertyLine>;
+        getTools(): Array<AbstractTreeTool>;
+    }
+}
+
+declare module INSPECTOR {
     class Canvas2DAdapter extends Adapter implements IToolVisible, IToolDebug {
         constructor(obj: any);
         /** Returns the name displayed in the tree */
@@ -596,6 +631,10 @@ declare module INSPECTOR {
         filter(str: string): void;
         /** Dispose properly this tab */
         abstract dispose(): any;
+        /** Select an item in the tree */
+        select(item: TreeItem): void;
+        /** Highlight the given node, and downplay all others */
+        highlightNode(item?: TreeItem): void;
         /**
          * Returns the total width in pixel of this tab, 0 by default
         */
@@ -639,6 +678,35 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    class CameraTab extends PropertyTab {
+        constructor(tabbar: TabBar, inspector: Inspector);
+        protected _getTree(): Array<TreeItem>;
+    }
+}
+
+declare module INSPECTOR {
+    class TextureTab extends Tab {
+        private _inspector;
+        /** The panel containing a list of items */
+        protected _treePanel: HTMLElement;
+        protected _treeItems: Array<TreeItem>;
+        private _imagePanel;
+        constructor(tabbar: TabBar, inspector: Inspector);
+        dispose(): void;
+        update(_items?: Array<TreeItem>): void;
+        private _getTree();
+        /** Display the details of the given item */
+        displayDetails(item: TreeItem): void;
+        /** Select an item in the tree */
+        select(item: TreeItem): void;
+        /** Set the given item as active in the tree */
+        activateNode(item: TreeItem): void;
+        /** Highlight the given node, and downplay all others */
+        highlightNode(item?: TreeItem): void;
+    }
+}
+
+declare module INSPECTOR {
     class Canvas2DTab extends PropertyTab {
         constructor(tabbar: TabBar, inspector: Inspector);
         protected _getTree(): Array<TreeItem>;
@@ -909,12 +977,16 @@ declare module INSPECTOR {
         private _tools;
         children: Array<TreeItem>;
         private _lineContent;
-        constructor(tab: PropertyTab, obj: Adapter);
+        constructor(tab: Tab, obj: Adapter);
         /** Returns the item ID == its adapter ID */
         readonly id: string;
         /** Add the given item as a child of this one */
         add(child: TreeItem): void;
         /**
+         * Returns the original adapter
+         */
+        readonly adapter: Adapter;
+        /**
          * Function used to compare this item to another tree item.
          * Returns the alphabetical sort of the adapter ID
          */
@@ -983,6 +1055,21 @@ declare module INSPECTOR {
 }
 
 declare module INSPECTOR {
+    interface ICameraPOV {
+        setPOV: () => void;
+    }
+    /**
+     *
+     */
+    class CameraPOV extends AbstractTreeTool {
+        private cameraPOV;
+        constructor(camera: ICameraPOV);
+        protected action(): void;
+        private _gotoPOV();
+    }
+}
+
+declare module INSPECTOR {
     /** Any object implementing this interface should
      * provide methods to toggle its visibility
      */

+ 333 - 32
dist/preview release/inspector/babylon.inspector.js

@@ -336,6 +336,7 @@ var INSPECTOR;
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
             properties: [
+                'position',
                 'alpha',
                 'beta',
                 'radius',
@@ -354,6 +355,21 @@ var INSPECTOR;
                 'checkCollisions'
             ]
         },
+        'FreeCamera': {
+            type: BABYLON.FreeCamera,
+            properties: [
+                'position',
+                'ellipsoid',
+                'applyGravity',
+                'angularSensibility',
+                'keysUp',
+                'keysDown',
+                'keysLeft',
+                'keysRight',
+                'onCollide',
+                'checkCollisions'
+            ]
+        },
         'Scene': {
             type: BABYLON.Scene,
             properties: [
@@ -570,6 +586,16 @@ var INSPECTOR;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(Adapter.prototype, "object", {
+            /**
+             * Returns the actual object used for this adapter
+             */
+            get: function () {
+                return this._obj;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /** Should be overriden in subclasses */
         Adapter.prototype.highlight = function (b) { };
         ;
@@ -589,6 +615,110 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 var INSPECTOR;
 (function (INSPECTOR) {
+    var CameraAdapter = (function (_super) {
+        __extends(CameraAdapter, _super);
+        function CameraAdapter(obj) {
+            return _super.call(this, obj) || this;
+        }
+        /** Returns the name displayed in the tree */
+        CameraAdapter.prototype.id = function () {
+            var str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        };
+        /** Returns the type of this object - displayed in the tree */
+        CameraAdapter.prototype.type = function () {
+            return INSPECTOR.Helpers.GET_TYPE(this._obj);
+        };
+        /** Returns the list of properties to be displayed for this adapter */
+        CameraAdapter.prototype.getProperties = function () {
+            var propertiesLines = [];
+            var camToDisplay = [];
+            // The if is there to work with the min version of babylon
+            if (this._obj instanceof BABYLON.ArcRotateCamera) {
+                camToDisplay = INSPECTOR.PROPERTIES['ArcRotateCamera'].properties;
+            }
+            else if (this._obj instanceof BABYLON.FreeCamera) {
+                camToDisplay = INSPECTOR.PROPERTIES['FreeCamera'].properties;
+            }
+            for (var _i = 0, camToDisplay_1 = camToDisplay; _i < camToDisplay_1.length; _i++) {
+                var dirty = camToDisplay_1[_i];
+                var infos = new INSPECTOR.Property(dirty, this._obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            return propertiesLines;
+        };
+        CameraAdapter.prototype.getTools = function () {
+            var tools = [];
+            // tools.push(new Checkbox(this));
+            tools.push(new INSPECTOR.CameraPOV(this));
+            return tools;
+        };
+        CameraAdapter.prototype.setPOV = function () {
+            this._obj.getScene().activeCamera = this._obj;
+        };
+        return CameraAdapter;
+    }(INSPECTOR.Adapter));
+    INSPECTOR.CameraAdapter = CameraAdapter;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=CameraAdapter.js.map
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
+    var TextureAdapter = (function (_super) {
+        __extends(TextureAdapter, _super);
+        function TextureAdapter(obj) {
+            return _super.call(this, obj) || this;
+        }
+        /** Returns the name displayed in the tree */
+        TextureAdapter.prototype.id = function () {
+            var str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        };
+        /** Returns the type of this object - displayed in the tree */
+        TextureAdapter.prototype.type = function () {
+            return INSPECTOR.Helpers.GET_TYPE(this._obj);
+        };
+        /** Returns the list of properties to be displayed for this adapter */
+        TextureAdapter.prototype.getProperties = function () {
+            var propertiesLines = [];
+            for (var _i = 0, _a = INSPECTOR.PROPERTIES['Texture'].properties; _i < _a.length; _i++) {
+                var dirty = _a[_i];
+                var infos = new INSPECTOR.Property(dirty, this._obj);
+                propertiesLines.push(new INSPECTOR.PropertyLine(infos));
+            }
+            return propertiesLines;
+        };
+        TextureAdapter.prototype.getTools = function () {
+            var tools = [];
+            // tools.push(new CameraPOV(this));
+            return tools;
+        };
+        return TextureAdapter;
+    }(INSPECTOR.Adapter));
+    INSPECTOR.TextureAdapter = TextureAdapter;
+})(INSPECTOR || (INSPECTOR = {}));
+
+//# sourceMappingURL=TextureAdapter.js.map
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
     var Canvas2DAdapter = (function (_super) {
         __extends(Canvas2DAdapter, _super);
         function Canvas2DAdapter(obj) {
@@ -1694,8 +1824,6 @@ var INSPECTOR;
     INSPECTOR.SearchBar = SearchBar;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=SearchBar.js.map
-
 var __extends = (this && this.__extends) || function (d, b) {
     for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
     function __() { this.constructor = d; }
@@ -1737,8 +1865,6 @@ var INSPECTOR;
     INSPECTOR.TextureElement = TextureElement;
 })(INSPECTOR || (INSPECTOR = {}));
 
-//# sourceMappingURL=TextureElement.js.map
-
 var INSPECTOR;
 (function (INSPECTOR) {
     /**
@@ -2014,6 +2140,14 @@ var INSPECTOR;
         /** Add this in the propertytab with the searchbar */
         Tab.prototype.filter = function (str) { };
         ;
+        /** Select an item in the tree */
+        Tab.prototype.select = function (item) {
+            // To define in subclasses if needed 
+        };
+        /** Highlight the given node, and downplay all others */
+        Tab.prototype.highlightNode = function (item) {
+            // To define in subclasses if needed
+        };
         /**
          * Returns the total width in pixel of this tab, 0 by default
         */
@@ -2171,6 +2305,150 @@ var __extends = (this && this.__extends) || function (d, b) {
 };
 var INSPECTOR;
 (function (INSPECTOR) {
+    var CameraTab = (function (_super) {
+        __extends(CameraTab, _super);
+        function CameraTab(tabbar, inspector) {
+            return _super.call(this, tabbar, 'Camera', inspector) || this;
+        }
+        /* Overrides super */
+        CameraTab.prototype._getTree = function () {
+            var arr = [];
+            // get all cameras from the first scene
+            var instances = this._inspector.scene;
+            for (var _i = 0, _a = instances.cameras; _i < _a.length; _i++) {
+                var camera = _a[_i];
+                arr.push(new INSPECTOR.TreeItem(this, new INSPECTOR.CameraAdapter(camera)));
+            }
+            return arr;
+        };
+        return CameraTab;
+    }(INSPECTOR.PropertyTab));
+    INSPECTOR.CameraTab = CameraTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
+    var TextureTab = (function (_super) {
+        __extends(TextureTab, _super);
+        function TextureTab(tabbar, inspector) {
+            var _this = _super.call(this, tabbar, 'Textures') || this;
+            _this._treeItems = [];
+            _this._inspector = inspector;
+            // Build the properties panel : a div that will contains the tree and the detail panel
+            _this._panel = INSPECTOR.Helpers.CreateDiv('tab-panel');
+            // Build the treepanel
+            _this._treePanel = INSPECTOR.Helpers.CreateDiv('insp-tree', _this._panel);
+            _this._imagePanel = INSPECTOR.Helpers.CreateDiv('image-panel', _this._panel);
+            Split([_this._treePanel, _this._imagePanel], {
+                blockDrag: _this._inspector.popupMode,
+                direction: 'vertical'
+            });
+            _this.update();
+            return _this;
+        }
+        TextureTab.prototype.dispose = function () {
+            // Nothing to dispose
+        };
+        TextureTab.prototype.update = function (_items) {
+            var items;
+            if (_items) {
+                items = _items;
+            }
+            else {
+                // Rebuild the tree
+                this._treeItems = this._getTree();
+                items = this._treeItems;
+            }
+            // Clean the tree
+            INSPECTOR.Helpers.CleanDiv(this._treePanel);
+            INSPECTOR.Helpers.CleanDiv(this._imagePanel);
+            // Sort items alphabetically
+            items.sort(function (item1, item2) {
+                return item1.compareTo(item2);
+            });
+            // Display items
+            for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
+                var item = items_1[_i];
+                this._treePanel.appendChild(item.toHtml());
+            }
+        };
+        /* Overrides super */
+        TextureTab.prototype._getTree = function () {
+            var arr = [];
+            // get all cameras from the first scene
+            var instances = this._inspector.scene;
+            for (var _i = 0, _a = instances.textures; _i < _a.length; _i++) {
+                var tex = _a[_i];
+                arr.push(new INSPECTOR.TreeItem(this, new INSPECTOR.TextureAdapter(tex)));
+            }
+            return arr;
+        };
+        /** Display the details of the given item */
+        TextureTab.prototype.displayDetails = function (item) {
+            // Remove active state on all items
+            this.activateNode(item);
+            INSPECTOR.Helpers.CleanDiv(this._imagePanel);
+            // Get the texture object
+            var texture = item.adapter.object;
+            var img = INSPECTOR.Helpers.CreateElement('img', '', this._imagePanel);
+            // If an url is present, the texture is an image
+            if (texture.url) {
+                img.src = texture.url;
+            }
+            else if (texture['_canvas']) {
+                // Dynamic texture
+                var base64Image = texture['_canvas'].toDataURL("image/png");
+                img.src = base64Image;
+            }
+        };
+        /** Select an item in the tree */
+        TextureTab.prototype.select = function (item) {
+            // Remove the node highlight
+            this.highlightNode();
+            // Active the node
+            this.activateNode(item);
+            // Display its details
+            this.displayDetails(item);
+        };
+        /** Set the given item as active in the tree */
+        TextureTab.prototype.activateNode = function (item) {
+            if (this._treeItems) {
+                for (var _i = 0, _a = this._treeItems; _i < _a.length; _i++) {
+                    var node = _a[_i];
+                    node.active(false);
+                }
+            }
+            item.active(true);
+        };
+        /** Highlight the given node, and downplay all others */
+        TextureTab.prototype.highlightNode = function (item) {
+            if (this._treeItems) {
+                for (var _i = 0, _a = this._treeItems; _i < _a.length; _i++) {
+                    var node = _a[_i];
+                    node.highlight(false);
+                }
+            }
+            if (item) {
+                item.highlight(true);
+            }
+        };
+        return TextureTab;
+    }(INSPECTOR.Tab));
+    INSPECTOR.TextureTab = TextureTab;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
     var Canvas2DTab = (function (_super) {
         __extends(Canvas2DTab, _super);
         function Canvas2DTab(tabbar, inspector) {
@@ -2633,34 +2911,6 @@ var INSPECTOR;
                 inside = this._beautify(inside, level + 1);
                 return this._beautify(left, level) + '{\n' + inside + '\n' + spaces + '}\n' + this._beautify(right, level);
             }
-            // // Replace bracket with @1 and @2 with correct indentation
-            // let newInside          = "@1\n\t" + inside + "\n@2";
-            // newInside              = newInside.replace(/;\n/g, ";\n\t");
-            // glsl                   = glsl.replace(insideWithBrackets, newInside);
-            // firstBracket       = glsl.indexOf('{');
-            // lastBracket        = glsl.lastIndexOf('}');
-            // }
-            // console.log(glsl);
-            // let regex = /(\{(?:\{??[^\{]*?}))+/gmi;
-            // let tmp = glsl;
-            // let m;
-            // while ((m = regex.exec(tmp)) !== null) {
-            //     // This is necessary to avoid infinite loops with zero-width matches
-            //     if (m.index === regex.lastIndex) {
-            //         regex.lastIndex++;
-            //     }                
-            //     // The result can be accessed through the `m`-variable.
-            //     m.forEach((match, groupIndex) => {
-            //         // Remove the first and the last bracket only
-            //         let matchWithoutBrackets = match.replace(/{/, "").replace(/}/, "");
-            //         // Indent the content inside brackets with tabs
-            //         glsl = glsl.replace(match, `{\n\t${matchWithoutBrackets}\n}\n`);
-            //         // removes the match from tmp
-            //         tmp = tmp.replace(match, "");
-            //         // and continue
-            //     });
-            // }
-            // return 
         };
         return ShaderTab;
     }(INSPECTOR.Tab));
@@ -3094,6 +3344,7 @@ var INSPECTOR;
             /** The list of tabs visible, displayed in the tab bar */
             _this._visibleTabs = [];
             _this._inspector = inspector;
+            _this._tabs.push(new INSPECTOR.TextureTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.SceneTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.ConsoleTab(_this, _this._inspector));
             _this._tabs.push(new INSPECTOR.StatsTab(_this, _this._inspector));
@@ -3106,6 +3357,7 @@ var INSPECTOR;
                 _this._tabs.push(new INSPECTOR.Canvas2DTab(_this, _this._inspector));
             }
             _this._tabs.push(new INSPECTOR.MaterialTab(_this, _this._inspector));
+            _this._tabs.push(new INSPECTOR.CameraTab(_this, _this._inspector));
             _this._toolBar = new INSPECTOR.Toolbar(_this._inspector);
             _this._build();
             // Active the first tab
@@ -3689,6 +3941,16 @@ var INSPECTOR;
             this.children.push(child);
             this.update();
         };
+        Object.defineProperty(TreeItem.prototype, "adapter", {
+            /**
+             * Returns the original adapter
+             */
+            get: function () {
+                return this._adapter;
+            },
+            enumerable: true,
+            configurable: true
+        });
         /**
          * Function used to compare this item to another tree item.
          * Returns the alphabetical sort of the adapter ID
@@ -3911,6 +4173,45 @@ var __extends = (this && this.__extends) || function (d, b) {
 var INSPECTOR;
 (function (INSPECTOR) {
     /**
+     *
+     */
+    var CameraPOV = (function (_super) {
+        __extends(CameraPOV, _super);
+        function CameraPOV(camera) {
+            var _this = _super.call(this) || this;
+            _this.cameraPOV = camera;
+            _this._elem.classList.add('fa-video-camera');
+            return _this;
+        }
+        CameraPOV.prototype.action = function () {
+            _super.prototype.action.call(this);
+            this._gotoPOV();
+        };
+        CameraPOV.prototype._gotoPOV = function () {
+            var actives = INSPECTOR.Inspector.DOCUMENT.querySelectorAll(".fa-video-camera.active");
+            console.log(actives);
+            for (var i = 0; i < actives.length; i++) {
+                actives[i].classList.remove('active');
+            }
+            //if (this._on) {
+            // set icon camera
+            this._elem.classList.add('active');
+            //}
+            this.cameraPOV.setPOV();
+        };
+        return CameraPOV;
+    }(INSPECTOR.AbstractTreeTool));
+    INSPECTOR.CameraPOV = CameraPOV;
+})(INSPECTOR || (INSPECTOR = {}));
+
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
+var INSPECTOR;
+(function (INSPECTOR) {
+    /**
      * Checkbox to display/hide the primitive
      */
     var Checkbox = (function (_super) {

File diff suppressed because it is too large
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


+ 1 - 0
inspector/sass/_tree.scss

@@ -15,6 +15,7 @@
   
     
     .line {
+        padding:3px;
         cursor:pointer;
         // Hover
         &:hover {

+ 25 - 18
inspector/src/adapters/Adapter.ts

@@ -1,36 +1,36 @@
 module INSPECTOR {
-    
+
     export interface IHighlight {
-        highlight : (b:boolean) => void
+        highlight: (b: boolean) => void
     }
 
     export abstract class Adapter implements IHighlight {
-        
-        protected _obj      : any;
+
+        protected _obj: any;
         // a unique name for this adapter, to retrieve its own key in the local storage
         private static _name: string = BABYLON.Geometry.RandomId();
-        
-        constructor(obj:any) {
+
+        constructor(obj: any) {
             this._obj = obj;
         }
-        
+
 
         /** Returns the name displayed in the tree */
-        public abstract id()           : string;
-        
+        public abstract id(): string;
+
         /** Returns the type of this object - displayed in the tree */
-        public abstract type()         : string;
-        
+        public abstract type(): string;
+
         /** Returns the list of properties to be displayed for this adapter */
         public abstract getProperties(): Array<PropertyLine>;
-        
+
         /** Returns the actual object behind this adapter */
-        public get actualObject()      : any {
-            return this._obj; 
+        public get actualObject(): any {
+            return this._obj;
         }
-        
+
         /** Returns true if the given object correspond to this  */
-        public correspondsTo(obj:any) {
+        public correspondsTo(obj: any) {
             return obj === this._obj;
         }
 
@@ -39,10 +39,17 @@ module INSPECTOR {
             return Adapter._name;
         }
 
+        /**
+         * Returns the actual object used for this adapter
+         */
+        public get object(): any {
+            return this._obj;
+        }
+
         /** Returns the list of tools available for this adapter */
-        public abstract getTools() : Array<AbstractTreeTool>;
+        public abstract getTools(): Array<AbstractTreeTool>;
 
         /** Should be overriden in subclasses */
-        public highlight(b:boolean) {};
+        public highlight(b: boolean) { };
     }
 }

+ 41 - 0
inspector/src/adapters/TextureAdapter.ts

@@ -0,0 +1,41 @@
+module INSPECTOR {
+
+    export class TextureAdapter
+        extends Adapter {
+
+        constructor(obj: BABYLON.BaseTexture) {
+            super(obj);
+        }
+
+        /** Returns the name displayed in the tree */
+        public id(): string {
+            let str = '';
+            if (this._obj.name) {
+                str = this._obj.name;
+            } // otherwise nothing displayed        
+            return str;
+        }
+
+        /** Returns the type of this object - displayed in the tree */
+        public type(): string {
+            return Helpers.GET_TYPE(this._obj);
+        }
+
+        /** Returns the list of properties to be displayed for this adapter */
+        public getProperties(): Array<PropertyLine> {
+            let propertiesLines: Array<PropertyLine> = [];
+            for (let dirty of PROPERTIES['Texture'].properties) {
+                let infos = new Property(dirty, this._obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+            return propertiesLines;
+        }
+
+        public getTools(): Array<AbstractTreeTool> {
+            let tools = [];
+            // tools.push(new CameraPOV(this));
+            return tools;
+        }
+
+    }
+}

+ 135 - 134
inspector/src/properties.ts

@@ -1,75 +1,75 @@
 module INSPECTOR {
-    
+
     export const PROPERTIES = {
         /** Format the given object : 
          * If a format function exists, returns the result of this function.
          * If this function doesn't exists, return the object type instead */
-        format : (obj:any) => {
-            let type = Helpers.GET_TYPE(obj) ||  'type_not_defined';
+        format: (obj: any) => {
+            let type = Helpers.GET_TYPE(obj) || 'type_not_defined';
             if (PROPERTIES[type] && PROPERTIES[type].format) {
                 return PROPERTIES[type].format(obj);
             } else {
                 return Helpers.GET_TYPE(obj);
             }
         },
-        'type_not_defined' : {
-            properties : [],
+        'type_not_defined': {
+            properties: [],
             format: () => ''
         },
-        
-        'Vector2' : {
+
+        'Vector2': {
             type: BABYLON.Vector2,
             properties: ['x', 'y'],
-            format: (vec : BABYLON.Vector2) => {return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}`;}
+            format: (vec: BABYLON.Vector2) => { return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}`; }
         },
-        'Vector3' : {
+        'Vector3': {
             type: BABYLON.Vector3,
             properties: ['x', 'y', 'z'],
-            format: (vec : BABYLON.Vector3) => {return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}, z:${Helpers.Trunc(vec.z)}`} 
+            format: (vec: BABYLON.Vector3) => { return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}, z:${Helpers.Trunc(vec.z)}` }
         },
-        'Color3' : {
+        'Color3': {
             type: BABYLON.Color3,
-            properties : ['r', 'g', 'b'],
-            format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}`}
+            properties: ['r', 'g', 'b'],
+            format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}` }
         },
-        'Quaternion' : {
+        'Quaternion': {
             type: BABYLON.Quaternion,
-            properties : ['x', 'y', 'z', 'w']
+            properties: ['x', 'y', 'z', 'w']
         },
-        'Size' : {
+        'Size': {
             type: BABYLON.Size,
-            properties :['width', 'height'],
-            format: (size:BABYLON.Size) => { return `Size - w:${Helpers.Trunc(size.width)}, h:${Helpers.Trunc(size.height)}`} 
+            properties: ['width', 'height'],
+            format: (size: BABYLON.Size) => { return `Size - w:${Helpers.Trunc(size.width)}, h:${Helpers.Trunc(size.height)}` }
         },
-        'Texture' : {
+        'Texture': {
             type: BABYLON.Texture,
-            properties :[
-                'hasAlpha', 
-                'level', 
-                'name', 
-                'wrapU', 
-                'wrapV', 
-                'uScale', 
-                'vScale', 
-                'uAng', 
-                'vAng', 
-                'wAng', 
-                'uOffset', 
+            properties: [
+                'hasAlpha',
+                'level',
+                'name',
+                'wrapU',
+                'wrapV',
+                'uScale',
+                'vScale',
+                'uAng',
+                'vAng',
+                'wAng',
+                'uOffset',
                 'vOffset'
             ],
-            format: (tex:BABYLON.Texture) => { return tex.name} 
+            format: (tex: BABYLON.Texture) => { return tex.name }
         },
-        
-        'ArcRotateCamera' : {
+
+        'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
-            properties : [
+            properties: [
                 'position',
-                'alpha', 
-                'beta', 
+                'alpha',
+                'beta',
                 'radius',
                 'angularSensibilityX',
                 'angularSensibilityY',
-                'target', 
+                'target',
 
                 'lowerAlphaLimit',
                 'lowerBetaLimit',
@@ -82,13 +82,14 @@ module INSPECTOR {
                 'wheelPrecision',
                 'allowUpsideDown',
                 'checkCollisions'
-            ]  
+            ]
         },
 
-        'FreeCamera' : {
+        'FreeCamera': {
             type: BABYLON.FreeCamera,
-            properties : [
+            properties: [
                 'position',
+                'rotation',
                 'ellipsoid',
                 'applyGravity',
                 'angularSensibility',
@@ -98,53 +99,53 @@ module INSPECTOR {
                 'keysRight',
                 'onCollide',
                 'checkCollisions'
-            ]  
+            ]
         },
-        
-        'Scene' : {
+
+        'Scene': {
             type: BABYLON.Scene,
-            properties:[
-                'actionManager', 
-                'activeCamera', 
-                'ambientColor', 
+            properties: [
+                'actionManager',
+                'activeCamera',
+                'ambientColor',
                 'clearColor',
                 'forceWireframe',
                 'forcePointsCloud',
                 'forceShowBoundingBoxes',
                 'useRightHandedSystem',
                 'hoverCursor',
-                'cameraToUseForPointers', 
-                'fogEnabled', 
-                'fogColor', 
-                'fogDensity', 
-                'fogStart', 
-                'fogEnd', 
-                'shadowsEnabled', 
-                'lightsEnabled', 
+                'cameraToUseForPointers',
+                'fogEnabled',
+                'fogColor',
+                'fogDensity',
+                'fogStart',
+                'fogEnd',
+                'shadowsEnabled',
+                'lightsEnabled',
                 'collisionsEnabled',
                 'gravity',
-                'meshUnderPointer', 
-                'pointerX', 
-                'pointerY', 
+                'meshUnderPointer',
+                'pointerX',
+                'pointerY',
                 'uid'
-            ]  
+            ]
         },
         'Mesh': {
             type: BABYLON.Mesh,
-            properties : [
-                'name', 
-                'position', 
-                'rotation', 
-                'rotationQuaternion', 
-                'absolutePosition', 
+            properties: [
+                'name',
+                'position',
+                'rotation',
+                'rotationQuaternion',
+                'absolutePosition',
                 'material',
-                'actionManager', 
-                'visibility', 
-                'isVisible', 
-                'isPickable', 
+                'actionManager',
+                'visibility',
+                'isVisible',
+                'isPickable',
                 'renderingGroupId',
-                'receiveShadows', 
-                'renderOutline', 
+                'receiveShadows',
+                'renderOutline',
                 'outlineColor',
                 'outlineWidth',
                 'renderOverlay',
@@ -154,102 +155,102 @@ module INSPECTOR {
                 'useVertexColors',
                 'layerMask',
                 'alwaysSelectAsActiveMesh',
-                'ellipsoid', 
-                'ellipsoidOffset', 
-                'edgesWidth', 
-                'edgesColor', 
+                'ellipsoid',
+                'ellipsoidOffset',
+                'edgesWidth',
+                'edgesColor',
                 'checkCollisions',
                 'hasLODLevels'
             ],
-            format : (m:BABYLON.Mesh) : string => {return m.name;}
-        },        
-        'StandardMaterial' : {
+            format: (m: BABYLON.Mesh): string => { return m.name; }
+        },
+        'StandardMaterial': {
             type: BABYLON.StandardMaterial,
-            properties : [
-                'name', 
+            properties: [
+                'name',
                 'alpha',
-                'alphaMode', 
-                'wireframe', 
-                'isFrozen', 
+                'alphaMode',
+                'wireframe',
+                'isFrozen',
                 'zOffset',
-                
-                'ambientColor', 
-                'emissiveColor', 
-                'diffuseColor', 
+
+                'ambientColor',
+                'emissiveColor',
+                'diffuseColor',
                 'specularColor',
-                
-                'specularPower',       
-                'useAlphaFromDiffuseTexture', 
+
+                'specularPower',
+                'useAlphaFromDiffuseTexture',
                 'linkEmissiveWithDiffuse',
                 'useSpecularOverAlpha',
-                
-                'diffuseFresnelParameters', 
-                'opacityFresnelParameters', 
-                'reflectionFresnelParameters', 
-                'refractionFresnelParameters', 
+
+                'diffuseFresnelParameters',
+                'opacityFresnelParameters',
+                'reflectionFresnelParameters',
+                'refractionFresnelParameters',
                 'emissiveFresnelParameters',
-                
-                'diffuseTexture', 
-                'emissiveTexture', 
-                'specularTexture', 
+
+                'diffuseTexture',
+                'emissiveTexture',
+                'specularTexture',
                 'ambientTexture',
                 'bumpTexture',
-                'lightMapTexture', 
-                'opacityTexture', 
+                'lightMapTexture',
+                'opacityTexture',
                 'reflectionTexture',
-                'refractionTexture'                
+                'refractionTexture'
             ],
-            format : (mat:BABYLON.StandardMaterial) : string => {return mat.name;}
+            format: (mat: BABYLON.StandardMaterial): string => { return mat.name; }
         },
-        'PrimitiveAlignment':{
+        'PrimitiveAlignment': {
             type: BABYLON.PrimitiveAlignment,
-            properties:['horizontal', 'vertical']
+            properties: ['horizontal', 'vertical']
         },
-        'PrimitiveThickness':{
+        'PrimitiveThickness': {
             type: BABYLON.PrimitiveThickness,
-            properties:['topPixels', 'leftPixels', 'rightPixels', 'bottomPixels']
+            properties: ['topPixels', 'leftPixels', 'rightPixels', 'bottomPixels']
         },
-        'BoundingInfo2D':{
+        'BoundingInfo2D': {
             type: BABYLON.BoundingInfo2D,
-            properties:['radius','center', 'extent']
+            properties: ['radius', 'center', 'extent']
         },
-        'SolidColorBrush2D':{
+        'SolidColorBrush2D': {
             type: BABYLON.SolidColorBrush2D,
-            properties:['color']
+            properties: ['color']
         },
-        'GradientColorBrush2D':{
+        'GradientColorBrush2D': {
             type: BABYLON.GradientColorBrush2D,
-            properties:['color1', 'color2', 'translation', 'rotation', 'scale']
+            properties: ['color1', 'color2', 'translation', 'rotation', 'scale']
         },
-        'PBRMaterial' : {
+        'PBRMaterial': {
             type: BABYLON.PBRMaterial,
             properties: [
-                'name', 
-                'albedoColor', 
-                'albedoTexture', 
+                'name',
+                'albedoColor',
+                'albedoTexture',
 
-                'opacityTexture', 
-                'reflectionTexture', 
-                'emissiveTexture', 
-                'bumpTexture', 
-                'lightmapTexture', 
+                'opacityTexture',
+                'reflectionTexture',
+                'emissiveTexture',
+                'bumpTexture',
+                'lightmapTexture',
 
-                'opacityFresnelParameters', 
-                'emissiveFresnelParameters', 
+                'opacityFresnelParameters',
+                'emissiveFresnelParameters',
 
-                'linkEmissiveWithAlbedo', 
-                'useLightmapAsShadowmap', 
+                'linkEmissiveWithAlbedo',
+                'useLightmapAsShadowmap',
 
-                'useAlphaFromAlbedoTexture', 
-                'useSpecularOverAlpha', 
-                'useAutoMicroSurfaceFromReflectivityMap', 
-                'useLogarithmicDepth', 
+                'useAlphaFromAlbedoTexture',
+                'useSpecularOverAlpha',
+                'useAutoMicroSurfaceFromReflectivityMap',
+                'useLogarithmicDepth',
 
                 'reflectivityColor',
                 'reflectivityTexture',
                 'reflectionTexture',
                 'reflectionColor',
-                
+
                 'alpha',
                 'linkRefractionWithTransparency',
                 'indexOfRefraction',
@@ -267,7 +268,7 @@ module INSPECTOR {
                 'cameraColorCurves'
             ]
         }
-        
+
     }
-    
+
 }

+ 49 - 85
inspector/src/tabs/ShaderTab.ts

@@ -2,80 +2,81 @@ module INSPECTOR {
 
     export class ShaderTab extends Tab {
 
-        private _inspector : Inspector;
-        
-        private _vertexPanel : HTMLElement;
-        private _fragmentPanel : HTMLElement;
+        private _inspector: Inspector;
 
-        constructor(tabbar:TabBar, insp:Inspector) {
-            super(tabbar, 'Shader');            
+        private _vertexPanel: HTMLElement;
+        private _fragmentPanel: HTMLElement;
+
+        constructor(tabbar: TabBar, insp: Inspector) {
+            super(tabbar, 'Shader');
             this._inspector = insp;
 
             // Build the shaders panel : a div that will contains the shaders tree and both shaders panels
-            this._panel         = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
+            this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
 
-            let shaderPanel     = Helpers.CreateDiv('shader-tree-panel') as HTMLDivElement;
-            this._vertexPanel   = Helpers.CreateDiv('shader-panel') as HTMLDivElement;
+            let shaderPanel = Helpers.CreateDiv('shader-tree-panel') as HTMLDivElement;
+            this._vertexPanel = Helpers.CreateDiv('shader-panel') as HTMLDivElement;
             this._fragmentPanel = Helpers.CreateDiv('shader-panel') as HTMLDivElement;
 
             this._panel.appendChild(shaderPanel);
             this._panel.appendChild(this._vertexPanel);
             this._panel.appendChild(this._fragmentPanel);
-            
+
             Helpers.LoadScript();
-            
+
             Split([this._vertexPanel, this._fragmentPanel], {
-                blockDrag : this._inspector.popupMode,
-                sizes:[50, 50],
-                direction:'vertical'}
-            );  
-            
+                blockDrag: this._inspector.popupMode,
+                sizes: [50, 50],
+                direction: 'vertical'
+            }
+            );
+
             let comboBox = Helpers.CreateElement('select', '', shaderPanel);
             comboBox.addEventListener('change', this._selectShader.bind(this));
-            
+
             let option = Helpers.CreateElement('option', '', comboBox);
             option.textContent = 'Select a shader';
             option.setAttribute('value', "");
             option.setAttribute('disabled', 'true');
-            option.setAttribute('selected', 'true');            
-            
+            option.setAttribute('selected', 'true');
+
             // Build shaders combobox
             for (let mat of this._inspector.scene.materials) {
                 if (mat instanceof BABYLON.ShaderMaterial) {
                     let option = Helpers.CreateElement('option', '', comboBox);
                     option.setAttribute('value', mat.id);
                     option.textContent = `${mat.name} - ${mat.id}`;
-                    
+
                 }
             }
 
         }
-        
-        private _selectShader(event:Event) {
+
+        private _selectShader(event: Event) {
             let id = (event.target as HTMLSelectElement).value;
-            let mat = this._inspector.scene.getMaterialByID(id); 
-            
+            let mat = this._inspector.scene.getMaterialByID(id);
+
             // Clean shader panel
             Helpers.CleanDiv(this._vertexPanel);
             // add the title - vertex shader
             let title = Helpers.CreateDiv('shader-panel-title', this._vertexPanel);
             title.textContent = 'Vertex shader';
             // add code
-            let code = Helpers.CreateElement('code', 'glsl',  Helpers.CreateElement('pre', '', this._vertexPanel));
+            let code = Helpers.CreateElement('code', 'glsl', Helpers.CreateElement('pre', '', this._vertexPanel));
             code.textContent = this._beautify(mat.getEffect().getVertexShaderSource());
-            
+
             Helpers.CleanDiv(this._fragmentPanel);
             // add the title - fragment shader
             title = Helpers.CreateDiv('shader-panel-title', this._fragmentPanel);
             title.textContent = 'Frgament shader';
             // add code
-            code = Helpers.CreateElement('code', 'glsl',  Helpers.CreateElement('pre', '', this._fragmentPanel));
-            code.textContent = this._beautify(mat.getEffect().getFragmentShaderSource());         
-                                    
+            code = Helpers.CreateElement('code', 'glsl', Helpers.CreateElement('pre', '', this._fragmentPanel));
+            code.textContent = this._beautify(mat.getEffect().getFragmentShaderSource());
+
             // Init the syntax highlighting
             let styleInit = Helpers.CreateElement('script', '', Inspector.DOCUMENT.body);
             styleInit.textContent = 'hljs.initHighlighting();';
-            
+
         }
 
         /** Overrides super.dispose */
@@ -85,9 +86,9 @@ module INSPECTOR {
         /** Returns the position of the first { and the corresponding } */
         private _getBracket(str) {
             let fb = str.indexOf('{');
-            let arr = str.substr(fb+1).split('');
+            let arr = str.substr(fb + 1).split('');
             let counter = 1;
-            let currentPosInString  = fb;
+            let currentPosInString = fb;
             let lastBracketIndex = 0;
             for (let char of arr) {
                 currentPosInString++;
@@ -99,82 +100,45 @@ module INSPECTOR {
                 }
                 if (counter == 0) {
                     lastBracketIndex = currentPosInString;
-                    break;         
+                    break;
                 }
             }
 
-            return {firstBracket : fb, lastBracket:lastBracketIndex};
+            return { firstBracket: fb, lastBracket: lastBracketIndex };
         }
 
         /** 
          * Beautify the given string : correct indentation
          */
-        private _beautify(glsl:string, level: number = 0) {
-            
+        private _beautify(glsl: string, level: number = 0) {
+
             // return condition : no brackets at all
             let brackets = this._getBracket(glsl);
-            let firstBracket       = brackets.firstBracket;
-            let lastBracket        = brackets.lastBracket;
+            let firstBracket = brackets.firstBracket;
+            let lastBracket = brackets.lastBracket;
 
             let spaces = "";
-            for (let i=0 ;i<level; i++) {
+            for (let i = 0; i < level; i++) {
                 spaces += "    "; // 4 spaces
             }
             // If no brackets, return the indented string
             if (firstBracket == -1) {
-                glsl = spaces+glsl; // indent first line
+                glsl = spaces + glsl; // indent first line
                 glsl = glsl
-                    .replace(/;./g, x => '\n'+x.substr(1)) // new line after ;  except the last one
-                    glsl = glsl.replace(/=/g, " = ") // space around =
-                    glsl = glsl.replace(/\n/g, "\n"+spaces); // indentation
+                    .replace(/;./g, x => '\n' + x.substr(1)) // new line after ;  except the last one
+                glsl = glsl.replace(/=/g, " = ") // space around =
+                glsl = glsl.replace(/\n/g, "\n" + spaces); // indentation
                 return glsl;
             } else {
                 // if brackets, beautify the inside                                 
                 // let insideWithBrackets = glsl.substr(firstBracket, lastBracket-firstBracket+1);
-                let left   = glsl.substr(0, firstBracket);
-                let right  = glsl.substr(lastBracket+1, glsl.length); 
-                let inside = glsl.substr(firstBracket+1, lastBracket-firstBracket-1);
-                inside     = this._beautify(inside, level+1);
-                return this._beautify(left, level)+'{\n'+inside+'\n'+spaces+'}\n'+this._beautify(right, level);
+                let left = glsl.substr(0, firstBracket);
+                let right = glsl.substr(lastBracket + 1, glsl.length);
+                let inside = glsl.substr(firstBracket + 1, lastBracket - firstBracket - 1);
+                inside = this._beautify(inside, level + 1);
+                return this._beautify(left, level) + '{\n' + inside + '\n' + spaces + '}\n' + this._beautify(right, level);
 
             }
-
-                
-                // // Replace bracket with @1 and @2 with correct indentation
-                // let newInside          = "@1\n\t" + inside + "\n@2";
-                // newInside              = newInside.replace(/;\n/g, ";\n\t");
-                
-                // glsl                   = glsl.replace(insideWithBrackets, newInside);
-
-                // firstBracket       = glsl.indexOf('{');
-                // lastBracket        = glsl.lastIndexOf('}');
-
-            // }
-
-            // console.log(glsl);
-
-            // let regex = /(\{(?:\{??[^\{]*?}))+/gmi;
-
-            // let tmp = glsl;
-
-            // let m;
-            // while ((m = regex.exec(tmp)) !== null) {
-            //     // This is necessary to avoid infinite loops with zero-width matches
-            //     if (m.index === regex.lastIndex) {
-            //         regex.lastIndex++;
-            //     }                
-            //     // The result can be accessed through the `m`-variable.
-            //     m.forEach((match, groupIndex) => {
-            //         // Remove the first and the last bracket only
-            //         let matchWithoutBrackets = match.replace(/{/, "").replace(/}/, "");
-            //         // Indent the content inside brackets with tabs
-            //         glsl = glsl.replace(match, `{\n\t${matchWithoutBrackets}\n}\n`);
-            //         // removes the match from tmp
-            //         tmp = tmp.replace(match, "");
-            //         // and continue
-            //     });
-            // }
-            // return 
         }
     }
 

+ 42 - 31
inspector/src/tabs/Tab.ts

@@ -1,70 +1,81 @@
-module INSPECTOR{
-    
+module INSPECTOR {
+
     export abstract class Tab extends BasicElement {
-        protected _tabbar  : TabBar;
+        protected _tabbar: TabBar;
         // The tab name displayed in the tabbar
-        public name        : string;        
+        public name: string;
         protected _isActive: boolean = false;
-        
+
         // The whole panel corresponding to this tab. It's what is displayed when the tab is activacted
-        protected _panel : HTMLDivElement;
-        
-        constructor(tabbar:TabBar, name:string) {
-            super();      
-            this._tabbar = tabbar;      
-            this.name   = name;
+        protected _panel: HTMLDivElement;
+
+        constructor(tabbar: TabBar, name: string) {
+            super();
+            this._tabbar = tabbar;
+            this.name = name;
             this._build();
         }
-        
+
         /** True if the tab is active, false otherwise */
-        public isActive() : boolean {
+        public isActive(): boolean {
             return this._isActive;
         }
-        
-        protected _build() {            
-            this._div.className = 'tab';  
-            this._div.textContent = this.name;     
-            
+
+        protected _build() {
+            this._div.className = 'tab';
+            this._div.textContent = this.name;
+
             this._div.addEventListener('click', (evt) => {
                 // Set this tab as active
                 this._tabbar.switchTab(this);
             });
         }
-        
+
         /** Set this tab as active or not, depending on the current state */
-        public active(b:boolean) {
-            if (b) {                
+        public active(b: boolean) {
+            if (b) {
                 this._div.classList.add('active');
             } else {
                 this._div.classList.remove('active');
             }
             this._isActive = b;
         }
-        
+
         public update() {
             // Nothing for the moment
         }
-        
-        /** Creates the tab panel for this tab. */   
-        public getPanel() : HTMLElement {
+
+        /** Creates the tab panel for this tab. */
+        public getPanel(): HTMLElement {
             return this._panel;
         }
-        
+
         /** Add this in the propertytab with the searchbar */
-        public filter(str:string) {};
+        public filter(str: string) { };
 
         /** Dispose properly this tab */
         public abstract dispose();
 
+        /** Select an item in the tree */
+        public select(item: TreeItem) {
+            // To define in subclasses if needed 
+        }
+
+
+        /** Highlight the given node, and downplay all others */
+        public highlightNode(item?: TreeItem) {
+            // To define in subclasses if needed
+        }
+
         /** 
          * Returns the total width in pixel of this tab, 0 by default
         */
-        public getPixelWidth() : number {
+        public getPixelWidth(): number {
             let style = Inspector.WINDOW.getComputedStyle(this._div);
-            let left = parseFloat(style.marginLeft.substr(0,style.marginLeft.length-2)) ||0;
-            let right = parseFloat(style.marginRight.substr(0,style.marginRight.length-2)) ||0;
+            let left = parseFloat(style.marginLeft.substr(0, style.marginLeft.length - 2)) || 0;
+            let right = parseFloat(style.marginRight.substr(0, style.marginRight.length - 2)) || 0;
             return (this._div.clientWidth || 0) + left + right;
         }
     }
-    
+
 }

+ 35 - 34
inspector/src/tabs/TabBar.ts

@@ -4,30 +4,31 @@ module INSPECTOR {
      * The default active tab is the first one of the list.
      */
     export class TabBar extends BasicElement {
-        
+
         // The list of available tabs
-        private _tabs         : Array<Tab> = [];
-        private _inspector    : Inspector;
+        private _tabs: Array<Tab> = [];
+        private _inspector: Inspector;
         /** The tab displaying all meshes */
-        private _meshTab      : MeshTab;
+        private _meshTab: MeshTab;
         /** The toolbar */
-        private _toolBar      : Toolbar;
+        private _toolBar: Toolbar;
         /** The icon displayed at the end of the toolbar displaying a combo box of tabs not displayed */
-        private _moreTabsIcon : HTMLElement;
+        private _moreTabsIcon: HTMLElement;
         /** The panel displayed when the 'more-tab' icon is selected */
         private _moreTabsPanel: HTMLElement;
         /** The list of tab displayed by clicking on the remainingIcon */
         private _invisibleTabs: Array<Tab> = [];
         /** The list of tabs visible, displayed in the tab bar */
-        private _visibleTabs  : Array<Tab> = [];
-                
-        constructor(inspector:Inspector) {
+        private _visibleTabs: Array<Tab> = [];
+
+        constructor(inspector: Inspector) {
             super();
             this._inspector = inspector;
+            this._tabs.push(new TextureTab(this, this._inspector));
             this._tabs.push(new SceneTab(this, this._inspector));
             this._tabs.push(new ConsoleTab(this, this._inspector));
             this._tabs.push(new StatsTab(this, this._inspector));
-            this._meshTab = new MeshTab(this, this._inspector); 
+            this._meshTab = new MeshTab(this, this._inspector);
             this._tabs.push(this._meshTab);
             this._tabs.push(new ShaderTab(this, this._inspector));
             this._tabs.push(new LightTab(this, this._inspector));
@@ -43,20 +44,20 @@ module INSPECTOR {
 
             this._build();
             // Active the first tab
-            this._tabs[0].active(true); 
+            this._tabs[0].active(true);
 
             // set all tab as visible
             for (let tab of this._tabs) {
                 this._visibleTabs.push(tab);
             }
         }
-        
+
         // No update
-        public update() {}
-        
-        protected _build() {            
+        public update() { }
+
+        protected _build() {
             this._div.className = 'tabbar';
-            
+
             this._div.appendChild(this._toolBar.toHtml());
             for (let tab of this._tabs) {
                 this._div.appendChild(tab.toHtml());
@@ -64,7 +65,7 @@ module INSPECTOR {
 
 
             this._moreTabsIcon = Helpers.CreateElement('i', 'fa fa-angle-double-right more-tabs');
-         
+
             this._moreTabsPanel = Helpers.CreateDiv('more-tabs-panel');
 
             this._moreTabsIcon.addEventListener('click', () => {
@@ -74,7 +75,7 @@ module INSPECTOR {
                 } else {
                     // Attach more-tabs-panel if not attached yet
                     let topPanel = this._div.parentNode as HTMLElement;
-                    if (! topPanel.contains(this._moreTabsPanel)) {
+                    if (!topPanel.contains(this._moreTabsPanel)) {
                         topPanel.appendChild(this._moreTabsPanel);
                     }
                     // Clean the 'more-tabs-panel'
@@ -82,7 +83,7 @@ module INSPECTOR {
                     // Add each invisible tabs to this panel
                     for (let tab of this._invisibleTabs) {
                         this._addInvisibleTabToPanel(tab);
-                    }        
+                    }
                     // And display it
                     this._moreTabsPanel.style.display = 'flex';
                 }
@@ -93,7 +94,7 @@ module INSPECTOR {
          * Add a tab to the 'more-tabs' panel, displayed by clicking on the 
          * 'more-tabs' icon
          */
-        private _addInvisibleTabToPanel(tab:Tab) {
+        private _addInvisibleTabToPanel(tab: Tab) {
             let div = Helpers.CreateDiv('invisible-tab', this._moreTabsPanel);
             div.textContent = tab.name;
             div.addEventListener('click', () => {
@@ -101,9 +102,9 @@ module INSPECTOR {
                 this.switchTab(tab);
             });
         }
-        
+
         /** Dispose the current tab, set the given tab as active, and refresh the treeview */
-        public switchTab(tab:Tab) {
+        public switchTab(tab: Tab) {
             // Dispose the active tab
             this.getActiveTab().dispose();
 
@@ -113,24 +114,24 @@ module INSPECTOR {
             }
             // activate the given tab
             tab.active(true);
-            
+
             // Refresh the inspector
             this._inspector.refresh();
         }
-        
+
         /** Display the mesh tab.
          * If a parameter is given, the given mesh details are displayed
          */
-        public switchMeshTab(mesh?:BABYLON.AbstractMesh) {
+        public switchMeshTab(mesh?: BABYLON.AbstractMesh) {
             this.switchTab(this._meshTab);
             if (mesh) {
                 let item = this._meshTab.getItemFor(mesh);
                 this._meshTab.select(item);
             }
         }
-        
+
         /** Returns the active tab */
-        public getActiveTab() : Tab {
+        public getActiveTab(): Tab {
             for (let tab of this._tabs) {
                 if (tab.isActive()) {
                     return tab;
@@ -138,7 +139,7 @@ module INSPECTOR {
             }
         }
 
-        public get inspector() : Inspector {
+        public get inspector(): Inspector {
             return this._inspector;
         }
 
@@ -146,7 +147,7 @@ module INSPECTOR {
          * Returns the total width in pixel of the tabbar, 
          * that corresponds to the sum of the width of each visible tab + toolbar width
         */
-        public getPixelWidth() : number {
+        public getPixelWidth(): number {
             let sum = 0;
             for (let tab of this._visibleTabs) {
                 sum += tab.getPixelWidth();
@@ -164,7 +165,7 @@ module INSPECTOR {
         public updateWidth() {
             let parentSize = this._div.parentElement.clientWidth;
             let lastTabWidth = 75;
-            let currentSize = this.getPixelWidth(); 
+            let currentSize = this.getPixelWidth();
 
             // Check if a tab should be removed : if the tab bar width is greater than
             // its parent width
@@ -175,7 +176,7 @@ module INSPECTOR {
                 this._invisibleTabs.push(tab);
                 // and removes it from the DOM
                 this._div.removeChild(tab.toHtml());
-                currentSize = this.getPixelWidth() + lastTabWidth;                
+                currentSize = this.getPixelWidth() + lastTabWidth;
             }
 
             // Check if a tab can be added to the tab bar : if the tab bar width
@@ -186,15 +187,15 @@ module INSPECTOR {
                     this._div.appendChild(lastTab.toHtml());
                     this._visibleTabs.push(lastTab);
                     // Update more-tab icon in last position if needed
-                     if (this._div.contains(this._moreTabsIcon)) {
+                    if (this._div.contains(this._moreTabsIcon)) {
                         this._div.removeChild(this._moreTabsIcon);
-                     }
+                    }
                 }
             }
             if (this._invisibleTabs.length > 0 && !this._div.contains(this._moreTabsIcon)) {
                 this._div.appendChild(this._moreTabsIcon);
             }
         }
-        
+
     }
 }

+ 127 - 0
inspector/src/tabs/TextureTab.ts

@@ -0,0 +1,127 @@
+module INSPECTOR {
+
+    export class TextureTab extends Tab {
+
+        private _inspector: Inspector;
+        /** The panel containing a list of items */
+        protected _treePanel: HTMLElement;
+        protected _treeItems: Array<TreeItem> = [];
+
+        /* Panel containing the texture image */
+        private _imagePanel: HTMLElement;
+
+        constructor(tabbar: TabBar, inspector: Inspector) {
+            super(tabbar, 'Textures');
+            this._inspector = inspector;
+
+            // Build the properties panel : a div that will contains the tree and the detail panel
+            this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
+
+            // Build the treepanel
+            this._treePanel = Helpers.CreateDiv('insp-tree', this._panel);
+
+            this._imagePanel = Helpers.CreateDiv('image-panel', this._panel) as HTMLDivElement;
+
+            Split([this._treePanel, this._imagePanel], {
+                blockDrag: this._inspector.popupMode,
+                direction: 'vertical'
+            });
+
+            this.update();
+        }
+
+        public dispose() {
+            // Nothing to dispose
+        }
+
+        public update(_items?: Array<TreeItem>) {
+
+            let items;
+            if (_items) {
+                items = _items;
+            } else {
+                // Rebuild the tree
+                this._treeItems = this._getTree();
+                items = this._treeItems;
+            }
+            // Clean the tree
+            Helpers.CleanDiv(this._treePanel);
+            Helpers.CleanDiv(this._imagePanel);
+
+            // Sort items alphabetically
+            items.sort((item1, item2) => {
+                return item1.compareTo(item2);
+            });
+
+            // Display items
+            for (let item of items) {
+                this._treePanel.appendChild(item.toHtml());
+            }
+        }
+
+        /* Overrides super */
+        private _getTree(): Array<TreeItem> {
+            let arr = [];
+
+            // get all cameras from the first scene
+            let instances = this._inspector.scene;
+            for (let tex of instances.textures) {
+                arr.push(new TreeItem(this, new TextureAdapter(tex)));
+            }
+            return arr;
+        }
+
+        /** Display the details of the given item */
+        public displayDetails(item: TreeItem) {
+            // Remove active state on all items
+            this.activateNode(item);
+            Helpers.CleanDiv(this._imagePanel);
+            // Get the texture object
+            let texture = item.adapter.object;
+
+            let img = Helpers.CreateElement('img', '', this._imagePanel) as HTMLImageElement;
+            // If an url is present, the texture is an image
+            if (texture.url) {
+                img.src = texture.url;
+            } else if (texture['_canvas']) {
+                // Dynamic texture
+                let base64Image = texture['_canvas'].toDataURL("image/png");
+                img.src = base64Image;
+            }
+        }
+
+        /** Select an item in the tree */
+        public select(item: TreeItem) {
+            // Remove the node highlight
+            this.highlightNode();
+            // Active the node
+            this.activateNode(item);
+            // Display its details
+            this.displayDetails(item);
+        }
+
+        /** Set the given item as active in the tree */
+        public activateNode(item: TreeItem) {
+            if (this._treeItems) {
+                for (let node of this._treeItems) {
+                    node.active(false);
+                }
+            }
+            item.active(true);
+        }
+
+        /** Highlight the given node, and downplay all others */
+        public highlightNode(item?: TreeItem) {
+            if (this._treeItems) {
+                for (let node of this._treeItems) {
+                    node.highlight(false);
+                }
+            }
+            if (item) {
+                item.highlight(true);
+            }
+        }
+
+    }
+
+}

+ 49 - 42
inspector/src/tree/TreeItem.ts

@@ -1,50 +1,57 @@
- module INSPECTOR {
-     
-    export class TreeItem extends BasicElement{
-    
+module INSPECTOR {
+
+    export class TreeItem extends BasicElement {
+
         // Reference to the tab
-        private _tab        : PropertyTab;
+        private _tab: Tab;
         // The object this item is linked to (should be a primitive or a canvas) TODO should be superclass of all primitives
-        private _adapter    : Adapter;
-        private _tools      : Array<AbstractTreeTool>;
-        public children     : Array<TreeItem> = [];
+        private _adapter: Adapter;
+        private _tools: Array<AbstractTreeTool>;
+        public children: Array<TreeItem> = [];
         // Div element that contains all children of this node.
-        private _lineContent: HTMLElement;  
+        private _lineContent: HTMLElement;
 
-        constructor(tab:PropertyTab, obj:Adapter ) {
+        constructor(tab: Tab, obj: Adapter) {
             super();
             this._tab = tab;
             this._adapter = obj;
-            
+
             this._tools = this._adapter.getTools();
-            
+
             this._build();
-            
+
         }
 
         /** Returns the item ID == its adapter ID */
-        public get id() : string {
+        public get id(): string {
             return this._adapter.id();
         }
 
         /** Add the given item as a child of this one */
-        public add(child:TreeItem) {
+        public add(child: TreeItem) {
             this.children.push(child);
             this.update();
         }
 
         /**
+         * Returns the original adapter
+         */
+        public get adapter(): Adapter {
+            return this._adapter;
+        }
+
+        /**
          * Function used to compare this item to another tree item.
          * Returns the alphabetical sort of the adapter ID
          */
-        public compareTo(item:TreeItem) : number {
+        public compareTo(item: TreeItem): number {
             let str1 = this.id;
             let str2 = item.id;
-            return str1.localeCompare(str2, [], {numeric:true});
+            return str1.localeCompare(str2, [], { numeric: true });
         }
-        
+
         /** Returns true if the given obj correspond to the adapter linked to this tree item */
-        public correspondsTo(obj:any) : boolean {
+        public correspondsTo(obj: any): boolean {
             return this._adapter.correspondsTo(obj);
         }
 
@@ -70,30 +77,30 @@
                 this._div.classList.remove('folded');
             }
         }
-        
+
         /** Build the HTML of this item */
         protected _build() {
-            this._div.className = 'line'; 
-            
-            
-            for (let tool of this._tools) { 
+            this._div.className = 'line';
+
+
+            for (let tool of this._tools) {
                 this._div.appendChild(tool.toHtml());
             }
-            
-            
+
+
             // Id
-            let text = Inspector.DOCUMENT.createElement('span');        
+            let text = Inspector.DOCUMENT.createElement('span');
             text.textContent = this._adapter.id();
             this._div.appendChild(text);
-            
+
             // Type
-            let type = Inspector.DOCUMENT.createElement('span'); 
+            let type = Inspector.DOCUMENT.createElement('span');
             type.className = 'property-type';
             if (this._adapter.type() !== 'type_not_defined') {
-                type.textContent = ' - '+this._adapter.type();
-            } 
+                type.textContent = ' - ' + this._adapter.type();
+            }
             this._div.appendChild(type);
-            
+
             this._lineContent = Helpers.CreateDiv('line-content', this._div);
 
             this._addEvent();
@@ -102,10 +109,10 @@
         /**
          * Returns one HTML element (.details) containing all  details of this primitive
          */
-        public getDetails() : Array<PropertyLine> {
+        public getDetails(): Array<PropertyLine> {
             return this._adapter.getProperties();
         }
-        
+
         public update() {
             // Clean division holding all children
             Helpers.CleanDiv(this._lineContent);
@@ -122,7 +129,7 @@
             }
             this.fold();
         }
-        
+
         /**
          * Add an event listener on the item : 
          * - one click display details
@@ -133,10 +140,10 @@
                 this._tab.select(this);
                 // Fold/unfold the tree
                 if (this._isFolded()) {
-                    this.unfold();        
+                    this.unfold();
                 } else {
                     this.fold();
-                }                   
+                }
                 e.stopPropagation();
             });
 
@@ -152,7 +159,7 @@
         }
 
         /** Highlight or downplay this node */
-        public highlight(b:boolean) {
+        public highlight(b: boolean) {
             // Remove highlight for all children 
             if (!b) {
                 for (let child of this.children) {
@@ -162,14 +169,14 @@
             // Highlight this node
             this._adapter.highlight(b);
         }
-        
+
         /** Returns true if the node is folded, false otherwise */
-        private _isFolded() : boolean {
+        private _isFolded(): boolean {
             return !this._div.classList.contains('unfolded');
         }
 
         /** Set this item as active (background lighter) in the tree panel */
-        public active(b:boolean) {
+        public active(b: boolean) {
             this._div.classList.remove('active');
             for (let child of this.children) {
                 child.active(false);
@@ -179,4 +186,4 @@
             }
         }
     }
- }
+}

+ 60 - 33
inspector/test/index.js

@@ -5,8 +5,8 @@ var Test = (function () {
     function Test(canvasId) {
         var _this = this;
         var canvas = document.getElementById(canvasId);
-        this.engine = new BABYLON.Engine(canvas, true);					
-		BABYLONDEVTOOLS.Loader.debugShortcut(this.engine);
+        this.engine = new BABYLON.Engine(canvas, true);
+        BABYLONDEVTOOLS.Loader.debugShortcut(this.engine);
         this.scene = null;
         window.addEventListener("resize", function () {
             _this.engine.resize();
@@ -64,15 +64,24 @@ var Test = (function () {
         light2.specular = new BABYLON.Color3(0, 0, 1);
         light3.diffuse = new BABYLON.Color3(1, 1, 1);
         light3.specular = new BABYLON.Color3(1, 1, 1);
-        BABYLON.Effect.ShadersStore["customVertexShader"] = 'precision highp float;attribute vec3 position;attribute vec2 uv;uniform mat4 worldViewProjection;varying vec2 vUV;varying vec3 vPos;void main(){gl_Position=worldViewProjection*vec4(position,1.),vPos=gl_Position.xyz;if(position.x >2.0) {gl_Position.x = 2.0;} else { gl_Position.y = 1.0;}}';
+        BABYLON.Effect.ShadersStore["customVertexShader"] = `precision highp float;
+        attribute vec3 position;
+        attribute vec2 uv;
+        uniform mat4 worldViewProjection;
+        varying vec2 vUV;
+        varying vec3 vPos;
+        void main(){vec4 p = vec4( position, 1. );
+            gl_Position = worldViewProjection * vec4(position, 1.0);
+            vUV = uv;
+        }`;
         BABYLON.Effect.ShadersStore["customFragmentShader"] = 'precision highp float;varying vec3 vPos;uniform vec3 color;void main(){gl_FragColor=vec4(mix(color,vPos,.05),1.);}';
         var shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, {
             vertex: "custom",
             fragment: "custom",
         }, {
-            attributes: ["position", "normal", "uv"],
-            uniforms: ["world", "worldView", "worldViewProjection", "view", "projection"]
-        });
+                attributes: ["position", "normal", "uv"],
+                uniforms: ["world", "worldView", "worldViewProjection", "view", "projection"]
+            });
         sphere.material = shaderMaterial;
         // Animations
         var alpha = 0;
@@ -85,6 +94,14 @@ var Test = (function () {
             lightSphere2.position = light2.position;
             alpha += 0.01;
         };
+
+        // Create texture panel
+        let panel = BABYLON.Mesh.CreatePlane('plane', 10, scene);
+        let tex = new BABYLON.StandardMaterial('panelMat', scene);
+        tex.diffuseTexture = new BABYLON.Texture('/assets/textures/amiga.jpg', scene);
+        panel.material = tex;
+
+
         this.scene = scene;
     };
     Test.prototype._initGame = function () {
@@ -95,36 +112,46 @@ var Test = (function () {
      */
     Test.prototype._createCanvas = function () {
         // object hierarchy  g1 -> g2 -> rect
-            
-            // when cachingStrategy is 1 or 2 - everything is rendered
-            // when it is 3 - only direct children of g1 are rendered
-            var canvas = new BABYLON.ScreenSpaceCanvas2D(this.scene, 
-                { id: "ScreenCanvas", 
-                cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_DONTCACHE });           // 1
-                // cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS });      // 2 
-                // cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_ALLGROUPS });           // 3
-            
-            canvas.createCanvasProfileInfoCanvas();
 
-            // parent group            
-            var g1 = new BABYLON.Group2D({parent: canvas, id: "G1",
-                x: 50, y: 50, size: new BABYLON.Size(60, 60)});
+        // when cachingStrategy is 1 or 2 - everything is rendered
+        // when it is 3 - only direct children of g1 are rendered
+        var canvas = new BABYLON.ScreenSpaceCanvas2D(this.scene,
+            {
+                id: "ScreenCanvas",
+                cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_DONTCACHE
+            });           // 1
+        // cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS });      // 2 
+        // cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_ALLGROUPS });           // 3
+
+        canvas.createCanvasProfileInfoCanvas();
+
+        // parent group            
+        var g1 = new BABYLON.Group2D({
+            parent: canvas, id: "G1",
+            x: 50, y: 50, size: new BABYLON.Size(60, 60)
+        });
+
+        // just to see it    
+        let frame1 = new BABYLON.Rectangle2D({
+            parent: g1,
+            x: 0, y: 0, size: g1.size, border: "#FF0000FF"
+        });
 
-            // just to see it    
-            let frame1 = new BABYLON.Rectangle2D({parent: g1, 
-                         x : 0, y: 0,  size: g1.size, border: "#FF0000FF" });
-            
-            // child group
-            let g2 = new BABYLON.Group2D({parent: g1, id: "G2",  
-                        x: 10, y: 10, size: new BABYLON.Size(40, 40)});
+        // child group
+        let g2 = new BABYLON.Group2D({
+            parent: g1, id: "G2",
+            x: 10, y: 10, size: new BABYLON.Size(40, 40)
+        });
+
+        // just to see it
+        let frame2 = new BABYLON.Rectangle2D({ parent: g2, x: 0, y: 0, size: g2.size, border: "#0000FFFF" });
+
+        let rect = new BABYLON.Rectangle2D({
+            parent: g2, x: 10, y: 10, size: new BABYLON.Size(20, 20),
+            fill: "#00FF00FF"
+        });
 
-            // just to see it
-            let frame2 = new BABYLON.Rectangle2D({parent: g2, x : 0, y: 0, size: g2.size, border: "#0000FFFF" }); 
-            
-            let rect =   new BABYLON.Rectangle2D({parent: g2, x : 10, y: 10, size: new BABYLON.Size(20, 20), 
-                                fill: "#00FF00FF" }) ;              
-                      
-            return canvas;
+        return canvas;
     };
     return Test;
 }());