ActionEvent.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using UnityEngine.InputSystem.Utilities;
  4. ////REVIEW: move this inside InputActionTrace?
  5. namespace UnityEngine.InputSystem.LowLevel
  6. {
  7. /// <summary>
  8. /// A variable-size event that captures the triggering of an action.
  9. /// </summary>
  10. /// <remarks>
  11. /// Action events capture fully processed values only.
  12. ///
  13. /// This struct is internal as the data it stores requires having access to <see cref="InputActionState"/>.
  14. /// Public access is meant to go through <see cref="InputActionTrace"/> which provides a wrapper around
  15. /// action events in the form of <see cref="InputActionTrace.ActionEventPtr"/>.
  16. /// </remarks>
  17. [StructLayout(LayoutKind.Explicit, Size = InputEvent.kBaseEventSize + 16 + 1)]
  18. internal unsafe struct ActionEvent : IInputEventTypeInfo
  19. {
  20. public static FourCC Type => new FourCC('A', 'C', 'T', 'N');
  21. ////REVIEW: should we decouple this from InputEvent? we get deviceId which we don't really have a use for
  22. [FieldOffset(0)] public InputEvent baseEvent;
  23. [FieldOffset(InputEvent.kBaseEventSize + 0)] private ushort m_ControlIndex;
  24. [FieldOffset(InputEvent.kBaseEventSize + 2)] private ushort m_BindingIndex;
  25. [FieldOffset(InputEvent.kBaseEventSize + 4)] private ushort m_InteractionIndex;
  26. [FieldOffset(InputEvent.kBaseEventSize + 6)] private byte m_StateIndex;
  27. [FieldOffset(InputEvent.kBaseEventSize + 7)] private byte m_Phase;
  28. [FieldOffset(InputEvent.kBaseEventSize + 8)] private double m_StartTime;
  29. [FieldOffset(InputEvent.kBaseEventSize + 16)] public fixed byte m_ValueData[1]; // Variable-sized.
  30. public double startTime
  31. {
  32. get => m_StartTime;
  33. set => m_StartTime = value;
  34. }
  35. public InputActionPhase phase
  36. {
  37. get => (InputActionPhase)m_Phase;
  38. set => m_Phase = (byte)value;
  39. }
  40. public byte* valueData
  41. {
  42. get
  43. {
  44. fixed(byte* data = m_ValueData)
  45. {
  46. return data;
  47. }
  48. }
  49. }
  50. public int valueSizeInBytes => (int)baseEvent.sizeInBytes - InputEvent.kBaseEventSize - 16;
  51. public int stateIndex
  52. {
  53. get => m_StateIndex;
  54. set
  55. {
  56. Debug.Assert(value >= 0 && value <= byte.MaxValue);
  57. if (value < 0 || value > byte.MaxValue)
  58. throw new NotSupportedException("State count cannot exceed byte.MaxValue");
  59. m_StateIndex = (byte)value;
  60. }
  61. }
  62. public int controlIndex
  63. {
  64. get => m_ControlIndex;
  65. set
  66. {
  67. Debug.Assert(value >= 0 && value <= ushort.MaxValue);
  68. if (value < 0 || value > ushort.MaxValue)
  69. throw new NotSupportedException("Control count cannot exceed ushort.MaxValue");
  70. m_ControlIndex = (ushort)value;
  71. }
  72. }
  73. public int bindingIndex
  74. {
  75. get => m_BindingIndex;
  76. set
  77. {
  78. Debug.Assert(value >= 0 && value <= ushort.MaxValue);
  79. if (value < 0 || value > ushort.MaxValue)
  80. throw new NotSupportedException("Binding count cannot exceed ushort.MaxValue");
  81. m_BindingIndex = (ushort)value;
  82. }
  83. }
  84. public int interactionIndex
  85. {
  86. get
  87. {
  88. if (m_InteractionIndex == ushort.MaxValue)
  89. return InputActionState.kInvalidIndex;
  90. return m_InteractionIndex;
  91. }
  92. set
  93. {
  94. Debug.Assert(value == InputActionState.kInvalidIndex || (value >= 0 && value < ushort.MaxValue));
  95. if (value == InputActionState.kInvalidIndex)
  96. m_InteractionIndex = ushort.MaxValue;
  97. else
  98. {
  99. if (value < 0 || value >= ushort.MaxValue)
  100. throw new NotSupportedException("Interaction count cannot exceed ushort.MaxValue-1");
  101. m_InteractionIndex = (ushort)value;
  102. }
  103. }
  104. }
  105. public InputEventPtr ToEventPtr()
  106. {
  107. fixed(ActionEvent* ptr = &this)
  108. {
  109. return new InputEventPtr((InputEvent*)ptr);
  110. }
  111. }
  112. public FourCC typeStatic => Type;
  113. public static int GetEventSizeWithValueSize(int valueSizeInBytes)
  114. {
  115. return InputEvent.kBaseEventSize + 16 + valueSizeInBytes;
  116. }
  117. public static ActionEvent* From(InputEventPtr ptr)
  118. {
  119. if (!ptr.valid)
  120. throw new ArgumentNullException(nameof(ptr));
  121. if (!ptr.IsA<ActionEvent>())
  122. throw new InvalidCastException($"Cannot cast event with type '{ptr.type}' into ActionEvent");
  123. return (ActionEvent*)ptr.data;
  124. }
  125. }
  126. }