Merge pull request #25 from SHADE-DP/SP3-18-Events
SP3-18 SP3-108 Event/Messaging System Ported over Events Manager from 200 Removed singleton design pattern Removed event package design Implemented event dynamic data Instructions to use are in SHEventManager.h
This commit is contained in:
commit
cf3f74e47d
|
@ -0,0 +1,28 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHCommonTypes.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Sep 8, 2022
|
||||||
|
\brief Contains the definitions of type alias for commonly used units for
|
||||||
|
clarity and convenience.
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
/*!
|
||||||
|
\brief
|
||||||
|
Type used to mark a value that is supposed to represent a size in bytes.
|
||||||
|
*/
|
||||||
|
/***********************************************************************************/
|
||||||
|
using Byte = size_t;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHEvent.h
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \brief Event class declaration
|
||||||
|
*
|
||||||
|
* \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 "SHEventDefines.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
struct SHEvent
|
||||||
|
{
|
||||||
|
SHEventIdentifier type;
|
||||||
|
SHEventDataPtr dataPtr;
|
||||||
|
SHEventHandle handle;
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
#include "SHpch.h"
|
||||||
|
|
||||||
|
typedef uint32_t SHEventIdentifier;
|
||||||
|
typedef uint32_t SHEventHandle;
|
||||||
|
typedef void* SHEventDataPtr;
|
||||||
|
|
||||||
|
//Add your event identifiers here:
|
||||||
|
constexpr SHEventIdentifier SH_EXAMPLE_EVENT{0};
|
|
@ -0,0 +1,107 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHEventManager.cpp
|
||||||
|
* \author Loh Xiao Qi
|
||||||
|
* \brief Function Implmentations for SHEventManager
|
||||||
|
*
|
||||||
|
* \copyright Copyright (c) 2021 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
|
||||||
|
******************************************************************************/
|
||||||
|
#include "SHpch.h"
|
||||||
|
#include "SHEventManager.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
std::unordered_map<SHEventIdentifier, ResponseVec> SHEventManager::packageReceiverRegistry;
|
||||||
|
std::unordered_map<SHEventHandle, SHEventDataPtr> SHEventManager::dataEventMap;
|
||||||
|
|
||||||
|
SHEventHandle SHEventManager::handleCounter{ 0 };
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \param ListenerConstPtr - Const pointer to listener that sent event.
|
||||||
|
* \param EventType - Templated type for every type of event
|
||||||
|
|
||||||
|
* \brief Receives event from the listeners.
|
||||||
|
****************************************************************************/
|
||||||
|
void SHEventManager::CatchEvent(SHEvent 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 SHEventIdentifier - package type that corresponding subscriber is
|
||||||
|
* subscribing to.
|
||||||
|
|
||||||
|
* \brief Links a function pointer from a subscriber to a particular
|
||||||
|
* package type
|
||||||
|
****************************************************************************/
|
||||||
|
void SHEventManager::SubscribeTo(SHEventIdentifier pkgType, ReceiverPtr receiver)
|
||||||
|
{
|
||||||
|
RegisterReceiverToType(pkgType, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T* SHEventManager::BroadcastEvent(T data, SHEventIdentifier eventType)
|
||||||
|
{
|
||||||
|
SHEventDataPtr ptr = new std::byte[sizeof(data)];
|
||||||
|
|
||||||
|
std::memcpy(ptr, &data, sizeof(data));
|
||||||
|
|
||||||
|
CatchEvent(
|
||||||
|
{
|
||||||
|
eventType,
|
||||||
|
ptr,
|
||||||
|
handleCounter++
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return reinterpret_cast<T*>(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \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.
|
||||||
|
****************************************************************************/
|
||||||
|
void SHEventManager::RegisterReceiverToType(
|
||||||
|
SHEventIdentifier pkgType, ReceiverPtr receiver)
|
||||||
|
{
|
||||||
|
if (packageReceiverRegistry.contains(pkgType))
|
||||||
|
{
|
||||||
|
packageReceiverRegistry[pkgType].emplace_back(receiver);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
packageReceiverRegistry.emplace(pkgType, std::vector{ receiver });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \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.
|
||||||
|
****************************************************************************/
|
||||||
|
void SHEventManager::Broadcast(SHEvent const& event)
|
||||||
|
{
|
||||||
|
ResponseVec& receivers{ packageReceiverRegistry[event.type] };
|
||||||
|
for (auto& receiver : receivers)
|
||||||
|
{
|
||||||
|
receiver->Receive(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
//auto& funcs{ ackageReceiverRegistry[event.GetType()] };
|
||||||
|
//for (auto func : funcs)
|
||||||
|
//{
|
||||||
|
// func(event.GetData());
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* \file SHEventManager.h
|
||||||
|
* \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 "SHEvent.h"
|
||||||
|
#include "SHEventReceiver.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
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);
|
||||||
|
|
||||||
|
Headers required: SHEventManager.h
|
||||||
|
|
||||||
|
On Receiver side:
|
||||||
|
1. Create a function with the signature:
|
||||||
|
SHEventHandle FunctionName(SHEvent);
|
||||||
|
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 void*
|
||||||
|
properly.
|
||||||
|
|
||||||
|
Headers required: SHEventManager.h, SHEventReceiver.h
|
||||||
|
|
||||||
|
If you have any questions/suggestions for improvement lmk.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
using ResponseFunction = std::function<SHEventHandle(SHEvent)>;
|
||||||
|
using ReceiverPtr = std::shared_ptr<SHEventReceiver>;
|
||||||
|
using ResponseVec = std::vector<ReceiverPtr>;
|
||||||
|
using StaticResponseVec = std::vector<ResponseFunction>;
|
||||||
|
|
||||||
|
using EventManagerListener = std::function<void(SHEvent)>;
|
||||||
|
|
||||||
|
class SHEventManager
|
||||||
|
{
|
||||||
|
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(SHEvent);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \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, ReceiverPtr);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static T* BroadcastEvent(T data, SHEventIdentifier eventType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Registry for broadcasters and subscribers
|
||||||
|
static std::unordered_map<SHEventIdentifier, ResponseVec> packageReceiverRegistry;
|
||||||
|
static std::unordered_map<SHEventHandle, SHEventDataPtr> dataEventMap;
|
||||||
|
|
||||||
|
static SHEventHandle handleCounter;
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \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(SHEvent const&);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* \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, ReceiverPtr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SHEvent.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
class SHEventReceiver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
virtual void Receive(SHEvent) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class SHEventReceiverSpec : public SHEventReceiver
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
T* object;
|
||||||
|
SHEventHandle(T::*callback)(SHEvent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
SHEventReceiverSpec(T* obj, void(T::* cb)(SHEventDataPtr))
|
||||||
|
:SHEventReceiver(), object{ obj }, callback{ cb }
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Receive(SHEvent evt) override
|
||||||
|
{
|
||||||
|
(object->*callback)(evt);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -30,5 +30,6 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
#include "SHCommonTypes.h"
|
#include "Common/SHCommonTypes.h"
|
||||||
|
|
Loading…
Reference in New Issue