Raise Error node now actually prints its own error message

This commit is contained in:
2024-11-13 18:18:32 -05:00
parent ce0a06c51c
commit eff7519d5d
3 changed files with 73 additions and 52 deletions

Binary file not shown.

View File

@@ -40,24 +40,26 @@
#define LOCTEXT_NAMESPACE "K2Node_RaiseError" #define LOCTEXT_NAMESPACE "K2Node_RaiseError"
// It simplifies everything if we can identify pins by name, but to do this // All argument pins will have Names that start with "A:"
// we need for pin names to be unique. To ensure that there's no overlap
// between the hardwired names and the scripter's names, we add a single
// whitespace to any pin name specified in the format string.
static const FName FormatPinName(TEXT("Format"));
static const FName ResultPinName(TEXT("Result"));
static bool IsFormatPin(const UEdGraphPin *Pin) {
return (Pin->PinName == FormatPinName);
}
static bool IsResultPin(const UEdGraphPin *Pin) {
return (Pin->PinName == ResultPinName);
}
static bool IsArgumentPin(const UEdGraphPin *Pin) { static bool IsArgumentPin(const UEdGraphPin *Pin) {
return ((Pin->PinName != FormatPinName) && (Pin->Direction == EGPD_Input)); TCHAR pname[FName::StringBufferSize];
Pin->PinName.ToString(pname);
return pname[0] == 'A' && pname[1] == ':';
}
static FName ArgumentNameAddPrefix(const FString &name) {
FString Prefixed = FString("A:") + name;
return FName(*Prefixed);
}
static FString ArgumentNameRemovePrefix(const FName &name) {
return name.ToString().Mid(2, FName::StringBufferSize);
}
static const FName FormatPinName(TEXT("Format"));
static bool IsFormatPin(const UEdGraphPin *Pin) {
return (Pin->PinName == FormatPinName);
} }
UK2Node_RaiseError::UK2Node_RaiseError(const FObjectInitializer& ObjectInitializer) UK2Node_RaiseError::UK2Node_RaiseError(const FObjectInitializer& ObjectInitializer)
@@ -74,14 +76,16 @@ void UK2Node_RaiseError::AllocateDefaultPins()
void UK2Node_RaiseError::CreateCorrectPins() void UK2Node_RaiseError::CreateCorrectPins()
{ {
// Create the Format Pin if it doesn't already exist. if (FindPin(UEdGraphSchema_K2::PN_Execute) == nullptr) {
if (FindPin(FormatPinName, EGPD_Input) == nullptr) { UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Text, FormatPinName);
} }
// Create the Result Pin if it doesn't already exist. if (FindPin(UEdGraphSchema_K2::PN_Then) == nullptr) {
if (FindPin(ResultPinName, EGPD_Output) == nullptr) { UEdGraphPin *P = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Text, ResultPinName); }
if (FindPin(FormatPinName, EGPD_Input) == nullptr) {
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Text, FormatPinName);
} }
// Transfer all Existing Argument pins to the Old Pins Map. // Transfer all Existing Argument pins to the Old Pins Map.
@@ -91,20 +95,21 @@ void UK2Node_RaiseError::CreateCorrectPins()
UEdGraphPin* CheckPin = *It; UEdGraphPin* CheckPin = *It;
if (IsArgumentPin(CheckPin)) if (IsArgumentPin(CheckPin))
{ {
OldPins.Add(CheckPin->PinName.ToString(), CheckPin); OldPins.Add(ArgumentNameRemovePrefix(CheckPin->PinName), CheckPin);
It.RemoveCurrent(); It.RemoveCurrent();
} }
} }
// Create Argument pins in the correct order, reusing old pins where possible. // Create Argument pins in the correct order, reusing old pins where possible.
for (const FName& PinName : PinNames) for (const FString& Name : PinNames)
{ {
UEdGraphPin **OldPin = OldPins.Find(PinName.ToString()); UEdGraphPin **OldPin = OldPins.Find(Name);
if (OldPin != nullptr) { if (OldPin != nullptr) {
Pins.Emplace(*OldPin); Pins.Emplace(*OldPin);
OldPins.Remove(PinName.ToString()); OldPins.Remove(Name);
} else { } else {
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, PinName); FName PrefixedName = ArgumentNameAddPrefix(Name);
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, PrefixedName);
} }
} }
@@ -169,6 +174,17 @@ FText UK2Node_RaiseError::GetNodeTitle(ENodeTitleType::Type TitleType) const
FText UK2Node_RaiseError::GetPinDisplayName(const UEdGraphPin* Pin) const FText UK2Node_RaiseError::GetPinDisplayName(const UEdGraphPin* Pin) const
{ {
// These pins should be unlabeled.
if ((Pin->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec) || (IsFormatPin(Pin))) {
return FText::GetEmpty();
}
// For argument pins, we must strip off the Argument Pin Prefix.
if (IsArgumentPin(Pin)) {
return FText::FromString(ArgumentNameRemovePrefix(Pin->PinName));
}
// Probably should never get here.
return FText::FromName(Pin->PinName); return FText::FromName(Pin->PinName);
} }
@@ -193,15 +209,8 @@ void UK2Node_RaiseError::PinDefaultValueChanged(UEdGraphPin* Pin)
{ {
if(IsFormatPin(Pin)) if(IsFormatPin(Pin))
{ {
TArray< FString > ArgumentParams; PinNames.Empty();
FText::GetFormatPatternParameters(Pin->DefaultTextValue, ArgumentParams); FText::GetFormatPatternParameters(Pin->DefaultTextValue, PinNames);
PinNames.Reset();
for (const FString& Param : ArgumentParams)
{
FString WithWhite = Param + TEXT(" ");
PinNames.Add(FName(*WithWhite));
}
CreateCorrectPins(); CreateCorrectPins();
GetGraph()->NotifyNodeChanged(this); GetGraph()->NotifyNodeChanged(this);
} }
@@ -265,29 +274,39 @@ void UK2Node_RaiseError::ExpandNode(class FKismetCompilerContext& CompilerContex
MakeArrayNode->AllocateDefaultPins(); MakeArrayNode->AllocateDefaultPins();
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(MakeArrayNode, this); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(MakeArrayNode, this);
UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin();
// This is the node that does all the Format work. // This is the node that does all the Format work.
UK2Node_CallFunction* CallFormatFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph); UK2Node_CallFunction* CallFormatFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
CallFormatFunction->SetFromFunction(UKismetTextLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetTextLibrary, Format))); CallFormatFunction->SetFromFunction(UKismetTextLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetTextLibrary, Format)));
CallFormatFunction->AllocateDefaultPins(); CallFormatFunction->AllocateDefaultPins();
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFormatFunction, this); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFormatFunction, this);
// This is the node that outputs the text.
UK2Node_CallFunction* CallPrintFunction = CompilerContext.SpawnIntermediateNode<UK2Node_CallFunction>(this, SourceGraph);
CallPrintFunction->SetFromFunction(UKismetSystemLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetSystemLibrary, PrintText)));
CallPrintFunction->AllocateDefaultPins();
CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallPrintFunction, this);
// Connect the output of the "Make Array" pin to the function's "InArgs" pin // Connect the output of the "Make Array" pin to the function's "InArgs" pin
UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin();
ArrayOut->MakeLinkTo(CallFormatFunction->FindPinChecked(TEXT("InArgs"))); ArrayOut->MakeLinkTo(CallFormatFunction->FindPinChecked(TEXT("InArgs")));
// This will set the "Make Array" node's type, only works if one pin is connected. // This will set the "Make Array" node's type, only works if one pin is connected.
MakeArrayNode->PinConnectionListChanged(ArrayOut); MakeArrayNode->PinConnectionListChanged(ArrayOut);
// Connect the output of the "Format" node to the PrintText function's "InText" pin
UEdGraphPin* FormatOut = CallFormatFunction->GetReturnValuePin();
FormatOut->MakeLinkTo(CallPrintFunction->FindPinChecked(TEXT("InText")));
// Configure the Print function to keep the text onscreen for 30 seconds.
UEdGraphPin* DurationIn = CallPrintFunction->FindPinChecked(TEXT("Duration"));
CallPrintFunction->GetSchema()->TrySetDefaultValue(*DurationIn, "30");
// For each argument, we will need to add in a "Make Struct" node. // For each argument, we will need to add in a "Make Struct" node.
for(int32 ArgIdx = 0; ArgIdx < PinNames.Num(); ++ArgIdx) for(int32 ArgIdx = 0; ArgIdx < PinNames.Num(); ++ArgIdx)
{ {
UEdGraphPin* ArgumentPin = FindPin(PinNames[ArgIdx], EGPD_Input); FString OriginalName = PinNames[ArgIdx];
UEdGraphPin* ArgumentPin = FindPin(ArgumentNameAddPrefix(OriginalName), EGPD_Input);
// All argument pins have a whitespace appended to their pin names.
// We need the original name before the whitespace was appended.
FString OriginalName = ArgumentPin->PinName.ToString().LeftChop(1);
static UScriptStruct* FormatArgumentDataStruct = FindObjectChecked<UScriptStruct>(FindObjectChecked<UPackage>(nullptr, TEXT("/Script/Engine")), TEXT("FormatArgumentData")); static UScriptStruct* FormatArgumentDataStruct = FindObjectChecked<UScriptStruct>(FindObjectChecked<UPackage>(nullptr, TEXT("/Script/Engine")), TEXT("FormatArgumentData"));
// Spawn a "Make Struct" node to create the struct needed for formatting the text. // Spawn a "Make Struct" node to create the struct needed for formatting the text.
@@ -410,7 +429,7 @@ void UK2Node_RaiseError::ExpandNode(class FKismetCompilerContext& CompilerContex
else else
{ {
// Unexpected pin type! // Unexpected pin type!
CompilerContext.MessageLog.Error(*FText::Format(LOCTEXT("Error_UnexpectedPinType", "Pin '{0}' has an unexpected type: {1}"), FText::FromName(PinNames[ArgIdx]), FText::FromName(ArgumentPinCategory)).ToString()); CompilerContext.MessageLog.Error(*FText::Format(LOCTEXT("Error_UnexpectedPinType", "Pin '{0}' has an unexpected type: {1}"), FText::FromString(OriginalName), FText::FromName(ArgumentPinCategory)).ToString());
} }
} }
else else
@@ -434,11 +453,13 @@ void UK2Node_RaiseError::ExpandNode(class FKismetCompilerContext& CompilerContex
FindOutputStructPinChecked(MakeFormatArgumentDataStruct)->MakeLinkTo(InputPin); FindOutputStructPinChecked(MakeFormatArgumentDataStruct)->MakeLinkTo(InputPin);
} }
// Move connection of RaiseError's "Result" pin to the call function's return value pin.
CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(ResultPinName, EGPD_Output), *CallFormatFunction->GetReturnValuePin());
// Move connection of RaiseError's "Format" pin to the call function's "InPattern" pin // Move connection of RaiseError's "Format" pin to the call function's "InPattern" pin
CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(FormatPinName, EGPD_Input), *CallFormatFunction->FindPinChecked(TEXT("InPattern"))); CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(FormatPinName), *CallFormatFunction->FindPinChecked(TEXT("InPattern")));
// Link up the Exec pins.
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *CallPrintFunction->GetExecPin());
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *CallPrintFunction->GetThenPin());
BreakAllNodeLinks(); BreakAllNodeLinks();
} }

View File

@@ -41,7 +41,7 @@ class UK2Node_RaiseError : public UK2Node
//~ End UEdGraphNode Interface. //~ End UEdGraphNode Interface.
//~ Begin UK2Node Interface. //~ Begin UK2Node Interface.
virtual bool IsNodePure() const override { return true; } virtual bool IsNodePure() const override { return false; }
virtual void PostReconstructNode() override; virtual void PostReconstructNode() override;
virtual bool NodeCausesStructuralBlueprintChange() const override { return true; } virtual bool NodeCausesStructuralBlueprintChange() const override { return true; }
virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override; virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override;
@@ -62,7 +62,7 @@ private:
private: private:
/** When adding arguments to the node, their names are placed here and are generated as pins during construction */ /** When adding arguments to the node, their names are placed here and are generated as pins during construction */
UPROPERTY() UPROPERTY()
TArray<FName> PinNames; TArray<FString> PinNames;
/** Tooltip text for this node. */ /** Tooltip text for this node. */
FText NodeTooltip; FText NodeTooltip;