Object Oriented Input System

This is an old revision of this page, as edited by Alex.Cham (talk | contribs) at 18:27, 7 November 2014 (External links). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

Object Oriented Input System (OIS), a cross-platform input system

OIS (Object-Oriented Input System) is a code library for constructing a human-computer interface with input devices such as a keyboard, mouse or game controller. OIS is designed so that software developers can easily use input from these devices with a computer application.

Object Oriented Input System
Developer(s)Wrecked Games
Stable release
1.3 / December 19, 2010; 14 years ago (2010-12-19)
Preview release
1.4 / April 4, 2012; 13 years ago (2012-04-04)
Repository
PlatformCross-platform
TypeInput/Games/Entertainment
Licensezlib/libpng license
Websitehttp://www.wreckedgames.com/

General information

The Object-Oriented Input Library is a mostly c++ library for handling input. Input types include mouse, keyboard, joystick and Wii remote.[1]

OIS is meant to be cross-platform, supporting Windows and Linux systems. OS X and FreeBSD are only partially supported.

Features

OIS uses an Object-oriented design.

Various types of input including mouse, keyboard, joystick and Wii Remote are supported.

OIS can handle force feedback devices.

Usage

Possible Ogre + OIS usage example

OIS::InputManager create input system @TODO

Ogre::FrameListener

A interface class defining a listener which can be used to receive notifications of frame events. A 'listener' is an interface designed to be called back when particular events are called. This class defines the interface relating to frame events. In order to receive notifications of frame events, you should create a subclass of FrameListener and override the methods for which you would like to customise the resulting processing. You should then call Root::addFrameListener passing an instance of this class. There is no limit to the number of frame listeners you can register, allowing you to register multiple listeners for different purposes. Note that a frame event occurs once for all rendering targets, not once per target. http://www.ogre3d.org/docs/api/1.9/class_ogre_1_1_frame_listener.html#details

OIS::InputManager

Base Manager class. No longer a Singleton; so feel free to create as many InputManager's as you have windows.

OIS::Keyboard

 

Keyboard base class. To be implemented by specific system (ie. DirectX Keyboard) This class is useful as you remain OS independent using this common interface.

OIS::KeyListener

To recieve buffered keyboard input, derive a class from this, and implement the methods here. Then set the call back to your Keyboard instance with Keyboard::setEventCallback

OIS keyboard kodes

