(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "three"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("three"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.three);
    global.FlyControls = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.FlyControls = void 0;

  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } Object.defineProperty(subClass, "prototype", { value: Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }), writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }

  function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }

  function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }

  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

  function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }

  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

  var _changeEvent = {
    type: 'change'
  };

  var FlyControls = /*#__PURE__*/function (_EventDispatcher) {
    _inherits(FlyControls, _EventDispatcher);

    var _super = _createSuper(FlyControls);

    function FlyControls(object, domElement) {
      var _this;

      _classCallCheck(this, FlyControls);

      _this = _super.call(this);

      if (domElement === undefined) {
        console.warn('THREE.FlyControls: The second parameter "domElement" is now mandatory.');
        domElement = document;
      }

      _this.object = object;
      _this.domElement = domElement; // API

      _this.movementSpeed = 1.0;
      _this.rollSpeed = 0.005;
      _this.dragToLook = false;
      _this.autoForward = false; // disable default target object behavior
      // internals

      var scope = _assertThisInitialized(_this);

      var EPS = 0.000001;
      var lastQuaternion = new _three.Quaternion();
      var lastPosition = new _three.Vector3();
      _this.tmpQuaternion = new _three.Quaternion();
      _this.mouseStatus = 0;
      _this.moveState = {
        up: 0,
        down: 0,
        left: 0,
        right: 0,
        forward: 0,
        back: 0,
        pitchUp: 0,
        pitchDown: 0,
        yawLeft: 0,
        yawRight: 0,
        rollLeft: 0,
        rollRight: 0
      };
      _this.moveVector = new _three.Vector3(0, 0, 0);
      _this.rotationVector = new _three.Vector3(0, 0, 0);

      _this.keydown = function (event) {
        if (event.altKey) {
          return;
        }

        switch (event.code) {
          case 'ShiftLeft':
          case 'ShiftRight':
            this.movementSpeedMultiplier = .1;
            break;

          case 'KeyW':
            this.moveState.forward = 1;
            break;

          case 'KeyS':
            this.moveState.back = 1;
            break;

          case 'KeyA':
            this.moveState.left = 1;
            break;

          case 'KeyD':
            this.moveState.right = 1;
            break;

          case 'KeyR':
            this.moveState.up = 1;
            break;

          case 'KeyF':
            this.moveState.down = 1;
            break;

          case 'ArrowUp':
            this.moveState.pitchUp = 1;
            break;

          case 'ArrowDown':
            this.moveState.pitchDown = 1;
            break;

          case 'ArrowLeft':
            this.moveState.yawLeft = 1;
            break;

          case 'ArrowRight':
            this.moveState.yawRight = 1;
            break;

          case 'KeyQ':
            this.moveState.rollLeft = 1;
            break;

          case 'KeyE':
            this.moveState.rollRight = 1;
            break;
        }

        this.updateMovementVector();
        this.updateRotationVector();
      };

      _this.keyup = function (event) {
        switch (event.code) {
          case 'ShiftLeft':
          case 'ShiftRight':
            this.movementSpeedMultiplier = 1;
            break;

          case 'KeyW':
            this.moveState.forward = 0;
            break;

          case 'KeyS':
            this.moveState.back = 0;
            break;

          case 'KeyA':
            this.moveState.left = 0;
            break;

          case 'KeyD':
            this.moveState.right = 0;
            break;

          case 'KeyR':
            this.moveState.up = 0;
            break;

          case 'KeyF':
            this.moveState.down = 0;
            break;

          case 'ArrowUp':
            this.moveState.pitchUp = 0;
            break;

          case 'ArrowDown':
            this.moveState.pitchDown = 0;
            break;

          case 'ArrowLeft':
            this.moveState.yawLeft = 0;
            break;

          case 'ArrowRight':
            this.moveState.yawRight = 0;
            break;

          case 'KeyQ':
            this.moveState.rollLeft = 0;
            break;

          case 'KeyE':
            this.moveState.rollRight = 0;
            break;
        }

        this.updateMovementVector();
        this.updateRotationVector();
      };

      _this.mousedown = function (event) {
        if (this.dragToLook) {
          this.mouseStatus++;
        } else {
          switch (event.button) {
            case 0:
              this.moveState.forward = 1;
              break;

            case 2:
              this.moveState.back = 1;
              break;
          }

          this.updateMovementVector();
        }
      };

      _this.mousemove = function (event) {
        if (!this.dragToLook || this.mouseStatus > 0) {
          var container = this.getContainerDimensions();
          var halfWidth = container.size[0] / 2;
          var halfHeight = container.size[1] / 2;
          this.moveState.yawLeft = -(event.pageX - container.offset[0] - halfWidth) / halfWidth;
          this.moveState.pitchDown = (event.pageY - container.offset[1] - halfHeight) / halfHeight;
          this.updateRotationVector();
        }
      };

      _this.mouseup = function (event) {
        if (this.dragToLook) {
          this.mouseStatus--;
          this.moveState.yawLeft = this.moveState.pitchDown = 0;
        } else {
          switch (event.button) {
            case 0:
              this.moveState.forward = 0;
              break;

            case 2:
              this.moveState.back = 0;
              break;
          }

          this.updateMovementVector();
        }

        this.updateRotationVector();
      };

      _this.update = function (delta) {
        var moveMult = delta * scope.movementSpeed;
        var rotMult = delta * scope.rollSpeed;
        scope.object.translateX(scope.moveVector.x * moveMult);
        scope.object.translateY(scope.moveVector.y * moveMult);
        scope.object.translateZ(scope.moveVector.z * moveMult);
        scope.tmpQuaternion.set(scope.rotationVector.x * rotMult, scope.rotationVector.y * rotMult, scope.rotationVector.z * rotMult, 1).normalize();
        scope.object.quaternion.multiply(scope.tmpQuaternion);

        if (lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
          scope.dispatchEvent(_changeEvent);
          lastQuaternion.copy(scope.object.quaternion);
          lastPosition.copy(scope.object.position);
        }
      };

      _this.updateMovementVector = function () {
        var forward = this.moveState.forward || this.autoForward && !this.moveState.back ? 1 : 0;
        this.moveVector.x = -this.moveState.left + this.moveState.right;
        this.moveVector.y = -this.moveState.down + this.moveState.up;
        this.moveVector.z = -forward + this.moveState.back; //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
      };

      _this.updateRotationVector = function () {
        this.rotationVector.x = -this.moveState.pitchDown + this.moveState.pitchUp;
        this.rotationVector.y = -this.moveState.yawRight + this.moveState.yawLeft;
        this.rotationVector.z = -this.moveState.rollRight + this.moveState.rollLeft; //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
      };

      _this.getContainerDimensions = function () {
        if (this.domElement != document) {
          return {
            size: [this.domElement.offsetWidth, this.domElement.offsetHeight],
            offset: [this.domElement.offsetLeft, this.domElement.offsetTop]
          };
        } else {
          return {
            size: [window.innerWidth, window.innerHeight],
            offset: [0, 0]
          };
        }
      };

      _this.dispose = function () {
        this.domElement.removeEventListener('contextmenu', contextmenu);
        this.domElement.removeEventListener('mousedown', _mousedown);
        this.domElement.removeEventListener('mousemove', _mousemove);
        this.domElement.removeEventListener('mouseup', _mouseup);
        window.removeEventListener('keydown', _keydown);
        window.removeEventListener('keyup', _keyup);
      };

      var _mousemove = _this.mousemove.bind(_assertThisInitialized(_this));

      var _mousedown = _this.mousedown.bind(_assertThisInitialized(_this));

      var _mouseup = _this.mouseup.bind(_assertThisInitialized(_this));

      var _keydown = _this.keydown.bind(_assertThisInitialized(_this));

      var _keyup = _this.keyup.bind(_assertThisInitialized(_this));

      _this.domElement.addEventListener('contextmenu', contextmenu);

      _this.domElement.addEventListener('mousemove', _mousemove);

      _this.domElement.addEventListener('mousedown', _mousedown);

      _this.domElement.addEventListener('mouseup', _mouseup);

      window.addEventListener('keydown', _keydown);
      window.addEventListener('keyup', _keyup);

      _this.updateMovementVector();

      _this.updateRotationVector();

      return _this;
    }

    return _createClass(FlyControls);
  }(_three.EventDispatcher);

  _exports.FlyControls = FlyControls;

  function contextmenu(event) {
    event.preventDefault();
  }
});