You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Sandbox/Plugins/EditorCommon/Events/EventManager.h

205 lines
6.5 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
#define CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H
#pragma once
#include "platform.h"
#include "EditorCommonAPI.h"
#include "IEditor.h"
#include "Serialization/IArchive.h"
struct SSystemGlobalEnvironment;
class CEventConnection
{
friend class CEventManager;
friend class CScopedEventConnection;
public:
CEventConnection()
: m_bConnected(false) {}
EDITOR_COMMON_API void Disconnect();
uint GetHandlerId() const { return m_handlerId; }
private:
CEventConnection(const uint address, const string& eventName, const uint handlerId)
: m_address(address)
, m_eventName(eventName)
, m_handlerId(handlerId)
, m_bConnected(true) {}
void Reset()
{
m_bConnected = false;
m_address = 0;
m_handlerId = 0;
m_eventName.clear();
}
void Move(CEventConnection& other)
{
m_bConnected = other.m_bConnected;
m_address = other.m_address;
m_handlerId = other.m_handlerId;
m_eventName.swap(other.m_eventName);
other.Reset();
}
bool m_bConnected;
uint m_address;
uint m_handlerId;
string m_eventName;
};
class CScopedEventConnection
: public CEventConnection
{
public:
CScopedEventConnection()
: CEventConnection() {}
CScopedEventConnection(CScopedEventConnection&& connection)
{
Move(connection);
}
CScopedEventConnection(CEventConnection&& connection)
{
Move(connection);
}
CScopedEventConnection& operator =(CEventConnection&& connection)
{
if (&connection != this)
{
Disconnect();
Move(connection);
}
return *this;
}
~CScopedEventConnection() { Disconnect(); }
private:
CScopedEventConnection(const CScopedEventConnection&); // no implementation
CScopedEventConnection& operator =(const CScopedEventConnection&); // no implementation
};
class EDITOR_COMMON_API CEventManager
{
friend class CEventConnection;
public:
CEventManager();
static CEventManager* GetInstance();
void Init(SSystemGlobalEnvironment* pEnv);
// Registers an address and returns its ID. Multiple event handlers can listen to the same address, allowing broadcasts.
uint GetAddressId(const char* name);
// Registers a new unique address
uint GetUniqueAddressId();
public:
// Sends an event to an address
//
// TMessageType must be a serializable struct
//
template <class TMessageType>
void SendEvent(const uint address, const TMessageType& message)
{
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
SendEventRaw(address, TMessageType::GetName(), json);
}
template <class TMessageType>
void SendEvent(const uint address, const TMessageType& message, const DynArray<uint>& excludedHandlers) const
{
const string json = SerializeMessageToJSON(Serialization::SStruct(message));
SendEventRaw(address, TMessageType::GetName(), json, excludedHandlers);
}
// For sending a raw JSON message.
void SendEventRaw(const uint address, const char* eventName, const char* message) const;
void SendEventRaw(const uint address, const char* eventName, const char* message, const DynArray<uint>& excludedHandlers) const;
// Tests if a call to SendEvent would actually send a message (there is someone listening to this message)
bool CanDeliverRaw(const uint address, const char* eventName) const;
template<class TMessageType>
bool CanDeliver(const uint address) const
{
const char* pEventName = TMessageType::GetName();
return CanDeliverRaw(address, pEventName);
}
// This should be the most common way to add an event callback
//
// This example will install an event handler for OnEvent(const SMessageType &message) that is sent to a specific address:
// CEventManager::GetInstance()->AddEventCallback(componentId, this, &CEventHandler::OnEvent);
//
// TMessageType must be a serializable struct
//
// Returns a CEventConnection. The callback is removed when this object is destroyed.
//
template <class TClassType, class TMessageType>
CEventConnection AddEventCallback(const uint address, TClassType* pThis, void (TClassType::* pMethod)(const TMessageType&))
{
return AddEventCallback<TMessageType>(address, std::bind(pMethod, pThis, std::placeholders::_1));
}
// Same as above, but you can pass in any function object that takes TMessageType& as an argument directly.
//
template <class TMessageType>
CEventConnection AddEventCallback(const uint address, std::function<void (const TMessageType&)> callback)
{
return AddEventCallbackRaw(address, TMessageType::GetName(), [=](const string& json)
{
TMessageType message;
DeserializeFromJSON(Serialization::SStruct(message), json);
callback(message);
});
}
// This can be used if raw parsing of JSON is preferred.
typedef std::function<void (const char*)> TEventHandlerFunc;
CEventConnection AddEventCallbackRaw(const uint componentId, const char* eventName, TEventHandlerFunc callback);
private:
void SendEventImplementation(const uint address, const string& eventName, const string& message, const DynArray<uint>& excludedHandlers) const;
string SerializeMessageToJSON(const Serialization::SStruct& ref) const;
void DeserializeFromJSON(const Serialization::SStruct& ref, const string& json);
uint m_nextAddress;
uint m_nextHandlerId;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
std::map<string, uint, stl::less_stricmp<string> > m_nameToAddressMap;
std::map<std::pair<uint, string>, std::vector<std::pair<uint, TEventHandlerFunc> > > m_messageRoutingMap;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
static CEventManager* ms_pEventManager;
};
#endif // CRYINCLUDE_EDITORCOMMON_EVENTS_EVENTMANAGER_H