// /Dependencies/src/ois/includes/OISKeyboard.h
	enum KeyCode
	{
		KC_UNASSIGNED  = 0x00,
		KC_ESCAPE      = 0x01,
		KC_1           = 0x02,
		KC_2           = 0x03,
		KC_3           = 0x04,
		KC_4           = 0x05,
		KC_5           = 0x06,
		KC_6           = 0x07,
		KC_7           = 0x08,
		KC_8           = 0x09,
		KC_9           = 0x0A,
		KC_0           = 0x0B,
		KC_MINUS       = 0x0C,    // - on main keyboard
		KC_EQUALS      = 0x0D,
		KC_BACK        = 0x0E,    // backspace
		KC_TAB         = 0x0F,
		KC_Q           = 0x10,
		KC_W           = 0x11,
		KC_E           = 0x12,
		KC_R           = 0x13,
		KC_T           = 0x14,
		KC_Y           = 0x15,
		KC_U           = 0x16,
		KC_I           = 0x17,
		KC_O           = 0x18,
		KC_P           = 0x19,
		KC_LBRACKET    = 0x1A,
		KC_RBRACKET    = 0x1B,
		KC_RETURN      = 0x1C,    // Enter on main keyboard
		KC_LCONTROL    = 0x1D,
		KC_A           = 0x1E,
		KC_S           = 0x1F,
		KC_D           = 0x20,
		KC_F           = 0x21,
		KC_G           = 0x22,
		KC_H           = 0x23,
		KC_J           = 0x24,
		KC_K           = 0x25,
		KC_L           = 0x26,
		KC_SEMICOLON   = 0x27,
		KC_APOSTROPHE  = 0x28,
		KC_GRAVE       = 0x29,    // accent
		KC_LSHIFT      = 0x2A,
		KC_BACKSLASH   = 0x2B,
		KC_Z           = 0x2C,
		KC_X           = 0x2D,
		KC_C           = 0x2E,
		KC_V           = 0x2F,
		KC_B           = 0x30,
		KC_N           = 0x31,
		KC_M           = 0x32,
		KC_COMMA       = 0x33,
		KC_PERIOD      = 0x34,    // . on main keyboard
		KC_SLASH       = 0x35,    // / on main keyboard
		KC_RSHIFT      = 0x36,
		KC_MULTIPLY    = 0x37,    // * on numeric keypad
		KC_LMENU       = 0x38,    // left Alt
		KC_SPACE       = 0x39,
		KC_CAPITAL     = 0x3A,
		KC_F1          = 0x3B,
		KC_F2          = 0x3C,
		KC_F3          = 0x3D,
		KC_F4          = 0x3E,
		KC_F5          = 0x3F,
		KC_F6          = 0x40,
		KC_F7          = 0x41,
		KC_F8          = 0x42,
		KC_F9          = 0x43,
		KC_F10         = 0x44,
		KC_NUMLOCK     = 0x45,
		KC_SCROLL      = 0x46,    // Scroll Lock
		KC_NUMPAD7     = 0x47,
		KC_NUMPAD8     = 0x48,
		KC_NUMPAD9     = 0x49,
		KC_SUBTRACT    = 0x4A,    // - on numeric keypad
		KC_NUMPAD4     = 0x4B,
		KC_NUMPAD5     = 0x4C,
		KC_NUMPAD6     = 0x4D,
		KC_ADD         = 0x4E,    // + on numeric keypad
		KC_NUMPAD1     = 0x4F,
		KC_NUMPAD2     = 0x50,
		KC_NUMPAD3     = 0x51,
		KC_NUMPAD0     = 0x52,
		KC_DECIMAL     = 0x53,    // . on numeric keypad
		KC_OEM_102     = 0x56,    // < > | on UK/Germany keyboards
		KC_F11         = 0x57,
		KC_F12         = 0x58,
		KC_F13         = 0x64,    //                     (NEC PC98)
		KC_F14         = 0x65,    //                     (NEC PC98)
		KC_F15         = 0x66,    //                     (NEC PC98)
		KC_KANA        = 0x70,    // (Japanese keyboard)
		KC_ABNT_C1     = 0x73,    // / ? on Portugese (Brazilian) keyboards
		KC_CONVERT     = 0x79,    // (Japanese keyboard)
		KC_NOCONVERT   = 0x7B,    // (Japanese keyboard)
		KC_YEN         = 0x7D,    // (Japanese keyboard)
		KC_ABNT_C2     = 0x7E,    // Numpad . on Portugese (Brazilian) keyboards
		KC_NUMPADEQUALS= 0x8D,    // = on numeric keypad (NEC PC98)
		KC_PREVTRACK   = 0x90,    // Previous Track (KC_CIRCUMFLEX on Japanese keyboard)
		KC_AT          = 0x91,    //                     (NEC PC98)
		KC_COLON       = 0x92,    //                     (NEC PC98)
		KC_UNDERLINE   = 0x93,    //                     (NEC PC98)
		KC_KANJI       = 0x94,    // (Japanese keyboard)
		KC_STOP        = 0x95,    //                     (NEC PC98)
		KC_AX          = 0x96,    //                     (Japan AX)
		KC_UNLABELED   = 0x97,    //                        (J3100)
		KC_NEXTTRACK   = 0x99,    // Next Track
		KC_NUMPADENTER = 0x9C,    // Enter on numeric keypad
		KC_RCONTROL    = 0x9D,
		KC_MUTE        = 0xA0,    // Mute
		KC_CALCULATOR  = 0xA1,    // Calculator
		KC_PLAYPAUSE   = 0xA2,    // Play / Pause
		KC_MEDIASTOP   = 0xA4,    // Media Stop
		KC_VOLUMEDOWN  = 0xAE,    // Volume -
		KC_VOLUMEUP    = 0xB0,    // Volume +
		KC_WEBHOME     = 0xB2,    // Web home
		KC_NUMPADCOMMA = 0xB3,    // , on numeric keypad (NEC PC98)
		KC_DIVIDE      = 0xB5,    // / on numeric keypad
		KC_SYSRQ       = 0xB7,
		KC_RMENU       = 0xB8,    // right Alt
		KC_PAUSE       = 0xC5,    // Pause
		KC_HOME        = 0xC7,    // Home on arrow keypad
		KC_UP          = 0xC8,    // UpArrow on arrow keypad
		KC_PGUP        = 0xC9,    // PgUp on arrow keypad
		KC_LEFT        = 0xCB,    // LeftArrow on arrow keypad
		KC_RIGHT       = 0xCD,    // RightArrow on arrow keypad
		KC_END         = 0xCF,    // End on arrow keypad
		KC_DOWN        = 0xD0,    // DownArrow on arrow keypad
		KC_PGDOWN      = 0xD1,    // PgDn on arrow keypad
		KC_INSERT      = 0xD2,    // Insert on arrow keypad
		KC_DELETE      = 0xD3,    // Delete on arrow keypad
		KC_LWIN        = 0xDB,    // Left Windows key
		KC_RWIN        = 0xDC,    // Right Windows key
		KC_APPS        = 0xDD,    // AppMenu key
		KC_POWER       = 0xDE,    // System Power
		KC_SLEEP       = 0xDF,    // System Sleep
		KC_WAKE        = 0xE3,    // System Wake
		KC_WEBSEARCH   = 0xE5,    // Web Search
		KC_WEBFAVORITES= 0xE6,    // Web Favorites
		KC_WEBREFRESH  = 0xE7,    // Web Refresh
		KC_WEBSTOP     = 0xE8,    // Web Stop
		KC_WEBFORWARD  = 0xE9,    // Web Forward
		KC_WEBBACK     = 0xEA,    // Web Back
		KC_MYCOMPUTER  = 0xEB,    // My Computer
		KC_MAIL        = 0xEC,    // Mail
		KC_MEDIASELECT = 0xED     // Media Select
	};

