private void SetFreeLook()
        {
            if (!Viewport.IsUnlocked(this))
            {
                return;
            }
            FreeLook = false;

            if (FreeLookToggle)
            {
                FreeLook = true;
            }
            else
            {
                var left  = Control.MouseButtons.HasFlag(MouseButtons.Left);
                var right = Control.MouseButtons.HasFlag(MouseButtons.Right);

                if (ToolManager.ActiveTool is CameraTool)
                {
                    FreeLook = left || right;
                }
                else
                {
                    var space = KeyboardState.IsKeyDown(Keys.Space);
                    var req   = Sledge.Settings.View.Camera3DPanRequiresMouseClick;
                    FreeLook = space && (!req || left || right);
                }
            }

            if (FreeLook && CursorVisible)
            {
                CursorClip       = Cursor.Clip;
                Cursor.Clip      = Viewport.RectangleToScreen(new Rectangle(0, 0, Viewport.Width, Viewport.Height));
                Viewport.Capture = true;
                CursorVisible    = false;
                Cursor.Hide();
                Viewport.AquireInputLock(this);
            }
            else if (!FreeLook && !CursorVisible)
            {
                Cursor.Clip      = CursorClip;
                CursorClip       = Rectangle.Empty;
                Viewport.Capture = false;
                CursorVisible    = true;
                Cursor.Show();
                Viewport.ReleaseInputLock(this);
            }
        }
 private void IfKey(Keys key, Action action, bool ignoreKeyboard)
 {
     if (!KeyboardState.IsKeyDown(key))
     {
         _downKeys.Remove(key);
     }
     else if (ignoreKeyboard)
     {
         if (_downKeys.Contains(key))
         {
             action();
         }
     }
     else
     {
         if (!_downKeys.Contains(key))
         {
             _downKeys.Add(key);
         }
         action();
     }
 }
        public void UpdateFrame(FrameInfo frame)
        {
            var currMillis = _lastMillis;

            _lastMillis = frame.Milliseconds;

            if (currMillis == 0)
            {
                return;
            }
            if (!Focus || !Viewport.IsUnlocked(this))
            {
                return;
            }

            var seconds = (frame.Milliseconds - currMillis) / 1000m;
            var units   = Sledge.Settings.View.ForwardSpeed * seconds;

            var down = KeyboardState.IsAnyKeyDown(Keys.W, Keys.A, Keys.S, Keys.D);

            if (!down)
            {
                _downMillis = 0;
            }
            else if (_downMillis == 0)
            {
                _downMillis = currMillis;
            }

            if (Sledge.Settings.View.TimeToTopSpeed > 0)
            {
                var downFor = (frame.Milliseconds - _downMillis) / Sledge.Settings.View.TimeToTopSpeed;
                if (downFor >= 0 && downFor < 1)
                {
                    units *= _easing.Evaluate(downFor);
                }
            }

            var move = units;
            var tilt = 2m;

            // These keys are used for hotkeys, don't want the 3D view to move about when trying to use hotkeys.
            var ignore = KeyboardState.IsAnyKeyDown(Keys.ShiftKey, Keys.ControlKey, Keys.Alt);

            IfKey(Keys.W, () => Camera.Advance(move), ignore);
            IfKey(Keys.S, () => Camera.Advance(-move), ignore);
            IfKey(Keys.A, () => Camera.Strafe(-move), ignore);
            IfKey(Keys.D, () => Camera.Strafe(move), ignore);
            IfKey(Keys.Q, () => Camera.AscendAbsolute(move), ignore);
            IfKey(Keys.E, () => Camera.AscendAbsolute(-move), ignore);

            // Arrow keys are not really used for hotkeys all that much, so we allow shift+arrows to match Hammer's keys
            var shiftDown = KeyboardState.IsKeyDown(Keys.ShiftKey);
            var otherDown = KeyboardState.IsAnyKeyDown(Keys.ControlKey, Keys.Alt);

            IfKey(Keys.Right, () => { if (shiftDown)
                                      {
                                          Camera.Strafe(move);
                                      }
                                      else
                                      {
                                          Camera.Pan(-tilt);
                                      } }, otherDown);
            IfKey(Keys.Left, () => { if (shiftDown)
                                     {
                                         Camera.Strafe(-move);
                                     }
                                     else
                                     {
                                         Camera.Pan(tilt);
                                     } }, otherDown);
            IfKey(Keys.Up, () => { if (shiftDown)
                                   {
                                       Camera.Ascend(move);
                                   }
                                   else
                                   {
                                       Camera.Tilt(-tilt);
                                   } }, otherDown);
            IfKey(Keys.Down, () => { if (shiftDown)
                                     {
                                         Camera.Ascend(-move);
                                     }
                                     else
                                     {
                                         Camera.Tilt(tilt);
                                     } }, otherDown);
        }