UltraStar-Deluxe / USDX

The free and open source karaoke singing game UltraStar Deluxe, inspired by Sony SingStar™
https://usdx.eu
GNU General Public License v2.0
832 stars 160 forks source link

Joypad support seem broken #19

Closed Emily9121 closed 7 years ago

Emily9121 commented 8 years ago

Hello,

As mentioned on the title, the joypad support doesn't seem to work when enabled in ~/.ultrastardx/config.ini via Joypad=On.

Archlinux x86_64 DS 3 pad. Commit 7d9773b.

RattleSN4K3 commented 8 years ago

Confirmed (45fac33). It's the same for Windows (and possible Mac as well). Likely due to the change to SDL2.

basisbit commented 8 years ago

Confirmed. This was removed when I switched to SDL2 because the Joypad api changed completely. The code is only commented out. I don't have any hardware here to test this and thus can't really implement this.

RattleSN4K3 commented 8 years ago

The code is only commented out.

The original code still kinda works, but with some small changes. From my test, the push event sends bad typed events which aren't recognized.

Since SDL2 now make use of GameControllers (which is the new simplified API), the current system could be changed a bit. I'm am currently trying to centralize the Joystick (legacy) and GameController tracking. My gamepad isn't recognized as GameController (SDL_IsGameController(..) = false), therefore I am not able to properly test it atm. But the plan is generalizing the interface and make use of button mapping and a button layout which is similar to Xbox360 (XInput compatible devices).

And possibly allowing experimental mouse support for the controller, as a workaround for things which require mouse or a specific keyboard hotkey.

RattleSN4K3 commented 8 years ago

My current approach is working well. I hope this is the initial interface to allow some more unified controlling, I already have various additions in mind.

However, the way input is currently handled is bugging the keyboard simulation. With 61f0afd, the keyboard input (in case of text) is converted/casted/translated into a unicode string.

            try
              s1:=Event.text.text;
              KeyCharUnicode:=UnicodeStringToUCS4String(UnicodeString(UTF8String(Event.text.text)))[0];
              //KeyCharUnicode:=UnicodeStringToUCS4String(UnicodeString(Event.key.keysym.unicode))[1];//Event.text.text)[0];
            except

