test
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE_LINUX
|
||||
using System;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
using System.Text;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
|
||||
namespace UnityEngine.InputSystem.Linux
|
||||
{
|
||||
[Serializable]
|
||||
internal class SDLLayoutBuilder
|
||||
{
|
||||
[SerializeField] private string m_ParentLayout;
|
||||
[SerializeField] private SDLDeviceDescriptor m_Descriptor;
|
||||
|
||||
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout,
|
||||
InputDeviceExecuteCommandDelegate executeCommandDelegate)
|
||||
{
|
||||
if (description.interfaceName != LinuxSupport.kInterfaceName)
|
||||
return null;
|
||||
|
||||
if (string.IsNullOrEmpty(description.capabilities))
|
||||
return null;
|
||||
|
||||
// Try to parse the SDL descriptor.
|
||||
SDLDeviceDescriptor deviceDescriptor;
|
||||
try
|
||||
{
|
||||
deviceDescriptor = SDLDeviceDescriptor.FromJson(description.capabilities);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Debug.LogError($"{exception} while trying to parse descriptor for SDL device: {description.capabilities}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (deviceDescriptor == null)
|
||||
return null;
|
||||
|
||||
string layoutName;
|
||||
if (string.IsNullOrEmpty(description.manufacturer))
|
||||
{
|
||||
layoutName = $"{SanitizeName(description.interfaceName)}::{SanitizeName(description.product)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
layoutName =
|
||||
$"{SanitizeName(description.interfaceName)}::{SanitizeName(description.manufacturer)}::{SanitizeName(description.product)}";
|
||||
}
|
||||
|
||||
var layout = new SDLLayoutBuilder { m_Descriptor = deviceDescriptor, m_ParentLayout = matchedLayout };
|
||||
InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, matchedLayout);
|
||||
|
||||
return layoutName;
|
||||
}
|
||||
|
||||
private static string SanitizeName(string originalName)
|
||||
{
|
||||
var stringLength = originalName.Length;
|
||||
var sanitizedName = new StringBuilder(stringLength);
|
||||
for (var i = 0; i < stringLength; i++)
|
||||
{
|
||||
var letter = originalName[i];
|
||||
if (char.IsUpper(letter) || char.IsLower(letter) || char.IsDigit(letter))
|
||||
sanitizedName.Append(letter);
|
||||
}
|
||||
return sanitizedName.ToString();
|
||||
}
|
||||
|
||||
private static bool IsAxis(SDLFeatureDescriptor feature, SDLAxisUsage axis)
|
||||
{
|
||||
return feature.featureType == JoystickFeatureType.Axis
|
||||
&& feature.usageHint == (int)axis;
|
||||
}
|
||||
|
||||
private static void BuildStickFeature(ref InputControlLayout.Builder builder, SDLFeatureDescriptor xFeature, SDLFeatureDescriptor yFeature)
|
||||
{
|
||||
int byteOffset;
|
||||
if (xFeature.offset <= yFeature.offset)
|
||||
byteOffset = xFeature.offset;
|
||||
else
|
||||
byteOffset = yFeature.offset;
|
||||
|
||||
const string stickName = "Stick";
|
||||
builder.AddControl(stickName)
|
||||
.WithLayout("Stick")
|
||||
.WithByteOffset((uint)byteOffset)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8 + (uint)yFeature.featureSize * 8)
|
||||
.WithUsages(CommonUsages.Primary2DMotion);
|
||||
|
||||
builder.AddControl(stickName + "/x")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithByteOffset(0)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8)
|
||||
.WithParameters("clamp=1,clampMin=-1,clampMax=1,scale,scaleFactor=65538");
|
||||
|
||||
builder.AddControl(stickName + "/y")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithByteOffset(4)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8)
|
||||
.WithParameters("clamp=1,clampMin=-1,clampMax=1,scale,scaleFactor=65538,invert");
|
||||
|
||||
builder.AddControl(stickName + "/up")
|
||||
.WithParameters("clamp=1,clampMin=-1,clampMax=0,scale,scaleFactor=65538,invert");
|
||||
|
||||
builder.AddControl(stickName + "/down")
|
||||
.WithParameters("clamp=1,clampMin=0,clampMax=1,scale,scaleFactor=65538,invert=false");
|
||||
|
||||
builder.AddControl(stickName + "/left")
|
||||
.WithParameters("clamp=1,clampMin=-1,clampMax=0,scale,scaleFactor=65538,invert");
|
||||
|
||||
builder.AddControl(stickName + "/right")
|
||||
.WithParameters("clamp=1,clampMin=0,clampMax=1,scale,scaleFactor=65538");
|
||||
}
|
||||
|
||||
private static bool IsHatX(SDLFeatureDescriptor feature)
|
||||
{
|
||||
return feature.featureType == JoystickFeatureType.Hat
|
||||
&& (feature.usageHint == (int)SDLAxisUsage.Hat0X
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat1X
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat2X
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat3X);
|
||||
}
|
||||
|
||||
private static bool IsHatY(SDLFeatureDescriptor feature)
|
||||
{
|
||||
return feature.featureType == JoystickFeatureType.Hat
|
||||
&& (feature.usageHint == (int)SDLAxisUsage.Hat0Y
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat1Y
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat2Y
|
||||
|| feature.usageHint == (int)SDLAxisUsage.Hat3Y);
|
||||
}
|
||||
|
||||
private static int HatNumber(SDLFeatureDescriptor feature)
|
||||
{
|
||||
Debug.Assert(feature.featureType == JoystickFeatureType.Hat);
|
||||
return 1 + (feature.usageHint - (int)SDLAxisUsage.Hat0X) / 2;
|
||||
}
|
||||
|
||||
private static void BuildHatFeature(ref InputControlLayout.Builder builder, SDLFeatureDescriptor xFeature, SDLFeatureDescriptor yFeature)
|
||||
{
|
||||
Debug.Assert(xFeature.offset < yFeature.offset, "Order of features must be X followed by Y");
|
||||
|
||||
var hat = HatNumber(xFeature);
|
||||
var hatName = hat > 1 ? $"Hat{hat}" : "Hat";
|
||||
|
||||
builder.AddControl(hatName)
|
||||
.WithLayout("Dpad")
|
||||
.WithByteOffset((uint)xFeature.offset)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8 + (uint)yFeature.featureSize * 8)
|
||||
.WithUsages(CommonUsages.Hatswitch);
|
||||
|
||||
builder.AddControl(hatName + "/up")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=0,invert")
|
||||
.WithByteOffset(4)
|
||||
.WithBitOffset(0)
|
||||
.WithSizeInBits((uint)yFeature.featureSize * 8);
|
||||
|
||||
builder.AddControl(hatName + "/down")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=0,clampMax=1")
|
||||
.WithByteOffset(4)
|
||||
.WithBitOffset(0)
|
||||
.WithSizeInBits((uint)yFeature.featureSize * 8);
|
||||
|
||||
builder.AddControl(hatName + "/left")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=0,invert")
|
||||
.WithByteOffset(0)
|
||||
.WithBitOffset(0)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8);
|
||||
|
||||
builder.AddControl(hatName + "/right")
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=0,clampMax=1")
|
||||
.WithByteOffset(0)
|
||||
.WithBitOffset(0)
|
||||
.WithSizeInBits((uint)xFeature.featureSize * 8);
|
||||
}
|
||||
|
||||
internal InputControlLayout Build()
|
||||
{
|
||||
var builder = new InputControlLayout.Builder
|
||||
{
|
||||
stateFormat = new FourCC('L', 'J', 'O', 'Y'),
|
||||
extendsLayout = m_ParentLayout
|
||||
};
|
||||
|
||||
for (var i = 0; i < m_Descriptor.controls.LengthSafe(); i++)
|
||||
{
|
||||
var feature = m_Descriptor.controls[i];
|
||||
switch (feature.featureType)
|
||||
{
|
||||
case JoystickFeatureType.Axis:
|
||||
{
|
||||
var usage = (SDLAxisUsage)feature.usageHint;
|
||||
var featureName = LinuxSupport.GetAxisNameFromUsage(usage);
|
||||
var parameters = "scale,scaleFactor=65538,clamp=1,clampMin=-1,clampMax=1";
|
||||
|
||||
// If X is followed by Y, build a stick out of the two.
|
||||
if (IsAxis(feature, SDLAxisUsage.X) && i + 1 < m_Descriptor.controls.Length)
|
||||
{
|
||||
var nextFeature = m_Descriptor.controls[i + 1];
|
||||
if (IsAxis(nextFeature, SDLAxisUsage.Y))
|
||||
{
|
||||
BuildStickFeature(ref builder, feature, nextFeature);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsAxis(feature, SDLAxisUsage.Y))
|
||||
parameters += ",invert";
|
||||
|
||||
var control = builder.AddControl(featureName)
|
||||
.WithLayout("Analog")
|
||||
.WithByteOffset((uint)feature.offset)
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters(parameters);
|
||||
|
||||
if (IsAxis(feature, SDLAxisUsage.RotateZ))
|
||||
control.WithUsages(CommonUsages.Twist);
|
||||
break;
|
||||
}
|
||||
|
||||
case JoystickFeatureType.Ball:
|
||||
{
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
|
||||
case JoystickFeatureType.Button:
|
||||
{
|
||||
var usage = (SDLButtonUsage)feature.usageHint;
|
||||
var featureName = LinuxSupport.GetButtonNameFromUsage(usage);
|
||||
if (featureName != null)
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Button")
|
||||
.WithByteOffset((uint)feature.offset)
|
||||
.WithBitOffset((uint)feature.bit)
|
||||
.WithFormat(InputStateBlock.FormatBit);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JoystickFeatureType.Hat:
|
||||
{
|
||||
var usage = (SDLAxisUsage)feature.usageHint;
|
||||
var featureName = LinuxSupport.GetAxisNameFromUsage(usage);
|
||||
var parameters = "scale,scaleFactor=2147483647,clamp=1,clampMin=-1,clampMax=1";
|
||||
|
||||
if (i + 1 < m_Descriptor.controls.Length)
|
||||
{
|
||||
var nextFeature = m_Descriptor.controls[i + 1];
|
||||
if (IsHatY(nextFeature) && HatNumber(feature) == HatNumber(nextFeature))
|
||||
{
|
||||
BuildHatFeature(ref builder, feature, nextFeature);
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsHatY(feature))
|
||||
parameters += ",invert";
|
||||
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Analog")
|
||||
.WithByteOffset((uint)feature.offset)
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithParameters(parameters);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
throw new NotImplementedException(
|
||||
$"SDLLayoutBuilder.Build: Trying to build an SDL device with an unknown feature of type {feature.featureType}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR || UNITY_STANDALONE_LINUX
|
Reference in New Issue
Block a user