Jelajahi Sumber

fix bug on inputmanager for detaching elements, improve VRDeviceOrientation input

gleborgne 10 tahun lalu
induk
melakukan
f7ea4c5b2b
36 mengubah file dengan 1873 tambahan dan 1515 penghapusan
  1. 762 669
      dist/preview release/babylon.d.ts
  2. 32 28
      dist/preview release/babylon.js
  3. 420 257
      dist/preview release/babylon.max.js
  4. 4 5
      src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js
  5. 3 7
      src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.ts
  6. 4 5
      src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js
  7. 4 5
      src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.ts
  8. 6 8
      src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js
  9. 7 11
      src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.ts
  10. 127 131
      src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js
  11. 144 151
      src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.ts
  12. 2 3
      src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js
  13. 2 4
      src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.ts
  14. 4 5
      src/Cameras/Inputs/babylon.freecamera.input.gamepad.js
  15. 2 6
      src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts
  16. 4 5
      src/Cameras/Inputs/babylon.freecamera.input.keyboard.js
  17. 4 6
      src/Cameras/Inputs/babylon.freecamera.input.keyboard.ts
  18. 7 18
      src/Cameras/Inputs/babylon.freecamera.input.mouse.js
  19. 8 23
      src/Cameras/Inputs/babylon.freecamera.input.mouse.ts
  20. 2 18
      src/Cameras/Inputs/babylon.freecamera.input.touch.js
  21. 2 24
      src/Cameras/Inputs/babylon.freecamera.input.touch.ts
  22. 16 14
      src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js
  23. 17 16
      src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.ts
  24. 22 12
      src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.js
  25. 31 21
      src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.ts
  26. 0 6
      src/Cameras/babylon.arcRotateCameraInputsManager.js
  27. 0 7
      src/Cameras/babylon.arcRotateCameraInputsManager.ts
  28. 11 10
      src/Cameras/babylon.cameraInputsManager.js
  29. 17 17
      src/Cameras/babylon.cameraInputsManager.ts
  30. 0 6
      src/Cameras/babylon.freeCameraInputsManager.js
  31. 1 8
      src/Cameras/babylon.freeCameraInputsManager.ts
  32. 39 0
      src/Physics/Plugins/babylon.cannonJSPlugin.js
  33. 30 0
      src/Physics/Plugins/babylon.oimoJSPlugin.js
  34. 18 0
      src/Physics/babylon.physicsEngine.js
  35. 19 8
      src/Physics/babylon.physicsImpostor.js
  36. 102 1
      src/Physics/babylon.physicsJoint.js

File diff ditekan karena terlalu besar
+ 762 - 669
dist/preview release/babylon.d.ts


File diff ditekan karena terlalu besar
+ 32 - 28
dist/preview release/babylon.js


File diff ditekan karena terlalu besar
+ 420 - 257
dist/preview release/babylon.max.js


+ 4 - 5
src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.js

@@ -8,15 +8,14 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var ArcRotateCameraGamepadInput = (function () {
     var ArcRotateCameraGamepadInput = (function () {
         function ArcRotateCameraGamepadInput() {
         function ArcRotateCameraGamepadInput() {
-            var _this = this;
             this.gamepadRotationSensibility = 80;
             this.gamepadRotationSensibility = 80;
             this.gamepadMoveSensibility = 40;
             this.gamepadMoveSensibility = 40;
-            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         }
         }
-        ArcRotateCameraGamepadInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        ArcRotateCameraGamepadInput.prototype.attachControl = function (element, noPreventDefault) {
+            var _this = this;
+            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         };
         };
-        ArcRotateCameraGamepadInput.prototype.detach = function () {
+        ArcRotateCameraGamepadInput.prototype.detachControl = function (element) {
             this._gamepads.dispose();
             this._gamepads.dispose();
         };
         };
         ArcRotateCameraGamepadInput.prototype.checkInputs = function () {
         ArcRotateCameraGamepadInput.prototype.checkInputs = function () {

+ 3 - 7
src/Cameras/Inputs/babylon.arcrotatecamera.input.gamepad.ts

@@ -11,15 +11,11 @@ module BABYLON {
         @serialize()
         @serialize()
         public gamepadMoveSensibility = 40;
         public gamepadMoveSensibility = 40;
 
 
-        constructor() {
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
         }
         }
-
-        attachCamera(camera: ArcRotateCamera) {
-            this.camera = camera;
-        }
-
-        detach() {
+        
+        detachControl(element : HTMLElement) {
             this._gamepads.dispose();
             this._gamepads.dispose();
         }
         }
 
 

+ 4 - 5
src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.js

@@ -14,9 +14,8 @@ var BABYLON;
             this.keysLeft = [37];
             this.keysLeft = [37];
             this.keysRight = [39];
             this.keysRight = [39];
         }
         }
-        ArcRotateCameraKeyboardMoveInput.prototype.attachCamera = function (camera) {
+        ArcRotateCameraKeyboardMoveInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
-            this.camera = camera;
             this._onKeyDown = function (evt) {
             this._onKeyDown = function (evt) {
                 if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
                 if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
                     _this.keysDown.indexOf(evt.keyCode) !== -1 ||
                     _this.keysDown.indexOf(evt.keyCode) !== -1 ||
@@ -27,7 +26,7 @@ var BABYLON;
                         _this._keys.push(evt.keyCode);
                         _this._keys.push(evt.keyCode);
                     }
                     }
                     if (evt.preventDefault) {
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -43,7 +42,7 @@ var BABYLON;
                         _this._keys.splice(index, 1);
                         _this._keys.splice(index, 1);
                     }
                     }
                     if (evt.preventDefault) {
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -58,7 +57,7 @@ var BABYLON;
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
             ]);
             ]);
         };
         };
