A lot of work on the Lua Call interface and some work on animation queues
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -114,7 +114,7 @@ void UK2Node_FormatError::CreateCorrectPins()
|
|||||||
|
|
||||||
if (FindPin(DisplayDurationPinName, EGPD_Input) == nullptr) {
|
if (FindPin(DisplayDurationPinName, EGPD_Input) == nullptr) {
|
||||||
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxErrorDisplayDuration>(), DisplayDurationPinName);
|
UEdGraphPin *P = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Byte, StaticEnum<ElxErrorDisplayDuration>(), DisplayDurationPinName);
|
||||||
P->DefaultValue = TEXT("No_Display");
|
P->DefaultValue = TEXT("No Show");
|
||||||
P->AutogeneratedDefaultValue = P->DefaultValue;
|
P->AutogeneratedDefaultValue = P->DefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "LuaCall.h"
|
#include "LuaCall.h"
|
||||||
#include "IntegrationGameModeBase.h"
|
#include "IntegrationGameModeBase.h"
|
||||||
|
#include "EdGraphSchema_K2.h"
|
||||||
|
|
||||||
static void FatalBlueprintError(const TCHAR *message) {
|
static void FatalBlueprintError(const TCHAR *message) {
|
||||||
FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::FatalError, FText::FromString(FString(message)));
|
FBlueprintExceptionInfo ExceptionInfo(EBlueprintExceptionType::FatalError, FText::FromString(FString(message)));
|
||||||
@@ -43,6 +44,164 @@ static constexpr uint64_t ParseNameAsToken(std::string_view str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// The lua function prototype parser.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
bool FlxParsedProto::IsLiteral(const TCHAR *text) {
|
||||||
|
return ((NextToken < Tokens.Num()) && (Tokens[NextToken] == text));
|
||||||
|
}
|
||||||
|
|
||||||
|
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("*")) && !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();
|
||||||
|
FString Type = Tokens[NextToken++];
|
||||||
|
if (!IsIdent()) return Syntax();
|
||||||
|
FString Name = Tokens[NextToken++];
|
||||||
|
Arguments.Add(Pin(Type, Name));
|
||||||
|
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()) {
|
||||||
|
FString Type = Tokens[NextToken++];
|
||||||
|
if (!IsIdent()) return Syntax();
|
||||||
|
FString Name = Tokens[NextToken++];
|
||||||
|
ReturnValues.Add(Pin(Type, Name));
|
||||||
|
if (!IsLiteral(TEXT(","))) break;
|
||||||
|
NextToken++;
|
||||||
|
} else {
|
||||||
|
return Syntax();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NextToken != Tokens.Num()) return Syntax();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// General functions of the Lua Call Library.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UFunction *UlxLuaCallLibrary::GetArgumentPacker(const FString &Type)
|
||||||
|
{
|
||||||
|
FString LType = Type.ToLower();
|
||||||
|
FName PackerName(FString::Printf(TEXT("LuaCallArgument_%s"), *LType));
|
||||||
|
return UlxLuaCallLibrary::StaticClass()->FindFunctionByName(PackerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
UFunction *UlxLuaCallLibrary::GetReturnValueUnpacker(const FString &Type)
|
||||||
|
{
|
||||||
|
FString LType = Type.ToLower();
|
||||||
|
FName PackerName(FString::Printf(TEXT("LuaCallReturnValue_%s"), *LType));
|
||||||
|
return UlxLuaCallLibrary::StaticClass()->FindFunctionByName(PackerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
FString UlxLuaCallLibrary::AllFunctionsWithPrefix(const TCHAR *Prefix)
|
||||||
|
{
|
||||||
|
FString Result;
|
||||||
|
|
||||||
|
for ( TFieldIterator<UFunction> FIT ( UlxLuaCallLibrary::StaticClass(), EFieldIteratorFlags::ExcludeSuper); FIT; ++FIT)
|
||||||
|
{
|
||||||
|
UFunction* Function = *FIT;
|
||||||
|
FString Name = Function->GetName();
|
||||||
|
if (Name.RemoveFromStart(Prefix))
|
||||||
|
{
|
||||||
|
if (!Result.IsEmpty()) Result += TEXT(", ");
|
||||||
|
Result += Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// General Lua-Callable functions of the Lua Call Library.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname) {
|
void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, const FString &fname) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
@@ -53,71 +212,6 @@ void UlxLuaCallLibrary::LuaCallBegin(UObject *context, const FString &cname, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddStringParameter(UObject *context, const FString &pstring) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
|
||||||
sb.write_string(pstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddNameParameter(UObject *context, const FName &pname) {
|
|
||||||
FTCHARToUTF8 utf8str(pname.ToString());
|
|
||||||
std::string_view namestr(utf8str.Get(), utf8str.Length());
|
|
||||||
uint64_t tokvalue = ParseNameAsToken(namestr);
|
|
||||||
if ((tokvalue == 0) && !namestr.empty()) {
|
|
||||||
FatalBlueprintError(TEXT("Names passed to lua must be short, and must contain only lowercase and digits"));
|
|
||||||
}
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::TOKEN);
|
|
||||||
sb.write_string(namestr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddFloatParameter(UObject *context, double pfloat) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
|
||||||
sb.write_double(pfloat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddIntParameter(UObject *context, int value) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
|
||||||
sb.write_double(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddVectorParameter(UObject *context, const FVector &pvector) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
|
||||||
sb.write_fvector(pvector);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddVector2DParameter(UObject *context, const FVector2D &pvector) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
|
||||||
sb.write_double(pvector.X);
|
|
||||||
sb.write_double(pvector.Y);
|
|
||||||
sb.write_double(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallAddBooleanParameter(UObject *context, bool pbool) {
|
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
|
||||||
CheckNotEmpty(sb);
|
|
||||||
sb.write_simple_dynamic_tag(SimpleDynamicTag::BOOLEAN);
|
|
||||||
sb.write_bool(pbool);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) {
|
void UlxLuaCallLibrary::LuaCallInvoke(UObject *context, AActor *place) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
@@ -166,7 +260,85 @@ ELpxSimpleDynamicTag UlxLuaCallLibrary::LuaCallNextResultType(UObject *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FString UlxLuaCallLibrary::LuaCallGetStringResult(UObject *context) {
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Argument Packing functions
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_string(UObject *context, const FString &pstring) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::STRING);
|
||||||
|
sb.write_string(pstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_name(UObject *context, const FName &pname) {
|
||||||
|
FTCHARToUTF8 utf8str(pname.ToString());
|
||||||
|
std::string_view namestr(utf8str.Get(), utf8str.Length());
|
||||||
|
uint64_t tokvalue = ParseNameAsToken(namestr);
|
||||||
|
if ((tokvalue == 0) && !namestr.empty()) {
|
||||||
|
FatalBlueprintError(TEXT("Names passed to lua must be short, and must contain only lowercase and digits"));
|
||||||
|
}
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::TOKEN);
|
||||||
|
sb.write_string(namestr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_float(UObject *context, double pfloat) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
||||||
|
sb.write_double(pfloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_int(UObject *context, int value) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::NUMBER);
|
||||||
|
sb.write_double(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_vector(UObject *context, const FVector &pvector) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
||||||
|
sb.write_fvector(pvector);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_vector2d(UObject *context, const FVector2D &pvector) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::VECTOR);
|
||||||
|
sb.write_double(pvector.X);
|
||||||
|
sb.write_double(pvector.Y);
|
||||||
|
sb.write_double(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaCallLibrary::LuaCallArgument_boolean(UObject *context, bool pbool) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetBuffer();
|
||||||
|
CheckNotEmpty(sb);
|
||||||
|
sb.write_simple_dynamic_tag(SimpleDynamicTag::BOOLEAN);
|
||||||
|
sb.write_bool(pbool);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Return Value Unpacking functions
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
FString UlxLuaCallLibrary::LuaCallReturnValue_string(UObject *context) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
@@ -174,7 +346,7 @@ FString UlxLuaCallLibrary::LuaCallGetStringResult(UObject *context) {
|
|||||||
return sb.read_fstring();
|
return sb.read_fstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
FName UlxLuaCallLibrary::LuaCallGetNameResult(UObject *context) {
|
FName UlxLuaCallLibrary::LuaCallReturnValue_name(UObject *context) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
@@ -182,7 +354,7 @@ FName UlxLuaCallLibrary::LuaCallGetNameResult(UObject *context) {
|
|||||||
return sb.read_fname();
|
return sb.read_fname();
|
||||||
}
|
}
|
||||||
|
|
||||||
double UlxLuaCallLibrary::LuaCallGetFloatResult(UObject *context) {
|
double UlxLuaCallLibrary::LuaCallReturnValue_float(UObject *context) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
@@ -190,7 +362,15 @@ double UlxLuaCallLibrary::LuaCallGetFloatResult(UObject *context) {
|
|||||||
return sb.read_double();
|
return sb.read_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
FVector UlxLuaCallLibrary::LuaCallGetVectorResult(UObject *context) {
|
int UlxLuaCallLibrary::LuaCallReturnValue_int(UObject *context) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
|
if (tag != SimpleDynamicTag::NUMBER) FatalBlueprintError(TEXT("expected lua to return a number"));
|
||||||
|
return int(sb.read_double());
|
||||||
|
}
|
||||||
|
|
||||||
|
FVector UlxLuaCallLibrary::LuaCallReturnValue_vector(UObject *context) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
@@ -198,10 +378,20 @@ FVector UlxLuaCallLibrary::LuaCallGetVectorResult(UObject *context) {
|
|||||||
return sb.read_fvector();
|
return sb.read_fvector();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UlxLuaCallLibrary::LuaCallGetBooleanResult(UObject *context) {
|
FVector2D UlxLuaCallLibrary::LuaCallReturnValue_vector2d(UObject *context) {
|
||||||
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
|
if (tag != SimpleDynamicTag::VECTOR) FatalBlueprintError(TEXT("expected lua to return a vector"));
|
||||||
|
FVector v = sb.read_fvector();
|
||||||
|
return FVector2D(v.X, v.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UlxLuaCallLibrary::LuaCallReturnValue_boolean(UObject *context) {
|
||||||
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
AIntegrationGameModeBase *mode = AIntegrationGameModeBase::GetFromContext(context);
|
||||||
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
FlxStreamBuffer &sb = mode->LuaCallGetResult();
|
||||||
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
SimpleDynamicTag tag = sb.read_simple_dynamic_tag();
|
||||||
if (tag != SimpleDynamicTag::BOOLEAN) FatalBlueprintError(TEXT("expected lua to return a boolean"));
|
if (tag != SimpleDynamicTag::BOOLEAN) FatalBlueprintError(TEXT("expected lua to return a boolean"));
|
||||||
return sb.read_bool();
|
return sb.read_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "EdGraph/EdGraphPin.h"
|
||||||
#include "LuaCall.generated.h"
|
#include "LuaCall.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// These are the types that can actually be packed into
|
||||||
|
// an argument or return value buffer. Any other type is
|
||||||
|
// subject to conversion before packing.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
enum class ELpxSimpleDynamicTag : uint8 {
|
enum class ELpxSimpleDynamicTag : uint8 {
|
||||||
None,
|
None,
|
||||||
@@ -13,13 +23,88 @@ enum class ELpxSimpleDynamicTag : uint8 {
|
|||||||
Vector
|
Vector
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// This UClass is never instantiated. It exists to
|
// This is a little parser that parses Lua function 'prototypes'.
|
||||||
// expose certain static functions to the blueprint
|
// The prototypes look like this:
|
||||||
// library.
|
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////
|
// class.name(int arg1, int arg2) : int ret1, int ret2
|
||||||
|
//
|
||||||
|
// The return values can be omitted if the function has no return
|
||||||
|
// values. Optionally, there can be one last return value which
|
||||||
|
// is just an ellipsis. The class name can be asterisk.
|
||||||
|
//
|
||||||
|
// For more information about the meaning of all this, see the docs
|
||||||
|
// for the 'Call Lua' blueprint node.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FlxParsedProto
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Pin
|
||||||
|
{
|
||||||
|
FString Type;
|
||||||
|
FString Name;
|
||||||
|
Pin(const FString &T, const FString &N) : Type(T), Name(N) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
FString ErrorMessage;
|
||||||
|
TArray<FString> Tokens;
|
||||||
|
int NextToken;
|
||||||
|
FString ClassName;
|
||||||
|
FString FunctionName;
|
||||||
|
TArray<Pin> Arguments;
|
||||||
|
TArray<Pin> ReturnValues;
|
||||||
|
bool ExtraReturnValues;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
// Make a syntax error message, using the tokens.
|
||||||
|
//
|
||||||
|
void Syntax();
|
||||||
|
|
||||||
|
// Empty out the FlxParsedProto.
|
||||||
|
//
|
||||||
|
void Empty();
|
||||||
|
|
||||||
|
// Parse a function prototype.
|
||||||
|
//
|
||||||
|
void Parse(const FString &proto);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Construct with a prototype.
|
||||||
|
//
|
||||||
|
FlxParsedProto(const FString &str) { Parse(str); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// To make a Lua Call from inside of a blueprint, use the convenient "Call Lua"
|
||||||
|
// blueprint node. This node macroexpands into a sequence of low-level
|
||||||
|
// function calls. This library contains the low-level functions that
|
||||||
|
// "Call Lua" macroexpands into.
|
||||||
|
//
|
||||||
|
// The procedure for making a lua call using the low-level functions is as follows:
|
||||||
|
//
|
||||||
|
// * Use LuaCallBegin to put the class name and function name into the argument buffer.
|
||||||
|
// * Use LuaCallArgumentXXX to put arguments into the argument buffer.
|
||||||
|
// * Use LuaCallInvoke or LuaCallProbe to actually make the call.
|
||||||
|
// * Use LuaCallReturnValueXXX to fetch return values from the return buffer.
|
||||||
|
//
|
||||||
|
// The two buffers are basically global variables, they are part of the
|
||||||
|
// IntegrationGameModeBase. This is okay because blueprint is single-threaded.
|
||||||
|
//
|
||||||
|
// The following three libraries contain all the low-level functions.
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
UCLASS()
|
UCLASS()
|
||||||
class INTEGRATION_API UlxLuaCallLibrary : public UObject
|
class INTEGRATION_API UlxLuaCallLibrary : public UObject
|
||||||
@@ -27,30 +112,25 @@ class INTEGRATION_API UlxLuaCallLibrary : public UObject
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Get an argument packing function or a return value unpacking function.
|
||||||
|
//
|
||||||
|
static UFunction *GetArgumentPacker(const FString &Type);
|
||||||
|
static UFunction *GetReturnValueUnpacker(const FString &Type);
|
||||||
|
|
||||||
|
// Get the types supported for arguments and return values, as a documentation string.
|
||||||
|
//
|
||||||
|
static FString AllFunctionsWithPrefix(const TCHAR *Prefix);
|
||||||
|
static FString AllKnownArgumentTypes() { return AllFunctionsWithPrefix(TEXT("LuaCallArgument_")); }
|
||||||
|
static FString AllKnownReturnValueTypes() { return AllFunctionsWithPrefix(TEXT("LuaCallReturnValue_")); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
//
|
||||||
|
// Functions that do miscellaneous things.
|
||||||
|
//
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
static void LuaCallBegin(UObject *context, const FString &ClassName, const FString &FunctionName);
|
static void LuaCallBegin(UObject *context, const FString &ClassName, const FString &FunctionName);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddStringParameter(UObject *context, const FString &Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddNameParameter(UObject *context, const FName &Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddFloatParameter(UObject *context, double Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddIntParameter(UObject *context, int Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddVectorParameter(UObject *context, const FVector &Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddVector2DParameter(UObject *context, const FVector2D &Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static void LuaCallAddBooleanParameter(UObject *context, bool Value);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
static void LuaCallInvoke(UObject *context, AActor *Place);
|
static void LuaCallInvoke(UObject *context, AActor *Place);
|
||||||
|
|
||||||
@@ -63,19 +143,55 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
static ELpxSimpleDynamicTag LuaCallNextResultType(UObject *context);
|
static ELpxSimpleDynamicTag LuaCallNextResultType(UObject *context);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
//
|
||||||
static FString LuaCallGetStringResult(UObject *context);
|
// Functions that pack arguments into the call buffer.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static FName LuaCallGetNameResult(UObject *context);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
|
||||||
static double LuaCallGetFloatResult(UObject *context);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
static FVector LuaCallGetVectorResult(UObject *context);
|
static void LuaCallArgument_string(UObject *context, const FString &Value);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
static bool LuaCallGetBooleanResult(UObject *context);
|
static void LuaCallArgument_name(UObject *context, const FName &Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static void LuaCallArgument_float(UObject *context, double Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static void LuaCallArgument_int(UObject *context, int Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static void LuaCallArgument_vector(UObject *context, const FVector &Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static void LuaCallArgument_vector2d(UObject *context, const FVector2D &Value);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static void LuaCallArgument_boolean(UObject *context, bool Value);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Functions that extract return values from the return buffer.
|
||||||
|
//
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static FString LuaCallReturnValue_string(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static FName LuaCallReturnValue_name(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static double LuaCallReturnValue_float(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static int LuaCallReturnValue_int(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static FVector LuaCallReturnValue_vector(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static FVector2D LuaCallReturnValue_vector2d(UObject *context);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (WorldContext = "context"), Category = "Luprex|Call Lua Function")
|
||||||
|
static bool LuaCallReturnValue_boolean(UObject *context);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -91,160 +91,43 @@ static bool IsPlacePin(const UEdGraphPin *Pin) {
|
|||||||
return (Pin->PinName == PlacePinName);
|
return (Pin->PinName == PlacePinName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A parser for lua function prototypes.
|
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
||||||
//
|
|
||||||
struct FlxParsedProto {
|
|
||||||
FString ErrorMessage;
|
|
||||||
TArray<FString> Tokens;
|
|
||||||
int NextToken;
|
|
||||||
FString ClassName;
|
|
||||||
FString FunctionName;
|
|
||||||
TArray<FString> Arguments;
|
|
||||||
TArray<FString> ReturnValues;
|
|
||||||
bool ExtraReturnValues;
|
|
||||||
|
|
||||||
// Check the next token to see if it's exactly equal to text.
|
static FEdGraphPinType GetPinType(const FProperty *Property)
|
||||||
//
|
{
|
||||||
bool IsLiteral(const TCHAR *text);
|
FEdGraphPinType PinType;
|
||||||
|
bool IsWeak;
|
||||||
// Check the next token to see if it's an identifier.
|
FName PinCat, PinSubCat;
|
||||||
//
|
UObject *PinSubCatObj = nullptr;
|
||||||
bool IsIdent();
|
UEdGraphSchema_K2::GetPropertyCategoryInfo(Property, PinCat, PinSubCat, PinSubCatObj, IsWeak);
|
||||||
|
PinType.PinCategory = PinCat;
|
||||||
// Empty out the FlxParsedProto.
|
PinType.PinSubCategory = PinSubCat;
|
||||||
//
|
PinType.PinSubCategoryObject = PinSubCatObj;
|
||||||
void Empty();
|
return PinType;
|
||||||
|
|
||||||
// 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
UK2Node_LuaCall::UK2Node_LuaCall(const FObjectInitializer& ObjectInitializer)
|
||||||
: Super(ObjectInitializer)
|
: Super(ObjectInitializer)
|
||||||
{
|
{
|
||||||
NodeTooltip = LOCTEXT("NodeTooltip",
|
FString ArgTypes = UlxLuaCallLibrary::AllKnownArgumentTypes();
|
||||||
"Probe or Invoke a Lua function.\n"
|
FString RetTypes = UlxLuaCallLibrary::AllKnownReturnValueTypes();
|
||||||
|
NodeTooltip = FText::FromString(FString::Printf(TEXT(
|
||||||
|
"Call a Lua function.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The lua function prototype must be a hardwired string which must look like\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"
|
"\n"
|
||||||
" function cname.fname(arg1, arg2)"
|
" classname.funcname(int arg1, int arg2)\n"
|
||||||
" function cname.fname(arg1, arg2) : ret1, ret2\n"
|
" classname.funcname(int arg1, int arg2) : int ret1, int ret2\n"
|
||||||
" function cname.fname(arg1, arg2) : ret1, 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"
|
"\n"
|
||||||
"The prototype is parsed to determine what lua function to call.\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"
|
"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"
|
"\n"
|
||||||
"Optionally, you may use the * wildcard for the classname. In that\n"
|
"Optionally, you may use the * wildcard for the classname. In that\n"
|
||||||
"case, the class of the 'place' tangible will be used.\n"
|
"case, the class of the 'place' tangible will be used.\n"
|
||||||
"\n"
|
"\n"), *ArgTypes, *RetTypes));
|
||||||
"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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UK2Node_LuaCall::AllocateDefaultPins()
|
void UK2Node_LuaCall::AllocateDefaultPins()
|
||||||
@@ -273,7 +151,7 @@ void UK2Node_LuaCall::CreateCorrectPins()
|
|||||||
{
|
{
|
||||||
if (LuaFunctionPrototype.IsEmpty())
|
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) {
|
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.
|
// 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);
|
UEdGraphPin **OldPin = OldArgumentPins.Find(PrefixedName);
|
||||||
if (OldPin != nullptr) {
|
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||||
Pins.Emplace(*OldPin);
|
Pins.Emplace(*OldPin);
|
||||||
OldArgumentPins.Remove(PrefixedName);
|
OldArgumentPins.Remove(PrefixedName);
|
||||||
} else {
|
} 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.
|
// 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);
|
UEdGraphPin **OldPin = OldReturnValuePins.Find(PrefixedName);
|
||||||
if (OldPin != nullptr) {
|
if ((OldPin != nullptr) && ((*OldPin)->PinType == PinType)) {
|
||||||
Pins.Emplace(*OldPin);
|
Pins.Emplace(*OldPin);
|
||||||
OldReturnValuePins.Remove(PrefixedName);
|
OldReturnValuePins.Remove(PrefixedName);
|
||||||
} else {
|
} 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
|
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
|
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)
|
void UK2Node_LuaCall::PinConnectionListChanged(UEdGraphPin* Pin)
|
||||||
{
|
{
|
||||||
Modify();
|
Modify();
|
||||||
SynchronizePinType(Pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UK2Node_LuaCall::PinDefaultValueChanged(UEdGraphPin* 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
|
FText UK2Node_LuaCall::GetTooltipText() const
|
||||||
{
|
{
|
||||||
return NodeTooltip;
|
return NodeTooltip;
|
||||||
@@ -482,55 +325,11 @@ FText UK2Node_LuaCall::GetTooltipText() const
|
|||||||
void UK2Node_LuaCall::PostReconstructNode()
|
void UK2Node_LuaCall::PostReconstructNode()
|
||||||
{
|
{
|
||||||
Super::PostReconstructNode();
|
Super::PostReconstructNode();
|
||||||
|
|
||||||
UEdGraph* OuterGraph = GetGraph();
|
|
||||||
if (!IsTemplate() && OuterGraph && OuterGraph->Schema) {
|
|
||||||
for (UEdGraphPin* CurrentPin : Pins)
|
|
||||||
{
|
|
||||||
SynchronizePinType(CurrentPin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateCorrectPins();
|
CreateCorrectPins();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
#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)
|
void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
||||||
{
|
{
|
||||||
@@ -555,38 +354,56 @@ void UK2Node_LuaCall::ExpandNode(class FKismetCompilerContext& CompilerContext,
|
|||||||
UK2Node_CallFunction* PrevNode = BeginNode;
|
UK2Node_CallFunction* PrevNode = BeginNode;
|
||||||
|
|
||||||
// Add Packing operations for all argument pins.
|
// 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);
|
// This codepath should be unreachable, but just in case.
|
||||||
if (PackingFunc != nullptr)
|
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;
|
|
||||||
}
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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.
|
// 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);
|
UFunction *Action = IsInvoke ? LuaCallLibraryFunction(LuaCallInvoke) : LuaCallLibraryFunction(LuaCallProbe);
|
||||||
UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(Action);
|
UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(Action);
|
||||||
CompilerContext.MovePinLinksToIntermediate(*FindPin(PlacePinName, EGPD_Input), *ActionNode->FindPinChecked(TEXT("Place")));
|
CompilerContext.MovePinLinksToIntermediate(*FindPin(PlacePinName, EGPD_Input), *ActionNode->FindPinChecked(TEXT("Place")));
|
||||||
PrevNode->GetThenPin()->MakeLinkTo(ActionNode->GetExecPin());
|
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.
|
// Link up the Exec pins.
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *ActionNode->GetThenPin());
|
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *PrevNode->GetThenPin());
|
||||||
|
|
||||||
BreakAllNodeLinks();
|
BreakAllNodeLinks();
|
||||||
}
|
}
|
||||||
@@ -653,21 +470,9 @@ bool UK2Node_LuaCall::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEd
|
|||||||
return true;
|
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);
|
return Super::IsConnectionDisallowed(MyPin, OtherPin, OutReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UK2Node_LuaCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
void UK2Node_LuaCall::GetMenuActions(FBlueprintActionDatabaseRegistrar& ActionRegistrar) const
|
||||||
{
|
{
|
||||||
// actions get registered under specific object-keys; the idea is that
|
// actions get registered under specific object-keys; the idea is that
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ class UK2Node_LuaCall : public UK2Node
|
|||||||
virtual bool ShouldShowNodeProperties() const override { return true; }
|
virtual bool ShouldShowNodeProperties() const override { return true; }
|
||||||
virtual void PinConnectionListChanged(UEdGraphPin* Pin) override;
|
virtual void PinConnectionListChanged(UEdGraphPin* Pin) override;
|
||||||
virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override;
|
virtual void PinDefaultValueChanged(UEdGraphPin* Pin) override;
|
||||||
virtual void PinTypeChanged(UEdGraphPin* Pin) override;
|
|
||||||
virtual FText GetTooltipText() const override;
|
virtual FText GetTooltipText() const override;
|
||||||
virtual FText GetPinDisplayName(const UEdGraphPin* Pin) const override;
|
virtual FText GetPinDisplayName(const UEdGraphPin* Pin) const override;
|
||||||
//~ End UEdGraphNode Interface.
|
//~ End UEdGraphNode Interface.
|
||||||
@@ -73,9 +72,6 @@ private:
|
|||||||
/** Create all necessary pins. */
|
/** Create all necessary pins. */
|
||||||
void CreateCorrectPins();
|
void CreateCorrectPins();
|
||||||
|
|
||||||
/** Synchronize the type of the given pin with the type its connected to, or reset it to a wildcard pin if there's no connection */
|
|
||||||
void SynchronizePinType(UEdGraphPin* Pin);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** The lua function prototype, which must be saved as a property **/
|
/** The lua function prototype, which must be saved as a property **/
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
|
|||||||
@@ -153,12 +153,22 @@ void UlxTangible::GetCurrentAnimation(AActor *target, FlxAnimationStep &step) {
|
|||||||
step = GetActorTangible(target)->AnimTracker.GetCurrentAnimation();
|
step = GetActorTangible(target)->AnimTracker.GetCurrentAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool autoxyz, bool autofacing, bool autoplane) {
|
void UlxTangible::FinishedAnimation(AActor *target, const FlxAnimationStep &step, bool AutoUpdate) {
|
||||||
|
if (target == nullptr)
|
||||||
|
{
|
||||||
|
UE_LOG(LogBlueprint, Error, TEXT("In FinishedAnimation, tangible cannot be null"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
UlxTangible *tan = GetActorTangible(target);
|
UlxTangible *tan = GetActorTangible(target);
|
||||||
if (autoxyz) step.AutoUpdateXYZ(target);
|
if (AutoUpdate)
|
||||||
if (autofacing) step.AutoUpdateFacing(target);
|
{
|
||||||
if (autoplane) step.AutoUpdatePlane(&(tan->Plane));
|
step.AutoUpdateXYZ(target);
|
||||||
|
step.AutoUpdateFacing(target);
|
||||||
|
step.AutoUpdatePlane(&(tan->Plane));
|
||||||
|
}
|
||||||
tan->AnimTracker.FinishedAnimation(step.Hash);
|
tan->AnimTracker.FinishedAnimation(step.Hash);
|
||||||
|
FString DebugString = UlxAnimationStepLibrary::AnimationStepDebugString(step);
|
||||||
|
UE_LOG(LogBlueprint, Display, TEXT("Animation Finished: %s"), *DebugString);
|
||||||
}
|
}
|
||||||
|
|
||||||
FString UlxTangible::GetTangiblePlane(AActor* target) {
|
FString UlxTangible::GetTangiblePlane(AActor* target) {
|
||||||
|
|||||||
@@ -131,9 +131,8 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Queue")
|
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Queue")
|
||||||
static void GetCurrentAnimation(AActor *target, FlxAnimationStep &step);
|
static void GetCurrentAnimation(AActor *target, FlxAnimationStep &step);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Queue")
|
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "Target"), Category = "Luprex|Animation Queue")
|
||||||
static void FinishedAnimation(AActor *target, const FlxAnimationStep &step,
|
static void FinishedAnimation(AActor *Target, const FlxAnimationStep &Step, bool AutoUpdate = true);
|
||||||
bool AutoUpdateXYZ = true, bool AutoUpdateFacing = true, bool AutoUpdatePlane = true);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Queue")
|
UFUNCTION(BlueprintCallable, Meta = (DefaultToSelf = "target"), Category = "Luprex|Animation Queue")
|
||||||
static void SetAutoFinish(AActor *target, const FString &action, const FVector &xyz);
|
static void SetAutoFinish(AActor *target, const FString &action, const FVector &xyz);
|
||||||
|
|||||||
@@ -26,3 +26,8 @@ end
|
|||||||
function engio.printhi(a1, a2, a3, a4, a5)
|
function engio.printhi(a1, a2, a3, a4, a5)
|
||||||
pprint("Hi there", a1, a2, a3, a4, a5)
|
pprint("Hi there", a1, a2, a3, a4, a5)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function engio.retthree(a1, a2)
|
||||||
|
return { 5, {3, 4, 5}, "Howdy" }
|
||||||
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user