Impossible to get cancelling of control rebind working with both keyboard and gamepad

I’ve made a controls customization screen which allows rebinding of both keyboard and gamepad controls. Here’s the code which initiates rebinding:

rebind = actionReference.action.PerformInteractiveRebinding()
 .WithTargetBinding(bindingIndex)
 .WithMatchingEventsBeingSuppressed()
 .WithCancelingThrough("*/{Cancel}")
 .OnCancel(_ => RebindCancelled())
 .OnComplete(_ => RebindComplete());

I want the user to be able to cancel either by pressing Esc on the keyboard or Start on a gamepad, but there seems to be no way to achieve this. {Cancel} corresponds to Esc or B, which means the user can’t remap anything to the B button. And as the docs state, WithCancelingThrough cannot be used more than once. So it appears that it’s not possible to write code that allows for the cancelling system to work in this scenario.

You could detect which device was used to start the rebinding and then configure a different binding path for the canceling. There might be other things you want to configure differently when rebinding a keyboard input vs a gamepad input.

Or you could set up an action for canceling, filter out that action’s controls in the rebinding operation, and then manually cancel the operation when the action is performed.

I tried an alternative solution:

        rebind = actionReference.action.PerformInteractiveRebinding()
            .WithTargetBinding(bindingIndex)
            .OnPotentialMatch(operation =>
            {
                if (   operation.selectedControl.path == "/Keyboard/escape"
                    || operation.selectedControl.path.Contains("/start"))
                {
                    operation.Cancel();
                }
            })
            .WithMatchingEventsBeingSuppressed()
            .OnCancel(_ => RebindCancelled())
            .OnComplete(_ => RebindComplete());

However, ultimately I had to go with the solution of checking for cancel in Update. In my remapping screen, some of the buttons are just for gamepads and some are just for keyboard. This prevents both remapping and cancelling via the alternative device, e.g. if you try to rebind a keyboard binding, the keyboard must be used to cancel it. This would fail Steam’s requirements for games with full controller support.

1 Like

It turns out that I still need OnPotentialMatch, my code checking for cancel in Update was not preventing rebinding to Escape or Start. The OnPotentialMatch now prevents that, and the code in Update allows cancelling using a different device.