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。当按下右键改变视角时,一般要先隐藏鼠标,待鼠标右键释放后再显示鼠标,如果要实现释放鼠标之后 鼠标的位置仍然在鼠标右键被按下的位置,就会比较麻烦了,我花了好一阵功夫才将其实现。不过一般不需要这么做,可以在释放鼠标右键之后将鼠标位置设置在窗 口正中央,这样用户也比较容易接受。