NEW: Can create devices reported by native using templates.

This commit is contained in:
Rene Damm rene@unity3d.com 2017-10-06 02:35:16 -07:00
Родитель 42daa0d115
Коммит ceabd76b9e
8 изменённых файлов: 154 добавлений и 11 удалений

Просмотреть файл

@ -0,0 +1,35 @@
namespace ISX
{
internal static class BuiltinDeviceTemplates
{
public static void RegisterTemplates(InputManager manager)
{
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
// Xbox one controller on OSX. State layout can be found here:
// https://github.com/360Controller/360Controller/blob/master/360Controller/ControlStruct.h
// struct State
// {
// short buttons;
// byte triggerLeft;
// byte triggerRight;
// short leftX;
// short leftY;
// short rightX;
// short rightY;
// }
// Report size is 14 bytes with some stuff at the end we can ignore.
manager.RegisterTemplate(@"
{
""name"" : ""XboxGamepadOSX"",
""extend"" : ""Gamepad"",
""stateTypeCode"" : ""HID"",
""device"" : {
""interface"" : ""HID"",
""product"" : ""Xbox One Wired Controller""
}
}
");
#endif
}
}
}

Просмотреть файл

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 22daba482c044e26991dfbdc69b89d15
timeCreated: 1507276459

Просмотреть файл

@ -1,5 +1,6 @@
using System;
using System.Text.RegularExpressions;
using UnityEngine;
namespace ISX
{
@ -43,9 +44,34 @@ namespace ISX
return true;
if (string.IsNullOrEmpty(right))
return false;
if (!Regex.IsMatch(right, left))
if (!Regex.IsMatch(right, left, RegexOptions.IgnoreCase))
return false;
return true;
}
public static InputDeviceDescription FromJson(string json)
{
var data = JsonUtility.FromJson<DeviceDescriptionJson>(json);
return new InputDeviceDescription
{
interfaceName = data.@interface,
deviceClass = data.type,
product = data.product,
manufacturer = data.manufacturer,
serial = data.serial,
version = data.version
};
}
private struct DeviceDescriptionJson
{
public string @interface;
public string type;
public string product;
public string serial;
public string version;
public string manufacturer;
}
}
}

Просмотреть файл

