@@ -329,11 +329,45 @@ public void Actions_Priority_PressingModifierShortcutWithSameBinding_TriggersHig
329329 Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
330330 InputSystem.Update();
331331
332- // Action2 won't be performed due to the priority being below action2
332+ // Action1 is not performed because action2 has higher priority on the shared key.
333333 Assert.That(action1.WasPerformedThisFrame(), Is.False);
334334 Assert.That(action2.WasPerformedThisFrame(), Is.True);
335335 }
336336
337+ [Test]
338+ [Category("Actions Priority")]
339+ [TestCase("ctrl", "x", true)]
340+ [TestCase("ctrl", "x", false)]
341+ public void Actions_Priority_SimpleBindingHigherPriority_PreemptsCompositeOnSharedKey(string sharedModifier, string binding1, bool legacyComposites)
342+ {
343+ InputSystem.settings.shortcutKeysConsumeInput = true;
344+ var keyboard = InputSystem.AddDevice<Keyboard>();
345+ var map = new InputActionMap("map");
346+
347+ var action1 = map.AddAction("action1");
348+ action1.AddBinding("<Keyboard>/" + binding1);
349+
350+ var action2 = map.AddAction("action2");
351+ action2.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
352+ .With("Modifier", "<Keyboard>/" + sharedModifier)
353+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
354+
355+ action1.Priority = 10;
356+ action2.Priority = 9;
357+
358+ map.Enable();
359+
360+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
361+ Assert.That(action2.WasPerformedThisFrame(), Is.False);
362+
363+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
364+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
365+ InputSystem.Update();
366+
367+ Assert.That(action1.WasPerformedThisFrame(), Is.True);
368+ Assert.That(action2.WasPerformedThisFrame(), Is.False);
369+ }
370+
337371 [Test]
338372 [Category("Actions Priority")]
339373 [TestCase("ctrl", "shift", "x", false)]
@@ -370,11 +404,172 @@ public void Actions_Priority_PressingTwoShortcutAtSameTime_TriggersOneShortcutDu
370404 Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
371405 InputSystem.Update();
372406
373- // Action1 won't be performed due to the priority being below action2
407+ // Action1 is not performed because action2 has higher priority on the shared key.
408+ Assert.That(action1WasPerformed, Is.False);
409+ Assert.That(action2.WasPerformedThisFrame(), Is.True);
410+ }
411+
412+ [Test]
413+ [Category("Actions Priority")]
414+ [TestCase("ctrl", "shift", "x", false)]
415+ [TestCase("ctrl", "shift", "x", true)]
416+ public void Actions_Priority_TwoShortcuts_HigherNumericPriorityWins(string sharedModifier, string sharedModifier2, string binding1, bool legacyComposites)
417+ {
418+ InputSystem.settings.shortcutKeysConsumeInput = true;
419+ var keyboard = InputSystem.AddDevice<Keyboard>();
420+
421+ var map = new InputActionMap("map");
422+ var action1 = map.AddAction("action1");
423+ action1.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
424+ .With("Modifier", "<Keyboard>/" + sharedModifier)
425+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
426+
427+ var action2 = map.AddAction("action2");
428+ action2.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
429+ .With("Modifier", "<Keyboard>/" + sharedModifier2)
430+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
431+
432+ action1.Priority = 2;
433+ action2.Priority = 100;
434+
435+ map.Enable();
436+
437+ var action1WasPerformed = false;
438+ action1.performed += _ => action1WasPerformed = true;
439+
440+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
441+ Press((ButtonControl)keyboard[sharedModifier2], queueEventOnly: true);
442+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
443+ InputSystem.Update();
444+
374445 Assert.That(action1WasPerformed, Is.False);
375446 Assert.That(action2.WasPerformedThisFrame(), Is.True);
376447 }
377448
449+ [Test]
450+ [Category("Actions Priority")]
451+ [TestCase("ctrl", "shift", "x", false)]
452+ [TestCase("ctrl", "shift", "x", true)]
453+ public void Actions_Priority_EqualPriority_ConflictingShortcuts_FirstActionInMapWins(string sharedModifier, string sharedModifier2, string binding1, bool legacyComposites)
454+ {
455+ InputSystem.settings.shortcutKeysConsumeInput = true;
456+ var keyboard = InputSystem.AddDevice<Keyboard>();
457+
458+ var map = new InputActionMap("map");
459+ var action1 = map.AddAction("action1");
460+ action1.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
461+ .With("Modifier", "<Keyboard>/" + sharedModifier)
462+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
463+
464+ var action2 = map.AddAction("action2");
465+ action2.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
466+ .With("Modifier", "<Keyboard>/" + sharedModifier2)
467+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
468+
469+ action1.Priority = 5;
470+ action2.Priority = 5;
471+
472+ map.Enable();
473+
474+ var action2WasPerformed = false;
475+ action2.performed += _ => action2WasPerformed = true;
476+
477+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
478+ Press((ButtonControl)keyboard[sharedModifier2], queueEventOnly: true);
479+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
480+ InputSystem.Update();
481+
482+ Assert.That(action1.WasPerformedThisFrame(), Is.True);
483+ Assert.That(action2WasPerformed, Is.False);
484+ }
485+
486+ [Test]
487+ [Category("Actions Priority")]
488+ [TestCase("ctrl", "shift", "x", false)]
489+ [TestCase("ctrl", "shift", "x", true)]
490+ public void Actions_Priority_BothPrioritiesZero_ConflictingShortcuts_BothPerform(string sharedModifier, string sharedModifier2, string binding1, bool legacyComposites)
491+ {
492+ InputSystem.settings.shortcutKeysConsumeInput = true;
493+ var keyboard = InputSystem.AddDevice<Keyboard>();
494+
495+ var map = new InputActionMap("map");
496+ var action1 = map.AddAction("action1");
497+ action1.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
498+ .With("Modifier", "<Keyboard>/" + sharedModifier)
499+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
500+
501+ var action2 = map.AddAction("action2");
502+ action2.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
503+ .With("Modifier", "<Keyboard>/" + sharedModifier2)
504+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
505+
506+ action1.Priority = 0;
507+ action2.Priority = 0;
508+
509+ map.Enable();
510+
511+ var action1WasPerformed = false;
512+ var action2WasPerformed = false;
513+ action1.performed += _ => action1WasPerformed = true;
514+ action2.performed += _ => action2WasPerformed = true;
515+
516+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
517+ Press((ButtonControl)keyboard[sharedModifier2], queueEventOnly: true);
518+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
519+ InputSystem.Update();
520+
521+ Assert.That(action1WasPerformed, Is.True);
522+ Assert.That(action2WasPerformed, Is.True);
523+ }
524+
525+ [Test]
526+ [Ignore("Enable once we fix this")]
527+ [Category("Actions Priority")]
528+ [TestCase("ctrl", "shift", "x", false)]
529+ [TestCase("ctrl", "shift", "x", true)]
530+ public void Actions_Priority_ShortcutConsumeDisabled_BothPerformDespiteDifferentPriorities(string sharedModifier, string sharedModifier2, string binding1, bool legacyComposites)
531+ {
532+ var previousShortcutConsume = InputSystem.settings.shortcutKeysConsumeInput;
533+ try
534+ {
535+ InputSystem.settings.shortcutKeysConsumeInput = false;
536+ var keyboard = InputSystem.AddDevice<Keyboard>();
537+
538+ var map = new InputActionMap("map");
539+ var action1 = map.AddAction("action1");
540+ action1.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
541+ .With("Modifier", "<Keyboard>/" + sharedModifier)
542+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
543+
544+ var action2 = map.AddAction("action2");
545+ action2.AddCompositeBinding((legacyComposites ? "ButtonWithOneModifier" : "OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
546+ .With("Modifier", "<Keyboard>/" + sharedModifier2)
547+ .With(legacyComposites ? "Button" : "Binding", "<Keyboard>/" + binding1);
548+
549+ action1.Priority = 0;
550+ action2.Priority = 10;
551+
552+ map.Enable();
553+
554+ var action1WasPerformed = false;
555+ var action2WasPerformed = false;
556+ action1.performed += _ => action1WasPerformed = true;
557+ action2.performed += _ => action2WasPerformed = true;
558+
559+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
560+ Press((ButtonControl)keyboard[sharedModifier2], queueEventOnly: true);
561+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
562+ InputSystem.Update();
563+
564+ Assert.That(action1WasPerformed, Is.True);
565+ Assert.That(action2WasPerformed, Is.True);
566+ }
567+ finally
568+ {
569+ InputSystem.settings.shortcutKeysConsumeInput = previousShortcutConsume;
570+ }
571+ }
572+
378573 [UnityTest]
379574 [Category("Actions Priority")]
380575 public IEnumerator Actions_Priority_PressingTwoShortcutAtSameTime_TriggersBothDueToNoConflictingBinding()
@@ -413,7 +608,7 @@ public IEnumerator Actions_Priority_PressingTwoShortcutAtSameTime_TriggersBothDu
413608 Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
414609 InputSystem.Update();
415610
416- // Action1 won't be performed due to the priority being below action2
611+ // Different letter keys: no conflict on the same control, so both shortcuts can perform despite different priorities.
417612 Assert.That(action1WasPerformed, Is.True);
418613 Assert.That(action2.WasPerformedThisFrame(), Is.True);
419614
@@ -425,7 +620,159 @@ public IEnumerator Actions_Priority_PressingTwoShortcutAtSameTime_TriggersBothDu
425620
426621 InputSystem.Update();
427622
623+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
624+ Assert.That(action2.WasPerformedThisFrame(), Is.False);
625+ }
626+
627+ [UnityTest]
628+ [Category("Actions Priority")]
629+ public IEnumerator Actions_Priority_TwoNonConflictingShortcuts_ReversedPriorityOrder_BothStillPerform()
630+ {
631+ string sharedModifier = "ctrl";
632+ string binding1 = "x";
633+ string binding2 = "c";
634+
635+ InputSystem.settings.shortcutKeysConsumeInput = true;
636+ var keyboard = InputSystem.AddDevice<Keyboard>();
637+
638+ var map = new InputActionMap("map");
639+ var action1 = map.AddAction("action1");
640+ action1.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
641+ .With("Modifier", "<Keyboard>/" + sharedModifier)
642+ .With("Binding", "<Keyboard>/" + binding1);
643+
644+ var action2 = map.AddAction("action2");
645+ action2.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
646+ .With("Modifier", "<Keyboard>/" + sharedModifier)
647+ .With("Binding", "<Keyboard>/" + binding2);
648+
649+ // Higher priority on the first action; letter keys still differ so both should run.
650+ action1.Priority = 10;
651+ action2.Priority = 0;
652+
653+ map.Enable();
654+
655+ var action1WasPerformed = false;
656+ action1.performed += _ => action1WasPerformed = true;
657+
658+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
659+ Assert.That(action2.WasPerformedThisFrame(), Is.False);
660+
661+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
662+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
663+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
664+ InputSystem.Update();
665+
666+ Assert.That(action1WasPerformed, Is.True);
667+ Assert.That(action2.WasPerformedThisFrame(), Is.True);
668+
669+ yield return null;
670+
671+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
672+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
673+
674+ InputSystem.Update();
675+
676+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
428677 Assert.That(action2.WasPerformedThisFrame(), Is.False);
678+ }
679+
680+ [UnityTest]
681+ [Category("Actions Priority")]
682+ public IEnumerator Actions_Priority_TwoNonConflictingShortcuts_EqualHighPriority_BothPerform()
683+ {
684+ string sharedModifier = "ctrl";
685+ string binding1 = "x";
686+ string binding2 = "c";
687+
688+ InputSystem.settings.shortcutKeysConsumeInput = true;
689+ var keyboard = InputSystem.AddDevice<Keyboard>();
690+
691+ var map = new InputActionMap("map");
692+ var action1 = map.AddAction("action1");
693+ action1.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
694+ .With("Modifier", "<Keyboard>/" + sharedModifier)
695+ .With("Binding", "<Keyboard>/" + binding1);
696+
697+ var action2 = map.AddAction("action2");
698+ action2.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
699+ .With("Modifier", "<Keyboard>/" + sharedModifier)
700+ .With("Binding", "<Keyboard>/" + binding2);
701+
702+ action1.Priority = 500;
703+ action2.Priority = 500;
704+
705+ map.Enable();
706+
707+ var action1WasPerformed = false;
708+ action1.performed += _ => action1WasPerformed = true;
709+
710+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
711+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
712+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
713+ InputSystem.Update();
714+
715+ Assert.That(action1WasPerformed, Is.True);
716+ Assert.That(action2.WasPerformedThisFrame(), Is.True);
717+
718+ yield return null;
719+
720+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
721+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
722+
723+ InputSystem.Update();
724+
725+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
726+ Assert.That(action2.WasPerformedThisFrame(), Is.False);
727+ }
728+
729+ [UnityTest]
730+ [Category("Actions Priority")]
731+ public IEnumerator Actions_Priority_TwoNonConflictingShortcuts_ReverseActionDeclarationOrder_BothPerform()
732+ {
733+ string sharedModifier = "ctrl";
734+ string binding1 = "x";
735+ string binding2 = "c";
736+
737+ InputSystem.settings.shortcutKeysConsumeInput = true;
738+ var keyboard = InputSystem.AddDevice<Keyboard>();
739+
740+ var map = new InputActionMap("map");
741+ // Add the second shortcut's action first so registration order differs from the original test.
742+ var action2 = map.AddAction("action2");
743+ action2.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
744+ .With("Modifier", "<Keyboard>/" + sharedModifier)
745+ .With("Binding", "<Keyboard>/" + binding2);
746+
747+ var action1 = map.AddAction("action1");
748+ action1.AddCompositeBinding(("OneModifier") + "(overrideModifiersNeedToBePressedFirst)")
749+ .With("Modifier", "<Keyboard>/" + sharedModifier)
750+ .With("Binding", "<Keyboard>/" + binding1);
751+
752+ action1.Priority = 0;
753+ action2.Priority = 1;
754+
755+ map.Enable();
756+
757+ var action1WasPerformed = false;
758+ action1.performed += _ => action1WasPerformed = true;
759+
760+ Press((ButtonControl)keyboard[sharedModifier], queueEventOnly: true);
761+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
762+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
763+ InputSystem.Update();
764+
765+ Assert.That(action1WasPerformed, Is.True);
766+ Assert.That(action2.WasPerformedThisFrame(), Is.True);
767+
768+ yield return null;
769+
770+ Press((ButtonControl)keyboard[binding1], queueEventOnly: true);
771+ Press((ButtonControl)keyboard[binding2], queueEventOnly: true);
772+
773+ InputSystem.Update();
774+
775+ Assert.That(action1.WasPerformedThisFrame(), Is.False);
429776 Assert.That(action2.WasPerformedThisFrame(), Is.False);
430777 }
431778
0 commit comments