//////////////////////////////// OS Nuetral Headers //////////////// #include "OISInputManager.h" #include "OISException.h" #include "OISKeyboard.h" #include "OISMouse.h" #include "OISJoyStick.h" #include "OISEvents.h" //Advanced Usage #include "OISForceFeedback.h" #include #include #include ////////////////////////////////////Needed Windows Headers//////////// #if defined OIS_WIN32_PLATFORM #define WIN32_LEAN_AND_MEAN #include "windows.h" #ifdef min #undef min #endif #include "resource.h" LRESULT DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); ////////////////////////////////////////////////////////////////////// ////////////////////////////////////Needed Linux Headers////////////// #elif defined OIS_LINUX_PLATFORM #include #include void checkX11Events(); ////////////////////////////////////////////////////////////////////// ////////////////////////////////////Needed Mac Headers////////////// #elif defined OIS_APPLE_PLATFORM #include void checkMacEvents(); #endif ////////////////////////////////////////////////////////////////////// using namespace OIS; //-- Some local prototypes --// void doStartup(); void handleNonBufferedKeys(); void handleNonBufferedMouse(); void handleNonBufferedJoy( JoyStick* js ); //-- Easy access globals --// bool appRunning = true; //Global Exit Flag const char *g_DeviceType[6] = {"OISUnknown", "OISKeyboard", "OISMouse", "OISJoyStick", "OISTablet", "OISOther"}; InputManager *g_InputManager = 0; //Our Input System Keyboard *g_kb = 0; //Keyboard Device Mouse *g_m = 0; //Mouse Device JoyStick* g_joys[4] = {0,0,0,0}; //This demo supports up to 4 controllers //-- OS Specific Globals --// #if defined OIS_WIN32_PLATFORM HWND hWnd = 0; #elif defined OIS_LINUX_PLATFORM Display *xDisp = 0; Window xWin = 0; #elif defined OIS_APPLE_PLATFORM WindowRef mWin = 0; #endif //////////// Common Event handler class //////// class EventHandler : public KeyListener, public MouseListener, public JoyStickListener { public: EventHandler() {} ~EventHandler() {} bool keyPressed( const KeyEvent &arg ) { std::cout << " KeyPressed {" << arg.key << ", " << ((Keyboard*)(arg.device))->getAsString(arg.key) << "} || Character (" << (char)arg.text << ")" << std::endl; return true; } bool keyReleased( const KeyEvent &arg ) { if( arg.key == KC_ESCAPE || arg.key == KC_Q ) appRunning = false; std::cout << "KeyReleased {" << ((Keyboard*)(arg.device))->getAsString(arg.key) << "}\n"; return true; } bool mouseMoved( const MouseEvent &arg ) { const OIS::MouseState& s = arg.state; std::cout << "\nMouseMoved: Abs(" << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel(" << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")"; return true; } bool mousePressed( const MouseEvent &arg, MouseButtonID id ) { const OIS::MouseState& s = arg.state; std::cout << "\nMouse button #" << id << " pressed. Abs(" << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel(" << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")"; return true; } bool mouseReleased( const MouseEvent &arg, MouseButtonID id ) { const OIS::MouseState& s = arg.state; std::cout << "\nMouse button #" << id << " released. Abs(" << s.X.abs << ", " << s.Y.abs << ", " << s.Z.abs << ") Rel(" << s.X.rel << ", " << s.Y.rel << ", " << s.Z.rel << ")"; return true; } bool buttonPressed( const JoyStickEvent &arg, int button ) { std::cout << std::endl << arg.device->vendor() << ". Button Pressed # " << button; return true; } bool buttonReleased( const JoyStickEvent &arg, int button ) { std::cout << std::endl << arg.device->vendor() << ". Button Released # " << button; return true; } bool axisMoved( const JoyStickEvent &arg, int axis ) { //Provide a little dead zone if( arg.state.mAxes[axis].abs > 2500 || arg.state.mAxes[axis].abs < -2500 ) std::cout << std::endl << arg.device->vendor() << ". Axis # " << axis << " Value: " << arg.state.mAxes[axis].abs; return true; } bool povMoved( const JoyStickEvent &arg, int pov ) { std::cout << std::endl << arg.device->vendor() << ". POV" << pov << " "; if( arg.state.mPOV[pov].direction & Pov::North ) //Going up std::cout << "North"; else if( arg.state.mPOV[pov].direction & Pov::South ) //Going down std::cout << "South"; if( arg.state.mPOV[pov].direction & Pov::East ) //Going right std::cout << "East"; else if( arg.state.mPOV[pov].direction & Pov::West ) //Going left std::cout << "West"; if( arg.state.mPOV[pov].direction == Pov::Centered ) //stopped/centered out std::cout << "Centered"; return true; } bool vector3Moved( const JoyStickEvent &arg, int index) { std::cout.precision(2); std::cout.flags(std::ios::fixed | std::ios::right); std::cout << std::endl << arg.device->vendor() << ". Orientation # " << index << " X Value: " << arg.state.mVectors[index].x << " Y Value: " << arg.state.mVectors[index].y << " Z Value: " << arg.state.mVectors[index].z; std::cout.precision(); std::cout.flags(); return true; } }; //Create a global instance EventHandler handler; int main() { std::cout << "\n\n*** OIS Console Demo App is starting up... *** \n"; try { doStartup(); std::cout << "\nStartup done... Hit 'q' or ESC to exit.\n\n"; while(appRunning) { //Throttle down CPU usage #if defined OIS_WIN32_PLATFORM Sleep(90); MSG msg; while( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } #elif defined OIS_LINUX_PLATFORM checkX11Events(); usleep( 500 ); #elif defined OIS_APPLE_PLATFORM checkMacEvents(); usleep( 500 ); #endif if( g_kb ) { g_kb->capture(); if( !g_kb->buffered() ) handleNonBufferedKeys(); } if( g_m ) { g_m->capture(); if( !g_m->buffered() ) handleNonBufferedMouse(); } for( int i = 0; i < 4 ; ++i ) { if( g_joys[i] ) { g_joys[i]->capture(); if( !g_joys[i]->buffered() ) handleNonBufferedJoy( g_joys[i] ); } } } } catch( const Exception &ex ) { #if defined OIS_WIN32_PLATFORM MessageBox( NULL, ex.eText, "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cout << "\nOIS Exception Caught!\n" << "\t" << ex.eText << "[Line " << ex.eLine << " in " << ex.eFile << "]\nExiting App"; #endif } catch(std::exception &ex) { std::cout << "Caught std::exception: what = " << ex.what() << std::endl; } //Destroying the manager will cleanup unfreed devices std::cout << "Cleaning up...\n"; if( g_InputManager ) InputManager::destroyInputSystem(g_InputManager); #if defined OIS_LINUX_PLATFORM // Be nice to X and clean up the x window XDestroyWindow(xDisp, xWin); XCloseDisplay(xDisp); #endif std::cout << "\nGoodbye!\n"; return 0; } void doStartup() { ParamList pl; #if defined OIS_WIN32_PLATFORM //Create a capture window for Input Grabbing hWnd = CreateDialog( 0, MAKEINTRESOURCE(IDD_DIALOG1), 0,(DLGPROC)DlgProc); if( hWnd == NULL ) OIS_EXCEPT(E_General, "Failed to create Win32 Window Dialog!"); ShowWindow(hWnd, SW_SHOW); std::ostringstream wnd; wnd << (size_t)hWnd; pl.insert(std::make_pair( std::string("WINDOW"), wnd.str() )); //Default mode is foreground exclusive..but, we want to show mouse - so nonexclusive // pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" ))); // pl.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE"))); #elif defined OIS_LINUX_PLATFORM //Connects to default X window if( !(xDisp = XOpenDisplay(0)) ) OIS_EXCEPT(E_General, "Error opening X!"); //Create a window xWin = XCreateSimpleWindow(xDisp, DefaultRootWindow(xDisp), 0, 0, 100, 100, 0, 0, 0); //bind our connection to that window XMapWindow(xDisp, xWin); // XInternAtom //Select what events we want to listen to locally XSelectInput(xDisp, xWin, StructureNotifyMask | SubstructureNotifyMask); Atom wmProto = XInternAtom(xDisp, "WM_PROTOCOLS", False); Atom wmDelete = XInternAtom(xDisp, "WM_DELETE_WINDOW", False); XChangeProperty(xDisp, xWin, wmProto, XA_ATOM, 32, 0, (const unsigned char*)&wmDelete, 1); XEvent evtent; do { XNextEvent(xDisp, &evtent); } while(evtent.type != MapNotify); std::ostringstream wnd; wnd << xWin; pl.insert(std::make_pair(std::string("WINDOW"), wnd.str())); //For this demo, show mouse and do not grab (confine to window) // pl.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false"))); // pl.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false"))); #elif defined OIS_APPLE_PLATFORM && !__LP64__ // create the window rect in global coords ::Rect windowRect; windowRect.left = 0; windowRect.top = 0; windowRect.right = 300; windowRect.bottom = 300; // set the default attributes for the window WindowAttributes windowAttrs = kWindowStandardDocumentAttributes | kWindowStandardHandlerAttribute | kWindowInWindowMenuAttribute | kWindowHideOnFullScreenAttribute; // Create the window CreateNewWindow(kDocumentWindowClass, windowAttrs, &windowRect, &mWin); // Color the window background black SetThemeWindowBackground (mWin, kThemeBrushBlack, true); // Set the title of our window CFStringRef titleRef = CFStringCreateWithCString( kCFAllocatorDefault, "OIS Input", kCFStringEncodingASCII ); SetWindowTitleWithCFString( mWin, titleRef ); // Center our window on the screen RepositionWindow( mWin, NULL, kWindowCenterOnMainScreen ); // Install the event handler for the window InstallStandardEventHandler(GetWindowEventTarget(mWin)); // This will give our window focus, and not lock it to the terminal ProcessSerialNumber psn = { 0, kCurrentProcess }; TransformProcessType( &psn, kProcessTransformToForegroundApplication ); SetFrontProcess(&psn); // Display and select our window ShowWindow(mWin); SelectWindow(mWin); std::ostringstream wnd; wnd << (unsigned int)mWin; //cast to int so it gets encoded correctly (else it gets stored as a hex string) std::cout << "WindowRef: " << mWin << " WindowRef as int: " << wnd.str() << "\n"; pl.insert(std::make_pair(std::string("WINDOW"), wnd.str())); #endif //This never returns null.. it will raise an exception on errors g_InputManager = InputManager::createInputSystem(pl); //Lets enable all addons that were compiled in: g_InputManager->enableAddOnFactory(InputManager::AddOn_All); //Print debugging information unsigned int v = g_InputManager->getVersionNumber(); std::cout << "OIS Version: " << (v>>16 ) << "." << ((v>>8) & 0x000000FF) << "." << (v & 0x000000FF) << "\nRelease Name: " << g_InputManager->getVersionName() << "\nManager: " << g_InputManager->inputSystemName() << "\nTotal Keyboards: " << g_InputManager->getNumberOfDevices(OISKeyboard) << "\nTotal Mice: " << g_InputManager->getNumberOfDevices(OISMouse) << "\nTotal JoySticks: " << g_InputManager->getNumberOfDevices(OISJoyStick); //List all devices DeviceList list = g_InputManager->listFreeDevices(); for( DeviceList::iterator i = list.begin(); i != list.end(); ++i ) std::cout << "\n\tDevice: " << g_DeviceType[i->first] << " Vendor: " << i->second; g_kb = (Keyboard*)g_InputManager->createInputObject( OISKeyboard, true ); g_kb->setEventCallback( &handler ); g_m = (Mouse*)g_InputManager->createInputObject( OISMouse, true ); g_m->setEventCallback( &handler ); const MouseState &ms = g_m->getMouseState(); ms.width = 100; ms.height = 100; try { //This demo uses at most 4 joysticks - use old way to create (i.e. disregard vendor) int numSticks = std::min(g_InputManager->getNumberOfDevices(OISJoyStick), 4); for( int i = 0; i < numSticks; ++i ) { g_joys[i] = (JoyStick*)g_InputManager->createInputObject( OISJoyStick, true ); g_joys[i]->setEventCallback( &handler ); std::cout << "\n\nCreating Joystick " << (i + 1) << "\n\tAxes: " << g_joys[i]->getNumberOfComponents(OIS_Axis) << "\n\tSliders: " << g_joys[i]->getNumberOfComponents(OIS_Slider) << "\n\tPOV/HATs: " << g_joys[i]->getNumberOfComponents(OIS_POV) << "\n\tButtons: " << g_joys[i]->getNumberOfComponents(OIS_Button) << "\n\tVector3: " << g_joys[i]->getNumberOfComponents(OIS_Vector3); } } catch(OIS::Exception &ex) { std::cout << "\nException raised on joystick creation: " << ex.eText << std::endl; } } void handleNonBufferedKeys() { if( g_kb->isKeyDown( KC_ESCAPE ) || g_kb->isKeyDown( KC_Q ) ) appRunning = false; if( g_kb->isModifierDown(Keyboard::Shift) ) std::cout << "Shift is down..\n"; if( g_kb->isModifierDown(Keyboard::Alt) ) std::cout << "Alt is down..\n"; if( g_kb->isModifierDown(Keyboard::Ctrl) ) std::cout << "Ctrl is down..\n"; } void handleNonBufferedMouse() { //Just dump the current mouse state const MouseState &ms = g_m->getMouseState(); std::cout << "\nMouse: Abs(" << ms.X.abs << " " << ms.Y.abs << " " << ms.Z.abs << ") B: " << ms.buttons << " Rel(" << ms.X.rel << " " << ms.Y.rel << " " << ms.Z.rel << ")"; } void handleNonBufferedJoy( JoyStick* js ) { //Just dump the current joy state const JoyStickState &joy = js->getJoyStickState(); for( unsigned int i = 0; i < joy.mAxes.size(); ++i ) std::cout << "\nAxis " << i << " X: " << joy.mAxes[i].abs; } #if defined OIS_WIN32_PLATFORM LRESULT DlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { return FALSE; } #endif #if defined OIS_LINUX_PLATFORM //This is just here to show that you still recieve x11 events, as the lib only needs mouse/key events void checkX11Events() { if(!appRunning) return; XEvent event; while(XPending(xDisp) > 0) { XNextEvent(xDisp, &event); //Handle Resize events if(event.type == ConfigureNotify) { if(g_m) { const MouseState &ms = g_m->getMouseState(); ms.width = event.xconfigure.width; ms.height = event.xconfigure.height; } } else if(event.type == ClientMessage || event.type == DestroyNotify) { // We only get DestroyNotify for child windows. However, we regeistered earlier to receive WM_DELETE_MESSAGEs std::cout << "Exiting...\n"; appRunning = false; return; } else { std::cout << "\nUnknown X Event: " << event.type << std::endl; } } } #endif #if defined OIS_APPLE_PLATFORM void checkMacEvents() { //TODO - Check for window resize events, and then adjust the members of mousestate EventRef event = NULL; EventTargetRef targetWindow = GetEventDispatcherTarget(); if( ReceiveNextEvent( 0, NULL, kEventDurationNoWait, true, &event ) == noErr ) { SendEventToEventTarget(event, targetWindow); std::cout << "Event : " << GetEventKind(event) << "\n"; ReleaseEvent(event); } } #endif