// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "Logging/TokenizedMessage.h" #include "Misc/Guid.h" #include "UObject/ObjectKey.h" #include "NiagaraCommon.h" #include "NiagaraShared.h" #include "NiagaraGraph.h" #include "NiagaraMessageDataBase.h" #include "NiagaraMessages.generated.h" struct FNiagaraMessageTopics { static NIAGARAEDITOR_API const FName CompilerTopicName; static NIAGARAEDITOR_API const FName ObjectTopicName; }; UENUM() enum class ENiagaraMessageSeverity : uint8 { CriticalError = 0, Error = 1, PerformanceWarning = 2, Warning = 3, Info = 4 }; //Struct for passing around script asset info from compile event message job to message types struct FNiagaraScriptNameAndAssetPath { public: FNiagaraScriptNameAndAssetPath(const FString& InScriptNameString, const FString& InScriptAssetPathString) : ScriptNameString(InScriptNameString) , ScriptAssetPathString(InScriptAssetPathString) {}; const FString ScriptNameString; const FString ScriptAssetPathString; }; // Struct for passing around named simple delegates. struct FLinkNameAndDelegate { public: FLinkNameAndDelegate() = default; FLinkNameAndDelegate(const FText& InLinkNameText, const FSimpleDelegate& InLinkDelegate) : LinkNameText(InLinkNameText) , LinkDelegate(InLinkDelegate) {}; FText LinkNameText; FSimpleDelegate LinkDelegate; }; /** * Interface for view-agnostic message that holds limited lifetime information on a message (e.g. a weak pointer to an asset.) */ class INiagaraMessage { public: INiagaraMessage(const TArray& InAssociatedObjectKeys = TArray()) : AssociatedObjectKeys(InAssociatedObjectKeys) , MessageTopicBitflag(0) {}; virtual ~INiagaraMessage() {}; virtual FText GenerateMessageText() const = 0; /** Can optionally be overriden to give the message a title/short description. */ virtual FText GenerateMessageTitle() const; virtual const FSimpleDelegate& GetDismissHandler() const { return DismissHandler; } virtual TSharedRef GenerateTokenizedMessage() const = 0; virtual void GenerateLinks(TArray& OutLinkDisplayNames, TArray& OutLinkNavigationActions) const = 0; virtual const FName GetMessageTopic() const = 0; const TArray& GetAssociatedObjectKeys() const { return AssociatedObjectKeys; }; const uint32 GetMessageTopicBitflag() const; /** Can optionally be overridden to allow a message to only be logged instead of appearing elsewhere, like the stack. */ virtual bool ShouldOnlyLog() const { return false; } protected: const TArray AssociatedObjectKeys; mutable uint32 MessageTopicBitflag; FSimpleDelegate DismissHandler; }; class FNiagaraMessageCompileEvent : public INiagaraMessage { public: FNiagaraMessageCompileEvent( const FNiagaraCompileEvent& InCompileEvent , TArray& InContextScriptNamesAndAssetPaths , TOptional& InOwningScriptNameAndUsageText , TOptional& InCompiledScriptNameAndAssetPath , const TArray& InAssociatedObjectKeys ); virtual FText GenerateMessageText() const override; virtual FText GenerateMessageTitle() const override; virtual TSharedRef GenerateTokenizedMessage() const override; virtual void GenerateLinks(TArray& OutLinkDisplayNames, TArray& OutLinkNavigationActions) const override; virtual const FName GetMessageTopic() const override { return FNiagaraMessageTopics::CompilerTopicName; }; virtual bool ShouldOnlyLog() const override { return CompileEvent.Severity == FNiagaraCompileEventSeverity::Log; } const FNiagaraCompileEvent& GetCompileEvent() const { return CompileEvent; } private: const FNiagaraCompileEvent CompileEvent; const TArray ContextScriptNamesAndAssetPaths; const TOptional OwningScriptNameAndUsageText; const TOptional CompiledScriptNameAndAssetPath; const TArray AssociatedObjectKeys; }; class FNiagaraMessageText : public INiagaraMessage { public: FNiagaraMessageText(const FText& InMessageText, const FText& InShortDescription, const EMessageSeverity::Type& InMessageSeverity, const FName& InTopicName, const FSimpleDelegate& InDismissHandler = FSimpleDelegate(), const TArray& InAssociatedObjectKeys = TArray()) : INiagaraMessage(InAssociatedObjectKeys) , MessageText(InMessageText) , ShortDescription(InShortDescription) , MessageSeverity(InMessageSeverity) , TopicName(InTopicName) , DismissHandler(InDismissHandler) { }; FNiagaraMessageText(const FText& InMessageText, const EMessageSeverity::Type& InMessageSeverity, const FName& InTopicName, const FSimpleDelegate& InDismissHandler = FSimpleDelegate(), const TArray& InAssociatedObjectKeys = TArray()) : INiagaraMessage(InAssociatedObjectKeys) , MessageText(InMessageText) , MessageSeverity(InMessageSeverity) , TopicName(InTopicName) , DismissHandler(InDismissHandler) { }; virtual FText GenerateMessageText() const override; virtual FText GenerateMessageTitle() const override; virtual const FSimpleDelegate& GetDismissHandler() const { return DismissHandler; } virtual TSharedRef GenerateTokenizedMessage() const override; virtual void GenerateLinks(TArray& OutLinkDisplayNames, TArray& OutLinkNavigationActions) const override { } virtual const FName GetMessageTopic() const override { return TopicName; }; private: const FText MessageText; const FText ShortDescription; const EMessageSeverity::Type MessageSeverity; const FName TopicName; const FSimpleDelegate DismissHandler; }; class FNiagaraMessageTextWithLinks : public FNiagaraMessageText { public: FNiagaraMessageTextWithLinks( const FText& InMessageText , const FText& InShortDescription , const EMessageSeverity::Type& InMessageSeverity , const FName& InTopicName , const FSimpleDelegate& InDismissHandler , const TArray& InLinks , const TArray& InAssociatedObjectKeys = TArray()) : FNiagaraMessageText(InMessageText, InShortDescription, InMessageSeverity, InTopicName, InDismissHandler, InAssociatedObjectKeys) , Links(InLinks) { }; virtual TSharedRef GenerateTokenizedMessage() const override; virtual void GenerateLinks(TArray& OutLinkDisplayNames, TArray& OutLinkNavigationActions) const override; private: const TArray Links; }; /** * Interface for "slow task" message generation jobs that should be time sliced to avoid stalling the UI. */ class INiagaraMessageJob { public: virtual TSharedRef GenerateNiagaraMessage() const = 0; virtual ~INiagaraMessageJob() {}; }; class FNiagaraMessageJobCompileEvent : public INiagaraMessageJob { public: FNiagaraMessageJobCompileEvent( const FNiagaraCompileEvent& InCompileEvent , const TWeakObjectPtr& InOriginatingScriptWeakObjPtr , FGuid InCompiledScriptVersion = FGuid() , const TOptional& InOwningScriptNameString = TOptional() , const TOptional& InSourceScriptAssetPath = TOptional() ); virtual TSharedRef GenerateNiagaraMessage() const override; private: bool RecursiveGetScriptNamesAndAssetPathsFromContextStack( TArray& InContextStackNodeGuids , FGuid NodeGuid , const UNiagaraGraph* InGraphToSearch , TArray& OutContextScriptNamesAndAssetPaths , TOptional& OutEmitterName , TOptional& OutFailureReason , TArray& OutContextNodeObjectKeys ) const; const FNiagaraCompileEvent CompileEvent; const TWeakObjectPtr OriginatingScriptWeakObjPtr; FGuid CompiledScriptVersion; TOptional OwningScriptNameString; TOptional SourceScriptAssetPath; }; USTRUCT() struct FNiagaraStackMessage { GENERATED_BODY() NIAGARAEDITOR_API FNiagaraStackMessage(); NIAGARAEDITOR_API FNiagaraStackMessage(const FText& MessageText, const FText& ShortDescription, ENiagaraMessageSeverity Severity, bool bAllowDismissal, FGuid Guid = FGuid::NewGuid()); UPROPERTY() FText MessageText; UPROPERTY() FText ShortDescription; UPROPERTY() ENiagaraMessageSeverity MessageSeverity = ENiagaraMessageSeverity::Info; UPROPERTY() bool bAllowDismissal = true; UPROPERTY() FGuid Guid; }; USTRUCT() struct FNiagaraStackNoteData { GENERATED_BODY() UPROPERTY() FText MessageHeader; UPROPERTY() FLinearColor Color = FLinearColor::Black; UPROPERTY() FText Message; /** If true, this note should be used inline for a stack entry, instead of adding additional rows. */ UPROPERTY() bool bInlineNote = false; bool operator==(const FNiagaraStackNoteData& Other) const { return MessageHeader.EqualTo(Other.MessageHeader) && Message.EqualTo(Other.Message); } bool IsValid() const { return MessageHeader.IsEmpty() == false || Message.IsEmpty() == false; } }; struct FGenerateNiagaraMessageInfo { public: FGenerateNiagaraMessageInfo() = default; void SetAssociatedObjectKeys(const TArray& InAssociatedObjectKeys) { AssociatedObjectKeys = InAssociatedObjectKeys; }; const TArray& GetAssociatedObjectKeys() const { return AssociatedObjectKeys; }; void SetLinks(const TArray& InLinks) { Links = InLinks; }; const TArray& GetLinks() const { return Links; }; void SetDismissHandler(const FSimpleDelegate& InDismissHandler) { DismissHandler = InDismissHandler; } const FSimpleDelegate& GetDismissHandler() const { return DismissHandler; } private: TArray AssociatedObjectKeys; TArray Links; FSimpleDelegate DismissHandler; }; UCLASS(abstract, MinimalAPI) class UNiagaraMessageData : public UNiagaraMessageDataBase { GENERATED_BODY() public: virtual TSharedRef GenerateNiagaraMessage(const FGenerateNiagaraMessageInfo& InGenerateInfo = FGenerateNiagaraMessageInfo()) const PURE_VIRTUAL(UNiagaraMessageData::GenerateNiagaraMessage, return TSharedRef(static_cast(nullptr));); }; UCLASS(MinimalAPI) class UNiagaraMessageDataText : public UNiagaraMessageData { GENERATED_BODY() public: NIAGARAEDITOR_API void Init(const FText& InMessageText, const ENiagaraMessageSeverity InMessageSeverity, const FName& InTopicName); NIAGARAEDITOR_API void Init(const FText& InMessageText, const FText& InShortDescription, const ENiagaraMessageSeverity InMessageSeverity, const FName& InTopicName); NIAGARAEDITOR_API virtual TSharedRef GenerateNiagaraMessage(const FGenerateNiagaraMessageInfo& InGenerateInfo = FGenerateNiagaraMessageInfo()) const override; virtual bool GetAllowDismissal() const override { return bAllowDismissal; } void SetAllowDismissal(bool bInAllowDismissal) { bAllowDismissal = bInAllowDismissal; } private: /* Marking those FTexts explicitly as editoronly_data will make localization not pick these up. */ #if WITH_EDITORONLY_DATA UPROPERTY() FText MessageText; UPROPERTY() FText ShortDescription; #endif UPROPERTY() ENiagaraMessageSeverity MessageSeverity; UPROPERTY() bool bAllowDismissal; UPROPERTY() FName TopicName; };