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

541 篇文章 16 订阅

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

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yacper/archive/2010/02/01/5277351.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值