Browse Source

gui: lines, ellipse linkToMesh, connectToControl

David Catuhe 8 years ago
parent
commit
df416ddbc6

+ 3 - 0
Tools/Gulp/config.json

@@ -1249,7 +1249,10 @@
                     "../../gui/src/valueAndUnit.ts",
                     "../../gui/src/controls/control.ts",
                     "../../gui/src/controls/container.ts",
+                    "../../gui/src/controls/stackPanel.ts",
                     "../../gui/src/controls/rectangle.ts",
+                    "../../gui/src/controls/ellipse.ts",
+                    "../../gui/src/controls/line.ts",
                     "../../gui/src/controls/textBlock.ts",
                     "../../gui/src/controls/image.ts",
                     "../../gui/src/controls/button.ts"

File diff suppressed because it is too large
+ 2569 - 2569
dist/preview release/babylon.d.ts


File diff suppressed because it is too large
+ 2569 - 2569
dist/preview release/babylon.module.d.ts


File diff suppressed because it is too large
+ 11 - 11
dist/preview release/canvas2D/babylon.canvas2d.min.js


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


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


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


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTF1FileLoader.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.glTF2FileLoader.min.js


File diff suppressed because it is too large
+ 2 - 2
dist/preview release/loaders/babylon.glTFFileLoader.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/loaders/babylon.objFileLoader.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.customMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/materialsLibrary/babylon.waterMaterial.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.asciiArtPostProcess.min.js


File diff suppressed because it is too large
+ 1 - 1
dist/preview release/postProcessesLibrary/babylon.digitalRainPostProcess.min.js


+ 0 - 4
gui/readme.md

@@ -14,7 +14,3 @@ The Babylon.js GUI library is an extension you can use to generate interactive u
 
 ==> ideas
 * lines (with cap)
-* ellipse
-* button
-* interactions
-* rotate / scale

+ 25 - 6
gui/src/advancedDynamicTexture.ts