OIS::Mouse

Mouse base class. To be implemented by specific system (ie. DirectX Mouse) This class is useful as you remain OS independent using this common interface.

OIS::MouseListener

To recieve buffered mouse input, derive a class from this, and implement the methods here. Then set the call back to your Mouse instance with Mouse::setEventCallback

OIS mouse button id's

// /Dependencies/src/ois/includes/OISMouse.h
	enum MouseButtonID
	{
		MB_Left = 0, MB_Right, MB_Middle,
		MB_Button3, MB_Button4,	MB_Button5, MB_Button6,	MB_Button7
	};

API

Ogre::FrameListener #include <OgreFrameListener.h>
virtual bool frameRenderingQueued(const Ogre::FrameEvent &evt);

Called after all render targets have had their rendering commands issued, but before render windows have been asked to flip their buffers over. The usefulness of this event comes from the fact that rendering commands are queued for the GPU to process. These can take a little while to finish, and so while that is happening the CPU can be doing useful things. Once the request to 'flip buffers' happens, the thread requesting it will block until the GPU is ready, which can waste CPU cycles. Therefore, it is often a good idea to use this callback to perform per-frame processing. Of course because the frame's rendering commands have already been issued, any changes you make will only take effect from the next frame, but in most cases that's not noticeable. Returns True to continue rendering, false to drop out of the rendering loop.

OIS::InputManager #include <OISInputManager.h>
static InputManager * createInputSystem (std::size_t winHandle)

Creates appropriate input system dependent on platform. Parameters winHandle Contains OS specific window handle (such as HWND or X11 Window)

static InputManager * createInputSystem (ParamList &paramList)

Creates appropriate input system dependent on platform. Parameters paramList ParamList contains OS specific info (such as HWND and HINSTANCE for window apps), and access mode.

