public override bool Initialize(GameHost host) { base.Initialize(host); Enabled.BindValueChanged(e => { var tkWin = (OsuTKWindow)host.Window; if (e.NewValue) { tkWin.MouseMove += handleMouseEvent; tkWin.MouseDown += handleMouseEvent; tkWin.MouseUp += handleMouseEvent; tkWin.MouseWheel += handleMouseEvent; // polling is used to keep a valid mouse position when we aren't receiving events. osuTK.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.Value || !tkWin.Visible || tkWin.WindowState.ToOsuTK() == osuTK.WindowState.Minimized) { return; } var cursorState = osuTK.Input.Mouse.GetCursorState(); if (lastCursorState != null && cursorState.Equals(lastCursorState.Value)) { return; } lastCursorState = cursorState; var mapped = tkWin.PointToClient(new Point(cursorState.X, cursorState.Y)); var newState = new OsuTKPollMouseState(cursorState, host.IsActive.Value, new Vector2(mapped.X, mapped.Y)); HandleState(newState, lastPollState, true); lastPollState = newState; }, 0, 1000.0 / 60)); } else { scheduled?.Cancel(); tkWin.MouseMove -= handleMouseEvent; tkWin.MouseDown -= handleMouseEvent; tkWin.MouseUp -= handleMouseEvent; tkWin.MouseWheel -= handleMouseEvent; lastPollState = null; lastEventState = null; } }, true); return(true); }
private Vector2 getUpdatedPosition(MouseState state, OsuTKMouseState lastState) { Vector2 currentPosition; if (state.Flags.HasFlag(MouseStateFlags.MoveAbsolute)) { 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.HasFlag(MouseStateFlags.VirtualDesktop) ? 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 = osuTK.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, osuTK.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 osuTK events // on windows when crossing centre screen boundaries (width/2 or height/2). return; } var newState = new OsuTKEventMouseState(e.Mouse, Host.IsActive, null); HandleState(newState, lastEventState, true); lastEventState = newState; }
protected void HandleState(OsuTKMouseState state, OsuTKMouseState 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 && state.WasActive) { 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.BindValueChanged(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.Buttons.HasAnyButtonPressed)) && host.Window.Focused) { osuTK.Input.Mouse.GetStates(newRawStates); 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 OsuTKPollMouseState(rawState, host.IsActive, getUpdatedPosition(rawState, lastState)); HandleState(newState, lastState, rawState.Flags.HasFlag(MouseStateFlags.MoveAbsolute)); lastEachDeviceStates[i] = newState; lastUnfocusedState = null; } } else { var state = osuTK.Input.Mouse.GetCursorState(); var screenPoint = host.Window.PointToClient(new Point(state.X, state.Y)); var newState = new UnfocusedMouseState(new 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; } }, true); return(true); }