OSG:幼儿园篇 第五章 界面交互类

一.简介

OSG 中主要使用 viewer 场景类来控制场景,通过添加事件处理器来响应事件

OSG 中主要使用 osgGA 库来处理用户的交互动作。GA 的全程是 GUI Abstraction(图形接口抽象层)

添加到视景器(viewer)的事件处理器队列(EventHandler)

 class A : public osgGA::GUIEventHandler {

  //自定义子类实现过程

};  

viewer.addEventHandler( new A(参数) );

二.视图类

osgViewer::Viewer viewer;

viewer.setSceneData(root.get());
viewer.addEventHandler(new 处理器子类())
viewer.realize();
viewer.run();

三.事件类

osgGA::GUIEventAdapter 类包含了常见窗口系统中的鼠标 键盘等操作

 

1.类定义

class OSGGA_EXPORT GUIEventAdapter : public Event
{

  GUIEventAdapter();
  GUIEVentAdapter(const GUIEventAdapter& rhs, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
  META_Object(osgGA, GUIEventAdapter);
  
  virtual GUIEventAdapter* asGUIEventAdapter();
  virtual const GUIEventAdapter* asGUIEventAdapter() const;

  static osg::ref_ptr<GUIEventAdapter>& getAccumulatedEventState();

  void setEventType(EventType Type)

  virtual EventType getEventType() const

  double time() const

  void setGraphicsContext(osg::GraphicsContext* context)
  osg::GraphicsContext* getGraphicsContext()
  const osg::GraphicsContext* getGraphicsContext() const

  void setWindowRectangle(int x, int y, int width, int height, bool updateMouseRange = true);

  void setWindowX(int v)
  void getWindowX() const

  void setWindowY(int v)
  int getWindowY() const

  void setWindowWidth(int v)
  int getWindowWidth() const

  void setWindowHeight(int v)
  int getWindowHeight() const

  inline void setKey(int key)
  virtual int getKey() const

  void setUnmodifiedKey(int key)
  int getunmodifiedKey() const

  void setButton(int button)
  int getButton() const

  void setInputRange(float Xmin, float Ymin, float Xmax, float Ymax);
  
  void setXmin(float v)
  float getXmin() const

  void setXmax(float v)
  float getXmax() const

  void setYmin(float v)
  float getYmin() const

  void setYmax(float v)
  float getYmax() const

  void setX(float x)
  float getX() const

  void setY(float y)
  float getY() const

  inline float getXnormalized() const
  inline float getYnormalized() const

  ...  

};

2.常见的事件类型

NONE       0      无事件

PUSH       1      鼠标某键按下

RELEASE     2      鼠标某键弹起

DOUBLECLICK  4      鼠标某键双击

DRAG      8      鼠标某键拖动

MOVE      16      鼠标移动

KEYDOWN    32     键盘上某键按下

KEYUP      64     键盘上某键弹起

RESIZE      256    窗口大小改变时会有的事件

SCROLL       512    鼠标轮滚动

具体键值在 GUIEventAdapter 头文件之中,都是2的N次方,因为二进制编码只有一位是1,便于判断事件

3.使用步骤

1.编写自定义子类 UseEventHandler 继承 osgGA::GUIEventHandler 界面事件处理器父类

2.重写 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) 处理器函数

3.用父类 osgGA::GUIActionAdapter&  aa 动作适配器类静态转化为 osgViewer::Viewer 视图类来获取场景数据

4.用动作适配器类 osgGA::GUIEventAdapter& aa 来判断事件类型

5.最后在视图类添加自己编写的处理器子类 viewer.addEventHandler(new UseEventHandler);

/** 响应鼠标键盘 */

#include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osg/Node> class UseEventHandler : public osgGA::GUIEventHandler { virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { //由父类转化到子类拿到场景数据,如果没有场景数据就返回 osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer* >(&aa); if(!viewer) return false; //根据适配器接口来判断事件类型 switch(ea.getEventType()) { //键盘事件 case osgGA::GUIEventAdapter::KEYDOWN: { //键盘事件号 if(ea.getKey() == 0xFF51) { viewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0); viewer->getSceneData()->asGroup()->getChild(0)->setNodeMask(1); } 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; } }; void main() { osgViewer::Viewer viewer; osg::ref_ptr<osg::Group> root = new osg::Group(); root->addChild(osgDB::readNodeFile("cow.osg")); root->addChild(osgDB::readNodeFile("glider.osg")); viewer.setSceneData(root.get()); //场景添加自己写的处理器子类,该子类继承父类 osgGA::GUIEventHandler 重写虚函数 handle() viewer.addEventHandler(new UseEventHandler); viewer.realize(); viewer.run(); }

四.动作类

通过 GUIActionAdapter 类可以实现用户向系统传递请求(常见的用户请求包括窗口的刷新以及鼠标坐标的设置)

//由于该类函数较少,一般用于转化为子类

//由父类转化到子类拿到场景数据,如果没有场景数据就返回
  osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer* >(&aa);
  if(!viewer) return false;

五.事件队列和处理类

EventQueue 类可以记录所有输入设备和系统事件的一个数据队列

GUIEventHandler可以将这些事件传递给用户进行处理

原文地址:https://www.cnblogs.com/k5bg/p/11477204.html