Introduction

This page contains two parts. The first section shows the bare minimum amount of code required in order to get input events from OIS. The second section contains a more complete example - an InputManager class that you can use in your applications with very little modification.

The choice is yours; either roll your own, or use the provided class.

Minimal OIS code

OIS is an object oriented input library. It supports many different devices, in three basic device categories (keyboards, mice, and joysticks). OIS is an open source library, so you can make changes & alterations as you see fit. The OIS homepage is here

Initialisation

OIS needs to be initialised. Here's the basic code to do this:

OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
m_win->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
m_InputManager = OIS::InputManager::createInputSystem( pl );


Let's go through that example line-by-line.

  1. Line 1 creates a ParamList object. This is basically a typedef for a std::map. It is used to pass parameters to classes (similar to the Ogre::NameValuePairList).
  2. Line 2 creates a size_t object that we will use to retrieve a window handle from our render window.
  3. Line 3 creates a std::ostringstream - we use this to "stringify" the size_t object created in line 2.
  4. Line 4 populates the size_t object with the window handle. 'm_win' in this example is a pointer to an initialised Ogre::RenderWindow
  5. Line 5 performs the stringification - we need a string representation of the window handle.
  6. Line 6 inserts into our parameter list the string "WINDOW", and the string object we created above.
  7. Line 7 actually creates the OIS input system. Note: m_InputManager is a pointer to an OIS::InputManager object.


An alternative method for initializing OIS:

size_t hWnd = 0;
m_win->getCustomAttribute("WINDOW", &hWnd);
m_InputManager = OIS::InputManager::createInputSystem(hWnd);


Phew! That's a lot of work just to create the input system!
Unfortunately, that's not all we have to do. We need to create OIS::Mouse and OIS::Keyboard objects (I'll leave joystick support as an exercise for the reader). The code to do this is fairly simple:

m_Mouse = static_cast<OIS::Mouse*>(m_InputManager->createInputObject(OIS::OISMouse, false));
m_Keyboard = static_cast<OIS::Keyboard*>(m_InputManager->createInputObject(OIS::OISKeyboard, false));


Here, m_Mouse is a pointer to an OIS::Mouse object, and m_Keyboard is a pointer to an OIS::Keyboard object. We need the static cast since the OIS::InputManager returns an OIS::Object (see the OIS API docs for more information). The second parameter to the OIS::InputManager::createInputObject is a hint on whether the input objects should be buffered, or unbuffered. This is an implementation decision that the programmer needs to make. I have chosen to go with unbuffered input.

Nearly there! The last thing we need to do is to tell OIS about the dimensions of the window. This is used in conjunction with mouse events (for example, OIS can trap the mouse inside your display window). The code is fairly simple:

unsigned int width, height, depth;
int top, left;
m_win->getMetrics(width, height, depth, left, top);
const OIS::MouseState &ms = m_Mouse->getMouseState();
ms.width = width;
ms.height = height;


Lines one and two create local variables that will store the window width & height, colour depth, and top and left coordinates. Line 3 gets these values from an Ogre::RenderWindow (m_win is a pointer to an initialised RenderWindow). Line 4 gets a mouse state object, and sets the width and height properties accordingly. Again, consult the OIS API docs for more information.

That's it for initialisation. Keep reading to find out how to use OIS to capture keycodes and mouse events!

Usage

Each time you want to get input device events (probably once per frame), you follow these simple steps:

  1. call the capture() method on the device in question.
  2. Interrogate the device directly.




For example:

m_Keyboard->capture();
if (m_Keyboard->isKeyDown(OIS::KC_ESCAPE))
     return false;


This code might go inside the Ogre::FrameListener::frameStarted event, to tell Ogre to stop rendering when the escape key is pressed. Similar interrogations can be performed on the OIS::Mouse object.

Summary

That's it! OIS is pretty easy to use, but the available documentation doesn't make it easy to get started. Hopefully I have made it a bit easier by providing some sample code. Please feel free to edit the code above, and add any suggestions / comments.

Thanks.

InputManager Class

