234 lines
7.2 KiB
Standard ML
234 lines
7.2 KiB
Standard ML
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
|
|
|
|
fun axisToDir (x, y, l2, r2) =
|
|
if isInDeadZone (x, y) then
|
|
(* analogue is in dead zone, so only query L2 and R2 *)
|
|
if r2 < 0.3 andalso l2 < 0.3 then CENTRE
|
|
else if abs r2 > abs l2 then R2
|
|
else L2
|
|
else
|
|
let
|
|
val ax = abs x
|
|
val ay = abs y
|
|
val al2 = abs l2
|
|
val ar2 = abs r2
|
|
in
|
|
if ax > ay andalso ax > al2 andalso ax > ar2 then
|
|
if x > 0.0 then RIGHT else LEFT
|
|
else if ay > ax andalso ay > al2 andalso ay > ar2 then
|
|
if y > 0.0 then DOWN else UP
|
|
else if al2 > ax andalso al2 > ay andalso al2 > ar2 then
|
|
L2
|
|
else
|
|
R2
|
|
end
|
|
|
|
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
|
|
val state =
|
|
{ crossPressed = ref false
|
|
, circlePressed = ref false
|
|
, squarePressed = ref false
|
|
, trianglePressed = ref false
|
|
, r1Pressed = ref false
|
|
, l1Pressed = ref false
|
|
, shiftChr = ref false
|
|
}
|
|
|
|
fun appendChr chr =
|
|
(InputMailbox.append (InputMsg.CHAR_EVENT chr); #shiftChr state := false)
|
|
|
|
fun handleTrianglePressed (x, y, l2, r2) =
|
|
if !(#trianglePressed state) then
|
|
()
|
|
else
|
|
let
|
|
val () = #trianglePressed state := true
|
|
val chr =
|
|
if !(#shiftChr state) then
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => #"A"
|
|
| UP => #"E"
|
|
| RIGHT => #"I"
|
|
| DOWN => #"M"
|
|
| LEFT => #"Q"
|
|
| L2 => #"U"
|
|
| R2 => #"Y"
|
|
else
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => #"a"
|
|
| UP => #"e"
|
|
| RIGHT => #"i"
|
|
| DOWN => #"m"
|
|
| LEFT => #"q"
|
|
| L2 => #"u"
|
|
| R2 => #"y"
|
|
in
|
|
appendChr chr
|
|
end
|
|
|
|
fun handleCirclePressed (x, y, l2, r2) =
|
|
if !(#circlePressed state) then
|
|
()
|
|
else
|
|
let
|
|
val () = #circlePressed state := true
|
|
val chr =
|
|
if !(#shiftChr state) then
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => #"B"
|
|
| UP => #"F"
|
|
| RIGHT => #"J"
|
|
| DOWN => #"N"
|
|
| LEFT => #"R"
|
|
| L2 => #"V"
|
|
| R2 => #"Z"
|
|
else
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => #"b"
|
|
| UP => #"f"
|
|
| RIGHT => #"j"
|
|
| DOWN => #"n"
|
|
| LEFT => #"r"
|
|
| L2 => #"v"
|
|
| R2 => #"z"
|
|
in
|
|
appendChr chr
|
|
end
|
|
|
|
fun handleCrossPressed (x, y, l2, r2) =
|
|
if !(#crossPressed state) then
|
|
()
|
|
else
|
|
let
|
|
val () = #crossPressed state := true
|
|
in
|
|
if !(#shiftChr state) then
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => appendChr #"U"
|
|
| UP => appendChr #"U"
|
|
| RIGHT => appendChr #"U"
|
|
| DOWN => appendChr #"U"
|
|
| LEFT => appendChr #"U"
|
|
| L2 => appendChr #"U"
|
|
| R2 => InputMailbox.append InputMsg.KEY_ENTER
|
|
else
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => appendChr #"c"
|
|
| UP => appendChr #"g"
|
|
| RIGHT => appendChr #"k"
|
|
| DOWN => appendChr #"o"
|
|
| LEFT => appendChr #"s"
|
|
| L2 => appendChr #"w"
|
|
| R2 => InputMailbox.append InputMsg.KEY_ENTER
|
|
end
|
|
|
|
fun handleSquarePressed (x, y, l2, r2) =
|
|
if !(#squarePressed state) then
|
|
()
|
|
else
|
|
let
|
|
val () = #squarePressed state := true
|
|
in
|
|
if !(#shiftChr state) then
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => appendChr #"U"
|
|
| UP => appendChr #"U"
|
|
| RIGHT => appendChr #"U"
|
|
| DOWN => appendChr #"U"
|
|
| LEFT => appendChr #"U"
|
|
| L2 => appendChr #"U"
|
|
| R2 => #shiftChr state := true
|
|
else
|
|
case axisToDir (x, y, l2, r2) of
|
|
CENTRE => appendChr #"d"
|
|
| UP => appendChr #"h"
|
|
| RIGHT => appendChr #"l"
|
|
| DOWN => appendChr #"p"
|
|
| LEFT => appendChr #"t"
|
|
| L2 => appendChr #"x"
|
|
| R2 => #shiftChr state := true
|
|
end
|
|
in
|
|
fun handleIfJoystickIsPresent () =
|
|
let
|
|
open InputMsg
|
|
|
|
(* query possible events for information *)
|
|
val xAxis = Input.getLeftJoystickXAxisState ()
|
|
val yAxis = Input.getLeftJoystickYAxisState ()
|
|
|
|
val r2 = (Input.getR2State () + 1.0) / 2.0
|
|
val l2 = (Input.getL2State () + 1.0) / 2.0
|
|
|
|
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, l2, r2)
|
|
|
|
val () =
|
|
if circlePressed = 0 then #circlePressed state := false
|
|
else if !(#circlePressed state) then ()
|
|
else handleCirclePressed (xAxis, yAxis, l2, r2)
|
|
|
|
val () =
|
|
if squarePressed = 0 then #squarePressed state := false
|
|
else handleSquarePressed (xAxis, yAxis, l2, r2)
|
|
|
|
val () =
|
|
if trianglePressed = 0 then #trianglePressed state := false
|
|
else if !(#trianglePressed state) then ()
|
|
else handleTrianglePressed (xAxis, yAxis, l2, r2)
|
|
|
|
val () =
|
|
if r1Pressed = 0 then
|
|
#r1Pressed state := false
|
|
else if !(#r1Pressed state) then
|
|
()
|
|
else
|
|
let val () = InputMailbox.append (InputMsg.CHAR_EVENT #" ")
|
|
in #r1Pressed state := true
|
|
end
|
|
|
|
val () =
|
|
if l1Pressed = 0 then
|
|
#l1Pressed state := false
|
|
else if !(#l1Pressed state) then
|
|
()
|
|
else
|
|
let val () = InputMailbox.append KEY_BACKSPACE
|
|
in #l1Pressed state := true
|
|
end
|
|
in
|
|
()
|
|
end
|
|
end
|
|
|
|
fun query () =
|
|
if getGamepadState () then handleIfJoystickIsPresent ()
|
|
else (* nothing to do if no gamepad is present *) ()
|
|
end
|