@@ -3,15 +3,17 @@
 module BABYLON.GUI {
     export class AdvancedDynamicTexture extends DynamicTexture {
         private _isDirty = false;
-        private _renderObserver: Observer<Scene>;
+        private _renderObserver: Observer<Camera>;
         private _resizeObserver: Observer<Engine>;
         private _pointerMoveObserver: Observer<PointerInfoPre>;
         private _background: string;
-        private _rootContainer = new Container("root");
+        public _rootContainer = new Container("root");
         public _lastControlOver: Control;
         public _lastControlDown: Control;
         public _shouldBlockPointer: boolean;
         public _toDispose: IDisposable;
+        public _linkedControls = new Array<Control>();
+        private _isFullscreen = false;
 
         public get background(): string {
             return this._background;
@@ -29,7 +31,7 @@ module BABYLON.GUI {
         constructor(name: string, width = 0, height = 0, scene: Scene, generateMipMaps = false, samplingMode = Texture.NEAREST_SAMPLINGMODE) {
             super(name, {width: width, height: height}, scene, generateMipMaps, samplingMode, Engine.TEXTUREFORMAT_RGBA);
 
-            this._renderObserver = this.getScene().onBeforeRenderObservable.add(() => this._checkUpdate());
+            this._renderObserver = this.getScene().onBeforeCameraRenderObservable.add((camera: Camera) => this._checkUpdate(camera));
 
             this._rootContainer._link(null, this);
 
@@ -57,7 +59,7 @@ module BABYLON.GUI {
         }
 
         public dispose() {
-            this.getScene().onBeforeRenderObservable.remove(this._renderObserver);
+            this.getScene().onBeforeCameraRenderObservable.remove(this._renderObserver);
 
             if (this._resizeObserver) {
                 this.getScene().getEngine().onResizeObservable.remove(this._resizeObserver);
@@ -88,7 +90,23 @@ module BABYLON.GUI {
             }
         }
 
-        private _checkUpdate(): void {
+        private _checkUpdate(camera: Camera): void {
+            if (this._isFullscreen && this._linkedControls.length) {
+                var scene = this.getScene();
+                var engine = scene.getEngine();
+                var viewport = camera.viewport;
+                var globalViewport = viewport.toGlobal(engine.getRenderWidth(), engine.getRenderHeight());
+
+                for (var control of this._linkedControls) {
+                    var mesh = control._linkedMesh;
+                    
+                    var position = mesh.getBoundingInfo().boundingSphere.center;
+                    var projectedPosition = Vector3.Project(position, mesh.getWorldMatrix(), scene.getTransformMatrix(), globalViewport);
+
+                    control._moveToProjectedPosition(projectedPosition);
+                }
+            }
+
             if (!this._isDirty && !this._rootContainer.isDirty) {
                 return;
             }
@@ -143,7 +161,7 @@ module BABYLON.GUI {
                 this._shouldBlockPointer = false;
                 this._doPicking(scene.pointerX, scene.pointerY, pi.type);
 
-                pi.skipOnPointerObservable = this._shouldBlockPointer;
+                pi.skipOnPointerObservable = this._shouldBlockPointer && pi.type !== BABYLON.PointerEventTypes.POINTERUP;
             });
         }
 
@@ -169,6 +187,7 @@ module BABYLON.GUI {
             layer.texture = result;
 
             result._toDispose = layer;
+            result._isFullscreen = true;
 
             // Attach
             result.attach();

+ 14 - 2
gui/src/controls/container.ts

@@ -2,14 +2,18 @@
 
 module BABYLON.GUI {
     export class Container extends Control {
-        private _children = new Array<Control>();
+        protected _children = new Array<Control>();
         protected _measureForChildren = Measure.Empty();     
 
         constructor(public name: string) {
             super(name);
         }
 
-       public addControl(control: Control): Container {
+        public containsControl(control: Control): boolean {
+            return this._children.indexOf(control) !== -1;
+        }
+
+        public addControl(control: Control): Container {
            var index = this._children.indexOf(control);
 
             if (index !== -1) {
@@ -49,6 +53,14 @@ module BABYLON.GUI {
             this._markAsDirty();
         }
 
+        public _markMatrixAsDirty(): void {
+            super._markMatrixAsDirty();
+
+            for (var index = 0; index < this._children.length; index++) {
+                this._children[index]._markMatrixAsDirty();
+            }
+        }
+
         protected _localDraw(context: CanvasRenderingContext2D): void {
             // Implemented by child to be injected inside main draw
         }

+ 93 - 26
gui/src/controls/control.ts

@@ -1,7 +1,8 @@
 /// <reference path="../../../dist/preview release/babylon.d.ts"/>
 
 module BABYLON.GUI {
-    export class Control {        
+    export class Control {       
+        private _alpha = 1; 
         private _zIndex = 0;
         public _root: Container;
         public _host: AdvancedDynamicTexture;
@@ -14,8 +15,8 @@ module BABYLON.GUI {
         private _lastMeasuredFont: string;
         protected _fontOffset: {ascent: number, height: number, descent: number};
         private _color: string;
-        private _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
-        private _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
+        protected _horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
+        protected _verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
         private _isDirty = true;
         private _cachedParentMeasure = Measure.Empty();
         private _marginLeft = new ValueAndUnit(0);
@@ -31,12 +32,17 @@ module BABYLON.GUI {
         private _transformCenterY = 0.5;
         private _transformMatrix = Matrix2D.Identity();
         private _invertTransformMatrix = Matrix2D.Identity();
+        private _transformedPosition = Vector2.Zero();
         private _isMatrixDirty = true;
         private _cachedOffsetX: number;
         private _cachedOffsetY: number;
+        public _linkedMesh: AbstractMesh;
 
         public isHitTestVisible = true;
         public isPointerBlocker = false;
+
+        public linkOffsetX = 0;
+        public linkOffsetY = 0;
         
         // Properties
 
@@ -68,7 +74,26 @@ module BABYLON.GUI {
         * An event triggered when pointer enters the control
         * @type {BABYLON.Observable}
         */
-        public onPointerEnterObservable = new Observable<Control>();           
+        public onPointerEnterObservable = new Observable<Control>();    
+
+        /**
+        * An event triggered when the control is marked as dirty
+        * @type {BABYLON.Observable}
+        */
+        public onDirtyObservable = new Observable<Control>();           
+
+        public get alpha(): number {
+            return this._alpha;
+        }
+
+        public set alpha(value: number) {
+            if (this._alpha === value) {
+                return;
+            }
+
+            this._alpha = value;
+            this._markAsDirty();
+        }                 
 
         public get scaleX(): number {
             return this._scaleX;
@@ -81,7 +106,7 @@ module BABYLON.GUI {
 
             this._scaleX = value;
             this._markAsDirty();
-            this._isMatrixDirty = true;
+            this._markMatrixAsDirty();
         }     
 
         public get scaleY(): number {
@@ -95,7 +120,7 @@ module BABYLON.GUI {
 
             this._scaleY = value;
             this._markAsDirty();
-            this._isMatrixDirty = true;
+            this._markMatrixAsDirty();
         }  
 
         public get rotation(): number {
@@ -109,7 +134,7 @@ module BABYLON.GUI {
 
             this._rotation = value;
             this._markAsDirty();
-            this._isMatrixDirty = true;
+            this._markMatrixAsDirty();
         }    
 
         public get transformCenterY(): number {
@@ -123,7 +148,7 @@ module BABYLON.GUI {
 
             this._transformCenterY = value;
             this._markAsDirty();
-            this._isMatrixDirty = true;
+            this._markMatrixAsDirty();
         }     
 
         public get transformCenterX(): number {
@@ -137,7 +162,7 @@ module BABYLON.GUI {
 
             this._transformCenterX = value;
             this._markAsDirty();
-            this._isMatrixDirty = true;
+            this._markMatrixAsDirty();
         }    
 
         public get horizontalAlignment(): number {
@@ -243,7 +268,10 @@ module BABYLON.GUI {
             }
 
             this._zIndex = value;
-            this._root._reOrderControl(this);
+
+            if (this._root) {
+                this._root._reOrderControl(this);
+            }
         }
 
         public get isDirty(): boolean {
@@ -308,6 +336,14 @@ module BABYLON.GUI {
             if (this._top.fromString(value)) {
                 this._markAsDirty();
             }
+        }     
+
+        public get centerX(): number {
+            return this._currentMeasure.left + this._currentMeasure.width / 2;
+        }       
+
+        public get centerY(): number {
+            return this._currentMeasure.top + this._currentMeasure.height / 2;
         }                   
 
         // Functions
@@ -315,6 +351,32 @@ module BABYLON.GUI {
             this.fontFamily = "Arial";
         }
 
+        public linkWithMesh(mesh: AbstractMesh): void {
+            if (!this._host || this._root !== this._host._rootContainer) {
+                Tools.Error("Cannot link a control to a mesh if the control is not at root level");
+                return;
+            }
+
+            if (this._host._linkedControls.indexOf(this) !== -1) {
+                return;
+            }
+
+
+            this.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+            this._linkedMesh = mesh;
+            this._host._linkedControls.push(this);
+        }
+
+        public _moveToProjectedPosition(projectedPosition: Vector3): void {
+            this.left = ((projectedPosition.x + this.linkOffsetX) - this._currentMeasure.width / 2) + "px";
+            this.top = ((projectedPosition.y + this.linkOffsetY) - this._currentMeasure.height / 2) + "px";
+        }
+
+        public _markMatrixAsDirty(): void {
+            this._isMatrixDirty = true;
+        }
+
         protected _markAsDirty(): void {            
             this._isDirty = true;
 
@@ -330,7 +392,7 @@ module BABYLON.GUI {
         }
 
         protected _transform(context: CanvasRenderingContext2D): void {
-            if (this._scaleX === 1 && this._scaleY ===1 && this._rotation === 0) {
+            if (!this._isMatrixDirty && this._scaleX === 1 && this._scaleY ===1 && this._rotation === 0) {
                 return;
             }
 
@@ -348,14 +410,13 @@ module BABYLON.GUI {
             // postTranslate
             context.translate(-offsetX, -offsetY);    
 
-
             // Need to update matrices?
             if (this._isMatrixDirty || this._cachedOffsetX !== offsetX || this._cachedOffsetY !== offsetY) {
                 this._cachedOffsetX = offsetX;
                 this._cachedOffsetY = offsetY;
                 this._isMatrixDirty = false;
 
-                Matrix2D.ComposeToRef(offsetX, offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
+                Matrix2D.ComposeToRef(-offsetX, -offsetY, this._rotation, this._scaleX, this._scaleY, this._root ? this._root._transformMatrix : null, this._transformMatrix);
 
                 this._transformMatrix.invertToRef(this._invertTransformMatrix);
             }
@@ -369,13 +430,16 @@ module BABYLON.GUI {
             if (this._color) {
                 context.fillStyle = this._color;
             }
+
+            context.globalAlpha = this._alpha;
         }
 
         protected _processMeasures(parentMeasure: Measure, context: CanvasRenderingContext2D) {     
             if (this._isDirty || !this._cachedParentMeasure.isEqualsTo(parentMeasure)) {
+                this._isDirty = false;
                 this._currentMeasure.copyFrom(parentMeasure);
 
-                this._measure(parentMeasure, context);
+                this._measure();
                 this._computeAlignment(parentMeasure, context);
 
                 // Convert to int values
@@ -387,8 +451,11 @@ module BABYLON.GUI {
                 // Let children add more features
                 this._additionalProcessing(parentMeasure, context);
 
-                this._isDirty = false;
                 this._cachedParentMeasure.copyFrom(parentMeasure);
+
+                if (this.onDirtyObservable.hasObservers()) {
+                    this.onDirtyObservable.notifyObservers(this);
+                }                
             }     
 
             // Transform
@@ -404,7 +471,7 @@ module BABYLON.GUI {
             context.rect(this._currentMeasure.left ,this._currentMeasure.top, this._currentMeasure.width, this._currentMeasure.height);
         }
 
-        protected _measure(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+        public _measure(): void {  
             // Width / Height
             if (this._width.isPixel) {
                 this._currentMeasure.width = this._width.value;
@@ -508,9 +575,10 @@ module BABYLON.GUI {
 
         public contains(x: number, y: number) : boolean {
             // Invert transform
-            if (this._scaleX !== 1 || this._scaleY !== 1 || this.rotation !== 0) {
-               
-            }
+            this._invertTransformMatrix.transformCoordinates(x, y, this._transformedPosition);
+
+            x = this._transformedPosition.x;
+            y = this._transformedPosition.y;
 
             // Check
             if (x < this._currentMeasure.left) {
@@ -536,6 +604,10 @@ module BABYLON.GUI {
         }
 
         public _processPicking(x: number, y: number, type: number): boolean {
+            if (!this.isHitTestVisible) {
+                return false;
+            }
+
             if (!this.contains(x, y)) {
                 return false;
             }
@@ -576,10 +648,6 @@ module BABYLON.GUI {
         }
 
         protected _processObservables(type: number): boolean {
-            if (!this.isHitTestVisible) {
-                return false;
-            }
-
             if (type === BABYLON.PointerEventTypes.POINTERMOVE) {
                 this._onPointerMove();
 
@@ -603,11 +671,10 @@ module BABYLON.GUI {
             }
 
             if (type === BABYLON.PointerEventTypes.POINTERUP) {
-                this._onPointerUp();
-                if (this._host._lastControlDown !== this) {
+                if (this._host._lastControlDown) {
                     this._host._lastControlDown._onPointerUp();
-                    this._host._lastControlDown = null;
                 }
+                this._host._lastControlDown = null;
                 return true;
             }
         

+ 79 - 0
gui/src/controls/ellipse.ts

@@ -0,0 +1,79 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class Ellipse extends Container {
+        private _thickness = 1;
+        private _background: string;          
+        
+        public get thickness(): number {
+            return this._thickness;
+        }
+
+        public set thickness(value: number) {
+            if (this._thickness === value) {
+                return;
+            }
+
+            this._thickness = value;
+            this._markAsDirty();
+        }   
+       
+        public get background(): string {
+            return this._background;
+        }
+
+        public set background(value: string) {
+            if (this._background === value) {
+                return;
+            }
+
+            this._background = value;
+            this._markAsDirty();
+        }           
+     
+        constructor(public name: string) {
+            super(name);
+        }
+
+        protected _localDraw(context: CanvasRenderingContext2D): void {
+            context.save();
+
+            context.beginPath();
+            context.ellipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, 
+                            this._currentMeasure.width / 2 - this._thickness / 2, this._currentMeasure.height / 2 - this._thickness / 2, 0, 0, 2 * Math.PI);
+            context.closePath();
+
+            if (this._background) {
+                context.fillStyle = this._background;
+
+                context.fill();
+            }
+
+            if (this._thickness) {
+                if (this.color) {
+                    context.strokeStyle = this.color;
+                }
+                context.lineWidth = this._thickness;
+
+                context.stroke();
+            }
+        
+            context.restore();
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {  
+            super._additionalProcessing(parentMeasure, context);
+
+            this._measureForChildren.width -= 2 * this._thickness;
+            this._measureForChildren.height -= 2 * this._thickness;
+            this._measureForChildren.left += this._thickness;
+            this._measureForChildren.top += this._thickness;            
+        }
+
+       protected _clipForChildren(context: CanvasRenderingContext2D) {
+            context.beginPath();
+            context.ellipse(this._currentMeasure.left + this._currentMeasure.width / 2, this._currentMeasure.top + this._currentMeasure.height / 2, this._currentMeasure.width / 2, this._currentMeasure.height / 2, 0, 0, 2 * Math.PI);
+            context.clip();
+        }
+    }    
+}

+ 174 - 0
gui/src/controls/line.ts

@@ -0,0 +1,174 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+var DOMImage = Image;
+
+module BABYLON.GUI {
+    export class Line extends Control {
+        private _lineWidth = 1;
+        private _background: string;
+        private _x1 = 0;
+        private _y1 = 0;
+        private _x2 = 0;
+        private _y2 = 0;
+        private _dash = new Array<number>();
+        private _connectedControl: Control;
+        private _connectedControlDirtyObserver: Observer<Control>;
+
+        public get dash(): Array<number> {
+            return this._dash;
+        }
+
+        public set dash(value: Array<number>) {
+            if (this._dash === value) {
+                return;
+            }
+
+            this._dash = value;
+            this._markAsDirty();
+        }     
+
+        public get connectedControl(): Control {
+            return this._connectedControl;
+        }
+
+        public set connectedControl(value: Control) {
+            if (this._connectedControl === value) {
+                return;
+            }
+
+            if (this._connectedControlDirtyObserver && this._connectedControl) {
+                this._connectedControl.onDirtyObservable.remove(this._connectedControlDirtyObserver);
+                this._connectedControlDirtyObserver = null;
+            }
+
+            if (value) {
+                this._connectedControlDirtyObserver = value.onDirtyObservable.add(() => this._markAsDirty());
+            }
+
+            this._connectedControl = value;
+            this._markAsDirty();
+        }              
+
+        public get x1(): number {
+            return this._x1;
+        }
+
+        public set x1(value: number) {
+            if (this._x1 === value) {
+                return;
+            }
+
+            this._x1 = value;
+            this._markAsDirty();
+        }    
+
+        public get y1(): number {
+            return this._y1;
+        }
+
+        public set y1(value: number) {
+            if (this._y1 === value) {
+                return;
+            }
+
+            this._y1 = value;
+            this._markAsDirty();
+        }     
+
+        public get x2(): number {
+            if (this._connectedControl) {
+                return this._connectedControl.centerX;
+            }
+            return this._x2;
+        }
+
+        public set x2(value: number) {
+            if (this._x2 === value) {
+                return;
+            }
+
+            this._x2 = value;
+            this._markAsDirty();
+        }    
+
+        public get y2(): number {
+            if (this._connectedControl) {
+                return this._connectedControl.centerY;
+            }
+            return this._y2;
+        }
+
+        public set y2(value: number) {
+            if (this._y2 === value) {
+                return;
+            }
+
+            this._y2 = value;
+            this._markAsDirty();
+        }                       
+        
+        public get lineWidth(): number {
+            return this._lineWidth;
+        }
+
+        public set lineWidth(value: number) {
+            if (this._lineWidth === value) {
+                return;
+            }
+
+            this._lineWidth = value;
+            this._markAsDirty();
+        }   
+
+        public set horizontalAlignment(value: number) {
+            return;
+        } 
+
+        public set verticalAlignment(value: number) {
+            return;
+        }         
+
+        constructor(public name: string) {
+            super(name);
+
+            this.isHitTestVisible = false;
+            this._horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
+            this._verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;            
+        }
+
+        public _draw(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            context.save();
+
+            this._applyStates(context);
+            super._processMeasures(parentMeasure, context);
+
+            context.strokeStyle = this.color;
+            context.lineWidth = this._lineWidth;
+            context.setLineDash(this._dash);
+
+            context.beginPath();
+            context.moveTo(this._x1, this._y1);
+            context.lineTo(this.x2, this.y2);
+
+            context.stroke();
+
+            context.restore();
+        }
+
+        public _measure(): void {  
+            // Width / Height
+            this._currentMeasure.width = Math.abs(this._x1 - this.x2);
+            this._currentMeasure.height = Math.abs(this._y1 - this.y2);
+        }
+
+        protected _computeAlignment(parentMeasure: Measure, context: CanvasRenderingContext2D): void {          
+            this._currentMeasure.left = Math.min(this._x1, this.x2);
+            this._currentMeasure.top = Math.min(this._y1, this.y2);            
+        }   
+
+        public _moveToProjectedPosition(projectedPosition: Vector3): void {
+            this.x1 = projectedPosition.x + this.linkOffsetX;
+            this.y1 = projectedPosition.y + this.linkOffsetY;
+        }
+    }    
+}

+ 24 - 0
gui/src/controls/stackPanel.ts

@@ -0,0 +1,24 @@
+/// <reference path="../../../dist/preview release/babylon.d.ts"/>
+
+module BABYLON.GUI {
+    export class StackPanel extends Container {
+    
+        constructor(public name: string) {
+            super(name);
+        }
+
+        protected _additionalProcessing(parentMeasure: Measure, context: CanvasRenderingContext2D): void {
+            var top = 0;
+            for (var child of this._children) {
+                child._measure();
+                child.top = top + "px";
+                top += child._currentMeasure.height;
+                child.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;
+            }
+
+            this.height = top + "px";
+
+            super._additionalProcessing(parentMeasure, context);
+        }    
+    }    
+}

+ 4 - 5
gui/src/math2D.ts

@@ -57,9 +57,9 @@ module BABYLON.GUI {
             return this;
         }
 
-        public transformCoordinates(x: number, y: number, rx: number, ry: number): Matrix2D {
-            rx = x * this.m[0] + y * this.m[2] + this.m[4];
-            ry = x * this.m[1] + y * this.m[3] + this.m[5];
+        public transformCoordinates(x: number, y: number, result: Vector2): Matrix2D {
+            result.x = x * this.m[0] + y * this.m[2] + this.m[4];
+            result.y = x * this.m[1] + y * this.m[3] + this.m[5];
 
             return this;
         }
@@ -84,7 +84,6 @@ module BABYLON.GUI {
             result.fromValues(c, s, -s, c,  0, 0);
         }
 
-
         private static _TempPreTranslationMatrix = Matrix2D.Identity();
         private static _TempPostTranslationMatrix = Matrix2D.Identity();
         private static _TempRotationMatrix = Matrix2D.Identity();
@@ -106,7 +105,7 @@ module BABYLON.GUI {
             Matrix2D._TempCompose0.multiplyToRef(Matrix2D._TempRotationMatrix, Matrix2D._TempCompose1);
             if (parentMatrix) {
                 Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, Matrix2D._TempCompose2);
-                parentMatrix.multiplyToRef(Matrix2D._TempCompose2, result);
+                Matrix2D._TempCompose2.multiplyToRef(parentMatrix, result);
             } else {
                 Matrix2D._TempCompose1.multiplyToRef(Matrix2D._TempPostTranslationMatrix, result);
             }