With this code, I'm trying to make a simple InputManager that uses OIS as input library. I basically used the input managers from Practical Application - Let's Get Started and Managing Game States with OGRE as templates for this one. I hope you can use it.

I tried to keep OGRE out of it as much as possible so you can also use it for other projects. That's why I used another method for getting a singleton pointer. I did keep the Ogre::Renderwindow because I like to keep the initialisation as easy and clean as possible.

InputManager.h

#ifndef InputManager_H
#define InputManager_H

#include <OISMouse.h>
#include <OISKeyboard.h>
#include <OISJoyStick.h>
#include <OISInputManager.h>

#include <OgreRenderWindow.h>

class InputManager : public OIS::KeyListener, public OIS::MouseListener, public OIS::JoyStickListener {
public:
    virtual ~InputManager( void );

    void initialise( Ogre::RenderWindow *renderWindow );
    void capture( void );

    void addKeyListener( OIS::KeyListener *keyListener, const std::string& instanceName );
    void addMouseListener( OIS::MouseListener *mouseListener, const std::string& instanceName );
    void addJoystickListener( OIS::JoyStickListener *joystickListener, const std::string& instanceName );

    void removeKeyListener( const std::string& instanceName );
    void removeMouseListener( const std::string& instanceName );
    void removeJoystickListener( const std::string& instanceName );

    void removeKeyListener( OIS::KeyListener *keyListener );
    void removeMouseListener( OIS::MouseListener *mouseListener );
    void removeJoystickListener( OIS::JoyStickListener *joystickListener );

    void removeAllListeners( void );
    void removeAllKeyListeners( void );
    void removeAllMouseListeners( void );
    void removeAllJoystickListeners( void );

    void setWindowExtents( int width, int height );

    OIS::Mouse*    getMouse( void );
    OIS::Keyboard* getKeyboard( void );
    OIS::JoyStick* getJoystick( unsigned int index );

    int getNumOfJoysticks( void );

    static InputManager* getSingletonPtr( void );
private:
    InputManager( void );
    InputManager( const InputManager& ) { }
    InputManager & operator = ( const InputManager& );

    bool keyPressed( const OIS::KeyEvent &e );
    bool keyReleased( const OIS::KeyEvent &e );

    bool mouseMoved( const OIS::MouseEvent &e );
    bool mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id );
    bool mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id );

    bool povMoved( const OIS::JoyStickEvent &e, int pov );
    bool axisMoved( const OIS::JoyStickEvent &e, int axis );
    bool sliderMoved( const OIS::JoyStickEvent &e, int sliderID );
    bool buttonPressed( const OIS::JoyStickEvent &e, int button );
    bool buttonReleased( const OIS::JoyStickEvent &e, int button );

    OIS::Mouse        *mMouse;
    OIS::Keyboard     *mKeyboard;
    OIS::InputManager *mInputSystem;

    std::vector<OIS::JoyStick*> mJoysticks;
    std::vector<OIS::JoyStick*>::iterator itJoystick;
    std::vector<OIS::JoyStick*>::iterator itJoystickEnd;

    std::map<std::string, OIS::KeyListener*> mKeyListeners;
    std::map<std::string, OIS::MouseListener*> mMouseListeners;
    std::map<std::string, OIS::JoyStickListener*> mJoystickListeners;

    std::map<std::string, OIS::KeyListener*>::iterator itKeyListener;
    std::map<std::string, OIS::MouseListener*>::iterator itMouseListener;
    std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListener;

    std::map<std::string, OIS::KeyListener*>::iterator itKeyListenerEnd;
    std::map<std::string, OIS::MouseListener*>::iterator itMouseListenerEnd;
    std::map<std::string, OIS::JoyStickListener*>::iterator itJoystickListenerEnd;

    static InputManager *mInputManager;
};
#endif

InputManager.cpp

#include "InputManager.h"

InputManager *InputManager::mInputManager;

InputManager::InputManager( void ) :
    mMouse( 0 ),
    mKeyboard( 0 ),
    mInputSystem( 0 ) {
}