@ -4,12 +4,16 @@ namespace ISX
{
// A chunk of memory signaling a data transfer in the input system.
// This has to be layout compatible with native events.
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Explicit)]
public struct InputEvent : IInputEventTypeInfo
{
[FieldOffset(0)]
private FourCC m_Type;
[FieldOffset(4)]
private int m_SizeInBytes;
[FieldOffset(8)]
private int m_DeviceId;
[FieldOffset(12)]
private double m_Time;
public FourCC type { get { return m_Type; } }

Просмотреть файл

@ -5,13 +5,16 @@ using UnityEngine;
namespace ISX
{
// Full state update for an input device.
[StructLayout(LayoutKind.Sequential)]
[StructLayout(LayoutKind.Explicit)]
public unsafe struct StateEvent : IInputEventTypeInfo
{
public const int Type = 0x42554C4B;
public const int Type = 0x53544154;
[FieldOffset(0)]
public InputEvent baseEvent;
[FieldOffset(20)]
public FourCC stateType;
[FieldOffset(24)]
public fixed byte stateData[1]; // Variable-sized.
public int stateSizeInBytes

Просмотреть файл

@ -91,12 +91,30 @@ namespace ISX
// Add it to our records.
m_TemplateStrings[name.ToLower()] = json;
if (!deviceDescription.empty)
{
m_DeviceDescriptions.Add(new DeviceDescription
{
description = deviceDescription,
template = name
});
// The template has a device description, so if there's any native
// devices we couldn't make sense of, see if the template helps
// with that.
for (var i = 0; i < m_NativeDevices.Count; ++i)
{
var deviceId = m_NativeDevices[i].deviceId;
if (TryGetDeviceById(deviceId) != null)
continue;
if (deviceDescription.Matches(m_NativeDevices[i].description))
{
AddNativeDevice(deviceId, name);
}
}
}
}
public string TryFindTemplate(InputDeviceDescription deviceDescription)
@ -244,6 +262,17 @@ namespace ISX
return AddDevice(template);
}
internal InputDevice AddNativeDevice(int deviceId, string template)
{
var setup = new InputControlSetup(template);
var device = setup.Finish();
device.m_Id = deviceId;
AddDevice(device);
return device;
}
public void RemoveDevice(InputDevice device)
{
//need to make sure that all actions rescan their source paths
@ -330,6 +359,7 @@ namespace ISX
m_DeviceDescriptions = new List<DeviceDescription>();
m_Processors = new Dictionary<string, Type>();
m_DevicesById = new Dictionary<int, InputDevice>();
m_NativeDevices = new List<NativeDevice>();
// Determine our default set of enabled update types. By
// default we enable both fixed and dynamic update because
@ -376,10 +406,9 @@ namespace ISX
// Register action modifiers.
//RegisterModifier("Hold", typeof(HoldModifier));
InputTemplate.s_TemplateTypes = m_TemplateTypes;
InputTemplate.s_TemplateStrings = m_TemplateStrings;
BuiltinDeviceTemplates.RegisterTemplates(this);
NativeInputSystem.onUpdate += OnNativeUpdate;
InstallGlobals();
}
internal void Destroy()
@ -388,6 +417,16 @@ namespace ISX
InputTemplate.s_TemplateStrings = null;
NativeInputSystem.onUpdate -= OnNativeUpdate;
NativeInputSystem.onDeviceDiscovered -= OnNativeDeviceDiscovered;
}
// Revive after domain reload.
internal void InstallGlobals()
{
InputTemplate.s_TemplateTypes = m_TemplateTypes;
InputTemplate.s_TemplateStrings = m_TemplateStrings;
NativeInputSystem.onUpdate += OnNativeUpdate;
NativeInputSystem.onDeviceDiscovered += OnNativeDeviceDiscovered;
}
// Bundles a template name and a device description.
@ -398,10 +437,19 @@ namespace ISX
public string template;
}
[Serializable]
private struct NativeDevice
{
public InputDeviceDescription description;
public int deviceId;
}
private Dictionary<string, Type> m_TemplateTypes;
private Dictionary<string, string> m_TemplateStrings;
private Dictionary<string, Type> m_Processors;
private List<DeviceDescription> m_DeviceDescriptions;
private List<NativeDevice> m_NativeDevices;
private InputDevice[] m_Devices;
private Dictionary<int, InputDevice> m_DevicesById;
@ -564,6 +612,26 @@ namespace ISX
////TODO: need to update state change monitors
}
private void OnNativeDeviceDiscovered(NativeInputDeviceInfo deviceInfo)
{
// Parse description.
var description = InputDeviceDescription.FromJson(deviceInfo.deviceDescriptor);
// Remember device.
m_NativeDevices.Add(new NativeDevice
{
description = description,
deviceId = deviceInfo.deviceId
});
// Try to turn it into a device instance.
var template = TryFindTemplate(description);
if (template != null)
{
AddNativeDevice(deviceInfo.deviceId, template);
}
}
// When we have the C# job system, this should be a job and NativeInputSystem should double
// buffer input between frames. On top, the state change detection in here can be further
// split off and put in its own job(s) (might not yield a gain; might be enough to just have
@ -886,6 +954,7 @@ namespace ISX
public TemplateState[] templateStrings;
public DeviceDescription[] deviceDescriptions;
public DeviceState[] devices;
public NativeDevice[] nativeDevices;
public InputStateBuffers buffers;
public DeviceChangeEvent deviceChangeEvent;
}
@ -942,6 +1011,7 @@ namespace ISX
templateStrings = templateStringArray,
deviceDescriptions = m_DeviceDescriptions.ToArray(),
devices = deviceArray,
nativeDevices = m_NativeDevices.ToArray(),
buffers = m_StateBuffers,
deviceChangeEvent = m_DeviceChangeEvent
};
@ -961,6 +1031,8 @@ namespace ISX
m_StateBuffers = m_SerializedState.buffers;
m_CurrentUpdate = InputUpdateType.Dynamic;
m_DeviceChangeEvent = m_SerializedState.deviceChangeEvent;
m_DevicesById = new Dictionary<int, InputDevice>();
m_NativeDevices = m_SerializedState.nativeDevices.ToList();
// Template types.
foreach (var template in m_SerializedState.templateTypes)
@ -984,6 +1056,7 @@ namespace ISX
device.m_Id = state.deviceId;
device.BakeOffsetIntoStateBlockRecursive(state.stateOffset);
devices[i] = device;
m_DevicesById[device.m_Id] = device;
}
m_Devices = devices;
ReallocateStateBuffers();

Просмотреть файл

@ -143,13 +143,12 @@ namespace ISX
if (s_Initialized)
return;
// We may get InitializeOnLoad-related calls to the static class constructor
// *after*
var existingSystemObjects = Resources.FindObjectsOfTypeAll<InputSystemObject>();
if (existingSystemObjects != null && existingSystemObjects.Length > 0)
{
m_SystemObject = existingSystemObjects[0];
s_Manager = m_SystemObject.manager;
s_Manager.InstallGlobals();
}
else
{

Просмотреть файл

@ -613,5 +613,5 @@ PlayerSettings:
projectName:
organizationId:
cloudEnabled: 0
enableNativePlatformBackendsForNewInputSystem: 0
disableOldInputManagerSupport: 0
enableNativePlatformBackendsForNewInputSystem: 1
disableOldInputManagerSupport: 1