Home | History | Annotate | Download | only in demos
      1 //////////////////////////////// OS Nuetral Headers ////////////////
      2 #include "OISInputManager.h"
      3 #include "OISException.h"
      4 #include "OISKeyboard.h"
      5 #include "OISMouse.h"
      6 #include "OISJoyStick.h"
      7 #include "OISEvents.h"
      8 
      9 //Advanced Usage
     10 #include "OISForceFeedback.h"
     11 
     12 #include <iostream>
     13 #include <vector>
     14 #include <sstream>
     15 
     16 ////////////////////////////////////Needed Windows Headers////////////
     17 #if defined OIS_WIN32_PLATFORM
     18 #define WIN32_LEAN_AND_MEAN
     19 #include "windows.h"
     20 #ifdef min
     21 #undef min
     22 #endif
     23 #include "resource.h"
     24 LRESULT DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
     25 //////////////////////////////////////////////////////////////////////
     26 ////////////////////////////////////Needed Linux Headers//////////////
     27 #elif defined OIS_LINUX_PLATFORM
     28 #include <X11/Xlib.h>
     29 #include <X11/Xatom.h>
     30 void checkX11Events();
     31 //////////////////////////////////////////////////////////////////////
     32 ////////////////////////////////////Needed Mac Headers//////////////
     33 #elif defined OIS_APPLE_PLATFORM
     34 #include <Carbon/Carbon.h>
     35 void checkMacEvents();
     36 #endif
     37 //////////////////////////////////////////////////////////////////////
     38 using namespace OIS;
     39 
     40 //-- Some local prototypes --//
     41 void doStartup();
     42 void handleNonBufferedKeys();
     43 void handleNonBufferedMouse();
     44 void handleNonBufferedJoy( JoyStick* js );
     45 
     46 //-- Easy access globals --//
     47 bool appRunning = true;				//Global Exit Flag
     48 
     49 const char *g_DeviceType[6] = {"OISUnknown", "OISKeyboard", "OISMouse", "OISJoyStick",
     50 							 "OISTablet", "OISOther"};
     51 
     52 InputManager *g_InputManager = 0;	//Our Input System
     53 Keyboard *g_kb  = 0;				//Keyboard Device
     54 Mouse	 *g_m   = 0;				//Mouse Device
     55 JoyStick* g_joys[4] = {0,0,0,0};	//This demo supports up to 4 controllers
     56 
     57 //-- OS Specific Globals --//
     58 #if defined OIS_WIN32_PLATFORM
     59   HWND hWnd = 0;
     60 #elif defined OIS_LINUX_PLATFORM
     61   Display *xDisp = 0;
     62   Window xWin = 0;
     63 #elif defined OIS_APPLE_PLATFORM
     64   WindowRef mWin = 0;
     65 #endif
     66 
     67 //////////// Common Event handler class ////////
     68 class EventHandler : public KeyListener, public MouseListener, public JoyStickListener
     69 {
     70 public:
     71 	EventHandler() {}
     72 	~EventHandler() {}
     73 	bool keyPressed( const KeyEvent &arg ) {
     74 		std::cout << " KeyPressed {" << arg.key
     75 			<< ", " << ((Keyboard*)(arg.device))->getAsString(arg.key)
     76 			<< "} || Character (" << (char)arg.text << ")" << std::endl;
     77 		return true;
     78 	}
     79 	bool keyReleased( const KeyEvent &arg ) {
     80 		if( arg.key == KC_ESCAPE || arg.key == KC_Q )
     81 			appRunning = false;
     82 		std::cout << "KeyReleased {" << ((Keyboard*)(arg.device))->getAsString(arg.key) << "}\n";
     83 		return true;
     84 	}
     85 	bool mouseMoved( const MouseEvent &arg ) {
     86 		const OIS::MouseState& s = arg.state;
     87 		std::cout << "\nMouseMoved: Abs("
     88 				  << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel("
     89 				  << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")";
     90 		return true;
     91 	}
     92 	bool mousePressed( const MouseEvent &arg, MouseButtonID id ) {
     93 		const OIS::MouseState& s = arg.state;
     94 		std::cout << "\nMouse button #" << id << " pressed. Abs("
     95 				  << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel("
     96 				  << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")";
     97 		return true;
     98 	}
     99 	bool mouseReleased( const MouseEvent &arg, MouseButtonID id ) {
    100 		const OIS::MouseState& s = arg.state;
    101 		std::cout << "\nMouse button #" << id << " released. Abs("
    102 				  << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel("
    103 				  << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")";
    104 		return true;
    105 	}
    106 	bool buttonPressed( const JoyStickEvent &arg, int button ) {
    107 		std::cout << std::endl << arg.device->vendor() << ". Button Pressed # " << button;
    108 		return true;
    109 	}
    110 	bool buttonReleased( const JoyStickEvent &arg, int button ) {
    111 		std::cout << std::endl << arg.device->vendor() << ". Button Released # " << button;
    112 		return true;
    113 	}
    114 	bool axisMoved( const JoyStickEvent &arg, int axis )
    115 	{
    116 		//Provide a little dead zone
    117 		if( arg.state.mAxes[axis].abs > 2500 || arg.state.mAxes[axis].abs < -2500 )
    118 			std::cout << std::endl << arg.device->vendor() << ". Axis # " << axis << " Value: " << arg.state.mAxes[axis].abs;
    119 		return true;
    120 	}
    121 	bool povMoved( const JoyStickEvent &arg, int pov )
    122 	{
    123 		std::cout << std::endl << arg.device->vendor() << ". POV" << pov << " ";
    124 
    125 		if( arg.state.mPOV[pov].direction & Pov::North ) //Going up
    126 			std::cout << "North";
    127 		else if( arg.state.mPOV[pov].direction & Pov::South ) //Going down
    128 			std::cout << "South";
    129 
    130 		if( arg.state.mPOV[pov].direction & Pov::East ) //Going right
    131 			std::cout << "East";
    132 		else if( arg.state.mPOV[pov].direction & Pov::West ) //Going left
    133 			std::cout << "West";
    134 
    135 		if( arg.state.mPOV[pov].direction == Pov::Centered ) //stopped/centered out
    136 			std::cout << "Centered";
    137 		return true;
    138 	}
    139 
    140 	bool vector3Moved( const JoyStickEvent &arg, int index)
    141 	{
    142 		std::cout.precision(2);
    143 		std::cout.flags(std::ios::fixed | std::ios::right);
    144 		std::cout << std::endl << arg.device->vendor() << ". Orientation # " << index
    145 			<< " X Value: " << arg.state.mVectors[index].x
    146 			<< " Y Value: " << arg.state.mVectors[index].y
    147 			<< " Z Value: " << arg.state.mVectors[index].z;
    148 		std::cout.precision();
    149 		std::cout.flags();
    150 		return true;
    151 	}
    152 };
    153 
    154 //Create a global instance
    155 EventHandler handler;
    156 
    157 int main()
    158 {
    159 	std::cout << "\n\n*** OIS Console Demo App is starting up... *** \n";
    160 	try
    161 	{
    162 		doStartup();
    163 		std::cout << "\nStartup done... Hit 'q' or ESC to exit.\n\n";
    164 
    165 		while(appRunning)
    166 		{
    167 			//Throttle down CPU usage
    168 			#if defined OIS_WIN32_PLATFORM
    169 			  Sleep(90);
    170 			  MSG  msg;
    171 			  while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
    172 			  {
    173 				TranslateMessage( &msg );
    174 				DispatchMessage( &msg );
    175 			  }
    176 			#elif defined OIS_LINUX_PLATFORM
    177 			  checkX11Events();
    178 			  usleep( 500 );
    179             #elif defined OIS_APPLE_PLATFORM
    180 			  checkMacEvents();
    181 			  usleep( 500 );
    182 			#endif
    183 
    184 			if( g_kb )
    185 			{
    186 				g_kb->capture();
    187 				if( !g_kb->buffered() )
    188 					handleNonBufferedKeys();
    189 			}
    190 
    191 			if( g_m )
    192 			{
    193 				g_m->capture();
    194 				if( !g_m->buffered() )
    195 					handleNonBufferedMouse();
    196 			}
    197 
    198 			for( int i = 0; i < 4 ; ++i )
    199 			{
    200 				if( g_joys[i] )
    201 				{
    202 					g_joys[i]->capture();
    203 					if( !g_joys[i]->buffered() )
    204 						handleNonBufferedJoy( g_joys[i] );
    205 				}
    206 			}
    207 		}
    208 	}
    209 	catch( const Exception &ex )
    210 	{
    211 		#if defined OIS_WIN32_PLATFORM
    212 		  MessageBox( NULL, ex.eText, "An exception has occurred!", MB_OK |
    213 				MB_ICONERROR | MB_TASKMODAL);
    214 		#else
    215 		  std::cout << "\nOIS Exception Caught!\n" << "\t" << ex.eText << "[Line "
    216 			<< ex.eLine << " in " << ex.eFile << "]\nExiting App";
    217 		#endif
    218 	}
    219 	catch(std::exception &ex)
    220 	{
    221 		std::cout << "Caught std::exception: what = " << ex.what() << std::endl;
    222 	}
    223 
    224 	//Destroying the manager will cleanup unfreed devices
    225 	std::cout << "Cleaning up...\n";
    226 	if( g_InputManager )
    227 		InputManager::destroyInputSystem(g_InputManager);
    228 
    229 #if defined OIS_LINUX_PLATFORM
    230 	// Be nice to X and clean up the x window
    231 	XDestroyWindow(xDisp, xWin);
    232 	XCloseDisplay(xDisp);
    233 #endif
    234 
    235 	std::cout << "\nGoodbye!\n";
    236 	return 0;
    237 }
    238 
    239 void doStartup()
    240 {
    241 	ParamList pl;
    242 
    243 #if defined OIS_WIN32_PLATFORM
    244 	//Create a capture window for Input Grabbing
    245 	hWnd = CreateDialog( 0, MAKEINTRESOURCE(IDD_DIALOG1), 0,(DLGPROC)DlgProc);
    246 	if( hWnd == NULL )
    247 		OIS_EXCEPT(E_General, "Failed to create Win32 Window Dialog!");
    248 
    249 	ShowWindow(hWnd, SW_SHOW);
    250 
    251 	std::ostringstream wnd;
    252 	wnd << (size_t)hWnd;
    253 
    254 	pl.insert(std::make_pair( std::string("WINDOW"), wnd.str() ));
    255 
    256 	//Default mode is foreground exclusive..but, we want to show mouse - so nonexclusive
    257 //	pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
    258 //	pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
    259 #elif defined OIS_LINUX_PLATFORM
    260 	//Connects to default X window
    261 	if( !(xDisp = XOpenDisplay(0)) )
    262 		OIS_EXCEPT(E_General, "Error opening X!");
    263 	//Create a window
    264 	xWin = XCreateSimpleWindow(xDisp, DefaultRootWindow(xDisp), 0, 0, 100, 100, 0, 0, 0);
    265 	//bind our connection to that window
    266 	XMapWindow(xDisp, xWin);
    267 	// XInternAtom
    268 	//Select what events we want to listen to locally
    269 	XSelectInput(xDisp, xWin, StructureNotifyMask | SubstructureNotifyMask);
    270 	Atom wmProto = XInternAtom(xDisp, "WM_PROTOCOLS", False);
    271 	Atom wmDelete = XInternAtom(xDisp, "WM_DELETE_WINDOW", False);
    272 	XChangeProperty(xDisp, xWin, wmProto, XA_ATOM, 32, 0, (const unsigned char*)&wmDelete, 1);
    273 	XEvent evtent;
    274 	do
    275 	{
    276 		XNextEvent(xDisp, &evtent);
    277 	} while(evtent.type != MapNotify);
    278 
    279 	std::ostringstream wnd;
    280 	wnd << xWin;
    281 
    282 	pl.insert(std::make_pair(std::string("WINDOW"), wnd.str()));
    283 
    284 	//For this demo, show mouse and do not grab (confine to window)
    285 //	pl.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
    286 //	pl.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
    287 #elif defined OIS_APPLE_PLATFORM && !__LP64__
    288     // create the window rect in global coords
    289     ::Rect windowRect;
    290     windowRect.left = 0;
    291     windowRect.top = 0;
    292     windowRect.right = 300;
    293     windowRect.bottom = 300;
    294 
    295     // set the default attributes for the window
    296     WindowAttributes windowAttrs = kWindowStandardDocumentAttributes
    297         | kWindowStandardHandlerAttribute
    298         | kWindowInWindowMenuAttribute
    299         | kWindowHideOnFullScreenAttribute;
    300 
    301     // Create the window
    302     CreateNewWindow(kDocumentWindowClass, windowAttrs, &windowRect, &mWin);
    303 
    304     // Color the window background black
    305     SetThemeWindowBackground (mWin, kThemeBrushBlack, true);
    306 
    307     // Set the title of our window
    308     CFStringRef titleRef = CFStringCreateWithCString( kCFAllocatorDefault, "OIS Input", kCFStringEncodingASCII );
    309     SetWindowTitleWithCFString( mWin, titleRef );
    310 
    311     // Center our window on the screen
    312     RepositionWindow( mWin, NULL, kWindowCenterOnMainScreen );
    313 
    314     // Install the event handler for the window
    315     InstallStandardEventHandler(GetWindowEventTarget(mWin));
    316 
    317     // This will give our window focus, and not lock it to the terminal
    318     ProcessSerialNumber psn = { 0, kCurrentProcess };
    319     TransformProcessType( &psn, kProcessTransformToForegroundApplication );
    320 	SetFrontProcess(&psn);
    321 
    322     // Display and select our window
    323     ShowWindow(mWin);
    324     SelectWindow(mWin);
    325 
    326     std::ostringstream wnd;
    327 	wnd << (unsigned int)mWin; //cast to int so it gets encoded correctly (else it gets stored as a hex string)
    328     std::cout << "WindowRef: " << mWin << " WindowRef as int: " << wnd.str() << "\n";
    329 	pl.insert(std::make_pair(std::string("WINDOW"), wnd.str()));
    330 #endif
    331 
    332 	//This never returns null.. it will raise an exception on errors
    333 	g_InputManager = InputManager::createInputSystem(pl);
    334 
    335 	//Lets enable all addons that were compiled in:
    336 	g_InputManager->enableAddOnFactory(InputManager::AddOn_All);
    337 
    338 	//Print debugging information
    339 	unsigned int v = g_InputManager->getVersionNumber();
    340 	std::cout << "OIS Version: " << (v>>16 ) << "." << ((v>>8) & 0x000000FF) << "." << (v & 0x000000FF)
    341 		<< "\nRelease Name: " << g_InputManager->getVersionName()
    342 		<< "\nManager: " << g_InputManager->inputSystemName()
    343 		<< "\nTotal Keyboards: " << g_InputManager->getNumberOfDevices(OISKeyboard)
    344 		<< "\nTotal Mice: " << g_InputManager->getNumberOfDevices(OISMouse)
    345 		<< "\nTotal JoySticks: " << g_InputManager->getNumberOfDevices(OISJoyStick);
    346 
    347 	//List all devices
    348 	DeviceList list = g_InputManager->listFreeDevices();
    349 	for( DeviceList::iterator i = list.begin(); i != list.end(); ++i )
    350 		std::cout << "\n\tDevice: " << g_DeviceType[i->first] << " Vendor: " << i->second;
    351 
    352 	g_kb = (Keyboard*)g_InputManager->createInputObject( OISKeyboard, true );
    353 	g_kb->setEventCallback( &handler );
    354 
    355 	g_m = (Mouse*)g_InputManager->createInputObject( OISMouse, true );
    356 	g_m->setEventCallback( &handler );
    357 	const MouseState &ms = g_m->getMouseState();
    358 	ms.width = 100;
    359 	ms.height = 100;
    360 
    361 	try
    362 	{
    363 		//This demo uses at most 4 joysticks - use old way to create (i.e. disregard vendor)
    364 		int numSticks = std::min(g_InputManager->getNumberOfDevices(OISJoyStick), 4);
    365 		for( int i = 0; i < numSticks; ++i )
    366 		{
    367 			g_joys[i] = (JoyStick*)g_InputManager->createInputObject( OISJoyStick, true );
    368 			g_joys[i]->setEventCallback( &handler );
    369 			std::cout << "\n\nCreating Joystick " << (i + 1)
    370 				<< "\n\tAxes: " << g_joys[i]->getNumberOfComponents(OIS_Axis)
    371 				<< "\n\tSliders: " << g_joys[i]->getNumberOfComponents(OIS_Slider)
    372 				<< "\n\tPOV/HATs: " << g_joys[i]->getNumberOfComponents(OIS_POV)
    373 				<< "\n\tButtons: " << g_joys[i]->getNumberOfComponents(OIS_Button)
    374 				<< "\n\tVector3: " << g_joys[i]->getNumberOfComponents(OIS_Vector3);
    375 		}
    376 	}
    377 	catch(OIS::Exception &ex)
    378 	{
    379 		std::cout << "\nException raised on joystick creation: " << ex.eText << std::endl;
    380 	}
    381 }
    382 
    383 void handleNonBufferedKeys()
    384 {
    385 	if( g_kb->isKeyDown( KC_ESCAPE ) || g_kb->isKeyDown( KC_Q ) )
    386 		appRunning = false;
    387 
    388 	if( g_kb->isModifierDown(Keyboard::Shift) )
    389 		std::cout << "Shift is down..\n";
    390 	if( g_kb->isModifierDown(Keyboard::Alt) )
    391 		std::cout << "Alt is down..\n";
    392 	if( g_kb->isModifierDown(Keyboard::Ctrl) )
    393 		std::cout << "Ctrl is down..\n";
    394 }
    395 
    396 void handleNonBufferedMouse()
    397 {
    398 	//Just dump the current mouse state
    399 	const MouseState &ms = g_m->getMouseState();
    400 	std::cout << "\nMouse: Abs(" << ms.X.abs << " " << ms.Y.abs << " " << ms.Z.abs
    401 		<< ") B: " << ms.buttons << " Rel(" << ms.X.rel << " " << ms.Y.rel << " " << ms.Z.rel << ")";
    402 }
    403 
    404 void handleNonBufferedJoy( JoyStick* js )
    405 {
    406 	//Just dump the current joy state
    407 	const JoyStickState &joy = js->getJoyStickState();
    408 	for( unsigned int i = 0; i < joy.mAxes.size(); ++i )
    409 		std::cout << "\nAxis " << i << " X: " << joy.mAxes[i].abs;
    410 }
    411 
    412 #if defined OIS_WIN32_PLATFORM
    413 LRESULT DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    414 {
    415 	return FALSE;
    416 }
    417 #endif
    418 
    419 #if defined OIS_LINUX_PLATFORM
    420 //This is just here to show that you still recieve x11 events, as the lib only needs mouse/key events
    421 void checkX11Events()
    422 {
    423 	if(!appRunning)
    424 		return;
    425 
    426 	XEvent event;
    427 
    428 	while(XPending(xDisp) > 0)
    429 	{
    430 		XNextEvent(xDisp, &event);
    431 		//Handle Resize events
    432 		if(event.type == ConfigureNotify)
    433 		{
    434 			if(g_m)
    435 			{
    436 				const MouseState &ms = g_m->getMouseState();
    437 				ms.width = event.xconfigure.width;
    438 				ms.height = event.xconfigure.height;
    439 			}
    440 		}
    441 		else if(event.type == ClientMessage || event.type == DestroyNotify)
    442 		{	// We only get DestroyNotify for child windows. However, we regeistered earlier to receive WM_DELETE_MESSAGEs
    443 			std::cout << "Exiting...\n";
    444 			appRunning = false;
    445 			return;
    446 		}
    447 		else
    448 		{
    449 			std::cout << "\nUnknown X Event: " << event.type << std::endl;
    450 		}
    451 	}
    452 }
    453 #endif
    454 
    455 #if defined OIS_APPLE_PLATFORM
    456 void checkMacEvents()
    457 {
    458 	//TODO - Check for window resize events, and then adjust the members of mousestate
    459 	EventRef event = NULL;
    460 	EventTargetRef targetWindow = GetEventDispatcherTarget();
    461 
    462 	if( ReceiveNextEvent( 0, NULL, kEventDurationNoWait, true, &event ) == noErr )
    463 	{
    464 		SendEventToEventTarget(event, targetWindow);
    465 		std::cout << "Event : " << GetEventKind(event) << "\n";
    466 		ReleaseEvent(event);
    467 	}
    468 }
    469 #endif
    470