InputManager::~InputManager( void ) {
    if( mInputSystem ) {
        if( mMouse ) {
            mInputSystem->destroyInputObject( mMouse );
            mMouse = 0;
        }

        if( mKeyboard ) {
            mInputSystem->destroyInputObject( mKeyboard );
            mKeyboard = 0;
        }

        if( mJoysticks.size() > 0 ) {
            itJoystick    = mJoysticks.begin();
            itJoystickEnd = mJoysticks.end();
            for(; itJoystick != itJoystickEnd; ++itJoystick ) {
                mInputSystem->destroyInputObject( *itJoystick );
            }

            mJoysticks.clear();
        }

        // If you use OIS1.0RC1 or above, uncomment this line
        // and comment the line below it
        mInputSystem->destroyInputSystem( mInputSystem );
        //mInputSystem->destroyInputSystem();
        mInputSystem = 0;

        // Clear Listeners
        mKeyListeners.clear();
        mMouseListeners.clear();
        mJoystickListeners.clear();
    }
}

void InputManager::initialise( Ogre::RenderWindow *renderWindow ) {
    if( !mInputSystem ) {
        // Setup basic variables
        OIS::ParamList paramList;    
        size_t windowHnd = 0;
        std::ostringstream windowHndStr;

        // Get window handle
        renderWindow->getCustomAttribute( "WINDOW", &windowHnd );

        // Fill parameter list
        windowHndStr << (unsigned int) windowHnd;
        paramList.insert( std::make_pair( std::string( "WINDOW" ), windowHndStr.str() ) );

        // Create inputsystem
        mInputSystem = OIS::InputManager::createInputSystem( paramList );

        // If possible create a buffered keyboard
        // (note: if below line doesn't compile, try:  if (mInputSystem->getNumberOfDevices(OIS::OISKeyboard) > 0) {
        //if( mInputSystem->numKeyboards() > 0 ) {
        if (mInputSystem->getNumberOfDevices(OIS::OISKeyboard) > 0) {
            mKeyboard = static_cast<OIS::Keyboard*>( mInputSystem->createInputObject( OIS::OISKeyboard, true ) );
            mKeyboard->setEventCallback( this );
        }

        // If possible create a buffered mouse
        // (note: if below line doesn't compile, try:  if (mInputSystem->getNumberOfDevices(OIS::OISMouse) > 0) {
        //if( mInputSystem->numMice() > 0 ) {
        if (mInputSystem->getNumberOfDevices(OIS::OISMouse) > 0) {
            mMouse = static_cast<OIS::Mouse*>( mInputSystem->createInputObject( OIS::OISMouse, true ) );
            mMouse->setEventCallback( this );

            // Get window size
            unsigned int width, height, depth;
            int left, top;
            renderWindow->getMetrics( width, height, depth, left, top );

            // Set mouse region
            this->setWindowExtents( width, height );
        }

        // If possible create all joysticks in buffered mode
        // (note: if below line doesn't compile, try:  if (mInputSystem->getNumberOfDevices(OIS::OISJoyStick) > 0) {
        //if( mInputSystem->numJoySticks() > 0 ) {
        if (mInputSystem->getNumberOfDevices(OIS::OISJoyStick) > 0) {
            //mJoysticks.resize( mInputSystem->numJoySticks() );
            mJoysticks.resize( mInputSystem->getNumberOfDevices(OIS::OISJoyStick) );

            itJoystick    = mJoysticks.begin();
            itJoystickEnd = mJoysticks.end();
            for(; itJoystick != itJoystickEnd; ++itJoystick ) {
                (*itJoystick) = static_cast<OIS::JoyStick*>( mInputSystem->createInputObject( OIS::OISJoyStick, true ) );
                (*itJoystick)->setEventCallback( this );
            }
        }
    }
}

