Просмотр исходного кода

Merge pull request #1605 from Temechon/master

Inspector - Bug fixes and improvments
David Catuhe 8 лет назад
Родитель
Сommit
014df3ec76

+ 0 - 4
canvas2D/src/Engine/babylon.canvas2d.ts

@@ -1286,10 +1286,6 @@
                 let worldMtx = node.getWorldMatrix();
 
                 let proj = Vector3.Project(Canvas2D._v, worldMtx, Canvas2D._m, v);
-
-                // Set the visibility state accordingly, if the position is outside the frustum (well on the Z planes only...) set the group to hidden
-                group.levelVisible = proj.z >= 0 && proj.z < 1.0;
-
                 let s = this.scale;
                 group.x = Math.round(proj.x/s);
                 group.y = Math.round((rh - proj.y)/s);

Разница между файлами не показана из-за своего большого размера
+ 4 - 4
dist/preview release/inspector/babylon.inspector.bundle.js


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

@@ -63,7 +63,7 @@
             background-color: #454545; }
   .insp-wrapper .tooltip {
     position: absolute;
-    top: 0;
+    top: 32px;
     right: 0;
     color: #f29766;
     display: none;

+ 23 - 5
dist/preview release/inspector/babylon.inspector.d.ts

@@ -88,8 +88,10 @@ declare module INSPECTOR {
         'Texture': {
             type: typeof BABYLON.Texture;
             properties: string[];
+            format: (tex: BABYLON.Texture) => string;
         };
         'ArcRotateCamera': {
+            type: typeof BABYLON.ArcRotateCamera;
             properties: string[];
         };
         'Scene': {
@@ -503,7 +505,7 @@ declare module INSPECTOR {
         private _elem;
         /** The tooltip div */
         private _infoDiv;
-        constructor(elem: HTMLElement, tip: string);
+        constructor(elem: HTMLElement, tip: string, attachTo?: HTMLElement);
     }
 }
 
@@ -545,7 +547,12 @@ declare module INSPECTOR {
          * Removes all children of the given div.
          */
         static CleanDiv(div: HTMLElement): void;
+        /**
+         * Returns the true value of the given CSS Attribute from the given element (in percentage or in pixel, as it was specified in the css)
+         */
+        static Css(elem: HTMLElement, cssAttribute: string): string;
         static LoadScript(): void;
+        static IsSystemName(name: string): boolean;
     }
 }
 
@@ -826,12 +833,23 @@ declare module INSPECTOR {
     class LabelTool extends AbstractTool {
         /** True if label are displayed, false otherwise */
         private _isDisplayed;
-        private _labels;
-        private _camera;
-        private _transformationMatrix;
+        private _canvas;
+        private _labelInitialized;
+        private _scene;
+        private _canvas2DLoaded;
+        private _newMeshObserver;
+        private _removedMeshObserver;
+        private _newLightObserver;
+        private _removedLightObserver;
+        private _newCameraObserver;
+        private _removedCameraObserver;
         constructor(parent: HTMLElement, inspector: Inspector);
+        dispose(): void;
+        private _checkC2DLoaded();
+        private _initializeLabels();
+        private _createLabel(node);
+        private _removeLabel(node);
         action(): void;
-        private _update();
     }
 }
 

+ 259 - 44
dist/preview release/inspector/babylon.inspector.js

@@ -14,6 +14,10 @@ var INSPECTOR;
             // Save HTML document and window
             Inspector.DOCUMENT = window.document;
             Inspector.WINDOW = window;
+            // Load the Canvas2D library if it's not already done
+            if (!BABYLON.Canvas2D) {
+                BABYLON.Tools.LoadScript("http://www.babylonjs.com/babylon.canvas2d.js", function () { });
+            }
             // POPUP MODE
             if (popup) {
                 // Build the inspector in the given parent
@@ -24,13 +28,11 @@ var INSPECTOR;
                 var canvas = this._scene.getEngine().getRenderingCanvas();
                 var canvasParent = canvas.parentElement;
                 var canvasParentComputedStyle = Inspector.WINDOW.getComputedStyle(canvasParent);
-                // resize canvas
-                // canvas.style.width = 'calc(100% - 750px - 12px)';
                 // get canvas style                
                 var canvasComputedStyle = Inspector.WINDOW.getComputedStyle(canvas);
                 this._canvasStyle = {
-                    width: canvasComputedStyle.width,
-                    height: canvasComputedStyle.height,
+                    width: INSPECTOR.Helpers.Css(canvas, 'width'),
+                    height: INSPECTOR.Helpers.Css(canvas, 'height'),
                     position: canvasComputedStyle.position,
                     top: canvasComputedStyle.top,
                     bottom: canvasComputedStyle.bottom,
@@ -203,9 +205,9 @@ var INSPECTOR;
                 for (var prop in this._canvasStyle) {
                     canvas.style[prop] = this._canvasStyle[prop];
                 }
-                // Get parent of the wrapper           
+                // Get parent of the wrapper 
                 var canvasParent = canvas.parentElement.parentElement;
-                canvasParent.appendChild(canvas);
+                canvasParent.insertBefore(canvas, this._c2diwrapper);
                 // Remove wrapper
                 INSPECTOR.Helpers.CleanDiv(this._c2diwrapper);
                 this._c2diwrapper.remove();
@@ -321,14 +323,56 @@ var INSPECTOR;
                 'uOffset',
                 'vOffset'
             ],
+            format: function (tex) { return tex.name; }
         },
         'ArcRotateCamera': {
-            // type: BABYLON.ArcRotateCamera,
-            properties: ['alpha', 'beta', 'radius']
+            type: BABYLON.ArcRotateCamera,
+            properties: [
+                'alpha',
+                'beta',
+                'radius',
+                'angularSensibilityX',
+                'angularSensibilityY',
+                'target',
+                'lowerAlphaLimit',
+                'lowerBetaLimit',
+                'upperAlphaLimit',
+                'upperBetaLimit',
+                'lowerRadiusLimit',
+                'upperRadiusLimit',
+                'pinchPrecision',
+                'wheelPrecision',
+                'allowUpsideDown',
+                'checkCollisions'
+            ]
         },
         'Scene': {
             type: BABYLON.Scene,
-            properties: ['actionManager', 'activeCamera', 'ambientColor', 'clearColor']
+            properties: [
+                'actionManager',
+                'activeCamera',
+                'ambientColor',
+                'clearColor',
+                'forceWireframe',
+                'forcePointsCloud',
+                'forceShowBoundingBoxes',
+                'useRightHandedSystem',
+                'hoverCursor',
+                'cameraToUseForPointers',
+                'fogEnabled',
+                'fogColor',
+                'fogDensity',
+                'fogStart',
+                'fogEnd',
+                'shadowsEnabled',
+                'lightsEnabled',
+                'collisionsEnabled',
+                'gravity',
+                'meshUnderPointer',
+                'pointerX',
+                'pointerY',
+                'uid'
+            ]
         },
         'Mesh': {
             type: BABYLON.Mesh,
@@ -338,7 +382,29 @@ var INSPECTOR;
                 'rotation',
                 'rotationQuaternion',
                 'absolutePosition',
-                'material'
+                'material',
+                'actionManager',
+                'visibility',
+                'isVisible',
+                'isPickable',
+                'renderingGroupId',
+                'receiveShadows',
+                'renderOutline',
+                'outlineColor',
+                'outlineWidth',
+                'renderOverlay',
+                'overlayColor',
+                'overlayAlpha',
+                'hasVertexAlpha',
+                'useVertexColors',
+                'layerMask',
+                'alwaysSelectAsActiveMesh',
+                'ellipsoid',
+                'ellipsoidOffset',
+                'edgesWidth',
+                'edgesColor',
+                'checkCollisions',
+                'hasLODLevels'
             ],
             format: function (m) { return m.name; }
         },
