Exemple #1
0
            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);
                }
            }
Exemple #2
0
        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);
        }
Exemple #3
0
            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 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");
        }
Exemple #5
0
            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());
            }
 /// <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);
     }
 }
        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);
        }
Exemple #8
0
            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());
            }
Exemple #9
0
    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.
        }
    }
Exemple #10
0
        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());
        }
Exemple #11
0
        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());
        }
Exemple #13
0
        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());
        }