void InputManager::capture( void ) {
    // Need to capture / update each device every frame
    if( mMouse ) {
        mMouse->capture();
    }

    if( mKeyboard ) {
        mKeyboard->capture();
    }

    if( mJoysticks.size() > 0 ) {
        itJoystick    = mJoysticks.begin();
        itJoystickEnd = mJoysticks.end();
        for(; itJoystick != itJoystickEnd; ++itJoystick ) {
            (*itJoystick)->capture();
        }
    }
}

void InputManager::addKeyListener( OIS::KeyListener *keyListener, const std::string& instanceName ) {
    if( mKeyboard ) {
        // Check for duplicate items
        itKeyListener = mKeyListeners.find( instanceName );
        if( itKeyListener == mKeyListeners.end() ) {
            mKeyListeners[ instanceName ] = keyListener;
        }
        else {
            // Duplicate Item
        }
    }
}

void InputManager::addMouseListener( OIS::MouseListener *mouseListener, const std::string& instanceName ) {
    if( mMouse ) {
        // Check for duplicate items
        itMouseListener = mMouseListeners.find( instanceName );
        if( itMouseListener == mMouseListeners.end() ) {
            mMouseListeners[ instanceName ] = mouseListener;
        }
        else {
            // Duplicate Item
        }
    }
}

void InputManager::addJoystickListener( OIS::JoyStickListener *joystickListener, const std::string& instanceName ) {
    if( mJoysticks.size() > 0 ) {
        // Check for duplicate items
        itJoystickListener = mJoystickListeners.find( instanceName );
        if( itJoystickListener == mJoystickListeners.end() ) {
            mJoystickListeners[ instanceName ] = joystickListener;
        }
        else {
            // Duplicate Item
        }
    }
}

void InputManager::removeKeyListener( const std::string& instanceName ) {
    // Check if item exists
    itKeyListener = mKeyListeners.find( instanceName );
    if( itKeyListener != mKeyListeners.end() ) {
        mKeyListeners.erase( itKeyListener );
    }
    else {
        // Doesn't Exist
    }
}

void InputManager::removeMouseListener( const std::string& instanceName ) {
    // Check if item exists
    itMouseListener = mMouseListeners.find( instanceName );
    if( itMouseListener != mMouseListeners.end() ) {
        mMouseListeners.erase( itMouseListener );
    }
    else {
        // Doesn't Exist
    }
}

void InputManager::removeJoystickListener( const std::string& instanceName ) {
    // Check if item exists
    itJoystickListener = mJoystickListeners.find( instanceName );
    if( itJoystickListener != mJoystickListeners.end() ) {
        mJoystickListeners.erase( itJoystickListener );
    }
    else {
        // Doesn't Exist
    }
}

void InputManager::removeKeyListener( OIS::KeyListener *keyListener ) {
    itKeyListener    = mKeyListeners.begin();
    itKeyListenerEnd = mKeyListeners.end();
    for(; itKeyListener != itKeyListenerEnd; ++itKeyListener ) {
        if( itKeyListener->second == keyListener ) {
            mKeyListeners.erase( itKeyListener );
            break;
        }
    }
}

void InputManager::removeMouseListener( OIS::MouseListener *mouseListener ) {
    itMouseListener    = mMouseListeners.begin();
    itMouseListenerEnd = mMouseListeners.end();
    for(; itMouseListener != itMouseListenerEnd; ++itMouseListener ) {
        if( itMouseListener->second == mouseListener ) {
            mMouseListeners.erase( itMouseListener );
            break;
        }
    }
}

void InputManager::removeJoystickListener( OIS::JoyStickListener *joystickListener ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if( itJoystickListener->second == joystickListener ) {
            mJoystickListeners.erase( itJoystickListener );
            break;
        }
    }
}

void InputManager::removeAllListeners( void ) {
    mKeyListeners.clear();
    mMouseListeners.clear();
    mJoystickListeners.clear();
}

void InputManager::removeAllKeyListeners( void ) {
    mKeyListeners.clear();
}

void InputManager::removeAllMouseListeners( void ) {
    mMouseListeners.clear();
}

void InputManager::removeAllJoystickListeners( void ) {
    mJoystickListeners.clear();
}

