This is awesome!
Now I can track function calls and function exceptions from PIE sessions in my plugin code:
.H:
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "UObject/WeakObjectPtr.h"
#include "UFSM_Log.generated.h"
DECLARE_LOG_CATEGORY_EXTERN(UFSM,Log,All);
#define FFIND(Name) FindFunction(Name)
#define PIE_Warning(Message,Token) FMessageLog("PIE").Warning(FText::FromString(FString::Printf(TEXT("{FSM}:: %s --> "),*Message)))->AddToken(Token)
#define PIE_Error(Message,Token) FMessageLog("PIE").Error(FText::FromString(FString::Printf(TEXT("{FSM}:: %s --> "),*Message)))->AddToken(Token)
#define PIE_Critical(Token) FMessageLog("PIE").Message(EMessageSeverity::CriticalError)->AddToken(Token)
#define PIE_Message(Token) FMessageLog("PIE").Message(EMessageSeverity::Info)->AddToken(Token);
UENUM()
enum class ESeverity : uint8 {
CriticalError = 0,
Error = 1,
Warning = 2,
Info = 3
};
UFSM_API void LOG_FSM(const bool Debug, const bool Logs, const float Duration, const FColor Color, const FString Message);
UFSM_API void LOG_PIE(const bool Debug, const ESeverity Severity, const UObject* Owner, const UFunction* Function, const FString Message = TEXT(""));
UFSM_API void LOG_PIE(const ESeverity Severity, const UObject* Owner, const UFunction* Function, const FString Message = TEXT(""));
UFSM_API void LOG_PIE(const UObject* Owner, const UFunction* Function, const FString Message = TEXT(""));
UFSM_API void LOG_PIE(const UFunction* Function, const UObject* Owner);
UFSM_API void LOG_PIE(const UFunction* Function);
.CPP:
#if WITH_EDITOR
#include "MessageLog.h"
#include "TokenizedMessage.h"
#endif
DEFINE_LOG_CATEGORY(UFSM);
#define LOCTEXT_NAMESPACE "MyEditorStuff"
void LOG_PIE(const bool Debug, const ESeverity Severity, const UObject* Owner, const UFunction* Function, const FString Message) {
if (!Debug) {return;}
if (!Function) {return;}
if (!Owner) {return;}
//
#if WITH_EDITOR
FFormatNamedArguments ARG;
FFormatArgumentValue AFunction = Function->GetDisplayNameText();
FFormatArgumentValue AInfo = FText::FromString(Function->GetFullName());
FFormatArgumentValue APackage = FText::FromString(Owner->GetFullName());
//
ARG.Add(TEXT("Function"),AFunction);
ARG.Add(TEXT("Package"),APackage);
ARG.Add(TEXT("Details"),AInfo);
//
const auto Token = FTextToken::Create(FText::Format(LOCTEXT("LOG_PIE","{Function}: {Details} at ({Package})]"),ARG));
//
switch (Severity) {
case ESeverity::Info:
PIE_Message(Token); break;
case ESeverity::Warning:
PIE_Warning(Message,Token); break;
case ESeverity::Error:
PIE_Error(Message,Token); break;
case ESeverity::CriticalError:
PIE_Critical(Token); break;
default: break;}
#endif
}
UFSM_API void LOG_PIE(const ESeverity Severity, const UObject* Owner, const UFunction* Function, const FString Message) {
LOG_PIE(true,Severity,Owner,Function,Message);
}
UFSM_API void LOG_PIE(const UObject* Owner, const UFunction* Function, const FString Message) {
LOG_PIE(ESeverity::Warning,Owner,Function,Message);
}
UFSM_API void LOG_PIE(const UFunction* Function, const UObject* Owner) {
LOG_PIE(Owner,Function,FString(TEXT("Something went wrong!")));
}
UFSM_API void LOG_PIE(const UFunction* Function) {
LOG_PIE(ESeverity::Info,Function,Function,TEXT(""));
}
#undef LOCTEXT_NAMESPACE
#undef PIE_Message
#undef PIE_Warning
#undef PIE_Critical
#undef PIE_Error
#undef FFIND
Calling from within a Game function; it identifies the calling function using its “Display Name” metadata, like the screenshot above:
void UStateMachineComponent::Client_SetState_Implementation(const FName Name, const bool Validate) {
//(...) // do stuff...
LOG_PIE(FFIND(TEXT("Client_SetState")));
LOG_PIE(FFIND(TEXT("Client_SetState")),GetOwner());
LOG_PIE(GetOwner(),FFIND(TEXT("Client_SetState")),TEXT("Message from Game Module!"));
LOG_PIE(ESeverity::Warning,GetOwner(),FFIND(TEXT("Client_SetState")),TEXT("Warning from Game Module!"));
LOG_PIE(Debug,ESeverity::Error,GetOwner(),FFIND(TEXT("Client_SetState")),TEXT("Error from Game Module!"));
//LOG_PIE(Debug,ESeverity::**CriticalError**,GetOwner(),FFIND(TEXT("Client_SetState")),TEXT("Oops!")); <-- This will crash the Editor and launch Bug Report window with traces up to where it locates and displays the 'Token' created.
}