Prechádzať zdrojové kódy

fix bug on inputmanager for detaching elements, improve VRDeviceOrientation input

gleborgne 9 rokov pred
rodič
commit
f7ea4c5b2b
36 zmenil súbory, kde vykonal 1873 pridanie a 1515 odobranie
  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

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 762 - 669
dist/preview release/babylon.d.ts


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 32 - 28
dist/preview release/babylon.js


Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 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) {
     var ArcRotateCameraGamepadInput = (function () {
         function ArcRotateCameraGamepadInput() {
-            var _this = this;
             this.gamepadRotationSensibility = 80;
             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();
         };
         ArcRotateCameraGamepadInput.prototype.checkInputs = function () {

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

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

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

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

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

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

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

@@ -10,12 +10,8 @@ var BABYLON;
         function ArcRotateCameraMouseWheelInput() {
             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;
-            this.attachedElement = element;
             this._wheel = function (event) {
                 var delta = 0;
                 if (event.wheelDelta) {
@@ -35,9 +31,11 @@ var BABYLON;
             element.addEventListener('mousewheel', 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 () {
             return "ArcRotateCameraMouseWheelInput";

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

@@ -1,19 +1,13 @@
 module BABYLON {
     export class ArcRotateCameraMouseWheelInput implements ICameraInput<ArcRotateCamera> {
         camera: ArcRotateCamera;
-        attachedElement: HTMLElement;
-
+        
         private _wheel: (e: MouseWheelEvent) => void;
 
         @serialize()
         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 => {
                 var delta = 0;
                 if (event.wheelDelta) {
@@ -35,9 +29,11 @@ module BABYLON {
             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 {

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

@@ -17,153 +17,149 @@ var BABYLON;
             this.pinchPrecision = 6.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;
-            this.attachedElement = element;
             var engine = this.camera.getEngine();
             var cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var pointers = new BABYLON.SmartCollection();
             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();
-                };
-                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).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([
                 { name: "blur", handler: this._onLostFocus }
             ]);
         };
-        ArcRotateCameraPointersInput.prototype.detach = function () {
+        ArcRotateCameraPointersInput.prototype.detachControl = function (element) {
             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([
                 { 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> {
         camera: ArcRotateCamera;
-        attachedElement: HTMLElement;
         private _isRightClick: boolean = false;
         private _isCtrlPushed: boolean = false;
         public pinchInwards = true;
-        
+
         @serialize()
         public angularSensibilityX = 1000.0;
 
@@ -18,7 +17,7 @@ module BABYLON {
         public pinchPrecision = 6.0;
 
         @serialize()
-        public panningSensibility: number = 50.0;       
+        public panningSensibility: number = 50.0;
 
         private _onKeyDown: (e: KeyboardEvent) => any;
         private _onKeyUp: (e: KeyboardEvent) => any;
@@ -31,199 +30,193 @@ module BABYLON {
         private _MSGestureHandler: MSGesture;
         private _onLostFocus: (e: FocusEvent) => any;
         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 cacheSoloPointer; // cache pointer object for better perf on camera rotation
             var pointers = new SmartCollection();
             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();
-                };
+                }
 
-                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).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([
                 { name: "blur", handler: this._onLostFocus }
             ]);
         }
 
-        public detach() {
+        public detachControl(element: HTMLElement) {
             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([
                 { name: "blur", handler: this._onLostFocus }
             ]);
-        }        
+        }
 
         getTypeName(): string {
             return "ArcRotateCameraPointersInput";
         }
-                
-        getSimpleName(){
+
+        getSimpleName() {
             return "pointers";
         }
     }
-    
+
     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._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("deviceorientation", this._orientationChanged);
         };
@@ -37,7 +36,7 @@ var BABYLON;
             this._offsetY = (this._initialOrientationBeta - this._orientationBeta);
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
         };
-        FreeCameraDeviceOrientationInput.prototype.detach = function () {
+        FreeCameraDeviceOrientationInput.prototype.detachControl = function (element) {
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             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);
         }
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             window.addEventListener("resize", this._resetOrientationGamma, false);
             window.addEventListener("deviceorientation", this._orientationChanged);
         }
@@ -46,7 +44,7 @@ module BABYLON {
             this._offsetX = (this._initialOrientationGamma - this._orientationGamma);
         }
 
-        detach() {
+        detachControl(element : HTMLElement) {
             window.removeEventListener("resize", this._resetOrientationGamma);
             window.removeEventListener("deviceorientation", this._orientationChanged);
             

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

@@ -8,15 +8,14 @@ var BABYLON;
 (function (BABYLON) {
     var FreeCameraGamepadInput = (function () {
         function FreeCameraGamepadInput() {
-            var _this = this;
             this.gamepadAngularSensibility = 200;
             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();
         };
         FreeCameraGamepadInput.prototype.checkInputs = function () {

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

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

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

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

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

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

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

@@ -10,13 +10,9 @@ var BABYLON;
         function FreeCameraMouseInput() {
             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 previousPosition;
-            this.attachedElement = element;
             if (this._onMouseDown === undefined) {
                 var camera = this.camera;
                 var engine = this.camera.getEngine();
@@ -71,19 +67,12 @@ var BABYLON;
             element.addEventListener("mouseout", this._onMouseOut, 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 () {

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

@@ -1,7 +1,6 @@
 module BABYLON {       
     export class FreeCameraMouseInput implements ICameraInput<FreeCamera> {
         camera : FreeCamera;
-        attachedElement : HTMLElement;
         
         @serialize()
         public angularSensibility = 2000.0;
@@ -11,13 +10,8 @@ module BABYLON {
         private _onMouseOut: (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;
-            this.attachedElement = element;
                 
             if (this._onMouseDown === undefined) {
                 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{

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

@@ -15,16 +15,9 @@ var BABYLON;
             this.touchAngularSensibility = 200000.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 previousPosition;
-            if (this._attachedElement) {
-                return;
-            }
-            this._attachedElement = element;
             if (this._onPointerDown === undefined) {
                 this._onLostFocus = function (evt) {
                     _this._offsetX = null;
@@ -89,16 +82,12 @@ var BABYLON;
             element.addEventListener("pointerout", this._onPointerUp);
             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("pointerdown", this._onPointerDown);
             element.removeEventListener("pointerup", this._onPointerUp);
             element.removeEventListener("pointerout", this._onPointerUp);
             element.removeEventListener("pointermove", this._onPointerMove);
-            this._attachedElement = null;
         };
         FreeCameraTouchInput.prototype.checkInputs = function () {
             if (this._offsetX) {
@@ -115,11 +104,6 @@ var BABYLON;
                 }
             }
         };
-        FreeCameraTouchInput.prototype.detach = function () {
-            if (this._attachedElement) {
-                this.detachElement(this._attachedElement);
-            }
-        };
         FreeCameraTouchInput.prototype.getTypeName = function () {
             return "FreeCameraTouchInput";
         };

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

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

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

@@ -10,21 +10,22 @@ var BABYLON;
             return this._rightjoystick;
         };
         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.setAxisForUpDown(BABYLON.JoystickAxis.Z);
             this._leftjoystick.setAxisForLeftRight(BABYLON.JoystickAxis.X);
@@ -36,8 +37,9 @@ var BABYLON;
             this._rightjoystick.setJoystickSensibility(0.05);
             this._rightjoystick.setJoystickColor("yellow");
         };
-        FreeCameraVirtualJoystickInput.prototype.detach = function () {
+        FreeCameraVirtualJoystickInput.prototype.detachControl = function (element) {
             this._leftjoystick.releaseCanvas();
+            this._rightjoystick.releaseCanvas();
         };
         FreeCameraVirtualJoystickInput.prototype.getTypeName = function () {
             return "FreeCameraVirtualJoystickInput";

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

@@ -14,24 +14,24 @@ module BABYLON {
         }
 
         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.setAxisForUpDown(JoystickAxis.Z);
             this._leftjoystick.setAxisForLeftRight(JoystickAxis.X);
@@ -44,8 +44,9 @@ module BABYLON {
             this._rightjoystick.setJoystickColor("yellow");
         }
 
-        detach() {
+        detachControl(element : HTMLElement) {
             this._leftjoystick.releaseCanvas();
+            this._rightjoystick.releaseCanvas();
         }
 
         getTypeName(): string {

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

@@ -2,13 +2,16 @@ var BABYLON;
 (function (BABYLON) {
     var FreeCameraVRDeviceOrientationInput = (function () {
         function FreeCameraVRDeviceOrientationInput() {
+            this.alphaCorrection = 1;
+            this.betaCorrection = 1;
+            this.gammaCorrection = 1;
             this._alpha = 0;
             this._beta = 0;
             this._gamma = 0;
+            this._dirty = false;
             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);
         };
         FreeCameraVRDeviceOrientationInput.prototype._onOrientationEvent = function (evt) {
@@ -16,18 +19,25 @@ var BABYLON;
             this._alpha = +evt.alpha | 0;
             this._beta = +evt.beta | 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);
         };
         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> {
         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 _deviceOrientationHandler;
@@ -13,32 +18,37 @@ module BABYLON {
             this._deviceOrientationHandler = this._onOrientationEvent.bind(this);
         }
 
-        attachCamera(camera: FreeCamera) {
-            this.camera = camera;
-
+        attachControl(element : HTMLElement, noPreventDefault?: boolean) {
             window.addEventListener("deviceorientation", this._deviceOrientationHandler);
         }
 
         public _onOrientationEvent(evt: DeviceOrientationEvent): void {
             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);
         }
 

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

@@ -10,12 +10,6 @@ var BABYLON;
         function ArcRotateCameraInputsManager(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 () {
             this.add(new BABYLON.ArcRotateCameraMouseWheelInput());
             return this;

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

@@ -4,13 +4,6 @@ module BABYLON {
             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(){
             this.add(new ArcRotateCameraMouseWheelInput());
             return this;

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

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

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

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

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

@@ -10,12 +10,6 @@ var BABYLON;
         function FreeCameraInputsManager(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 () {
             this.add(new BABYLON.FreeCameraKeyboardMoveInput());
             return this;

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

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

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

@@ -162,6 +162,7 @@ var BABYLON;
             }*/
             switch (impostorJoint.joint.type) {
                 case BABYLON.PhysicsJoint.HingeJoint:
+                case BABYLON.PhysicsJoint.Hinge2Joint:
                     constraint = new CANNON.HingeConstraint(mainBody, connectedBody, constraintData);
                     break;
                 case BABYLON.PhysicsJoint.DistanceJoint:
@@ -371,6 +372,18 @@ var BABYLON;
         CannonJSPlugin.prototype.setAngularVelocity = function (impostor, 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) {
             impostor.physicsBody.mass = mass;
             impostor.physicsBody.updateMassProperties();
@@ -381,6 +394,32 @@ var BABYLON;
         CannonJSPlugin.prototype.wakeUpBody = function (impostor) {
             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 () {
             //nothing to do, actually.
         };

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

@@ -264,6 +264,18 @@ var BABYLON;
         OimoJSPlugin.prototype.setAngularVelocity = function (impostor, velocity) {
             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) {
             var staticBody = mass === 0;
             //this will actually set the body's density and not its mass.
@@ -277,6 +289,24 @@ var BABYLON;
         OimoJSPlugin.prototype.wakeUpBody = function (impostor) {
             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 () {
             this.world.clear();
         };

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

@@ -24,6 +24,7 @@ var BABYLON;
          * default is 1/60.
          * To slow it down, enter 1/600 for example.
          * To speed it up, 1/30
+         * @param {number} newTimeStep the new timestep to apply to this world.
          */
         PhysicsEngine.prototype.setTimeStep = function (newTimeStep) {
             if (newTimeStep === void 0) { newTimeStep = 1 / 60; }
@@ -38,6 +39,11 @@ var BABYLON;
         PhysicsEngine.prototype.getPhysicsPluginName = function () {
             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) {
             this._impostors.push(impostor);
             //if no parent, generate the body
@@ -45,6 +51,11 @@ var BABYLON;
                 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) {
             var index = this._impostors.indexOf(impostor);
             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) {
             var impostorJoint = {
                 mainImpostor: mainImpostor,
                 connectedImpostor: connectedImpostor,
                 joint: joint
             };
+            joint.physicsPlugin = this._physicsPlugin;
             this._joints.push(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._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);
         };
+        PhysicsImpostor.prototype.getLinearVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getLinearVelocity(this);
+        };
         /**
          * Set the body's linear velocity.
          */
         PhysicsImpostor.prototype.setLinearVelocity = function (velocity) {
             this._physicsEngine.getPhysicsPlugin().setLinearVelocity(this, velocity);
         };
+        PhysicsImpostor.prototype.getAngularVelocity = function () {
+            return this._physicsEngine.getPhysicsPlugin().getAngularVelocity(this);
+        };
         /**
          * 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;
 (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 () {
         function PhysicsJoint(type, jointData) {
             this.type = type;
@@ -18,6 +27,21 @@ var BABYLON;
             enumerable: 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
         //Joint Types
         PhysicsJoint.DistanceJoint = 0;
@@ -29,7 +53,7 @@ var BABYLON;
         PhysicsJoint.PrismaticJoint = 5;
         //ENERGY FTW! (compare with this - http://ode-wiki.org/wiki/index.php?title=Manual:_Joint_Types_and_Functions)
         PhysicsJoint.UniversalJoint = 6;
-        PhysicsJoint.Hinge2Joint = 7;
+        PhysicsJoint.Hinge2Joint = PhysicsJoint.WheelJoint;
         //Cannon
         //Similar to a Ball-Joint. Different in params
         //TODO check!!
@@ -39,4 +63,81 @@ var BABYLON;
         return 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 = {}));