void InputManager::setWindowExtents( int width, int height ) {
    // Set mouse region (if window resizes, we should alter this to reflect as well)
    const OIS::MouseState &mouseState = mMouse->getMouseState();
    mouseState.width  = width;
    mouseState.height = height;
}

OIS::Mouse* InputManager::getMouse( void ) {
    return mMouse;
}

OIS::Keyboard* InputManager::getKeyboard( void ) {
    return mKeyboard;
}

OIS::JoyStick* InputManager::getJoystick( unsigned int index ) {
    // Make sure it's a valid index
    if( index < mJoysticks.size() ) {
        return mJoysticks[ index ];
    }

    return 0;
}

int InputManager::getNumOfJoysticks( void ) {
    // Cast to keep compiler happy ^^
    return (int) mJoysticks.size();
}

bool InputManager::keyPressed( const OIS::KeyEvent &e ) {
    itKeyListener    = mKeyListeners.begin();
    itKeyListenerEnd = mKeyListeners.end();
    for(; itKeyListener != itKeyListenerEnd; ++itKeyListener ) {
        if(!itKeyListener->second->keyPressed( e ))
            break;
    }

    return true;
}

bool InputManager::keyReleased( const OIS::KeyEvent &e ) {
    itKeyListener    = mKeyListeners.begin();
    itKeyListenerEnd = mKeyListeners.end();
    for(; itKeyListener != itKeyListenerEnd; ++itKeyListener ) {
        if(!itKeyListener->second->keyReleased( e ))
            break;
    }

    return true;
}

bool InputManager::mouseMoved( const OIS::MouseEvent &e ) {
    itMouseListener    = mMouseListeners.begin();
    itMouseListenerEnd = mMouseListeners.end();
    for(; itMouseListener != itMouseListenerEnd; ++itMouseListener ) {
        if(!itMouseListener->second->mouseMoved( e ))
            break;
    }

    return true;
}

bool InputManager::mousePressed( const OIS::MouseEvent &e, OIS::MouseButtonID id ) {
    itMouseListener    = mMouseListeners.begin();
    itMouseListenerEnd = mMouseListeners.end();
    for(; itMouseListener != itMouseListenerEnd; ++itMouseListener ) {
        if(!itMouseListener->second->mousePressed( e, id ))
            break;
    }

    return true;
}

bool InputManager::mouseReleased( const OIS::MouseEvent &e, OIS::MouseButtonID id ) {
    itMouseListener    = mMouseListeners.begin();
    itMouseListenerEnd = mMouseListeners.end();
    for(; itMouseListener != itMouseListenerEnd; ++itMouseListener ) {
        if(!itMouseListener->second->mouseReleased( e, id ))
            break;
    }

    return true;
}

bool InputManager::povMoved( const OIS::JoyStickEvent &e, int pov ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if(!itJoystickListener->second->povMoved( e, pov ))
            break;
    }

    return true;
}

bool InputManager::axisMoved( const OIS::JoyStickEvent &e, int axis ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if(!itJoystickListener->second->axisMoved( e, axis ))
            break;
    }

    return true;
}

bool InputManager::sliderMoved( const OIS::JoyStickEvent &e, int sliderID ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if(!itJoystickListener->second->sliderMoved( e, sliderID ))
            break;
    }

    return true;
}

bool InputManager::buttonPressed( const OIS::JoyStickEvent &e, int button ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if(!itJoystickListener->second->buttonPressed( e, button ))
            break;
    }

    return true;
}

bool InputManager::buttonReleased( const OIS::JoyStickEvent &e, int button ) {
    itJoystickListener    = mJoystickListeners.begin();
    itJoystickListenerEnd = mJoystickListeners.end();
    for(; itJoystickListener != itJoystickListenerEnd; ++itJoystickListener ) {
        if(!itJoystickListener->second->buttonReleased( e, button ))
            break;
    }

    return true;
}

InputManager* InputManager::getSingletonPtr( void ) {
    if( !mInputManager ) {
        mInputManager = new InputManager();
    }

    return mInputManager;
}

Sample Usage

