Lots of work on several unrelated things.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
|
||||
#include "LuaCallNode.h"
|
||||
#include "StringDecoder.h"
|
||||
|
||||
#include "BlueprintActionDatabaseRegistrar.h"
|
||||
#include "BlueprintNodeSpawner.h"
|
||||
@@ -40,59 +41,41 @@
|
||||
|
||||
#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:"
|
||||
|
||||
static bool IsArgumentPin(const UEdGraphPin *Pin) {
|
||||
const FName UK2Node_LuaCall::FunctionPinName(TEXT("Lua Function Prototype"));
|
||||
const FName UK2Node_LuaCall::InvokeOrProbePinName(TEXT("Invoke or Probe"));
|
||||
const FName UK2Node_LuaCall::PlacePinName(TEXT("Place Tangible"));
|
||||
const FName UK2Node_LuaCall::ExtraResultsPinName(TEXT("Extra Results"));
|
||||
|
||||
bool UK2Node_LuaCall::IsPrefix(const UEdGraphPin *Pin, char Prefix)
|
||||
{
|
||||
TCHAR pname[FName::StringBufferSize];
|
||||
Pin->PinName.ToString(pname);
|
||||
return pname[0] == 'A' && pname[1] == ':';
|
||||
return pname[0] == Prefix && pname[1] == ':';
|
||||
}
|
||||
|
||||
static FName ArgumentNameAddPrefix(const FString &name) {
|
||||
FString Prefixed = FString("A:") + name;
|
||||
FName UK2Node_LuaCall::AddPrefix(const FString &Name, char Prefix)
|
||||
{
|
||||
TCHAR PrefixChars[3];
|
||||
PrefixChars[0] = Prefix;
|
||||
PrefixChars[1] = ':';
|
||||
PrefixChars[2] = 0;
|
||||
FString Prefixed = PrefixChars + Name;
|
||||
return FName(*Prefixed);
|
||||
}
|
||||
|
||||
static FString ArgumentNameRemovePrefix(const FName &name) {
|
||||
return name.ToString().Mid(2, FName::StringBufferSize);
|
||||
}
|
||||
|
||||
// All return value pins will have internal Names that start with "R:"
|
||||
|
||||
static bool IsReturnValuePin(const UEdGraphPin *Pin) {
|
||||
FString UK2Node_LuaCall::RemovePrefix(FName Name, char Prefix)
|
||||
{
|
||||
TCHAR pname[FName::StringBufferSize];
|
||||
Pin->PinName.ToString(pname);
|
||||
return pname[0] == 'R' && pname[1] == ':';
|
||||
Name.ToString(pname);
|
||||
check(pname[0] == Prefix);
|
||||
check(pname[1] == ':');
|
||||
return FString(pname + 2);
|
||||
}
|
||||
|
||||
static FName ReturnValueNameAddPrefix(const FString &name) {
|
||||
FString Prefixed = FString("R:") + name;
|
||||
return FName(*Prefixed);
|
||||
}
|
||||
|
||||
static FString ReturnValueNameRemovePrefix(const FName &name) {
|
||||
return name.ToString().Mid(2, FName::StringBufferSize);
|
||||
}
|
||||
|
||||
// Builtin pins will have names with no prefixes.
|
||||
|
||||
static const FName FunctionPinName(TEXT("Lua Function Prototype"));
|
||||
static bool IsFunctionPin(const UEdGraphPin *Pin) {
|
||||
return (Pin->PinName == FunctionPinName);
|
||||
}
|
||||
|
||||
static const FName InvokeOrProbePinName(TEXT("Invoke or Probe"));
|
||||
static bool IsInvokeOrProbePin(const UEdGraphPin *Pin) {
|
||||
return (Pin->PinName == InvokeOrProbePinName);
|
||||
}
|
||||
|
||||
static const FName PlacePinName(TEXT("Place Tangible"));
|
||||
static bool IsPlacePin(const UEdGraphPin *Pin) {
|
||||
return (Pin->PinName == PlacePinName);
|
||||
}
|
||||
|
||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
||||
|
||||
static FEdGraphPinType GetPinType(const FProperty *Property)
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
@@ -107,7 +90,6 @@ static FEdGraphPinType GetPinType(const FProperty *Property)
|
||||
}
|
||||
|
||||
|
||||
|
||||
UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
@@ -154,29 +136,6 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
LuaFunctionPrototype = TEXT("class.func(int arg1, int arg2) : int ret1, int ret2");
|
||||
}
|
||||
|
||||
if (FindPin(UEdGraphSchema_K2::PN_Execute) == nullptr) {
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
||||
}
|
||||
|
||||
if (FindPin(UEdGraphSchema_K2::PN_Then) == nullptr) {
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
||||
}
|
||||
|
||||
if (FindPin(FunctionPinName, EGPD_Input) == nullptr) {
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FunctionPinName);
|
||||
P->DefaultValue = LuaFunctionPrototype;
|
||||
}
|
||||
|
||||
if (FindPin(InvokeOrProbePinName, EGPD_Input) == nullptr) {
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxInvokeOrProbe>(), InvokeOrProbePinName);
|
||||
P->DefaultValue = TEXT("Probe");
|
||||
P->AutogeneratedDefaultValue = P->DefaultValue;
|
||||
}
|
||||
|
||||
if (FindPin(PlacePinName, EGPD_Input) == nullptr) {
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, AActor::StaticClass(), PlacePinName);
|
||||
}
|
||||
|
||||
// Parse the lua function prototype.
|
||||
FlxParsedProto ParsedProto(LuaFunctionPrototype);
|
||||
if (!ParsedProto.ErrorMessage.IsEmpty())
|
||||
@@ -186,26 +145,60 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
ErrorMsg = FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage);
|
||||
}
|
||||
|
||||
// Transfer all Existing argument and return value pins to the Old Pins Maps.
|
||||
TMap<FName, UEdGraphPin *> OldArgumentPins;
|
||||
TMap<FName, UEdGraphPin *> OldReturnValuePins;
|
||||
// Transfer all pins to the old pins map and clear the pin list.
|
||||
TMap<FName, UEdGraphPin *> OldPins;
|
||||
for (auto It = Pins.CreateIterator(); It; ++It)
|
||||
{
|
||||
UEdGraphPin* CheckPin = *It;
|
||||
if (IsArgumentPin(CheckPin)) {
|
||||
OldArgumentPins.Add(CheckPin->PinName, CheckPin);
|
||||
It.RemoveCurrent();
|
||||
}
|
||||
if (IsReturnValuePin(CheckPin)) {
|
||||
OldReturnValuePins.Add(CheckPin->PinName, CheckPin);
|
||||
It.RemoveCurrent();
|
||||
OldPins.Add(CheckPin->PinName, CheckPin);
|
||||
}
|
||||
Pins.Empty();
|
||||
|
||||
// KeepPin is a function that moves a pin from the old pins
|
||||
// map back onto the pins list.
|
||||
auto KeepPin = [&](FName Name, FEdGraphPinType Type = FEdGraphPinType()) -> bool
|
||||
{
|
||||
UEdGraphPin **OldPin = OldPins.Find(Name);
|
||||
if ((OldPin != nullptr) && (((*OldPin)->PinType == Type) || (Type.PinCategory == FName())))
|
||||
{
|
||||
Pins.Emplace(*OldPin);
|
||||
OldPins.Remove(Name);
|
||||
}
|
||||
return OldPin != nullptr;
|
||||
};
|
||||
|
||||
if (!KeepPin(UEdGraphSchema_K2::PN_Execute))
|
||||
{
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
||||
}
|
||||
|
||||
if (!KeepPin(UEdGraphSchema_K2::PN_Then))
|
||||
{
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
||||
}
|
||||
|
||||
if (!KeepPin(FunctionPinName))
|
||||
{
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FunctionPinName);
|
||||
P->DefaultValue = LuaFunctionPrototype;
|
||||
}
|
||||
|
||||
if (!KeepPin(InvokeOrProbePinName))
|
||||
{
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxInvokeOrProbe>(), InvokeOrProbePinName);
|
||||
P->DefaultValue = TEXT("Probe");
|
||||
P->AutogeneratedDefaultValue = P->DefaultValue;
|
||||
}
|
||||
|
||||
if (!KeepPin(PlacePinName))
|
||||
{
|
||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, AActor::StaticClass(), PlacePinName);
|
||||
}
|
||||
|
||||
// Create Argument pins in the correct order, reusing old pins where possible.
|
||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.Arguments)
|
||||
{
|
||||
FName PrefixedName = ArgumentNameAddPrefix(Pin.Name);
|
||||
FName PrefixedName = AddPrefix(Pin.Name, 'A');
|
||||
UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type);
|
||||
if (Accessor == nullptr) {
|
||||
bHasCompilerMessage = true;
|
||||
@@ -214,11 +207,8 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
continue;
|
||||
}
|
||||
FEdGraphPinType PinType = GetPinType(Accessor->FindPropertyByName(TEXT("Value")));
|
||||
UEdGraphPin **OldPin = OldArgumentPins.Find(PrefixedName);
|
||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||
Pins.Emplace(*OldPin);
|
||||
OldArgumentPins.Remove(PrefixedName);
|
||||
} else {
|
||||
if (!KeepPin(PrefixedName, PinType))
|
||||
{
|
||||
CreatePin(EGPD_Input, PinType, PrefixedName);
|
||||
}
|
||||
}
|
||||
@@ -226,7 +216,7 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
// Create ReturnValue pins in the correct order, reusing old pins where possible.
|
||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
||||
{
|
||||
FName PrefixedName = ReturnValueNameAddPrefix(Pin.Name);
|
||||
FName PrefixedName = AddPrefix(Pin.Name, 'R');
|
||||
UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type);
|
||||
if (Accessor == nullptr) {
|
||||
bHasCompilerMessage = true;
|
||||
@@ -235,28 +225,27 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
continue;
|
||||
}
|
||||
FEdGraphPinType PinType = GetPinType(Accessor->GetReturnProperty());
|
||||
UEdGraphPin **OldPin = OldReturnValuePins.Find(PrefixedName);
|
||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||
Pins.Emplace(*OldPin);
|
||||
OldReturnValuePins.Remove(PrefixedName);
|
||||
} else {
|
||||
if (!KeepPin(PrefixedName, PinType))
|
||||
{
|
||||
CreatePin(EGPD_Output, PinType, PrefixedName);
|
||||
}
|
||||
}
|
||||
|
||||
if (ParsedProto.ExtraReturnValues)
|
||||
{
|
||||
if (!KeepPin(ExtraResultsPinName))
|
||||
{
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UlxLuaValues::StaticClass(), ExtraResultsPinName);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any unused pins.
|
||||
for (auto &iter : OldArgumentPins)
|
||||
for (auto &iter : OldPins)
|
||||
{
|
||||
iter.Value->Modify();
|
||||
iter.Value->MarkAsGarbage();
|
||||
}
|
||||
for (auto &iter : OldReturnValuePins)
|
||||
{
|
||||
iter.Value->Modify();
|
||||
iter.Value->MarkAsGarbage();
|
||||
}
|
||||
OldArgumentPins.Empty();
|
||||
OldReturnValuePins.Empty();
|
||||
OldPins.Empty();
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +263,7 @@ FText UK2Node_LuaCall::GetPinDisplayName(const UEdGraphPin* Pin) const
|
||||
}
|
||||
|
||||
// Many pins can go unlabeled if they have default values.
|
||||
if (IsFunctionPin(Pin) || IsInvokeOrProbePin(Pin))
|
||||
if ((Pin->PinName == FunctionPinName) || (Pin->PinName == InvokeOrProbePinName))
|
||||
{
|
||||
if (Pin->LinkedTo.Num() == 0)
|
||||
{
|
||||
@@ -283,13 +272,15 @@ FText UK2Node_LuaCall::GetPinDisplayName(const UEdGraphPin* Pin) const
|
||||
}
|
||||
|
||||
// For argument pins, we must strip off the Argument Pin Prefix.
|
||||
if (IsArgumentPin(Pin)) {
|
||||
return FText::FromString(ArgumentNameRemovePrefix(Pin->PinName));
|
||||
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 (IsReturnValuePin(Pin)) {
|
||||
return FText::FromString(ReturnValueNameRemovePrefix(Pin->PinName));
|
||||
if (IsPrefix(Pin, 'R'))
|
||||
{
|
||||
return FText::FromString(RemovePrefix(Pin->PinName, 'R'));
|
||||
}
|
||||
|
||||
// Otherwise, just return the Pin Name the normal way.
|
||||
@@ -309,7 +300,7 @@ void UK2Node_LuaCall::PinConnectionListChanged(UEdGraphPin* Pin)
|
||||
|
||||
void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||
{
|
||||
if(IsFunctionPin(Pin))
|
||||
if(Pin->PinName == FunctionPinName)
|
||||
{
|
||||
LuaFunctionPrototype = Pin->DefaultValue;
|
||||
CreateCorrectPins();
|
||||
@@ -356,7 +347,7 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
||||
// Add Packing operations for all argument pins.
|
||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.Arguments)
|
||||
{
|
||||
UEdGraphPin *Pin = FindPinChecked(ArgumentNameAddPrefix(PinInfo.Name));
|
||||
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'A'));
|
||||
UFunction *PackingFunc = UlxLuaCallLibrary::GetArgumentPacker(PinInfo.Type);
|
||||
if (PackingFunc == nullptr)
|
||||
{
|
||||
@@ -378,10 +369,10 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
||||
PrevNode->GetThenPin()->MakeLinkTo(ActionNode->GetExecPin());
|
||||
PrevNode = ActionNode;
|
||||
|
||||
// Add Unpacking operations for all argument pins.
|
||||
// Add Unpacking operations for all return value pins.
|
||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
||||
{
|
||||
UEdGraphPin *Pin = FindPinChecked(ReturnValueNameAddPrefix(PinInfo.Name));
|
||||
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'R'));
|
||||
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
||||
if (UnpackingFunc == nullptr)
|
||||
{
|
||||
@@ -395,16 +386,26 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
||||
PrevNode = UnpackNode;
|
||||
}
|
||||
|
||||
// Make sure we didn't have return values for an invoke.
|
||||
if (IsInvoke && (ParsedProto.ReturnValues.Num() > 0))
|
||||
// If there is an extra results pin, hook it up.
|
||||
if (ParsedProto.ExtraReturnValues)
|
||||
{
|
||||
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
||||
UEdGraphPin *Pin = FindPinChecked(ExtraResultsPinName);
|
||||
UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(LuaCallLibraryFunction(LuaCallGetRest));
|
||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue));
|
||||
PrevNode->GetThenPin()->MakeLinkTo(UnpackNode->GetExecPin());
|
||||
PrevNode = UnpackNode;
|
||||
}
|
||||
|
||||
// Link up the Exec pins.
|
||||
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *PrevNode->GetThenPin());
|
||||
|
||||
// Make sure we didn't have return values for an invoke.
|
||||
if (IsInvoke && ((ParsedProto.ReturnValues.Num() > 0) || (ParsedProto.ExtraReturnValues)))
|
||||
{
|
||||
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
||||
}
|
||||
|
||||
BreakAllNodeLinks();
|
||||
}
|
||||
|
||||
@@ -457,14 +458,14 @@ UK2Node::ERedirectType UK2Node_LuaCall::DoPinsMatchForReconstruction(const UEdGr
|
||||
bool UK2Node_LuaCall::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
||||
{
|
||||
// The function pin cannot be connected.
|
||||
if (IsFunctionPin(MyPin))
|
||||
if (MyPin->PinName == FunctionPinName)
|
||||
{
|
||||
OutReason = LOCTEXT("Error_FunctionPrototypeMustBeHardwired", "Lua function prototype must be a hardwired constant.").ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
// The invoke-or-probe pin cannot be connected.
|
||||
if (IsInvokeOrProbePin(MyPin))
|
||||
if (MyPin->PinName == InvokeOrProbePinName)
|
||||
{
|
||||
OutReason = LOCTEXT("Error_InvokeOrProbeMustBeHardwired", "Invoke vs Probe must be a hardwired constant.").ToString();
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user