如何在 C++ 中基于模板的事件系统中预绑定参数

问题描述 投票:0回答:1

我的游戏引擎中有一个事件系统,由两个主要组件组成:Event 和 EventCallback。

事件.h:

#ifndef _EVENT_H_
#define _EVENT_H_
#include "EventCallback.h"
#include <vector>

template<typename... Args>
class Event
{
public:
    Event() = default;
    ~Event()
    {
        for (IEventCallback<Args...>* action : m_actions)
            delete action;

        m_actions.clear();
    }

    void AddListener(IEventCallback<Args...>* action)
    {
        m_actions.push_back(action);
    }

    void RemoveListener(IEventCallback<Args...>* action)
    {
        auto position = std::find(m_actions.begin(), m_actions.end(), action);

        if (position == m_actions.end())
            return;

        m_actions.erase(position);

        if(action != nullptr)
            delete action;
    }

    void Trigger(Args... args)
    {
        for (IEventCallback<Args...>* action : m_actions)
        {
            action->Trigger(args...);
        }
    }

private:
    std::vector<IEventCallback<Args...>*> m_actions;
};

#endif

EventCallback.h:

#ifndef _EVENTCALLBACK_H_
#define _EVENTCALLBACK_H_

template<typename... Args>
class IEventCallback
{
public:
    virtual bool operator == (IEventCallback* other) = 0;
    virtual void Trigger(Args... args) = 0;
};
 
template<typename T, typename... Args>
class EventCallback : public IEventCallback<Args...>
{    
public:    
    EventCallback(T* instance, void (T::* function)(Args... args))
    {
        m_instance = instance;
        m_function = function;
    }
    virtual void Trigger(Args... args) override
    { 
        if(m_instance != nullptr)
            (m_instance->*m_function)(args...);
    } 
    
    virtual bool operator == (IEventCallback<Args...>* other) override
    {
        EventCallback<T, Args...>* otherEventCallback = dynamic_cast<EventCallback<T, Args...>*>(other);
        if (otherEventCallback == nullptr)
            return false;

        return  (this->m_function == otherEventCallback->m_function) &&
                (this->m_instance == otherEventCallback->m_instance);
    }

private:
    void (T::*m_function)(Args...);
    T* m_instance;
};

#endif

目前,我可以创建一个事件并添加侦听器,如下所示:

CameraController* instance = new CameraController();
Event<InputCallbackData> Ongoing;
Ongoing.AddListener(new EventCallback<CameraController, InputCallbackData>(this, &CameraController::MoveRight));

void CameraController::MoveRight(InputCallbackData data)
{
    Vector3D cameraPos = m_cameraComponent->GetWorldPosition();
    Vector3D cameraRight = m_cameraComponent->GetWorldRotation().GetRightDirection();

    m_cameraComponent->SetWorldPosition(cameraPos + cameraRight * movementSpeed);
}

InputCallbackData inputCallbackData = InputCallbackData();
Ongoing.Trigger(inputCallbackData);

现在,我想将参数预先绑定到EventCallback。这就是我的目标:

CameraController* instance = new CameraController();
Event<InputCallbackData> Ongoing;
Ongoing.AddListener(new EventCallback<CameraController, InputCallbackData>(this, &CameraController::MoveRight, 10));

void CameraController::MoveRight(InputCallbackData data, float speed)
{
    Vector3D cameraPos = m_cameraComponent->GetWorldPosition();
    Vector3D cameraRight = m_cameraComponent->GetWorldRotation().GetRightDirection();

    m_cameraComponent->SetWorldPosition(cameraPos + cameraRight * speed);
}

InputCallbackData inputCallbackData = InputCallbackData();
Ongoing.Trigger(inputCallbackData);

我应该如何修改我的EventCallback类以支持预绑定参数?

我不知道如何实现我的目标:

CameraController* instance = new CameraController();
Event<InputCallbackData> Ongoing;
Ongoing.AddListener(new EventCallback<CameraController, InputCallbackData>(this, &CameraController::MoveRight, 10));

void CameraController::MoveRight(InputCallbackData data, float speed)
{
    Vector3D cameraPos = m_cameraComponent->GetWorldPosition();
    Vector3D cameraRight = m_cameraComponent->GetWorldRotation().GetRightDirection();

    m_cameraComponent->SetWorldPosition(cameraPos + cameraRight * speed);
}

InputCallbackData inputCallbackData = InputCallbackData();
Ongoing.Trigger(inputCallbackData);
c++ templates events callback variadic-templates
1个回答
0
投票

也许是这样的(未经测试):

template<typename T, typename... Args>
class EventCallback : public IEventCallback<Args...>
{    
public:
    template <typename... ExtraArgs
    EventCallback(T* instance, void (T::* function)(Args..., ExtraArgs...),
                  const ExtraArgs&... extra_args) {
      m_callback = [=](Args... args) {
          (intance->*function)(args..., extra_args...);
       };
    }

    virtual void Trigger(Args... args) override
    { 
        if(m_callback)
            m_callback(args...);
    } 

private:
    std::function<void(Args...)> m_callback;
};
© www.soinside.com 2019 - 2024. All rights reserved.