static void destroyInputSystem (InputManager *manager)
OIS::Keyboard #include <OISKeyboard.h>
virtual void setEventCallback(KeyListener *keyListener)
// /OIS/OISKeyboard.h
		/**
		@remarks
			Register/unregister a Keyboard Listener - Only one allowed for simplicity. If broadcasting
			is neccessary, just broadcast from the callback you registered.
		@param keyListener
			Send a pointer to a class derived from KeyListener or 0 to clear the callback
		*/
		virtual void setEventCallback(KeyListener *keyListener) { mListener = keyListener;}
OIS::KeyListener #include <OISKeyboard.h>
virtual bool keyPressed (const OIS::KeyEvent &arg);
virtual bool keyReleased (const OIS::KeyEvent &arg);
OIS::Mouse #include <OISMouse.h>
virtual void setEventCallback( MouseListener *mouseListener )
// /OIS/OISMouse.h
		/**
		@remarks
			Register/unregister a Mouse Listener - Only one allowed for simplicity. If broadcasting
			is neccessary, just broadcast from the callback you registered.
		@param mouseListener
			Send a pointer to a class derived from MouseListener or 0 to clear the callback
		*/
		virtual void setEventCallback( MouseListener *mouseListener ) {mListener = mouseListener;}
OIS::MouseListener #include <OISMouse.h>
virtual bool mouseMoved (const OIS::MouseEvent &arg);
virtual bool mousePressed (const OIS::MouseEvent &arg, OIS::MouseButtonID id);
virtual bool mouseReleased (const OIS::MouseEvent &arg, OIS::MouseButtonID id);

Summary

//////////////////// Somewhere in your code

	OISManager* ois = OISManager::Builder::getInstance()
			->setRenderWindow(this->mOgreRenderWindow)
			->setBufferedKeyboardInput(builder->bufferedKeyboardInput)
			->setBufferedMouseInput(builder->bufferedMouseInput)
			->build();
	//
	this->mKeyboard = Ogress::OISManager::getKeyboardInstancePtr();
	this->mMouse = Ogress::OISManager::getMouseInstancePtr();
	//
	this->mOgreRoot->addFrameListener(ois);
//////////////////// Somewhere in your code





/*
 * OISManager.h
 *
 *  Created on: Oct 31, 2014
 *      Author: Alex Cham
 */

#ifndef OISMANAGER_H_
#define OISMANAGER_H_

#include <OgreRenderWindow.h>
#include <OgreFrameListener.h>
//
#include <OISInputManager.h>
#include <OISKeyboard.h>
#include <OISMouse.h>
//
#include "OISKeyboardListener.h"
#include "OISMouseListener.h"

namespace Ogress {

	class OISManager: public Ogre::FrameListener {

		public:
			class Builder {

				private:

					Builder();
					~Builder();
					static Builder INSTANCE;

				public:

					static Builder* getInstance() {
						return &INSTANCE;
					}

					OISManager* build();

					Ogre::RenderWindow* mWindow;
//
					bool bufferedKeyboardInput;
					bool bufferedMouseInput;
//
					Builder* setRenderWindow(Ogre::RenderWindow*);
//
					Builder* setBufferedKeyboardInput(
							bool);
					Builder* setBufferedMouseInput(bool);
			};

			static OIS::Keyboard* getKeyboardInstancePtr() {
				return mKeyboard;
			}
			static OIS::Mouse* getMouseInstancePtr() {
				return mMouse;
			}
		private:

			OISManager(Builder*);
			~OISManager();
			//
			Ogre::RenderWindow* mWindow;
			//
			OIS::ParamList mParamList;
			OIS::InputManager* mInputManager;
			static OIS::Mouse* mMouse;
			static OIS::Keyboard* mKeyboard;

			bool bufferedKeyboardInput;
			bool bufferedMouseInput;
			//
			void initParamList();
			void initInputSystem();
			virtual bool frameRenderingQueued(const Ogre::FrameEvent &evt);
	};
}

#endif /* OISMANAGER_H_ */





/*
 * InputSystem.cpp
 *
 *  Created on: Oct 31, 2014
 *      Author: Alex Cham
 */

#include "OISManager.h"