Just fire up the inputmanager like that:

// Setup input
    mInputMgr = InputManager::getSingletonPtr();
    mInputMgr->initialise( mRenderWindow );
    mInputMgr->addKeyListener( this, "ListenerName" );
    mInputMgr->addMouseListener( this, "ListenerName" );
    mInputMgr->addJoystickListener( this, "ListenerName" );

Example (Download)

Here you can download an example which uses the OIS InputManager with game states and a custom application loop (instead of using the framelisteners): Download link

Important Notes

  • Very Important: If you are not using Ogre's startRendering() call (e.g using renderOneFrame() or window->update() instead), make sure you pump Win32 messages. This can be done with Ogre's Ogre::WindowEventUtilities::messagePump();. If you forget to do so, you will have weird behavior with regards to text/shift/capslock.
  • The first call to InputManager::getSingletonPtr() creates the input manager. Do not forget to destroy it at the end(OIS::InputManager::destroyInputSystem()).
  • Don't forget to capture incoming input events before every frame!
  • If your render window resizes, you should readjust the Mouse clipping values of the mouse state structure.
  • In buffered mode, the keyboard keys will trigger a call to keyPressed() and keyReleased(). Unbuffered access (or immediate access) to the keyboard keys is obtained via a call of InputManager::getSingletonPtr()->getKeyboard()->isKeyDown(OIS::KC_UP). In this case, it is tested whether the up arrow is pressed. If you are calling capture() outside of FrameStarted(), such as within a main loop, the following hack will trigger a call to keyPressed() with an "unassigned" key. Add the two bold printed lines to the keyboard handling code within InputManager::capture( void ):

if( mKeyboard ) {
   mKeyboard->capture();
   '''OIS::KeyEvent e(mKeyboard, 0, OIS::KC_UNASSIGNED, 0);'''
   '''keyPressed(e);'''
 }

  • When writing your input handler functions such as keyPressed(), keyReleased(), mouseMoved(), etc, it is vitally important to always return true, otherwise (if you return false) you are asking for OIS to discard the remainder of your input buffer. This will have a subtle effect of dropping your character inputs randomly, especially when running at low frame rates and typing quickly (and hence using your input buffer more).
  • Double-clicks Using OIS: Basically, whenever the left mouse button is released, you note the time. Whenever it's pressed, you subtract the last-released time. If it's less than (say) 250 milliseconds, you've got a double click. Otherwise, you've got a single click. This assumes, of course, that you're treating a "click" as a mouse press-and-release (rather than just the press).
  • If you are using Paul Nettle's Memory Manager (OGRE uses it internally for tracking down issues, but it's disabled by default) to tackle memory bugs in your project, don't forget to include any STL headers used by OIS (or any external library for that matter) before you include anything OIS related. I just spent four hours chasing my tail because I didn't take into consideration OIS's dependencies on the STL.
  • If you crash your application using the X11 window system in linux you can go to a console by pressing CTRL+ALT+F2 and there kill your application using "ps -Al" and "killall -s KILL appname". After that your keyboard may stop working correctly and not repeat keys when you hold a key down. To fix that just type "xset r on".

Non-exclusive input

This is useful for non fullscreen mode running applications, especially when debugging.
If you want to see the mouse cursor and be able to move it outside your OGRE window and use the keyboard outside the running application, you might want to try the following:

// insert the following lines right before calling mInputSystem = OIS::InputManager::createInputSystem( paramList );
#if defined OIS_WIN32_PLATFORM
paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
#elif defined OIS_LINUX_PLATFORM
paramList.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
paramList.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
#endif


If you are using ExampleFrameListener, there's an easy way to override it. In your child class constructor, destroy the InputSystem first, then just recreate it with your own parameters, as follows:

mInputManager->destroyInputObject(mMouse);
mInputManager->destroyInputObject(mKeyboard);
mInputManager->destroyInputObject(mJoy);
OIS::InputManager::destroyInputSystem(mInputManager);

// override OIS construction to avoid grabbing mouse
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;

