Переглянути джерело

Merge pull request #3144 from Temechon/master

Fixed several issues on inspector
David Catuhe 7 роки тому
батько
коміт
3a2ba3185b

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

@@ -273,6 +273,10 @@
         display: inline-block;
         font-family: 'FontAwesome', sans-serif;
         content: "\f054"; }
+      .insp-wrapper .insp-tree .line.unfolded.transformNode > span:first-of-type {
+        color: #f29766; }
+      .insp-wrapper .insp-tree .line.folded.transformNode > span:first-of-type {
+        color: #f29766; }
       .insp-wrapper .insp-tree .line .line-content {
         padding-left: 15px; }
         .insp-wrapper .insp-tree .line .line-content:hover {

+ 8 - 1
inspector/sass/_tree.scss

@@ -35,7 +35,7 @@
             line-height: 1em;
             display    : inline-block;
             font-family: 'FontAwesome', sans-serif;
-            content    : "\f078";
+            content    : "\f078";            
         }
         &.folded:before{            
             width      : 1em;
@@ -45,6 +45,13 @@
             font-family: 'FontAwesome', sans-serif;
             content    : "\f054";
         }
+        
+        &.unfolded.transformNode > span:first-of-type{
+            color:$color-top;
+        }
+        &.folded.transformNode > span:first-of-type{ 
+            color:$color-top;
+        }
 
         // Sub lines
         .line-content {

+ 0 - 5
inspector/src/adapters/Adapter.ts

@@ -20,11 +20,6 @@ module INSPECTOR {
         /** 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;
-        }
-
         /** Returns true if the given object correspond to this  */
         public correspondsTo(obj: any) {
             return obj === this._obj;

+ 16 - 8
inspector/src/adapters/MeshAdapter.ts

@@ -8,7 +8,7 @@ module INSPECTOR {
         private _axesViewer: BABYLON.Nullable<BABYLON.Debug.AxesViewer>;
         private onBeforeRenderObserver: BABYLON.Nullable<BABYLON.Observer<BABYLON.Scene>>;
 
-        constructor(mesh: BABYLON.AbstractMesh) {
+        constructor(mesh: BABYLON.Node) {
             super(mesh);
         }
 
@@ -35,10 +35,13 @@ module INSPECTOR {
             let tools = [];
             tools.push(new Checkbox(this));
             tools.push(new DebugArea(this));
-            if ((this._obj as BABYLON.AbstractMesh).getTotalVertices() > 0) {
-                tools.push(new BoundingBox(this));
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                if ((this._obj as BABYLON.AbstractMesh).getTotalVertices() > 0) {
+                    tools.push(new BoundingBox(this));
+                }
             }
 
+
             tools.push(new Info(this));
             return tools;
         }
@@ -60,7 +63,7 @@ module INSPECTOR {
         public debug(enable: boolean) {
             // Draw axis the first time
             if (!this._axesViewer) {
-                 this._drawAxis();
+                this._drawAxis();
             }
             // Display or hide axis
             if (!enable && this._axesViewer) {
@@ -73,7 +76,10 @@ module INSPECTOR {
 
         /** Returns some information about this mesh */
         public getInfo(): string {
-            return `${(this._obj as BABYLON.AbstractMesh).getTotalVertices()} vertices`;
+            if (this._obj instanceof BABYLON.AbstractMesh) {
+                return `${(this._obj as BABYLON.AbstractMesh).getTotalVertices()} vertices`;
+            }
+            return '0 vertices';
         }
 
         /** Draw X, Y and Z axis for the actual object if this adapter.
@@ -82,8 +88,6 @@ module INSPECTOR {
         private _drawAxis() {
             this._obj.computeWorldMatrix();
 
-            let mesh = this._obj as BABYLON.Mesh;
-
             // Axis
             var x = new BABYLON.Vector3(1, 0, 0);
             var y = new BABYLON.Vector3(0, 1, 0);
@@ -91,9 +95,13 @@ module INSPECTOR {
 
             this._axesViewer = new BABYLON.Debug.AxesViewer(this._obj.getScene());
 
+            let mesh = this._obj as BABYLON.TransformNode;
             this.onBeforeRenderObserver = mesh.getScene().onBeforeRenderObservable.add(() => {
                 let matrix = mesh.getWorldMatrix();
-                let extend = mesh.getBoundingInfo()!.boundingBox.extendSizeWorld;
+                let extend = new BABYLON.Vector3(1, 1, 1);
+                if (mesh instanceof BABYLON.AbstractMesh) {
+                    extend = mesh.getBoundingInfo()!.boundingBox.extendSizeWorld;
+                }
                 this._axesViewer!.scaleLines = Math.max(extend.x, extend.y, extend.z) * 2;
                 this._axesViewer!.update(this._obj.position, BABYLON.Vector3.TransformNormal(x, matrix), BABYLON.Vector3.TransformNormal(y, matrix), BABYLON.Vector3.TransformNormal(z, matrix));
             });

+ 15 - 13
inspector/src/details/PropertyLine.ts

@@ -150,7 +150,7 @@ module INSPECTOR {
             }
         }
 
-        public validateInput(value: any, forceupdate:boolean = true): void {
+        public validateInput(value: any, forceupdate: boolean = true): void {
             this.updateObject();
             if (typeof this._property.value === 'number') {
                 this._property.value = parseFloat(value);
@@ -182,7 +182,7 @@ module INSPECTOR {
             Helpers.CleanDiv(this._valueDiv);
             if (typeof this.value !== 'boolean' && !this._isSliderType()) {
                 this._valueDiv.textContent = "-";
-            } 
+            }
             // restore elements
             for (let elem of this._elements) {
                 this._valueDiv.appendChild(elem.toHtml());
@@ -313,7 +313,7 @@ module INSPECTOR {
             // Then update its value
             // this._valueDiv.textContent = " "; // TOFIX this removes the elements after
             if (typeof this.value === 'boolean') {
-                 this._checkboxInput();
+                this._checkboxInput();
             } else if (this._isSliderType()) { // Add slider when parent have slider property
                 this._rangeInput();
             } else {
@@ -386,7 +386,9 @@ module INSPECTOR {
                 this._div.classList.toggle('unfolded');
                 if (this._children.length == 0) {
                     let objToDetail = this.value;
-                    let propToDisplay = (<any>PROPERTIES)[Helpers.GET_TYPE(objToDetail)].properties.slice().reverse();
+                    // Display all properties that are not functions
+                    let propToDisplay = Helpers.GetAllLinesPropertiesAsString(objToDetail);
+                    propToDisplay.sort().reverse();
 
                     for (let prop of propToDisplay) {
                         let infos = new Property(prop, this._property.value);
@@ -395,7 +397,7 @@ module INSPECTOR {
                     }
                 }
                 // otherwise display it    
-                if (this._div.parentNode) {                
+                if (this._div.parentNode) {
                     for (let child of this._children) {
                         this._div.parentNode.insertBefore(child.toHtml(), this._div.nextSibling);
                     }
@@ -437,7 +439,7 @@ module INSPECTOR {
          * Create input entry
          */
         private _checkboxInput() {
-            if(this._valueDiv.childElementCount < 1) { // Prevent display two checkbox
+            if (this._valueDiv.childElementCount < 1) { // Prevent display two checkbox
                 this._input = Helpers.CreateInput('checkbox-element', this._valueDiv);
                 this._input.type = 'checkbox'
                 this._input.checked = this.value;
@@ -445,11 +447,11 @@ module INSPECTOR {
                     Scheduler.getInstance().pause = true;
                     this.validateInput(!this.value)
                 })
-            }            
+            }
         }
 
         private _rangeInput() {
-            if(this._valueDiv.childElementCount < 1) { // Prevent display two input range
+            if (this._valueDiv.childElementCount < 1) { // Prevent display two input range
                 this._input = Helpers.CreateInput('slider-element', this._valueDiv);
                 this._input.type = 'range';
                 this._input.style.display = 'inline-block';
@@ -457,7 +459,7 @@ module INSPECTOR {
                 this._input.max = this._getSliderProperty().max;
                 this._input.step = this._getSliderProperty().step;
                 this._input.value = this.value;
-                
+
                 this._validateInputHandler = this._rangeHandler.bind(this)
                 this._input.addEventListener('input', this._validateInputHandler)
                 this._input.addEventListener('change', () => {
@@ -479,10 +481,10 @@ module INSPECTOR {
         }
 
         private _isSliderType() { //Check if property have slider definition
-            return this._property  && 
-            PROPERTIES.hasOwnProperty(this._property.obj.constructor.name) &&
-            (<any>PROPERTIES)[this._property.obj.constructor.name].hasOwnProperty('slider') && 
-            (<any>PROPERTIES)[this._property.obj.constructor.name].slider.hasOwnProperty(this.name);
+            return this._property &&
+                PROPERTIES.hasOwnProperty(this._property.obj.constructor.name) &&
+                (<any>PROPERTIES)[this._property.obj.constructor.name].hasOwnProperty('slider') &&
+                (<any>PROPERTIES)[this._property.obj.constructor.name].slider.hasOwnProperty(this.name);
         }
 
         private _getSliderProperty() {

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

@@ -7,7 +7,7 @@ module INSPECTOR {
          * uses getClassName. If nothing is returned, used the type of the constructor
          */
         public static GET_TYPE(obj: any): string {
-            if(typeof obj === 'boolean') {
+            if (typeof obj === 'boolean') {
                 return 'boolean';
             }
 
@@ -24,10 +24,10 @@ module INSPECTOR {
                 if (!this._CheckIfTypeExists(classname)) {
                     return this._GetTypeFor(obj);
                 }
-                
+
                 return classname;
             } else {
-                
+
                 return 'type_not_defined';
             }
         }
@@ -91,6 +91,9 @@ module INSPECTOR {
 
         /** Returns the given number with 2 decimal number max if a decimal part exists */
         public static Trunc(nb: number): number {
+            if (typeof nb !== 'number') {
+                return 0;
+            }
             if (Math.round(nb) !== nb) {
                 return (<any>nb.toFixed(2));
             }
@@ -141,7 +144,7 @@ module INSPECTOR {
             div.style.display = 'none';
             div.appendChild(clone);
             let value = (<any>Inspector.WINDOW.getComputedStyle(clone))[cssAttribute];
-            if (div.parentNode)  {
+            if (div.parentNode) {
                 div.parentNode.removeChild(div);
             }
             return value;
@@ -185,20 +188,33 @@ module INSPECTOR {
          */
         public static GetAllLinesProperties(obj: any): Array<PropertyLine> {
             let propertiesLines: Array<PropertyLine> = [];
-            
+            let props = Helpers.GetAllLinesPropertiesAsString(obj);
+
+            for (let prop of props) {
+                let infos = new Property(prop, obj);
+                propertiesLines.push(new PropertyLine(infos));
+            }
+            return propertiesLines;
+        }
+
+
+        /**
+         * Returns an array of string corresponding to tjhe list of properties of the object to be displayed
+         * @param obj 
+         */
+        public static GetAllLinesPropertiesAsString(obj: any): Array<string> {
+            let props: Array<string> = [];
+
             for (let prop in obj) {
-                /**
-                 * No private and no function
-                 */
-                if(prop.substring(0, 1) !== '_' && typeof obj[prop] !== 'function') {
-                    let infos = new Property(prop, obj);
-                    propertiesLines.push(new PropertyLine(infos));
+                //No private and no function
+                if (prop.substring(0, 1) !== '_' && typeof obj[prop] !== 'function') {
+                    props.push(prop);
                 }
             }
-            return propertiesLines;
+            return props;
         }
 
-        public static Capitalize (str : string) : string {
+        public static Capitalize(str: string): string {
             return str.charAt(0).toUpperCase() + str.slice(1);
         }
     }

+ 17 - 237
inspector/src/properties.ts

@@ -20,59 +20,39 @@ module INSPECTOR {
         },
         'Vector2': {
             type: BABYLON.Vector2,
-            properties: ['x', 'y'],
             format: (vec: BABYLON.Vector2) => { return `x:${Helpers.Trunc(vec.x)}, y:${Helpers.Trunc(vec.y)}`; }
         },
         '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)}` }
         },
         'Color3': {
             type: BABYLON.Color3,
-            properties: ['r', 'g', 'b'],
             format: (color: BABYLON.Color3) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
             slider: {
-                r: {min: 0, max: 1, step: 0.01},
-                g: {min: 0, max: 1, step: 0.01},
-                b: {min: 0, max: 1, step: 0.01}
+                r: { min: 0, max: 1, step: 0.01 },
+                g: { min: 0, max: 1, step: 0.01 },
+                b: { min: 0, max: 1, step: 0.01 }
             }
         },
         'Color4': {
             type: BABYLON.Color4,
-            properties: ['r', 'g', 'b'],
             format: (color: BABYLON.Color4) => { return `R:${color.r}, G:${color.g}, B:${color.b}` },
             slider: {
-                r: {min: 0, max: 1, step: 0.01},
-                g: {min: 0, max: 1, step: 0.01},
-                b: {min: 0, max: 1, step: 0.01}
+                r: { min: 0, max: 1, step: 0.01 },
+                g: { min: 0, max: 1, step: 0.01 },
+                b: { min: 0, max: 1, step: 0.01 }
             }
         },
         'Quaternion': {
-            type: BABYLON.Quaternion,
-            properties: ['x', 'y', 'z', 'w']
+            type: BABYLON.Quaternion
         },
         'Size': {
             type: BABYLON.Size,
-            properties: ['width', 'height'],
             format: (size: BABYLON.Size) => { return `Size - w:${Helpers.Trunc(size.width)}, h:${Helpers.Trunc(size.height)}` }
         },
         'Texture': {
             type: BABYLON.Texture,
-            properties: [
-                'hasAlpha',
-                'level',
-                'name',
-                'wrapU',
-                'wrapV',
-                'uScale',
-                'vScale',
-                'uAng',
-                'vAng',
-                'wAng',
-                'uOffset',
-                'vOffset'
-            ],
             format: (tex: BABYLON.Texture) => { return tex.name }
         },
         'RenderTargetTexture': {
@@ -91,247 +71,47 @@ module INSPECTOR {
             type: BABYLON.HDRCubeTexture
         },
         'Sound': {
-            type: BABYLON.Sound,
-            properties: [
-                'name',
-                'autoplay',
-                'loop',
-                'useCustomAttenuation',
-                'soundTrackId',
-                'spatialSound',
-                'refDistance',
-                'rolloffFactor',
-                'maxDistance',
-                'distanceModel',
-                'isPlaying',
-                'isPaused'
-            ]
+            type: BABYLON.Sound
         },
         'ArcRotateCamera': {
             type: BABYLON.ArcRotateCamera,
-            properties: [
-                'position',
-                'alpha',
-                'beta',
-                'radius',
-                'angularSensibilityX',
-                'angularSensibilityY',
-                'angularTouchSensibilityX',
-                'angularTouchSensibilityY',
-                'target',
-                'lowerAlphaLimit',
-                'lowerBetaLimit',
-                'upperAlphaLimit',
-                'upperBetaLimit',
-                'lowerRadiusLimit',
-                'upperRadiusLimit',
-
-                'pinchPrecision',
-                'wheelPrecision',
-                'allowUpsideDown',
-                'checkCollisions'
-            ],
             slider: {
-                alpha: {min: 0, max: 2*Math.PI, step: 0.01},
-                beta: {min: -Math.PI, max: Math.PI, step: 0.01},
-                fov: {min: 0, max: 180, step: 1}
+                alpha: { min: 0, max: 2 * Math.PI, step: 0.01 },
+                beta: { min: -Math.PI, max: Math.PI, step: 0.01 },
+                fov: { min: 0, max: 180, step: 1 }
             }
         },
         'FreeCamera': {
             type: BABYLON.FreeCamera,
-            properties: [
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'cameraDirection',
-                'cameraRotation',
-                'ellipsoid',
-                'applyGravity',
-                'angularSensibility',
-                'keysUp',
-                'keysDown',
-                'keysLeft',
-                'keysRight',
-                'checkCollisions',
-                'speed',
-                'lockedTarget',
-                'noRotationConstraint',
-                'fov',
-                'inertia',
-                'minZ', 'maxZ',
-                'layerMask',
-                'mode',
-                'orthoBottom',
-                'orthoTop',
-                'orthoLeft',
-                'orthoRight'
-            ],
             slider: {
-                fov: {min: 0, max: 180, step: 1}
+                fov: { min: 0, max: 180, step: 1 }
             }
         },
         'Scene': {
             type: BABYLON.Scene,
-            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,
-            properties: [
-                'name',
-                'position',
-                'rotation',
-                'rotationQuaternion',
-                'absolutePosition',
-                '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; },
             slider: {
-                visibility: {min: 0, max: 1, step: 0.1}
+                visibility: { min: 0, max: 1, step: 0.1 }
             }
         },
         'StandardMaterial': {
             type: BABYLON.StandardMaterial,
-            properties: [
-                'name',
-                'alpha',
-                'alphaMode',
-                'wireframe',
-                'isFrozen',
-                'zOffset',
-
-                'ambientColor',
-                'emissiveColor',
-                'diffuseColor',
-                'specularColor',
-
-                'specularPower',
-                'useAlphaFromDiffuseTexture',
-                'linkEmissiveWithDiffuse',
-                'useSpecularOverAlpha',
-
-                'diffuseFresnelParameters',
-                'opacityFresnelParameters',
-                'reflectionFresnelParameters',
-                'refractionFresnelParameters',
-                'emissiveFresnelParameters',
-
-                'diffuseTexture',
-                'emissiveTexture',
-                'specularTexture',
-                'ambientTexture',
-                'bumpTexture',
-                'lightMapTexture',
-                'opacityTexture',
-                'reflectionTexture',
-                'refractionTexture'
-            ],
             format: (mat: BABYLON.StandardMaterial): string => { return mat.name; },
             slider: {
-                alpha: {min: 0, max: 1, step: 0.01}
+                alpha: { min: 0, max: 1, step: 0.01 }
             }
         },
         'PBRMaterial': {
             type: BABYLON.PBRMaterial,
-            properties: [
-                'name',
-                'albedoColor',
-                'albedoTexture',
-
-                'opacityTexture',
-                'reflectionTexture',
-                'emissiveTexture',
-                'bumpTexture',
-                'lightmapTexture',
-
-                'opacityFresnelParameters',
-                'emissiveFresnelParameters',
-
-                'linkEmissiveWithAlbedo',
-                'useLightmapAsShadowmap',
-
-                'useAlphaFromAlbedoTexture',
-                'useSpecularOverAlpha',
-                'useAutoMicroSurfaceFromReflectivityMap',
-                'useLogarithmicDepth',
-
-                'reflectivityColor',
-                'reflectivityTexture',
-                'reflectionTexture',
-                'reflectionColor',
-
-                'alpha',
-                'linkRefractionWithTransparency',
-                'indexOfRefraction',
-
-                'microSurface',
-                'useMicroSurfaceFromReflectivityMapAlpha',
-
-                'directIntensity',
-                'emissiveIntensity',
-                'specularIntensity',
-                'environmentIntensity',
-                'cameraExposure',
-                'cameraContrast',
-                'cameraColorGradingTexture',
-                'cameraColorCurves'
-            ],
             slider: {
-                alpha: {min: 0, max: 1, step: 0.01}
+                alpha: { min: 0, max: 1, step: 0.01 }
             }
-        },  
+        },
         'PhysicsImpostor': {
-            type: BABYLON.PhysicsImpostor,
-            properties: [
-                'friction',
-                'mass',
-                'restitution',
-            ]
+            type: BABYLON.PhysicsImpostor
         },
     }
 

+ 39 - 22
inspector/src/tabs/MeshTab.ts

@@ -1,66 +1,83 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
-module INSPECTOR{
-    
+module INSPECTOR {
+
     export class MeshTab extends PropertyTab {
-                
-        constructor(tabbar:TabBar, inspector:Inspector) {
-            super(tabbar, 'Mesh', inspector); 
+
+        constructor(tabbar: TabBar, inspector: Inspector) {
+            super(tabbar, 'Mesh', inspector);
         }
 
         /* Overrides super */
-        protected _getTree() : Array<TreeItem> {
+        protected _getTree(): Array<TreeItem> {
             let arr = new Array<TreeItem>();
             // Tab containing mesh already in results
-            let alreadyIn = new Array<BABYLON.AbstractMesh>();
+            let alreadyIn = new Array<BABYLON.Node>();
 
             // Recursive method building the tree panel
-            let createNode = (obj : BABYLON.AbstractMesh) => {
+            let createNode = (obj: BABYLON.Node) => {
                 let descendants = obj.getDescendants(true);
 
                 let node = new TreeItem(this, new MeshAdapter(obj));
 
                 if (descendants.length > 0) {
-                    for (let child of descendants) {     
-                        if (child instanceof BABYLON.AbstractMesh) {
-                            if (!Helpers.IsSystemName(child.name)) {  
+                    for (let child of descendants) {
+                        if (child instanceof BABYLON.TransformNode) {
+                            if (!Helpers.IsSystemName(child.name)) {
                                 let n = createNode(child);
-                                node.add(n); 
+                                node.add(n);
                             }
                         }
                     }
                     node.update();
-                } 
+                }
 
                 // Retrieve the root node if the mesh is actually child of another mesh
                 // This can hapen if the child mesh has been created before the parent mesh
-                if(obj.parent != null && alreadyIn.indexOf(obj) != -1){
+                if (obj.parent != null && alreadyIn.indexOf(obj) != -1) {
                     let i: number = 0;
                     let notFound: boolean = true;
                     // Find and delete the root node standing for this mesh
-                    while(i < arr.length && notFound){
-                        if(obj.name === arr[i].id){
-                             arr.splice(i, 1);
-                             notFound = false;
+                    while (i < arr.length && notFound) {
+                        if (obj.name === arr[i].id) {
+                            arr.splice(i, 1);
+                            notFound = false;
                         }
                         i++;
                     }
                 }
 
-                alreadyIn.push(obj);                
+                alreadyIn.push(obj);
                 return node;
             };
-            
+
             // get all meshes from the first scene
             let instances = this._inspector.scene;
+
+            // Find top of hierarchy for meshes...
+            let meshWithoutAnyParent: Array<BABYLON.Node> = [];
             for (let mesh of instances.meshes) {
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(mesh) == -1 && !Helpers.IsSystemName(mesh.name) && !mesh.parent) {
+                    meshWithoutAnyParent.push(mesh);
+                }
+            }
+            // ... and for transforms
+            for (let tn of instances.transformNodes) {
+                // Not already in the array, not system name and no parent
+                if (meshWithoutAnyParent.indexOf(tn) == -1 && !Helpers.IsSystemName(tn.name) && !tn.parent) {
+                    meshWithoutAnyParent.push(tn);
+                }
+            }
+
+            for (let mesh of meshWithoutAnyParent) {
                 if (alreadyIn.indexOf(mesh) == -1 && !Helpers.IsSystemName(mesh.name)) {
                     let node = createNode(mesh);
                     arr.push(node);
                 }
             }
             return arr;
-        }  
+        }
     }
-    
+
 }

+ 78 - 77
inspector/src/tabs/SceneTab.ts

@@ -1,55 +1,56 @@
 declare function Split(elements: HTMLElement[], options: any): void;
 module INSPECTOR {
-    
+
     export class SceneTab extends Tab {
-        
-        private _inspector : Inspector;
+
+        private _inspector: Inspector;
         /** The list of  channels/options that can be activated/deactivated */
-        private _actions   : HTMLDivElement;
+        private _actions: HTMLDivElement;
 
         /** The list of skeleton viewer */
-        private _skeletonViewers : Array<BABYLON.Debug.SkeletonViewer> = [];
+        private _skeletonViewers: Array<BABYLON.Debug.SkeletonViewer> = [];
 
         /** The detail of the scene */
-        private _detailsPanel : DetailPanel;        
-                
-        constructor(tabbar:TabBar, insp:Inspector) {
-            super(tabbar, 'Scene');            
-            this._inspector = insp;  
-            
+        private _detailsPanel: DetailPanel;
+
+        constructor(tabbar: TabBar, insp: Inspector) {
+            super(tabbar, 'Scene');
+            this._inspector = insp;
+
             // Build the properties panel : a div that will contains the tree and the detail panel
-            this._panel   = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
-            
+            this._panel = Helpers.CreateDiv('tab-panel') as HTMLDivElement;
+
             this._actions = Helpers.CreateDiv('scene-actions', this._panel) as HTMLDivElement;
-           
+
             this._detailsPanel = new DetailPanel();
             this._panel.appendChild(this._detailsPanel.toHtml());
-            
+
             // build propertiesline
             let details = [];
-            for (let prop of PROPERTIES['Scene'].properties) {
-                details.push(new PropertyLine(new Property(prop, this._inspector.scene)));
+            let props = Helpers.GetAllLinesProperties(this._inspector.scene);
+            for (let prop of props) {
+                details.push(prop);
             }
             this._detailsPanel.details = details;
-            
-            Split([this._actions, this._detailsPanel.toHtml()], {  
-                blockDrag : this._inspector.popupMode,
-                sizes:[50, 50],
-                direction:'vertical'
-            });  
-            
+
+            Split([this._actions, this._detailsPanel.toHtml()], {
+                blockDrag: this._inspector.popupMode,
+                sizes: [50, 50],
+                direction: 'vertical'
+            });
+
             // Build actions
             {
-                
+
                 // Rendering mode
                 let title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Rendering mode';
-                let point             = Helpers.CreateDiv('action-radio', this._actions);
-                let wireframe         = Helpers.CreateDiv('action-radio', this._actions);
-                let solid             = Helpers.CreateDiv('action-radio', this._actions);
-                point.textContent     = 'Point';
+                let point = Helpers.CreateDiv('action-radio', this._actions);
+                let wireframe = Helpers.CreateDiv('action-radio', this._actions);
+                let solid = Helpers.CreateDiv('action-radio', this._actions);
+                point.textContent = 'Point';
                 wireframe.textContent = 'Wireframe';
-                solid.textContent     = 'Solid';
+                solid.textContent = 'Solid';
                 if (this._inspector.scene.forcePointsCloud) {
                     point.classList.add('active');
                 } else if (this._inspector.scene.forceWireframe) {
@@ -58,64 +59,64 @@ module INSPECTOR {
                     solid.classList.add('active');
                 }
                 this._generateRadioAction([point, wireframe, solid]);
-                point.addEventListener('click', () => {this._inspector.scene.forcePointsCloud = true; this._inspector.scene.forceWireframe = false;});
-                wireframe.addEventListener('click', () => {this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = true; });
-                solid.addEventListener('click',  () => {this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = false; });
+                point.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = true; this._inspector.scene.forceWireframe = false; });
+                wireframe.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = true; });
+                solid.addEventListener('click', () => { this._inspector.scene.forcePointsCloud = false; this._inspector.scene.forceWireframe = false; });
 
                 // Textures
                 title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Textures channels';
-                this._generateActionLine('Diffuse Texture', BABYLON.StandardMaterial.DiffuseTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.DiffuseTextureEnabled = b });
-                this._generateActionLine('Ambient Texture', BABYLON.StandardMaterial.AmbientTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.AmbientTextureEnabled = b });
-                this._generateActionLine('Specular Texture', BABYLON.StandardMaterial.SpecularTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.SpecularTextureEnabled = b });
-                this._generateActionLine('Emissive Texture', BABYLON.StandardMaterial.EmissiveTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.EmissiveTextureEnabled = b });
-                this._generateActionLine('Bump Texture', BABYLON.StandardMaterial.BumpTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.BumpTextureEnabled = b });
-                this._generateActionLine('Opacity Texture', BABYLON.StandardMaterial.OpacityTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.OpacityTextureEnabled = b });
-                this._generateActionLine('Reflection Texture', BABYLON.StandardMaterial.ReflectionTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.ReflectionTextureEnabled = b });
-                this._generateActionLine('Refraction Texture', BABYLON.StandardMaterial.RefractionTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.RefractionTextureEnabled = b });
-                this._generateActionLine('ColorGrading', BABYLON.StandardMaterial.ColorGradingTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.ColorGradingTextureEnabled = b });
-                this._generateActionLine('Lightmap Texture', BABYLON.StandardMaterial.LightmapTextureEnabled, (b:boolean) => {BABYLON.StandardMaterial.LightmapTextureEnabled = b });
-                this._generateActionLine('Fresnel', BABYLON.StandardMaterial.FresnelEnabled, (b:boolean) => {BABYLON.StandardMaterial.FresnelEnabled = b });
+                this._generateActionLine('Diffuse Texture', BABYLON.StandardMaterial.DiffuseTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.DiffuseTextureEnabled = b });
+                this._generateActionLine('Ambient Texture', BABYLON.StandardMaterial.AmbientTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.AmbientTextureEnabled = b });
+                this._generateActionLine('Specular Texture', BABYLON.StandardMaterial.SpecularTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.SpecularTextureEnabled = b });
+                this._generateActionLine('Emissive Texture', BABYLON.StandardMaterial.EmissiveTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.EmissiveTextureEnabled = b });
+                this._generateActionLine('Bump Texture', BABYLON.StandardMaterial.BumpTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.BumpTextureEnabled = b });
+                this._generateActionLine('Opacity Texture', BABYLON.StandardMaterial.OpacityTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.OpacityTextureEnabled = b });
+                this._generateActionLine('Reflection Texture', BABYLON.StandardMaterial.ReflectionTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.ReflectionTextureEnabled = b });
+                this._generateActionLine('Refraction Texture', BABYLON.StandardMaterial.RefractionTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.RefractionTextureEnabled = b });
+                this._generateActionLine('ColorGrading', BABYLON.StandardMaterial.ColorGradingTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.ColorGradingTextureEnabled = b });
+                this._generateActionLine('Lightmap Texture', BABYLON.StandardMaterial.LightmapTextureEnabled, (b: boolean) => { BABYLON.StandardMaterial.LightmapTextureEnabled = b });
+                this._generateActionLine('Fresnel', BABYLON.StandardMaterial.FresnelEnabled, (b: boolean) => { BABYLON.StandardMaterial.FresnelEnabled = b });
 
                 // Options
                 title = Helpers.CreateDiv('actions-title', this._actions);
-                title.textContent = 'Options'; 
-                this._generateActionLine('Animations', this._inspector.scene.animationsEnabled, (b:boolean) => {this._inspector.scene.animationsEnabled = b });
-                this._generateActionLine('Collisions', this._inspector.scene.collisionsEnabled, (b:boolean) => {this._inspector.scene.collisionsEnabled = b });
-                this._generateActionLine('Fog', this._inspector.scene.fogEnabled, (b:boolean) => {this._inspector.scene.fogEnabled = b });
-                this._generateActionLine('Lens flares', this._inspector.scene.lensFlaresEnabled, (b:boolean) => {this._inspector.scene.lensFlaresEnabled = b });
-                this._generateActionLine('Lights', this._inspector.scene.lightsEnabled, (b:boolean) => {this._inspector.scene.lightsEnabled = b });
-                this._generateActionLine('Particles', this._inspector.scene.particlesEnabled, (b:boolean) => {this._inspector.scene.particlesEnabled = b });
-                this._generateActionLine('Post-processes', this._inspector.scene.postProcessesEnabled, (b:boolean) => {this._inspector.scene.postProcessesEnabled = b });
-                this._generateActionLine('Probes', this._inspector.scene.probesEnabled, (b:boolean) => {this._inspector.scene.probesEnabled = b });
-                this._generateActionLine('Procedural textures', this._inspector.scene.proceduralTexturesEnabled, (b:boolean) => {this._inspector.scene.proceduralTexturesEnabled = b });
-                this._generateActionLine('Render targets', this._inspector.scene.renderTargetsEnabled, (b:boolean) => {this._inspector.scene.renderTargetsEnabled = b });
-                this._generateActionLine('Shadows', this._inspector.scene.shadowsEnabled, (b:boolean) => {this._inspector.scene.shadowsEnabled = b });
-                this._generateActionLine('Skeletons', this._inspector.scene.skeletonsEnabled, (b:boolean) => {this._inspector.scene.skeletonsEnabled = b });
-                this._generateActionLine('Sprites', this._inspector.scene.spritesEnabled, (b:boolean) => {this._inspector.scene.spritesEnabled = b });
-                this._generateActionLine('Textures', this._inspector.scene.texturesEnabled, (b:boolean) => {this._inspector.scene.texturesEnabled = b });
-                
+                title.textContent = 'Options';
+                this._generateActionLine('Animations', this._inspector.scene.animationsEnabled, (b: boolean) => { this._inspector.scene.animationsEnabled = b });
+                this._generateActionLine('Collisions', this._inspector.scene.collisionsEnabled, (b: boolean) => { this._inspector.scene.collisionsEnabled = b });
+                this._generateActionLine('Fog', this._inspector.scene.fogEnabled, (b: boolean) => { this._inspector.scene.fogEnabled = b });
+                this._generateActionLine('Lens flares', this._inspector.scene.lensFlaresEnabled, (b: boolean) => { this._inspector.scene.lensFlaresEnabled = b });
+                this._generateActionLine('Lights', this._inspector.scene.lightsEnabled, (b: boolean) => { this._inspector.scene.lightsEnabled = b });
+                this._generateActionLine('Particles', this._inspector.scene.particlesEnabled, (b: boolean) => { this._inspector.scene.particlesEnabled = b });
+                this._generateActionLine('Post-processes', this._inspector.scene.postProcessesEnabled, (b: boolean) => { this._inspector.scene.postProcessesEnabled = b });
+                this._generateActionLine('Probes', this._inspector.scene.probesEnabled, (b: boolean) => { this._inspector.scene.probesEnabled = b });
+                this._generateActionLine('Procedural textures', this._inspector.scene.proceduralTexturesEnabled, (b: boolean) => { this._inspector.scene.proceduralTexturesEnabled = b });
+                this._generateActionLine('Render targets', this._inspector.scene.renderTargetsEnabled, (b: boolean) => { this._inspector.scene.renderTargetsEnabled = b });
+                this._generateActionLine('Shadows', this._inspector.scene.shadowsEnabled, (b: boolean) => { this._inspector.scene.shadowsEnabled = b });
+                this._generateActionLine('Skeletons', this._inspector.scene.skeletonsEnabled, (b: boolean) => { this._inspector.scene.skeletonsEnabled = b });
+                this._generateActionLine('Sprites', this._inspector.scene.spritesEnabled, (b: boolean) => { this._inspector.scene.spritesEnabled = b });
+                this._generateActionLine('Textures', this._inspector.scene.texturesEnabled, (b: boolean) => { this._inspector.scene.texturesEnabled = b });
+
                 // Audio
                 title = Helpers.CreateDiv('actions-title', this._actions);
-                title.textContent         = 'Audio'; 
-                let headphones            = Helpers.CreateDiv('action-radio', this._actions);
-                let normalSpeaker         = Helpers.CreateDiv('action-radio', this._actions);
-                this._generateActionLine('Disable audio', !this._inspector.scene.audioEnabled, (b:boolean) => {this._inspector.scene.audioEnabled = !b });
-                headphones.textContent    = 'Headphones';
-                normalSpeaker.textContent = 'Normal speakers';                
+                title.textContent = 'Audio';
+                let headphones = Helpers.CreateDiv('action-radio', this._actions);
+                let normalSpeaker = Helpers.CreateDiv('action-radio', this._actions);
+                this._generateActionLine('Disable audio', !this._inspector.scene.audioEnabled, (b: boolean) => { this._inspector.scene.audioEnabled = !b });
+                headphones.textContent = 'Headphones';
+                normalSpeaker.textContent = 'Normal speakers';
                 this._generateRadioAction([headphones, normalSpeaker]);
                 if (this._inspector.scene.headphone) {
                     headphones.classList.add('active');
                 } else {
                     normalSpeaker.classList.add('active');
                 }
-                headphones.addEventListener('click', () => {this._inspector.scene.headphone = true;});
-                normalSpeaker.addEventListener('click', () => {this._inspector.scene.headphone = false;});
-                
+                headphones.addEventListener('click', () => { this._inspector.scene.headphone = true; });
+                normalSpeaker.addEventListener('click', () => { this._inspector.scene.headphone = false; });
+
                 // Viewers
                 title = Helpers.CreateDiv('actions-title', this._actions);
                 title.textContent = 'Viewer';
-                this._generateActionLine('Skeletons', false, (b:boolean) => {
+                this._generateActionLine('Skeletons', false, (b: boolean) => {
                     if (b) {
                         for (var index = 0; index < this._inspector.scene.meshes.length; index++) {
                             var mesh = this._inspector.scene.meshes[index];
@@ -141,17 +142,17 @@ module INSPECTOR {
                         }
                         this._skeletonViewers = [];
                     }
-                });                
-            }            
+                });
+            }
         }
 
         /** Overrides super.dispose */
         public dispose() {
             this._detailsPanel.dispose();
         }
-        
+
         /** generates a div which correspond to an option that can be activated/deactivated */
-        private _generateActionLine(name:string, initValue:boolean, action:(b:boolean) => void) {
+        private _generateActionLine(name: string, initValue: boolean, action: (b: boolean) => void) {
             let div = Helpers.CreateDiv('scene-actions', this._actions);
             div.textContent = name;
             div.classList.add('action');
@@ -159,9 +160,9 @@ module INSPECTOR {
                 div.classList.add('active');
             }
             div.addEventListener('click', (e) => {
-                div.classList.toggle('active');      
+                div.classList.toggle('active');
                 let isActivated = div.classList.contains('active');
-                action(isActivated);          
+                action(isActivated);
             })
         }
 
@@ -169,7 +170,7 @@ module INSPECTOR {
          * Add a click action for all given elements : 
          * the clicked element is set as active, all others elements are deactivated
          */
-        private _generateRadioAction(arr:Array<HTMLElement>) {
+        private _generateRadioAction(arr: Array<HTMLElement>) {
             let active = (elem: HTMLElement, evt: any) => {
                 for (let e of arr) {
                     e.classList.remove('active');

+ 8 - 0
inspector/src/tree/TreeItem.ts

@@ -82,6 +82,14 @@ module INSPECTOR {
         protected _build() {
             this._div.className = 'line';
 
+            // special class for transform node ONLY
+            if (this.adapter instanceof MeshAdapter) {
+                let obj = this.adapter.object;
+                if (obj instanceof BABYLON.TransformNode && !(obj instanceof BABYLON.AbstractMesh)) {
+                    this._div.className += ' transformNode';
+                }
+            }
+
 
             for (let tool of this._tools) {
                 this._div.appendChild(tool.toHtml());

+ 24 - 284
inspector/test/index.js

@@ -35,301 +35,41 @@ var Test = (function () {
     Test.prototype._initScene = function () {
         var scene = new BABYLON.Scene(this.engine);
         var canvas = scene.getEngine().getRenderingCanvas();
-        var light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 0), scene);
 
-        var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, 1.0, 110, new BABYLON.Vector3(0, -20, 0), scene);
-        camera.attachControl(canvas, true);
 
-        var camera1 = new BABYLON.ArcRotateCamera("Camera1", 1.58, 1.2, 110, BABYLON.Vector3.Zero(), scene);
-        var camera2 = new BABYLON.ArcRotateCamera("Camera2", Math.PI / 3, .8, 40, BABYLON.Vector3.Zero(), scene);
-        var camera3 = new BABYLON.ArcRotateCamera("Camera3", -Math.PI / 5, 1.0, 70, BABYLON.Vector3.Zero(), scene);
-        var camera4 = new BABYLON.ArcRotateCamera("Camera4", -Math.PI / 6, 1.3, 110, BABYLON.Vector3.Zero(), scene);
+        var sceneRoot = new BABYLON.TransformNode("abstractmesh");
 
-        camera1.layerMask = 2;
-        camera2.layerMask = 2;
-        camera3.layerMask = 2;
-        camera4.layerMask = 2;
-        /*
-            camera1.parent = camera;
-            camera2.parent = camera;
-            camera3.parent = camera;
-            camera4.parent = camera;
-        */
+        var tn = new BABYLON.TransformNode("transform node");
 
-        //Sounds
-        var jump = new BABYLON.Sound("Jump", "test/jump.wav", scene);
-        var explosion = new BABYLON.Sound("Explosion", "test/explosion.wav", scene);
-        jump.setVolume(0.1);
-        window.addEventListener("keydown", function (evt) {
-            if (evt.keyCode === 32) {
-                jump.play();
-            }
-        });
-
-        // Skybox
-        var skybox = BABYLON.Mesh.CreateBox("skyBox", 500.0, scene);
-        var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
-        skyboxMaterial.backFaceCulling = false;
-        skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("/playground/textures/TropicalSunnyDay", scene);
-        skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
-        skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
-        skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
-        skyboxMaterial.disableLighting = true;
-        skybox.material = skyboxMaterial;
-
-        var sphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 10.0, 9.0, scene);
-        var sphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 2.0, 9.0, scene);//Only two segments
-        var sphere3 = BABYLON.Mesh.CreateSphere("Sphere3", 10.0, 9.0, scene);
-        var sphere4 = BABYLON.Mesh.CreateSphere("Sphere4", 10.0, 9.0, scene);
-        var sphere5 = BABYLON.Mesh.CreateSphere("Sphere5", 10.0, 9.0, scene);
-        var sphere6 = BABYLON.Mesh.CreateSphere("Sphere6", 10.0, 9.0, scene);
-
-        sphere1.position.x = 40;
-        sphere2.position.x = 25;
-        sphere3.position.x = 10;
-        sphere4.position.x = -5;
-        sphere5.position.x = -20;
-        sphere6.position.x = -35;
-
-        var rt1 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt1);
-        rt1.activeCamera = camera1;
-        rt1.renderList = scene.meshes;
-
-        var rt2 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt2);
-        rt2.activeCamera = camera2;
-        rt2.renderList = scene.meshes;
-
-        var rt3 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt3);
-        rt3.activeCamera = camera3;
-        rt3.renderList = scene.meshes;
-
-        var rt4 = new BABYLON.RenderTargetTexture("depth", 1024, scene, true, true);
-        scene.customRenderTargets.push(rt4);
-        rt4.activeCamera = camera4;
-        rt4.renderList = scene.meshes;
-
-        var mon1 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon1.position = new BABYLON.Vector3(-8.8, -7.8, 25)
-        // mon1.showBoundingBox = true;
-        var mon1mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon1mat.diffuseTexture = rt1;
-        mon1.material = mon1mat;
-        mon1.parent = camera;
-        mon1.layerMask = 1;
-
-        var mon2 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon2.position = new BABYLON.Vector3(-2.9, -7.8, 25)
-        // mon2.showBoundingBox = true;
-        var mon2mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon2mat.diffuseTexture = rt2;
-        mon2.material = mon2mat;
-        mon2.parent = camera;
-        mon2.layerMask = 1;
-
-        var mon3 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon3.position = new BABYLON.Vector3(2.9, -7.8, 25)
-        // mon3.showBoundingBox = true;
-        var mon3mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon3mat.diffuseTexture = rt3;
-        mon3.material = mon3mat;
-        mon3.parent = camera;
-        mon3.layerMask = 1;
-
-
-        var mon4 = BABYLON.Mesh.CreatePlane("plane", 5, scene);
-        mon4.position = new BABYLON.Vector3(8.8, -7.8, 25)
-        // mon4.showBoundingBox = true;
-        var mon4mat = new BABYLON.StandardMaterial("texturePlane", scene);
-        mon4mat.diffuseTexture = rt4;
-        mon4.material = mon4mat;
-        mon4.parent = camera;
-        mon4.layerMask = 1;
-
-
-        var butback = BABYLON.MeshBuilder.CreatePlane("plane", { width: 25, height: 6 }, scene);
-        butback.position = new BABYLON.Vector3(0, -8.2, 26)
-        // butback.showBoundingBox = true;
-        var butbackmat = new BABYLON.StandardMaterial("texturePlane", scene);
-        butbackmat.diffuseColor = BABYLON.Color3.Black();
-        butback.material = butbackmat;
-        butback.parent = camera;
-        butback.layerMask = 1;
-
-        var plane = BABYLON.Mesh.CreatePlane("plane", 120, scene);
-        plane.position.y = -5;
-        plane.rotation.x = Math.PI / 2;
-
-        var materialSphere1 = new BABYLON.StandardMaterial("texture1", scene);
-        materialSphere1.wireframe = true;
-
-        //Creation of a red material with alpha
-        var materialSphere2 = new BABYLON.StandardMaterial("texture2", scene);
-        materialSphere2.diffuseColor = new BABYLON.Color3(1, 0, 0); //Red
-        materialSphere2.alpha = 0.3;
-
-        //Creation of a material with an image texture
-        var materialSphere3 = new BABYLON.StandardMaterial("texture3", scene);
-        materialSphere3.diffuseTexture = new BABYLON.Texture("/playground/textures/amiga.jpg", scene);
-
-        //Creation of a material with translated texture
-        var materialSphere4 = new BABYLON.StandardMaterial("texture4", scene);
-        materialSphere4.diffuseTexture = new BABYLON.Texture("/playground/textures/floor.png", scene);
-        materialSphere4.diffuseTexture.vOffset = 0.1;//Vertical offset of 10%
-        materialSphere4.diffuseTexture.uOffset = 0.4;//Horizontal offset of 40%
-
-        //Creation of a material with an alpha texture
-        var materialSphere5 = new BABYLON.StandardMaterial("texture5", scene);
-        materialSphere5.diffuseTexture = new BABYLON.Texture("/playground/textures/rock.png", scene);
-        materialSphere5.diffuseTexture.hasAlpha = true;//Has an alpha
-
-        //Creation of a material and show all the faces
-        var materialSphere6 = new BABYLON.StandardMaterial("texture6", scene);
-        materialSphere6.diffuseTexture = new BABYLON.Texture("/playground/textures/grass.png", scene);
-        materialSphere6.diffuseTexture.hasAlpha = true;//Have an alpha
-        materialSphere6.backFaceCulling = false;//Show all the faces of the element
-
-        //Creation of a repeated textured material
-        var materialPlane = new BABYLON.StandardMaterial("texturePlane", scene);
-        materialPlane.diffuseTexture = new BABYLON.Texture("/playground/textures/mixMap.png", scene);
-        materialPlane.diffuseTexture.uScale = 5.0;
-        materialPlane.diffuseTexture.vScale = 5.0;
-        materialPlane.backFaceCulling = false;
-
-        //Apply the materials to meshes
-        sphere1.material = materialSphere1;
-        sphere2.material = materialSphere2;
+        // Our built-in 'ground' shape. Params: name, width, depth, subdivs, scene
+        var ground = BABYLON.Mesh.CreateGround("node_damagedHelmet_-6514", 6, 6, 2, scene);
+        ground.parent = tn;
 
-        sphere3.material = materialSphere3;
-        sphere4.material = materialSphere4;
+        let num = 5;
+        let angStep = 6.283185307 / num;
+        let rad = 2;
+        let p = sceneRoot;
+        for (let i = 0; i < num; i++) {
+            // Our built-in 'sphere' shape. Params: name, subdivs, size, scene
+            let sphere = BABYLON.Mesh.CreateSphere(`sphere${i}`, 16, 2, scene);
 
-        sphere5.material = materialSphere5;
-        sphere6.material = materialSphere6;
-
-        plane.material = materialPlane;
-
-        new BABYLON.Mesh('mesh_without_geometry', scene);
-
-
-
-        var d = 50;
-        var cubes = new Array();
-        for (var i = 0; i < 360; i += 20) {
-            var r = BABYLON.Tools.ToRadians(i);
-            var b = BABYLON.Mesh.CreateBox("Box #" + i / 20, 5, scene, false);
-            b.position.x = Math.cos(r) * d;
-            b.position.z = Math.sin(r) * d;
-            cubes.push(b);
+            // Move the sphere upward 1/2 its height        
+            sphere.position.y = 0.2;
+            sphere.position.x = Math.sin(i * angStep) * rad;
+            sphere.position.z = Math.cos(i * angStep) * rad;
+            sphere.parent = p;
+            p = sphere;
         }
 
-        scene.getMeshByName("Box #6").scaling.x = 2;
-
-        //Other meshes, to contrôl mesh hierarchy
-        var box1 = BABYLON.MeshBuilder.CreateBox("box1", {size: 1}, scene);
-
-        var box2 = BABYLON.MeshBuilder.CreateBox("box2", {size: 1}, scene);
-        box2.position.x = 1.5;
-        box2.parent = box1;
-
-        var box3 = BABYLON.MeshBuilder.CreateBox("box3", {size: 1}, scene);
-        box3.position.x = 1.5;
-        box3.parent = box2;
-
-        var box4 = BABYLON.MeshBuilder.CreateBox("box4", {size: 1}, scene);
-        box4.position.x = 1.5;
-        box4.parent = box3;
-
-        window.addEventListener("keydown", function (evt) {
-            sphere1.dispose();
-            var sphere7 = BABYLON.Mesh.CreateSphere("Sphere7", 10.0, 9.0, scene);
-            sphere7.position.x = 40;
+        let t = 0;
+        scene.registerBeforeRender(() => {
+            ground.rotation.y += 0.01;
+            ground.position.y = Math.cos(t += 0.01);
         });
 
-        var sphere_1 = BABYLON.Mesh.CreateSphere("_sphere_1", 16, 2, scene);
-
-        var assets_mesh = new BABYLON.AbstractMesh("assets_mesh", scene);
-        var sphere_2 = BABYLON.Mesh.CreateSphere("_sphere_2", 3, 2, scene);
-        var sphere_3 = BABYLON.Mesh.CreateSphere("_sphere_3", 2, 2, scene);
-        var scene_mesh = new BABYLON.AbstractMesh;
-        scene_mesh.name="scene_mesh";
-    
-        sphere_1.parent = assets_mesh;
-        sphere_2.parent = assets_mesh;
-        sphere_3.parent = assets_mesh;
-
-        for (var i=0; i<10 ; i++){
-            var inst = sphere_1.createInstance("C_" + i + "clone");
-            inst.isVisible = true;
-            inst.setEnabled = true;
-            inst.parent = scene_mesh;
-            inst.position.x = i*2;
-            inst.refreshBoundingInfo();
-            inst.computeWorldMatrix();
-        }
-
-        // to test reflection prob texture handling
-        var probe = new BABYLON.ReflectionProbe("probe", 512, scene);
-        probe.renderList.push(sphere1);
-
-        // gui
-        var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
-
-        var picker = new BABYLON.GUI.ColorPicker();
-        picker.height = "150px";
-        picker.width = "150px";
-        picker.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
-
-        var checkbox = new BABYLON.GUI.Checkbox();
-        checkbox.width = "20px";
-        checkbox.height = "20px";
-
-        var slider = new BABYLON.GUI.Slider();
-        slider.minimum = 0;
-        slider.maximum = 2 * Math.PI;
-        slider.value = 0;
-        slider.height = "20px";
-        slider.width = "200px";
-
-        var line = new BABYLON.GUI.Line();
-        line.x1 = 10;
-        line.y1 = 10;
-        line.x2 = 1000;
-        line.y2 = 500;
-
-        var panel = new BABYLON.GUI.StackPanel();    
-
-        var button = BABYLON.GUI.Button.CreateSimpleButton("but", "Click Me");
-        button.width = 0.2;
-        button.height = "40px";
-        button.color = "white";
-        button.background = "green";
-        panel.addControl(button);     
-
-        var button2 = BABYLON.GUI.Button.CreateSimpleButton("but2", "Click Me also!");
-        button2.width = 0.2;
-        button2.height = "40px";
-        button2.color = "white";
-        button2.background = "green";
-        panel.addControl(button2);     
-
-        var ellipse1 = new BABYLON.GUI.Ellipse();
-        ellipse1.width = "100px"
-        ellipse1.height = "100px";
-        ellipse1.color = "Orange";
-        ellipse1.thickness = 4;
-        ellipse1.background = "green";
-
+        scene.createDefaultCameraOrLight(true);
+        scene.activeCamera.attachControl(canvas);
 
-        advancedTexture.addControl(ellipse1);    
-        advancedTexture.addControl(panel);   
-        advancedTexture.addControl(picker);    
-        advancedTexture.addControl(checkbox);    
-        advancedTexture.addControl(slider);    
-        advancedTexture.addControl(line);    
-        advancedTexture.addControl(checkbox);  
-        
         this.scene = scene;
     };
     return Test;

+ 1 - 1
sandbox/index.css

@@ -56,7 +56,7 @@ a {
     width: 100%;
     height: 100%;
     top: 0;
-    margin-bottom: 70px;
+    margin-bottom: 65px;
     touch-action: none;
     -ms-touch-action: none;
 }