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