window->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
#if defined OIS_WIN32_PLATFORM
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));
pl.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
#elif defined OIS_LINUX_PLATFORM
pl.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
pl.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
pl.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
pl.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
#endif

mInputManager = OIS::InputManager::createInputSystem( pl );

//Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse)
mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, false ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, false ));
try {
	mJoy = static_cast<OIS::JoyStick*>(mInputManager->createInputObject( OIS::OISJoyStick, false ));
}
catch(...) {
	mJoy = 0;
}



Warning! This might break absolute mouseposition under win32, but maybe you can correct the error by listening to the windowMoved event in a Ogre::WindowEventListener and substract the left-top coordinates of the window from the "absolute" mouseposition returned by OIS.

Info NOTE: As of 2010-05-04, there are no problems with OIS and non-exclusive input under Windows. All you have to do is tell OIS the size of the render window each time the window is (re)created:

Ogre::RenderWindow::getMetrics(w, h, d, left, top);
const OIS::MouseState &ms = mMouse->getMouseState();
ms.width = w;
ms.height = h;


If you are using a Mac / OSX you have to manually override the cursor visibility. OIS will hide it by default with no option to show it and share it.

First include the Carbon.h header

#ifdef OIS_APPLE_PLATFORM
#include <Carbon/Carbon.h>
#endif

Then, after you create and initialize OIS and create a mouse input execute the appropriate commands.

#ifdef OIS_APPLE_PLATFORM
CGDisplayShowCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(TRUE);
#endif

OIS on OSX in windowed mode

If you run your app in windowed mode you may notice that you receive no mouse input when your app launches. This is because OIS is incorrectly computing the center coords for your window, so the mouse is hidden and outside the bounds of your application window. To fix this you can manually move the mouse to the correct position.

First include the Carbon.h header

#ifdef OIS_APPLE_PLATFORM
#include <Carbon/Carbon.h>
#endif


Next, after initializing OIS and creating a mouse input.

#ifdef OIS_APPLE_PLATFORM
            Ogre::Rect r = getWindowBounds(renderWindow);
            CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, CGPointMake(r.left + r.right / 2, r.top - r.bottom / 2));
#endif


Where renderWindow is a pointer to your Ogre::RenderWindow. You will also need to create a new class to bridge between your objective c code and your c++ code. So create a class called something like OgreInputInterface

OgreInputInterface.h

@interface OgreInputInterface : NSObject
@end


OgreInputInterface.mm <-- the mm ending is IMPORTANT

#import "OgreInputInterface.h"
#include <Ogre.h>
// HAX - this prevents collisions with glew / gl type defines
#define __glew_h__
#include <OgreOSXCocoaWindow.h>
@implementation OgreInputInterface
Ogre::Rect getWindowBounds(Ogre::RenderWindow *renderWindow)
{
    Ogre::OSXCocoaWindow *cw = static_cast<Ogre::OSXCocoaWindow*>(renderWindow);
    NSWindow *win = cw->ogreWindow();
    
    // invert the y value to get the distance from the top of the display. ugh. 
    NSScreen *screen = NSScreen.mainScreen;
    NSRect rect = screen.frame;
    
    return Ogre::Rect(win.frame.origin.x, rect.size.height - win.frame.origin.y, win.frame.size.width, win.frame.size.height);
}

@end

See also


Alias: Using_OIS

<HR>
Creative Commons Copyright -- Some rights reserved.


THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

  • "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
  • "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
  • "Licensor" means the individual or entity that offers the Work under the terms of this License.
  • "Original Author" means the individual or entity who created the Work.
  • "Work" means the copyrightable work of authorship offered under the terms of this License.
  • "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
  • "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.

2. Fair Use Rights

Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.

3. License Grant

Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

  • to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
  • to create and reproduce Derivative Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
  • For the avoidance of doubt, where the work is a musical composition:
    • Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
    • Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
    • Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).


The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.

4. Restrictions

The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

  • You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
  • You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
  • If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability.

EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

  • This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
  • Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

  • Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
  • Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
  • If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
  • No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
  • This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.