diff --git a/SHADE_Engine/src/Common/SHCommonTypes.h b/SHADE_Engine/src/Common/SHCommonTypes.h new file mode 100644 index 00000000..97ef7928 --- /dev/null +++ b/SHADE_Engine/src/Common/SHCommonTypes.h @@ -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; +} diff --git a/SHADE_Engine/src/Events/SHEvent.h b/SHADE_Engine/src/Events/SHEvent.h new file mode 100644 index 00000000..2ca6648e --- /dev/null +++ b/SHADE_Engine/src/Events/SHEvent.h @@ -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; + }; +} diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h new file mode 100644 index 00000000..76b403bd --- /dev/null +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -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}; \ No newline at end of file diff --git a/SHADE_Engine/src/Events/SHEventManager.cpp b/SHADE_Engine/src/Events/SHEventManager.cpp new file mode 100644 index 00000000..1cede2a0 --- /dev/null +++ b/SHADE_Engine/src/Events/SHEventManager.cpp @@ -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 SHEventManager::packageReceiverRegistry; + std::unordered_map 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 + 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(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()); + //} + } +} diff --git a/SHADE_Engine/src/Events/SHEventManager.h b/SHADE_Engine/src/Events/SHEventManager.h new file mode 100644 index 00000000..f2f19fef --- /dev/null +++ b/SHADE_Engine/src/Events/SHEventManager.h @@ -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 +#include + +/****************************************************************************** + 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, 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> thisReceiver{ + std::make_shared>(this, &ReceiverClass::ReceiveFunction) + }; + ReceiverPtr receiver = std::dynamic_pointer_cast(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; + using ReceiverPtr = std::shared_ptr; + using ResponseVec = std::vector; + using StaticResponseVec = std::vector; + + using EventManagerListener = std::function; + + 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 + static T* BroadcastEvent(T data, SHEventIdentifier eventType); + + private: + + // Registry for broadcasters and subscribers + static std::unordered_map packageReceiverRegistry; + static std::unordered_map 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); + + }; + +} diff --git a/SHADE_Engine/src/Events/SHEventReceiver.h b/SHADE_Engine/src/Events/SHEventReceiver.h new file mode 100644 index 00000000..f968e579 --- /dev/null +++ b/SHADE_Engine/src/Events/SHEventReceiver.h @@ -0,0 +1,33 @@ +#pragma once + +#include "SHEvent.h" + +namespace SHADE +{ + class SHEventReceiver + { + private: + public: + virtual void Receive(SHEvent) = 0; + }; + + template + 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); + } + }; +} diff --git a/SHADE_Engine/src/SHpch.h b/SHADE_Engine/src/SHpch.h index 1db73cb9..43a832f3 100644 --- a/SHADE_Engine/src/SHpch.h +++ b/SHADE_Engine/src/SHpch.h @@ -30,5 +30,6 @@ #include #include #include +#include -#include "SHCommonTypes.h" \ No newline at end of file +#include "Common/SHCommonTypes.h"