فهرست منبع

Added stackPanel3d
Attached to #4310

David Catuhe 7 سال پیش
والد
کامیت
0b93412b47

+ 2 - 1
Tools/Gulp/config.json

@@ -1668,7 +1668,8 @@
                     "../../gui/src/3D/controls/control3D.ts",
                     "../../gui/src/3D/controls/container3D.ts",
                     "../../gui/src/3D/controls/button3D.ts",
-                    "../../gui/src/3D/controls/holographicButton.ts"
+                    "../../gui/src/3D/controls/holographicButton.ts",
+                    "../../gui/src/3D/controls/stackPanel3D.ts"
                 ],
                 "shaderFiles": [
                     "../../gui/src/3D/materials/shaders/fluent.vertex.fx",

+ 2 - 2
gui/src/3D/controls/button3D.ts

@@ -76,7 +76,7 @@ module BABYLON.GUI {
         }        
 
         // Mesh association
-        protected _createMesh(scene: Scene): Mesh {
+        protected _createNode(scene: Scene): TransformNode {
             var faceUV = new Array(6);
 
             for (var i = 0; i < 6; i++) {
@@ -87,7 +87,7 @@ module BABYLON.GUI {
             let mesh = MeshBuilder.CreateBox(this.name + "Mesh", {
                 width: 1.0, 
                 height: 1.0,
-                depth: 0.1,
+                depth: 0.05,
                 faceUV: faceUV
             }, scene); 
            

+ 24 - 2
gui/src/3D/controls/container3D.ts

@@ -5,7 +5,10 @@ module BABYLON.GUI {
      * Class used to create containers for controls
      */
     export class Container3D extends Control3D {
-        private _children = new Array<Control3D>();
+        /**
+         * Gets the list of child controls
+         */
+        protected _children = new Array<Control3D>();
 
         /**
          * Creates a new container
@@ -38,13 +41,32 @@ module BABYLON.GUI {
             control.parent = this;
             control._host = this._host;
 
+            this._children.push(control);
+
             if (this._host.utilityLayer) {
-                control.prepareMesh(this._host.utilityLayer.utilityLayerScene);
+                control._prepareNode(this._host.utilityLayer.utilityLayerScene);
+
+                if (control.node) {
+                    control.node.parent = this.node;
+                }
+
+                this._arrangeChildren();
             }
 
             return this;
         }
 
+
+        /**
+         * This function will be called everytime a new control is added 
+         */
+        protected _arrangeChildren() {
+        }
+
+        protected _createNode(scene: Scene): Nullable<TransformNode> {
+            return new TransformNode("ContainerNode", scene);
+        }
+
         /**
          * Removes the control from the children of this control
          * @param control defines the control to remove

+ 47 - 44
gui/src/3D/controls/control3D.ts

@@ -7,12 +7,17 @@ module BABYLON.GUI {
     export class Control3D implements IDisposable, IBehaviorAware<Control3D> {
         /** @hidden */
         public _host: GUI3DManager;
-        private _mesh: Nullable<Mesh>;
+        private _node: Nullable<TransformNode>;
         private _downCount = 0;
         private _enterCount = 0;
         private _downPointerIds:{[id:number] : boolean} = {};
         private _isVisible = true;
 
+        /** Gets or sets the control position */
+        public position = new Vector3(0, 0, 0);
+        /** Gets or sets the control scaling */
+        public scaling = new Vector3(1, 1, 1);
+
         /** Callback used to start pointer enter animation */
         public pointerEnterAnimation: () => void;
         /** Callback used to start pointer out animation */
@@ -142,24 +147,11 @@ module BABYLON.GUI {
             }
 
             this._isVisible = value;
-            if (this._mesh) {
-                this._mesh.isVisible = value;
-            }
-        }
 
-        /** Gets or sets the control position */
-        public get position(): Vector3 {
-            if (this._mesh) {
-                return this._mesh.position;
+            let mesh = this.mesh;
+            if (mesh) {
+                mesh.isVisible = value;
             }
-
-            return Vector3.Zero();
-        }
-
-        public set position(value: Vector3) {
-            if (this._mesh) {
-                this._mesh.position = value;
-            }            
         }
 
         /**
@@ -185,46 +177,57 @@ module BABYLON.GUI {
         /**
          * Gets the mesh used to render this control
          */
+        public get node(): Nullable<TransformNode> {
+            return this._node;
+        }
+
+        /**
+         * Gets the mesh used to render this control
+         */
         public get mesh(): Nullable<Mesh> {
-            return this._mesh;
+            return this._node as Mesh;
         }
 
         /**
-         * Link the control as child of the given mesh
-         * @param mesh defines the mesh to link to. Use null to unlink the control
+         * Link the control as child of the given node
+         * @param node defines the node to link to. Use null to unlink the control
          * @returns the current control
          */
-        public linkToMesh(mesh: Nullable<AbstractMesh>): Control3D {
-            if (this._mesh) {
-                this._mesh.parent = mesh;
+        public linkToTransformNode(node: Nullable<TransformNode>): Control3D {
+            if (this._node) {
+                this._node.parent = node;
             }
             return this;
         }    
 
-        /**
-         * Get the attached mesh used to render the control
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
-         */        
-        public prepareMesh(scene: Scene): Nullable<Mesh> {
-            if (!this._mesh) {
-                this._mesh = this._createMesh(scene);
-                this._mesh!.isPickable = true;
-                this._mesh!.metadata = this; // Store the control on the metadata field in order to get it when picking
-
-                this._affectMaterial(this._mesh!);
-            }
+        /** @hidden **/      
+        public _prepareNode(scene: Scene): void{
+            if (!this._node) {
+                this._node = this._createNode(scene);
 
-            return this._mesh;
+                if (!this.node) {
+                    return;
+                }
+                this._node!.metadata = this; // Store the control on the metadata field in order to get it when picking
+                this._node!.position = this.position;
+                this._node!.scaling = this.scaling;
+
+                let mesh = this.mesh;
+                if (mesh) {
+                    mesh.isPickable = true;
+
+                    this._affectMaterial(mesh);
+                }
+            }
         }
 
         /**
-         * Mesh creation.
+         * Node creation.
          * Can be overriden by children
-         * @param scene defines the scene where the mesh must be attached
-         * @returns the attached mesh or null if none
+         * @param scene defines the scene where the node must be attached
+         * @returns the attached node or null if none
          */
-        protected _createMesh(scene: Scene): Nullable<Mesh> {
+        protected _createNode(scene: Scene): Nullable<TransformNode> {
             // Do nothing by default
             return null;
         }
@@ -366,9 +369,9 @@ module BABYLON.GUI {
             this.onPointerUpObservable.clear();
             this.onPointerClickObservable.clear();
 
-            if (this._mesh) {
-                this._mesh.dispose(false, true);
-                this._mesh = null;
+            if (this._node) {
+                this._node.dispose(false, true);
+                this._node = null;
             }
 
             // Behaviors

+ 17 - 11
gui/src/3D/controls/holographicButton.ts

@@ -5,7 +5,8 @@ module BABYLON.GUI {
      * Class used to create a holographic button in 3D
      */
     export class HolographicButton extends Button3D {
-        private _edgesRenderer: EdgesRenderer;
+        private _frontPlate: Mesh;
+
         /**
          * Creates a new button
          * @param name defines the control name
@@ -19,14 +20,14 @@ module BABYLON.GUI {
                 if (!this.mesh) {
                     return;
                 }
-                this._edgesRenderer.isEnabled = true;
+                this._frontPlate.setEnabled(true);
             }
 
             this.pointerOutAnimation = () => {
                 if (!this.mesh) {
                     return;
                 }
-                this._edgesRenderer.isEnabled = false;
+                this._frontPlate.setEnabled(false);
             }                      
         }
     
@@ -35,14 +36,19 @@ module BABYLON.GUI {
         }        
 
         // Mesh association
-        protected _createMesh(scene: Scene): Mesh {
-            var mesh = super._createMesh(scene);
-
-            mesh.edgesWidth = 0.5;
-            mesh.edgesColor = new Color4(1.0, 1.0, 1.0, 1.0);
-            mesh.enableEdgesRendering();
-            this._edgesRenderer = mesh.edgesRenderer!;
-            this._edgesRenderer.isEnabled = false
+        protected _createNode(scene: Scene): TransformNode {
+            var mesh = <Mesh>super._createNode(scene);
+
+            this._frontPlate= <Mesh>super._createNode(scene);
+            this._frontPlate.parent = mesh;
+            this._frontPlate.position.z = -0.05;
+            this._frontPlate.setEnabled(false);
+            this._frontPlate.isPickable = false;
+            this._frontPlate.visibility = 0.001;
+
+            this._frontPlate.edgesWidth = 1.0;
+            this._frontPlate.edgesColor = new Color4(1.0, 1.0, 1.0, 1.0);
+            this._frontPlate.enableEdgesRendering();
             
             return mesh;
         }

+ 102 - 0
gui/src/3D/controls/stackPanel3D.ts

@@ -0,0 +1,102 @@
+/// <reference path="../../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    /**
+     * Class used to create a stack panel in 3D on XY plane
+     */
+    export class StackPanel3D extends Container3D {
+        private _isVertical = false;
+
+        /**
+         * Gets or sets a boolean indicating if the stack panel is vertical or horizontal (horizontal by default)
+         */
+        public get isVertical(): boolean {
+            return this._isVertical;
+        }
+
+        public set isVertical(value: boolean) {
+            if (this._isVertical === value) {
+                return;
+            }
+
+            this._isVertical = value;
+            this._arrangeChildren();
+        }
+
+        /**
+         * Gets or sets the distance between elements
+         */
+        public margin = 0.1;
+        
+        /**
+         * Creates new StackPanel
+         * @param isVertical 
+         */
+        public constructor() {
+            super();
+        }
+
+        protected _arrangeChildren() {
+            let width = 0;
+            let height = 0;
+            let controlCount = 0;
+            let extendSizes = [];
+
+            let currentInverseWorld = Matrix.Invert(this.node!.computeWorldMatrix(true));
+
+            // Measure
+            for (var child of this._children) {
+                if (!child.mesh) {
+                    continue;
+                }
+
+                controlCount++;
+                child.mesh.computeWorldMatrix(true);
+                let boundingBox = child.mesh.getBoundingInfo().boundingBox;
+                let extendSize = Vector3.TransformNormal(boundingBox.extendSizeWorld, currentInverseWorld);
+                extendSizes.push(extendSize);
+
+                if (this._isVertical) {
+                    height += extendSize.y;
+                } else {
+                    width += extendSize.x;
+                }
+            }
+
+            if (this._isVertical) {
+                height += (controlCount - 1) * this.margin / 2;
+            } else {
+                width += (controlCount - 1) * this.margin / 2;
+            }
+
+            // Arrange
+            let offset: number;
+            if (this._isVertical) {
+                offset = -height;
+            } else {
+                offset = -width;
+            }
+
+            let index = 0;
+            for (var child of this._children) {
+                if (!child.mesh) {
+                    continue;
+                }                
+                controlCount--;
+                let extendSize = extendSizes[index++];
+
+                if (this._isVertical) {
+                    child.position.y = offset + extendSize.y;
+                    child.position.x = 0;
+                    offset += extendSize.y * 2;
+                } else {
+                    child.position.x = offset + extendSize.x;
+                    child.position.y = 0;
+                    offset += extendSize.x * 2;
+                }
+
+                offset += (controlCount > 0 ? this.margin : 0)
+            }
+        }
+    }
+}