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