packages feed

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