Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add virtual joypad buttons for semantic "yes"/"no" #103744

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Grublady
Copy link
Contributor

@Grublady Grublady commented Mar 7, 2025

This PR adds "virtual" joypad buttons which correspond to semantic inputs rather than physical inputs.

These virtual button events can be mapped to actions as usual, allowing interface actions such as "confirm" or "cancel" to use any supported controller's native semantics.

For example, although the A buttons on Xbox and Switch controllers send JoyButton::A and JoyButton::B respectively, both inputs would now also send JoyButton::SEMANTIC_YES as well.

Tested on macOS 15.3 with Switch Pro Controller and Switch Joy-Cons, needs testing on other platforms/controllers.

Motivation

Previously, joypad face button events were identified strictly by position (ie top, bottom, left, right).
This is typically desirable for gameplay, as the control layout can be designed once and keep the same ergonomics across controllers.

However, this system created a problem when accounting for controller layouts whose face button semantics are reversed:
For example, Xbox controllers use the bottom (A) button for "yes," "confirm," or "select" in menu navigation, whereas Switch controllers use the right (A) button for these purposes.
Thus, mapping one of these face button positions to menu navigation is always unintuitive for some controllers.

The goal of this PR is to allow developers to easily implement semantically-correct interaction.
This is relevant to most games, so I believe it makes sense as an engine feature.

@Grublady Grublady requested a review from a team as a code owner March 7, 2025 03:01
@AThousandShips AThousandShips added this to the 4.x milestone Mar 7, 2025
@JoNax97
Copy link
Contributor

JoNax97 commented Mar 7, 2025

Isn't mapping physical inputs to semantic ones the whole point of actions?
I'm not opposed to the underlying idea, I just feel we're reinventing the wheel and mixing comcerns here

@Grublady
Copy link
Contributor Author

Grublady commented Mar 7, 2025

Isn't mapping physical inputs to semantic ones the whole point of actions?

Yes, and in most cases this is sufficient.

The issue arises when the same physical input means something different depending on which controller is in use.

Specifically, Xbox controller users expect the bottom face button to act as "yes," whereas Nintendo controller users expect it to act as "no." (And vice versa for the right face button.)

@JoNax97
Copy link
Contributor

JoNax97 commented Mar 7, 2025

I ser your point now. I feel this might be addressed in a way that's more in line with the current way input works, by allowing defining a different physical input to an action based on controller type.

So for example, you create an accept action bound to Nintendo A and Xbox A, instead of mapping to generic "button 1". I imagine this would work similarly to choosing between physical and vs keycode when adding a keyboard input.

This way the semantics stay on the side of the action, while allowing different configurations for each platform.

How does that sound?

@Grublady
Copy link
Contributor Author

Grublady commented Mar 7, 2025

I ser your point now. I feel this might be addressed in a way that's more in line with the current way input works, by allowing defining a different physical input to an action based on controller type.

That might be another possibility, though I worry it may be a bit over-engineered.

Really the only scenario this PR currently seeks to address is the discrepancy in A & B buttons, and I think the complexity of providing per-controller-type events would be overkill for this case.

Is there another use case you have in mind for segregated input events?

@JoNax97
Copy link
Contributor

JoNax97 commented Mar 7, 2025

I don't have a use case right now, but it makes me wonder how common it would be for games to map input differently per-console.

For example the convention for jumping being different between switch and playstation (making this up)

@Grublady
Copy link
Contributor Author

Grublady commented Mar 7, 2025

I don't have a use case right now, but it makes me wonder how common it would be for games to map input differently per-console.

As far as I'm aware, all other controls are typically mapped to the same physical position.

I checked some popular games from other engines to see how they handle it:

  • Hollow Knight (Unity) maps all gameplay controls positionally but uses the expected A/B mappings for menu actions on each console.
  • Fortnite (Unreal) similarly seems to map all gameplay controls positionally but use the native A/B menu actions.
  • Minecraft Bedrock Ed. (custom C++ engine) maps everything positionally except for A/B, which it maps according to platform (for both menu and gameplay actions).

Even if we were to find another common case of differing conventions, it should be fairly trivial to extend it from this PR.
I don't foresee a significant number of these (if any), so I don't think it makes sense to preemptively accommodate them.

@JoNax97
Copy link
Contributor

JoNax97 commented Mar 7, 2025

Makes sense to me

Comment on lines 581 to 583
if (p_name == "Pro Controller" || p_name == "Joy-Con (L/R)") {
js.nintendo_button_layout = true;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail to detect third-party Switch controllers.

See #89193 which aims to be more reliable in controller type detection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, I'll rebase and update to use that PR's detection

@Grublady Grublady requested a review from a team as a code owner March 7, 2025 19:25
@Grublady
Copy link
Contributor Author

Grublady commented Mar 7, 2025

Now based on #89193 and its controller type detection

@Grublady Grublady force-pushed the semantic_ab branch 2 times, most recently from af61818 to e95908f Compare March 25, 2025 05:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants