SP3-18 Event/Messaging System #25
|
@ -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