Format Error Message is in good condition.

This commit is contained in:
2024-11-19 21:41:09 -05:00
parent 26fca0fca8
commit c332fea06b
2 changed files with 142 additions and 38 deletions

View File

@@ -76,7 +76,15 @@ static bool IsFormatPin(const UEdGraphPin *Pin) {
UK2Node_FormatError::UK2Node_FormatError(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
NodeTooltip = LOCTEXT("NodeTooltip", "Builds a formatted string using available format argument values.\n \u2022 Use {} to denote format arguments.\n \u2022 Argument types may be Byte, Integer, Float, Text, String, Name, Boolean, Object or ETextGender.");
NodeTooltip = LOCTEXT("NodeTooltip",
"Output an error, warning, or informational message to the log file.\n"
"\n"
" \u2022 Use {ArgName} to denote format arguments, giving each argument a different ArgName.\n"
" \u2022 Arguments may be Byte, Integer, Float, Text, String, Name, Boolean, Object or ETextGender.\n"
"\n"
"It is often desirable to use this in conjunction with a separate utility that\n"
"pauses the execution of the blueprint whenever an error is logged."
);
}
void UK2Node_FormatError::AllocateDefaultPins()
@@ -198,14 +206,18 @@ FText UK2Node_FormatError::GetNodeTitle(ENodeTitleType::Type TitleType) const
FText UK2Node_FormatError::GetPinDisplayName(const UEdGraphPin* Pin) const
{
// Many pins can go unlabeled if they have default values.
if ((Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec) ||
IsFormatPin(Pin) || IsVerbosityPin(Pin) || IsDisplayDurationPin(Pin))
// The exec pins don't need labels.
if (Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec)
{
if (Pin->LinkedTo.Num() == 0) {
return FText::GetEmpty();
}
// Many pins can go unlabeled if they have default values.
if (IsFormatPin(Pin) || IsVerbosityPin(Pin) || IsDisplayDurationPin(Pin))
{
if (Pin->LinkedTo.Num() == 0)
{
return FText::GetEmpty();
} else {
return FText::FromName(Pin->PinName);
}
}
@@ -214,7 +226,7 @@ FText UK2Node_FormatError::GetPinDisplayName(const UEdGraphPin* Pin) const
return FText::FromString(ArgumentNameRemovePrefix(Pin->PinName));
}
// Probably should never get here.
// Otherwise, just return the Pin Name the normal way.
return FText::FromName(Pin->PinName);
}
@@ -596,17 +608,20 @@ FText UK2Node_FormatError::GetMenuCategory() const
return FEditorCategoryUtils::GetCommonCategory(FCommonEditorCategory::Text);
}
void UlxFormatErrorLibrary::FormatErrorInternal(ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray<FFormatArgumentData> InArgs)
void UlxFormatErrorLibrary::FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray<FFormatArgumentData> InArgs)
{
// Generate the formatted string.
//
FText Message = FTextFormatter::Format(MoveTemp(InPattern), MoveTemp(InArgs), false, false);
FString MessageString = Message.ToString();
// Convert the DisplayDuration enum into a number of seconds.
//
int Seconds = int(DisplayDuration);
if (Seconds > 100) Seconds = (Seconds - 100) * 60;
// Choose a color appropriate to the verbosity level.
//
FLinearColor Color;
switch (Verbosity) {
case ElxLogVerbosity::Fatal : Color = FLinearColor(1.0, 0.6, 0.6); break;
@@ -615,21 +630,48 @@ void UlxFormatErrorLibrary::FormatErrorInternal(ElxLogVerbosity Verbosity, ElxDi
default: Color = FLinearColor(0.8, 0.8, 0.8); break;
}
// Output to Log
// Convert verbosity to an internal value.
//
ELogVerbosity::Type VerbosityValue;
switch (Verbosity) {
case ElxLogVerbosity::Fatal: UE_LOG(LogBlueprint, Fatal, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Error: UE_LOG(LogBlueprint, Error, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Warning: UE_LOG(LogBlueprint, Warning, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Display: UE_LOG(LogBlueprint, Display, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Log: UE_LOG(LogBlueprint, Log, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Verbose: UE_LOG(LogBlueprint, Verbose, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::VeryVerbose: UE_LOG(LogBlueprint, VeryVerbose, TEXT("%s"), *MessageString); break;
case ElxLogVerbosity::Error: VerbosityValue = ELogVerbosity::Error; break;
case ElxLogVerbosity::Warning: VerbosityValue = ELogVerbosity::Warning; break;
case ElxLogVerbosity::Display: VerbosityValue = ELogVerbosity::Display; break;
case ElxLogVerbosity::Log: VerbosityValue = ELogVerbosity::Log; break;
case ElxLogVerbosity::Verbose: VerbosityValue = ELogVerbosity::Verbose; break;
case ElxLogVerbosity::VeryVerbose: VerbosityValue = ELogVerbosity::VeryVerbose; break;
case ElxLogVerbosity::Fatal: VerbosityValue = ELogVerbosity::Fatal; break;
}
// Output to Screen (Maybe)
if (Seconds != 0) {
// Get the blueprint name.
//
// Normally, the log function expects you to pass in a filename, and a log
// category name. We use the blueprint name for both.
//
// Using the blueprint name as a log category name is not technically
// correct. However, there is no correct way to create log categories
// from inside of blueprints. Doing it this way at least produces a reasonable
// message inside the log. What doesn't work correctly is the log message
// suppression system. Ie, console commands like 'log <category> verbose'
// don't have any effect here. The design of the log message suppression
// system is such that there just is no reasonable way to hook into it from
// inside of blueprints.
//
FString BlueprintNameString = Context->GetClass()->GetName();
auto BlueprintNameAnsi = StringCast<ANSICHAR>(*BlueprintNameString);
FLogCategoryName BlueprintNameLogCategory(Context->GetClass()->GetFName());
// Output to Screen, if requested.
//
if (Seconds != 0)
{
UKismetSystemLibrary::PrintText(NULL, Message, true, false, Color, Seconds, NAME_None);
}
// Output to Log
//
FMsg::Logf(BlueprintNameAnsi.Get(), 0, BlueprintNameLogCategory, VerbosityValue, TEXT("%s"), *MessageString);
}

View File

@@ -21,44 +21,106 @@ class UEdGraph;
class UObject;
//
// Export log verbosity to blueprints.
//
UENUM(BlueprintType)
enum class ElxLogVerbosity : uint8 {
Fatal,
Error,
Warning,
Display,
Log,
Verbose,
VeryVerbose,
};
//
// Display Duration - how long to show a message on-screen.
// The following UENUM contains all the ELogVerbosity levels, in a form
// that the blueprint editor can manipulate.
//
// We deliberately moved Fatal to the end of the list, because the editor
// will display these values in the order shown here, and we want Error to
// be the value that is 'promoted', and we want Fatal to be buried as a
// rarely-used option.
//
/** Log Verbosity: The importance of the message, which affects where the message goes and how it is filtered. */
UENUM(BlueprintType)
enum class ElxLogVerbosity : uint8 {
/* Prints an error to the console and log file. The editor collects and reports errors. */
Error,
/* Prints a warning to the console and log file. The editor collects and report warnings. */
Warning,
/* Prints a message to the console and log file. */
Display,
/* Prints a message to the log file, however, it does not print to the console. */
Log,
/* Prints a message to a log file only if Verbose logging is enabled for the given category. This is usually used for detailed logging. */
Verbose,
/* Prints a message to a log file. If VeryVerbose logging is enabled, then this is used for detailed logging that would otherwise spam output. */
VeryVerbose,
/* Danger! Prints a fatal error to the console and log file, then crashes (this crashes the editor too). */
Fatal,
};
/** Display Duration: How long to display a message in the game's viewport */
UENUM(BlueprintType)
enum class ElxDisplayDuration : uint8 {
No_Display = 0,
/* Do not display the message in the viewport */
No_Display_in_Viewport = 0,
/* Display the message in the viewport for 1 second */
Display_1_Seconds = 1,
/* Display the message in the viewport for 2 second */
Display_2_Seconds = 2,
/* Display the message in the viewport for 3 second */
Display_3_Seconds = 3,
/* Display the message in the viewport for 4 second */
Display_4_Seconds = 4,
/* Display the message in the viewport for 5 second */
Display_5_Seconds = 5,
/* Display the message in the viewport for 10 second */
Display_10_Seconds = 10,
/* Display the message in the viewport for 20 second */
Display_20_Seconds = 20,
/* Display the message in the viewport for 30 second */
Display_30_Seconds = 30,
/* Display the message in the viewport for 1 second */
Display_40_Seconds = 40,
/* Display the message in the viewport for 1 second */
Display_50_Seconds = 50,
/* Display the message in the viewport for 1 second */
Display_60_Seconds = 60,
/* Display the message in the viewport for 1 second */
Display_70_Seconds = 70,
/* Display the message in the viewport for 1 second */
Display_80_Seconds = 80,
/* Display the message in the viewport for 1 second */
Display_90_Seconds = 90,
/* Display the message in the viewport for 1 second */
Display_1_Minute = 101,
/* Display the message in the viewport for 1 second */
Display_2_Minutes = 102,
/* Display the message in the viewport for 1 second */
Display_3_Minutes = 103,
/* Display the message in the viewport for 1 second */
Display_4_Minutes = 104,
/* Display the message in the viewport for 1 second */
Display_5_Minutes = 105,
};
@@ -71,13 +133,13 @@ class UlxFormatErrorLibrary : public UBlueprintFunctionLibrary
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, meta=(BlueprintInternalUseOnly = "true"))
static void FormatErrorInternal(ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray<FFormatArgumentData> InArgs);
UFUNCTION(BlueprintCallable, meta=(WorldContext = "Context", BlueprintInternalUseOnly = "true"))
static void FormatErrorInternal(UObject *Context, ElxLogVerbosity Verbosity, ElxDisplayDuration DisplayDuration, FText InPattern, TArray<FFormatArgumentData> InArgs);
};
//
// Library functions used by Format Error Message, and also
// by scripters writing their own Error Message Handler classes.
// The Format Error Message K2Node.
//
UCLASS(MinimalAPI)
class UK2Node_FormatError : public UK2Node