diff --git a/Content/Luprex/lxGameMode.uasset b/Content/Luprex/lxGameMode.uasset index c0a98507..93c3cd0d 100644 --- a/Content/Luprex/lxGameMode.uasset +++ b/Content/Luprex/lxGameMode.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:14b8fbd6e4b4c0f13a9da5f6e0b027ce3ba74edfb38825ead9e6dbef59df890d -size 188885 +oid sha256:16624a72b2cfa5af0de3fe6f6084e3402f4f7148853782d30966ea39d2007ecc +size 188593 diff --git a/Content/Tangibles/TAN_Character.uasset b/Content/Tangibles/TAN_Character.uasset index f81d9978..9156611c 100644 --- a/Content/Tangibles/TAN_Character.uasset +++ b/Content/Tangibles/TAN_Character.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2abb2748d894962e38ab916b3a44223695e0c6e73922ea5b0ec5eab178d09e94 -size 372022 +oid sha256:7fef91fc73422c67d7f09f4ea1d0ec0e21fdd88c829de1c3011857d87b3defb2 +size 375026 diff --git a/Source/Integration/LuaCallNode.cpp b/Source/Integration/LuaCallNode.cpp index f60a6d5c..4d38854b 100644 --- a/Source/Integration/LuaCallNode.cpp +++ b/Source/Integration/LuaCallNode.cpp @@ -2,48 +2,17 @@ #include "LuaCallNode.h" -#include "StreamBuffer.h" -#include "GameFramework/Actor.h" #include "BlueprintActionDatabaseRegistrar.h" #include "BlueprintNodeSpawner.h" -#include "Containers/EnumAsByte.h" -#include "Containers/UnrealString.h" -#include "EdGraph/EdGraph.h" -#include "EdGraph/EdGraphSchema.h" #include "EdGraphSchema_K2.h" -#include "EdGraphSchema_K2_Actions.h" -#include "EditorCategoryUtils.h" -#include "Engine/Blueprint.h" -#include "HAL/PlatformCrt.h" -#include "Internationalization/Internationalization.h" +#include "GameFramework/Actor.h" #include "K2Node_CallFunction.h" -#include "K2Node_MakeArray.h" -#include "K2Node_MakeStruct.h" -#include "Kismet/KismetMathLibrary.h" -#include "Kismet/KismetTextLibrary.h" -#include "Kismet2/BlueprintEditorUtils.h" -#include "Kismet2/CompilerResultsLog.h" #include "KismetCompiler.h" #include "LuaCall.h" -#include "Math/Vector2D.h" -#include "Misc/AssertionMacros.h" -#include "Misc/CString.h" -#include "ScopedTransaction.h" -#include "Templates/Casts.h" -#include "Templates/SubclassOf.h" -#include "UObject/Class.h" -#include "UObject/ObjectPtr.h" -#include "UObject/Package.h" -#include "UObject/UnrealNames.h" -#include "UObject/UnrealType.h" -#include "UObject/WeakObjectPtr.h" -#include "UObject/WeakObjectPtrTemplates.h" #define LOCTEXT_NAMESPACE "LuaCall" -#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name))) - // All argument pins will have internal Names that start with "A:" const FName UK2Node_LuaInvoke::FunctionPinName(TEXT("Lua Function Prototype")); @@ -51,44 +20,6 @@ const FName UK2Node_LuaInvoke::PlacePinName(TEXT("Place Tangible")); const FName UK2Node_LuaInvoke::ExtraResultsPinName(TEXT("Extra Results")); const FName UK2Node_LuaInvoke::ErrorPinName(TEXT("Error")); -bool UK2Node_LuaInvoke::IsPrefix(const UEdGraphPin *Pin, char Prefix) -{ - TCHAR pname[FName::StringBufferSize]; - Pin->PinName.ToString(pname); - return pname[0] == Prefix && pname[1] == ':'; -} - -FName UK2Node_LuaInvoke::AddPrefix(const FString &Name, char Prefix) -{ - TCHAR PrefixChars[3]; - PrefixChars[0] = Prefix; - PrefixChars[1] = ':'; - PrefixChars[2] = 0; - FString Prefixed = PrefixChars + Name; - return FName(*Prefixed); -} - -FString UK2Node_LuaInvoke::RemovePrefix(FName Name, char Prefix) -{ - TCHAR pname[FName::StringBufferSize]; - Name.ToString(pname); - check(pname[0] == Prefix); - check(pname[1] == ':'); - return FString(pname + 2); -} - - -UK2Node_LuaInvoke::UK2Node_LuaInvoke(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ -} - -UK2Node_LuaProbe::UK2Node_LuaProbe(const FObjectInitializer& ObjectInitializer) - : Super(ObjectInitializer) -{ -} - - FText UK2Node_LuaInvoke::GetTooltipText() const { static FText Tooltip = FText::FromString(FString::Printf(TEXT( @@ -134,9 +65,7 @@ void UK2Node_LuaInvoke::AllocateDefaultPins() FlxParsedProto ParsedProto(LuaFunctionPrototype); if (!ParsedProto.ErrorMessage.IsEmpty()) { - bHasCompilerMessage = true; - ErrorType = EMessageSeverity::Error; - ErrorMsg = FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage); + SetErrorMsg(FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage)); } CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute); @@ -158,14 +87,10 @@ void UK2Node_LuaInvoke::AllocateDefaultPins() FName PrefixedName = AddPrefix(Pin.Name, 'A'); UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type); if (Accessor == nullptr) { - bHasCompilerMessage = true; - ErrorType = EMessageSeverity::Error; - ErrorMsg = FString::Printf(TEXT("Unknown argument type: %s"), *Pin.Type); + SetErrorMsg(FString::Printf(TEXT("Unknown argument type: %s"), *Pin.Type)); continue; } - FEdGraphPinType PinType; - GetDefault()->ConvertPropertyToPinType(Accessor->FindPropertyByName(TEXT("Value")), PinType); - CreatePin(EGPD_Input, PinType, PrefixedName); + CreatePin(EGPD_Input, PropertyToPinType(Accessor->FindPropertyByName(TEXT("Value"))), PrefixedName); } // Create return value pins. @@ -174,14 +99,10 @@ void UK2Node_LuaInvoke::AllocateDefaultPins() FName PrefixedName = AddPrefix(Pin.Name, 'R'); UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type); if (Accessor == nullptr) { - bHasCompilerMessage = true; - ErrorType = EMessageSeverity::Error; - ErrorMsg = FString::Printf(TEXT("Unknown return value type: %s"), *Pin.Type); + SetErrorMsg(FString::Printf(TEXT("Unknown return value type: %s"), *Pin.Type)); continue; } - FEdGraphPinType PinType; - GetDefault()->ConvertPropertyToPinType(Accessor->FindPropertyByName(TEXT("Result")), PinType); - CreatePin(EGPD_Output, PinType, PrefixedName); + CreatePin(EGPD_Output, PropertyToPinType(Accessor->FindPropertyByName(TEXT("Result"))), PrefixedName); } if (ParsedProto.ExtraReturnValues) @@ -213,26 +134,8 @@ FText UK2Node_LuaInvoke::GetPinDisplayName(const UEdGraphPin* Pin) const return FText::GetEmpty(); } - // For argument pins, we must strip off the Argument Pin Prefix. - if (IsPrefix(Pin, 'A')) - { - return FText::FromString(RemovePrefix(Pin->PinName, 'A')); - } - - // For return value pins, we must strip off the Return Value Pin Prefix. - if (IsPrefix(Pin, 'R')) - { - return FText::FromString(RemovePrefix(Pin->PinName, 'R')); - } - - // Otherwise, just return the Pin Name the normal way. - return FText::FromName(Pin->PinName); -} - -void UK2Node_LuaInvoke::PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) -{ - Super::PostEditChangeProperty(PropertyChangedEvent); - // GetGraph()->NotifyNodeChanged(this); + // Return the pin name, removing A: or R: if present. + return FText::FromName(RemovePrefix(Pin->PinName)); } void UK2Node_LuaInvoke::PinDefaultValueChanged(UEdGraphPin* Pin) @@ -251,23 +154,12 @@ void UK2Node_LuaInvoke::PinDefaultValueChanged(UEdGraphPin* Pin) void UK2Node_LuaInvoke::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph) { Super::ExpandNode(CompilerContext, SourceGraph); - const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema(); - - // Define a local function that creates a CallFunctionNode - auto MakeCallFunctionNode = [&](UFunction *func) - { - UK2Node_CallFunction* CallNode = CompilerContext.SpawnIntermediateNode(this, SourceGraph); - CallNode->SetFromFunction(func); - CallNode->AllocateDefaultPins(); - CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallNode, this); - return CallNode; - }; - // The BeginNode function packs the class name and function name into the call buffer. FlxParsedProto ParsedProto(LuaFunctionPrototype); - UK2Node_CallFunction* BeginNode = MakeCallFunctionNode(LuaCallLibraryFunction(LuaCallBegin)); - Schema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("ClassName")), ParsedProto.ClassName); - Schema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("FunctionName")), ParsedProto.FunctionName); + const UEdGraphSchema_K2* CCSchema = CompilerContext.GetSchema(); + UK2Node_CallFunction* BeginNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallBegin)); + CCSchema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("ClassName")), ParsedProto.ClassName); + CCSchema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("FunctionName")), ParsedProto.FunctionName); UEdGraphPin *ThenPin = BeginNode->GetThenPin(); // Add Packing operations for all argument pins. @@ -281,29 +173,26 @@ void UK2Node_LuaInvoke::ExpandNode(class FKismetCompilerContext& CompilerContext CompilerContext.MessageLog.Error(TEXT("All argument pins must have known types")); continue; } - UK2Node_CallFunction *PackNode = MakeCallFunctionNode(PackingFunc); + UK2Node_CallFunction *PackNode = MakeCallFunctionNode(CompilerContext, SourceGraph, PackingFunc); CompilerContext.MovePinLinksToIntermediate(*Pin, *PackNode->FindPinChecked(TEXT("Value"))); - ThenPin->MakeLinkTo(PackNode->GetExecPin()); - ThenPin = PackNode->GetThenPin(); + ThenPin = ChainExecPin(ThenPin, PackNode, TEXT("Then")); } // Add the invoke or probe node. UEdGraphPin *ReturnArrayPin = nullptr; if (IsInvoke()) { - UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(LuaCallLibraryFunction(LuaCallInvoke)); + UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallInvoke)); CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(PlacePinName), *ActionNode->FindPinChecked(TEXT("Place"))); - ThenPin->MakeLinkTo(ActionNode->GetExecPin()); - ThenPin = ActionNode->GetThenPin(); + ThenPin = ChainExecPin(ThenPin, ActionNode, TEXT("Then")); } else { - UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(LuaCallLibraryFunction(LuaCallProbe)); + UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallProbe)); CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(PlacePinName), *ActionNode->FindPinChecked(TEXT("Place"))); CompilerContext.CopyPinLinksToIntermediate(*FindPinChecked(ErrorPinName), *ActionNode->FindPinChecked(TEXT("False"))); ReturnArrayPin = ActionNode->FindPinChecked(TEXT("ReturnArray")); - ThenPin->MakeLinkTo(ActionNode->GetExecPin()); - ThenPin = ActionNode->FindPinChecked(TEXT("True")); + ThenPin = ChainExecPin(ThenPin, ActionNode, TEXT("True")); } if (IsInvoke()) @@ -327,12 +216,11 @@ void UK2Node_LuaInvoke::ExpandNode(class FKismetCompilerContext& CompilerContext CompilerContext.MessageLog.Error(TEXT("All return value pins must have known types.")); continue; } - UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(UnpackingFunc); + UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(CompilerContext, SourceGraph, UnpackingFunc); ReturnArrayPin->MakeLinkTo(UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_Self)); CompilerContext.CopyPinLinksToIntermediate(*FindPinChecked(ErrorPinName), *UnpackNode->FindPinChecked(TEXT("WrongType"))); CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(TEXT("Result"))); - ThenPin->MakeLinkTo(UnpackNode->GetExecPin()); - ThenPin = UnpackNode->FindPinChecked(TEXT("Success")); + ThenPin = ChainExecPin(ThenPin, UnpackNode, TEXT("Success")); } // If there is an extra results pin, hook it up. @@ -340,10 +228,9 @@ void UK2Node_LuaInvoke::ExpandNode(class FKismetCompilerContext& CompilerContext { UEdGraphPin *ExtraPin = FindPinChecked(ExtraResultsPinName); UFunction *DiscardFunc = UlxLuaValues::StaticClass()->FindFunctionByName(TEXT("DiscardBeforeCursor")); - UK2Node_CallFunction *DiscardNode = MakeCallFunctionNode(DiscardFunc); + UK2Node_CallFunction *DiscardNode = MakeCallFunctionNode(CompilerContext, SourceGraph, DiscardFunc); ReturnArrayPin->MakeLinkTo(DiscardNode->FindPinChecked(UEdGraphSchema_K2::PN_Self)); - ThenPin->MakeLinkTo(DiscardNode->GetExecPin()); - ThenPin = DiscardNode->GetThenPin(); + ThenPin = ChainExecPin(ThenPin, DiscardNode, TEXT("Then")); CompilerContext.MovePinLinksToIntermediate(*ExtraPin, *ReturnArrayPin); } } @@ -382,20 +269,11 @@ bool UK2Node_LuaInvoke::IsConnectionDisallowed(const UEdGraphPin* MyPin, const U void UK2Node_LuaInvoke::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const { - // actions get registered under specific object-keys; the idea is that - // actions might have to be updated (or deleted) if their object-key is - // mutated (or removed)... here we use the node's class (so if the node - // type disappears, then the action should go with it) UClass* ActionKey = GetClass(); - // to keep from needlessly instantiating a UBlueprintNodeSpawner, first - // check to make sure that the registrar is looking for actions of this type - // (could be regenerating actions for a specific asset, and therefore the - // registrar would only accept actions corresponding to that asset) if (ActionRegistrar.IsOpenForRegistration(ActionKey)) { UBlueprintNodeSpawner* NodeSpawner = UBlueprintNodeSpawner::Create(GetClass()); check(NodeSpawner != nullptr); - ActionRegistrar.AddBlueprintAction(ActionKey, NodeSpawner); } } diff --git a/Source/Integration/LuaCallNode.h b/Source/Integration/LuaCallNode.h index 1fc8887a..f8b9c289 100644 --- a/Source/Integration/LuaCallNode.h +++ b/Source/Integration/LuaCallNode.h @@ -1,16 +1,7 @@ #pragma once -#include "Containers/Array.h" -#include "CoreMinimal.h" -#include "EdGraph/EdGraphNode.h" -#include "EdGraph/EdGraphPin.h" -#include "HAL/Platform.h" -#include "Internationalization/Text.h" -#include "K2Node.h" -#include "UObject/NameTypes.h" -#include "UObject/ObjectMacros.h" -#include "UObject/UObjectGlobals.h" +#include "LuprexK2Node.h" #include "LuaCallNode.generated.h" @@ -24,14 +15,11 @@ class UObject; // The Lua Call K2Node. // UCLASS(MinimalAPI) -class UK2Node_LuaInvoke : public UK2Node +class UK2Node_LuaInvoke : public UlxK2Node { - GENERATED_UCLASS_BODY() - - //~ Begin UObject Interface - virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override; - //~ End UObject Interface + GENERATED_BODY() +public: //~ Begin UEdGraphNode Interface. virtual void AllocateDefaultPins() override; virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override; @@ -62,11 +50,6 @@ private: static const FName ExtraResultsPinName; static const FName ErrorPinName; - /** Utility functions for manipulating pin names with prefixes **/ - static bool IsPrefix(const UEdGraphPin *Pin, char Prefix); - static FName AddPrefix(const FString &String, char Prefix); - static FString RemovePrefix(FName Name, char Prefix); - private: /** The lua function prototype, which must be saved as a property **/ UPROPERTY() @@ -77,7 +60,7 @@ private: UCLASS(MinimalAPI) class UK2Node_LuaProbe : public UK2Node_LuaInvoke { - GENERATED_UCLASS_BODY() + GENERATED_BODY() // Setting this flag alters the behavior of LuaInvoke, making it // probe instead of invoke. diff --git a/Source/Integration/LuprexK2Node.cpp b/Source/Integration/LuprexK2Node.cpp new file mode 100644 index 00000000..e9942f11 --- /dev/null +++ b/Source/Integration/LuprexK2Node.cpp @@ -0,0 +1,62 @@ + +#include "LuprexK2Node.h" + +#include "EdGraphSchema_K2.h" +#include "K2Node_CallFunction.h" +#include "KismetCompiler.h" + +FName UlxK2Node::AddPrefix(const FString &Name, char Prefix) +{ + TCHAR PrefixChars[3]; + PrefixChars[0] = Prefix; + PrefixChars[1] = ':'; + PrefixChars[2] = 0; + FString Prefixed = PrefixChars + Name; + return FName(*Prefixed); +} + +FName UlxK2Node::RemovePrefix(FName Name) +{ + TCHAR pname[FName::StringBufferSize]; + Name.ToString(pname); + if ((pname[0] != 0) && (pname[1] == ':')) + { + return FName(pname + 2); + } + return Name; +} + +FEdGraphPinType UlxK2Node::PropertyToPinType(const FProperty *Property) +{ + FEdGraphPinType PinType; + if (Property) + { + GetDefault()->ConvertPropertyToPinType(Property, PinType); + } + return PinType; +} + +void UlxK2Node::SetErrorMsg(const FString &Msg) +{ + if (bHasCompilerMessage) return; + bHasCompilerMessage = true; + ErrorType = EMessageSeverity::Error; + ErrorMsg = Msg; +} + +UEdGraphPin* UlxK2Node::ChainExecPin(UEdGraphPin *ExecOut, UK2Node *NextNode, const TCHAR *OutputPinName) +{ + ExecOut->MakeLinkTo(NextNode->GetExecPin()); + UEdGraphPin *Result = NextNode->FindPinChecked(FName(OutputPinName), EGPD_Output); + check(Result->PinType.PinCategory == UEdGraphSchema_K2::PC_Exec); + return Result; +} + +UK2Node_CallFunction* UlxK2Node::MakeCallFunctionNode(FKismetCompilerContext &CompilerContext, UEdGraph *SourceGraph, UFunction *Func) +{ + UK2Node_CallFunction* CallNode = CompilerContext.SpawnIntermediateNode(this, SourceGraph); + CallNode->SetFromFunction(Func); + CallNode->AllocateDefaultPins(); + CompilerContext.MessageLog.NotifyIntermediateObjectCreation(CallNode, this); + return CallNode; +} diff --git a/Source/Integration/LuprexK2Node.h b/Source/Integration/LuprexK2Node.h new file mode 100644 index 00000000..3ba33645 --- /dev/null +++ b/Source/Integration/LuprexK2Node.h @@ -0,0 +1,34 @@ + +#pragma once + +#include "K2Node.h" + +#include "LuprexK2Node.generated.h" + +// +// Base class for Luprex K2 nodes, adding common utility functions. +// +UCLASS(Abstract, MinimalAPI) +class UlxK2Node : public UK2Node +{ + GENERATED_BODY() + +protected: + /** Add a single-char prefix to a pin name, e.g. AddPrefix("foo", 'A') -> "A:foo" */ + static FName AddPrefix(const FString &Name, char Prefix); + + /** Strip a single-char prefix from a pin name, returning the original name if no prefix is found. */ + static FName RemovePrefix(FName Name); + + /** Convert a UFunction property to a pin type. Returns a default (wildcard) pin type on failure. */ + static FEdGraphPinType PropertyToPinType(const FProperty *Property); + + /** Set a fatal error message on this node. */ + void SetErrorMsg(const FString &Msg); + + /** Spawn an intermediate UK2Node_CallFunction during node expansion. */ + class UK2Node_CallFunction* MakeCallFunctionNode(class FKismetCompilerContext &CompilerContext, UEdGraph *SourceGraph, UFunction *Func); + + /** Link ExecOut to NextNode's exec pin, return NextNode's output exec pin (by name). */ + static UEdGraphPin* ChainExecPin(UEdGraphPin *ExecOut, UK2Node *NextNode, const TCHAR *OutputPinName); +};