Skip to content

Commit

Permalink
FIX: fixed logic when checking for next composite part in the TreeView (
Browse files Browse the repository at this point in the history
#1925)

* Fixed logic when checking for next composite part in the TreeView

* Added test case for multiple bindings per composite part for Vector2 composite type.

---------

Co-authored-by: Håkan Sidenvall <[email protected]>
Co-authored-by: Paulius Dervinis <[email protected]>
  • Loading branch information
3 people authored Jul 1, 2024
1 parent 01326cb commit 37d120e
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 17 deletions.
159 changes: 159 additions & 0 deletions Assets/Tests/InputSystem/CoreTests_Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9610,6 +9610,165 @@ public void Actions_Vector2Composite_WithKeyboardKeys_CancelOnRelease()
}
}

[Test]
[Category("Actions")]
public void Actions_CanCreateComposite_WithMultipleBindingsPerPart()
{
var keyboard = InputSystem.AddDevice<Keyboard>();

// Set up classic WASD control and additional arrow key support on the same composite.
var action = new InputAction();
action.AddCompositeBinding("Dpad")
.With("Up", "<Keyboard>/w")
.With("Down", "<Keyboard>/s")
.With("Left", "<Keyboard>/a")
.With("Right", "<Keyboard>/d")
.With("Up", "<Keyboard>/upArrow")
.With("Down", "<Keyboard>/downArrow")
.With("Left", "<Keyboard>/leftArrow")
.With("Right", "<Keyboard>/rightArrow");
action.Enable();

Vector2? value = null;
action.performed += ctx => { value = ctx.ReadValue<Vector2>(); };

// Up.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.W));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.up));

// Up left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.W, Key.A));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.up + Vector2.left).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.up + Vector2.left).normalized.y).Within(0.00001));

// Left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.A));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.left));

// Down left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.A, Key.S));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.left + Vector2.down).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.left + Vector2.down).normalized.y).Within(0.00001));

// Down.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.S));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.down));

// Down right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.S, Key.D));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.down + Vector2.right).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.down + Vector2.right).normalized.y).Within(0.00001));

// Right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.D));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.right));

// Up right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.D, Key.W));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.right + Vector2.up).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.right + Vector2.up).normalized.y).Within(0.00001));

// Up.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.UpArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.up));

// Up left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.UpArrow, Key.LeftArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.up + Vector2.left).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.up + Vector2.left).normalized.y).Within(0.00001));

// Left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.LeftArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.left));

// Down left.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.LeftArrow, Key.DownArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.left + Vector2.down).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.left + Vector2.down).normalized.y).Within(0.00001));

// Down.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.DownArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.down));

// Down right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.DownArrow, Key.RightArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.down + Vector2.right).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.down + Vector2.right).normalized.y).Within(0.00001));

// Right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.RightArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value, Is.EqualTo(Vector2.right));

// Up right.
value = null;
InputSystem.QueueStateEvent(keyboard, new KeyboardState(Key.RightArrow, Key.UpArrow));
InputSystem.Update();

Assert.That(value, Is.Not.Null);
Assert.That(value.Value.x, Is.EqualTo((Vector2.right + Vector2.up).normalized.x).Within(0.00001));
Assert.That(value.Value.y, Is.EqualTo((Vector2.right + Vector2.up).normalized.y).Within(0.00001));
}

[Test]
[Category("Actions")]
public void Actions_CanCreateComposite_WithPartsBeingOutOfOrder()
Expand Down
1 change: 1 addition & 0 deletions Packages/com.unity.inputsystem/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ however, it has to be formatted properly to pass verification tests.
- Added additional device information when logging the error due to exceeding the maximum number of events processed
set by `InputSystem.settings.maxEventsBytesPerUpdate`. This additional information is available in development builds
only.
- Fixed deletion of last composite part raising an exception. [ISXB-804](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-804)

### Changed
- Changed `DualSenseHIDInputReport` from internal to public visibility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,30 +611,38 @@ public static List<TreeViewItemData<ActionOrBindingData>> GetActionsAsTreeViewDa

if (serializedInputBinding.isComposite)
{
var isLastBinding = i >= actionBindings.Count - 1;
var hasHiddenCompositeParts = false;

var compositeItems = new List<TreeViewItemData<ActionOrBindingData>>();
var nextBinding = actionBindings[++i];
var hiddenCompositeParts = false;
while (nextBinding.isPartOfComposite)

if (!isLastBinding)
{
var isVisible = ShouldBindingBeVisible(nextBinding, state.selectedControlScheme, state.selectedDeviceRequirementIndex);
if (isVisible)
var nextBinding = actionBindings[++i];

while (nextBinding.isPartOfComposite)
{
var name = GetHumanReadableCompositeName(nextBinding, state.selectedControlScheme, controlSchemes);
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(new Guid(nextBinding.id), idDictionary),
new ActionOrBindingData(isAction: false, name, actionMapIndex, isComposite: false,
isPartOfComposite: true, GetControlLayout(nextBinding.path), bindingIndex: nextBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, nextBinding.indexOfBinding))));
var isVisible = ShouldBindingBeVisible(nextBinding, state.selectedControlScheme, state.selectedDeviceRequirementIndex);
if (isVisible)
{
var name = GetHumanReadableCompositeName(nextBinding, state.selectedControlScheme, controlSchemes);
compositeItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(new Guid(nextBinding.id), idDictionary),
new ActionOrBindingData(isAction: false, name, actionMapIndex, isComposite: false,
isPartOfComposite: true, GetControlLayout(nextBinding.path), bindingIndex: nextBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, nextBinding.indexOfBinding))));
}
else
hasHiddenCompositeParts = true;

if (++i >= actionBindings.Count)
break;

nextBinding = actionBindings[i];
}
else
hiddenCompositeParts = true;

if (++i >= actionBindings.Count)
break;

nextBinding = actionBindings[i];
i--;
}
i--;

var shouldCompositeBeVisible = !(compositeItems.Count == 0 && hiddenCompositeParts); //hide composite if all parts are hidden
var shouldCompositeBeVisible = !(compositeItems.Count == 0 && hasHiddenCompositeParts); //hide composite if all parts are hidden
if (shouldCompositeBeVisible)
bindingItems.Add(new TreeViewItemData<ActionOrBindingData>(GetIdForGuid(inputBindingId, idDictionary),
new ActionOrBindingData(isAction: false, serializedInputBinding.name, actionMapIndex, isComposite: true, isPartOfComposite: false, action.expectedControlType, bindingIndex: serializedInputBinding.indexOfBinding, isCut: state.IsBindingCut(actionMapIndex, serializedInputBinding.indexOfBinding)),
Expand Down

0 comments on commit 37d120e

Please sign in to comment.