@@ -1196,12 +1262,10 @@ var INSPECTOR;
          * (example : mesh.position = new BABYLON.Vector3 ; the original vector3 object is deleted from the mesh).
         */
         PropertyLine.prototype.updateObject = function () {
-            if (!this._parent) {
-                return this._property.value;
-            }
-            else {
+            if (this._parent) {
                 this._property.obj = this._parent.updateObject();
             }
+            return this._property.value;
         };
         Object.defineProperty(PropertyLine.prototype, "name", {
             // Returns the property name
@@ -1672,10 +1736,13 @@ var INSPECTOR;
      * Creates a tooltip for the parent of the given html element
      */
     var Tooltip = (function () {
-        function Tooltip(elem, tip) {
+        function Tooltip(elem, tip, attachTo) {
             var _this = this;
             this._elem = elem;
-            this._infoDiv = INSPECTOR.Helpers.CreateDiv('tooltip', this._elem.parentElement);
+            if (!attachTo) {
+                attachTo = this._elem.parentElement;
+            }
+            this._infoDiv = INSPECTOR.Helpers.CreateDiv('tooltip', attachTo);
             this._elem.addEventListener('mouseover', function () {
                 _this._infoDiv.textContent = tip;
                 _this._infoDiv.style.display = 'block';
@@ -1802,6 +1869,18 @@ var INSPECTOR;
                 div.removeChild(div.firstChild);
             }
         };
+        /**
+         * Returns the true value of the given CSS Attribute from the given element (in percentage or in pixel, as it was specified in the css)
+         */
+        Helpers.Css = function (elem, cssAttribute) {
+            var clone = elem.cloneNode(true);
+            var div = Helpers.CreateDiv('', INSPECTOR.Inspector.DOCUMENT.body);
+            div.style.display = 'none';
+            div.appendChild(clone);
+            var value = INSPECTOR.Inspector.WINDOW.getComputedStyle(clone)[cssAttribute];
+            div.remove();
+            return value;
+        };
         Helpers.LoadScript = function () {
             BABYLON.Tools.LoadFile("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js", function (elem) {
                 var script = Helpers.CreateElement('script', '', INSPECTOR.Inspector.DOCUMENT.body);
@@ -1822,6 +1901,12 @@ var INSPECTOR;
                 console.log("erreur");
             });
         };
+        Helpers.IsSystemName = function (name) {
+            if (name == null) {
+                return false;
+            }
+            return name.indexOf("###") === 0 && name.lastIndexOf("###") === (name.length - 3);
+        };
         return Helpers;
     }());
     INSPECTOR.Helpers = Helpers;
@@ -2082,17 +2167,13 @@ var INSPECTOR;
             var arr = [];
             // get all canvas2D
             var instances = BABYLON.Canvas2D.instances || [];
-            // Returns true if the id of the given object starts and ends with '###'
-            var shouldExcludeThisPrim = function (obj) {
-                return (obj.id && obj.id.indexOf('###') == 0 && obj.id.lastIndexOf('###', 0) === 0);
-            };
             // Recursive method building the tree panel
             var createNode = function (obj) {
                 if (obj.children && obj.children.length > 0) {
                     var node = new INSPECTOR.TreeItem(_this, new INSPECTOR.Canvas2DAdapter(obj));
                     for (var _i = 0, _a = obj.children; _i < _a.length; _i++) {
                         var child = _a[_i];
-                        if (!shouldExcludeThisPrim(child)) {
+                        if (!INSPECTOR.Helpers.IsSystemName(child.id)) {
                             var n = createNode(child);
                             node.add(n);
                         }
@@ -2106,6 +2187,9 @@ var INSPECTOR;
             };
             for (var _i = 0, instances_1 = instances; _i < instances_1.length; _i++) {
                 var inst = instances_1[_i];
+                if (INSPECTOR.Helpers.IsSystemName(inst.id)) {
+                    continue;
+                }
                 var c2d = inst;
                 var nodes = createNode(c2d);
                 arr.push(nodes);
@@ -2187,17 +2271,44 @@ var INSPECTOR;
         }
         /* Overrides super */
         MeshTab.prototype._getTree = function () {
+            var _this = this;
             var arr = [];
+            // Tab containign mesh already in results
+            var alreadyIn = [];
             // Returns true if the id of the given object starts and ends with '###'
             var shouldExcludeThisMesh = function (obj) {
                 return (obj.name && obj.name.indexOf('###') == 0 && obj.name.lastIndexOf('###', 0) === 0);
             };
+            // Recursive method building the tree panel
+            var createNode = function (obj) {
+                var descendants = obj.getDescendants(true);
+                if (descendants.length > 0) {
+                    var node = new INSPECTOR.TreeItem(_this, new INSPECTOR.MeshAdapter(obj));
+                    alreadyIn.push(node);
+                    for (var _i = 0, descendants_1 = descendants; _i < descendants_1.length; _i++) {
+                        var child = descendants_1[_i];
+                        if (child instanceof BABYLON.AbstractMesh) {
+                            if (!INSPECTOR.Helpers.IsSystemName(child.name)) {
+                                var n = createNode(child);
+                                node.add(n);
+                            }
+                        }
+                    }
+                    node.update();
+                    return node;
+                }
+                else {
+                    alreadyIn.push(obj);
+                    return new INSPECTOR.TreeItem(_this, new INSPECTOR.MeshAdapter(obj));
+                }
+            };
             // get all meshes from the first scene
             var instances = this._inspector.scene;
             for (var _i = 0, _a = instances.meshes; _i < _a.length; _i++) {
                 var mesh = _a[_i];
-                if (!shouldExcludeThisMesh(mesh)) {
-                    arr.push(new INSPECTOR.TreeItem(this, new INSPECTOR.MeshAdapter(mesh)));
+                if (alreadyIn.indexOf(mesh) == -1) {
+                    var node = createNode(mesh);
+                    arr.push(node);
                 }
             }
             return arr;
@@ -3179,32 +3290,136 @@ var INSPECTOR;
             var _this = _super.call(this, 'fa-tags', parent, inspector, 'Display mesh names on the canvas') || this;
             /** True if label are displayed, false otherwise */
             _this._isDisplayed = false;
-            _this._labels = [];
-            _this._transformationMatrix = BABYLON.Matrix.Identity();
+            _this._canvas = null;
+            _this._labelInitialized = false;
+            _this._scene = null;
+            _this._canvas2DLoaded = false;
+            _this._newMeshObserver = null;
+            _this._removedMeshObserver = null;
+            _this._newLightObserver = null;
+            _this._removedLightObserver = null;
+            _this._newCameraObserver = null;
+            _this._removedCameraObserver = null;
+            _this._scene = inspector.scene;
             return _this;
         }
+        LabelTool.prototype.dispose = function () {
+            if (this._newMeshObserver) {
+                this._scene.onNewMeshAddedObservable.remove(this._newMeshObserver);
+                this._scene.onMeshRemovedObservable.remove(this._removedMeshObserver);
+                this._scene.onNewLightAddedObservable.remove(this._newLightObserver);
+                this._scene.onLightRemovedObservable.remove(this._removedLightObserver);
+                this._scene.onNewCameraAddedObservable.remove(this._newCameraObserver);
+                this._scene.onCameraRemovedObservable.remove(this._removedCameraObserver);
+                this._newMeshObserver = this._newLightObserver = this._newCameraObserver = this._removedMeshObserver = this._removedLightObserver = this._removedCameraObserver = null;
+            }
+            this._canvas.dispose();
+            this._canvas = null;
+        };
+        LabelTool.prototype._checkC2DLoaded = function () {
+            if (this._canvas2DLoaded === true) {
+                return true;
+            }
+            if (BABYLON.Canvas2D) {
+                this._canvas2DLoaded = true;
+            }
+            return this._canvas2DLoaded;
+        };
+        LabelTool.prototype._initializeLabels = function () {
+            var _this = this;
+            // Check if the label are already initialized and quit if it's the case
+            if (this._labelInitialized) {
+                return;
+            }
+            // Can't initialize them if the Canvas2D lib is not loaded yet
+            if (!this._checkC2DLoaded()) {
+                return;
+            }
+            // Create the canvas that will be used to display the labels
+            this._canvas = new BABYLON.ScreenSpaceCanvas2D(this._scene, { id: "###Label Canvas###" /*, cachingStrategy: BABYLON.Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS*/ });
+            this._canvas.createCanvasProfileInfoCanvas();
+            // Create label for all the Meshes, Lights and Cameras
+            // Those that will be created/removed after this method is called will be taken care by the event handlers added below
+            for (var _i = 0, _a = this._scene.meshes; _i < _a.length; _i++) {
+                var m = _a[_i];
+                this._createLabel(m);
+            }
+            for (var _b = 0, _c = this._scene.lights; _b < _c.length; _b++) {
+                var l = _c[_b];
+                this._createLabel(l);
+            }
+            for (var _d = 0, _e = this._scene.cameras; _d < _e.length; _d++) {
+                var c = _e[_d];
+                this._createLabel(c);
+            }
+            // Add handlers for new/removed meshes, camera and lights
+            this._newMeshObserver = this._scene.onNewMeshAddedObservable.add(function (e, s) {
+                _this._createLabel(e);
+            });
+            this._removedMeshObserver = this._scene.onMeshRemovedObservable.add(function (e, s) {
+                _this._removeLabel(e);
+            });
+            this._newLightObserver = this._scene.onNewLightAddedObservable.add(function (e, s) {
+                _this._createLabel(e);
+            });
+            this._removedLightObserver = this._scene.onLightRemovedObservable.add(function (e, s) {
+                _this._removeLabel(e);
+            });
+            this._newCameraObserver = this._scene.onNewCameraAddedObservable.add(function (e, s) {
+                _this._createLabel(e);
+            });
+            this._removedCameraObserver = this._scene.onCameraRemovedObservable.add(function (e, s) {
+                _this._removeLabel(e);
+            });
+            this._labelInitialized = true;
+        };
+        LabelTool.prototype._createLabel = function (node) {
+            // Don't create label for "system nodes" (starting and ending with ###)
+            var name = node.name;
+            if (INSPECTOR.Helpers.IsSystemName(name)) {
+                return;
+            }
+            var labelGroup = new BABYLON.Group2D({ parent: this._canvas, id: "Label of " + node.name, trackNode: node, origin: BABYLON.Vector2.Zero(),
+                children: [
+                    new BABYLON.Rectangle2D({ id: "LabelRect", x: 0, y: 0, width: 100, height: 30, origin: BABYLON.Vector2.Zero(), border: "#FFFFFFFF", fill: "#808080B0", children: [
+                            new BABYLON.Text2D(node.name, { x: 10, y: 4, fontName: "bold 16px Arial", fontSignedDistanceField: true })
+                        ]
+                    })
+                ] });
+            var r = labelGroup.children[0];
+            var t = r.children[0];
+            var ts = t.textSize.width;
+            r.width = ts + 20;
+            r.height = t.textSize.height + 12;
+            labelGroup.addExternalData("owner", node);
+            return labelGroup;
+        };
+        LabelTool.prototype._removeLabel = function (node) {
+            for (var _i = 0, _a = this._canvas.children; _i < _a.length; _i++) {
+                var g = _a[_i];
+                var ed = g.getExternalData("owner");
+                if (ed === node) {
+                    g.dispose();
+                    break;
+                }
+            }
+        };
         // Action : Display/hide mesh names on the canvas
         LabelTool.prototype.action = function () {
+            // Don't toggle if the script is not loaded
+            if (!this._checkC2DLoaded()) {
+                return;
+            }
+            // Toggle the label display state
+            this._isDisplayed = !this._isDisplayed;
+            // Check if we have to display the labels
             if (this._isDisplayed) {
+                this._initializeLabels();
+                this._canvas.levelVisible = true;
+            }
+            else {
+                this._canvas.levelVisible = false;
             }
-        };
-        LabelTool.prototype._update = function () {
-            this._camera = this._inspector.scene.activeCamera;
-            var engine = this._inspector.scene.getEngine();
-            var viewport = this._camera.viewport;
-            var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
-            this._camera.getViewMatrix().multiplyToRef(this._camera.getProjectionMatrix(), this._transformationMatrix);
-            // Old method
-            // let meshes = this._camera.getActiveMeshes();
-            // let projectedPosition: BABYLON.Vector3;
-            // for (let index = 0; index < meshes.length; index++) {
-            //     let mesh = meshes.data[index];
-            //     let position = mesh.getBoundingInfo().boundingSphere.center;
-            //     projectedPosition = BABYLON.Vector3.Project(position, mesh.getWorldMatrix(), this._transformationMatrix, globalViewport);
-            //     this._renderLabel(mesh.name, projectedPosition, 12,
-            //         () => { mesh.renderOverlay = !mesh.renderOverlay },
-            //         () => { return mesh.renderOverlay ? 'red' : 'black'; });
-            // }
         };
         return LabelTool;
     }(INSPECTOR.AbstractTool));
@@ -3634,7 +3849,7 @@ var INSPECTOR;
             var _this = _super.call(this) || this;
             _this._obj = obj;
             _this._elem.classList.add('fa-info-circle');
-            _this._tooltip = new INSPECTOR.Tooltip(_this._elem, _this._obj.getInfo());
+            _this._tooltip = new INSPECTOR.Tooltip(_this._elem, _this._obj.getInfo(), _this._elem);
             return _this;
         }
         // Nothing to do on click

Разница между файлами не показана из-за своего большого размера
+ 3 - 3
dist/preview release/inspector/babylon.inspector.min.js


+ 16 - 9
inspector/index.html

@@ -19,8 +19,8 @@
             font-family:sans-serif;
         }
 
-        /* First try : PG-like
-        #game-canvas {
+        /* First try : PG-like */
+        /*#game-canvas {
             width:75%;
             height:100%; 
             top:0;
@@ -39,12 +39,19 @@
             background-color: #333;
         }*/
         
+        /*Second : sandbox like*/
         #game-canvas {
             position:absolute;
             width:100%;
-            height:650px; 
+            height:100%; 
             top:0;
-            left : 150px;
+        }
+        .fakeFooter {
+            position:absolute;
+            width:100%;
+            height:50px;
+            background-color: #333;
+            bottom: 0;
         }
 
     </style>
@@ -52,15 +59,15 @@
 </head>
 <body>
     
-    <!-- First try : PG-like
+    <!-- First try : PG-like 
     <div class="fakeToolbar"></div>
     <div class="mini">
         <div class="fakeBarAgain"></div>
         <canvas id="game-canvas"></canvas> 
-    </div>
-    -->
-    <!--Second try : Sandbox-like-->
-    <canvas id="game-canvas"></canvas> 
+    </div>-->
+    <!--Second try : Sandbox-like -->
+    <canvas id="game-canvas"></canvas>
+    <div class="fakeFooter"></div>
 
     <!--Starting the game-->
     <script>

+ 2 - 6
inspector/sass/_tooltip.scss

@@ -2,17 +2,13 @@
 
 .tooltip {
     position        : absolute;
-    top             : 0;
+    top             : $tabbar-height;
     right           : 0;
     color           : $color-top;
     display         : none;
     z-index         : 4;
-    font-family     : $font;
-    
-    
-    // width        : 120px;
+    font-family     : $font;  
     padding         : 2px;
-    // line-height  : 25px;
     background-color: $background;
     border          : 1px solid $background-lighter3;
 }

+ 6 - 7
inspector/src/Inspector.ts

@@ -48,16 +48,14 @@ module INSPECTOR {
                 // Get canvas and its DOM parent
                 let canvas                    = this._scene.getEngine().getRenderingCanvas();            
                 let canvasParent              = canvas.parentElement;            
-                let canvasParentComputedStyle = Inspector.WINDOW.getComputedStyle(canvasParent);            
-                // resize canvas
-                // canvas.style.width = 'calc(100% - 750px - 12px)';
+                let canvasParentComputedStyle = Inspector.WINDOW.getComputedStyle(canvasParent);
 
                 // get canvas style                
                 let canvasComputedStyle  = Inspector.WINDOW.getComputedStyle(canvas);
 
                 this._canvasStyle = { 
-                    width        : canvasComputedStyle.width, 
-                    height       : canvasComputedStyle.height,
+                    width        : Helpers.Css(canvas, 'width'),
+                    height       : Helpers.Css(canvas, 'height'),
 
                     position     : canvasComputedStyle.position,
                     top          : canvasComputedStyle.top,
@@ -247,13 +245,14 @@ module INSPECTOR {
             if (!this._popupMode) {
                 // Get canvas
                 let canvas         = this._scene.getEngine().getRenderingCanvas(); 
+
                 // restore canvas style
                 for (let prop in this._canvasStyle) {
                     canvas.style[prop] = this._canvasStyle[prop];
                 }
-                // Get parent of the wrapper           
+                // Get parent of the wrapper 
                 let canvasParent   = canvas.parentElement.parentElement;  
-                canvasParent.appendChild(canvas);                              
+                canvasParent.insertBefore(canvas, this._c2diwrapper);
                 // Remove wrapper
                 Helpers.CleanDiv(this._c2diwrapper);
                 this._c2diwrapper.remove();                   

+ 3 - 5
inspector/src/details/PropertyLine.ts

@@ -187,12 +187,10 @@ module INSPECTOR {
          * (example : mesh.position = new BABYLON.Vector3 ; the original vector3 object is deleted from the mesh).
         */
         public updateObject() {
-            if (!this._parent) {
-                return this._property.value;
-            }
-            else {
+            if (this._parent) {
                 this._property.obj = this._parent.updateObject();
-            } 
+            }
+            return this._property.value;            
         }
 
         // Returns the property name

+ 5 - 3
inspector/src/gui/Tooltip.ts

@@ -11,11 +11,13 @@ module INSPECTOR {
         /** The tooltip div */
         private _infoDiv : HTMLDivElement;
         
-        constructor(elem: HTMLElement, tip:string) {
+        constructor(elem: HTMLElement, tip:string, attachTo?:HTMLElement) {
             
             this._elem = elem;
-            
-            this._infoDiv = Helpers.CreateDiv('tooltip', this._elem.parentElement) as HTMLDivElement;
+            if (!attachTo) {
+                attachTo = this._elem.parentElement;
+            }
+            this._infoDiv = Helpers.CreateDiv('tooltip', attachTo) as HTMLDivElement;
             
 
             this._elem.addEventListener('mouseover', () => { 

+ 13 - 0
inspector/src/helpers/Helpers.ts

@@ -118,6 +118,19 @@ module INSPECTOR {
                 div.removeChild(div.firstChild);
             }
         }
+
+        /**
+         * Returns the true value of the given CSS Attribute from the given element (in percentage or in pixel, as it was specified in the css)
+         */
+        public static Css(elem:HTMLElement, cssAttribute:string) : string{
+            let clone = elem.cloneNode(true) as HTMLElement;
+            let div = Helpers.CreateDiv('', Inspector.DOCUMENT.body);
+            div.style.display = 'none';
+            div.appendChild(clone);
+            let value = Inspector.WINDOW.getComputedStyle(clone)[cssAttribute];
+            div.remove();
+            return value;
+        }
         
         public static LoadScript() {
             BABYLON.Tools.LoadFile("https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.7.0/highlight.min.js", (elem) => {

+ 70 - 4
inspector/src/properties.ts

@@ -57,16 +57,60 @@ module INSPECTOR {
                 'uOffset', 
                 'vOffset'
             ],
+            format: (tex:BABYLON.Texture) => { return tex.name} 
         },
         
         'ArcRotateCamera' : {
-            // type: BABYLON.ArcRotateCamera,
-            properties : ['alpha', 'beta', 'radius']  
+            type: BABYLON.ArcRotateCamera,
+            properties : [
+                'alpha', 
+                'beta', 
+                'radius',
+                'angularSensibilityX',
+                'angularSensibilityY',
+                'target', 
+
+                'lowerAlphaLimit',
+                'lowerBetaLimit',
+                'upperAlphaLimit',
+                'upperBetaLimit',
+                'lowerRadiusLimit',
+                'upperRadiusLimit',
+
+                'pinchPrecision',
+                'wheelPrecision',
+                'allowUpsideDown',
+                'checkCollisions'
+            ]  
         },
         
         'Scene' : {
             type: BABYLON.Scene,
-            properties:['actionManager', 'activeCamera', 'ambientColor', 'clearColor']  
+            properties:[
+                'actionManager', 
+                'activeCamera', 
+                'ambientColor', 
+                'clearColor',
+                'forceWireframe',
+                'forcePointsCloud',
+                'forceShowBoundingBoxes',
+                'useRightHandedSystem',
+                'hoverCursor',
+                'cameraToUseForPointers', 
+                'fogEnabled', 
+                'fogColor', 
+                'fogDensity', 
+                'fogStart', 
+                'fogEnd', 
+                'shadowsEnabled', 
+                'lightsEnabled', 
+                'collisionsEnabled',
+                'gravity',
+                'meshUnderPointer', 
+                'pointerX', 
+                'pointerY', 
+                'uid'
+            ]  
         },
         'Mesh': {
             type: BABYLON.Mesh,
@@ -76,7 +120,29 @@ module INSPECTOR {
                 'rotation', 
                 'rotationQuaternion', 
                 'absolutePosition', 
-                'material'
+                'material',
+                'actionManager', 
+                'visibility', 
+                'isVisible', 
+                'isPickable', 
+                'renderingGroupId',
+                'receiveShadows', 
+                'renderOutline', 
+                'outlineColor',
+                'outlineWidth',
+                'renderOverlay',
+                'overlayColor',
+                'overlayAlpha',
+                'hasVertexAlpha',
+                'useVertexColors',
+                'layerMask',
+                'alwaysSelectAsActiveMesh',
+                'ellipsoid', 
+                'ellipsoidOffset', 
+                'edgesWidth', 
+                'edgesColor', 
+                'checkCollisions',
+                'hasLODLevels'
             ],
             format : (m:BABYLON.Mesh) : string => {return m.name;}
         },        

+ 33 - 2
inspector/src/tabs/MeshTab.ts

@@ -9,12 +9,43 @@ module INSPECTOR{
         /* Overrides super */
         protected _getTree() : Array<TreeItem> {
             let arr = [];
+            // Tab containign mesh already in results
+            let alreadyIn = [];
+            
+            // Returns true if the id of the given object starts and ends with '###'
+            let shouldExcludeThisMesh = (obj:BABYLON.Node) : boolean => {
+                return (obj.name && obj.name.indexOf('###') == 0 && obj.name.lastIndexOf('###', 0) === 0);
+            };
+
+            // Recursive method building the tree panel
+            let createNode = (obj : BABYLON.AbstractMesh) => {
+                let descendants = obj.getDescendants(true);
+
+                if (descendants.length > 0) {
+                    let node = new TreeItem(this, new MeshAdapter(obj));
+                    alreadyIn.push(node);
+                    for (let child of descendants) {     
+                        if (child instanceof BABYLON.AbstractMesh) {
+                            if (!Helpers.IsSystemName(child.name)) {  
+                                let n = createNode(child);
+                                node.add(n); 
+                            }
+                        }
+                    }
+                    node.update();
+                    return node;
+                } else {
+                    alreadyIn.push(obj);
+                    return new TreeItem(this, new MeshAdapter(obj));
+                }
+            };
             
             // get all meshes from the first scene
             let instances = this._inspector.scene;
             for (let mesh of instances.meshes) {
-                if (!Helpers.IsSystemName(mesh.name)){
-                    arr.push(new TreeItem(this, new MeshAdapter(mesh)));
+                if (alreadyIn.indexOf(mesh) == -1) {
+                    let node = createNode(mesh);
+                    arr.push(node);
                 }
             }
             return arr;

+ 5 - 0
inspector/src/tabs/PropertyTab.ts

@@ -136,6 +136,11 @@ module INSPECTOR{
                 if (item.id.toLowerCase().indexOf(filter.toLowerCase()) != -1) {
                     items.push(item);
                 }
+                for (let child of item.children) {
+                    if (child.id.toLowerCase().indexOf(filter.toLowerCase()) != -1) {
+                        items.push(item);
+                    }
+                }
             }    
             this.update(items);
         }

+ 10 - 10
inspector/src/tree/TreeItem.ts

@@ -7,7 +7,7 @@
         // 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>;
-        private _children   : Array<TreeItem> = [];
+        public children     : Array<TreeItem> = [];
         // Div element that contains all children of this node.
         private _lineContent: HTMLElement;  
 
@@ -29,7 +29,7 @@
 
         /** Add the given item as a child of this one */
         public add(child:TreeItem) {
-            this._children.push(child);
+            this.children.push(child);
             this.update();
         }
 
@@ -51,8 +51,8 @@
         /** hide all children of this item */
         public fold() {
             // Do nothing id no children
-            if (this._children.length > 0) {
-                for (let elem of this._children) {
+            if (this.children.length > 0) {
+                for (let elem of this.children) {
                     elem.toHtml().style.display = 'none';
                 }
                 this._div.classList.add('folded');
@@ -62,8 +62,8 @@
         /** Show all children of this item */
         public unfold() {
             // Do nothing id no children
-            if (this._children.length > 0) {
-                for (let elem of this._children) {
+            if (this.children.length > 0) {
+                for (let elem of this.children) {
                     elem.toHtml().style.display = 'block';
                 }
                 this._div.classList.add('unfolded');
@@ -110,11 +110,11 @@
             // Clean division holding all children
             Helpers.CleanDiv(this._lineContent);
 
-            for (let child of this._children) {
+            for (let child of this.children) {
                 let elem = child.toHtml();
                 this._lineContent.appendChild(elem);
             }
-            if (this._children.length > 0) {
+            if (this.children.length > 0) {
                 // Check if folded or not
                 if (!this._div.classList.contains('folded') && !this._div.classList.contains('unfolded')) {
                     this._div.classList.add('folded');
@@ -155,7 +155,7 @@
         public highlight(b:boolean) {
             // Remove highlight for all children 
             if (!b) {
-                for (let child of this._children) {
+                for (let child of this.children) {
                     child._adapter.highlight(b);
                 }
             }
@@ -171,7 +171,7 @@
         /** Set this item as active (background lighter) in the tree panel */
         public active(b:boolean) {
             this._div.classList.remove('active');
-            for (let child of this._children) {
+            for (let child of this.children) {
                 child.active(false);
             }
             if (b) {

+ 1 - 1
inspector/src/treetools/Info.ts

@@ -20,7 +20,7 @@ module INSPECTOR{
             this._obj = obj;
             this._elem.classList.add('fa-info-circle');
 
-            this._tooltip = new Tooltip(this._elem, this._obj.getInfo());
+            this._tooltip = new Tooltip(this._elem, this._obj.getInfo(), this._elem);
         }
 
         // Nothing to do on click

+ 2 - 4
inspector/test/index.js

@@ -16,10 +16,7 @@ var Test = (function () {
     Test.prototype._run = function () {
         var _this = this;
         this._initScene();
-        // BABYLON.DebugLayer.InspectorURL = 'http://localhost:1338/dist/preview release/inspector/babylon.inspector.js';
-        window.addEventListener('click', () => {
-            this.scene.debugLayer.show();
-        })
+        this.scene.debugLayer.show();
         this.scene.executeWhenReady(function () {
             _this._initGame();
             _this.engine.runRenderLoop(function () {
@@ -92,6 +89,7 @@ var Test = (function () {
     };
     Test.prototype._initGame = function () {
         this._createCanvas();
+        BABYLON.SceneLoader.ImportMesh('', 'test/', 'Rabbit.babylon', this.scene);
     };
     /**
      * Create the canvas2D