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