CEGUI、DirectX和OIS结合
OIS即面向对象的输入系统(Object-Oriented Input System(OIS)
OIS是一个面向对象的输入系统,理论上它可以支持任何输入设备,其中最主要的三类是键盘、鼠标和游戏控制器。OIS是一个开放源码的项目,你可以按你的要求定制它,以满足你的需求。
下载地址:http://sourceforge.net/projects/wgois/
主要过程:
1.编译好OIS
2.创建好windows窗口,初始化Directx和CEGUI
3.初始化输入管理系统和输入设备
HWND m_hWnd; OIS::InputManager *m_pInputManager; OIS::Mouse *m_pMouse; OIS::Keyboard *m_pKeyboard; OIS::ParamList pl; std::ostringstream windowHndStr; windowHndStr <<(size_t)hwnd; // 窗口句柄 pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); // 传入窗口句柄 pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_FOREGROUND")); //前台模式,也就是说使用它的程序必须处于激活状态, //如果它失去焦点就会自动失去设备,在它重新获得焦点的时候必须重新获得设备使用权 pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_NONEXCLUSIVE")); // 允许其他程序使用,并且不会干扰其他应用程序的使用 // 创建输入设备 m_pInputManager = OIS::InputManager::createInputSystem( pl ); //m_pInputManager=OIS::InputManager::createInputSystem((size_t)m_hWnd); m_pMouse = static_cast<OIS::Mouse*>(m_pInputManager->createInputObject( OIS::OISMouse, true));//第三个参数为真是为缓冲处理 m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputManager->createInputObject( OIS::OISKeyboard, true ));
首先我们先讲一个问题,就是 缓冲和非缓冲。
缓冲输入就是说你每次的按键值都要先存入缓冲区,等程序有时间了就会去做相应的处理,意思说只要你按了某个键,电脑早晚都会给你做相应的事情,哪怕等到程序死机(如果这样,说明你很不幸哦!)。非缓冲就是程序现在有时间处理你的时候来问你,“有什么要做的没?“,如果这是你的鼠标键盘有任何时间的话,程序就做相应的处理,没有的话,不做任何处理,哪怕在这之前你按了鼠标或者键盘的某些键,程序也会忽略。它们的区别就是缓冲可以处理一切事件,但是需要缓冲,则比较慢,非缓冲可能会忽略某些信息,但是它不需要缓冲,处理速度要快一些。
4.创建并设置监听类
class GuiFrameListener:public OIS::MouseListener,public OIS::KeyListener { private: bool mShoutdownRequested; //结束标志 HWND m_hWnd; public: GuiFrameListener(HWND hWnd) { m_hWnd=hWnd; mShoutdownRequested=true; } bool quit(const CEGUI::EventArgs &evt) { mShoutdownRequested=true; return true; } bool mouseMoved(const OIS::MouseEvent &evt); bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) ; bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id ); bool keyPressed(const OIS::KeyEvent &evt ); bool keyReleased(const OIS::KeyEvent &evt ); void doNumKeyboard(OIS::KeyEvent &evt); };
m_listener=new GuiFrameListener(m_hWnd); m_pMouse->setEventCallback(m_listener); m_pKeyboard->setEventCallback(m_listener);
5.在循环函数中加入输入设备的接收数据接口
m_pMouse->capture();
m_pKeyboard->capture();
6.OIS与CEGUI结合,主要是在监听类里的鼠标键盘响应函数中加入响应的injectXXXXX函数
例如鼠标按下的:
bool GuiFrameListener::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) { CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(id)); return true; }
7.因为传入鼠标ID的时候 OIS::MouseButtonID和CEGUI::MouseButton是两个不同的枚举,所以要作下转换
CEGUI::MouseButton convertOgreButtonToCegui(int buttonID) { switch (buttonID) { case OIS::MB_Left: return CEGUI::LeftButton; case OIS::MB_Right: return CEGUI::RightButton; case OIS::MB_Middle: return CEGUI::MiddleButton; default: return CEGUI::LeftButton; } }
下面是完整的代码:
头文件
#ifndef _OISAPP_H_ #define _OISAPP_H_ #include <windows.h> #include "OIS.h" #include"CEGUI.h" using namespace std; #ifdef _DEBUG #pragma comment( lib, "OIS_d.lib" ) #else #pragma comment( lib, "OIS.lib" ) #endif CEGUI::MouseButton convertOgreButtonToCegui(int buttonID); class GuiFrameListener:public OIS::MouseListener,public OIS::KeyListener { private: bool mShoutdownRequested; //结束标志 HWND m_hWnd; public: GuiFrameListener(HWND hWnd) { m_hWnd=hWnd; mShoutdownRequested=true; } bool quit(const CEGUI::EventArgs &evt) { mShoutdownRequested=true; return true; } bool mouseMoved(const OIS::MouseEvent &evt); bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) ; bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id ); bool keyPressed(const OIS::KeyEvent &evt ); bool keyReleased(const OIS::KeyEvent &evt ); void doNumKeyboard(OIS::KeyEvent &evt); }; class OISApp { public: OISApp(); ~OISApp(); bool Init(HWND hwnd); void capture(); public: HWND m_hWnd; OIS::InputManager *m_pInputManager; OIS::Mouse *m_pMouse; OIS::Keyboard *m_pKeyboard; GuiFrameListener *m_listener; }; #endif
cpp
#include "oisApp.h" #include "publicFunc.h" CEGUI::MouseButton convertOgreButtonToCegui(int buttonID) { switch (buttonID) { case OIS::MB_Left: return CEGUI::LeftButton; case OIS::MB_Right: return CEGUI::RightButton; case OIS::MB_Middle: return CEGUI::MiddleButton; default: return CEGUI::LeftButton; } } //////////// OISApp::OISApp() { m_pInputManager=NULL; m_pMouse=NULL; m_pKeyboard=NULL; m_listener=NULL; } OISApp::~OISApp() { m_pInputManager->destroyInputObject(m_pMouse); m_pInputManager->destroyInputObject(m_pKeyboard); OIS::InputManager::destroyInputSystem(m_pInputManager); safeDele(m_listener); } bool OISApp::Init(HWND hwnd) { if(m_hWnd<=0) { printf("ERROR: m_hWnd <=0\n"); return false; } m_hWnd=hwnd; OIS::ParamList pl; std::ostringstream windowHndStr; windowHndStr <<(size_t)hwnd; // 窗口句柄 pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); // 传入窗口句柄 pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_FOREGROUND")); //前台模式,也就是说使用它的程序必须处于激活状态, //如果它失去焦点就会自动失去设备,在它重新获得焦点的时候必须重新获得设备使用权 pl.insert(std::make_pair(std::string("w32_mouse"), "DISCL_NONEXCLUSIVE")); // 允许其他程序使用,并且不会干扰其他应用程序的使用 // 创建输入设备 m_pInputManager = OIS::InputManager::createInputSystem( pl ); //m_pInputManager=OIS::InputManager::createInputSystem((size_t)m_hWnd); m_pMouse = static_cast<OIS::Mouse*>(m_pInputManager->createInputObject( OIS::OISMouse, true));//第三个参数为真是为缓冲处理 m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputManager->createInputObject( OIS::OISKeyboard, true )); m_listener=new GuiFrameListener(m_hWnd); m_pMouse->setEventCallback(m_listener); m_pKeyboard->setEventCallback(m_listener); // 设置鼠标移动范围,OIS默认范围为50*50 RECT clientRect; GetClientRect(m_hWnd,&clientRect); //GetWindowRect(m_hWnd,&clientRect); m_pMouse->getMouseState().width =clientRect.right; m_pMouse->getMouseState().height = clientRect.bottom; ShowCursor(0); //隐藏系统鼠标指针 return true; } void OISApp::capture() { if (m_pMouse&&m_pKeyboard) { m_pMouse->capture(); m_pKeyboard->capture(); } } /////////////////////////// bool GuiFrameListener::mouseMoved(const OIS::MouseEvent &evt) { //CEGUI::System::getSingleton().injectMouseMove(evt.state.X.rel,evt.state.Y.rel); RECT clientRect; GetClientRect(m_hWnd,&clientRect); //GetWindowRect(m_hWnd,&clientRect); int width =clientRect.right; int height = clientRect.bottom; int curx=evt.state.X.abs; int cury=evt.state.Y.abs; if (curx>0&&curx<width&&cury>0&&cury<height) { //ShowCursor(0); //隐藏系统鼠标指针 CEGUI::MouseCursor::getSingleton().show(); CEGUI::System::getSingleton().injectMousePosition(curx,cury); }else { CEGUI::MouseCursor::getSingleton().hide(); } return true; } bool GuiFrameListener::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id) { CEGUI::System::getSingleton().injectMouseButtonDown(convertOgreButtonToCegui(id)); return true; } bool GuiFrameListener::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id ) { CEGUI::System::getSingleton().injectMouseButtonUp(convertOgreButtonToCegui(id)); return true; } void GuiFrameListener::doNumKeyboard(OIS::KeyEvent &evt) { switch (evt.key) { case OIS::KeyCode::KC_NUMPAD0: { evt.text=48; } break; case OIS::KeyCode::KC_NUMPAD1: { evt.text=49; } break; case OIS::KeyCode::KC_NUMPAD2: { evt.text=50; } break; case OIS::KeyCode::KC_NUMPAD3: { evt.text=51; } break; case OIS::KeyCode::KC_NUMPAD4: { evt.text=52; } break; case OIS::KeyCode::KC_NUMPAD5: { evt.text=53; } break; case OIS::KeyCode::KC_NUMPAD6: { evt.text=54; } break; case OIS::KeyCode::KC_NUMPAD7: { evt.text=55; } break; case OIS::KeyCode::KC_NUMPAD8: { evt.text=56; } break; case OIS::KeyCode::KC_NUMPAD9: { evt.text=57; } break; } } bool GuiFrameListener::keyPressed(const OIS::KeyEvent &evt ) { //if(evt.key==OIS::KC_ESCAPE) //{ // mShoutdownRequested=true; // return true; //} OIS::KeyEvent cEvent=evt; doNumKeyboard(cEvent); CEGUI::System::getSingleton().injectKeyDown(cEvent.key); CEGUI::System::getSingleton().injectChar(cEvent.text); switch (evt.key) { case OIS::KC_ESCAPE: mShoutdownRequested = true; break; case OIS::KC_UP: case OIS::KC_W: break; case OIS::KC_DOWN: case OIS::KC_S: break; case OIS::KC_LEFT: case OIS::KC_A: break; case OIS::KC_RIGHT: case OIS::KC_D: break; case OIS::KC_PGDOWN: case OIS::KC_E: break; case OIS::KC_PGUP: case OIS::KC_Q: break; } return true; } bool GuiFrameListener::keyReleased(const OIS::KeyEvent &evt ) { CEGUI::System::getSingleton().injectKeyUp(evt.key); switch (evt.key) { case OIS::KC_UP: case OIS::KC_W: break; case OIS::KC_DOWN: case OIS::KC_S: break; case OIS::KC_LEFT: case OIS::KC_A: break; case OIS::KC_RIGHT: case OIS::KC_D: break; case OIS::KC_PGDOWN: case OIS::KC_E: break; case OIS::KC_PGUP: case OIS::KC_Q: break; } return true; }