public override bool Initialize(GameHost host)
        {
            base.Initialize(host);

            Enabled.BindValueChanged(enabled =>
            {
                if (enabled)
                {
                    host.Window.MouseMove  += handleMouseEvent;
                    host.Window.MouseDown  += handleMouseEvent;
                    host.Window.MouseUp    += handleMouseEvent;
                    host.Window.MouseWheel += handleMouseEvent;

                    // polling is used to keep a valid mouse position when we aren't receiving events.
                    OpenTK.Input.MouseState?lastCursorState  = null;
                    host.InputThread.Scheduler.Add(scheduled = new ScheduledDelegate(delegate
                    {
                        // we should be getting events if the mouse is inside the window.
                        if (MouseInWindow || !host.Window.Visible || host.Window.WindowState == WindowState.Minimized)
                        {
                            return;
                        }

                        var cursorState = OpenTK.Input.Mouse.GetCursorState();

                        if (cursorState.Equals(lastCursorState))
                        {
                            return;
                        }

                        lastCursorState = cursorState;

                        var mapped = host.Window.PointToClient(new Point(cursorState.X, cursorState.Y));

                        var newState = new OpenTKPollMouseState(cursorState, host.IsActive, new Vector2(mapped.X, mapped.Y));
                        HandleState(newState, lastPollState, true);
                        lastPollState = newState;
                    }, 0, 1000.0 / 60));
                }
                else
                {
                    scheduled?.Cancel();

                    host.Window.MouseMove  -= handleMouseEvent;
                    host.Window.MouseDown  -= handleMouseEvent;
                    host.Window.MouseUp    -= handleMouseEvent;
                    host.Window.MouseWheel -= handleMouseEvent;

                    lastPollState  = null;
                    lastEventState = null;
                }
            }, true);

            return(true);
        }
        private Vector2 getUpdatedPosition(OpenTK.Input.MouseState state, OpenTKMouseState lastState)
        {
            Vector2 currentPosition;

            if ((state.Flags & MouseStateFlags.MoveAbsolute) > 0)
            {
                const int raw_input_resolution = 65536;

                if (mapAbsoluteInputToWindow)
                {
                    // map directly to local window
                    currentPosition.X = ((float)((state.X - raw_input_resolution / 2f) * sensitivity.Value) + raw_input_resolution / 2f) / raw_input_resolution * Host.Window.Width;
                    currentPosition.Y = ((float)((state.Y - raw_input_resolution / 2f) * sensitivity.Value) + raw_input_resolution / 2f) / raw_input_resolution
                                        * Host.Window.Height;
                }
                else
                {
                    Rectangle screenRect = (state.Flags & MouseStateFlags.VirtualDesktop) > 0
                        ? Platform.Windows.Native.Input.GetVirtualScreenRect()
                        : new Rectangle(0, 0, DisplayDevice.Default.Width, DisplayDevice.Default.Height);

                    // map to full screen space
                    currentPosition.X = (float)state.X / raw_input_resolution * screenRect.Width + screenRect.X;
                    currentPosition.Y = (float)state.Y / raw_input_resolution * screenRect.Height + screenRect.Y;

                    // find local window coordinates
                    var clientPos = Host.Window.PointToClient(new Point((int)Math.Round(currentPosition.X), (int)Math.Round(currentPosition.Y)));

                    // apply sensitivity from window's centre
                    currentPosition.X = (float)((clientPos.X - Host.Window.Width / 2f) * sensitivity.Value + Host.Window.Width / 2f);
                    currentPosition.Y = (float)((clientPos.Y - Host.Window.Height / 2f) * sensitivity.Value + Host.Window.Height / 2f);
                }
            }
            else
            {
                if (lastState == null)
                {
                    // when we return from being outside of the window, we want to set the new position of our game cursor
                    // to where the OS cursor is, just once.
                    var cursorState = OpenTK.Input.Mouse.GetCursorState();
                    var screenPoint = Host.Window.PointToClient(new Point(cursorState.X, cursorState.Y));
                    currentPosition = new Vector2(screenPoint.X, screenPoint.Y);
                }
                else
                {
                    currentPosition = lastState.Position + new Vector2(state.X - lastState.RawState.X, state.Y - lastState.RawState.Y) * (float)sensitivity.Value;
                }
            }

            return(currentPosition);
        }
        private void handleMouseEvent(object sender, OpenTK.Input.MouseEventArgs e)
        {
            if (!MouseInWindow)
            {
                return;
            }

            if (e.Mouse.X < 0 || e.Mouse.Y < 0)
            {
                // todo: investigate further why we are getting negative values from OpenTK events
                // on windows when crossing centre screen boundaries (width/2 or height/2).
                return;
            }

            var newState = new OpenTKEventMouseState(e.Mouse, Host.IsActive, null);

            HandleState(newState, lastEventState, true);
            lastEventState = newState;
        }