-        ArcRotateCameraKeyboardMoveInput.prototype.detach = function () {
+        ArcRotateCameraKeyboardMoveInput.prototype.detachControl = function (element) {
             BABYLON.Tools.UnregisterTopRootEvents([
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },

+ 4 - 5
src/Cameras/Inputs/babylon.arcrotatecamera.input.keyboard.ts

@@ -18,8 +18,7 @@ module BABYLON {
         @serialize()
         @serialize()
         public keysRight = [39];
         public keysRight = [39];
 
 
-        public attachCamera(camera: ArcRotateCamera) {
-            this.camera = camera;
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean) {
 
 
             this._onKeyDown = evt => {
             this._onKeyDown = evt => {
                 if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
                 if (this.keysUp.indexOf(evt.keyCode) !== -1 ||
@@ -33,7 +32,7 @@ module BABYLON {
                     }
                     }
 
 
                     if (evt.preventDefault) {
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -52,7 +51,7 @@ module BABYLON {
                     }
                     }
 
 
                     if (evt.preventDefault) {
                     if (evt.preventDefault) {
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -70,7 +69,7 @@ module BABYLON {
             ]);
             ]);
         }
         }
 
 
-        public detach() {
+        public detachControl(element: HTMLElement) {
             Tools.UnregisterTopRootEvents([
             Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },

+ 6 - 8
src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.js

@@ -10,12 +10,8 @@ var BABYLON;
         function ArcRotateCameraMouseWheelInput() {
         function ArcRotateCameraMouseWheelInput() {
             this.wheelPrecision = 3.0;
             this.wheelPrecision = 3.0;
         }
         }
-        ArcRotateCameraMouseWheelInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        ArcRotateCameraMouseWheelInput.prototype.attachElement = function (element) {
+        ArcRotateCameraMouseWheelInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
-            this.attachedElement = element;
             this._wheel = function (event) {
             this._wheel = function (event) {
                 var delta = 0;
                 var delta = 0;
                 if (event.wheelDelta) {
                 if (event.wheelDelta) {
@@ -35,9 +31,11 @@ var BABYLON;
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('mousewheel', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
         };
         };
-        ArcRotateCameraMouseWheelInput.prototype.detach = function () {
-            this.attachedElement.removeEventListener('mousewheel', this._wheel);
-            this.attachedElement.removeEventListener('DOMMouseScroll', this._wheel);
+        ArcRotateCameraMouseWheelInput.prototype.detachControl = function (element) {
+            if (this._wheel && element) {
+                element.removeEventListener('mousewheel', this._wheel);
+                element.removeEventListener('DOMMouseScroll', this._wheel);
+            }
         };
         };
         ArcRotateCameraMouseWheelInput.prototype.getTypeName = function () {
         ArcRotateCameraMouseWheelInput.prototype.getTypeName = function () {
             return "ArcRotateCameraMouseWheelInput";
             return "ArcRotateCameraMouseWheelInput";

+ 7 - 11
src/Cameras/Inputs/babylon.arcrotatecamera.input.mousewheel.ts

@@ -1,19 +1,13 @@
 module BABYLON {
 module BABYLON {
     export class ArcRotateCameraMouseWheelInput implements ICameraInput<ArcRotateCamera> {
     export class ArcRotateCameraMouseWheelInput implements ICameraInput<ArcRotateCamera> {
         camera: ArcRotateCamera;
         camera: ArcRotateCamera;
-        attachedElement: HTMLElement;
-
+        
         private _wheel: (e: MouseWheelEvent) => void;
         private _wheel: (e: MouseWheelEvent) => void;
 
 
         @serialize()
         @serialize()
         public wheelPrecision = 3.0;
         public wheelPrecision = 3.0;
 
 
-        public attachCamera(camera: ArcRotateCamera) {
-            this.camera = camera;
-        }
-
-        public attachElement(element: HTMLElement) {
-            this.attachedElement = element;
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean) {
             this._wheel = event => {
             this._wheel = event => {
                 var delta = 0;
                 var delta = 0;
                 if (event.wheelDelta) {
                 if (event.wheelDelta) {
@@ -35,9 +29,11 @@ module BABYLON {
             element.addEventListener('DOMMouseScroll', this._wheel, false);
             element.addEventListener('DOMMouseScroll', this._wheel, false);
         }
         }
 
 
-        public detach() {
-            this.attachedElement.removeEventListener('mousewheel', this._wheel);
-            this.attachedElement.removeEventListener('DOMMouseScroll', this._wheel);
+        public detachControl(element: HTMLElement) {
+            if (this._wheel && element){
+                element.removeEventListener('mousewheel', this._wheel);
+                element.removeEventListener('DOMMouseScroll', this._wheel);
+            }
         }
         }
 
 
         getTypeName(): string {
         getTypeName(): string {

+ 127 - 131
src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.js

@@ -17,153 +17,149 @@ var BABYLON;
             this.pinchPrecision = 6.0;
             this.pinchPrecision = 6.0;
             this.panningSensibility = 50.0;
             this.panningSensibility = 50.0;
         }
         }
-        ArcRotateCameraPointersInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        ArcRotateCameraPointersInput.prototype.attachElement = function (element, noPreventDefault) {
+        ArcRotateCameraPointersInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
-            this.attachedElement = element;
             var engine = this.camera.getEngine();
             var engine = this.camera.getEngine();
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var pointers = new BABYLON.SmartCollection();
             var pointers = new BABYLON.SmartCollection();
             var previousPinchDistance = 0;
             var previousPinchDistance = 0;
-            if (this._onPointerDown === undefined) {
-                if (!this.camera._useCtrlForPanning) {
-                    element.addEventListener("contextmenu", this._onContextMenu, false);
+            if (!this.camera._useCtrlForPanning) {
+                element.addEventListener("contextmenu", this._onContextMenu, false);
+            }
+            this._onLostFocus = function () {
+                //this._keys = [];
+                pointers.empty();
+                previousPinchDistance = 0;
+                cacheSoloPointer = null;
+            };
+            this._onKeyDown = function (evt) {
+                _this._isCtrlPushed = evt.ctrlKey;
+            };
+            this._onKeyUp = function (evt) {
+                _this._isCtrlPushed = evt.ctrlKey;
+            };
+            this._onPointerDown = function (evt) {
+                // Manage panning with right click
+                _this._isRightClick = evt.button === 2;
+                // manage pointers
+                pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
+                cacheSoloPointer = pointers.item(evt.pointerId);
+                if (!noPreventDefault) {
+                    evt.preventDefault();
                 }
                 }
-                this._onLostFocus = function () {
-                    //this._keys = [];
-                    pointers.empty();
-                    previousPinchDistance = 0;
-                    cacheSoloPointer = null;
-                };
-                this._onKeyDown = function (evt) {
-                    _this._isCtrlPushed = evt.ctrlKey;
-                };
-                this._onKeyUp = function (evt) {
-                    _this._isCtrlPushed = evt.ctrlKey;
-                };
-                this._onPointerDown = function (evt) {
-                    // Manage panning with right click
-                    _this._isRightClick = evt.button === 2;
-                    // manage pointers
-                    pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
-                    cacheSoloPointer = pointers.item(evt.pointerId);
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onPointerUp = function (evt) {
-                    cacheSoloPointer = null;
-                    previousPinchDistance = 0;
-                    //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
-                    //but emptying completly pointers collection is required to fix a bug on iPhone : 
-                    //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
-                    //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
-                    pointers.empty();
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onContextMenu = function (evt) {
+            };
+            this._onPointerUp = function (evt) {
+                cacheSoloPointer = null;
+                previousPinchDistance = 0;
+                //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
+                //but emptying completly pointers collection is required to fix a bug on iPhone : 
+                //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
+                //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
+                pointers.empty();
+                if (!noPreventDefault) {
                     evt.preventDefault();
                     evt.preventDefault();
-                };
-                this._onPointerMove = function (evt) {
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                    switch (pointers.count) {
-                        case 1:
-                            if (_this.panningSensibility !== 0 && ((_this._isCtrlPushed && _this.camera._useCtrlForPanning) || (!_this.camera._useCtrlForPanning && _this._isRightClick))) {
-                                _this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / _this.panningSensibility;
-                                _this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / _this.panningSensibility;
-                            }
-                            else {
-                                var offsetX = evt.clientX - cacheSoloPointer.x;
-                                var offsetY = evt.clientY - cacheSoloPointer.y;
-                                _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
-                                _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
-                            }
-                            cacheSoloPointer.x = evt.clientX;
-                            cacheSoloPointer.y = evt.clientY;
-                            break;
-                        case 2:
-                            //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                }
+            };
+            this._onContextMenu = function (evt) {
+                evt.preventDefault();
+            };
+            this._onPointerMove = function (evt) {
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+                switch (pointers.count) {
+                    case 1:
+                        if (_this.panningSensibility !== 0 && ((_this._isCtrlPushed && _this.camera._useCtrlForPanning) || (!_this.camera._useCtrlForPanning && _this._isRightClick))) {
+                            _this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / _this.panningSensibility;
+                            _this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / _this.panningSensibility;
+                        }
+                        else {
+                            var offsetX = evt.clientX - cacheSoloPointer.x;
+                            var offsetY = evt.clientY - cacheSoloPointer.y;
+                            _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
+                            _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
+                        }
+                        cacheSoloPointer.x = evt.clientX;
+                        cacheSoloPointer.y = evt.clientY;
+                        break;
+                    case 2:
+                        //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                        pointers.item(evt.pointerId).x = evt.clientX;
+                        pointers.item(evt.pointerId).y = evt.clientY;
+                        var direction = _this.pinchInwards ? 1 : -1;
+                        var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
+                        var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
+                        var pinchSquaredDistance = (distX * distX) + (distY * distY);
+                        if (previousPinchDistance === 0) {
+                            previousPinchDistance = pinchSquaredDistance;
+                            return;
+                        }
+                        if (pinchSquaredDistance !== previousPinchDistance) {
+                            _this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (_this.pinchPrecision * ((_this.angularSensibilityX + _this.angularSensibilityY) / 2) * direction);
+                            previousPinchDistance = pinchSquaredDistance;
+                        }
+                        break;
+                    default:
+                        if (pointers.item(evt.pointerId)) {
                             pointers.item(evt.pointerId).x = evt.clientX;
                             pointers.item(evt.pointerId).x = evt.clientX;
                             pointers.item(evt.pointerId).y = evt.clientY;
                             pointers.item(evt.pointerId).y = evt.clientY;
-                            var direction = _this.pinchInwards ? 1 : -1;
-                            var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
-                            var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
-                            var pinchSquaredDistance = (distX * distX) + (distY * distY);
-                            if (previousPinchDistance === 0) {
-                                previousPinchDistance = pinchSquaredDistance;
-                                return;
-                            }
-                            if (pinchSquaredDistance !== previousPinchDistance) {
-                                _this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (_this.pinchPrecision * ((_this.angularSensibilityX + _this.angularSensibilityY) / 2) * direction);
-                                previousPinchDistance = pinchSquaredDistance;
-                            }
-                            break;
-                        default:
-                            if (pointers.item(evt.pointerId)) {
-                                pointers.item(evt.pointerId).x = evt.clientX;
-                                pointers.item(evt.pointerId).y = evt.clientY;
-                            }
-                    }
-                };
-                this._onMouseMove = function (evt) {
-                    if (!engine.isPointerLock) {
-                        return;
-                    }
-                    var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
-                    var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
-                    _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
-                    _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
-                this._onGestureStart = function (e) {
-                    if (window.MSGesture === undefined) {
-                        return;
-                    }
-                    if (!_this._MSGestureHandler) {
-                        _this._MSGestureHandler = new MSGesture();
-                        _this._MSGestureHandler.target = element;
-                    }
-                    _this._MSGestureHandler.addPointer(e.pointerId);
-                };
-                this._onGesture = function (e) {
-                    _this.camera.radius *= e.scale;
-                    if (e.preventDefault) {
-                        if (!noPreventDefault) {
-                            e.stopPropagation();
-                            e.preventDefault();
                         }
                         }
+                }
+            };
+            this._onMouseMove = function (evt) {
+                if (!engine.isPointerLock) {
+                    return;
+                }
+                var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
+                var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
+                _this.camera.inertialAlphaOffset -= offsetX / _this.angularSensibilityX;
+                _this.camera.inertialBetaOffset -= offsetY / _this.angularSensibilityY;
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+            };
+            this._onGestureStart = function (e) {
+                if (window.MSGesture === undefined) {
+                    return;
+                }
+                if (!_this._MSGestureHandler) {
+                    _this._MSGestureHandler = new MSGesture();
+                    _this._MSGestureHandler.target = element;
+                }
+                _this._MSGestureHandler.addPointer(e.pointerId);
+            };
+            this._onGesture = function (e) {
+                _this.camera.radius *= e.scale;
+                if (e.preventDefault) {
+                    if (!noPreventDefault) {
+                        e.stopPropagation();
+                        e.preventDefault();
                     }
                     }
-                };
-            }
-            this.attachedElement.addEventListener(eventPrefix + "down", this._onPointerDown, false);
-            this.attachedElement.addEventListener(eventPrefix + "up", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "out", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "move", this._onPointerMove, false);
-            this.attachedElement.addEventListener("mousemove", this._onMouseMove, false);
-            this.attachedElement.addEventListener("MSPointerDown", this._onGestureStart, false);
-            this.attachedElement.addEventListener("MSGestureChange", this._onGesture, false);
+                }
+            };
+            element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
+            element.addEventListener(eventPrefix + "up", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "out", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "move", this._onPointerMove, false);
+            element.addEventListener("mousemove", this._onMouseMove, false);
+            element.addEventListener("MSPointerDown", this._onGestureStart, false);
+            element.addEventListener("MSGestureChange", this._onGesture, false);
             BABYLON.Tools.RegisterTopRootEvents([
             BABYLON.Tools.RegisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
             ]);
             ]);
         };
         };
-        ArcRotateCameraPointersInput.prototype.detach = function () {
+        ArcRotateCameraPointersInput.prototype.detachControl = function (element) {
             this._MSGestureHandler = null;
             this._MSGestureHandler = null;
-            this.attachedElement.removeEventListener("contextmenu", this._onContextMenu);
-            this.attachedElement.removeEventListener(eventPrefix + "down", this._onPointerDown);
-            this.attachedElement.removeEventListener(eventPrefix + "up", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "out", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "move", this._onPointerMove);
-            this.attachedElement.removeEventListener("mousemove", this._onMouseMove);
-            this.attachedElement.removeEventListener("MSPointerDown", this._onGestureStart);
-            this.attachedElement.removeEventListener("MSGestureChange", this._onGesture);
+            if (element && this._onPointerDown) {
+                element.removeEventListener("contextmenu", this._onContextMenu);
+                element.removeEventListener(eventPrefix + "down", this._onPointerDown);
+                element.removeEventListener(eventPrefix + "up", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "out", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "move", this._onPointerMove);
+                element.removeEventListener("mousemove", this._onMouseMove);
+                element.removeEventListener("MSPointerDown", this._onGestureStart);
+                element.removeEventListener("MSGestureChange", this._onGesture);
+            }
             BABYLON.Tools.UnregisterTopRootEvents([
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
             ]);
             ]);

+ 144 - 151
src/Cameras/Inputs/babylon.arcrotatecamera.input.pointers.ts

@@ -3,11 +3,10 @@ module BABYLON {
 
 
     export class ArcRotateCameraPointersInput implements ICameraInput<ArcRotateCamera> {
     export class ArcRotateCameraPointersInput implements ICameraInput<ArcRotateCamera> {
         camera: ArcRotateCamera;
         camera: ArcRotateCamera;
-        attachedElement: HTMLElement;
         private _isRightClick: boolean = false;
         private _isRightClick: boolean = false;
         private _isCtrlPushed: boolean = false;
         private _isCtrlPushed: boolean = false;
         public pinchInwards = true;
         public pinchInwards = true;
-        
+
         @serialize()
         @serialize()
         public angularSensibilityX = 1000.0;
         public angularSensibilityX = 1000.0;
 
 
@@ -18,7 +17,7 @@ module BABYLON {
         public pinchPrecision = 6.0;
         public pinchPrecision = 6.0;
 
 
         @serialize()
         @serialize()
-        public panningSensibility: number = 50.0;       
+        public panningSensibility: number = 50.0;
 
 
         private _onKeyDown: (e: KeyboardEvent) => any;
         private _onKeyDown: (e: KeyboardEvent) => any;
         private _onKeyUp: (e: KeyboardEvent) => any;
         private _onKeyUp: (e: KeyboardEvent) => any;
@@ -31,199 +30,193 @@ module BABYLON {
         private _MSGestureHandler: MSGesture;
         private _MSGestureHandler: MSGesture;
         private _onLostFocus: (e: FocusEvent) => any;
         private _onLostFocus: (e: FocusEvent) => any;
         private _onContextMenu: (e: PointerEvent) => void;
         private _onContextMenu: (e: PointerEvent) => void;
-        
-        public attachCamera(camera: ArcRotateCamera) {
-            this.camera = camera;
-
-        }
-
-        public attachElement(element: HTMLElement, noPreventDefault?: boolean) {
-            this.attachedElement = element;
 
 
+        public attachControl(element: HTMLElement, noPreventDefault?: boolean) {
             var engine = this.camera.getEngine();
             var engine = this.camera.getEngine();
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var pointers = new SmartCollection();
             var pointers = new SmartCollection();
             var previousPinchDistance = 0;
             var previousPinchDistance = 0;
 
 
-            if (this._onPointerDown === undefined) {
-                if (!this.camera._useCtrlForPanning) {
-                    element.addEventListener("contextmenu", this._onContextMenu, false);
+            if (!this.camera._useCtrlForPanning) {
+                element.addEventListener("contextmenu", this._onContextMenu, false);
+            }
+
+            this._onLostFocus = () => {
+                //this._keys = [];
+                pointers.empty();
+                previousPinchDistance = 0;
+                cacheSoloPointer = null;
+            };
+
+            this._onKeyDown = evt => {
+                this._isCtrlPushed = evt.ctrlKey;
+            };
+
+            this._onKeyUp = evt => {
+                this._isCtrlPushed = evt.ctrlKey;
+            };
+
+            this._onPointerDown = evt => {
+                // Manage panning with right click
+                this._isRightClick = evt.button === 2;
+
+                // manage pointers
+                pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
+                cacheSoloPointer = pointers.item(evt.pointerId);
+                if (!noPreventDefault) {
+                    evt.preventDefault();
                 }
                 }
-                
-                this._onLostFocus = () => {
-                    //this._keys = [];
-                    pointers.empty();
-                    previousPinchDistance = 0;
-                    cacheSoloPointer = null;
-                };
-
-                this._onKeyDown = evt => {
-                    this._isCtrlPushed = evt.ctrlKey;
-                };
-
-                this._onKeyUp = evt => {
-                    this._isCtrlPushed = evt.ctrlKey;
-                };
-
-                this._onPointerDown = evt => {
-                    // Manage panning with right click
-                    this._isRightClick = evt.button === 2;
-
-                    // manage pointers
-                    pointers.add(evt.pointerId, { x: evt.clientX, y: evt.clientY, type: evt.pointerType });
-                    cacheSoloPointer = pointers.item(evt.pointerId);
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
+            };
 
 
-                this._onPointerUp = evt => {
-                    cacheSoloPointer = null;
-                    previousPinchDistance = 0;
+            this._onPointerUp = evt => {
+                cacheSoloPointer = null;
+                previousPinchDistance = 0;
 
 
-                    //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
-                    //but emptying completly pointers collection is required to fix a bug on iPhone : 
-                    //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
-                    //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
-                    pointers.empty();
+                //would be better to use pointers.remove(evt.pointerId) for multitouch gestures, 
+                //but emptying completly pointers collection is required to fix a bug on iPhone : 
+                //when changing orientation while pinching camera, one pointer stay pressed forever if we don't release all pointers  
+                //will be ok to put back pointers.remove(evt.pointerId); when iPhone bug corrected
+                pointers.empty();
 
 
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+            };
+
+            this._onContextMenu = evt => {
+                evt.preventDefault();
+            };
 
 
-                this._onContextMenu = evt => {
+            this._onPointerMove = evt => {
+                if (!noPreventDefault) {
                     evt.preventDefault();
                     evt.preventDefault();
-                };
+                }
 
 
-                this._onPointerMove = evt => {
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
+                switch (pointers.count) {
+
+                    case 1: //normal camera rotation
+                        if (this.panningSensibility !== 0 && ((this._isCtrlPushed && this.camera._useCtrlForPanning) || (!this.camera._useCtrlForPanning && this._isRightClick))) {
+                            this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / this.panningSensibility;
+                            this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / this.panningSensibility;
+                        } else {
+                            var offsetX = evt.clientX - cacheSoloPointer.x;
+                            var offsetY = evt.clientY - cacheSoloPointer.y;
+                            this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
+                            this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
+                        }
+                        cacheSoloPointer.x = evt.clientX;
+                        cacheSoloPointer.y = evt.clientY;
+                        break;
+
+                    case 2: //pinch
+                        //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                        pointers.item(evt.pointerId).x = evt.clientX;
+                        pointers.item(evt.pointerId).y = evt.clientY;
+                        var direction = this.pinchInwards ? 1 : -1;
+                        var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
+                        var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
+                        var pinchSquaredDistance = (distX * distX) + (distY * distY);
+                        if (previousPinchDistance === 0) {
+                            previousPinchDistance = pinchSquaredDistance;
+                            return;
+                        }
 
 
-                    switch (pointers.count) {
-
-                        case 1: //normal camera rotation
-                            if (this.panningSensibility !== 0 && ((this._isCtrlPushed && this.camera._useCtrlForPanning) || (!this.camera._useCtrlForPanning && this._isRightClick))) {
-                                this.camera.inertialPanningX += -(evt.clientX - cacheSoloPointer.x) / this.panningSensibility;
-                                this.camera.inertialPanningY += (evt.clientY - cacheSoloPointer.y) / this.panningSensibility;
-                            } else {
-                                var offsetX = evt.clientX - cacheSoloPointer.x;
-                                var offsetY = evt.clientY - cacheSoloPointer.y;
-                                this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
-                                this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
-                            }
-                            cacheSoloPointer.x = evt.clientX;
-                            cacheSoloPointer.y = evt.clientY;
-                            break;
-
-                        case 2: //pinch
-                            //if (noPreventDefault) { evt.preventDefault(); } //if pinch gesture, could be usefull to force preventDefault to avoid html page scroll/zoom in some mobile browsers
+                        if (pinchSquaredDistance !== previousPinchDistance) {
+                            this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (this.pinchPrecision * ((this.angularSensibilityX + this.angularSensibilityY) / 2) * direction);
+                            previousPinchDistance = pinchSquaredDistance;
+                        }
+                        break;
+
+                    default:
+                        if (pointers.item(evt.pointerId)) {
                             pointers.item(evt.pointerId).x = evt.clientX;
                             pointers.item(evt.pointerId).x = evt.clientX;
                             pointers.item(evt.pointerId).y = evt.clientY;
                             pointers.item(evt.pointerId).y = evt.clientY;
-                            var direction = this.pinchInwards ? 1 : -1;
-                            var distX = pointers.getItemByIndex(0).x - pointers.getItemByIndex(1).x;
-                            var distY = pointers.getItemByIndex(0).y - pointers.getItemByIndex(1).y;
-                            var pinchSquaredDistance = (distX * distX) + (distY * distY);
-                            if (previousPinchDistance === 0) {
-                                previousPinchDistance = pinchSquaredDistance;
-                                return;
-                            }
-
-                            if (pinchSquaredDistance !== previousPinchDistance) {
-                                this.camera.inertialRadiusOffset += (pinchSquaredDistance - previousPinchDistance) / (this.pinchPrecision * ((this.angularSensibilityX + this.angularSensibilityY) / 2) * direction);
-                                previousPinchDistance = pinchSquaredDistance;
-                            }
-                            break;
-
-                        default:
-                            if (pointers.item(evt.pointerId)) {
-                                pointers.item(evt.pointerId).x = evt.clientX;
-                                pointers.item(evt.pointerId).y = evt.clientY;
-                            }
-                    }
-                };
+                        }
+                }
+            };
 
 
-                this._onMouseMove = evt => {
-                    if (!engine.isPointerLock) {
-                        return;
-                    }
+            this._onMouseMove = evt => {
+                if (!engine.isPointerLock) {
+                    return;
+                }
 
 
-                    var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
-                    var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
+                var offsetX = evt.movementX || evt.mozMovementX || evt.webkitMovementX || evt.msMovementX || 0;
+                var offsetY = evt.movementY || evt.mozMovementY || evt.webkitMovementY || evt.msMovementY || 0;
 
 
-                    this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
-                    this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
+                this.camera.inertialAlphaOffset -= offsetX / this.angularSensibilityX;
+                this.camera.inertialBetaOffset -= offsetY / this.angularSensibilityY;
 
 
-                    if (!noPreventDefault) {
-                        evt.preventDefault();
-                    }
-                };
+                if (!noPreventDefault) {
+                    evt.preventDefault();
+                }
+            };
 
 
-                this._onGestureStart = e => {
-                    if (window.MSGesture === undefined) {
-                        return;
-                    }
+            this._onGestureStart = e => {
+                if (window.MSGesture === undefined) {
+                    return;
+                }
 
 
-                    if (!this._MSGestureHandler) {
-                        this._MSGestureHandler = new MSGesture();
-                        this._MSGestureHandler.target = element;
-                    }
+                if (!this._MSGestureHandler) {
+                    this._MSGestureHandler = new MSGesture();
+                    this._MSGestureHandler.target = element;
+                }
 
 
-                    this._MSGestureHandler.addPointer(e.pointerId);
-                };
+                this._MSGestureHandler.addPointer(e.pointerId);
+            };
 
 
-                this._onGesture = e => {
-                    this.camera.radius *= e.scale;
+            this._onGesture = e => {
+                this.camera.radius *= e.scale;
 
 
 
 
-                    if (e.preventDefault) {
-                        if (!noPreventDefault) {
-                            e.stopPropagation();
-                            e.preventDefault();
-                        }
+                if (e.preventDefault) {
+                    if (!noPreventDefault) {
+                        e.stopPropagation();
+                        e.preventDefault();
                     }
                     }
-                };
-            }
+                }
+            };
+
 
 
-            this.attachedElement.addEventListener(eventPrefix + "down", this._onPointerDown, false);
-            this.attachedElement.addEventListener(eventPrefix + "up", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "out", this._onPointerUp, false);
-            this.attachedElement.addEventListener(eventPrefix + "move", this._onPointerMove, false);
-            this.attachedElement.addEventListener("mousemove", this._onMouseMove, false);
-            this.attachedElement.addEventListener("MSPointerDown", this._onGestureStart, false);
-            this.attachedElement.addEventListener("MSGestureChange", this._onGesture, false);
+            element.addEventListener(eventPrefix + "down", this._onPointerDown, false);
+            element.addEventListener(eventPrefix + "up", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "out", this._onPointerUp, false);
+            element.addEventListener(eventPrefix + "move", this._onPointerMove, false);
+            element.addEventListener("mousemove", this._onMouseMove, false);
+            element.addEventListener("MSPointerDown", this._onGestureStart, false);
+            element.addEventListener("MSGestureChange", this._onGesture, false);
 
 
             Tools.RegisterTopRootEvents([
             Tools.RegisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
             ]);
             ]);
         }
         }
 
 
-        public detach() {
+        public detachControl(element: HTMLElement) {
             this._MSGestureHandler = null;
             this._MSGestureHandler = null;
 
 
-            this.attachedElement.removeEventListener("contextmenu", this._onContextMenu);
-            this.attachedElement.removeEventListener(eventPrefix + "down", this._onPointerDown);
-            this.attachedElement.removeEventListener(eventPrefix + "up", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "out", this._onPointerUp);
-            this.attachedElement.removeEventListener(eventPrefix + "move", this._onPointerMove);
-            this.attachedElement.removeEventListener("mousemove", this._onMouseMove);
-            this.attachedElement.removeEventListener("MSPointerDown", this._onGestureStart);
-            this.attachedElement.removeEventListener("MSGestureChange", this._onGesture);
-
+            if (element && this._onPointerDown){
+                element.removeEventListener("contextmenu", this._onContextMenu);
+                element.removeEventListener(eventPrefix + "down", this._onPointerDown);
+                element.removeEventListener(eventPrefix + "up", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "out", this._onPointerUp);
+                element.removeEventListener(eventPrefix + "move", this._onPointerMove);
+                element.removeEventListener("mousemove", this._onMouseMove);
+                element.removeEventListener("MSPointerDown", this._onGestureStart);
+                element.removeEventListener("MSGestureChange", this._onGesture);
+            }
+            
             Tools.UnregisterTopRootEvents([
             Tools.UnregisterTopRootEvents([
                 { name: "blur", handler: this._onLostFocus }
                 { name: "blur", handler: this._onLostFocus }
             ]);
             ]);
-        }        
+        }
 
 
         getTypeName(): string {
         getTypeName(): string {
             return "ArcRotateCameraPointersInput";
             return "ArcRotateCameraPointersInput";
         }
         }
-                
-        getSimpleName(){
+
+        getSimpleName() {
             return "pointers";
             return "pointers";
         }
         }
     }
     }
-    
+
     CameraInputTypes["ArcRotateCameraPointersInput"] = ArcRotateCameraPointersInput;
     CameraInputTypes["ArcRotateCameraPointersInput"] = ArcRotateCameraPointersInput;
 }
 }

+ 2 - 3
src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.js

@@ -19,8 +19,7 @@ var BABYLON;
             this._resetOrientationGamma = this.resetOrientationGamma.bind(this);
             this._resetOrientationGamma = this.resetOrientationGamma.bind(this);
             this._orientationChanged = this.orientationChanged.bind(this);
             this._orientationChanged = this.orientationChanged.bind(this);
         }
         }
-        FreeCameraDeviceOrientationInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("deviceorientation", this._orientationChanged);
             window.addEventListener("deviceorientation", this._orientationChanged);
         };
         };
@@ -37,7 +36,7 @@ var BABYLON;
             this._offsetY = (this._initialOrientationBeta - this._orientationBeta);
             this._offsetY = (this._initialOrientationBeta - this._orientationBeta);
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
         };
         };
-        FreeCameraDeviceOrientationInput.prototype.detach = function () {
+        FreeCameraDeviceOrientationInput.prototype.detachControl = function (element) {
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             this._orientationGamma = 0;
             this._orientationGamma = 0;

+ 2 - 4
src/Cameras/Inputs/babylon.freecamera.input.deviceorientation.ts

@@ -22,9 +22,7 @@ module BABYLON {
             this._orientationChanged = this.orientationChanged.bind(this);
             this._orientationChanged = this.orientationChanged.bind(this);
         }
         }
 
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("deviceorientation", this._orientationChanged);
             window.addEventListener("deviceorientation", this._orientationChanged);
         }
         }
@@ -46,7 +44,7 @@ module BABYLON {
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
         }
         }
 
 
-        detach() {
+        detachControl(element : HTMLElement) {
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             
             

+ 4 - 5
src/Cameras/Inputs/babylon.freecamera.input.gamepad.js

@@ -8,15 +8,14 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var FreeCameraGamepadInput = (function () {
     var FreeCameraGamepadInput = (function () {
         function FreeCameraGamepadInput() {
         function FreeCameraGamepadInput() {
-            var _this = this;
             this.gamepadAngularSensibility = 200;
             this.gamepadAngularSensibility = 200;
             this.gamepadMoveSensibility = 40;
             this.gamepadMoveSensibility = 40;
-            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         }
         }
-        FreeCameraGamepadInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraGamepadInput.prototype.attachControl = function (element, noPreventDefault) {
+            var _this = this;
+            this._gamepads = new BABYLON.Gamepads(function (gamepad) { _this._onNewGameConnected(gamepad); });
         };
         };
-        FreeCameraGamepadInput.prototype.detach = function () {
+        FreeCameraGamepadInput.prototype.detachControl = function (element) {
             this._gamepads.dispose();
             this._gamepads.dispose();
         };
         };
         FreeCameraGamepadInput.prototype.checkInputs = function () {
         FreeCameraGamepadInput.prototype.checkInputs = function () {

+ 2 - 6
src/Cameras/Inputs/babylon.freecamera.input.gamepad.ts

@@ -11,15 +11,11 @@ module BABYLON {
         @serialize()
         @serialize()
         public gamepadMoveSensibility = 40;
         public gamepadMoveSensibility = 40;
         
         
-        constructor(){
+        attachControl(element : HTMLElement, noPreventDefault?: boolean){
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
             this._gamepads = new Gamepads((gamepad: Gamepad) => { this._onNewGameConnected(gamepad); });
         }
         }
         
         
-        attachCamera(camera : FreeCamera){
-            this.camera = camera;
-        }
-        
-        detach(){
+        detachControl(element : HTMLElement){
             this._gamepads.dispose();
             this._gamepads.dispose();
         }
         }
         
         

+ 4 - 5
src/Cameras/Inputs/babylon.freecamera.input.keyboard.js

@@ -14,9 +14,8 @@ var BABYLON;
             this.keysLeft = [37];
             this.keysLeft = [37];
             this.keysRight = [39];
             this.keysRight = [39];
         }
         }
-        FreeCameraKeyboardMoveInput.prototype.attachCamera = function (camera) {
+        FreeCameraKeyboardMoveInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
-            this.camera = camera;
             if (this._onKeyDown === undefined) {
             if (this._onKeyDown === undefined) {
                 this._onKeyDown = function (evt) {
                 this._onKeyDown = function (evt) {
                     if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
                     if (_this.keysUp.indexOf(evt.keyCode) !== -1 ||
@@ -27,7 +26,7 @@ var BABYLON;
                         if (index === -1) {
                         if (index === -1) {
                             _this._keys.push(evt.keyCode);
                             _this._keys.push(evt.keyCode);
                         }
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -41,7 +40,7 @@ var BABYLON;
                         if (index >= 0) {
                         if (index >= 0) {
                             _this._keys.splice(index, 1);
                             _this._keys.splice(index, 1);
                         }
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -53,7 +52,7 @@ var BABYLON;
                 ]);
                 ]);
             }
             }
         };
         };
-        FreeCameraKeyboardMoveInput.prototype.detach = function () {
+        FreeCameraKeyboardMoveInput.prototype.detachControl = function (element) {
             BABYLON.Tools.UnregisterTopRootEvents([
             BABYLON.Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },

+ 4 - 6
src/Cameras/Inputs/babylon.freecamera.input.keyboard.ts

@@ -17,9 +17,7 @@ module BABYLON {
         @serialize()
         @serialize()
         public keysRight = [39];
         public keysRight = [39];
 
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-            
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             if (this._onKeyDown === undefined) {
             if (this._onKeyDown === undefined) {
 
 
                 this._onKeyDown = evt => {
                 this._onKeyDown = evt => {
@@ -32,7 +30,7 @@ module BABYLON {
                         if (index === -1) {
                         if (index === -1) {
                             this._keys.push(evt.keyCode);
                             this._keys.push(evt.keyCode);
                         }
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -48,7 +46,7 @@ module BABYLON {
                         if (index >= 0) {
                         if (index >= 0) {
                             this._keys.splice(index, 1);
                             this._keys.splice(index, 1);
                         }
                         }
-                        if (!camera._noPreventDefault) {
+                        if (!noPreventDefault) {
                             evt.preventDefault();
                             evt.preventDefault();
                         }
                         }
                     }
                     }
@@ -62,7 +60,7 @@ module BABYLON {
             }
             }
         }
         }
 
 
-        detach() {
+        detachControl(element : HTMLElement) {
             Tools.UnregisterTopRootEvents([
             Tools.UnregisterTopRootEvents([
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keydown", handler: this._onKeyDown },
                 { name: "keyup", handler: this._onKeyUp },
                 { name: "keyup", handler: this._onKeyUp },

+ 7 - 18
src/Cameras/Inputs/babylon.freecamera.input.mouse.js

@@ -10,13 +10,9 @@ var BABYLON;
         function FreeCameraMouseInput() {
         function FreeCameraMouseInput() {
             this.angularSensibility = 2000.0;
             this.angularSensibility = 2000.0;
         }
         }
-        FreeCameraMouseInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        FreeCameraMouseInput.prototype.attachElement = function (element, noPreventDefault) {
+        FreeCameraMouseInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
             var previousPosition;
             var previousPosition;
-            this.attachedElement = element;
             if (this._onMouseDown === undefined) {
             if (this._onMouseDown === undefined) {
                 var camera = this.camera;
                 var camera = this.camera;
                 var engine = this.camera.getEngine();
                 var engine = this.camera.getEngine();
@@ -71,19 +67,12 @@ var BABYLON;
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mouseout", this._onMouseOut, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
             element.addEventListener("mousemove", this._onMouseMove, false);
         };
         };
-        FreeCameraMouseInput.prototype.detachElement = function (element) {
-            if (this.attachedElement !== element) {
-                return;
-            }
-            element.removeEventListener("mousedown", this._onMouseDown);
-            element.removeEventListener("mouseup", this._onMouseUp);
-            element.removeEventListener("mouseout", this._onMouseOut);
-            element.removeEventListener("mousemove", this._onMouseMove);
-            this.attachedElement = null;
-        };
-        FreeCameraMouseInput.prototype.detach = function () {
-            if (this.attachedElement) {
-                this.detachElement(this.attachedElement);
+        FreeCameraMouseInput.prototype.detachControl = function (element) {
+            if (this._onMouseDown && element) {
+                element.removeEventListener("mousedown", this._onMouseDown);
+                element.removeEventListener("mouseup", this._onMouseUp);
+                element.removeEventListener("mouseout", this._onMouseOut);
+                element.removeEventListener("mousemove", this._onMouseMove);
             }
             }
         };
         };
         FreeCameraMouseInput.prototype.getTypeName = function () {
         FreeCameraMouseInput.prototype.getTypeName = function () {

+ 8 - 23
src/Cameras/Inputs/babylon.freecamera.input.mouse.ts

@@ -1,7 +1,6 @@
 module BABYLON {       
 module BABYLON {       
     export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
     export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
         camera : FreeCamera;
         camera : FreeCamera;
-        attachedElement : HTMLElement;
         
         
         @serialize()
         @serialize()
         public angularSensibility = 2000.0;
         public angularSensibility = 2000.0;
@@ -11,13 +10,8 @@ module BABYLON {
         private _onMouseOut: (e: MouseEvent) => any;
         private _onMouseOut: (e: MouseEvent) => any;
         private _onMouseMove: (e: MouseEvent) => any;
         private _onMouseMove: (e: MouseEvent) => any;
         
         
-        attachCamera(camera : FreeCamera){
-            this.camera = camera;
-        }
-        
-        attachElement(element: HTMLElement, noPreventDefault?: boolean){     
+        attachControl(element: HTMLElement, noPreventDefault?: boolean){     
             var previousPosition;
             var previousPosition;
-            this.attachedElement = element;
                 
                 
             if (this._onMouseDown === undefined) {
             if (this._onMouseDown === undefined) {
                 var camera = this.camera;
                 var camera = this.camera;
@@ -86,22 +80,13 @@ module BABYLON {
    
    
         }
         }
         
         
-        detachElement(element : HTMLElement){   
-            if (this.attachedElement !== element) {
-                return;
-            }
-
-            element.removeEventListener("mousedown", this._onMouseDown);
-            element.removeEventListener("mouseup", this._onMouseUp);
-            element.removeEventListener("mouseout", this._onMouseOut);
-            element.removeEventListener("mousemove", this._onMouseMove); 
-            this.attachedElement = null;        
-        }
-        
-        detach(){          
-            if (this.attachedElement){
-                this.detachElement(this.attachedElement);
-            }  
+        detachControl(element : HTMLElement){   
+            if (this._onMouseDown && element){
+                element.removeEventListener("mousedown", this._onMouseDown);
+                element.removeEventListener("mouseup", this._onMouseUp);
+                element.removeEventListener("mouseout", this._onMouseOut);
+                element.removeEventListener("mousemove", this._onMouseMove);
+            }        
         }
         }
         
         
         getTypeName(): string{
         getTypeName(): string{

+ 2 - 18
src/Cameras/Inputs/babylon.freecamera.input.touch.js

@@ -15,16 +15,9 @@ var BABYLON;
             this.touchAngularSensibility = 200000.0;
             this.touchAngularSensibility = 200000.0;
             this.touchMoveSensibility = 250.0;
             this.touchMoveSensibility = 250.0;
         }
         }
-        FreeCameraTouchInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
-        };
-        FreeCameraTouchInput.prototype.attachElement = function (element, noPreventDefault) {
+        FreeCameraTouchInput.prototype.attachControl = function (element, noPreventDefault) {
             var _this = this;
             var _this = this;
             var previousPosition;
             var previousPosition;
-            if (this._attachedElement) {
-                return;
-            }
-            this._attachedElement = element;
             if (this._onPointerDown === undefined) {
             if (this._onPointerDown === undefined) {
                 this._onLostFocus = function (evt) {
                 this._onLostFocus = function (evt) {
                     _this._offsetX = null;
                     _this._offsetX = null;
@@ -89,16 +82,12 @@ var BABYLON;
             element.addEventListener("pointerout", this._onPointerUp);
             element.addEventListener("pointerout", this._onPointerUp);
             element.addEventListener("pointermove", this._onPointerMove);
             element.addEventListener("pointermove", this._onPointerMove);
         };
         };
-        FreeCameraTouchInput.prototype.detachElement = function (element) {
-            if (this._attachedElement !== element) {
-                return;
-            }
+        FreeCameraTouchInput.prototype.detachControl = function (element) {
             element.removeEventListener("blur", this._onLostFocus);
             element.removeEventListener("blur", this._onLostFocus);
             element.removeEventListener("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointermove", this._onPointerMove);
             element.removeEventListener("pointermove", this._onPointerMove);
-            this._attachedElement = null;
         };
         };
         FreeCameraTouchInput.prototype.checkInputs = function () {
         FreeCameraTouchInput.prototype.checkInputs = function () {
             if (this._offsetX) {
             if (this._offsetX) {
@@ -115,11 +104,6 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
-        FreeCameraTouchInput.prototype.detach = function () {
-            if (this._attachedElement) {
-                this.detachElement(this._attachedElement);
-            }
-        };
         FreeCameraTouchInput.prototype.getTypeName = function () {
         FreeCameraTouchInput.prototype.getTypeName = function () {
             return "FreeCameraTouchInput";
             return "FreeCameraTouchInput";
         };
         };

+ 2 - 24
src/Cameras/Inputs/babylon.freecamera.input.touch.ts

@@ -6,7 +6,6 @@ module BABYLON {
         private _offsetY: number = null;
         private _offsetY: number = null;
         private _pointerCount: number = 0;
         private _pointerCount: number = 0;
         private _pointerPressed = [];
         private _pointerPressed = [];
-        private _attachedElement: HTMLElement;
         private _onPointerDown: (e: PointerEvent) => any;
         private _onPointerDown: (e: PointerEvent) => any;
         private _onPointerUp: (e: PointerEvent) => any;
         private _onPointerUp: (e: PointerEvent) => any;
         private _onPointerMove: (e: PointerEvent) => any;
         private _onPointerMove: (e: PointerEvent) => any;
@@ -18,19 +17,9 @@ module BABYLON {
         @serialize()
         @serialize()
         public touchMoveSensibility: number = 250.0;
         public touchMoveSensibility: number = 250.0;
 
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-        }
-        
-        attachElement(element: HTMLElement, noPreventDefault?: boolean) {
+        attachControl(element: HTMLElement, noPreventDefault?: boolean) {
             var previousPosition;
             var previousPosition;
 
 
-            if (this._attachedElement) {
-                return;
-            }
-
-            this._attachedElement = element;
-
             if (this._onPointerDown === undefined) {
             if (this._onPointerDown === undefined) {
                 this._onLostFocus = (evt) => {
                 this._onLostFocus = (evt) => {
                     this._offsetX = null;
                     this._offsetX = null;
@@ -117,17 +106,12 @@ module BABYLON {
             element.addEventListener("pointermove", this._onPointerMove);
             element.addEventListener("pointermove", this._onPointerMove);
         }
         }
 
 
-        detachElement(element: HTMLElement) {
-            if (this._attachedElement !== element) {
-                return;
-            }
-
+        detachControl(element: HTMLElement) {
             element.removeEventListener("blur", this._onLostFocus);
             element.removeEventListener("blur", this._onLostFocus);
             element.removeEventListener("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointermove", this._onPointerMove);
             element.removeEventListener("pointermove", this._onPointerMove);
-            this._attachedElement = null;
         }
         }
 
 
         checkInputs() {
         checkInputs() {
@@ -147,12 +131,6 @@ module BABYLON {
             }
             }
         }
         }
 
 
-        detach() {
-            if (this._attachedElement) {
-                this.detachElement(this._attachedElement);
-            }
-        }
-
         getTypeName(): string {
         getTypeName(): string {
             return "FreeCameraTouchInput";
             return "FreeCameraTouchInput";
         }
         }

+ 16 - 14
src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.js

@@ -10,21 +10,22 @@ var BABYLON;
             return this._rightjoystick;
             return this._rightjoystick;
         };
         };
         FreeCameraVirtualJoystickInput.prototype.checkInputs = function () {
         FreeCameraVirtualJoystickInput.prototype.checkInputs = function () {
-            var camera = this.camera;
-            var speed = camera._computeLocalCameraSpeed() * 50;
-            var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
-            var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
-            camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
-            camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
-            if (!this._leftjoystick.pressed) {
-                this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
-            }
-            if (!this._rightjoystick.pressed) {
-                this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+            if (this._leftjoystick) {
+                var camera = this.camera;
+                var speed = camera._computeLocalCameraSpeed() * 50;
+                var cameraTransform = BABYLON.Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
+                var deltaTransform = BABYLON.Vector3.TransformCoordinates(new BABYLON.Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
+                camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
+                camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
+                if (!this._leftjoystick.pressed) {
+                    this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
+                }
+                if (!this._rightjoystick.pressed) {
+                    this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+                }
             }
             }
         };
         };
-        FreeCameraVirtualJoystickInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraVirtualJoystickInput.prototype.attachControl = function (element, noPreventDefault) {
             this._leftjoystick = new BABYLON.VirtualJoystick(true);
             this._leftjoystick = new BABYLON.VirtualJoystick(true);
             this._leftjoystick.setAxisForUpDown(BABYLON.JoystickAxis.Z);
             this._leftjoystick.setAxisForUpDown(BABYLON.JoystickAxis.Z);
             this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
             this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
@@ -36,8 +37,9 @@ var BABYLON;
             this._rightjoystick.setJoystickSensibility(0.05);
             this._rightjoystick.setJoystickSensibility(0.05);
             this._rightjoystick.setJoystickColor("yellow");
             this._rightjoystick.setJoystickColor("yellow");
         };
         };
-        FreeCameraVirtualJoystickInput.prototype.detach = function () {
+        FreeCameraVirtualJoystickInput.prototype.detachControl = function (element) {
             this._leftjoystick.releaseCanvas();
             this._leftjoystick.releaseCanvas();
+            this._rightjoystick.releaseCanvas();
         };
         };
         FreeCameraVirtualJoystickInput.prototype.getTypeName = function () {
         FreeCameraVirtualJoystickInput.prototype.getTypeName = function () {
             return "FreeCameraVirtualJoystickInput";
             return "FreeCameraVirtualJoystickInput";

+ 17 - 16
src/Cameras/Inputs/babylon.freecamera.input.virtualjoystick.ts

@@ -14,24 +14,24 @@ module BABYLON {
         }
         }
 
 
         public checkInputs() {
         public checkInputs() {
-            var camera = this.camera;
-            var speed = camera._computeLocalCameraSpeed() * 50;
-            var cameraTransform = Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
-            var deltaTransform = Vector3.TransformCoordinates(new Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
-            camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
-            camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
-            
-            if (!this._leftjoystick.pressed) {
-                this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
-            }
-            if (!this._rightjoystick.pressed) {
-                this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+            if (this._leftjoystick){
+                var camera = this.camera;
+                var speed = camera._computeLocalCameraSpeed() * 50;
+                var cameraTransform = Matrix.RotationYawPitchRoll(camera.rotation.y, camera.rotation.x, 0);
+                var deltaTransform = Vector3.TransformCoordinates(new Vector3(this._leftjoystick.deltaPosition.x * speed, this._leftjoystick.deltaPosition.y * speed, this._leftjoystick.deltaPosition.z * speed), cameraTransform);
+                camera.cameraDirection = camera.cameraDirection.add(deltaTransform);
+                camera.cameraRotation = camera.cameraRotation.addVector3(this._rightjoystick.deltaPosition);
+                
+                if (!this._leftjoystick.pressed) {
+                    this._leftjoystick.deltaPosition = this._leftjoystick.deltaPosition.scale(0.9);
+                }
+                if (!this._rightjoystick.pressed) {
+                    this._rightjoystick.deltaPosition = this._rightjoystick.deltaPosition.scale(0.9);
+                }
             }
             }
         }
         }
         
         
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-            
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             this._leftjoystick = new VirtualJoystick(true);
             this._leftjoystick = new VirtualJoystick(true);
             this._leftjoystick.setAxisForUpDown(JoystickAxis.Z);
             this._leftjoystick.setAxisForUpDown(JoystickAxis.Z);
             this._leftjoystick.setAxisForLeftRight(JoystickAxis.X);
             this._leftjoystick.setAxisForLeftRight(JoystickAxis.X);
@@ -44,8 +44,9 @@ module BABYLON {
             this._rightjoystick.setJoystickColor("yellow");
             this._rightjoystick.setJoystickColor("yellow");
         }
         }
 
 
-        detach() {
+        detachControl(element : HTMLElement) {
             this._leftjoystick.releaseCanvas();
             this._leftjoystick.releaseCanvas();
+            this._rightjoystick.releaseCanvas();
         }
         }
 
 
         getTypeName(): string {
         getTypeName(): string {

+ 22 - 12
src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.js

@@ -2,13 +2,16 @@ var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
     var FreeCameraVRDeviceOrientationInput = (function () {
     var FreeCameraVRDeviceOrientationInput = (function () {
         function FreeCameraVRDeviceOrientationInput() {
         function FreeCameraVRDeviceOrientationInput() {
+            this.alphaCorrection = 1;
+            this.betaCorrection = 1;
+            this.gammaCorrection = 1;
             this._alpha = 0;
             this._alpha = 0;
             this._beta = 0;
             this._beta = 0;
             this._gamma = 0;
             this._gamma = 0;
+            this._dirty = false;
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
         }
         }
-        FreeCameraVRDeviceOrientationInput.prototype.attachCamera = function (camera) {
-            this.camera = camera;
+        FreeCameraVRDeviceOrientationInput.prototype.attachControl = function (element, noPreventDefault) {
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
         };
         };
         FreeCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
         FreeCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
@@ -16,18 +19,25 @@ var BABYLON;
             this._alpha = +evt.alpha | 0;
             this._alpha = +evt.alpha | 0;
             this._beta = +evt.beta | 0;
             this._beta = +evt.beta | 0;
             this._gamma = +evt.gamma | 0;
             this._gamma = +evt.gamma | 0;
-            if (this._gamma < 0) {
-                this._gamma = 90 + this._gamma;
-            }
-            else {
-                // Incline it in the correct angle.
-                this._gamma = 270 - this._gamma;
+            this._dirty = true;
+        };
+        FreeCameraVRDeviceOrientationInput.prototype.checkInputs = function () {
+            if (this._dirty) {
+                this._dirty = false;
+                var rotationX = this._gamma;
+                if (rotationX < 0) {
+                    rotationX = 90 + rotationX;
+                }
+                else {
+                    // Incline it in the correct angle.
+                    rotationX = 270 - rotationX;
+                }
+                this.camera.rotation.x = this.gammaCorrection * rotationX / 180.0 * Math.PI;
+                this.camera.rotation.y = this.alphaCorrection * -this._alpha / 180.0 * Math.PI;
+                this.camera.rotation.z = this.betaCorrection * this._beta / 180.0 * Math.PI;
             }
             }
-            camera.rotation.x = this._gamma / 180.0 * Math.PI;
-            camera.rotation.y = -this._alpha / 180.0 * Math.PI;
-            camera.rotation.z = this._beta / 180.0 * Math.PI;
         };
         };
-        FreeCameraVRDeviceOrientationInput.prototype.detach = function () {
+        FreeCameraVRDeviceOrientationInput.prototype.detachControl = function (element) {
             window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
             window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
         };
         };
         FreeCameraVRDeviceOrientationInput.prototype.getTypeName = function () {
         FreeCameraVRDeviceOrientationInput.prototype.getTypeName = function () {

+ 31 - 21
src/Cameras/Inputs/babylon.freecamera.input.vrdeviceorientation.ts

@@ -2,9 +2,14 @@ module BABYLON {
     export class FreeCameraVRDeviceOrientationInput implements ICameraInput<FreeCamera> {
     export class FreeCameraVRDeviceOrientationInput implements ICameraInput<FreeCamera> {
         camera: FreeCamera;
         camera: FreeCamera;
 
 
-        public _alpha = 0;
-        public _beta = 0;
-        public _gamma = 0;
+        public alphaCorrection = 1;
+        public betaCorrection = 1;
+        public gammaCorrection = 1;
+
+        private _alpha = 0;
+        private _beta = 0;
+        private _gamma = 0;
+        private _dirty = false;
     
     
         private _offsetOrientation: { yaw: number; pitch: number; roll: number };
         private _offsetOrientation: { yaw: number; pitch: number; roll: number };
         private _deviceOrientationHandler;
         private _deviceOrientationHandler;
@@ -13,32 +18,37 @@ module BABYLON {
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
         }
         }
 
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
         }
         }
 
 
         public _onOrientationEvent(evt: DeviceOrientationEvent): void {
         public _onOrientationEvent(evt: DeviceOrientationEvent): void {
             var camera = this.camera;
             var camera = this.camera;
-            this._alpha = +evt.alpha|0;
-            this._beta = +evt.beta|0;
-            this._gamma = +evt.gamma|0;
+            this._alpha = +evt.alpha | 0;
+            this._beta = +evt.beta | 0;
+            this._gamma = +evt.gamma | 0;
+            this._dirty = true;
+        }
 
 
-            if (this._gamma < 0) {
-                this._gamma = 90 + this._gamma;
-            }
-            else {
-                // Incline it in the correct angle.
-                this._gamma = 270 - this._gamma;
-            }
+        public checkInputs() {
+            if (this._dirty){
+                this._dirty = false;
+                var rotationX = this._gamma;
+                if (rotationX < 0) {
+                    rotationX = 90 + rotationX;
+                }
+                else {
+                    // Incline it in the correct angle.
+                    rotationX = 270 - rotationX;
+                }
 
 
-            camera.rotation.x = this._gamma / 180.0 * Math.PI;   
-            camera.rotation.y = -this._alpha / 180.0 * Math.PI;   
-            camera.rotation.z = this._beta / 180.0 * Math.PI;     
-        }
+                this.camera.rotation.x = this.gammaCorrection * rotationX / 180.0 * Math.PI;
+                this.camera.rotation.y = this.alphaCorrection * -this._alpha / 180.0 * Math.PI;
+                this.camera.rotation.z = this.betaCorrection * this._beta / 180.0 * Math.PI;
+            }
+        }              
 
 
-        detach() {
+        detachControl(element : HTMLElement) {
             window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
             window.removeEventListener("deviceorientation", this._deviceOrientationHandler);
         }
         }
 
 

+ 0 - 6
src/Cameras/babylon.arcRotateCameraInputsManager.js

@@ -10,12 +10,6 @@ var BABYLON;
         function ArcRotateCameraInputsManager(camera) {
         function ArcRotateCameraInputsManager(camera) {
             _super.call(this, camera);
             _super.call(this, camera);
         }
         }
-        ArcRotateCameraInputsManager.prototype.add = function (input) {
-            _super.prototype.add.call(this, input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        };
         ArcRotateCameraInputsManager.prototype.addMouseWheel = function () {
         ArcRotateCameraInputsManager.prototype.addMouseWheel = function () {
             this.add(new BABYLON.ArcRotateCameraMouseWheelInput());
             this.add(new BABYLON.ArcRotateCameraMouseWheelInput());
             return this;
             return this;

+ 0 - 7
src/Cameras/babylon.arcRotateCameraInputsManager.ts

@@ -4,13 +4,6 @@ module BABYLON {
             super(camera);    
             super(camera);    
         }
         }
         
         
-        add(input: ICameraInput<ArcRotateCamera>){
-            super.add(input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        }
-        
         public addMouseWheel(){
         public addMouseWheel(){
             this.add(new ArcRotateCameraMouseWheelInput());
             this.add(new ArcRotateCameraMouseWheelInput());
             return this;
             return this;

+ 11 - 10
src/Cameras/babylon.cameraInputsManager.js

@@ -14,18 +14,21 @@ var BABYLON;
                 return;
                 return;
             }
             }
             this.attached[type] = input;
             this.attached[type] = input;
-            input.attachCamera(this.camera);
+            input.camera = this.camera;
             //for checkInputs, we are dynamically creating a function
             //for checkInputs, we are dynamically creating a function
             //the goal is to avoid the performance penalty of looping for inputs in the render loop
             //the goal is to avoid the performance penalty of looping for inputs in the render loop
             if (input.checkInputs) {
             if (input.checkInputs) {
                 this.checkInputs = this._addCheckInputs(input.checkInputs.bind(input));
                 this.checkInputs = this._addCheckInputs(input.checkInputs.bind(input));
             }
             }
+            if (this.attachedElement) {
+                input.attachControl(this.attachedElement);
+            }
         };
         };
         CameraInputsManager.prototype.remove = function (inputToRemove) {
         CameraInputsManager.prototype.remove = function (inputToRemove) {
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
                 if (input == inputToRemove) {
                 if (input == inputToRemove) {
-                    input.detach();
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     delete this.attached[cam];
                 }
                 }
             }
             }
@@ -34,7 +37,7 @@ var BABYLON;
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
                 if (input.getTypeName() == inputType) {
                 if (input.getTypeName() == inputType) {
-                    input.detach();
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     delete this.attached[cam];
                 }
                 }
             }
             }
@@ -47,17 +50,16 @@ var BABYLON;
             };
             };
         };
         };
         CameraInputsManager.prototype.attachElement = function (element, noPreventDefault) {
         CameraInputsManager.prototype.attachElement = function (element, noPreventDefault) {
+            this.attachedElement = element;
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
-                if (input.attachElement)
-                    this.attached[cam].attachElement(element, noPreventDefault);
+                this.attached[cam].attachControl(element, noPreventDefault);
             }
             }
         };
         };
         CameraInputsManager.prototype.detachElement = function (element) {
         CameraInputsManager.prototype.detachElement = function (element) {
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
-                if (input.detachElement)
-                    this.attached[cam].detachElement(element);
+                this.attached[cam].detachControl(element);
             }
             }
         };
         };
         CameraInputsManager.prototype.rebuildInputCheck = function (element) {
         CameraInputsManager.prototype.rebuildInputCheck = function (element) {
@@ -70,10 +72,9 @@ var BABYLON;
             }
             }
         };
         };
         CameraInputsManager.prototype.clear = function () {
         CameraInputsManager.prototype.clear = function () {
-            for (var cam in this.attached) {
-                this.attached[cam].detach();
-            }
+            this.detachElement(this.attachedElement);
             this.attached = {};
             this.attached = {};
+            this.attachedElement = null;
             this.checkInputs = function () { };
             this.checkInputs = function () { };
         };
         };
         CameraInputsManager.prototype.serialize = function (serializedCamera) {
         CameraInputsManager.prototype.serialize = function (serializedCamera) {

+ 17 - 17
src/Cameras/babylon.cameraInputsManager.ts

@@ -2,14 +2,11 @@ module BABYLON {
     export var CameraInputTypes = {};
     export var CameraInputTypes = {};
 
 
     export interface ICameraInput<TCamera extends BABYLON.Camera> {
     export interface ICameraInput<TCamera extends BABYLON.Camera> {
-        camera: TCamera;
-        attachCamera(camera: TCamera);
-        detach();
+        camera: TCamera;        
         getTypeName(): string;
         getTypeName(): string;
         getSimpleName(): string;
         getSimpleName(): string;
-
-        attachElement?: (element: HTMLElement, noPreventDefault?: boolean) => void;
-        detachElement?: (element: HTMLElement) => void;
+        attachControl: (element: HTMLElement, noPreventDefault?: boolean) => void;
+        detachControl: (element: HTMLElement) => void;        
         checkInputs?: () => void;
         checkInputs?: () => void;
     }
     }
 
 
@@ -20,6 +17,7 @@ module BABYLON {
 
 
     export class CameraInputsManager<TCamera extends BABYLON.Camera> {
     export class CameraInputsManager<TCamera extends BABYLON.Camera> {
         attached: CameraInputsMap<TCamera>;
         attached: CameraInputsMap<TCamera>;
+        attachedElement: HTMLElement;
         camera: TCamera;
         camera: TCamera;
         checkInputs: () => void;
         checkInputs: () => void;
 
 
@@ -37,20 +35,25 @@ module BABYLON {
             }
             }
 
 
             this.attached[type] = input;
             this.attached[type] = input;
-            input.attachCamera(this.camera);
+            
+            input.camera = this.camera;
             
             
             //for checkInputs, we are dynamically creating a function
             //for checkInputs, we are dynamically creating a function
             //the goal is to avoid the performance penalty of looping for inputs in the render loop
             //the goal is to avoid the performance penalty of looping for inputs in the render loop
             if (input.checkInputs) {
             if (input.checkInputs) {
                 this.checkInputs = this._addCheckInputs(input.checkInputs.bind(input));
                 this.checkInputs = this._addCheckInputs(input.checkInputs.bind(input));
             }
             }
+            
+            if (this.attachedElement){
+                input.attachControl(this.attachedElement);
+            }
         }
         }
 
 
         public remove(inputToRemove: ICameraInput<TCamera>) {
         public remove(inputToRemove: ICameraInput<TCamera>) {
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
                 if (input == inputToRemove) {
                 if (input == inputToRemove) {
-                    input.detach();
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     delete this.attached[cam];
                 }
                 }
             }
             }
@@ -60,7 +63,7 @@ module BABYLON {
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
                 if (input.getTypeName() == inputType) {
                 if (input.getTypeName() == inputType) {
-                    input.detach();
+                    input.detachControl(this.attachedElement);
                     delete this.attached[cam];
                     delete this.attached[cam];
                 }
                 }
             }
             }
@@ -75,18 +78,17 @@ module BABYLON {
         }
         }
 
 
         public attachElement(element: HTMLElement, noPreventDefault?: boolean) {
         public attachElement(element: HTMLElement, noPreventDefault?: boolean) {
+            this.attachedElement = element;
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
-                if (input.attachElement)
-                    this.attached[cam].attachElement(element, noPreventDefault);
+                this.attached[cam].attachControl(element, noPreventDefault);
             }
             }
         }
         }
 
 
         public detachElement(element: HTMLElement) {
         public detachElement(element: HTMLElement) {
             for (var cam in this.attached) {
             for (var cam in this.attached) {
                 var input = this.attached[cam];
                 var input = this.attached[cam];
-                if (input.detachElement)
-                    this.attached[cam].detachElement(element);
+                this.attached[cam].detachControl(element);
             }
             }
         }
         }
 
 
@@ -102,11 +104,9 @@ module BABYLON {
         }
         }
 
 
         public clear() {
         public clear() {
-            for (var cam in this.attached) {
-                this.attached[cam].detach();
-            }
-
+            this.detachElement(this.attachedElement);
             this.attached = {};
             this.attached = {};
+            this.attachedElement = null;
             this.checkInputs = () => { };
             this.checkInputs = () => { };
         }
         }
 
 

+ 0 - 6
src/Cameras/babylon.freeCameraInputsManager.js

@@ -10,12 +10,6 @@ var BABYLON;
         function FreeCameraInputsManager(camera) {
         function FreeCameraInputsManager(camera) {
             _super.call(this, camera);
             _super.call(this, camera);
         }
         }
-        FreeCameraInputsManager.prototype.add = function (input) {
-            _super.prototype.add.call(this, input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        };
         FreeCameraInputsManager.prototype.addKeyboard = function () {
         FreeCameraInputsManager.prototype.addKeyboard = function () {
             this.add(new BABYLON.FreeCameraKeyboardMoveInput());
             this.add(new BABYLON.FreeCameraKeyboardMoveInput());
             return this;
             return this;

+ 1 - 8
src/Cameras/babylon.freeCameraInputsManager.ts

@@ -2,14 +2,7 @@ module BABYLON {
     export class FreeCameraInputsManager extends CameraInputsManager<FreeCamera> {
     export class FreeCameraInputsManager extends CameraInputsManager<FreeCamera> {
         constructor(camera : FreeCamera){
         constructor(camera : FreeCamera){
             super(camera);    
             super(camera);    
-        }
-        
-        add(input: ICameraInput<FreeCamera>){
-            super.add(input);
-            if (this.camera._attachedElement && input.attachElement) {
-                input.attachElement(this.camera._attachedElement, this.camera._noPreventDefault);
-            }
-        }
+        }        
         
         
         addKeyboard(){
         addKeyboard(){
             this.add(new FreeCameraKeyboardMoveInput());
             this.add(new FreeCameraKeyboardMoveInput());

+ 39 - 0
src/Physics/Plugins/babylon.cannonJSPlugin.js

@@ -162,6 +162,7 @@ var BABYLON;
             }*/
             }*/
             switch (impostorJoint.joint.type) {
             switch (impostorJoint.joint.type) {
                 case BABYLON.PhysicsJoint.HingeJoint:
                 case BABYLON.PhysicsJoint.HingeJoint:
+                case BABYLON.PhysicsJoint.Hinge2Joint:
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
                     break;
                     break;
                 case BABYLON.PhysicsJoint.DistanceJoint:
                 case BABYLON.PhysicsJoint.DistanceJoint:
@@ -371,6 +372,18 @@ var BABYLON;
         CannonJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
         CannonJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
             impostor.physicsBody.angularVelocity.copy(velocity);
             impostor.physicsBody.angularVelocity.copy(velocity);
         };
         };
+        CannonJSPlugin.prototype.getLinearVelocity = function (impostor) {
+            var v = impostor.physicsBody.velocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
+        CannonJSPlugin.prototype.getAngularVelocity = function (impostor) {
+            var v = impostor.physicsBody.angularVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
         CannonJSPlugin.prototype.setBodyMass = function (impostor, mass) {
         CannonJSPlugin.prototype.setBodyMass = function (impostor, mass) {
             impostor.physicsBody.mass = mass;
             impostor.physicsBody.mass = mass;
             impostor.physicsBody.updateMassProperties();
             impostor.physicsBody.updateMassProperties();
@@ -381,6 +394,32 @@ var BABYLON;
         CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
         CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
             impostor.physicsBody.wakeUp();
             impostor.physicsBody.wakeUp();
         };
         };
+        CannonJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
+            joint.physicsJoint.distance = maxDistance;
+        };
+        CannonJSPlugin.prototype.enableMotor = function (joint, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.enableMotor();
+            }
+        };
+        CannonJSPlugin.prototype.disableMotor = function (joint, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.disableMotor();
+            }
+        };
+        CannonJSPlugin.prototype.setMotor = function (joint, speed, maxForce, motorIndex) {
+            if (!motorIndex) {
+                joint.physicsJoint.enableMotor();
+                joint.physicsJoint.setMotorSpeed(speed);
+                if (maxForce) {
+                    this.setLimit(joint, maxForce);
+                }
+            }
+        };
+        CannonJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit) {
+            joint.physicsJoint.motorEquation.maxForce = upperLimit;
+            joint.physicsJoint.motorEquation.minForce = lowerLimit || -upperLimit;
+        };
         CannonJSPlugin.prototype.dispose = function () {
         CannonJSPlugin.prototype.dispose = function () {
             //nothing to do, actually.
             //nothing to do, actually.
         };
         };

+ 30 - 0
src/Physics/Plugins/babylon.oimoJSPlugin.js

@@ -264,6 +264,18 @@ var BABYLON;
         OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
         OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
             impostor.physicsBody.angularVelocity.init(velocity.x, velocity.y, velocity.z);
             impostor.physicsBody.angularVelocity.init(velocity.x, velocity.y, velocity.z);
         };
         };
+        OimoJSPlugin.prototype.getLinearVelocity = function (impostor) {
+            var v = impostor.physicsBody.linearVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
+        OimoJSPlugin.prototype.getAngularVelocity = function (impostor) {
+            var v = impostor.physicsBody.angularVelocity;
+            if (!v)
+                return null;
+            return new BABYLON.Vector3(v.x, v.y, v.z);
+        };
         OimoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
         OimoJSPlugin.prototype.setBodyMass = function (impostor, mass) {
             var staticBody = mass === 0;
             var staticBody = mass === 0;
             //this will actually set the body's density and not its mass.
             //this will actually set the body's density and not its mass.
@@ -277,6 +289,24 @@ var BABYLON;
         OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
         OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
             impostor.physicsBody.awake();
             impostor.physicsBody.awake();
         };
         };
+        OimoJSPlugin.prototype.updateDistanceJoint = function (joint, maxDistance, minDistance) {
+            joint.physicsJoint.limitMotoe.upperLimit = maxDistance;
+            if (minDistance !== void 0) {
+                joint.physicsJoint.limitMotoe.lowerLimit = minDistance;
+            }
+        };
+        OimoJSPlugin.prototype.setMotor = function (joint, force, maxForce, motorIndex) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setMotor(force, maxForce);
+            }
+        };
+        OimoJSPlugin.prototype.setLimit = function (joint, upperLimit, lowerLimit, motorIndex) {
+            var motor = motorIndex ? joint.physicsJoint.rotationalLimitMotor2 : joint.physicsJoint.rotationalLimitMotor1 || joint.physicsJoint.limitMotor;
+            if (motor) {
+                motor.setLimit(upperLimit, lowerLimit || -upperLimit);
+            }
+        };
         OimoJSPlugin.prototype.dispose = function () {
         OimoJSPlugin.prototype.dispose = function () {
             this.world.clear();
             this.world.clear();
         };
         };

+ 18 - 0
src/Physics/babylon.physicsEngine.js

@@ -24,6 +24,7 @@ var BABYLON;
          * default is 1/60.
          * default is 1/60.
          * To slow it down, enter 1/600 for example.
          * To slow it down, enter 1/600 for example.
          * To speed it up, 1/30
          * To speed it up, 1/30
+         * @param {number} newTimeStep the new timestep to apply to this world.
          */
          */
         PhysicsEngine.prototype.setTimeStep = function (newTimeStep) {
         PhysicsEngine.prototype.setTimeStep = function (newTimeStep) {
             if (newTimeStep === void 0) { newTimeStep = 1 / 60; }
             if (newTimeStep === void 0) { newTimeStep = 1 / 60; }
@@ -38,6 +39,11 @@ var BABYLON;
         PhysicsEngine.prototype.getPhysicsPluginName = function () {
         PhysicsEngine.prototype.getPhysicsPluginName = function () {
             return this._physicsPlugin.name;
             return this._physicsPlugin.name;
         };
         };
+        /**
+         * Adding a new impostor for the impostor tracking.
+         * This will be done by the impostor itself.
+         * @param {PhysicsImpostor} impostor the impostor to add
+         */
         PhysicsEngine.prototype.addImpostor = function (impostor) {
         PhysicsEngine.prototype.addImpostor = function (impostor) {
             this._impostors.push(impostor);
             this._impostors.push(impostor);
             //if no parent, generate the body
             //if no parent, generate the body
@@ -45,6 +51,11 @@ var BABYLON;
                 this._physicsPlugin.generatePhysicsBody(impostor);
                 this._physicsPlugin.generatePhysicsBody(impostor);
             }
             }
         };
         };
+        /**
+         * Remove an impostor from the engine.
+         * This impostor and its mesh will not longer be updated by the physics engine.
+         * @param {PhysicsImpostor} impostor the impostor to remove
+         */
         PhysicsEngine.prototype.removeImpostor = function (impostor) {
         PhysicsEngine.prototype.removeImpostor = function (impostor) {
             var index = this._impostors.indexOf(impostor);
             var index = this._impostors.indexOf(impostor);
             if (index > -1) {
             if (index > -1) {
@@ -56,12 +67,19 @@ var BABYLON;
                 }
                 }
             }
             }
         };
         };
+        /**
+         * Add a joint to the physics engine
+         * @param {PhysicsImpostor} mainImpostor the main impostor to which the joint is added.
+         * @param {PhysicsImpostor} connectedImpostor the impostor that is connected to the main impostor using this joint
+         * @param {PhysicsJoint} the joint that will connect both impostors.
+         */
         PhysicsEngine.prototype.addJoint = function (mainImpostor, connectedImpostor, joint) {
         PhysicsEngine.prototype.addJoint = function (mainImpostor, connectedImpostor, joint) {
             var impostorJoint = {
             var impostorJoint = {
                 mainImpostor: mainImpostor,
                 mainImpostor: mainImpostor,
                 connectedImpostor: connectedImpostor,
                 connectedImpostor: connectedImpostor,
                 joint: joint
                 joint: joint
             };
             };
+            joint.physicsPlugin = this._physicsPlugin;
             this._joints.push(impostorJoint);
             this._joints.push(impostorJoint);
             this._physicsPlugin.generateJoint(impostorJoint);
             this._physicsPlugin.generateJoint(impostorJoint);
         };
         };

+ 19 - 8
src/Physics/babylon.physicsImpostor.js

@@ -55,15 +55,20 @@ var BABYLON;
                     });
                     });
                 }
                 }
             };
             };
-            //default options params
-            this._options.mass = (_options.mass === void 0) ? 0 : _options.mass;
-            this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction;
-            this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution;
             this._physicsEngine = this._mesh.getScene().getPhysicsEngine();
             this._physicsEngine = this._mesh.getScene().getPhysicsEngine();
-            this._joints = [];
-            //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
-            if (!this._mesh.parent) {
-                this._init();
+            if (!this._physicsEngine) {
+                BABYLON.Tools.Error("Physics not enabled. Please use scene.enablePhysics(...) before creating impostors.");
+            }
+            else {
+                //default options params
+                this._options.mass = (_options.mass === void 0) ? 0 : _options.mass;
+                this._options.friction = (_options.friction === void 0) ? 0.2 : _options.friction;
+                this._options.restitution = (_options.restitution === void 0) ? 0.2 : _options.restitution;
+                this._joints = [];
+                //If the mesh has a parent, don't initialize the physicsBody. Instead wait for the parent to do that.
+                if (!this._mesh.parent) {
+                    this._init();
+                }
             }
             }
         }
         }
         /**
         /**
@@ -165,12 +170,18 @@ var BABYLON;
             }
             }
             this._physicsEngine.getPhysicsPlugin().setBodyMass(this, mass);
             this._physicsEngine.getPhysicsPlugin().setBodyMass(this, mass);
         };
         };
+        PhysicsImpostor.prototype.getLinearVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this);
+        };
         /**
         /**
          * Set the body's linear velocity.
          * Set the body's linear velocity.
          */
          */
         PhysicsImpostor.prototype.setLinearVelocity = function (velocity) {
         PhysicsImpostor.prototype.setLinearVelocity = function (velocity) {
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
         };
         };
+        PhysicsImpostor.prototype.getAngularVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this);
+        };
         /**
         /**
          * Set the body's linear velocity.
          * Set the body's linear velocity.
          */
          */

+ 102 - 1
src/Physics/babylon.physicsJoint.js

@@ -1,5 +1,14 @@
+var __extends = (this && this.__extends) || function (d, b) {
+    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
+    function __() { this.constructor = d; }
+    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
+};
 var BABYLON;
 var BABYLON;
 (function (BABYLON) {
 (function (BABYLON) {
+    /**
+     * This is a holder class for the physics joint created by the physics plugin.
+     * It holds a set of functions to control the underlying joint.
+     */
     var PhysicsJoint = (function () {
     var PhysicsJoint = (function () {
         function PhysicsJoint(type, jointData) {
         function PhysicsJoint(type, jointData) {
             this.type = type;
             this.type = type;
@@ -18,6 +27,21 @@ var BABYLON;
             enumerable: true,
             enumerable: true,
             configurable: true
             configurable: true
         });
         });
+        Object.defineProperty(PhysicsJoint.prototype, "physicsPlugin", {
+            set: function (physicsPlugin) {
+                this._physicsPlugin = physicsPlugin;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        /**
+         * Execute a function that is physics-plugin specific.
+         * @param {Function} func the function that will be executed.
+         *                        It accepts two parameters: the physics world and the physics joint.
+         */
+        PhysicsJoint.prototype.executeNativeFunction = function (func) {
+            func(this._physicsPlugin.world, this._physicsJoint);
+        };
         //TODO check if the native joints are the same
         //TODO check if the native joints are the same
         //Joint Types
         //Joint Types
         PhysicsJoint.DistanceJoint = 0;
         PhysicsJoint.DistanceJoint = 0;
@@ -29,7 +53,7 @@ var BABYLON;
         PhysicsJoint.PrismaticJoint = 5;
         PhysicsJoint.PrismaticJoint = 5;
         //ENERGY FTW! (compare with this - http://ode-wiki.org/wiki/index.php?title=Manual:_Joint_Types_and_Functions)
         //ENERGY FTW! (compare with this - http://ode-wiki.org/wiki/index.php?title=Manual:_Joint_Types_and_Functions)
         PhysicsJoint.UniversalJoint = 6;
         PhysicsJoint.UniversalJoint = 6;
-        PhysicsJoint.Hinge2Joint = 7;
+        PhysicsJoint.Hinge2Joint = PhysicsJoint.WheelJoint;
         //Cannon
         //Cannon
         //Similar to a Ball-Joint. Different in params
         //Similar to a Ball-Joint. Different in params
         //TODO check!!
         //TODO check!!
@@ -39,4 +63,81 @@ var BABYLON;
         return PhysicsJoint;
         return PhysicsJoint;
     })();
     })();
     BABYLON.PhysicsJoint = PhysicsJoint;
     BABYLON.PhysicsJoint = PhysicsJoint;
+    /**
+     * A class representing a physics distance joint.
+     */
+    var DistanceJoint = (function (_super) {
+        __extends(DistanceJoint, _super);
+        function DistanceJoint(jointData) {
+            _super.call(this, PhysicsJoint.DistanceJoint, jointData);
+        }
+        /**
+         * Update the predefined distance.
+         */
+        DistanceJoint.prototype.updateDistance = function (maxDistance, minDistance) {
+            this._physicsPlugin.updateDistanceJoint(this, maxDistance, minDistance);
+        };
+        return DistanceJoint;
+    })(PhysicsJoint);
+    BABYLON.DistanceJoint = DistanceJoint;
+    /**
+     * This class represents a single hinge physics joint
+     */
+    var HingeJoint = (function (_super) {
+        __extends(HingeJoint, _super);
+        function HingeJoint(jointData) {
+            _super.call(this, PhysicsJoint.HingeJoint, jointData);
+        }
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         */
+        HingeJoint.prototype.setMotor = function (force, maxForce) {
+            this._physicsPlugin.setMotor(this, force, maxForce);
+        };
+        /**
+         * Set the motor's limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         */
+        HingeJoint.prototype.setLimit = function (upperLimit, lowerLimit) {
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit);
+        };
+        return HingeJoint;
+    })(PhysicsJoint);
+    BABYLON.HingeJoint = HingeJoint;
+    /**
+     * This class represents a dual hinge physics joint (same as wheel joint)
+     */
+    var Hinge2Joint = (function (_super) {
+        __extends(Hinge2Joint, _super);
+        function Hinge2Joint(jointData) {
+            _super.call(this, PhysicsJoint.Hinge2Joint, jointData);
+        }
+        /**
+         * Set the motor values.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} force the force to apply
+         * @param {number} maxForce max force for this motor.
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        Hinge2Joint.prototype.setMotor = function (force, maxForce, motorIndex) {
+            if (motorIndex === void 0) { motorIndex = 0; }
+            this._physicsPlugin.setMotor(this, force, maxForce, motorIndex);
+        };
+        /**
+         * Set the motor limits.
+         * Attention, this function is plugin specific. Engines won't react 100% the same.
+         * @param {number} upperLimit the upper limit
+         * @param {number} lowerLimit lower limit
+         * @param {motorIndex} the motor's index, 0 or 1.
+         */
+        Hinge2Joint.prototype.setLimit = function (upperLimit, lowerLimit, motorIndex) {
+            if (motorIndex === void 0) { motorIndex = 0; }
+            this._physicsPlugin.setLimit(this, upperLimit, lowerLimit, motorIndex);
+        };
+        return Hinge2Joint;
+    })(PhysicsJoint);
+    BABYLON.Hinge2Joint = Hinge2Joint;
 })(BABYLON || (BABYLON = {}));
 })(BABYLON || (BABYLON = {}));