Files
UnrealEngine/Engine/Plugins/FX/Niagara/Source/NiagaraEditor/Public/NiagaraMessageManager.h
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

211 lines
7.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "NiagaraShared.h"
#include "NiagaraCommon.h"
#include "Logging/TokenizedMessage.h"
#include "TickableEditorObject.h"
#include "UObject/ObjectKey.h"
#include "Templates/SharedPointer.h"
#include "NiagaraMessages.h"
class FNiagaraScriptToolkit;
//Extension of message token to allow opening the asset editor when clicking on the linked asset name.
class FNiagaraCompileEventToken : public IMessageToken
{
public:
/** Factory method, tokens can only be constructed as shared refs */
static TSharedRef<FNiagaraCompileEventToken> Create(
const FString& InScriptAssetPath
, const FText& InMessage
, const TOptional<const FGuid>& InNodeGUID = TOptional<const FGuid>()
, const TOptional<const FGuid>& InPinGUID = TOptional<const FGuid>()
);
/** Begin IMessageToken interface */
virtual EMessageToken::Type GetType() const override
{
return EMessageToken::AssetName;
}
/** End IMessageToken interface */
private:
/** Private constructor */
FNiagaraCompileEventToken(
const FString& InScriptAssetPath
, const FText& InMessage
, const TOptional<const FGuid>& InNodeGUID
, const TOptional<const FGuid>& InPinGUID
);
/**
* Find and open an asset in editor
* @param Token The token that was clicked
* @param InAssetPath The asset to find
*/
static void OpenScriptAssetByPathAndFocusNodeOrPinIfSet(
const TSharedRef<IMessageToken>& Token
, FString InScriptAssetPath
, const TOptional<const FGuid> InNodeGUID
, const TOptional<const FGuid> InPinGUID
);
/** The script asset path to open the editor toolkit for. */
const FString ScriptAssetPath;
/** The optional Node or Pin GUID to find and focus after opening the script asset */
const TOptional<const FGuid> NodeGUID;
const TOptional<const FGuid> PinGUID;
};
class INiagaraMessageRegistrationHandle : public TSharedFromThis<INiagaraMessageRegistrationHandle>
{
public:
DECLARE_DELEGATE_OneParam(FOnRequestRefresh, const TArray<TSharedRef<const INiagaraMessage>>& /** NewMessages*/)
INiagaraMessageRegistrationHandle(const uint32 InTopicBitfield = 0)
: TopicBitfield(InTopicBitfield)
{};
virtual ~INiagaraMessageRegistrationHandle() = default;
virtual TArray<TSharedRef<const INiagaraMessage>> FilterMessages(const TArray<TSharedRef<const INiagaraMessage>>& Messages, const uint32& DesiredTopicBitfield) const = 0;
FOnRequestRefresh& GetOnRequestRefresh() { return RefreshDelegate; };
uint32 GetTopicBitfield() const { return TopicBitfield; };
protected:
const uint32 TopicBitfield;
FOnRequestRefresh RefreshDelegate;
};
class FNiagaraMessageTopicRegistrationHandle : public INiagaraMessageRegistrationHandle
{
public:
FNiagaraMessageTopicRegistrationHandle(const uint32 InTopicBitfield)
: INiagaraMessageRegistrationHandle(InTopicBitfield)
{};
virtual TArray<TSharedRef<const INiagaraMessage>> FilterMessages(const TArray<TSharedRef<const INiagaraMessage>>& Messages, const uint32& DesiredTopicBitfield) const override;
};
class FNiagaraMessageObjectRegistrationHandle : public INiagaraMessageRegistrationHandle
{
public:
FNiagaraMessageObjectRegistrationHandle(const FObjectKey& InObjectKey)
: INiagaraMessageRegistrationHandle(INT32_MAX) //Pure object registrations listen for every topic
, ObjectKey(InObjectKey)
{};
virtual TArray<TSharedRef<const INiagaraMessage>> FilterMessages(const TArray<TSharedRef<const INiagaraMessage>>& Messages, const uint32& DesiredTopicBitfield) const override;
protected:
const FObjectKey ObjectKey;
};
class FNiagaraMessageManager : FTickableEditorObject
{
public:
NIAGARAEDITOR_API static FNiagaraMessageManager* Get();
NIAGARAEDITOR_API void AddMessage(const TSharedRef<const INiagaraMessage>& InMessage, const FGuid& InMessageAssetKey);
NIAGARAEDITOR_API void AddMessageJob(TUniquePtr<const INiagaraMessageJob>&& InMessageJob, const FGuid& InMessageJobAssetKey);
void ClearAssetMessages(const FGuid& AssetKey);
void ClearAssetMessagesForTopic(const FGuid& AssetKey, const FName& Topic);
void ClearAssetMessagesForObject(const FGuid& AssetKey, const FObjectKey& ObjectKeys);
static const TOptional<const FString> GetStringForScriptUsageInStack(const ENiagaraScriptUsage InScriptUsage);
NIAGARAEDITOR_API void RegisterMessageTopic(FName TopicName);
NIAGARAEDITOR_API void RegisterAdditionalMessageLogTopic(FName MessageLogTopicName);
uint32 GetMessageTopicBitflag(FName TopicName);
NIAGARAEDITOR_API FNiagaraMessageTopicRegistrationHandle::FOnRequestRefresh& SubscribeToAssetMessagesByTopic(
const FText& DebugNameText
, const FGuid& MessageAssetKey
, const TArray<FName>& MessageTopics
, FGuid& OutMessageManagerRegistrationKey);
NIAGARAEDITOR_API FNiagaraMessageTopicRegistrationHandle::FOnRequestRefresh& SubscribeToAssetMessagesByObject(
const FText& DebugNameText
, const FGuid& MessageAssetKey
, const FObjectKey& ObjectKey
, FGuid& OutMessageManagerRegistrationKey);
void Unsubscribe(const FText& DebugNameText, const FGuid& MessageAssetKey, FGuid& MessageManagerRegistrationKey);
const TArray<FName>& GetAdditionalMessageLogTopics() { return AdditionalMessageLogTopics; };
//~ Begin FTickableEditorObject Interface.
virtual void Tick(float DeltaSeconds) override;
virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; };
virtual TStatId GetStatId() const override { RETURN_QUICK_DECLARE_CYCLE_STAT(FNiagaraMessageManager, STATGROUP_Tickables); };
//~ End FTickableEditorObject Interface
private:
struct FAssetMessageInfo
{
FAssetMessageInfo()
: bDirty(false)
, DirtyTopicBitfield(0)
{};
TArray<TSharedRef<const INiagaraMessage>> Messages;
TMap<FGuid, TSharedPtr<INiagaraMessageRegistrationHandle>> RegistrationKey_To_RegistrationHandleMap;
bool bDirty;
uint32 DirtyTopicBitfield;
};
struct FMessageJobAndAssetKey
{
FMessageJobAndAssetKey(const FGuid& InAssetKey)
: AssetKey(InAssetKey)
{};
// FMessageJobAndAssetKey(TUniquePtr<const INiagaraMessageJob>&& InMessageJob, const FGuid& InAssetKey) //@todo(ng) impl
// : MessageJob(MoveTemp(InMessageJob))
// , AssetKey(InAssetKey)
// {};
TUniquePtr<const INiagaraMessageJob> MessageJob;
const FGuid AssetKey;
};
FNiagaraMessageManager();
void DoMessageJobsTick();
void TryFlushMessagesTick();
void FlushMessages();
static void SetRefreshTimerElapsed();
uint32 MakeBitfieldForMessageTopics(const FText& DebugNameText, const TArray<FName>& MessageTopics);
private:
static constexpr double MaxJobWorkTime = .02f; // do message jobs at 50 fps.
static constexpr double RefreshHysterisisTime = 2.0f; // do not consecutively request refresh subscribers more often than every 2 seconds.
static bool bRefreshTimeElapsed;
static bool bNeedFlushMessages;
static uint32 NextTopicBitflag; // every time a topic is registered, assign this bitflag to the topic and then binary increment this bitflag.
static FNiagaraMessageManager* Singleton;
FTimerHandle RefreshTimerHandle;
TArray<FMessageJobAndAssetKey> MessageJobs;
TMap<const FGuid, FAssetMessageInfo> AssetToMessageInfoMap;
TMap<const FName, uint32> RegisteredTopicToBitflagsMap;
TArray<FName> AdditionalMessageLogTopics;
};