Add 'shf/' from commit 'b6c5a95b664aeb861d7b33ffc9eefe447ba99dd7'
git-subtree-dir: shf git-subtree-mainline:401408448fgit-subtree-split:b6c5a95b66
This commit is contained in:
264
shf/shell/glfw-gamepad.sml
Normal file
264
shf/shell/glfw-gamepad.sml
Normal file
@@ -0,0 +1,264 @@
|
||||
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
|
||||
Reference in New Issue
Block a user