diff --git a/shell/glfw-gamepad.sml b/shell/glfw-gamepad.sml index d2cbbf8..46ce0fb 100644 --- a/shell/glfw-gamepad.sml +++ b/shell/glfw-gamepad.sml @@ -5,7 +5,7 @@ struct 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 *) + (* todo: also 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 @@ -22,95 +22,144 @@ struct orelse Input.getGamepadState 12 <> 0 orelse Input.getGamepadState 13 <> 0 orelse Input.getGamepadState 14 <> 0 orelse Input.getGamepadState 15 <> 0 - local open InputMsg - in + local + val state = + { crossPressed = ref false + , circlePressed = ref false + , squarePressed = ref false + , trianglePressed = ref false + , r1Pressed = ref false + , l1Pressed = ref false + } + + open InputMsg + 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 + if !(#trianglePressed state) then + () + else + let + val () = #trianglePressed state := true + 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 + if !(#circlePressed state) then + () + else + let + val () = #circlePressed state := true + 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" + if !(#crossPressed state) then + () + else + let + val () = #crossPressed state := true + in + 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" + end 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 + if !(#squarePressed state) then () - end + else + let + val () = #squarePressed state := true + in + 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 + in + fun handleIfJoystickIsPresent () = + let + open InputMsg + + (* query possible events for information *) + val xAxis = Input.getLeftJoystickXAxisState () + val yAxis = Input.getLeftJoystickYAxisState () + + val crossPressed = Input.isCrossButtonPressed () + val circlePressed = Input.isCircleButtonPressed () + val squarePressed = Input.isSquareButtonPressed () + val trianglePressed = Input.isTriangleButtonPressed () + + val r1Pressed = Input.isR1ButtonPressed () + val l1Pressed = Input.isL1ButtonPressed () + + (* handle button events *) + val () = + if crossPressed = 0 then #crossPressed state := false + else if !(#crossPressed state) then () + else handleCrossPressed (xAxis, yAxis) + + val () = + if circlePressed = 0 then #circlePressed state := false + else if !(#circlePressed state) then () + else handleCirclePressed (xAxis, yAxis) + + val () = + if squarePressed = 0 then #squarePressed state := false + else if !(#squarePressed state) then () + else handleSquarePressed (xAxis, yAxis) + + val () = + if trianglePressed = 0 then #trianglePressed state := false + else if !(#trianglePressed state) then () + else handleTrianglePressed (xAxis, yAxis) + + val () = + if r1Pressed = 0 then #r1Pressed state := false + else if !(#r1Pressed state) then () + else InputMailbox.append (CHAR_EVENT #" ") + + val () = + if l1Pressed = 0 then #l1Pressed state := false + else if !(#l1Pressed state) then () + else InputMailbox.append KEY_BACKSPACE + in + () + end + end fun query () = if getGamepadState () then handleIfJoystickIsPresent ()