OSG 事件处理机制 类图


本文为osg源码学习笔记,有理解不当之处,请随时指正. 

PS: 本文参考osg 版本: 3.4.0


1. 事件处理框架

OSG的事件处理可分为两个大的模块. 

1)  事件适配模块(类图右侧) : 为各窗口平台中间抽象层(GA: GUI Abstraction)或适配层, 将各平台的用户输入事件适配为OSG内部定义的事件(EventAdapter).   

2) 事件处理模块(类图左侧):  为用户提供输入事件的处理机制. 用户注册事件handler,对输入事件(EventAdapter)进行处理. 

osg 事件处理类图




2. 源码分析

按照从 用户事件输入->用户事件处理的过程,用源码佐证上述分析. 整个分析过程,以鼠标事件为例.


1) 平台相关事件 适配为  OSG内部定义事件

a. 接收用户输入

源码现场: GraphicsWindowWin32::handleNativeWindowingEvent()

以鼠标事件为例,将windows鼠标事件的相关信息,交由eventqueue处理. 

        case WM_LBUTTONDOWN :
        case WM_MBUTTONDOWN :
        case WM_RBUTTONDOWN :
        /////////////////////

            {
                ::SetCapture(hwnd);

                int button;

                if (uMsg==WM_LBUTTONDOWN)      button = 1;
                else if (uMsg==WM_MBUTTONDOWN) button = 2;
                else button = 3;

                _capturedMouseButtons.insert(button);

                float mx = GET_X_LPARAM(lParam);
                float my = GET_Y_LPARAM(lParam);
                transformMouseXY(mx, my);
                getEventQueue()->mouseButtonPress(mx, my, button, eventTime);
            }
            break;


b. 适配事件, 并添加至事件队列

源码现场: osgGA::GUIEventAdapter* EventQueue

GUIEventAdapter* event = new GUIEventAdapter(*_accumulateEventState);
    event->setEventType(GUIEventAdapter::PUSH);
    event->setTime(time);

    switch(button)
    {
        case(1):
            event->setButton(GUIEventAdapter::LEFT_MOUSE_BUTTON);
            break;
        case(2):
            event->setButton(GUIEventAdapter::MIDDLE_MOUSE_BUTTON);
            break;
        case(3):
            event->setButton(GUIEventAdapter::RIGHT_MOUSE_BUTTON);
            break;
    }

    addEvent(event);
事件处理时序图
2) 事件处理

至此,用户 输入外部事件已经适配为osg内部eventAdapter,并添加至事件队列中. 

Viewer负责在事件更新循环中,将事件队列中的事件,分发给各event handler进行处理. 

源码现场: Viewer::eventTraversal()

   for(osgGA::EventQueue::Events::iterator itr = events.begin();
        itr != events.end();
        ++itr)
    {
        osgGA::Event* event = itr->get();
        for(EventHandlers::iterator hitr = _eventHandlers.begin();
            hitr != _eventHandlers.end();
            ++hitr)
        {
          (*hitr)->handle( event, 0, _eventVisitor.get());
        }

    }



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值