Aucune description
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

StateEvent.cs 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using Unity.Collections;
  4. using UnityEngine.InputSystem.Utilities;
  5. using Unity.Collections.LowLevel.Unsafe;
  6. namespace UnityEngine.InputSystem.LowLevel
  7. {
  8. /// <summary>
  9. /// A complete state snapshot for an entire input device.
  10. /// </summary>
  11. /// <remarks>
  12. /// This is a variable-sized event.
  13. /// </remarks>
  14. [StructLayout(LayoutKind.Explicit, Size = InputEvent.kBaseEventSize + 4 + kStateDataSizeToSubtract, Pack = 1)]
  15. public unsafe struct StateEvent : IInputEventTypeInfo
  16. {
  17. public const int Type = 0x53544154; // 'STAT'
  18. internal const int kStateDataSizeToSubtract = 1;
  19. [FieldOffset(0)]
  20. public InputEvent baseEvent;
  21. /// <summary>
  22. /// Type code for the state stored in the event.
  23. /// </summary>
  24. [FieldOffset(InputEvent.kBaseEventSize)]
  25. public FourCC stateFormat;
  26. [FieldOffset(InputEvent.kBaseEventSize + sizeof(int))]
  27. internal fixed byte stateData[kStateDataSizeToSubtract]; // Variable-sized.
  28. public uint stateSizeInBytes => baseEvent.sizeInBytes - (InputEvent.kBaseEventSize + sizeof(int));
  29. public void* state
  30. {
  31. get
  32. {
  33. fixed(byte* data = stateData)
  34. {
  35. return data;
  36. }
  37. }
  38. }
  39. public InputEventPtr ToEventPtr()
  40. {
  41. fixed(StateEvent * ptr = &this)
  42. {
  43. return new InputEventPtr((InputEvent*)ptr);
  44. }
  45. }
  46. public FourCC typeStatic => Type;
  47. /// <summary>
  48. /// Retrieve the state stored in the event.
  49. /// </summary>
  50. /// <typeparam name="TState">Type of state expected to be stored in the event. <see cref="IInputStateTypeInfo.format"/>
  51. /// must match <see cref="stateFormat"/>.</typeparam>
  52. /// <returns>Copy of the state stored in the event.</returns>
  53. /// <exception cref="InvalidOperationException"><see cref="stateFormat"/> does not match <see cref="IInputStateTypeInfo.format"/>
  54. /// of <typeparamref name="TState"/>.</exception>
  55. /// <remarks>
  56. /// The event may contain less or more data than what is found in the struct. Only the data found in the event
  57. /// is copied. The remainder of the struct is left at default values.
  58. /// </remarks>
  59. /// <seealso cref="GetState{T}(InputEventPtr)"/>
  60. public TState GetState<TState>()
  61. where TState : struct, IInputStateTypeInfo
  62. {
  63. var result = default(TState);
  64. if (stateFormat != result.format)
  65. throw new InvalidOperationException($"Expected state format '{result.format}' but got '{stateFormat}' instead");
  66. UnsafeUtility.MemCpy(UnsafeUtility.AddressOf(ref result), state, Math.Min(stateSizeInBytes, UnsafeUtility.SizeOf<TState>()));
  67. return result;
  68. }
  69. /// <summary>
  70. /// Retrieve the state stored in the event.
  71. /// </summary>
  72. /// <typeparam name="TState">Type of state expected to be stored in the event. <see cref="IInputStateTypeInfo.format"/>
  73. /// must match <see cref="stateFormat"/>.</typeparam>
  74. /// <param name="ptr">A pointer to an input event. The pointer is checked for <c>null</c> and
  75. /// for whether the type of event it refers to is indeed a StateEvent.</param>
  76. /// <returns>Copy of the state stored in the event.</returns>
  77. /// <remarks>
  78. /// The event may contain less or more data than what is found in the struct. Only the data found in the event
  79. /// is copied. The remainder of the struct is left at default values.
  80. /// </remarks>
  81. /// <exception cref="InvalidOperationException"><see cref="stateFormat"/> does not match <see cref="IInputStateTypeInfo.format"/>
  82. /// of <typeparamref name="TState"/>.</exception>
  83. /// <exception cref="ArgumentNullException"><paramref name="ptr"/> is <c>default(InputEventPtr)</c>.</exception>
  84. /// <exception cref="InvalidCastException"><paramref name="ptr"/> does not refer to a StateEvent.</exception>
  85. /// <seealso cref="GetState{T}()"/>
  86. public static TState GetState<TState>(InputEventPtr ptr)
  87. where TState : struct, IInputStateTypeInfo
  88. {
  89. return From(ptr)->GetState<TState>();
  90. }
  91. public static int GetEventSizeWithPayload<TState>()
  92. where TState : struct
  93. {
  94. return UnsafeUtility.SizeOf<TState>() + InputEvent.kBaseEventSize + sizeof(int);
  95. }
  96. /// <summary>
  97. /// Return the given <see cref="InputEventPtr"/> as a StateEvent pointer.
  98. /// </summary>
  99. /// <param name="ptr">A pointer to an input event. The pointer is checked for <c>null</c> and
  100. /// for whether the type of event it refers to is indeed a StateEvent.</param>
  101. /// <returns>Pointer <paramref name="ptr"/> converted to a StateEvent pointer.</returns>
  102. /// <exception cref="ArgumentNullException"><paramref name="ptr"/> is <c>default(InputEventPtr)</c>.</exception>
  103. /// <exception cref="InvalidCastException"><paramref name="ptr"/> does not refer to a StateEvent.</exception>
  104. public static StateEvent* From(InputEventPtr ptr)
  105. {
  106. if (!ptr.valid)
  107. throw new ArgumentNullException(nameof(ptr));
  108. if (!ptr.IsA<StateEvent>())
  109. throw new InvalidCastException($"Cannot cast event with type '{ptr.type}' into StateEvent");
  110. return FromUnchecked(ptr);
  111. }
  112. internal static StateEvent* FromUnchecked(InputEventPtr ptr)
  113. {
  114. return (StateEvent*)ptr.data;
  115. }
  116. /// <summary>
  117. /// Read the current state of <paramref name="device"/> and create a state event from it.
  118. /// </summary>
  119. /// <param name="device">Device to grab the state from. Must be a device that has been added to the system.</param>
  120. /// <param name="eventPtr">Receives a pointer to the newly created state event.</param>
  121. /// <param name="allocator">Which native allocator to allocate memory for the event from. By default, the buffer is
  122. /// allocated as temporary memory (<see cref="Allocator.Temp"/>. Note that this means the buffer will not be valid
  123. /// past the current frame. Use <see cref="Allocator.Persistent"/> if the buffer for the state event is meant to
  124. /// persist for longer.</param>
  125. /// <returns>Buffer of unmanaged memory allocated for the event.</returns>
  126. /// <exception cref="ArgumentException"><paramref name="device"/> has not been added to the system.</exception>
  127. /// <exception cref="ArgumentNullException"><paramref name="device"/> is <c>null</c>.</exception>
  128. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
  129. public static NativeArray<byte> From(InputDevice device, out InputEventPtr eventPtr, Allocator allocator = Allocator.Temp)
  130. {
  131. return From(device, out eventPtr, allocator, useDefaultState: false);
  132. }
  133. /// <summary>
  134. /// Create a state event for the given <paramref name="device"/> and copy the default state of the device
  135. /// into the event.
  136. /// </summary>
  137. /// <param name="device">Device to create a state event for. Must be a device that has been added to the system.</param>
  138. /// <param name="eventPtr">Receives a pointer to the newly created state event.</param>
  139. /// <param name="allocator">Which native allocator to allocate memory for the event from. By default, the buffer is
  140. /// allocated as temporary memory (<see cref="Allocator.Temp"/>. Note that this means the buffer will not be valid
  141. /// past the current frame. Use <see cref="Allocator.Persistent"/> if the buffer for the state event is meant to
  142. /// persist for longer.</param>
  143. /// <returns>Buffer of unmanaged memory allocated for the event.</returns>
  144. /// <exception cref="ArgumentException"><paramref name="device"/> has not been added to the system.</exception>
  145. /// <exception cref="ArgumentNullException"><paramref name="device"/> is <c>null</c>.</exception>
  146. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
  147. public static NativeArray<byte> FromDefaultStateFor(InputDevice device, out InputEventPtr eventPtr, Allocator allocator = Allocator.Temp)
  148. {
  149. return From(device, out eventPtr, allocator, useDefaultState: true);
  150. }
  151. private static NativeArray<byte> From(InputDevice device, out InputEventPtr eventPtr, Allocator allocator, bool useDefaultState)
  152. {
  153. if (device == null)
  154. throw new ArgumentNullException(nameof(device));
  155. if (!device.added)
  156. throw new ArgumentException($"Device '{device}' has not been added to system",
  157. nameof(device));
  158. var stateFormat = device.m_StateBlock.format;
  159. var stateSize = device.m_StateBlock.alignedSizeInBytes;
  160. var stateOffset = device.m_StateBlock.byteOffset;
  161. var statePtr = (byte*)(useDefaultState ? device.defaultStatePtr : device.currentStatePtr) + (int)stateOffset;
  162. var eventSize = InputEvent.kBaseEventSize + sizeof(int) + stateSize;
  163. var buffer = new NativeArray<byte>((int)eventSize.AlignToMultipleOf(4), allocator);
  164. var stateEventPtr = (StateEvent*)buffer.GetUnsafePtr();
  165. stateEventPtr->baseEvent = new InputEvent(Type, (int)eventSize, device.deviceId, InputRuntime.s_Instance.currentTime);
  166. stateEventPtr->stateFormat = stateFormat;
  167. UnsafeUtility.MemCpy(stateEventPtr->state, statePtr, stateSize);
  168. eventPtr = stateEventPtr->ToEventPtr();
  169. return buffer;
  170. }
  171. }
  172. }