blitz-foundation / monkey2

zlib License
3 stars 0 forks source link

Joystick.GetAxis state after losing/restoring focus #101

Open Pharmhaus-2 opened 5 years ago

Pharmhaus-2 commented 5 years ago

Original Author: DruggedBunny

Just ran into this while auto-pausing/resuming my game on window-focus loss/reinstatement.

When I run this code (note: set up for Xbox pad, first one it finds, uses right trigger for input) it sits at a value of 1.0 when not held in, going down to -1.0 as you squeeze the trigger.

Test:

For me, it acts as if Joystick.GetAxis is still receiving the last value from when it lost focus, until I touch the trigger again. (Edit: Sometimes picks up changes in trigger state while not focused, though doesn't correctly reflect current value.)

Expected result here would be that it detects the current (released) state after regaining focus, returning 1.0.

Result in my game is that if you Alt-Tab away while boosting, then come back later and restore the game, the trigger is effectively still held, and keeps on boosting, regardless of the 'real' state of the pad.

Suspect this might be something at driver or SDL2 level (eg. only updates on physical change), but it could do with a workaround if at all possible. (Maybe poll joystick? Tried SDL_JoystickUpdate though, didn't work... )

Namespace myapp

#Import "<std>"
#Import "<mojo>"

Using std..
Using mojo..

Function ValidateJoystick:Joystick (j:Joystick)

    If Not j Or Not j.Attached
        j = FindFirstXboxPad ()
    Endif

    Return j

End

Function FindFirstXboxPad:Joystick ()

    ' Try find an Xbox gamepad, use first one found...

    Local j:Joystick

    For Local loop:Int = 0 Until Joystick.NumJoysticks ()

        j = Joystick.Open (loop)

        If j

            If Not j.Name.StartsWith ("XInput Controller #")
                j.Close ()
                j = Null
            Else
                Exit ' Found one!
            Endif

        Endif

    Next

    Return j

End

Class MyWindow Extends Window

    Field joy:Joystick

    Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )

        Super.New( title,width,height,flags )
    End

    Method OnRender( canvas:Canvas ) Override

        Local jyraw:Float

        If Keyboard.KeyHit (Key.Escape) Then App.Terminate ()

        joy = ValidateJoystick (joy) ' Specifically checks for Xbox pad

        ' JOYSTICK

        If joy And joy.Attached

            jyraw = joy.GetAxis (5)

            Select Sgn (jyraw)
                Case 0
                    canvas.Color = Color.White
                Case 1
                    canvas.Color = Color.Red
                Case -1
                    canvas.Color = Color.Green
            End

            canvas.DrawRect (0, canvas.Viewport.Height * 0.5, canvas.Viewport.Width, jyraw * 100.0)

        Endif

        App.RequestRender()

        canvas.DrawText (jyraw, 20, 20)

    End

End

Function Main()

    New AppInstance

    New MyWindow

    App.Run()
End