A lot of work on the Lua Call interface and some work on animation queues
This commit is contained in:
@@ -91,160 +91,43 @@ static bool IsPlacePin(const UEdGraphPin *Pin) {
|
||||
return (Pin->PinName == PlacePinName);
|
||||
}
|
||||
|
||||
// A parser for lua function prototypes.
|
||||
//
|
||||
struct FlxParsedProto {
|
||||
FString ErrorMessage;
|
||||
TArray<FString> Tokens;
|
||||
int NextToken;
|
||||
FString ClassName;
|
||||
FString FunctionName;
|
||||
TArray<FString> Arguments;
|
||||
TArray<FString> ReturnValues;
|
||||
bool ExtraReturnValues;
|
||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
||||
|
||||
// Check the next token to see if it's exactly equal to text.
|
||||
//
|
||||
bool IsLiteral(const TCHAR *text);
|
||||
|
||||
// Check the next token to see if it's an identifier.
|
||||
//
|
||||
bool IsIdent();
|
||||
|
||||
// Empty out the FlxParsedProto.
|
||||
//
|
||||
void Empty();
|
||||
|
||||
// Make a syntax error message, using the tokens.
|
||||
//
|
||||
void Syntax();
|
||||
|
||||
// Parse a function prototype.
|
||||
//
|
||||
void Parse(const FString &proto);
|
||||
|
||||
// Construct with a prototype.
|
||||
//
|
||||
FlxParsedProto(const FString &str) { Parse(str); }
|
||||
};
|
||||
|
||||
bool FlxParsedProto::IsLiteral(const TCHAR *text) {
|
||||
return ((NextToken < Tokens.Num()) && (Tokens[NextToken] == text));
|
||||
static FEdGraphPinType GetPinType(const FProperty *Property)
|
||||
{
|
||||
FEdGraphPinType PinType;
|
||||
bool IsWeak;
|
||||
FName PinCat, PinSubCat;
|
||||
UObject *PinSubCatObj = nullptr;
|
||||
UEdGraphSchema_K2::GetPropertyCategoryInfo(Property, PinCat, PinSubCat, PinSubCatObj, IsWeak);
|
||||
PinType.PinCategory = PinCat;
|
||||
PinType.PinSubCategory = PinSubCat;
|
||||
PinType.PinSubCategoryObject = PinSubCatObj;
|
||||
return PinType;
|
||||
}
|
||||
|
||||
bool FlxParsedProto::IsIdent() {
|
||||
return ((NextToken < Tokens.Num()) && (FChar::IsAlpha(Tokens[NextToken][0])));
|
||||
}
|
||||
|
||||
void FlxParsedProto::Empty() {
|
||||
ErrorMessage = TEXT("");
|
||||
Tokens.Empty();
|
||||
NextToken = 0;
|
||||
ClassName = TEXT("");
|
||||
FunctionName = TEXT("");
|
||||
Arguments.Empty();
|
||||
ReturnValues.Empty();
|
||||
ExtraReturnValues = false;
|
||||
}
|
||||
|
||||
void FlxParsedProto::Syntax() {
|
||||
FString Message;
|
||||
if (Tokens.Num() == 0) {
|
||||
Message = TEXT("Function prototype cannot be blank");
|
||||
}
|
||||
for (int i = 0; i < Tokens.Num(); i++) {
|
||||
if (i == NextToken) {
|
||||
Message.Append(TEXT(" ? "));
|
||||
} else {
|
||||
if ((i > 0) && (FChar::IsAlpha(Tokens[i][0])) && (FChar::IsAlpha(Tokens[i-1][0]))) {
|
||||
Message.Append(TEXT(" "));
|
||||
}
|
||||
}
|
||||
Message.Append(Tokens[i]);
|
||||
}
|
||||
Empty();
|
||||
ErrorMessage = Message;
|
||||
}
|
||||
|
||||
void FlxParsedProto::Parse(const FString &str) {
|
||||
Empty();
|
||||
|
||||
// Step one: tokenize.
|
||||
int offset = 0;
|
||||
while (offset < str.Len()) {
|
||||
TCHAR c = str[offset];
|
||||
if (FChar::IsWhitespace(c)) {
|
||||
offset++;
|
||||
} else if (FChar::IsAlpha(c)) {
|
||||
int lo = offset;
|
||||
while ((offset < str.Len()) && FChar::IsAlnum(str[offset])) offset++;
|
||||
Tokens.Add(str.Mid(lo, offset-lo));
|
||||
} else if (str.Mid(offset, 3) == TEXT("...")) {
|
||||
Tokens.Add(str.Mid(offset, 3));
|
||||
offset += 3;
|
||||
} else if (FChar::IsPunct(c)) {
|
||||
Tokens.Add(str.Mid(offset, 1));
|
||||
offset += 1;
|
||||
} else {
|
||||
Empty();
|
||||
ErrorMessage = FString::Printf(TEXT("%s ? %s"), *str.Mid(0, offset), *str.Mid(offset));
|
||||
return;
|
||||
}
|
||||
}
|
||||
NextToken = 0;
|
||||
|
||||
// Step two: Parse.
|
||||
if (!IsLiteral(TEXT("function"))) return Syntax();
|
||||
NextToken++;
|
||||
if (!IsLiteral(TEXT("*")) && !IsIdent()) return Syntax();
|
||||
ClassName = Tokens[NextToken++];
|
||||
if (!IsLiteral(TEXT("."))) return Syntax();
|
||||
NextToken++;
|
||||
if (!IsIdent()) return Syntax();
|
||||
FunctionName = Tokens[NextToken++];
|
||||
if (!IsLiteral(TEXT("("))) return Syntax();
|
||||
NextToken++;
|
||||
if (IsIdent()) {
|
||||
while (true) {
|
||||
if (!IsIdent()) return Syntax();
|
||||
Arguments.Add(Tokens[NextToken++]);
|
||||
if (!IsLiteral(TEXT(","))) break;
|
||||
NextToken++;
|
||||
}
|
||||
}
|
||||
if (!IsLiteral(TEXT(")"))) return Syntax();
|
||||
NextToken++;
|
||||
if (IsLiteral(TEXT(":"))) {
|
||||
NextToken++;
|
||||
while (true) {
|
||||
if (IsLiteral(TEXT("..."))) {
|
||||
ExtraReturnValues = true;
|
||||
NextToken++;
|
||||
break;
|
||||
} else if (IsIdent()) {
|
||||
ReturnValues.Add(Tokens[NextToken++]);
|
||||
if (!IsLiteral(TEXT(","))) break;
|
||||
NextToken++;
|
||||
} else {
|
||||
return Syntax();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NextToken != Tokens.Num()) return Syntax();
|
||||
}
|
||||
|
||||
UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
NodeTooltip = LOCTEXT("NodeTooltip",
|
||||
"Probe or Invoke a Lua function.\n"
|
||||
FString ArgTypes = UlxLuaCallLibrary::AllKnownArgumentTypes();
|
||||
FString RetTypes = UlxLuaCallLibrary::AllKnownReturnValueTypes();
|
||||
NodeTooltip = FText::FromString(FString::Printf(TEXT(
|
||||
"Call a Lua function.\n"
|
||||
"\n"
|
||||
"The lua function prototype must be a hardwired string which must look like\n"
|
||||
"one of the following:"
|
||||
"one of the following:\n"
|
||||
"\n"
|
||||
" function cname.fname(arg1, arg2)"
|
||||
" function cname.fname(arg1, arg2) : ret1, ret2\n"
|
||||
" function cname.fname(arg1, arg2) : ret1, ret2, ...\n"
|
||||
" classname.funcname(int arg1, int arg2)\n"
|
||||
" classname.funcname(int arg1, int arg2) : int ret1, int ret2\n"
|
||||
" classname.funcname(int arg1, int arg2) : int ret1, int ret2, ...\n"
|
||||
"\n"
|
||||
"You must specify types for the argument and return value pins. The:\n"
|
||||
"types that you may specify are:\n"
|
||||
"\n"
|
||||
"Arguments: %s\n"
|
||||
"Return Values: %s\n"
|
||||
"\n"
|
||||
"The prototype is parsed to determine what lua function to call.\n"
|
||||
"The lua call node will automatically add pins for the arguments and\n"
|
||||
@@ -255,12 +138,7 @@ UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
||||
"\n"
|
||||
"Optionally, you may use the * wildcard for the classname. In that\n"
|
||||
"case, the class of the 'place' tangible will be used.\n"
|
||||
"\n"
|
||||
"Argument and return value pins have wildcard types initially, you can\n"
|
||||
"hook them to inputs and outputs of the following types:\n"
|
||||
"\n"
|
||||
" string, name, float, boolean, vector\n"
|
||||
"\n");
|
||||
"\n"), *ArgTypes, *RetTypes));
|
||||
}
|
||||
|
||||
void UK2Node_LuaCall::AllocateDefaultPins()
|
||||
@@ -273,7 +151,7 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
{
|
||||
if (LuaFunctionPrototype.IsEmpty())
|
||||
{
|
||||
LuaFunctionPrototype = TEXT("function class.func(arg1, arg2) : ret1, ret2");
|
||||
LuaFunctionPrototype = TEXT("class.func(int arg1, int arg2) : int ret1, int ret2");
|
||||
}
|
||||
|
||||
if (FindPin(UEdGraphSchema_K2::PN_Execute) == nullptr) {
|
||||
@@ -325,28 +203,44 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
}
|
||||
|
||||
// Create Argument pins in the correct order, reusing old pins where possible.
|
||||
for (const FString& Name : ParsedProto.Arguments)
|
||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.Arguments)
|
||||
{
|
||||
FName PrefixedName = ArgumentNameAddPrefix(Name);
|
||||
FName PrefixedName = ArgumentNameAddPrefix(Pin.Name);
|
||||
UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type);
|
||||
if (Accessor == nullptr) {
|
||||
bHasCompilerMessage = true;
|
||||
ErrorType = EMessageSeverity::Error;
|
||||
ErrorMsg = FString::Printf(TEXT("Unknown argument type: %s"), *Pin.Type);
|
||||
continue;
|
||||
}
|
||||
FEdGraphPinType PinType = GetPinType(Accessor->FindPropertyByName(TEXT("Value")));
|
||||
UEdGraphPin **OldPin = OldArgumentPins.Find(PrefixedName);
|
||||
if (OldPin != nullptr) {
|
||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||
Pins.Emplace(*OldPin);
|
||||
OldArgumentPins.Remove(PrefixedName);
|
||||
} else {
|
||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Wildcard, PrefixedName);
|
||||
CreatePin(EGPD_Input, PinType, PrefixedName);
|
||||
}
|
||||
}
|
||||
|
||||
// Create ReturnValue pins in the correct order, reusing old pins where possible.
|
||||
for (const FString& Name : ParsedProto.ReturnValues)
|
||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
||||
{
|
||||
FName PrefixedName = ReturnValueNameAddPrefix(Name);
|
||||
FName PrefixedName = ReturnValueNameAddPrefix(Pin.Name);
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
FEdGraphPinType PinType = GetPinType(Accessor->GetReturnProperty());
|
||||
UEdGraphPin **OldPin = OldReturnValuePins.Find(PrefixedName);
|
||||
if (OldPin != nullptr) {
|
||||
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||
Pins.Emplace(*OldPin);
|
||||
OldReturnValuePins.Remove(PrefixedName);
|
||||
} else {
|
||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Wildcard, PrefixedName);
|
||||
CreatePin(EGPD_Output, PinType, PrefixedName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,53 +260,9 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
||||
}
|
||||
|
||||
|
||||
void UK2Node_LuaCall::SynchronizePinType(UEdGraphPin* Pin)
|
||||
{
|
||||
if (IsArgumentPin(Pin) || IsReturnValuePin(Pin))
|
||||
{
|
||||
const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema());
|
||||
|
||||
bool bPinTypeChanged = false;
|
||||
if (Pin->LinkedTo.Num() == 0)
|
||||
{
|
||||
static const FEdGraphPinType WildcardPinType = FEdGraphPinType(UEdGraphSchema_K2::PC_Wildcard, NAME_None, nullptr, EPinContainerType::None, false, FEdGraphTerminalType());
|
||||
|
||||
// Ensure wildcard
|
||||
if (Pin->PinType != WildcardPinType)
|
||||
{
|
||||
Pin->PinType = WildcardPinType;
|
||||
bPinTypeChanged = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UEdGraphPin* OtherPin = Pin->LinkedTo[0];
|
||||
|
||||
// Take the type of the connected pin
|
||||
if (Pin->PinType != OtherPin->PinType)
|
||||
{
|
||||
Pin->PinType = OtherPin->PinType;
|
||||
bPinTypeChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bPinTypeChanged)
|
||||
{
|
||||
// Let the graph know to refresh
|
||||
GetGraph()->NotifyNodeChanged(this);
|
||||
|
||||
UBlueprint* Blueprint = GetBlueprint();
|
||||
if (!Blueprint->bBeingCompiled)
|
||||
{
|
||||
FBlueprintEditorUtils::MarkBlueprintAsModified(Blueprint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FText UK2Node_LuaCall::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||
{
|
||||
return LOCTEXT("LuaCall_Title", "Probe or Invoke a Lua Function");
|
||||
return LOCTEXT("LuaCall_Title", "Call a Lua Function");
|
||||
}
|
||||
|
||||
FText UK2Node_LuaCall::GetPinDisplayName(const UEdGraphPin* Pin) const
|
||||
@@ -455,7 +305,6 @@ void UK2Node_LuaCall::PostEditChangeProperty(struct FPropertyChangedEvent& Prope
|
||||
void UK2Node_LuaCall::PinConnectionListChanged(UEdGraphPin* Pin)
|
||||
{
|
||||
Modify();
|
||||
SynchronizePinType(Pin);
|
||||
}
|
||||
|
||||
void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||
@@ -468,12 +317,6 @@ void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||
}
|
||||
}
|
||||
|
||||
void UK2Node_LuaCall::PinTypeChanged(UEdGraphPin* Pin)
|
||||
{
|
||||
SynchronizePinType(Pin);
|
||||
Super::PinTypeChanged(Pin);
|
||||
}
|
||||
|
||||
FText UK2Node_LuaCall::GetTooltipText() const
|
||||
{
|
||||
return NodeTooltip;
|
||||
@@ -482,55 +325,11 @@ FText UK2Node_LuaCall::GetTooltipText() const
|
||||
void UK2Node_LuaCall::PostReconstructNode()
|
||||
{
|
||||
Super::PostReconstructNode();
|
||||
|
||||
UEdGraph* OuterGraph = GetGraph();
|
||||
if (!IsTemplate() && OuterGraph && OuterGraph->Schema) {
|
||||
for (UEdGraphPin* CurrentPin : Pins)
|
||||
{
|
||||
SynchronizePinType(CurrentPin);
|
||||
}
|
||||
}
|
||||
|
||||
CreateCorrectPins();
|
||||
}
|
||||
|
||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
||||
|
||||
static UFunction *GetArgumentPackingFunction(const FEdGraphPinType &Type)
|
||||
{
|
||||
if (Type.PinCategory == UEdGraphSchema_K2::PC_Real)
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddFloatParameter);
|
||||
}
|
||||
if (Type.PinCategory == UEdGraphSchema_K2::PC_Int)
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddIntParameter);
|
||||
}
|
||||
else if (Type.PinCategory == UEdGraphSchema_K2::PC_Boolean)
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddBooleanParameter);
|
||||
}
|
||||
else if (Type.PinCategory == UEdGraphSchema_K2::PC_Name)
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddNameParameter);
|
||||
}
|
||||
else if (Type.PinCategory == UEdGraphSchema_K2::PC_String)
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddStringParameter);
|
||||
}
|
||||
else if ((Type.PinCategory == UEdGraphSchema_K2::PC_Struct) && (Type.PinSubCategoryObject == TBaseStructure<FVector>::Get()))
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddVectorParameter);
|
||||
}
|
||||
else if ((Type.PinCategory == UEdGraphSchema_K2::PC_Struct) && (Type.PinSubCategoryObject == TBaseStructure<FVector2D>::Get()))
|
||||
{
|
||||
return LuaCallLibraryFunction(LuaCallAddVector2DParameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
||||
{
|
||||
@@ -555,38 +354,56 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
||||
UK2Node_CallFunction* PrevNode = BeginNode;
|
||||
|
||||
// Add Packing operations for all argument pins.
|
||||
for (UEdGraphPin* Pin : Pins)
|
||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.Arguments)
|
||||
{
|
||||
if (IsArgumentPin(Pin))
|
||||
UEdGraphPin *Pin = FindPinChecked(ArgumentNameAddPrefix(PinInfo.Name));
|
||||
UFunction *PackingFunc = UlxLuaCallLibrary::GetArgumentPacker(PinInfo.Type);
|
||||
if (PackingFunc == nullptr)
|
||||
{
|
||||
UFunction *PackingFunc = GetArgumentPackingFunction(Pin->PinType);
|
||||
if (PackingFunc != nullptr)
|
||||
{
|
||||
UK2Node_CallFunction *PackNode = MakeCallFunctionNode(PackingFunc);
|
||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *PackNode->FindPinChecked(TEXT("Value")));
|
||||
PrevNode->GetThenPin()->MakeLinkTo(PackNode->GetExecPin());
|
||||
PrevNode = PackNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
FText PinName = GetPinDisplayName(Pin);
|
||||
FText PinType = FText::FromName(Pin->PinType.PinCategory);
|
||||
FText Error = FText::Format(LOCTEXT("Error_UnexpectedPinType", "Pin '{0}' has an unexpected type: {1}"), PinName, PinType);
|
||||
CompilerContext.MessageLog.Error(*Error.ToString());
|
||||
}
|
||||
// This codepath should be unreachable, but just in case.
|
||||
CompilerContext.MessageLog.Error(TEXT("All argument pins must have known types"));
|
||||
continue;
|
||||
}
|
||||
UK2Node_CallFunction *PackNode = MakeCallFunctionNode(PackingFunc);
|
||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *PackNode->FindPinChecked(TEXT("Value")));
|
||||
PrevNode->GetThenPin()->MakeLinkTo(PackNode->GetExecPin());
|
||||
PrevNode = PackNode;
|
||||
}
|
||||
|
||||
// Add the invoke or probe node.
|
||||
bool IsInvoke = (FindPin(InvokeOrProbePinName, EGPD_Input)->DefaultValue == TEXT("Invoke"));
|
||||
bool IsInvoke = (FindPinChecked(InvokeOrProbePinName, EGPD_Input)->DefaultValue == TEXT("Invoke"));
|
||||
UFunction *Action = IsInvoke ? LuaCallLibraryFunction(LuaCallInvoke) : LuaCallLibraryFunction(LuaCallProbe);
|
||||
UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(Action);
|
||||
CompilerContext.MovePinLinksToIntermediate(*FindPin(PlacePinName, EGPD_Input), *ActionNode->FindPinChecked(TEXT("Place")));
|
||||
PrevNode->GetThenPin()->MakeLinkTo(ActionNode->GetExecPin());
|
||||
PrevNode = ActionNode;
|
||||
|
||||
// Add Unpacking operations for all argument pins.
|
||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
||||
{
|
||||
UEdGraphPin *Pin = FindPinChecked(ReturnValueNameAddPrefix(PinInfo.Name));
|
||||
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
||||
if (UnpackingFunc == nullptr)
|
||||
{
|
||||
// This codepath should be unreachable, but just in case.
|
||||
CompilerContext.MessageLog.Error(TEXT("All return value pins must have known types."));
|
||||
continue;
|
||||
}
|
||||
UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(UnpackingFunc);
|
||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_ReturnValue));
|
||||
PrevNode->GetThenPin()->MakeLinkTo(UnpackNode->GetExecPin());
|
||||
PrevNode = UnpackNode;
|
||||
}
|
||||
|
||||
// Make sure we didn't have return values for an invoke.
|
||||
if (IsInvoke && (ParsedProto.ReturnValues.Num() > 0))
|
||||
{
|
||||
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
||||
}
|
||||
|
||||
// Link up the Exec pins.
|
||||
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *ActionNode->GetThenPin());
|
||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *PrevNode->GetThenPin());
|
||||
|
||||
BreakAllNodeLinks();
|
||||
}
|
||||
@@ -653,21 +470,9 @@ bool UK2Node_LuaCall::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEd
|
||||
return true;
|
||||
}
|
||||
|
||||
// Argument input pins may only be connected to packable types.
|
||||
if (IsArgumentPin(MyPin))
|
||||
{
|
||||
UFunction *Packer = GetArgumentPackingFunction(OtherPin->PinType);
|
||||
if (Packer == nullptr)
|
||||
{
|
||||
OutReason = LOCTEXT("Error_InvalidArgumentType", "Lua Call Arguments may be float, boolean, string, name, or vector.").ToString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return Super::IsConnectionDisallowed(MyPin, OtherPin, OutReason);
|
||||
}
|
||||
|
||||
|
||||
void UK2Node_LuaCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
||||
{
|
||||
// actions get registered under specific object-keys; the idea is that
|
||||
|
||||
Reference in New Issue
Block a user