7、osg中响应键盘鼠标事件以及鼠标和键盘编码表

1、首先定义一个类,该类继承与osgGA::GUIEventHandler,在此类中存在一个handle函数,所有的事件都在此函数中进行处理,如下类的代码:

//声明类UseEventHandler,由于它是从osgGA::GUIEventHandler派生而来,所以它拥有处理事件的能力,其中这种能力体现在一个虚函数handle上。
//一切的处理都在handle当中。
class UseEventHandler:public::osgGA::GUIEventHandler
{
public:
	//handle函数,其中有两个极其重要的参数,
	//一个是const osgGA::GUIEventAdapter,注意有不少人在写时少写了个const结果就不灵了,
	//因为是虚函数,参数必须与父类中虚函数相应一致。该参数是用来识别各种事件类型的参数。
	//第二个参数也很重要:osgGA::GUIActionAdapter,它是控制显示的参数,其实最重要的是它是Viewer的祖父类,由它可以得到viewer,在操作中有体现。
	virtual bool handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa)
	{
		//将aa强制转换为viewer对象
		osgViewer::Viewer *viewer=dynamic_cast<osgViewer::Viewer*>(&aa);
		if (!viewer)//如果转换失败则直接退出
		{
			return false;
		}
		switch(ea.getEventType())//获取事件的类型,是键盘上的事件,还是鼠标上的事件以及鼠标单击,右击,双击等等。
		{
		case osgGA::GUIEventAdapter::KEYDOWN://键盘响应事件
			if (ea.getKey()==0xFF51)
			{
				//首先获得场景中的数据,然后在获得Group,然后在获得Group的子节点,最后设置显示模式
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(1);//按向左的方向键
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0);
			}
			if (ea.getKey()==0xFF53)
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(0);//按下向右的方向键
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(1);
			}
			break;
		case osgGA::GUIEventAdapter::PUSH:
			if (ea.getButton()==4)//表示按鼠标右键
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(0);
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0);
			}
			break;
		case osgGA::GUIEventAdapter::DOUBLECLICK://表示双击类型
			if (ea.getButton()==1)//表示按鼠标左键
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(1);
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(1);
			}
			break;
		default:
			break;
		}
		return false;
	}
};
2、写完了类,然后就是在场景中通过viewer.addEventHandler(new UseEventHandler());为场景添加定义好的事件类,如下代码所示:

//将UseEventHandler加入到viewer事件中,在UseEventHandler会有一个handle函数,此函数有两个参数,第一个参数是捕捉事件的,比如鼠标单击,双击,键盘事件等等
//第二个参数则是viewer的祖父GUIActionAdapter,可以通过强制转换来获得viewer对象,这样就可以在事件中控制场景中的物体模型了
viewer.addEventHandler(new UseEventHandler());

3、完整的代码如下:

#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
//声明类UseEventHandler,由于它是从osgGA::GUIEventHandler派生而来,所以它拥有处理事件的能力,其中这种能力体现在一个虚函数handle上。
//一切的处理都在handle当中。
class UseEventHandler:public::osgGA::GUIEventHandler
{
public:
	//handle函数,其中有两个极其重要的参数,
	//一个是const osgGA::GUIEventAdapter,注意有不少人在写时少写了个const结果就不灵了,
	//因为是虚函数,参数必须与父类中虚函数相应一致。该参数是用来识别各种事件类型的参数。
	//第二个参数也很重要:osgGA::GUIActionAdapter,它是控制显示的参数,其实最重要的是它是Viewer的祖父类,由它可以得到viewer,在操作中有体现。
	virtual bool handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa)
	{
		//将aa强制转换为viewer对象
		osgViewer::Viewer *viewer=dynamic_cast<osgViewer::Viewer*>(&aa);
		if (!viewer)//如果转换失败则直接退出
		{
			return false;
		}
		switch(ea.getEventType())//获取事件的类型,是键盘上的事件,还是鼠标上的事件以及鼠标单击,右击,双击等等。
		{
		case osgGA::GUIEventAdapter::KEYDOWN://键盘响应事件
			if (ea.getKey()==0xFF51)
			{
				//首先获得场景中的数据,然后在获得Group,然后在获得Group的子节点,最后设置显示模式
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(1);//按向左的方向键
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0);
			}
			if (ea.getKey()==0xFF53)
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(0);//按下向右的方向键
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(1);
			}
			break;
		case osgGA::GUIEventAdapter::PUSH:
			if (ea.getButton()==4)//表示按鼠标右键
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(0);
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0);
			}
			break;
		case osgGA::GUIEventAdapter::DOUBLECLICK://表示双击类型
			if (ea.getButton()==1)//表示按鼠标左键
			{
				viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(1);
				viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(1);
			}
			break;
		default:
			break;
		}
		return false;
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Group> root=new osg::Group();
	root->addChild(osgDB::readNodeFile("avatar.osg"));
	root->addChild(osgDB::readNodeFile("glider.osg"));
	viewer.setSceneData(root.get());
	//将UseEventHandler加入到viewer事件中,在UseEventHandler会有一个handle函数,此函数有两个参数,第一个参数是捕捉事件的,比如鼠标单击,双击,键盘事件等等
	//第二个参数则是viewer的祖父GUIActionAdapter,可以通过强制转换来获得viewer对象,这样就可以在事件中控制场景中的物体模型了
	viewer.addEventHandler(new UseEventHandler());
	viewer.realize();
	return viewer.run();
}

