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;
}

 

 

posted @ 2013-01-25 12:08  冷夜 - 网游编程技术  阅读(967)  评论(0编辑  收藏  举报