Search Unity

Question InputSystem.QueueDeltaStateEvent for bitfield

Discussion in 'Input System' started by pajamajama, Dec 2, 2022.

  1. pajamajama

    pajamajama

    Joined:
    Oct 22, 2012
    Posts:
    66
    I have a custom device/layout. My button states are stored in a ushort bitfield.
    InputSystem.QueueDeltaStateEvent throws an error.
    Is there a workaround? Thanks much!

    [InputControl(name = "buttonA", layout = "Button", bit = 0)]
    [InputControl(name = "buttonB", layout = "Button", bit = 1)]
    public ushort buttons;


    InvalidOperationException: Cannot send delta state events against bitfield controls: Button:/AxisOrangeInputDevice/buttonB
     
  2. abegue

    abegue

    Joined:
    Jan 28, 2019
    Posts:
    24
    Got same issue and this the only place on Internet where the subject is raised so I will try to answer the question for other people who encounter the same issue.

    This error messages is triggered from this condition:
    Code (CSharp):
    1. if (control.stateBlock.bitOffset != 0)
    2.     throw new InvalidOperationException($"Cannot send delta state events against bitfield controls: {control}");
    So, you just cannot use
    InputSystem.QueueDeltaStateEvent
    on a
    InputControl
    that use bitfields (that was the case in your example with bit = 0 and bit = 1.


    In my own case, it was due to
    UnityEngine.InputSystem.TrackedDevice
    .
    Code (CSharp):
    1. [InputControl(synthetic = true)]
    2. public ButtonControl isTracked { get; private set; }
    The message appeared when trying to set the delta state event on this
    InputControl
    . However there is no bit field manipulation so I do not understand why. When debugging, its
    stateBlock.bitOffset
    is 5.

    My own code is based on
    Unity.XR.Hands.XRHandDevice
    and they use
    InputSystem.InputSystem.QueueDeltaStateEvent(isTracked, false);
    with no problem, but I cannot.

    Well, a workaround is to get ride of
    InputSystem.QueueDeltaStateEvent
    and use
    StateEvent.From
    and
    InputControl.WriteValueIntoEvent
    .
    Here is an example:
    Code (CSharp):
    1. using (StateEvent.From(this, out InputEventPtr eventPtr))
    2. {
    3. ...
    4. devicePosition.WriteValueIntoEvent(position, eventPtr);
    5. deviceRotation.WriteValueIntoEvent(rotation, eventPtr);
    6. isTracked.WriteValueIntoEvent(isDeviceTracked ? 1.0f : 0.0f, eventPtr);
    7. ...
    8. }
    Be really careful on the type you use when using
    WriteValueIntoEvent
    . For example, the
    ButtonControl
    use a float internally so you may want to set:
    buttonControl.WriteValueIntoEvent(isPressed ? 1.0f : 0.0f);
    instead of
    buttonControl.WriteValueIntoEvent(isPressed);
     
  3. wechat_os_Qy01eDJfSV7CWSHuAPwDqgMCA

    wechat_os_Qy01eDJfSV7CWSHuAPwDqgMCA

    Joined:
    Aug 4, 2022
    Posts:
    8
    I had the same issue and accidentally solved it.
    Here's my code that gives
    InvalidOperationException: Cannot send delta state events against bitfield controls
    for
    InputSystem.QueueDeltaStateEvent(poking, isPoking);
    . However,
    InputSystem.QueueDeltaStateEvent(grabbableGrabbed, isGrabbableGrabbed);
    was working fine. This is weird because poking and grabbableGrabbed have the same types.

    My solution is adding the
    offset = 0
    to the
    [InputControl]
    tag:
    Code (CSharp):
    1.     [InputControl(offset = 0)]
    2.     public ButtonControl grabbableGrabbed { get; private set; }
    3.    
    4.     [InputControl(offset = 1)]
    5.     public ButtonControl poking { get; private set; }
    and updating works fine...
    Code (CSharp):
    1. InputSystem.QueueDeltaStateEvent(grabbableGrabbed, isGrabbableGrabbed);
    2. InputSystem.QueueDeltaStateEvent(poking, isPoking);