92 lines
3.3 KiB
C#
92 lines
3.3 KiB
C#
|
using System.Runtime.InteropServices;
|
||
|
using UnityEngine.InputSystem.Utilities;
|
||
|
using Unity.Collections;
|
||
|
using Unity.Collections.LowLevel.Unsafe;
|
||
|
|
||
|
namespace UnityEngine.InputSystem.LowLevel
|
||
|
{
|
||
|
////REVIEW: why is this passing the command by pointer instead of by ref?
|
||
|
/// <summary>
|
||
|
/// Delegate used by <see cref="InputSystem.onDeviceCommand"/>.
|
||
|
/// </summary>
|
||
|
public unsafe delegate long? InputDeviceCommandDelegate(InputDevice device, InputDeviceCommand* command);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Delegate for executing <see cref="InputDeviceCommand"/>s inside <see cref="InputSystem.onFindLayoutForDevice"/>.
|
||
|
/// </summary>
|
||
|
/// <param name="command">Command to execute.</param>
|
||
|
/// <seealso cref="InputSystem.onFindLayoutForDevice"/>
|
||
|
/// <seealso cref="Layouts.InputDeviceFindControlLayoutDelegate"/>
|
||
|
public delegate long InputDeviceExecuteCommandDelegate(ref InputDeviceCommand command);
|
||
|
|
||
|
/// <summary>
|
||
|
/// Data header for a command send to an <see cref="InputDevice"/>.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// Commands are essentially synchronously processed events send directly
|
||
|
/// to a specific device. Their primary use is to expose device-specific
|
||
|
/// functions without having to extend the C# API used to communicate
|
||
|
/// between input code and backend device implementations (which may sit
|
||
|
/// in native code).
|
||
|
///
|
||
|
/// Like input events, device commands use <see cref="FourCC"/> codes
|
||
|
/// to indicate their type.
|
||
|
/// </remarks>
|
||
|
[StructLayout(LayoutKind.Explicit, Size = kBaseCommandSize)]
|
||
|
public struct InputDeviceCommand : IInputDeviceCommandInfo
|
||
|
{
|
||
|
////TODO: Remove kBaseCommandSize
|
||
|
internal const int kBaseCommandSize = 8;
|
||
|
public const int BaseCommandSize = 8;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Generic failure code for <see cref="InputDevice.ExecuteCommand{TCommand}"/> calls.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// Any negative return value for an <see cref="InputDevice.ExecuteCommand{TCommand}"/> call should be considered failure.
|
||
|
/// </remarks>
|
||
|
public const long GenericFailure = -1;
|
||
|
|
||
|
public const long GenericSuccess = 1;
|
||
|
|
||
|
[FieldOffset(0)] public FourCC type;
|
||
|
[FieldOffset(4)] public int sizeInBytes;
|
||
|
|
||
|
public int payloadSizeInBytes => sizeInBytes - kBaseCommandSize;
|
||
|
|
||
|
public unsafe void* payloadPtr
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
fixed(void* thisPtr = &this)
|
||
|
{
|
||
|
return ((byte*)thisPtr) + kBaseCommandSize;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public InputDeviceCommand(FourCC type, int sizeInBytes = kBaseCommandSize)
|
||
|
{
|
||
|
this.type = type;
|
||
|
this.sizeInBytes = sizeInBytes;
|
||
|
}
|
||
|
|
||
|
public static unsafe NativeArray<byte> AllocateNative(FourCC type, int payloadSize)
|
||
|
{
|
||
|
var sizeInBytes = payloadSize + kBaseCommandSize;
|
||
|
var buffer = new NativeArray<byte>(sizeInBytes, Allocator.Temp);
|
||
|
|
||
|
var commandPtr = (InputDeviceCommand*)NativeArrayUnsafeUtility.GetUnsafePtr(buffer);
|
||
|
commandPtr->type = type;
|
||
|
commandPtr->sizeInBytes = sizeInBytes;
|
||
|
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
public FourCC typeStatic
|
||
|
{
|
||
|
get { return new FourCC(); }
|
||
|
}
|
||
|
}
|
||
|
}
|