致谢
感谢网友提出这个问题。大家有问题也可以在评论区提出,有问必有答。
问题描述
经常的我们需要响应一些组合键,最常见的是左Shift+某键,以及鼠标左/右键按下去+键盘某键。OSG做这些操作非常简便。
本节代码在网盘中:
注意: 务必使用浏览器打开:
链接:https://pan.baidu.com/s/13gwJLwo_LbRnN3Bl2NXXXw
提取码:xrf5
功能描述
1. 当我们按下左shift+a的时候,会出打印:按下了左SHIFT+A
2. 当我们按下鼠标左键+a的时候,会出打印:按下了鼠标左键+A
有了这两功能,其它依资类推。
注意:
1. 正常的表况下,也受通用键盘的功能限制,键盘上一般只会检测同时两个键按下。需要检测三个键按下的情况较少。检测三键如果有需求可以使用::GetAsyncKeyState全局函数进行尝试。
2. 其它正常字母的组合键,比如as同时按下,正常判断即可。
关键实现
OSG的事件处理中有个掩码getModKeyMask,可以用来判断当前某个键是否按下,如下就是本节实现的关键代码:
if (ea.getEventType() == ea.KEYDOWN)
{
if ((ea.getKey() == 'A') || (ea.getKey() == 'a'))
{
if (ea.getModKeyMask() == ea.MODKEY_LEFT_SHIFT)
{
std::cout << "按下了左SHIFT+A" << std::endl;
}
if (ea.getButtonMask() == ea.LEFT_MOUSE_BUTTON)
{
std::cout << "按下了鼠标左键+A" << std::endl;
}
_aDown = true;
}
if ((ea.getKey() == 's') || (ea.getKey() == 'S'))
{
if(_aDown)
std::cout << "as一起按下" << std::endl;
}
}
OSG中当前支持的键盘掩码如下:
enum ModKeyMask
{
MODKEY_LEFT_SHIFT = 0x0001,
MODKEY_RIGHT_SHIFT = 0x0002,
MODKEY_LEFT_CTRL = 0x0004,
MODKEY_RIGHT_CTRL = 0x0008,
MODKEY_LEFT_ALT = 0x0010,
MODKEY_RIGHT_ALT = 0x0020,
MODKEY_LEFT_META = 0x0040,
MODKEY_RIGHT_META = 0x0080,
MODKEY_LEFT_SUPER = 0x0100,
MODKEY_RIGHT_SUPER = 0x0200,
MODKEY_LEFT_HYPER = 0x0400,
MODKEY_RIGHT_HYPER = 0x0800,
MODKEY_NUM_LOCK = 0x1000,
MODKEY_CAPS_LOCK = 0x2000,
MODKEY_CTRL = (MODKEY_LEFT_CTRL|MODKEY_RIGHT_CTRL),
MODKEY_SHIFT = (MODKEY_LEFT_SHIFT|MODKEY_RIGHT_SHIFT),
MODKEY_ALT = (MODKEY_LEFT_ALT|MODKEY_RIGHT_ALT),
MODKEY_META = (MODKEY_LEFT_META|MODKEY_RIGHT_META),
MODKEY_SUPER = (MODKEY_LEFT_SUPER|MODKEY_RIGHT_SUPER),
MODKEY_HYPER = (MODKEY_LEFT_HYPER|MODKEY_RIGHT_HYPER)
};
支持的鼠标掩码如下:
enum MouseButtonMask {
LEFT_MOUSE_BUTTON = 1<<0,
MIDDLE_MOUSE_BUTTON = 1<<1,
RIGHT_MOUSE_BUTTON = 1<<2
};
以下是全部代码实现
//#include <windows.h>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/EventHandler>
osg::Node* _base = nullptr;
osg::Group* _root = new osg::Group;
class MyEventHandler : public osgGA::GUIEventHandler
{
public:
MyEventHandler()
{}
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
if (ea.getEventType() == ea.KEYDOWN)
{
if ((ea.getKey() == 'A') || (ea.getKey() == 'a'))
{
if (ea.getModKeyMask() == ea.MODKEY_LEFT_SHIFT)
{
std::cout << "按下了左SHIFT+A" << std::endl;
}
if (ea.getButtonMask() == ea.LEFT_MOUSE_BUTTON)
{
std::cout << "按下了鼠标左键+A" << std::endl;
}
_aDown = true;
}
if ((ea.getKey() == 's') || (ea.getKey() == 'S'))
{
if(_aDown)
std::cout << "as一起按下" << std::endl;
}
}
if (ea.getEventType() == ea.KEYUP)
{
if ((ea.getKey() == 'A') || (ea.getKey() == 'a'))
{
_aDown = false;
}
}
判断三键ASD
//if ((::GetAsyncKeyState(0x41) & 0x8000) && (::GetAsyncKeyState(0x53) & 0x8000) && (::GetAsyncKeyState(0x44) & 0x8000))
//{
// std::cout << "同时按下了asd" << std::endl;
//}
return false;
}
bool _aDown;
};
int main()
{
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("glider.osg"));
viewer.addEventHandler(new MyEventHandler());
return viewer.run();
}