OGRE 分析之消息机制
一、 消息的产生
InputReader:从各种输入设备读取数据,可以看作是消息产生地。具体的InputReader由PlatformManager 创建,它是与平台相关的。
OGRE::InputReader
________________|_______________
| | |
Ogre::GLXInput Ogre::SDLInput Ogre::Win32Input8
InputEvent:消息的载体。界面元素层输入消息的基类。
输入消息在它的产生地正常处理之前先被发送给Listeners。这样就可以用Listeners 和GuiElement subclasses 拦截消息,改变消息处理的默认行为。
InputEvent 包含判断组合键的按下情况。
Ogre::InputEvent
________|_______
| |
Ogre::KeyEvent Ogre::MouseEvent
二、 消息的处理
EventListener:真正处理消息的地方。
Ogre::EventListener
_________________|___________________
| | |
Ogre::KeyListener Ogre::MouseListener Ogre::MouseMotionListener
EventTarget:处理消息的中介。所有InputEvent消息处理者的基类。EventTarget处理
消息是由各种Listener 完成的。KeyTarget 调用KeyListener , MouseTarget 调用
MouseListener,MouseMotionTarget调用MouseMotionListener。
Ogre::EventTarget
_______________|____________________
| |
Ogre::KeyTarget Ogre::PositionTarget
| __________|________________
Ogre::EventProcessor | |
Ogre::MouseMotionTarget Ogre::MouseTarget
___________|________ __________|________
| | | |
Ogre::Cursor Ogre::EventProcessor Ogre::Cursor Ogre::EventProcessor
三、 消息的传递
EventDispatcher:代理分发消息。负责把InputEvent消息分派给EventTarget。在分发消息时,EventDispatcher根据InputEvent的类型(MouseEvent或者KeyEvent)分别发送给需要的PositionTarget。
EventTarget 由TargetManager 管理, 每一个TargetManager 都对应一个EventDispatcher。对应OverlayManager的EventDispatcher管理2D GUI组件,对应
SceneManager的EventDispatcher管理3D物体。
EventProcessor:获取消息、维护消息队列、分发消息。
Ogre::EventTarget Ogre::EventTarget
| |
Ogre::PositionTarget Ogre::PositionTarget Ogre::EventTarget
| | |
Ogre::FrameListener | | |
| Ogre::MouseTarget Ogre::MouseMotionTarget Ogre::KeyTarget
| | | Ogre::Singleton<EventProcessor> |
|_____________|_____________|________________|__________________|
|
Ogre::EventProcessor
EventProcessor 在初始化的时候,创建一个EventQueue 和一个InputReader,
InputReader 初始化为侦听鼠标和键盘消息,接收到的消息存放于上述的EventQueue
中。
EventProcessor 是一个FrameListener,调用EventProcessor::startProcessingEvents(true)把EventProcessor 添加到Root 的FrameListener 链表中(实际为std::set),并激活EventQueue。
EventProcessor又是EvenetTarget,所以维护有Listener列表,从基类继承而来的。除此之外,EventProcessor还维护了一个EvenetTarget列表和EventDispatcher列表。而所有的这些都是用来处理或传递消息的。
四、 消息处理整个过程
程序进入Root::startRendering()后,进入消息循环。在渲染帧开始之前,Root 调用所有注册的FrameListener 的FrameListener::framStarted(…)函数,使之做好渲染前的准备。前面分析了EventProcessor 属于FrameListener 并注册到了Root,所以Root会调用EventProcessor:: framStarted(…) 函数。此时, EventProcessor 调用InputReader 捕获鼠标、键盘消息,然后进入消息分发阶段。
EventProcessor将把队列中所有的消息通过EventDispatchers分发给EventTarget处理,EventTarget本身不能处理消息,需要借助EventListeners来处理。所以消息由依附在EventTarget上的EventListeners处理。
EventDispatchers返回后,若存在没有处理的消息则先由EventProcessor维护的EventTargets处理,仍未处理的则由EventProcessor本身处理。由于EventProcessor也是EventTargets,所以它需要发给添加到EventProcessor中的EventListeners来处理。
处理完鼠标键盘消息之后,Root 开始调用RenderSystem 来渲染RenderTarget。然后调用所有FrameListener 的FrameListener::frameEnded(…)。
总体过程可以看成如下顺序如下:
InputReader
--> EventProcessor --> EventDispatcher --> EventTarget
--> EventListener