With that code being implemented, the keyboard input for A..Z (and some special chars) cannot be simulated that easily (you'd need the unicode representation for a given SDL key, and this has to be compatible to the use or Ord(CHAR) in some of the screen ParseInput methods).

I've tried various approaches, but they have some critical side effects. Such as recognizing non A..Z input as text input, or a simulated A..Z button press not working at all. Gonna have to work on that and likely change the way how text input is tracked. SDL2 allows a different method.

My current hacky workaround (also using deprecated methods of SDL) is this and simulated the keyboard with unicode := 0:

            if (Event.type_ = SDL_TEXTINPUT) or (Event.key.keysym.unicode <> 0) then
            try
              s1:=Event.text.text;
              KeyCharUnicode:=UnicodeStringToUCS4String(UnicodeString(UTF8String(Event.text.text)))[0];
              //KeyCharUnicode:=UnicodeStringToUCS4String(UnicodeString(Event.key.keysym.unicode))[1];//Event.text.text)[0];
            except
            end
            else if Event.key.keysym.unicode = 0 then
            begin
              s1 := SDL_GetScancodeName(Event.key.keysym.scancode);
              if Length(s1) = 1 then KeyCharUnicode := Ord(s1[1])
            end; 

Other than that and a small issue, keyboard simulation and mouse simulation is working well (uing old Joystick handling). Will work on a unified method using the GameController API and some other stuff. But before, I am trying to work around the keyboard input problem - without changing much of the other code - initially and improving SDL2 usage with text input a lot (+ other options).

RattleSN4K3 commented 8 years ago

Resolved with 4dc9859.

It should now support Joysticks or GameControllers out of the box again. It will always prefer a connected XInput-compatible device (for now). Xbox360-Controller is Xinput compatible (its the origin) and DualShocks are perfectly fine using tools to mimic/emulate XInput input and are perfectly mapped. More to come in future changes. With XInput compatible devices (including 2 sticks and 1 DPad/CoolieHat), you can also use the Mouse. It will use the left stick for now (not configurable) as it is easier to use the stick and mouse buttons (Xbox360: A: LMB, B: RMB, LeftStickButton: MMB; Start and Select are Return and Escape in mouse mode). By using the DPad (or the right stick again), it will switch to keyboard simulation again.

For all non-GameControllers (legacy Joysticks), USDX will map the first 4 buttons to Return, Escape, M (for menu) and R (for shuffle).

Currently, controller input is only simulating keyboard/mouse input. There is no native handling of controller input buttons/axis/etc. More to come on future changes.

Please, try this change and report back. I keep this issue opened for initial feedback on the new method.

PS: GameController is the prefered controller. It is fully/properly mapped. In case you have a non-XInput controller, use x360ce (Windows; Source) or xboxdrv (Linux; Source). These programs will emulate a Xbox360-Controller.

basisbit commented 7 years ago

plain old joysticks were not supported because they for some reason cause SDL_JOYDEVICEADDED, then a SDL_JOYDEVICEREMOVED and another SDL_JOYDEVICEADDED. Quick and dirty workaround was to just reinitialize the Joystick support on SDL_JOYDEVICEADDED event. Anyways, how about getting rid of the mouse-motion by joydevice arrow keys and instead translate it to the arrow key presses instead?

RattleSN4K3 commented 7 years ago

Hmm, TJoy should actually act as singleton and not re-created on such event. I haven't tested the specific change but from checking the source and the order of events, it can result into various undesired cases. Have you tried calling Joy.OnControllerAdded for hotplugging support of legacy Joysticks (and Joy.OnControllerRemoved).

Why instead? It can be added additionally if the key-input implementation gets properly rewritten (modularizing). It's not safe to say a user wants Arrow keys for selection. Legacy joysticks do already use the arrow keys and don't use mouse-motion per se, only if a 2nd hat is available/given. Gamepads with more then 2 sticks use 1 stick for arrow-ke emulation and 1 stick for mouse-motion. The system is specificaly designed to easily add mapping per-device but I haven't added it due to prioritzing other stuff.

So, why you'd want to get rid of the mouse-motion? It is added to support edge cases where mouse is required (see editor; or if anyone wants to use mouse instead as it is mostly fully supported).

PS: Why using 2-case checks instead of the single case check in OnJoystickPollEvent?

basisbit commented 7 years ago

PS: Why using 2-case checks instead of the single case check in OnJoystickPollEvent?

because you should always filter early. Also makes code much better readable for others. Don't just forward every single other event to UJoystick.

Why I want to get rid of mouse motion? Because using a Joypad or Joystick, it is really badly usable. Having the keys mapped on the keyboard keys gives a much better result and easier usage. Lots of very basic game controllers out there are a joystick board with only a few inputs soldered to it. All of these are not really usable right now. (-> your 2nd hat assumption does not work in real life). I tried Joy.OnControllerAdded for Joypad events, but your joypad code implementation doesn't work for later on connected Joypads. I tried to figure out what is wrong but decided to not put any more effort into it as the whole Joypad/Gamepad support code should be rewritten and simplified.

basisbit commented 7 years ago

in case you wanna try one of these shitty joypad controllers, order the cheapest NES usb controller you can find on ebay. they are like 3€ including shipping costs

RattleSN4K3 commented 7 years ago

in case you wanna try one of these shitty joypad controllers, order the cheapest NES usb controller you can find on ebay. they are like 3€ including shipping costs

What for? Is this reply even related to what I mentioned?

Edit: Sorry. Wasn't seeing the previous reply. Github moved the page to the last reply.

basisbit commented 7 years ago

to test what you develop. it is indeed related. see previous reply.

RattleSN4K3 commented 7 years ago

because you should always filter early. Also makes code much better readable for others. Don't just forward every single other event to UJoystick.

Yep. It somehow makes it more readable. But in case you add an event to the OnJoystickPollEvent implemenation, you also have to add it in that list (vice vera on removing in order to keep it clean). Having it at the central place (and only there), keeps the possible problems low and follows the principle of modular programming (through loose interface).

Having the keys mapped on the keyboard keys gives a much better result and easier usage.

They are mapped. But as there are various types of gamepads and joysticks, a general behavior might not be the best. The current layout is optmized for Xbox360/XboxOne/PS3/PS4 controllers and similar generic controllers. Older or controllers with a different layout has to be checked. TJoyControllerJoyStick.TranslateAxisToKey isn't specifically implemented. Legacy controllers (respectively joysticks) are currently only mapping the DPads/hats to the arrow keys. The analog axis are currently used for the mouse.

What I can recommend though is the use of x360ce as a workaround. Remapping the Axis to DPad should work just fine

whole Joypad/Gamepad support code should be rewritten and simplified.

How or why?

The thing what I have in mind would be using a per-device (ID or type) mapping, the other stuff pretty much stays the same.

basisbit commented 7 years ago

joypad and controller input mostly works now. we will continue this topic in #242