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:
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 std::cout << "KeyReleased {" << ((Keyboard*)(arg.device))->getAsString(arg.key) << "}\n";
83 return true;
84 }
mouseMoved(const MouseEvent & arg)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 }
mousePressed(const MouseEvent & arg,MouseButtonID id)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 }
mouseReleased(const MouseEvent & arg,MouseButtonID id)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 }
buttonPressed(const JoyStickEvent & arg,int button)106 bool buttonPressed( const JoyStickEvent &arg, int button ) {
107 std::cout << std::endl << arg.device->vendor() << ". Button Pressed # " << button;
108 return true;
109 }
buttonReleased(const JoyStickEvent & arg,int button)110 bool buttonReleased( const JoyStickEvent &arg, int button ) {
111 std::cout << std::endl << arg.device->vendor() << ". Button Released # " << button;
112 return true;
113 }
axisMoved(const JoyStickEvent & arg,int axis)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 }
povMoved(const JoyStickEvent & arg,int pov)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
vector3Moved(const JoyStickEvent & arg,int index)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
main()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
doStartup()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
handleNonBufferedKeys()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
handleNonBufferedMouse()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
handleNonBufferedJoy(JoyStick * js)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
DlgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)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
checkX11Events()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
checkMacEvents()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