bogre-banana-0.0.1: src/Reactive/Banana/BOGRE/OIS.hs
--
-- Insert Documentation here :-)
--
module Reactive.Banana.BOGRE.OIS (
InputSystem,
createInputSystem,
getKeysPressE,
getMouseE,
capture,
KeyCode(..),
KeysPressed,
KeyState(..),
MouseState
) where
import OIS
import OIS.Types hiding (MouseState)
import Reactive.Banana
import Reactive.Banana.Frameworks (
Frameworks,
AddHandler,
fromAddHandler,
newAddHandler
)
import Foreign.C.Types (CInt(..))
import Unsafe.Coerce
import Control.Monad (
filterM
)
import Control.Concurrent (
ThreadId,
threadDelay
)
import BB.Workarounds
type InputSystem = (
(Keyboard, (AddHandler KeysPressed, KeysPressed -> IO ())),
(Mouse, (AddHandler MouseState, MouseState -> IO ()))
)
type KeysPressed = [KeyCode]
type MouseState = (Int, Int) -- relative x and y values
data KeyState = Up | Down
deriving Eq
createInputSystem :: Int -> IO (InputSystem)
createInputSystem hwnd = do
im <- inputManager_createInputSystem_size_t hwnd
-- get mouse and keyboard objects
-- unsafeCoerce instead of static_cast
mouse <- unsafeCoerce $ inputManager_createInputObject im OISMouse False ""
keyboard <- unsafeCoerce $ inputManager_createInputObject im OISKeyboard True ""
-- create the addhandlers
mouseNewAddHandler <- newAddHandler
keyboardNewAddHandler <- newAddHandler
-- done, package into a InputSystem
return ((keyboard, keyboardNewAddHandler), (mouse, mouseNewAddHandler))
getKeysPressE :: Frameworks t => InputSystem -> Moment t (Event t KeysPressed)
getKeysPressE is = (fromAddHandler . getKeyboardAddHandler) is
getMouseE :: Frameworks t => InputSystem -> Moment t (Event t MouseState)
getMouseE = fromAddHandler . getMouseAddHandler
-- | Get all the keys currenly down (being pressed)
getKeysPress :: InputSystem -> IO (KeysPressed)
getKeysPress is = filterM (isKeyDown is) allKeyCodes
--
-- some direct polling functions
--
-- call the capture function of all input Objects, and poll for changes
capture :: InputSystem -> IO (MouseState, KeysPressed)
capture is@((kb,_), (ms,_)) = do
object_capture $ toObject kb
object_capture $ toObject ms
-- poll keyboard
keyPressed <- getKeysPress is
-- poll mouse
relX <- getMouseRelX ms
relY <- getMouseRelY ms
return ((relX, relY), keyPressed)
-- Check if a key is down. Note that you should call capture before using isKeyDown
isKeyDown :: InputSystem -> KeyCode -> IO (Bool)
isKeyDown ((kb,_), _) = keyboard_isKeyDown kb
-- Check if a mouse button down. Note that you should call capture before using isKeyDown
isMouseButtonDown :: InputSystem -> KeyCode -> IO (Bool)
isMouseButtonDown ((kb,_), _) = keyboard_isKeyDown kb
--
-- some accessor functions
--
getKeyboardAddHandler :: InputSystem -> AddHandler KeysPressed
getKeyboardAddHandler ((_, (kbah,_)), _) = kbah
getMouseAddHandler :: InputSystem -> AddHandler MouseState
getMouseAddHandler (_, (_, (msah,_))) = msah
fireKeyboadEvent :: InputSystem -> KeysPressed -> IO ()
fireKeyboadEvent ((_, (_,kbcb)), _) = kbcb
fireMouseEvent :: InputSystem -> MouseState -> IO ()
fireMouseEvent (_, (_, (_,mscb))) = mscb
-- modify the KeyCodes to be more usable
allKeyCodes :: [KeyCode]
allKeyCodes = [KC_UNASSIGNED,KC_ESCAPE,KC_1,KC_2,KC_3,KC_4,KC_5,KC_6,KC_7,KC_8,KC_9,KC_0,KC_MINUS,KC_EQUALS,KC_BACK,KC_TAB,KC_Q,KC_W,KC_E,KC_R,KC_T,KC_Y,KC_U,KC_I,KC_O,KC_P,KC_LBRACKET,KC_RBRACKET,KC_RETURN,KC_LCONTROL,KC_A,KC_S,KC_D,KC_F,KC_G,KC_H,KC_J,KC_K,KC_L,KC_SEMICOLON,KC_APOSTROPHE,KC_GRAVE,KC_LSHIFT,KC_BACKSLASH,KC_Z,KC_X,KC_C,KC_V,KC_B,KC_N,KC_M,KC_COMMA,KC_PERIOD,KC_SLASH,KC_RSHIFT,KC_MULTIPLY,KC_LMENU,KC_SPACE,KC_CAPITAL,KC_F1,KC_F2,KC_F3,KC_F4,KC_F5,KC_F6,KC_F7,KC_F8,KC_F9,KC_F10,KC_NUMLOCK,KC_SCROLL,KC_NUMPAD7,KC_NUMPAD8,KC_NUMPAD9,KC_SUBTRACT,KC_NUMPAD4,KC_NUMPAD5,KC_NUMPAD6,KC_ADD,KC_NUMPAD1,KC_NUMPAD2,KC_NUMPAD3,KC_NUMPAD0,KC_DECIMAL,KC_OEM_102,KC_F11,KC_F12,KC_F13,KC_F14,KC_F15,KC_KANA,KC_ABNT_C1,KC_CONVERT,KC_NOCONVERT,KC_YEN,KC_ABNT_C2,KC_NUMPADEQUALS,KC_PREVTRACK,KC_AT,KC_COLON,KC_UNDERLINE,KC_KANJI,KC_STOP,KC_AX,KC_UNLABELED,KC_NEXTTRACK,KC_NUMPADENTER,KC_RCONTROL,KC_MUTE,KC_CALCULATOR,KC_PLAYPAUSE,KC_MEDIASTOP,KC_VOLUMEDOWN,KC_VOLUMEUP,KC_WEBHOME,KC_NUMPADCOMMA,KC_DIVIDE,KC_SYSRQ,KC_RMENU,KC_PAUSE,KC_HOME,KC_UP,KC_PGUP,KC_LEFT,KC_RIGHT,KC_END,KC_DOWN,KC_PGDOWN,KC_INSERT,KC_DELETE,KC_LWIN,KC_RWIN,KC_APPS,KC_POWER,KC_SLEEP,KC_WAKE,KC_WEBSEARCH,KC_WEBFAVORITES,KC_WEBREFRESH,KC_WEBSTOP,KC_WEBFORWARD,KC_WEBBACK,KC_MYCOMPUTER,KC_MAIL,KC_MEDIASELECT]
instance Enum KeyCode where
toEnum = cintToKeyCode . CInt . fromIntegral
fromEnum = fromIntegral . keyCodeToCInt
instance Eq KeyCode where
a == b = (fromEnum a) == (fromEnum b)
instance Show KeyCode where
show = show . fromEnum
-- TODO make KeyCodes instance of Enum and Bounded