Add support for DualSense Adaptive Triggers and custom joypad data packets#111682
Add support for DualSense Adaptive Triggers and custom joypad data packets#111682Nintorch wants to merge 1 commit into
Conversation
bc37d56 to
50140bb
Compare
|
Would be nice if we had HID input reading so we could determine if the triggers are actually affected. |
Not sure it's worth it, I think if the packets are constructed correctly, then the triggers must be affected. |
|
I'll have to double check but my recollection is that you can read the triggers' analog values (similar to how you'd read a stick's axis value) and see the amount it changes by as you push down the triggers change. |
Apart of that, it's possible to read currently applied effect and trigger pressure status, for ex. "Weapon" mode has three statuses (0 not pressed, 1 cocking trigger, 2 is fired)
Fandom wiki describes input report structure. Also see my implementation for Quake to get the idea: |
|
In between some of my school work, I've been working on making a little demo project to test and demonstrate each of the adaptive trigger methods:
I can upload the project ZIP when it's done, or post the repo on GitHub so people can use it sooner and then pull updates when I make them (or perhaps contribute portions themselves) 😄 On the TODO, I see you have "Makes the functions only work if the controller is DualSense (throw an error if it's not)". Personally, I feel like it might be better to have the functions do something less intrusive like return if Input.is_joy_dualsense(current_device): # pseudocode function for demo purposes
Input.joy_adaptive_triggers_feedback(...)Ideally, the adaptive trigger functionality should play for anyone who has it, but shouldn't affect those who don't. If the functions themselves check for adaptive trigger support and early-return if it's not there, then the game developer's code won't need to check. I don't know if this should be a blocker for these functions themselves being merged, but I do think we should have more descriptive explanations of each of the adaptive trigger functions. It looks like the gist you linked with the factory functions describes the effects; Apple's |
|
Should there be a way to setup trigger effect for both triggers in one method call, for example, by passing |
|
That would make sense to me! Unfortunately, it looks like |
|
The test project is now up on GitHub at https://github.com/Meorge/godot-test-adaptive-triggers !! 🥳 It has scenes to test all of the DualSense adaptive trigger methods; Due to differences in how I thought the methods worked versus what they actually do after testing, some of the UI layouts might not totally make sense, but they still work well enough to see the adaptive triggers in action. I may be able to study the existing docs on the adaptive triggers, as well as do my own experimentation and testing, to write more descriptive documentation for how the effects feel over the next couple of days. |
11b47d1 to
8a45074
Compare
|
Looking at Apple's APIs for these controller functions, I see that they used normalized floats instead of integers for the arguments, and I think that could be a good idea to implement for Godot's API too. As I was building the testing project, I found myself often having to go back to the documentation to check what the valid ranges for each different parameter type were. Having the API take in a normalized float and map it to the corresponding integer internally would make it more intuitive for the programmer, I think. There is the disadvantage that users may put in slightly different float values and expect different behavior, but instead get the exact same behavior (since the two float values map to the same integer). My gut says these differences won't be significant enough to notice, though. |
Meorge
left a comment
There was a problem hiding this comment.
I've suggested short descriptions of the adaptive trigger effects for the documentation 🙂
Some of the suggestions for joy_adaptive_triggers_feedback are also applicable to the other methods' documentation, but I held off on submitting those as separate suggestions until people could discuss and agree on them.
8a45074 to
ed3ceee
Compare
|
Thank you very much for the documenation improvements, Meorge! I included your suggestions into the code :) |
|
Linux editor CI fails with erros in documentation about the order of parameters in |
I see! Thank you :) |
303dad4 to
47d2032
Compare
97249b6 to
3368a35
Compare
|
Thank you for your review, AThousandShips! I included your suggested changes into the code! I hope I didn't forget anything :D |
3368a35 to
1f173e6
Compare
AThousandShips
left a comment
There was a problem hiding this comment.
The style and documentation looks great save for a few final notes
1f173e6 to
88b602c
Compare
I'm still not sure if that's necessary, sorry. Will it be used often? Would it be better than storing the triggers' state in a separate variable in the game code? |
|
For the adaptive triggers specifically, I think it would be best for the developer to not assume with their code that a player has adaptive triggers or that they work correctly. If they're there, then they can enhance the experience, but generally a game shouldn't be unplayable if the triggers aren't adaptive. So IMO what is in the PR right now is sufficient. Another use case I can think of for HID input reading is determining the colors on Switch Joy-Con controllers. You have to send a query to the controllers asking for a particular range of their flash memory that contains the color data. This can then be used to display elements on-screen that are color-coordinated to the controllers players are holding in their hands, which is nice. Perhaps this is a topic for another thread, but looking at the SDL APIs I'm not entirely sure how reading would work. I see this PR uses |
I haven't used SDL HID functions, but I hope it's possible to open it via something like |
88b602c to
a335450
Compare
a335450 to
8512018
Compare
|
As it was briefly discussed on RocketChat, should we only expose |
|
I'm feeling quite conflicted on this, and would love for someone to propose arguments in favor of keeping it in core, because on a personal level I do love having things built in and not needing to worry about addons. But, based on what I know of the general Godot philosophy, at the moment it makes sense to me that the adaptive trigger functions would be moved to an addon, and only
I think in my ideal scenario, Godot would have classes of some kind to represent different controller types with specific input methods; for example, a Anyways, as I said before, on a personal level I would love to have these controller-specific features easily accessible from core. So if people have other arguments to make in favor of keeping them in core, I would very much appreciate them! |
|
I will also have to check if we can even skip adding |
|
In the longer run, I would love to have that. Using HID read/write commands, it's possible to interface with the Switch Joy-Cons and do things like get the controllers' physical colors and read data from the IR camera. Being able to play with these capabilities without needing to use GDExtension and hidapi would be quite nice 😄 |
| ClassDB::bind_method(D_METHOD("joy_adaptive_triggers_multi_feedback", "device", "axis", "strengths"), &Input::joy_adaptive_triggers_multi_feedback); | ||
| ClassDB::bind_method(D_METHOD("joy_adaptive_triggers_slope_feedback", "device", "axis", "start_position", "end_position", "start_strength", "end_strength"), &Input::joy_adaptive_triggers_slope_feedback); | ||
| ClassDB::bind_method(D_METHOD("joy_adaptive_triggers_multi_vibration", "device", "axis", "frequency", "amplitudes"), &Input::joy_adaptive_triggers_multi_vibration); | ||
| ClassDB::bind_method(D_METHOD("send_joy_packet", "device", "packet"), &Input::send_joy_packet); |
There was a problem hiding this comment.
I might need to make this function not exposed at the moment, because it might be superseded by exposing HIDAPI later.






Partially addresses godotengine/godot-proposals#12087
Partially supersedes #88590
Requires #111707 to be merged first
I decided to split my big SDL3 joypad features PR ( #107967 ) into several smaller PRs, this PR is one of them.
This PR adds the ability to use DualSense's Adaptive Triggers functionality. This code has been tested in my older PR, see: #107967 (comment), #107967 (comment)
This code was based on this SDL2 Adaptive Triggers example: https://github.com/libsdl-org/SDL/blob/f201b64ffe1380713b181a3421c7fd910c95aada/test/testgamecontroller.c#L304-L352
Here's how the joypad packets are constructed: https://gist.github.com/Nielk1/6d54cc2c00d2201ccb8c2720ad7538db
(I hope I'm not spamming the PRs or anything 😅 )
TODO:
Get trigger status (see https://controllers.fandom.com/wiki/Sony_DualSense#Input_Reports and DualSense Adaptive Triggers andrei-drexler/ironwail#309 ) (I think it can be done in a separate PR if needed)
[code skip-lint]...[/code]with[parameter ...]Input.has_joy_adaptive_triggers()Input.send_joy_packet()(will be superseded by exposing HIDAPI)voidfor most method