Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
InputManager.Windows.Desktop.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 
4 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
5 
6 using System;
7 using System.Diagnostics;
8 using System.Windows;
9 using System.Windows.Forms;
10 
11 using SiliconStudio.Core;
12 using SiliconStudio.Paradox.Games;
14 
15 namespace SiliconStudio.Paradox.Input
16 {
17  public partial class InputManager
18  {
19  private Control uiControl;
20  private Stopwatch pointerClock;
21 
22  public InputManager(IServiceRegistry registry) : base(registry)
23  {
24  HasKeyboard = true;
25  HasMouse = true;
26  HasPointer = true;
27 
28  pointerClock = new Stopwatch();
29 
30  GamePadFactories.Add(new XInputGamePadFactory());
31  GamePadFactories.Add(new DirectInputGamePadFactory());
32  }
33 
34  public override void Initialize()
35  {
36  base.Initialize();
37 
38  switch (Game.Context.ContextType)
39  {
40  case AppContextType.Desktop:
41  InitializeFromWindowsForms(Game.Context);
42  break;
43  case AppContextType.DesktopWpf:
44  InitializeFromWindowsWpf(Game.Context);
45  break;
46 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL
47  case AppContextType.DesktopOpenTK:
48  InitializeFromOpenTK(Game.Context);
49  break;
50 #endif
51  default:
52  throw new ArgumentException(string.Format("WindowContext [{0}] not supported", Game.Context.ContextType));
53  }
54 
55  // Scan all registered inputs
56  Scan();
57  }
58 
59  private void InitializeFromWindowsForms(GameContext uiContext)
60  {
61  uiControl = (Control) uiContext.Control;
62 
63  pointerClock.Restart();
64 
65  BindRawInputKeyboard(uiControl);
66 
67  uiControl.MouseEnter += (_, e) => uiControl.Focus();
68  uiControl.MouseMove += (_, e) => OnMouseMoveEvent(new Vector2(e.X, e.Y));
69  uiControl.MouseDown += (_, e) => OnMouseInputEvent(new Vector2(e.X, e.Y), ConvertMouseButton(e.Button), InputEventType.Down);
70  uiControl.MouseUp += (_, e) => OnMouseInputEvent(new Vector2(e.X, e.Y), ConvertMouseButton(e.Button), InputEventType.Up);
71  uiControl.MouseWheel += (_, e) => OnMouseInputEvent(new Vector2(e.X, e.Y), MouseButton.Middle, InputEventType.Wheel, e.Delta);
72  uiControl.MouseLeave += (_, e) => OnMouseLeaveEvent();
73  uiControl.SizeChanged += UiControlOnSizeChanged;
74 
75  ControlWidth = uiControl.ClientSize.Width;
76  ControlHeight = uiControl.ClientSize.Height;
77  }
78 
79  private void InitializeFromWindowsWpf(GameContext uiContext)
80  {
81  var uiControlWpf = (Window)uiContext.Control;
82 
83  var inputElement = uiControlWpf;
84 
85  BindRawInputKeyboard(uiControl);
86  uiControlWpf.Deactivated += OnUiControlLostFocus;
87  uiControlWpf.MouseMove += (_, e) => OnMouseMoveEvent(PointToVector2(e.GetPosition(inputElement)));
88  uiControlWpf.MouseDown += (_, e) => OnMouseInputEvent(PointToVector2(e.GetPosition(inputElement)), ConvertMouseButton(e.ChangedButton), InputEventType.Down);
89  uiControlWpf.MouseUp += (_, e) => OnMouseInputEvent(PointToVector2(e.GetPosition(inputElement)), ConvertMouseButton(e.ChangedButton), InputEventType.Up);
90  uiControlWpf.MouseWheel += (_, e) => OnMouseInputEvent(PointToVector2(e.GetPosition(inputElement)), MouseButton.Middle, InputEventType.Wheel, e.Delta);
91  uiControlWpf.MouseLeave += (_, e) => OnMouseLeaveEvent();
92  uiControlWpf.SizeChanged += OnWpfSizeChanged;
93 
94  ControlWidth = (float)uiControlWpf.ActualWidth;
95  ControlHeight = (float)uiControlWpf.ActualHeight;
96  }
97 
98  private void UiControlOnSizeChanged(object sender, EventArgs eventArgs)
99  {
100  ControlWidth = uiControl.ClientSize.Width;
101  ControlHeight = uiControl.ClientSize.Height;
102  }
103 
104  private void OnWpfSizeChanged(object sender, SizeChangedEventArgs e)
105  {
106  ControlWidth = (float)e.NewSize.Width;
107  ControlHeight = (float)e.NewSize.Height;
108  }
109 
110  private void OnMouseInputEvent(Vector2 pixelPosition, MouseButton button, InputEventType type, float value = 0)
111  {
112  // The mouse wheel event are still received even when the mouse cursor is out of the control boundaries. Discard the event in this case.
113  if (!uiControl.ClientRectangle.Contains(uiControl.PointToClient(Control.MousePosition)))
114  return;
115 
116  // the mouse events series has been interrupted because out of the window.
117  if (type == InputEventType.Up && !MouseButtonCurrentlyDown[(int)button])
118  return;
119 
120  CurrentMousePosition = NormalizeScreenPosition(pixelPosition);
121 
122  var mouseInputEvent = new MouseInputEvent { Type = type, MouseButton = button, Value = value};
123  lock (MouseInputEvents)
124  MouseInputEvents.Add(mouseInputEvent);
125 
126  if (type != InputEventType.Wheel)
127  {
128  var buttonId = (int)button;
129  MouseButtonCurrentlyDown[buttonId] = type == InputEventType.Down;
130  HandlePointerEvents(buttonId, CurrentMousePosition, InputEventTypeToPointerState(type), PointerType.Mouse);
131  }
132  }
133 
134  private void OnMouseMoveEvent(Vector2 pixelPosition)
135  {
136  CurrentMousePosition = NormalizeScreenPosition(pixelPosition);
137 
138  // trigger touch move events
139  foreach (MouseButton button in Enum.GetValues(typeof(MouseButton)))
140  {
141  var buttonId = (int)button;
142  if (MouseButtonCurrentlyDown[buttonId])
143  HandlePointerEvents(buttonId, CurrentMousePosition, PointerState.Move, PointerType.Mouse);
144  }
145  }
146 
147  private void OnMouseLeaveEvent()
148  {
149  if (HasDownMouseButtons())
150  LostFocus = true;
151 
152  // trigger touch leave events
153  foreach (MouseButton button in Enum.GetValues(typeof(MouseButton)))
154  {
155  var buttonId = (int)button;
156  if (MouseButtonCurrentlyDown[buttonId])
157  {
158  HandlePointerEvents(buttonId, PointerInfos[buttonId].LastPosition, PointerState.Out, PointerType.Mouse);
159 
160  MouseButtonCurrentlyDown[buttonId] = false;
161  }
162  }
163  }
164 
165  private void OnUiControlLostFocus(object sender, EventArgs e)
166  {
167  LostFocus = true;
168  }
169 
170  private MouseButton ConvertMouseButton(MouseButtons mouseButton)
171  {
172  switch (mouseButton)
173  {
174  case MouseButtons.Left:
175  return MouseButton.Left;
176  case MouseButtons.Right:
177  return MouseButton.Right;
178  case MouseButtons.Middle:
179  return MouseButton.Middle;
180  case MouseButtons.XButton1:
181  return MouseButton.Extended1;
182  case MouseButtons.XButton2:
183  return MouseButton.Extended2;
184  }
185  return (MouseButton)(-1);
186  }
187 
188  private MouseButton ConvertMouseButton(System.Windows.Input.MouseButton mouseButton)
189  {
190  switch (mouseButton)
191  {
192  case System.Windows.Input.MouseButton.Left:
193  return MouseButton.Left;
194  case System.Windows.Input.MouseButton.Right:
195  return MouseButton.Right;
196  case System.Windows.Input.MouseButton.Middle:
197  return MouseButton.Middle;
198  case System.Windows.Input.MouseButton.XButton1:
199  return MouseButton.Extended1;
200  case System.Windows.Input.MouseButton.XButton2:
201  return MouseButton.Extended2;
202  }
203  return (MouseButton)(-1);
204  }
205 
206  private PointerState InputEventTypeToPointerState(InputEventType type)
207  {
208  switch (type)
209  {
210  case InputEventType.Up:
211  return PointerState.Up;
212  case InputEventType.Down:
213  return PointerState.Down;
214  default:
215  throw new ArgumentOutOfRangeException("type");
216  }
217  }
218 
219  private Vector2 PointToVector2(Point point)
220  {
221  return new Vector2((float)point.X, (float)point.Y);
222  }
223 
224  // There is no multi-touch on windows, so there is nothing specific to do.
225  public override bool MultiTouchEnabled { get; set; }
226  }
227 }
228 #endif
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
PointerType
Type of a pointer device.
Definition: PointerType.cs:8
MouseButton
Mouse buttons.
Definition: MouseButton.cs:10
SiliconStudio.Core.IServiceRegistry IServiceRegistry
Definition: ModelRenderer.cs:9
PointerState
State of a pointer event.
Definition: PointerState.cs:8
The type of the serialized type will be passed as a generic arguments of the serializer. Example: serializer of A becomes instantiated as Serializer{A}.
System.Windows.Point Point
Definition: ColorPicker.cs:15