157 lines
5.4 KiB
C++
157 lines
5.4 KiB
C++
/******************************************************************************
|
|
* \file SHEventManager.hpp
|
|
* \author Loh Xiao Qi
|
|
* \brief Class declaration for event manager.
|
|
*
|
|
* \copyright Copyright (c) 2022 Digipen Institute of Technology. Reproduction
|
|
* or disclosure of this file or its contents without the prior written consent
|
|
* of Digipen Institute of Technology is prohibited.
|
|
******************************************************************************/
|
|
#pragma once
|
|
|
|
#include "SHpch.h"
|
|
#include "SHEvent.h"
|
|
#include "SHEventReceiver.h"
|
|
#include "SH_API.h"
|
|
|
|
/******************************************************************************
|
|
INSTRUCTIONS FOR USE:
|
|
On broadcaster side:
|
|
1. Create a struct/class to contain the data that you would need to send
|
|
in the event.
|
|
2. Create unique event identifier in SHEventDefines.h, follow the example
|
|
provided.
|
|
3. When ready to send the event, call
|
|
SHEventManager::BroadcastEvent<ExampleClass>(exampleClass, EVENT_IDENTIFIER);
|
|
|
|
NOTE: If your custom struct to contain data requires a deep copy, please
|
|
overload the assignment operator accordingly. It is fine to send
|
|
a single object of a basic type such as int/float.
|
|
|
|
Headers required: SHEventManager.hpp
|
|
|
|
On Receiver side:
|
|
1. Create a function with the signature:
|
|
SHEventHandle FunctionName(SHEventPtr);
|
|
|
|
2. In the init function of the class, copy the below in and replace the
|
|
necessary:
|
|
|
|
std::shared_ptr<SHEventReceiverSpec<ReceiverClass>> thisReceiver{
|
|
std::make_shared<SHEventReceiverSpec<ReceiverClass>>(this, &ReceiverClass::ReceiveFunction)
|
|
};
|
|
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
|
|
SHEventManager::SubscribeTo(EVENT_IDENTIFIER, receiver);
|
|
|
|
ReceiverClass is the class that the receiver is in. E.g., SHPhysicsSystem
|
|
|
|
3. Note: The EventIdentifier should match all that is defined in
|
|
SHEventDefines.h so check there. When the receiver catches the event, it
|
|
needs to know the struct that the broadcaster is using to cast the event
|
|
ptr as such:
|
|
|
|
reinterpret_cast<std::shared_ptr<SHEventSpec<CustomClass>>>(event)
|
|
|
|
4. Inside the new ptr should be a shared pointer of const CustomClass type.
|
|
|
|
Headers required: SHEventManager.hpp, SHEventReceiver.h
|
|
|
|
If you have any questions/suggestions for improvement lmk.
|
|
******************************************************************************/
|
|
|
|
namespace SHADE
|
|
{
|
|
//using ResponseFunction = std::function<SHEventHandle(SHEventPtr)>;
|
|
using ReceiverPtr = std::shared_ptr<SHEventReceiver>;
|
|
using ResponseVec = std::vector<ReceiverPtr>;
|
|
|
|
using EventManagerListener = std::function<void(SHEvent)>;
|
|
|
|
|
|
class SH_API SHEventManager
|
|
{
|
|
private:
|
|
|
|
// Registry for broadcasters and subscribers
|
|
inline static std::unordered_map<SHEventIdentifier, ResponseVec> packageReceiverRegistry;
|
|
|
|
inline static SHEventHandle handleCounter {0};
|
|
|
|
/****************************************************************************
|
|
* \param ListenerConstPtr - Const pointer to listener that sent event.
|
|
* \param EventType - Event data
|
|
|
|
* \brief Broadcast event to all receivers that are subscribed to this
|
|
* listener.
|
|
****************************************************************************/
|
|
static void Broadcast(SHEventPtr event)
|
|
{
|
|
ResponseVec& receivers{ packageReceiverRegistry[event->type] };
|
|
for (auto& receiver : receivers)
|
|
{
|
|
receiver->Receive(event);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* \param ReceiverPtr - Pointer to receiver
|
|
* \param ListenerConstPtr - Const pointer to listener that receiver is
|
|
* subscribing to.
|
|
|
|
* \brief Registers receiver as a subscriber to listener in the registry.
|
|
****************************************************************************/
|
|
static void RegisterReceiverToType(SHEventIdentifier pkgType, ReceiverPtr receiver)
|
|
{
|
|
if (packageReceiverRegistry.find(pkgType) == packageReceiverRegistry.end())
|
|
{
|
|
packageReceiverRegistry.emplace(pkgType, std::vector{ receiver });
|
|
}
|
|
else
|
|
{
|
|
packageReceiverRegistry[pkgType].emplace_back(receiver);
|
|
}
|
|
}
|
|
|
|
public:
|
|
|
|
/****************************************************************************
|
|
* \param ListenerConstPtr - Const pointer to listener that sent event.
|
|
* \param EventType - Templated type for every type of event
|
|
|
|
* \brief Receives event from the listeners.
|
|
****************************************************************************/
|
|
static void CatchEvent(SHEventPtr event)
|
|
{
|
|
|
|
// Do something with the event
|
|
|
|
Broadcast(event);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* \param ResponseFunction - function pointer from receiver to be passed
|
|
* into event manager to be called when events are broadcasted.
|
|
* \param SHPackageType - package type that corresponding subscriber is
|
|
* subscribing to.
|
|
|
|
* \brief Links a function pointer from a subscriber to a particular
|
|
* package type
|
|
****************************************************************************/
|
|
static void SubscribeTo(SHEventIdentifier pkgType, ReceiverPtr receiver)
|
|
{
|
|
RegisterReceiverToType(pkgType, receiver);
|
|
}
|
|
|
|
template<typename T>
|
|
static void BroadcastEvent(T data, SHEventIdentifier eventType)
|
|
{
|
|
std::shared_ptr<const T> ptr = std::make_shared<T>(data);
|
|
|
|
CatchEvent(
|
|
std::make_shared<SHEventSpec<T>>(eventType, handleCounter++, ptr)
|
|
);
|
|
}
|
|
};
|
|
|
|
}
|