4、ea.getEventType()可获取的类型包括以下内容:

OSG中常用的事件类型
代码事件类型
NONE0无事件。
PUSH1鼠标某键按下
RELEASE2鼠标某键弹起。
DOUBLECLICK4鼠标某键双击。
DRAG8鼠标某键拖动。
MOVE16鼠标移动。
KEYDOWN32键盘上某键按下。
KEYUP64键盘上某键弹起。
FRAME128应该是鼠标每帧。没用过。
RESIZE256窗口大小改变时会有的事件。
SCROLL512鼠标轮滚动。
PEN_PRESSURE1024手写板的某事件?
PEN_PROXIMITY_ENTER2048手写板的某事件?
PEN_PROXIMITY_LEAVE4096手写板的某事件?
CLOSE_WINDOWS8192关闭窗口。
QUIT_APPLICATION16384退出程序。
USER32768用户定义。















5、osg中支持的键盘编码值列表如下:

OSG中支持的键盘码值
KEY_Space0x20KEY_KP_Tab0xFF89                        
KEY_BackSpace0xFF08KEY_KP_Enter0xFF8D
KEY_Tab0xFF09KEY_KP_F10xFF91
KEY_Linefeed0xFF0AKEY_KP_F20xFF92
KEY_Clear0xFF0BKEY_KP_F30xFF93
KEY_Return0xFF0DKEY_KP_F40xFF94
KEY_Pause0xFF13KEY_KP_Home0xFF95
KEY_Scroll_Lock0xFF14KEY_KP_Left0xFF96
KEY_Sys_Req0xFF15KEY_KP_Up0xFF97
KEY_Escape0xFF1BKEY_KP_Right0xFF98
KEY_Delete0xFFFFKEY_KP_Down0xFF99
KEY_Home0xFF50KEY_KP_Prior0xFF9A
KEY_Left0xFF51KEY_KP_Page_Up0xFF9A
KEY_Up0xFF52KEY_KP_Next0xFF9B
KEY_Right0xFF53KEY_KP_Page_Down0xFF9B
KEY_Down0xFF54KEY_KP_End0xFF9C
KEY_Prior0xFF55KEY_KP_Begin0xFF9D
KEY_Page_Up0xFF55KEY_KP_Insert0xFF9E
KEY_Next0xFF56KEY_KP_Delete0xFF9F
KEY_Page_Down0xFF56KEY_KP_Equal0xFFBD
KEY_End0xFF57KEY_KP_Multiply0xFFAA
KEY_Begin0xFF58KEY_KP_Add0xFFAB
KEY_Select0xFF60KEY_KP_Separator0xFFAC
KEY_Print0xFF61KEY_KP_Subtract0xFFAD
KEY_Execute0xFF62KEY_KP_Decimal0xFFAE
KEY_Insert0xFF63KEY_KP_Divide0xFFAF
KEY_Undo0xFF65  
KEY_Redo0xFF66KEY_KP_00xFFB0
KEY_Menu0xFF67KEY_KP_10xFFB1
KEY_Find0xFF68KEY_KP_20xFFB2
KEY_Cancel0xFF69KEY_KP_30xFFB3
KEY_Help0xFF6AKEY_KP_40xFFB4
KEY_Break0xFF6BKEY_KP_50xFFB5
KEY_Mode_switch0xFF7EKEY_KP_60xFFB6
KEY_Script_switch0xFF7EKEY_KP_70xFFB7
KEY_Num_Lock0xFF7FKEY_KP_80xFFB8
KEY_KP_Space0xFF80KEY_KP_90xFFB9
KEY_F10xFFBEKEY_F240xFFD5
KEY_F20xFFBFKEY_F250xFFD6
KEY_F30xFFC0KEY_F260xFFD7
KEY_F40xFFC1KEY_F270xFFD8
KEY_F50xFFC2KEY_F280xFFD9
KEY_F60xFFC3KEY_F290xFFDA
KEY_F70xFFC4KEY_F300xFFDB
KEY_F80xFFC5KEY_F310xFFDC
KEY_F90xFFC6KEY_F320xFFDD
KEY_F100xFFC7KEY_F330xFFDE
KEY_F110xFFC8KEY_F340xFFDF
KEY_F120xFFC9KEY_F350xFFE0
KEY_F130xFFCAKEY_Shift_L0xFFE1
KEY_F140xFFCBKEY_Shift_R0xFFE2
KEY_F150xFFCCKEY_Control_L0xFFE3
KEY_F160xFFCDKEY_Control_R0xFFE4
KEY_F170xFFCEKEY_Caps_Lock0xFFE5
KEY_F180xFFCFKEY_Shift_Lock0xFFE6
KEY_F190xFFD0  
KEY_F200xFFD1KEY_Meta_L0xFFE7
KEY_F210xFFD2KEY_Meta_R0xFFE8
KEY_F220xFFD3KEY_Alt_L0xFFE9
KEY_F230xFFD4KEY_Alt_R0xFFEA
KEY_Super_L0xFFEBKEY_Hyper_L0xFFED
KEY_Super_R0xFFECKEY_Hyper_R0xFFEE
 


要使用OpenSceneGraph (OSG)来实现捕捉键盘鼠标事件,您需要创建一个继承自`osgGA::GUIEventHandler`的自定义事件处理类,并在其重写相应的方法来处理键盘鼠标事件。下面是一个示例代码,展示了如何使用OSG来捕捉键盘鼠标事件: ```cpp #include <osgViewer/Viewer> #include <osgGA/GUIEventHandler> class EventCaptureHandler : public osgGA::GUIEventHandler { public: virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN) { // 按下键盘时触发该事件 osgGA::GUIEventAdapter::KeySymbol key = ea.getKey(); // 执行相应操作 return true; } else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE) { // 鼠标移动时触发该事件 int x = ea.getX(); int y = ea.getY(); // 执行相应操作 return true; } return false; } }; int main() { // 创建一个OSG查看器 osgViewer::Viewer viewer; // 创建一个自定义事件处理器 EventCaptureHandler* eventHandler = new EventCaptureHandler; // 将事件处理器添加到查看器 viewer.addEventHandler(eventHandler); // 运行查看器 return viewer.run(); } ``` 在上述示例,我们创建了一个名为`EventCaptureHandler`的自定义事件处理类,继承自`osgGA::GUIEventHandler`。我们重写了`handle`方法,并根据事件类型来处理键盘鼠标事件。在`handle`方法,我们判断事件类型,如果是键盘按键事件,则执行相应的操作;如果是鼠标移动事件,则执行相应的操作。 在`main`函数,我们创建了一个OSG查看器`viewer`,然后创建了一个自定义事件处理器`eventHandler`。接下来,我们将事件处理器添加到查看器,并通过调用`viewer.run()`来运行查看器。 通过这种方式,您可以使用OSG来捕捉键盘鼠标事件,并根据需要执行相应的操作。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值