diff --git a/ffi/glfw-input.c b/ffi/glfw-input.c index 60852d7..b11cc15 100644 --- a/ffi/glfw-input.c +++ b/ffi/glfw-input.c @@ -45,9 +45,12 @@ GLFWgamepadstate state; float* axes; int axesCount = -1; -void getGamepadState(int joystickID) { - if (glfwGetGamepadState(joystickID, &state)) { +int getGamepadState(int joystickID) { + if (glfwJoystickIsGamepad(joystickID) && glfwGetGamepadState(joystickID, &state)) { axes = glfwGetJoystickAxes(joystickID, &axesCount); + return 1; + } else { + return 0; } } diff --git a/ffi/glfw-input.sml b/ffi/glfw-input.sml index 27320c0..df66cbd 100644 --- a/ffi/glfw-input.sml +++ b/ffi/glfw-input.sml @@ -55,7 +55,7 @@ struct (* gamepad bindings below *) val getGamepadState = - _import "getGamepadState" public : int -> unit; + _import "getGamepadState" public : int -> int; val getLeftJoystickXAxisState = _import "getLeftJoystickXAxisState" public : unit -> Real32.real; diff --git a/shell/gl-draw.sml b/shell/gl-draw.sml index 1d30760..3d6565f 100644 --- a/shell/gl-draw.sml +++ b/shell/gl-draw.sml @@ -145,28 +145,6 @@ struct updateLoop (0, InputMailbox.getMessagesAndClear (), app) end -fun getGamepadState () = - let - val () = Input.getGamepadState 0 - val () = Input.getGamepadState 1 - val () = Input.getGamepadState 2 - val () = Input.getGamepadState 3 - val () = Input.getGamepadState 4 - val () = Input.getGamepadState 5 - val () = Input.getGamepadState 6 - val () = Input.getGamepadState 7 - val () = Input.getGamepadState 8 - val () = Input.getGamepadState 9 - val () = Input.getGamepadState 10 - val () = Input.getGamepadState 11 - val () = Input.getGamepadState 12 - val () = Input.getGamepadState 13 - val () = Input.getGamepadState 14 - val () = Input.getGamepadState 15 - in - () - end - fun helpLoop (app, shellState as {window, ...}: t) = case Glfw.windowShouldClose window of false => @@ -176,13 +154,7 @@ fun getGamepadState () = val _ = Gles3.clearColor (0.89, 0.89, 0.89, 1.0) val _ = Gles3.clear () - val () = getGamepadState () - val xAxis = Input.getLeftJoystickXAxisState () - val yAxis = Input.getLeftJoystickYAxisState () - val () = print ("x axis = " ^ Real32.toString xAxis ^ "\n") - val () = print ("y axis = " ^ Real32.toString yAxis ^ "\n") - val () = print "\n" - + val () = GlfwGamepad.query () val app = update app val _ = draw shellState diff --git a/shell/glfw-gamepad.sml b/shell/glfw-gamepad.sml new file mode 100644 index 0000000..d2cbbf8 --- /dev/null +++ b/shell/glfw-gamepad.sml @@ -0,0 +1,118 @@ +structure GlfwGamepad = +struct + datatype joystick_dir = UP | LEFT | DOWN | RIGHT | CENTRE | L2 | R2 + + fun isInDeadZone (x, y) = + x < 0.1 andalso x > ~0.1 andalso y < 0.1 andalso y > ~0.1 + + (* todo: query L2 and R2, and handle them *) + fun axisToDir (x, y) = + if isInDeadZone (x, y) then CENTRE + else if abs x > abs y then if x > 0.0 then RIGHT else LEFT + else if y > 0.0 then DOWN + else UP + + fun getGamepadState () = + Input.getGamepadState 0 <> 0 orelse Input.getGamepadState 1 <> 0 + orelse Input.getGamepadState 2 <> 0 orelse Input.getGamepadState 3 <> 0 + orelse Input.getGamepadState 4 <> 0 orelse Input.getGamepadState 5 <> 0 + orelse Input.getGamepadState 6 <> 0 orelse Input.getGamepadState 7 <> 0 + orelse Input.getGamepadState 8 <> 0 orelse Input.getGamepadState 9 <> 0 + orelse Input.getGamepadState 10 <> 0 orelse Input.getGamepadState 11 <> 0 + orelse Input.getGamepadState 12 <> 0 orelse Input.getGamepadState 13 <> 0 + orelse Input.getGamepadState 14 <> 0 orelse Input.getGamepadState 15 <> 0 + + local open InputMsg + in + fun handleTrianglePressed (x, y) = + let + val chr = + case axisToDir (x, y) of + CENTRE => #"a" + | UP => #"e" + | RIGHT => #"i" + | DOWN => #"m" + | LEFT => #"q" + | L2 => #"u" + | R2 => #"y" + in + InputMailbox.append (CHAR_EVENT chr) + end + + fun handleCirclePressed (x, y) = + let + val chr = + case axisToDir (x, y) of + CENTRE => #"b" + | UP => #"f" + | RIGHT => #"j" + | DOWN => #"n" + | LEFT => #"r" + | L2 => #"v" + | R2 => #"z" + in + InputMailbox.append (CHAR_EVENT chr) + end + + fun handleCrossPressed (x, y) = + case axisToDir (x, y) of + CENTRE => InputMailbox.append (CHAR_EVENT #"c") + | UP => InputMailbox.append (CHAR_EVENT #"g") + | RIGHT => InputMailbox.append (CHAR_EVENT #"k") + | DOWN => InputMailbox.append (CHAR_EVENT #"o") + | LEFT => InputMailbox.append (CHAR_EVENT #"s") + | L2 => InputMailbox.append (CHAR_EVENT #"w") + | R2 => + (* todo: either shift or enter *) + raise Fail "glfw-gamepad.sml: 77\n" + + fun handleSquarePressed (x, y) = + case axisToDir (x, y) of + CENTRE => InputMailbox.append (CHAR_EVENT #"d") + | UP => InputMailbox.append (CHAR_EVENT #"h") + | RIGHT => InputMailbox.append (CHAR_EVENT #"l") + | DOWN => InputMailbox.append (CHAR_EVENT #"p") + | LEFT => InputMailbox.append (CHAR_EVENT #"t") + | L2 => InputMailbox.append (CHAR_EVENT #"x") + | R2 => + (* todo: either shift or enter *) + raise Fail "glfw-gamepad.sml: 87\n" + end + + fun handleIfJoystickIsPresent () = + let + open InputMsg + + val xAxis = Input.getLeftJoystickXAxisState () + val yAxis = Input.getLeftJoystickYAxisState () + + val crossPrressed = Input.isCrossButtonPressed () + val circlePressed = Input.isCircleButtonPressed () + val squarePressed = Input.isSquareButtonPressed () + val trianglePressed = Input.isTriangleButtonPressed () + + val r1Pressed = Input.isR1ButtonPressed () + val l1Pressed = Input.isL1ButtonPressed () + in + if crossPrressed <> 0 then + (* pressing two buttons at the same time is a no-op *) + if + circlePressed <> 0 orelse squarePressed <> 0 + orelse trianglePressed <> 0 orelse r1Pressed <> 0 + orelse l1Pressed <> 0 + then () + else handleCrossPressed (xAxis, yAxis) + else if circlePressed <> 0 then + if + squarePressed <> 0 orelse trianglePressed <> 0 orelse r1Pressed <> 0 + orelse l1Pressed <> 0 + then () + else handleCirclePressed (xAxis, yAxis) + else + () + end + + fun query () = + if getGamepadState () then handleIfJoystickIsPresent () + else (* nothing to do if no gamepad is present *) () +end diff --git a/shf.mlb b/shf.mlb index 55fc81b..044e9f0 100644 --- a/shf.mlb +++ b/shf.mlb @@ -82,6 +82,7 @@ shell/draw-mailbox.sml shell/exception-logger.sml shell/updater.sml +shell/glfw-gamepad.sml shell/gl-shaders.sml shell/gl-draw.sml shell/shell.sml