4 using System.Collections.Generic;
5 using System.Collections.Specialized;
6 using System.Diagnostics;
9 using SiliconStudio.Core;
10 using SiliconStudio.Core.Collections;
11 using SiliconStudio.Core.Diagnostics;
12 using SiliconStudio.Paradox.Games;
13 using SiliconStudio.Core.Mathematics;
15 namespace SiliconStudio.
Paradox.Input
22 #region Constants and Fields
26 internal const float GamePadAxisDeadZone = 0.01f;
28 internal readonly List<GamePadFactory> GamePadFactories =
new List<GamePadFactory>();
30 private const int MaximumGamePadCount = 8;
34 private readonly
GamePad[] gamePads;
36 private int gamePadCount;
38 private readonly List<Keys> downKeysList =
new List<Keys>();
40 private readonly HashSet<Keys> pressedKeysSet =
new HashSet<Keys>();
42 private readonly HashSet<Keys> releasedKeysSet =
new HashSet<Keys>();
44 internal List<KeyboardInputEvent> KeyboardInputEvents =
new List<KeyboardInputEvent>();
46 internal bool LostFocus;
48 internal List<MouseInputEvent> MouseInputEvents =
new List<MouseInputEvent>();
50 internal Vector2 CurrentMousePosition;
52 private readonly Dictionary<Keys, bool> activeKeys =
new Dictionary<Keys, bool>();
54 private const int NumberOfMouseButtons = 5;
56 private readonly
bool[] mouseButtons =
new bool[NumberOfMouseButtons];
58 private readonly
bool[] mouseButtonsPrevious =
new bool[NumberOfMouseButtons];
63 internal readonly
bool[] MouseButtonCurrentlyDown =
new bool[NumberOfMouseButtons];
65 private readonly List<Dictionary<object, float>> virtualButtonValues =
new List<Dictionary<object, float>>();
67 private readonly List<PointerEvent> pointerEvents =
new List<PointerEvent>();
69 private readonly List<PointerEvent> currentPointerEvents =
new List<PointerEvent>();
71 private readonly List<GestureEvent> currentGestureEvents =
new List<GestureEvent>();
73 private readonly Dictionary<GestureConfig, GestureRecognizer> gestureConfigToRecognizer =
new Dictionary<GestureConfig, GestureRecognizer>();
85 internal readonly Dictionary<int, PointerInfo> PointerInfos =
new Dictionary<int, PointerInfo>();
90 public float MouseWheelDelta {
get;
private set; }
95 internal float ControlWidth
97 get {
return controlWidth; }
100 controlWidth = Math.Max(0, value);
102 if (controlHeight > 0)
103 ScreenAspectRatio = ControlWidth / ControlHeight;
107 private float controlWidth;
112 internal float ControlHeight
114 get {
return controlHeight; }
117 controlHeight = Math.Max(0, value);
119 if (controlHeight > 0)
120 ScreenAspectRatio = ControlWidth / ControlHeight;
123 private float controlHeight;
125 internal float ScreenAspectRatio
127 get {
return screenAspectRatio; }
130 screenAspectRatio = value;
132 foreach (var recognizer
in gestureConfigToRecognizer.Values)
133 recognizer.ScreenRatio = ScreenAspectRatio;
137 private float screenAspectRatio;
141 internal class PointerInfo
143 public readonly Stopwatch PointerClock =
new Stopwatch();
150 gamePads =
new GamePad[MaximumGamePadCount];
151 gamePadStates =
new GamePadState[MaximumGamePadCount];
153 KeyDown = downKeysList;
154 KeyEvents =
new List<KeyEvent>();
155 PointerEvents = currentPointerEvents;
156 GestureEvents = currentGestureEvents;
158 ActivatedGestures =
new GestureConfigCollection();
159 ActivatedGestures.CollectionChanged += ActivatedGesturesChanged;
161 Services.AddService(typeof(InputManager),
this);
166 switch (trackingCollectionChangedEventArgs.
Action)
168 case NotifyCollectionChangedAction.Add:
169 StartGestureRecognition((GestureConfig)trackingCollectionChangedEventArgs.
Item);
171 case NotifyCollectionChangedAction.Remove:
172 StopGestureRecognition((GestureConfig)trackingCollectionChangedEventArgs.
Item);
174 case NotifyCollectionChangedAction.Replace:
175 case NotifyCollectionChangedAction.Reset:
176 throw new NotSupportedException(
"ActivatedGestures collection was modified but the action was not supported by the system.");
177 case NotifyCollectionChangedAction.Move:
180 throw new ArgumentOutOfRangeException();
184 private void StartGestureRecognition(GestureConfig config)
186 gestureConfigToRecognizer.Add(config, config.CreateRecognizer(ScreenAspectRatio));
189 private void StopGestureRecognition(GestureConfig config)
191 gestureConfigToRecognizer.Remove(config);
196 return new Vector2(pixelPosition.
X / ControlWidth, pixelPosition.
Y / ControlHeight);
203 if (!PointerInfos.ContainsKey(pointerId))
204 PointerInfos[pointerId] =
new PointerInfo();
206 var pointerInfo = PointerInfos[pointerId];
210 pointerInfo.LastPosition = newPosition;
211 pointerInfo.PointerClock.Restart();
214 var pointerEvent = PointerEvent.GetOrCreatePointerEvent();
216 pointerEvent.PointerId = pointerId;
217 pointerEvent.Position = newPosition;
218 pointerEvent.DeltaPosition = newPosition - pointerInfo.LastPosition;
219 pointerEvent.DeltaTime = pointerInfo.PointerClock.Elapsed;
220 pointerEvent.State = pState;
221 pointerEvent.PointerType = pointerType;
222 pointerEvent.IsPrimary = pointerId == 0;
225 pointerEvents.Add(pointerEvent);
227 pointerInfo.LastPosition = newPosition;
228 pointerInfo.PointerClock.Restart();
232 internal enum InputEventType
251 public List<PointerEvent> PointerEvents {
get;
private set; }
257 public List<GestureEvent> GestureEvents {
get;
private set; }
263 public bool HasGamePad
267 return gamePadCount > 0;
275 public int GamePadCount
287 public bool HasKeyboard {
get;
internal set; }
293 public bool HasMouse {
get;
internal set; }
299 public bool HasPointer {
get;
internal set; }
305 public List<Keys> KeyDown {
get;
private set; }
311 public List<KeyEvent> KeyEvents {
get;
private set; }
317 public Vector2 MousePosition {
get;
private set; }
333 virtualButtonValues[configIndex].TryGetValue(bindingName, out value);
345 if (gamepadIndex < 0)
348 for(
int i = 0; i < gamePadStates.Length; i++)
350 if (gamePadStates[i].IsConnected)
357 else if (gamepadIndex >= gamePadStates.Length)
359 for (gamepadIndex = gamePadStates.Length - 1; gamepadIndex >= 0; gamepadIndex--)
361 if (gamePadStates[gamepadIndex].IsConnected)
368 return gamePadStates[gamepadIndex];
379 activeKeys.TryGetValue(key, out pressed);
390 return pressedKeysSet.Contains(key);
400 return releasedKeysSet.Contains(key);
409 for (
int i = 0; i < mouseButtons.Length; ++i)
422 for (
int i = 0; i < mouseButtons.Length; ++i)
435 for (
int i = 0; i < mouseButtons.Length; ++i)
449 return mouseButtons[(int)mouseButton];
459 return !mouseButtonsPrevious[(int)mouseButton] && mouseButtons[(
int)mouseButton];
469 return mouseButtonsPrevious[(int)mouseButton] && !mouseButtons[(
int)mouseButton];
482 List<GamePadKey> gamePadKeys = GamePadFactories.SelectMany(gamePadFactory => gamePadFactory.GetConnectedPads()).ToList();
484 int nextAvailable = -1;
485 for (
int i = 0; i < gamePads.Length; i++)
490 if (nextAvailable < 0)
497 if (gamePadKeys.Contains(gamePad.Key))
499 gamePadKeys.Remove(gamePad.Key);
506 if (nextAvailable < 0)
513 foreach (GamePadKey gamePadKey
in gamePadKeys)
515 int gamePadIndex = -1;
516 for (
int i = nextAvailable; i < gamePads.Length; i++)
518 if (gamePads[i] == null)
525 if (gamePadIndex >= 0)
527 GamePad gamePad = gamePadKey.Factory.GetGamePad(gamePadKey.Guid);
528 gamePads[gamePadIndex] = gamePad;
529 nextAvailable = gamePadIndex + 1;
534 foreach (
GamePad internalGamePad
in gamePads)
536 if (internalGamePad != null)
549 UpdatePointerEvents();
550 UpdateVirtualButtonValues();
551 UpdateGestureEvents(gameTime.
Elapsed);
554 private void UpdateGestureEvents(TimeSpan elapsedGameTime)
556 currentGestureEvents.Clear();
558 foreach (var gestureRecognizer
in gestureConfigToRecognizer.Values)
559 currentGestureEvents.AddRange(gestureRecognizer.ProcessPointerEvents(elapsedGameTime, currentPointerEvents));
562 private void UpdatePointerEvents()
564 lock (PointerEvent.Pool)
566 foreach (var pointerEvent
in currentPointerEvents)
567 PointerEvent.Pool.Enqueue(pointerEvent);
569 currentPointerEvents.Clear();
573 currentPointerEvents.AddRange(pointerEvents);
574 pointerEvents.Clear();
578 private void UpdateVirtualButtonValues()
580 if (VirtualButtonConfigSet != null)
582 for (
int i = 0; i < VirtualButtonConfigSet.Count; i++)
584 var config = VirtualButtonConfigSet[i];
586 Dictionary<object, float> mapNameToValue;
587 if (i == virtualButtonValues.Count)
589 mapNameToValue =
new Dictionary<object, float>();
590 virtualButtonValues.Add(mapNameToValue);
594 mapNameToValue = virtualButtonValues[i];
597 mapNameToValue.Clear();
601 foreach (var name
in config.BindingNames)
603 mapNameToValue[name] = config.GetValue(
this, name);
610 private void UpdateGamePads()
614 for (
int i = 0, j = gamePadCount; i < gamePads.Length && j > 0; i++, j--)
616 if (gamePads[i] != null)
619 gamePadStates[i] = gamePads[i].GetState();
625 private void UpdateMouse()
629 for (
int i = 0; i < mouseButtons.Length; ++i)
630 mouseButtonsPrevious[i] = mouseButtons[i];
632 lock (MouseInputEvents)
634 foreach (MouseInputEvent mouseInputEvent
in MouseInputEvents)
636 var mouseButton = (int)mouseInputEvent.MouseButton;
637 if (mouseButton < 0 || mouseButton >= mouseButtons.Length)
640 switch (mouseInputEvent.Type)
642 case InputEventType.Down:
643 mouseButtons[mouseButton] =
true;
645 case InputEventType.Up:
646 mouseButtons[mouseButton] =
false;
648 case InputEventType.Wheel:
649 if (mouseInputEvent.MouseButton !=
MouseButton.Middle)
651 throw new NotImplementedException();
653 MouseWheelDelta += mouseInputEvent.Value;
656 throw new NotSupportedException();
659 MouseInputEvents.Clear();
662 MousePosition = CurrentMousePosition;
666 for (
int i = 0; i < mouseButtons.Length; ++i)
667 mouseButtons[i] =
false;
673 private void UpdateKeyboard()
675 pressedKeysSet.Clear();
676 releasedKeysSet.Clear();
679 lock (KeyboardInputEvents)
681 foreach (KeyboardInputEvent keyboardInputEvent
in KeyboardInputEvents)
683 var key = keyboardInputEvent.Key;
685 if (key ==
Keys.None)
688 switch (keyboardInputEvent.Type)
690 case InputEventType.Down:
693 activeKeys[key] =
true;
694 pressedKeysSet.Add(key);
697 downKeysList.Add(key);
700 case InputEventType.Up:
701 activeKeys[key] =
false;
702 releasedKeysSet.Add(key);
703 KeyEvents.Add(
new KeyEvent(key,
KeyEventType.Released));
704 downKeysList.Remove(key);
707 throw new NotSupportedException();
711 KeyboardInputEvents.Clear();
717 downKeysList.Clear();
721 internal static float ClampDeadZone(
float value,
float deadZone)
741 value = value / (1.0f - deadZone);
742 return value < -1.0f ? -1.0f : value > 1.0f ? 1.0f : value;
745 internal struct GamePadKey : IEquatable<GamePadKey>
747 #region Constants and Fields
749 public readonly GamePadFactory
Factory;
751 public readonly Guid Guid;
755 public GamePadKey(Guid guid, GamePadFactory factory)
761 public bool Equals(GamePadKey other)
763 return Guid.Equals(other.Guid) &&
Factory.Equals(other.Factory);
766 public override bool Equals(
object obj)
768 if (ReferenceEquals(null, obj))
return false;
769 return obj is GamePadKey && Equals((GamePadKey)obj);
772 public override int GetHashCode()
776 return (Guid.GetHashCode() * 397) ^
Factory.GetHashCode();
780 public static bool operator ==(GamePadKey left, GamePadKey right)
782 return left.Equals(right);
785 public static bool operator !=(GamePadKey left, GamePadKey right)
787 return !left.Equals(right);
791 internal struct KeyboardInputEvent
793 #region Constants and Fields
797 public InputEventType
Type;
802 internal struct MouseInputEvent
804 #region Constants and Fields
808 public InputEventType
Type;
819 public abstract bool MultiTouchEnabled {
get; set; }
824 internal abstract class GamePad : IDisposable
826 #region Constants and Fields
831 public GamePadKey Key;
835 protected GamePad(GamePadKey key)
840 public virtual void Dispose()
844 public abstract GamePadState GetState();
850 internal abstract class GamePadFactory
854 public abstract GamePad GetGamePad(Guid guid);
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
Represents a two dimensional mathematical vector.
SharpDX.DirectWrite.Factory Factory
Searchg files going upward in the directory hierarchy.
Search files in all sub-directories.
SiliconStudio.Paradox.Input.Keys Keys
A service registry is a IServiceProvider that provides methods to register and unregister services...
Base class for a GameSystemBase component.
Base implementation for ILogger.
Current timing used for variable-step (real time) or fixed-step (game time) games.
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}.
float Y
The Y component of the vector.
object Item
Gets the added or removed item (if dictionary, value only).
NotifyCollectionChangedAction Action
Gets the type of action performed. Allowed values are NotifyCollectionChangedAction.Add and NotifyCollectionChangedAction.Remove.
float X
The X component of the vector.
TimeSpan Elapsed
Gets the elapsed game time since the last update