internal void AddChildControls(string controlName, ref InputControlLayout.Builder builder) { if (usagePage == UsagePage.GenericDesktop && usage == (int)GenericDesktop.HatSwitch) { // There doesn't seem to be enough specificity in the HID spec to reliably figure this case out. // Albeit detail is scarce, we could probably make some inferences based on the unit setting // of the hat switch but even then it seems there's much left to the whims of a hardware manufacturer. // Even if we know values go clockwise (HID spec doesn't really say; probably can be inferred from unit), // which direction do we start with? Is 0 degrees up or right? // // What we do here is simply make the assumption that we're dealing with degrees here, that we go clockwise, // and that 0 degrees is up (which is actually the opposite of the coordinate system suggested in 5.9 of // of the HID spec but seems to be what manufacturers are actually using in practice). Of course, if the // device we're looking at actually sets things up differently, then we end up with either an incorrectly // oriented or (worse) a non-functional hat switch. var nullValue = DetermineDefaultState(); if (nullValue.isEmpty) return; ////REVIEW: this probably only works with hatswitches that have their null value at logicalMax+1 builder.AddControl(controlName + "/up") .WithFormat(InputStateBlock.kTypeBit) .WithLayout("DiscreteButton") .WithParameters(string.Format(CultureInfo.InvariantCulture, "minValue={0},maxValue={1},nullValue={2},wrapAtValue={3}", logicalMax, logicalMin + 1, nullValue.ToString(), logicalMax)) .WithBitOffset(0) .WithSizeInBits((uint)reportSizeInBits); builder.AddControl(controlName + "/right") .WithFormat(InputStateBlock.kTypeBit) .WithLayout("DiscreteButton") .WithParameters(string.Format(CultureInfo.InvariantCulture, "minValue={0},maxValue={1}", logicalMin + 1, logicalMin + 3)) .WithBitOffset(0) .WithSizeInBits((uint)reportSizeInBits); builder.AddControl(controlName + "/down") .WithFormat(InputStateBlock.kTypeBit) .WithLayout("DiscreteButton") .WithParameters(string.Format(CultureInfo.InvariantCulture, "minValue={0},maxValue={1}", logicalMin + 3, logicalMin + 5)) .WithBitOffset(0) .WithSizeInBits((uint)reportSizeInBits); builder.AddControl(controlName + "/left") .WithFormat(InputStateBlock.kTypeBit) .WithLayout("DiscreteButton") .WithParameters(string.Format(CultureInfo.InvariantCulture, "minValue={0},maxValue={1}", logicalMin + 5, logicalMin + 7)) .WithBitOffset(0) .WithSizeInBits((uint)reportSizeInBits); } }
public InputControlLayout Build() { var builder = new InputControlLayout.Builder { type = typeof(HID), stateFormat = new FourCC('H', 'I', 'D'), }; ////TODO: for joysticks, set up stick from X and Y // Process HID descriptor. foreach (var element in hidDescriptor.elements) { if (element.reportType != HIDReportType.Input) { continue; } var layout = element.DetermineLayout(); if (layout != null) { // Assign unique name. var name = element.DetermineName(); Debug.Assert(!string.IsNullOrEmpty(name)); name = StringHelpers.MakeUniqueName(name, builder.controls, x => x.name); // Add control. var control = builder.AddControl(name) .WithLayout(layout) .WithByteOffset((uint)element.reportOffsetInBits / 8) .WithBitOffset((uint)element.reportOffsetInBits % 8) .WithSizeInBits((uint)element.reportSizeInBits) .WithFormat(element.DetermineFormat()) .WithDefaultState(element.DetermineDefaultState()); var parameters = element.DetermineParameters(); if (!string.IsNullOrEmpty(parameters)) { control.WithParameters(parameters); } var usages = element.DetermineUsages(); if (usages != null) { control.WithUsages(usages); } element.AddChildControls(name, ref builder); } } return(builder.Build()); }
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 void BuildHatFeature(ref InputControlLayout.Builder builder, SDLFeatureDescriptor xFeature, SDLFeatureDescriptor yFeature) { string xFeatureName = SDLSupport.GetAxisNameFromUsage((SDLAxisUsage)xFeature.usageHint); string yFeatureName = SDLSupport.GetAxisNameFromUsage((SDLAxisUsage)yFeature.usageHint); var hat = HatNumber(xFeature); var hatName = (hat > 1) ? $"Hat{hat}" : "Hat"; var control = builder.AddControl(hatName) .WithLayout("Dpad") .WithByteOffset((uint)xFeature.offset) .WithSizeInBits((uint)xFeature.size * 8) .WithUsages(new InternedString[] { CommonUsages.Hatswitch }); builder.AddControl(hatName + "/up") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=0,invert") .WithByteOffset(4) .WithSizeInBits((uint)yFeature.size * 8); builder.AddControl(hatName + "/down") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=0,clampMax=1") .WithByteOffset(4) .WithSizeInBits((uint)yFeature.size * 8); builder.AddControl(hatName + "/left") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=0,invert") .WithByteOffset(0) .WithSizeInBits((uint)xFeature.size * 8); builder.AddControl(hatName + "/right") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=0,clampMax=1") .WithByteOffset(0) .WithSizeInBits((uint)xFeature.size * 8); builder.AddControl(hatName + "/x") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Analog") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=0,clampMax=1") .WithByteOffset(0) .WithSizeInBits((uint)xFeature.size * 8); builder.AddControl(hatName + "/y") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Analog") .WithParameters("scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=1,invert") .WithByteOffset(4) .WithSizeInBits((uint)yFeature.size * 8); }
public InputControlLayout Build() { var builder = new InputControlLayout.Builder { type = typeof(HID), stateFormat = new FourCC('H', 'I', 'D'), }; ////TODO: for joysticks, set up stick from X and Y // Process HID descriptor. foreach (var element in hidDescriptor.elements) { if (element.reportType != HIDReportType.Input) { continue; } var layout = element.DetermineLayout(); if (layout != null) { var control = builder.AddControl(element.DetermineName()) .WithLayout(layout) .WithOffset((uint)element.reportOffsetInBits / 8) .WithBit((uint)element.reportOffsetInBits % 8) .WithFormat(element.DetermineFormat()); var parameters = element.DetermineParameters(); if (!string.IsNullOrEmpty(parameters)) { control.WithParameters(parameters); } var usages = element.DetermineUsages(); if (usages != null) { control.WithUsages(usages); } } } return(builder.Build()); }
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"); }
/// <summary> /// /// </summary> /// <param name="defaultMap"></param> /// <param name="layoutName"></param> /// <returns></returns> internal static void RegisterLayoutBuilder(InputActionMap defaultMap, string layoutName) { if (InputSystem.LoadLayout(layoutName) == null) { InputSystem.RegisterLayoutBuilder(() => { // TODO does this need to change based on the action map we use? var builder = new InputControlLayout.Builder() .WithName(layoutName) .WithFormat(mlAgentsLayoutFormat); for (var i = 0; i < defaultMap.actions.Count; i++) { var action = defaultMap.actions[i]; builder.AddControl(action.name) .WithLayout(action.expectedControlType); } return(builder.Build()); }, layoutName); } }
public InputControlLayout Build() { var builder = new InputControlLayout.Builder { type = typeof(WebGLJoystick), extendsLayout = "Joystick", stateFormat = new FourCC('H', 'T', 'M', 'L') }; // Best guess: Treat first two axes as stick uint offset = 0; if (capabilities.numAxes >= 2) { var stickName = "Stick"; builder.AddControl(stickName) .WithLayout("Stick") .WithByteOffset(offset) .WithSizeInBits(64) .WithFormat(InputStateBlock.FormatFloat); builder.AddControl(stickName + "/x") .WithLayout("Axis") .WithByteOffset(offset) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); builder.AddControl(stickName + "/y") .WithLayout("Axis") .WithByteOffset(offset + 4) .WithParameters("invert") .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); //Need to handle Up/Down/Left/Right builder.AddControl(stickName + "/up") .WithLayout("Button") .WithParameters("clamp=1,clampMin=-1,clampMax=0,invert") .WithByteOffset(offset + 4) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); builder.AddControl(stickName + "/down") .WithLayout("Button") .WithParameters("clamp=1,clampMin=0,clampMax=1") .WithByteOffset(offset + 4) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); builder.AddControl(stickName + "/left") .WithLayout("Button") .WithParameters("clamp=1,clampMin=-1,clampMax=0,invert") .WithByteOffset(offset) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); builder.AddControl(stickName + "/right") .WithLayout("Button") .WithParameters("clamp=1,clampMin=0,clampMax=1") .WithByteOffset(offset) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); offset += 8; } for (var axis = 2; axis < capabilities.numAxes; axis++) { builder.AddControl($"Axis {axis - 1}") .WithLayout("Axis") .WithByteOffset(offset) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); offset += 4; } var buttonStartOffset = offset; for (var button = 0; button < capabilities.numButtons; button++) { builder.AddControl($"Button {button + 1}") .WithLayout("Button") .WithByteOffset(offset) .WithSizeInBits(32) .WithFormat(InputStateBlock.FormatFloat); offset += 4; } builder.AddControl("Trigger") .WithLayout("AnyKey") .WithByteOffset(buttonStartOffset) .IsSynthetic(true) .WithSizeInBits((uint)(32 * capabilities.numButtons)) .WithFormat(InputStateBlock.FormatBit); return(builder.Build()); }
public void Remote_OnlyGeneratedLayoutsAreSentToRemotes() { // Register "normal" layout. InputSystem.RegisterLayout(@" { ""name"" : ""TestLayout_NOT_GENERATED"", ""extend"" : ""Gamepad"", ""controls"" : [ { ""name"" : ""newButton"", ""layout"" : ""Button"" } ] } "); // Register generated layout. InputSystem.RegisterLayoutBuilder(() => { var builder = new InputControlLayout.Builder() .WithType <MyDevice>(); builder.AddControl("MyControl") .WithLayout("Button"); return(builder.Build()); }, "TestLayout_GENERATED"); using (var remote = new FakeRemote()) { Assert.That(remote.remoteManager.ListControlLayouts(), Has.None.EqualTo("TestLayout_NOT_GENERATED")); // Not remoted. Assert.That(remote.remoteManager.ListControlLayouts(), Has.Exactly(1).EqualTo("TestLayout_GENERATED")); // Remoted. // Make sure we do not remote "normal" layouts. Assert.That(remote.remoteManager.ListControlLayouts(), Has.None.Matches((string s) => s.StartsWith("Remote::") && s.EndsWith("Gamepad"))); // Add a device using the layout builder. InputSystem.AddDevice("TestLayout_GENERATED"); Assert.That(remote.remoteManager.devices, Has.Count.EqualTo(1)); Assert.That(remote.remoteManager.devices[0].layout, Is.EqualTo("TestLayout_GENERATED")); Assert.That(remote.remoteManager.devices[0].remote, Is.True); // Register another "normal" layout. InputSystem.RegisterLayout(@" { ""name"" : ""OtherLayout_NOT_GENERATED"", ""extend"" : ""Gamepad"", ""controls"" : [ { ""name"" : ""newButton"", ""layout"" : ""Button"" } ] } "); Assert.That(remote.remoteManager.ListControlLayouts(), Has.None.EqualTo("OtherLayout_NOT_GENERATED")); // Not remoted. // Register another generated layout. InputSystem.RegisterLayoutBuilder(() => { var builder = new InputControlLayout.Builder() .WithType <MyDevice>(); builder.AddControl("MyControl") .WithLayout("Button"); return(builder.Build()); }, "OtherLayout_GENERATED"); Assert.That(remote.remoteManager.ListControlLayouts(), Has.Exactly(1).EqualTo("OtherLayout_GENERATED")); // Remoted. // Remove the two layouts we just added. Shouldn't make a difference // on the remote. InputSystem.RemoveLayout("OtherLayout_GENERATED"); InputSystem.RemoveLayout("OtherLayout_NOT_GENERATED"); Assert.That(remote.remoteManager.ListControlLayouts(), Has.None.EqualTo("OtherLayout_NOT_GENERATED")); // Not remoted. Assert.That(remote.remoteManager.ListControlLayouts(), Has.Exactly(1).EqualTo("OtherLayout_GENERATED")); // Remoted. } }
internal InputControlLayout Build() { var builder = new InputControlLayout.Builder { stateFormat = new FourCC('L', 'J', 'O', 'Y'), extendsLayout = parentLayout }; for (var i = 0; i < descriptor.controls.Count; i++) { SDLFeatureDescriptor feature = descriptor.controls[i]; switch (feature.featureType) { case JoystickFeatureType.Axis: { SDLAxisUsage usage = (SDLAxisUsage)feature.usageHint; string featureName = SDLSupport.GetAxisNameFromUsage(usage); string parameters = "scale,scaleFactor=65538,clamp,clampMin=-1,clampMax=1"; if (IsAxisX(feature) && i + 1 < descriptor.controls.Count) { SDLFeatureDescriptor nextFeature = descriptor.controls[i + 1]; if (IsAxisY(nextFeature)) { BuildStickFeature(ref builder, feature, nextFeature); } } if (IsAxisY(feature)) { parameters += ",invert"; } builder.AddControl(featureName) .WithLayout("Analog") .WithByteOffset((uint)feature.offset) .WithFormat(InputStateBlock.kTypeInt) .WithParameters(parameters); } break; case JoystickFeatureType.Ball: { //TODO } break; case JoystickFeatureType.Button: { SDLButtonUsage usage = (SDLButtonUsage)feature.usageHint; string featureName = SDLSupport.GetButtonNameFromUsage(usage); if (featureName != null) { builder.AddControl(featureName) .WithLayout("Button") .WithByteOffset((uint)feature.offset) .WithBitOffset((uint)feature.bit) .WithFormat(InputStateBlock.kTypeBit); } } break; case JoystickFeatureType.Hat: { SDLAxisUsage usage = (SDLAxisUsage)feature.usageHint; string featureName = SDLSupport.GetAxisNameFromUsage(usage); string parameters = "scale,scaleFactor=2147483647,clamp,clampMin=-1,clampMax=1"; if (i + 1 < descriptor.controls.Count) { SDLFeatureDescriptor nextFeature = descriptor.controls[i + 1]; if (IsHatY(nextFeature) && HatNumber(feature) == HatNumber(nextFeature)) { BuildHatFeature(ref builder, feature, nextFeature); } } if (IsHatY(feature)) { parameters += ",invert"; } builder.AddControl(featureName) .WithLayout("Analog") .WithByteOffset((uint)feature.offset) .WithFormat(InputStateBlock.kTypeInt) .WithParameters(parameters); } break; default: { throw new NotImplementedException(String.Format("SDLLayoutBuilder.Build: Trying to build an SDL device with an unknown feature of type {0}.", feature.featureType)); } } } return(builder.Build()); }
internal void BuildStickFeature(ref InputControlLayout.Builder builder, SDLFeatureDescriptor xFeature, SDLFeatureDescriptor yFeature) { int byteOffset; if (xFeature.offset <= yFeature.offset) { byteOffset = xFeature.offset; } else { byteOffset = yFeature.offset; } var stickName = "Stick"; var control = builder.AddControl(stickName) .WithLayout("Stick") .WithByteOffset((uint)byteOffset) .WithSizeInBits((uint)xFeature.size * 8) .WithUsages(new InternedString[] { CommonUsages.Primary2DMotion }); builder.AddControl(stickName + "/x") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Axis") .WithByteOffset(0) .WithSizeInBits((uint)xFeature.size * 8) .WithParameters("clamp,clampMin=-1,clampMax=1,scale,scaleFactor=65538"); builder.AddControl(stickName + "/y") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Axis") .WithByteOffset((uint)4) .WithSizeInBits((uint)xFeature.size * 8) .WithParameters("clamp,clampMin=-1,clampMax=1,scale,scaleFactor=65538,invert"); //Need to handle Up/Down/Left/Right builder.AddControl(stickName + "/up") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("clamp,clampMin=-1,clampMax=0,scale,scaleFactor=65538,invert") .WithByteOffset((uint)4) .WithSizeInBits((uint)yFeature.size * 8); builder.AddControl(stickName + "/down") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("clamp,clampMin=0,clampMax=1,scale,scaleFactor=65538,invert=false") .WithByteOffset((uint)4) .WithSizeInBits((uint)yFeature.size * 8); builder.AddControl(stickName + "/left") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("clamp,clampMin=-1,clampMax=0,scale,scaleFactor=65538,invert") .WithByteOffset((uint)0) .WithSizeInBits((uint)xFeature.size * 8); builder.AddControl(stickName + "/right") .WithFormat(InputStateBlock.kTypeInt) .WithLayout("Button") .WithParameters("clamp,clampMin=0,clampMax=1,scale,scaleFactor=65538") .WithByteOffset((uint)0) .WithSizeInBits((uint)xFeature.size * 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()); }
private InputControlLayout Build() { var builder = new InputControlLayout.Builder { stateFormat = new FourCC('X', 'R', 'S', '0'), extendsLayout = parentLayout, updateBeforeRender = true }; var inheritedLayout = !string.IsNullOrEmpty(parentLayout) ? InputSystem.LoadLayout(parentLayout) : null; var currentUsages = new List <string>(); uint currentOffset = 0; foreach (var feature in descriptor.inputFeatures) { currentUsages.Clear(); if (feature.usageHints != null) { foreach (var usageHint in feature.usageHints) { if (!string.IsNullOrEmpty(usageHint.content)) { currentUsages.Add(usageHint.content); } } } var featureName = feature.name; featureName = SanitizeName(featureName); if (inheritedLayout != null) { featureName = ConvertPotentialAliasToName(inheritedLayout, featureName); } featureName = featureName.ToLower(); uint nextOffset = GetSizeOfFeature(feature); if (interfaceName == XRUtilities.InterfaceV1) { #if UNITY_ANDROID if (nextOffset < 4) { nextOffset = 4; } #endif } else { if (nextOffset >= 4 && (currentOffset % 4 != 0)) { currentOffset += (4 - (currentOffset % 4)); } } switch (feature.featureType) { case FeatureType.Binary: { builder.AddControl(featureName) .WithLayout("Button") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatBit) .WithUsages(currentUsages); break; } case FeatureType.DiscreteStates: { builder.AddControl(featureName) .WithLayout("Integer") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatInt) .WithUsages(currentUsages); break; } case FeatureType.Axis1D: { builder.AddControl(featureName) .WithLayout("Analog") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatFloat) .WithUsages(currentUsages); break; } case FeatureType.Axis2D: { builder.AddControl(featureName) .WithLayout("Vector2") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatVector2) .WithUsages(currentUsages); break; } case FeatureType.Axis3D: { builder.AddControl(featureName) .WithLayout("Vector3") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatVector3) .WithUsages(currentUsages); break; } case FeatureType.Rotation: { builder.AddControl(featureName) .WithLayout("Quaternion") .WithByteOffset(currentOffset) .WithFormat(InputStateBlock.FormatQuaternion) .WithUsages(currentUsages); break; } case FeatureType.Hand: { break; } case FeatureType.Bone: { builder.AddControl(featureName) .WithLayout("Bone") .WithByteOffset(currentOffset) .WithUsages(currentUsages); break; } case FeatureType.Eyes: { builder.AddControl(featureName) .WithLayout("Eyes") .WithByteOffset(currentOffset) .WithUsages(currentUsages); break; } } currentOffset += nextOffset; } return(builder.Build()); }