From eff7519d5d098a4d23efe8e55284b212cc913f03 Mon Sep 17 00:00:00 2001 From: jyelon Date: Wed, 13 Nov 2024 18:18:32 -0500 Subject: [PATCH] Raise Error node now actually prints its own error message --- Content/Tangibles/tangiblecharacter.uasset | 4 +- Source/Integration/K2Node_RaiseError.cpp | 117 ++++++++++++--------- Source/Integration/K2Node_RaiseError.h | 4 +- 3 files changed, 73 insertions(+), 52 deletions(-) diff --git a/Content/Tangibles/tangiblecharacter.uasset b/Content/Tangibles/tangiblecharacter.uasset index 987ed3e3..1cb4e5d5 100644 --- a/Content/Tangibles/tangiblecharacter.uasset +++ b/Content/Tangibles/tangiblecharacter.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:679f48b72656a40b3a6a83e106df2b2d4c76390a8f87948e5122526852257d44 -size 389151 +oid sha256:dc5b5f51d4749f652f7e80b9f73c25b71200f493964704affda5b68a30a2e0c6 +size 371534 diff --git a/Source/Integration/K2Node_RaiseError.cpp b/Source/Integration/K2Node_RaiseError.cpp index d75ae95f..1630f6e5 100644 --- a/Source/Integration/K2Node_RaiseError.cpp +++ b/Source/Integration/K2Node_RaiseError.cpp @@ -40,24 +40,26 @@ #define LOCTEXT_NAMESPACE "K2Node_RaiseError" -// It simplifies everything if we can identify pins by name, but to do this -// 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); -} +// All argument pins will have Names that start with "A:" 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) @@ -74,14 +76,16 @@ void UK2Node_RaiseError::AllocateDefaultPins() void UK2Node_RaiseError::CreateCorrectPins() { - // Create the Format Pin if it doesn't already exist. - if (FindPin(FormatPinName, EGPD_Input) == nullptr) { - CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Text, FormatPinName); + if (FindPin(UEdGraphSchema_K2::PN_Execute) == nullptr) { + UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute); } - // Create the Result Pin if it doesn't already exist. - if (FindPin(ResultPinName, EGPD_Output) == nullptr) { - CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Text, ResultPinName); + if (FindPin(UEdGraphSchema_K2::PN_Then) == nullptr) { + UEdGraphPin *P = CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then); + } + + 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. @@ -91,20 +95,21 @@ void UK2Node_RaiseError::CreateCorrectPins() UEdGraphPin* CheckPin = *It; if (IsArgumentPin(CheckPin)) { - OldPins.Add(CheckPin->PinName.ToString(), CheckPin); + OldPins.Add(ArgumentNameRemovePrefix(CheckPin->PinName), CheckPin); It.RemoveCurrent(); } } // 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) { Pins.Emplace(*OldPin); - OldPins.Remove(PinName.ToString()); + OldPins.Remove(Name); } 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 { + // 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); } @@ -193,15 +209,8 @@ void UK2Node_RaiseError::PinDefaultValueChanged(UEdGraphPin* Pin) { if(IsFormatPin(Pin)) { - TArray< FString > ArgumentParams; - FText::GetFormatPatternParameters(Pin->DefaultTextValue, ArgumentParams); - - PinNames.Reset(); - for (const FString& Param : ArgumentParams) - { - FString WithWhite = Param + TEXT(" "); - PinNames.Add(FName(*WithWhite)); - } + PinNames.Empty(); + FText::GetFormatPatternParameters(Pin->DefaultTextValue, PinNames); CreateCorrectPins(); GetGraph()->NotifyNodeChanged(this); } @@ -265,29 +274,39 @@ void UK2Node_RaiseError::ExpandNode(class FKismetCompilerContext& CompilerContex MakeArrayNode->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(MakeArrayNode, this); - UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin(); - // This is the node that does all the Format work. UK2Node_CallFunction* CallFormatFunction = CompilerContext.SpawnIntermediateNode(this, SourceGraph); CallFormatFunction->SetFromFunction(UKismetTextLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UKismetTextLibrary, Format))); CallFormatFunction->AllocateDefaultPins(); CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallFormatFunction, this); + // This is the node that outputs the text. + UK2Node_CallFunction* CallPrintFunction = CompilerContext.SpawnIntermediateNode(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 + UEdGraphPin* ArrayOut = MakeArrayNode->GetOutputPin(); ArrayOut->MakeLinkTo(CallFormatFunction->FindPinChecked(TEXT("InArgs"))); // This will set the "Make Array" node's type, only works if one pin is connected. 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(int32 ArgIdx = 0; ArgIdx < PinNames.Num(); ++ArgIdx) { - UEdGraphPin* ArgumentPin = FindPin(PinNames[ArgIdx], 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); - + FString OriginalName = PinNames[ArgIdx]; + UEdGraphPin* ArgumentPin = FindPin(ArgumentNameAddPrefix(OriginalName), EGPD_Input); + static UScriptStruct* FormatArgumentDataStruct = FindObjectChecked(FindObjectChecked(nullptr, TEXT("/Script/Engine")), TEXT("FormatArgumentData")); // 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 { // 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 @@ -434,11 +453,13 @@ void UK2Node_RaiseError::ExpandNode(class FKismetCompilerContext& CompilerContex 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 - 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(); } diff --git a/Source/Integration/K2Node_RaiseError.h b/Source/Integration/K2Node_RaiseError.h index 0192c591..67e29568 100644 --- a/Source/Integration/K2Node_RaiseError.h +++ b/Source/Integration/K2Node_RaiseError.h @@ -41,7 +41,7 @@ class UK2Node_RaiseError : public UK2Node //~ End UEdGraphNode Interface. //~ Begin UK2Node Interface. - virtual bool IsNodePure() const override { return true; } + virtual bool IsNodePure() const override { return false; } virtual void PostReconstructNode() override; virtual bool NodeCausesStructuralBlueprintChange() const override { return true; } virtual void ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) override; @@ -62,7 +62,7 @@ private: private: /** When adding arguments to the node, their names are placed here and are generated as pins during construction */ UPROPERTY() - TArray PinNames; + TArray PinNames; /** Tooltip text for this node. */ FText NodeTooltip;