示例#4
0
        protected void HandleState(OpenTKMouseState state, OpenTKMouseState lastState, bool isAbsolutePosition)
        {
            if (lastState == null || isAbsolutePosition)
            {
                PendingInputs.Enqueue(new MousePositionAbsoluteInput {
                    Position = state.Position
                });
                currentPosition = state.Position;
            }
            else
            {
                var delta = state.Position - lastState.Position;
                if (delta != Vector2.Zero)
                {
                    PendingInputs.Enqueue(new MousePositionRelativeInput {
                        Delta = delta
                    });
                    currentPosition += delta;
                }
            }

            if (lastState != null)
            {
                var scrollDelta = state.Scroll - lastState.Scroll;
                if (scrollDelta != Vector2.Zero)
                {
                    PendingInputs.Enqueue(new MouseScrollRelativeInput {
                        Delta = scrollDelta, IsPrecise = state.HasPreciseScroll
                    });
                }
            }

            PendingInputs.Enqueue(new MouseButtonInput(state.Buttons, lastState?.Buttons));

            FrameStatistics.Increment(StatisticsCounterType.MouseEvents);
        }
        public override bool Initialize(GameHost host)
        {
            base.Initialize(host);

            // Get the bindables we need to determine whether to confine the mouse to window or not
            if (host.Window is DesktopGameWindow desktopWindow)
            {
                confineMode.BindTo(desktopWindow.ConfineMouseMode);
                windowMode.BindTo(desktopWindow.WindowMode);
                mapAbsoluteInputToWindow.BindTo(desktopWindow.MapAbsoluteInputToWindow);
            }

            Enabled.ValueChanged += enabled =>
            {
                if (enabled)
                {
                    host.InputThread.Scheduler.Add(scheduled = new ScheduledDelegate(delegate
                    {
                        if (!host.Window.Visible || host.Window.WindowState == WindowState.Minimized)
                        {
                            return;
                        }

                        if ((MouseInWindow || lastEachDeviceStates.Any(s => s != null && s.HasAnyButtonPressed)) && host.Window.Focused)
                        {
                            var newRawStates = new List <OpenTK.Input.MouseState>(mostSeenStates + 1);

                            for (int i = 0; i <= mostSeenStates + 1; i++)
                            {
                                var s = OpenTK.Input.Mouse.GetState(i);
                                if (s.IsConnected || i < mostSeenStates)
                                {
                                    newRawStates.Add(s);
                                    mostSeenStates = i;
                                }
                            }

                            while (lastEachDeviceStates.Count < newRawStates.Count)
                            {
                                lastEachDeviceStates.Add(null);
                            }

                            for (int i = 0; i < newRawStates.Count; i++)
                            {
                                if (newRawStates[i].IsConnected != true)
                                {
                                    lastEachDeviceStates[i] = null;
                                    continue;
                                }

                                var rawState  = newRawStates[i];
                                var lastState = lastEachDeviceStates[i];

                                if (lastState != null && rawState.Equals(lastState.RawState))
                                {
                                    continue;
                                }

                                var newState = new OpenTKPollMouseState(rawState, host.IsActive, getUpdatedPosition(rawState, lastState));

                                HandleState(newState, lastState, (rawState.Flags & MouseStateFlags.MoveAbsolute) > 0);

                                lastEachDeviceStates[i] = newState;
                                lastUnfocusedState      = null;
                            }
                        }
                        else
                        {
                            var state       = OpenTK.Input.Mouse.GetCursorState();
                            var screenPoint = host.Window.PointToClient(new Point(state.X, state.Y));

                            var newState = new UnfocusedMouseState(new OpenTK.Input.MouseState(), host.IsActive, new Vector2(screenPoint.X, screenPoint.Y));

                            HandleState(newState, lastUnfocusedState, true);

                            lastUnfocusedState = newState;
                            lastEachDeviceStates.Clear();
                        }
                    }, 0, 0));
                }
                else
                {
                    scheduled?.Cancel();
                    lastEachDeviceStates.Clear();
                    lastUnfocusedState = null;
                }
            };

            Enabled.TriggerChange();
            return(true);
        }