OIS::Keyboard* Ogress::OISManager::mKeyboard;
OIS::Mouse* Ogress::OISManager::mMouse;
Ogress::OISManager::Builder Ogress::OISManager::Builder::INSTANCE;

//////////////////// X::

Ogress::OISManager::OISManager(Builder* builder) {
	this->mWindow = builder->mWindow;
	this->bufferedKeyboardInput = builder->bufferedKeyboardInput;
	this->bufferedMouseInput = builder->bufferedMouseInput;
	//
	initParamList();
	initInputSystem();
	//
	OIS::KeyListener* kL = new Ogress::OISKeyboardListener();
	this->mKeyboard->setEventCallback(kL);
	//
	OIS::MouseListener* mL = new Ogress::OISMouseListener();
	this->mMouse->setEventCallback(mL);
}

Ogress::OISManager::~OISManager() {
	delete &this->mParamList;
	delete &this->mMouse;
	delete &this->mKeyboard;
	delete &this->mInputManager;
	delete &this->mWindow;
	delete this;
}

void Ogress::OISManager::initParamList(){
	size_t windowHnd = 0;
	std::ostringstream windowHndStr;
	this->mWindow->getCustomAttribute("WINDOW", &windowHnd);
	windowHndStr << windowHnd;
	this->mParamList.insert(
			std::make_pair(std::string("WINDOW"), windowHndStr.str()));
}



/**
 * WARNING:
 * Mouse trap troubleshooting (Linux)
 * Ctrl+Alt+F1
 * Login as user which start this app
 * ps -a
 * kill pN
 */
void Ogress::OISManager::initInputSystem(){
	this->mInputManager = OIS::InputManager::createInputSystem(this->mParamList);
	//
	this->mKeyboard = static_cast<OIS::Keyboard*>(this->mInputManager->createInputObject(
			OIS::OISKeyboard, this->bufferedKeyboardInput));
	//assert(mKeyboard != NULL);

	this->mMouse = static_cast<OIS::Mouse*>(this->mInputManager->createInputObject(
			OIS::OISMouse, this->bufferedMouseInput));
	//assert(mMouse != NULL);
}



bool Ogress::OISManager::frameRenderingQueued(const Ogre::FrameEvent& evt) {
	if (this->mWindow->isClosed())
		return false;

	//Need to capture/update each device
	this->mKeyboard->capture();
	this->mMouse->capture();

	if (this->mKeyboard->isKeyDown(OIS::KC_ESCAPE)){
		std::cout << "Ogress::OISManager::frameRenderingQueued: OIS::KC_ESCAPE" << std::endl;//Is Esc pressed
		return false;	//Exit Render loop
	}
	return true;
}



//////////////////// X::Builder::


Ogress::OISManager::Builder::Builder() {

}

Ogress::OISManager::Builder::~Builder() {
	delete &this->mWindow;
	delete &this->INSTANCE;
	delete this;
}

Ogress::OISManager* Ogress::OISManager::Builder::build() {
	OISManager* x = new OISManager(this);
	return x;
}


Ogress::OISManager::Builder* Ogress::OISManager::Builder::setRenderWindow(Ogre::RenderWindow* window) {
	this->mWindow = window;
	return &INSTANCE;
}
//

Ogress::OISManager::Builder* Ogress::OISManager::Builder::setBufferedKeyboardInput(bool bufferedKeyboardInput) {
	this->bufferedKeyboardInput = bufferedKeyboardInput;
	return &INSTANCE;
}

Ogress::OISManager::Builder* Ogress::OISManager::Builder::setBufferedMouseInput(bool bufferedMouseInput) {
	this->bufferedMouseInput = bufferedMouseInput;
	return &INSTANCE;
}






/*
 * OISKeyboardListener.h
 *
 *  Created on: Oct 31, 2014
 *      Author: Alex Cham
 */

#ifndef OISKEYBOARDLISTENER_H_
#define OISKEYBOARDLISTENER_H_

/*
 To recieve buffered keyboard input, derive a class from OIS::KeyListener, and implement the methods.
 Then set the call back to your Keyboard instance with Keyboard::setEventCallback
 */
