Urho3D

Danny Teng bio photo By Danny Teng

运行框架

(以下均构造时订阅接受的事件)

  • 创建Context
  • 创建Example<Sample<Application<Object
  • Application - 解析参数成vector - 创建Engine
    • 使用context创建注册子系统
  • Example
  • Example->Run(Application->Run)
  • Sample::Setup()
    • 更新引擎启动参数(窗口化、标题等)
    • 获取启动目录等
  • engine初始化
    • 根据参数初始化附加库(2D等),打开log,开启多线程,添加资源目录,添加资源package,添加自动加载目录
    • 初始化图形和音频输出
    • 初始化输入网络等
  • Example::Start()
    • Sample::Start()
      • 自定义初始化
    • 自定义初始化
  • 主循环:engine->RunFrame()
    • ——-Loop——-
    • time->BeginFrame(ctime)
    • 是否已经暂停或者最小化
    • 如果是:停止声音
    • 否则如果声音暂停恢复之,engine->Update()
      • SendEvent(E_UPDATE, eventData);
      • SendEvent(E_POSTUPDATE, eventData);
      • SendEvent(E_RENDERUPDATE, eventData);
      • SendEvent(E_POSTRENDERUPDATE, eventData);
    • engine->Render()
      • Graphics->BeginFrame()
        • SetRenderTarget(i, (RenderSurface*)0);
        • SetDepthStencil((RenderSurface*)0);
        • SetViewport(IntRect(0, 0, width_, height_));
      • renderer->Render();
      • ui->Render();
      • Graphics->EndFrame();
        • impl_->swapChain_->Present(vsync_ ? 1 : 0, 0);
    • 限制帧率
    • time->EndFrame()
    • ——-Loop——-
  • Sample->Stop()
    • Engine::DumpResources()

事件系统

Engine是一个Object,Event的Sender和Receiver都是Object。

分发事件细节:

  • Engine使用SendEvent发送指定类型(eventType)的事件

    • Check主线程,当前只支持在主线程sendeEvent。

    • Enginr继承于Object中的context_调用context->BeginSendEvent(this,eventType),this代表Engine。
      • context->eventSenders_.push(sender)eventSenders是一个装sender的容器,sender这里指engine。
    • 根据发送者和事件类型,获取一个接受指定eventType的receiver_group.
      • 参考代码片1.
    • 如果找到了这样的接受者,接受者调用BeginSendEvent(),这个函数自加group的某个成员计数器。
    • 遍历group中的所有receiver,为每一个receiver调用onEvent(sender,eventType,eventData)
      • 如果sender因为事件处理而被销毁,立即终止group sendEvent,context->EndSendEvent。
      • 在已处理receiver集合processed中插入当前处理过的receiver。
    • 仅仅根据事件类型获取receiver组
    • 如果processed空则按照之前的方法处理receiver,否则,要check防止事件被接收两次。
    • context->EndSendEvent(this,eventType),this代表Engine。
      • eventSenders_.Pop();

订阅事件细节:

  • 首先创建EventHandler: URHO3D_HANDLER(SkeletalAnimation, HandleUpdate); 参数1是receiver,参数2是处理函数,由用户自己定义,是类成员。

  • 订阅,参考代码片2/3.


代码片1:

EventReceiverGroup* GetEventReceivers(Object* sender, StringHash eventType)
{
        HashMap<Object*, HashMap<StringHash, SharedPtr<EventReceiverGroup> > >::Iterator i = specificEventReceivers_.Find(sender);
        if (i != specificEventReceivers_.End())
        {
            HashMap<StringHash, SharedPtr<EventReceiverGroup> >::Iterator j = i->second_.Find(eventType);
            return j != i->second_.End() ? j->second_ : (EventReceiverGroup*)0;
        }
        else
            return 0;
}

代码片2:

void Object::SubscribeToEvent(StringHash eventType, EventHandler* handler)
{
    if (!handler)
        return;

    handler->SetSenderAndEventType(0, eventType);
    // Remove old event handler first
    EventHandler* previous;
    EventHandler* oldHandler = FindSpecificEventHandler(0, eventType, &previous);
    if (oldHandler)
    {
        eventHandlers_.Erase(oldHandler, previous);
        eventHandlers_.InsertFront(handler);
    }
    else
    {
        eventHandlers_.InsertFront(handler);
        context_->AddEventReceiver(this, eventType);
    }
}

void Object::SubscribeToEvent(Object* sender, StringHash eventType, EventHandler* handler)
{
    // If a null sender was specified, the event can not be subscribed to. Delete the handler in that case
    if (!sender || !handler)
    {
        delete handler;
        return;
    }

    handler->SetSenderAndEventType(sender, eventType);
    // Remove old event handler first
    EventHandler* previous;
    EventHandler* oldHandler = FindSpecificEventHandler(sender, eventType, &previous);
    if (oldHandler)
    {
        eventHandlers_.Erase(oldHandler, previous);
        eventHandlers_.InsertFront(handler);
    }
    else
    {
        eventHandlers_.InsertFront(handler);
        context_->AddEventReceiver(this, sender, eventType);
    }
}

代码片3:

void Context::AddEventReceiver(Object* receiver, StringHash eventType)
{
    SharedPtr<EventReceiverGroup>& group = eventReceivers_[eventType];
    if (!group)
        group = new EventReceiverGroup();
    group->Add(receiver);
}