示例#6
0
        private Vector2 getUpdatedPosition(OpenTK.Input.MouseState state, OpenTKMouseState lastState)
        {
            Vector2 currentPosition;

            if ((state.RawFlags & RawMouseFlags.MOUSE_MOVE_ABSOLUTE) > 0)
            {
                const int raw_input_resolution = 65536;

                if (mapAbsoluteInputToWindow)
                {
                    // map directly to local window
                    currentPosition.X = ((float)((state.X - raw_input_resolution / 2f) * sensitivity.Value) + raw_input_resolution / 2f) / raw_input_resolution * host.Window.Width;
                    currentPosition.Y = ((float)((state.Y - raw_input_resolution / 2f) * sensitivity.Value) + raw_input_resolution / 2f) / raw_input_resolution
                                        * host.Window.Height;
                }
                else
                {
                    Rectangle screenRect = (state.RawFlags & RawMouseFlags.MOUSE_VIRTUAL_DESKTOP) > 0
                        ? Platform.Windows.Native.Input.GetVirtualScreenRect()
                        : new Rectangle(0, 0, DisplayDevice.Default.Width, DisplayDevice.Default.Height);

                    // map to full screen space
                    currentPosition.X = (float)state.X / raw_input_resolution * screenRect.Width + screenRect.X;
                    currentPosition.Y = (float)state.Y / raw_input_resolution * screenRect.Height + screenRect.Y;

                    // find local window coordinates
                    var clientPos = host.Window.PointToClient(new Point((int)Math.Round(currentPosition.X), (int)Math.Round(currentPosition.Y)));

                    // apply sensitivity from window's centre
                    currentPosition.X = (float)((clientPos.X - host.Window.Width / 2f) * sensitivity.Value + host.Window.Width / 2f);
                    currentPosition.Y = (float)((clientPos.Y - host.Window.Height / 2f) * sensitivity.Value + host.Window.Height / 2f);
                }
            }
            else
            {
                if (lastState == null)
                {
                    // when we return from being outside of the window, we want to set the new position of our game cursor
                    // to where the OS cursor is, just once.
                    var cursorState = OpenTK.Input.Mouse.GetCursorState();
                    var screenPoint = host.Window.PointToClient(new Point(cursorState.X, cursorState.Y));
                    currentPosition = new Vector2(screenPoint.X, screenPoint.Y);
                }
                else
                {
                    currentPosition = lastState.Position + new Vector2(state.X - lastState.RawState.X, state.Y - lastState.RawState.Y) * (float)sensitivity.Value;

                    // When confining, clamp to the window size.
                    if (confineMode.Value == ConfineMouseMode.Always || confineMode.Value == ConfineMouseMode.Fullscreen && windowMode.Value == WindowMode.Fullscreen)
                    {
                        currentPosition = Vector2.Clamp(currentPosition, Vector2.Zero, new Vector2(host.Window.Width, host.Window.Height));
                    }

                    // update the windows cursor to match our raw cursor position.
                    // this is important when sensitivity is decreased below 1.0, where we need to ensure the cursor stays within the window.
                    var screenPoint = host.Window.PointToScreen(new Point((int)currentPosition.X, (int)currentPosition.Y));
                    OpenTK.Input.Mouse.SetPosition(screenPoint.X, screenPoint.Y);
                }
            }

            return(currentPosition);
        }