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