git-subtree-dir: shf git-subtree-mainline:401408448fgit-subtree-split:b6c5a95b66
265 lines
7.2 KiB
Standard ML
265 lines
7.2 KiB
Standard ML
structure GlfwGamepad =
|
|
struct
|
|
datatype mode =
|
|
PENDING
|
|
(* we need to wait for all keys to be released after pressing a button *)
|
|
| WAIT_FOR_KEY_RELEASE
|
|
| TRIANGLE
|
|
| TRIANGLE_CIRCLE
|
|
| CIRCLE
|
|
| CIRCLE_CROSS
|
|
| CROSS
|
|
| CROSS_SQUARE
|
|
| SQUARE
|
|
(* maybe SQUARE_TRIANGLE for numbers and symbols? *)
|
|
| SQUARE_TRIANGLE
|
|
|
|
structure IM = InputMsg
|
|
|
|
type gamepad_state =
|
|
{ mode: mode
|
|
, shiftChr: bool
|
|
, trianglePressed: bool
|
|
, circlePressed: bool
|
|
, crossPressed: bool
|
|
, squarePressed: bool
|
|
}
|
|
|
|
fun releaseKeysAndUnshift (gamepadState: gamepad_state) =
|
|
let
|
|
val
|
|
{ mode = _
|
|
, shiftChr = _
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
} = gamepadState
|
|
in
|
|
{ mode = WAIT_FOR_KEY_RELEASE
|
|
, shiftChr = false
|
|
, trianglePressed = false
|
|
, circlePressed = false
|
|
, crossPressed = false
|
|
, squarePressed = false
|
|
}
|
|
end
|
|
|
|
fun onWaitForKeyRelease
|
|
( gamepadState: gamepad_state
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions
|
|
) =
|
|
if
|
|
trianglePressed orelse circlePressed orelse crossPressed
|
|
orelse squarePressed
|
|
then
|
|
(gamepadState, actions)
|
|
else
|
|
let
|
|
val newState =
|
|
{ mode = PENDING
|
|
, shiftChr = #shiftChr gamepadState
|
|
, trianglePressed = false
|
|
, circlePressed = false
|
|
, crossPressed = false
|
|
, squarePressed = false
|
|
}
|
|
in
|
|
(newState, actions)
|
|
end
|
|
|
|
fun onPendingMode
|
|
( state: gamepad_state
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions: IM.t list
|
|
) =
|
|
if
|
|
trianglePressed orelse circlePressed orelse crossPressed
|
|
orelse squarePressed
|
|
then
|
|
(* some button is being pressed,
|
|
* so we record that in the returned state,
|
|
* in addition to whatever buttons were previously pressed *)
|
|
let
|
|
val trianglePressed = #trianglePressed state orelse trianglePressed
|
|
val circlePressed = #circlePressed state orelse circlePressed
|
|
val crossPressed = #crossPressed state orelse crossPressed
|
|
val squarePressed = #squarePressed state orelse squarePressed
|
|
|
|
val newState =
|
|
{ mode = #mode state
|
|
, shiftChr = #shiftChr state
|
|
, trianglePressed = trianglePressed
|
|
, circlePressed = circlePressed
|
|
, crossPressed = crossPressed
|
|
, squarePressed = squarePressed
|
|
}
|
|
in
|
|
(newState, actions)
|
|
end
|
|
else
|
|
(* nothing is currently pressed,
|
|
* so we check if there is a valid mode indicated by the state
|
|
* and change the mode if so *)
|
|
let
|
|
val
|
|
{ trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, shiftChr
|
|
, mode = _
|
|
} = state
|
|
val newMode =
|
|
if trianglePressed andalso not (crossPressed orelse squarePressed) then
|
|
if not circlePressed then TRIANGLE else TRIANGLE_CIRCLE
|
|
else if circlePressed andalso not squarePressed then
|
|
if not crossPressed then CIRCLE else CIRCLE_CROSS
|
|
else if crossPressed then
|
|
if not squarePressed then CROSS else CROSS_SQUARE
|
|
else if squarePressed then
|
|
if not trianglePressed then SQUARE else SQUARE_TRIANGLE
|
|
else
|
|
(* some buttons are being pressed,
|
|
* but not a valid combination to switch
|
|
* to another mode, so we are still on PENDING *)
|
|
PENDING
|
|
|
|
val newState =
|
|
{ mode = newMode
|
|
, shiftChr = shiftChr
|
|
, trianglePressed = false
|
|
, circlePressed = false
|
|
, crossPressed = false
|
|
, squarePressed = false
|
|
}
|
|
in
|
|
(newState, actions)
|
|
end
|
|
|
|
fun onTriangleMode
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions
|
|
) =
|
|
if trianglePressed then
|
|
let
|
|
val newState = releaseKeysAndUnshift gamepadState
|
|
val actions = IM.CHAR_EVENT #"a" :: actions
|
|
in
|
|
(newState, actions)
|
|
end
|
|
else if circlePressed then
|
|
let
|
|
val newState = releaseKeysAndUnshift gamepadState
|
|
val actions = IM.CHAR_EVENT #"b" :: actions
|
|
in
|
|
(newState, actions)
|
|
end
|
|
else if crossPressed then
|
|
let
|
|
val newState = releaseKeysAndUnshift gamepadState
|
|
val actions = IM.CHAR_EVENT #"c" :: actions
|
|
in
|
|
(newState, actions)
|
|
end
|
|
else if squarePressed then
|
|
let
|
|
val newState = releaseKeysAndUnshift gamepadState
|
|
val actions = IM.CHAR_EVENT #"d" :: actions
|
|
in
|
|
(newState, actions)
|
|
end
|
|
else
|
|
(gamepadState, actions)
|
|
|
|
fun handleButtons
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, l1Pressed
|
|
, r1Pressed
|
|
) =
|
|
let
|
|
val actions = if l1Pressed then [IM.KEY_BACKSPACE] else []
|
|
val actions =
|
|
if r1Pressed then (IM.CHAR_EVENT #" ") :: actions else actions
|
|
in
|
|
case #mode gamepadState of
|
|
PENDING =>
|
|
onPendingMode
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions
|
|
)
|
|
| WAIT_FOR_KEY_RELEASE =>
|
|
onWaitForKeyRelease
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions
|
|
)
|
|
| TRIANGLE =>
|
|
onTriangleMode
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, actions
|
|
)
|
|
end
|
|
|
|
(* impure functions below *)
|
|
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
|
|
|
|
fun query gamepadState =
|
|
if getGamepadState () then
|
|
let
|
|
val trianglePressed = Input.isTriangleButtonPressed () <> 0
|
|
val circlePressed = Input.isCircleButtonPressed () <> 0
|
|
val crossPressed = Input.isCrossButtonPressed () <> 0
|
|
val squarePressed = Input.isSquareButtonPressed () <> 0
|
|
val l1Pressed = Input.isL1ButtonPressed () <> 0
|
|
val r1Pressed = Input.isR1ButtonPressed () <> 0
|
|
in
|
|
handleButtons
|
|
( gamepadState
|
|
, trianglePressed
|
|
, circlePressed
|
|
, crossPressed
|
|
, squarePressed
|
|
, l1Pressed
|
|
, r1Pressed
|
|
)
|
|
end
|
|
else
|
|
(* nothing to do, so return same state *)
|
|
(gamepadState, [])
|
|
end
|