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

gamepad: add Gamepad package #8

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

inkeliz
Copy link
Contributor

@inkeliz inkeliz commented Dec 25, 2021

Support gamepad for Windows, macOS, iOS and JS.

Signed-off-by: Inkeliz inkeliz@inkeliz.com

Comment on lines +87 to +93
type Buttons struct {
A, B, Y, X Button
Left, Right, Up, Down Button
LT, RT, LB, RB Button
LeftThumb, RightThumb Button
Start, Back Button
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe replace to map[ButtonID]float32?

Comment on lines +134 to +136
for name, button := range mappingButton {
controller.Buttons.setButtonForce(button, float32(C.getButtonFrom(state, name)))
}
Copy link
Contributor Author

@inkeliz inkeliz Dec 25, 2021

Choose a reason for hiding this comment

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

It sounds very inefficient, but it's easier to understand.

Maybe change the map to [...][2]uinptr (the first is NSString and the second item is the offset struct-item) and provide access directly to controller.Buttons). So, the C code will change the Go-Struct directly, so it's a single call to C, instead of multiple calls.

@gedw99
Copy link

gedw99 commented Dec 26, 2021

@inkeliz This is going to be fun...

which gamepad are you testing with ?

@inkeliz
Copy link
Contributor Author

inkeliz commented Dec 26, 2021

I'm using Xbox One Controller on Windows and iOS; Nintendo Switch Pro Controller and Xbox on macOS.

I notice some issues with remapping on macOS/iOS, that I will fix soon. Since Nintendo Switch uses a "reverted scheme" pressing "A" acts like "B". I think makes more sense to map to the physical button position. Pressing "B" on Nintendo Pro Controller must be the same as "A" on Xbox, and "X" on Playstation (all those buttons have the same position in the gamepad). Another function or field to explain "what is the controller" (brand, name....) might be useful, but some APIs (Windows/XInput) doesn't support it.


I can't implement for Linux because I fail to enable pass-through the USB to VM machine. The Android not work based on snapshot/state. The Android is the only one that is event-based exclusive (similar to keystrokes) and those events are sent to the View. Maybe I can manage a way to create a custom invisible View to get those inputs, but I'm not sure if that will work.

Support gamepad for Windows, macOS, iOS and JS.

Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
@gedw99
Copy link

gedw99 commented Dec 27, 2021

Hey

thanks for the updates !!

Ok wil watch out for updates and retest here.

I am only testing on Intel Mac for now. It compiles fine but crashes at runtime. If you want output logs let me know.

Some things are working at the CLI level though using some custom code.
I got it work with my stadia controller but i need to button mapping.
We can probably add control type detection to do button mapping for users ?

I wish we have github workflow CI to test stuff :)

@inkeliz
Copy link
Contributor Author

inkeliz commented Dec 27, 2021

I am only testing on Intel Mac for now. It compiles fine but crashes at runtime. If you want output logs let me know.

What is the exact issue? The logs will be nice. What is the version of macOS did you have? It requires macOS 12, but it should act as "no-op" for older macOS versions. I compile to amd64 (using CGO_ENABLED=1 GOARCH=amd64 go run .) and I didn't hit the same bug.


We can probably add control type detection to do button mapping for users ?

It's not possible on all OSes. On iOS/macOS the user can remap in the OS settings and that settings is honored by return [Inputs mappedElementAliasForPhysicalInputName:name];.

@gedw99
Copy link

gedw99 commented Dec 27, 2021

@inkeliz I will put up the full code on a github fork so you can see everything.

Bit busy with holidays stuff here right now.

@gedw99
Copy link

gedw99 commented Dec 27, 2021

I am only testing on Intel Mac for now. It compiles fine but crashes at runtime. If you want output logs let me know.

What is the exact issue? The logs will be nice. What is the version of macOS did you have? It requires macOS 12, but it should act as "no-op" for older macOS versions. I compile to amd64 (using CGO_ENABLED=1 GOARCH=amd64 go run .) and I didn't hit the same bug.

We can probably add control type detection to do button mapping for users ?

It's not possible on all OSes. On iOS/macOS the user can remap in the OS settings and that settings is honored by return [Inputs mappedElementAliasForPhysicalInputName:name];.

I have it working only on desktop via USB for now to detect the gamepad type. Will make sure its in the github fork i put up.

@gedw99
Copy link

gedw99 commented Jan 5, 2022

hey @inkeliz

The mappings to support many different gamepads are in the ebitne code base here: https://github.com/hajimehoshi/ebiten/blob/main/internal/glfw/glfw/src/mappings.h

there are so many gamepads !!

DO you think we can use the mappings ?

@inkeliz
Copy link
Contributor Author

inkeliz commented Jan 6, 2022

I don't know how can we use it.

On JS (Gamepad API) the only map supported is standard and (empty):

enum GamepadMappingType {
"",
"standard",
"xr-standard",
};

https://w3c.github.io/gamepad/#gamepadmappingtype-enum

Currently, it's not checked. But, maybe it must only support "standard" and any other type must be reported as "disconnected".


On Windows, the XInput only supports XINPUT_DEVTYPE_GAMEPAD and there's some "Sub-Type" defined on XINPUT_CAPABILITIES (https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes), however, they are already mapped:

XINPUT_DEVSUBTYPE_WHEEL 0x02 Racing wheel controller.Left Stick X reports the wheel rotation, Right Trigger is the acceleration pedal, and Left Trigger is the brake pedal. Includes Directional Pad and most standard buttons (A, B, X, Y, START, BACK, LB, RB). LSB and RSB are optional.

Again, maybe we can enforce to only support XINPUT_DEVSUBTYPE_GAMEPAD and drop anything else, but I don't think it's necessary.


On MacOS/iOS the button mapping can be changed on user settings:

Use this method to get the alias for an input element. For example, if the user remaps a physical press of the controller’s A button to button B, then passing GCInputButtonA to this method returns GCInputButtonB.

https://developer.apple.com/documentation/gamecontroller/gcphysicalinputprofile/3867058-mappedelementaliasforphysicalinp?language=objc

That function is currently used by Gamepad package, so the user can map their gamepad on the OS itself, and some devices are already mapped (like Nintendo Switch). Actually, that is why that package only works on macOS 12+ and iOS 15+.


On Android, I don't know, it have other issues.


What I want is to add some way to get the device name. That is useful to show the correct icons, for instance show "X" instead of "A". Maybe it can be changed on the in-game settings, but could also be changed by the name of the device. If the name contains "XBOX" it will be "A", if the name contains "DualShock" it will show "X" icon. However, the gamepad package will always report as "A", that is just visual change.

@gedw99
Copy link

gedw99 commented Jan 6, 2022

@inkeliz thanks for the in depth analysis on the mappings and potential uses. I guess we can swing back to the button mappings later...

I just realised i forgot to send the logs to you.. I will try to do it today..

@inkeliz
Copy link
Contributor Author

inkeliz commented Sep 26, 2022

@whereswaldon, similar to Share Dialog, it's preferable to drop it from Gio-x?

@whereswaldon
Copy link
Member

@inkeliz I'm more interested in this joining x. I think it is likely that many people are using Gio for hobby gaming projects, and I'd like a semi-official way for them to do that. It's also smaller than share was (lines of code). I will try to review this soon, but I'm not going to be able to test all permutations of controller and OS. I have PS3 and Switch controllers, and I can test Linux, Windows, Android, and WASM. I won't be able to verify correctness for XBox controllers, newer PlayStation controllers, or on macOS. Are you willing to help with any bugs for those permutations as they crop up?

@gedw99
Copy link

gedw99 commented Nov 11, 2022 via email

@inkeliz
Copy link
Contributor Author

inkeliz commented Nov 12, 2022

Are you willing to help with any bugs for those permutations as they crop up?

Yes.🙂

The only point that I don't remember is the Android. I need to revisit and check what is required to implement Android.

@inkeliz
Copy link
Contributor Author

inkeliz commented Nov 12, 2022

Related to mapping, @gedw99, this file seems to be related to SDL2/GLFW. This package (and Gio) doesn't use SDL/GLFW. I think Ebiten uses GLFW (at least in the past, I'm not sure currently).

Honestly, I'm not sure how we can use that, and if that is (so) important. You can always re-map the gamepad externally to the package. Some OSes (MacOS/iOS) allows the user to customize the gamepad layout and also seems to detect it. On WASM it have only one layout: "There is currently one canonical layout, the Standard Gamepad" (https://www.w3.org/TR/gamepad/#remapping). I think exists another mapping for VR/AR controller, but that is part of XR API.

@gedw99
Copy link

gedw99 commented Nov 14, 2022

Oh I did not realise there is only on mapping for XR !

XR is something I have been pondering about too :)

Great stuff

@gedw99
Copy link

gedw99 commented Nov 14, 2022

Would be cool if we get this to the point of a basic demo.

@inkeliz
Copy link
Contributor Author

inkeliz commented Nov 14, 2022

If you are looking for some basic demo, its parked at gioui/gio-example#3. That can be broken now, due to changes in gio-x/gio.

In order to remap you can use unsafe.Pointer and replace it with some custom struct (which changes the order) or use if/else when read it. That is also why I suggest change the struct to map/slice (#8 (comment)), because avoid unsafe and if/else. I mean, you can use gamepad[JUMP_BUTTON], where JUMP_BUTTON can be either gamepad.A or gamepad.B.

@gedw99
Copy link

gedw99 commented Nov 14, 2022

Thanks @inkeliz

will try it out tomorrow..

@gedw99
Copy link

gedw99 commented May 6, 2023

Hey all,

I never got a try this out and work on it or the example at gioui/gio-example#3

@whereswaldon thats exactly what i am thinking too. Lots of devs playing around with self made games etc.

@whereswaldon
Copy link
Member

@inkeliz I'm very sorry for the multi-year PR. I've found it extremely difficult (as a new parent) to make time to test this since it involves lots of hardware permutations, and I honestly don't see that changing in the short term. As such, I don't think I can accept it into x under my maintenance. I see two paths forward:

  • this just lives in your own repositories (no major change from the current status quo)
  • this goes into x, but with you as the official maintainer (you gain commit rights on x and some new responsibilities)

Which path would you like to pursue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants