• 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可以将这些事件传递给用户进行处理

  • 相关阅读:
    java字符串实现正序和倒序输出
    暑假前挑战赛1—— A,B题解
    深搜
    poj 1200 Crazy Search
    poj 1840 Eqs (hash)
    Choose the best route
    一个人的旅行
    畅通工程续
    最短路基础算法
    完全背包问题
  • 原文地址:https://www.cnblogs.com/k5bg/p/11477204.html
Copyright © 2020-2023  润新知