OIS鼠标在游戏窗口内外切换(non-exclusive input)

useful for non fullscreen mode, especially when debugging)

如果想鼠标在游戏窗口和其它应用程序间自动切换,或键盘在游戏之外使用,可在OIS中加入下面代码:


// insert the following right before calling mInputSystem = OIS::InputManager::createInputSystem( paramList );
#if defined OIS_WIN32_PLATFORM
paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND" )));
paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_FOREGROUND")));

paramList.insert(std::make_pair(std::string("w32_keyboard"), std::string("DISCL_NONEXCLUSIVE")));
ShowCursor(0);     //隐藏系统鼠标

 

#elif defined OIS_LINUX_PLATFORM
paramList.insert(std::make_pair(std::string("x11_mouse_grab"), std::string("false")));
paramList.insert(std::make_pair(std::string("x11_mouse_hide"), std::string("false")));
paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
#endif

 

基本上这样就够了!

 

 

当OGRE渲染窗口非全屏的情况下,希望能像其他应用程序一样可以将鼠标移出应用窗口,但如过按照OGRE教程中并没有介绍具体方法。先上网搜一下,如果有人实现了就不用浪费脑细胞了。
网上确实有人实现了,但是按照其方法移动鼠标时鼠标位置总是不协调,主要问题在这句话 mouse::MouseMoved 事件中把 Moved(e.state.X.rel, e.state.Y.rel) 替换成 Postion(e.state.X.abs, e.state.Y.abs)“ ,我怎么也没找到 mouse::MouseMoved“ 这个事件(说明一下,我用的是OGRE1.6)。
没办法,只有靠自己了,在捣鼓了好一阵子后终于搞定了。
无代码无真相,下边是详细的步骤+代码:
1.先在ExampleFrameListener构造函数中加上如下代码
OIS::ParamList pl;
size_t windowHnd = 0;
std::ostringstream windowHndStr;
win->getCustomAttribute("WINDOW", &windowHnd);
windowHndStr << windowHnd;
pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
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")));
mInputManager = OIS::InputManager::createInputSystem( pl );
ShowCursor(0);     //隐藏系统鼠标

 

2.在mouseMoved(const OIS::MouseEvent &arg)函数中加入检测鼠标是否在窗口范围内的代码
//mWindow为当前渲染的窗口
if(arg.state.X.abs<mWindow->getViewport(0)->getActualLeft()+2 
        ||(arg.state.Y.abs<mWindow->getViewport(0)->getActualTop()+0.5) 
        ||(arg.state.X.abs>(mWindow->getViewport(0)->getActualLeft()+mWindow->getViewport(0)->getActualWidth()-2)) 
        ||(arg.state.Y.abs>(mWindow->getViewport(0)->getActualTop()+mWindow->getViewport(0)->getActualHeight()-2)))

    { 
        CEGUI::MouseCursor::getSingleton().hide(); 
    } 
    else  //鼠标在窗口内
    { 
        //使用OIS绝对坐标
       //若使用injectMouseMove(arg.state.X.rel,arg.state.Y.rel),就会出现bug,表现为CEGUI鼠标位置与系统鼠标位置不一致
       //因此改用injectMousePosition(arg.state.X.abs,arg.state.Y.abs),使用这个函数同样也能触发CEGUI中的mouseMove事件
        CEGUI::System::getSingleton().injectMousePosition(arg.state.X.abs,arg.state.Y.abs);
        CEGUI::MouseCursor::getSingleton().show();
       
    } 
如果鼠标只能在很小的范围内移动,则需要将鼠标状态state.width和state.height设置与渲染窗口的width和height一致,不过我没出现这种情况。

这 样改完之后基本就OK了,但只是基本,还有一些小bug。当按下右键改变视角时,一般要先隐藏鼠标,待鼠标右键释放后再显示鼠标,如果要实现释放鼠标之后 鼠标的位置仍然在鼠标右键被按下的位置,就会比较麻烦了,我花了好一阵功夫才将其实现。不过一般不需要这么做,可以在释放鼠标右键之后将鼠标位置设置在窗 口正中央,这样用户也比较容易接受。

你可能感兴趣的:(游戏,String,input,keyboard,pair,debugging)