#include <OISKeyboard.h>

namespace Ogress {
	class OISKeyboardListener: public OIS::KeyListener {
		public:
			OISKeyboardListener();
			~OISKeyboardListener();
			virtual bool keyPressed(const OIS::KeyEvent &arg);
			virtual bool keyReleased(const OIS::KeyEvent &arg);
	};
}

#endif /* OISKEYBOARDLISTENER_H_ */





/*
 * InputSystemListener.cpp
 *
 *  Created on: Oct 31, 2014
 *      Author: Alex Cham
 */

#include <iostream>
#include "OISKeyboardListener.h"

Ogress::OISKeyboardListener::OISKeyboardListener() {

}

Ogress::OISKeyboardListener::~OISKeyboardListener() {
	delete this;
}

bool Ogress::OISKeyboardListener::keyPressed(const OIS::KeyEvent &evt) {
	switch (evt.key) {
		case OIS::KC_Q:
			std::cout << "Ogress::OISKeyboardListener::keyPressed: Q" << std::endl;
			break;
	}
	return true;
}

bool Ogress::OISKeyboardListener::keyReleased(const OIS::KeyEvent &evt) {
	switch (evt.key) {
		case OIS::KC_Q:
			std::cout << "Ogress::OISKeyboardListener::keyReleased: Q" << std::endl;
			break;
	}
	return true;
}





/*
 * OISMouseListener.h
 *
 *  Created on: Nov 1, 2014
 *      Author: Alex Cham
 */

#ifndef OISMOUSELISTENER_H_
#define OISMOUSELISTENER_H_

#include <OISMouse.h>
/**
 * To recieve buffered mouse input, derive a class from OIS::MouseListener, and implement the methods here.
 * Then set the call back to your Mouse instance with Mouse::setEventCallback
 */
namespace Ogress {
	class OISMouseListener: public OIS::MouseListener {
		public:
			OISMouseListener();
			~OISMouseListener();
//
			virtual bool mouseMoved(const OIS::MouseEvent &arg);
			virtual bool mousePressed(const OIS::MouseEvent &arg,
					OIS::MouseButtonID id);
			virtual bool mouseReleased(const OIS::MouseEvent &arg,
					OIS::MouseButtonID id);
	};
}

#endif /* OISMOUSELISTENER_H_ */





/*
 * OISMouseListener.cpp
 *
 *  Created on: Nov 1, 2014
 *      Author: Alex Cham
 */


#include <iostream>
#include "OISMouseListener.h"

Ogress::OISMouseListener::OISMouseListener(){

}

Ogress::OISMouseListener::~OISMouseListener(){
	delete this;
}

bool Ogress::OISMouseListener::mouseMoved (const OIS::MouseEvent &arg){
	return true;
}

bool Ogress::OISMouseListener::mousePressed (const OIS::MouseEvent &arg, OIS::MouseButtonID id){
	//MB_Left = 0, MB_Right, MB_Middle,
	switch(id){
		case OIS::MB_Left :
			std::cout << "Ogress::OISMouseListener::mousePressed: MB_Left" << std::endl;
			break;
		case OIS::MB_Right :
			std::cout << "Ogress::OISMouseListener::mousePressed: MB_Right" << std::endl;
			break;
		case OIS::MB_Middle :
			std::cout << "Ogress::OISMouseListener::mousePressed: MB_Middle" << std::endl;
			break;
	}
	return true;
}

bool Ogress::OISMouseListener::mouseReleased (const OIS::MouseEvent &arg, OIS::MouseButtonID id){
	return true;
}

What happens?

Ogress::OISKeyboardListener::keyPressed: Q
Ogress::OISKeyboardListener::keyReleased: Q
Ogress::OISMouseListener::mousePressed: MB_Left
Ogress::OISMouseListener::mousePressed: MB_Middle
Ogress::OISMouseListener::mousePressed: MB_Right
Ogress::OISManager::frameRenderingQueued: OIS::KC_ESCAPE


References

  1. ^ "SourceForge: version 1.2 release notes".