Finished implementing the ReadLuaValues K2Node
This commit is contained in:
Binary file not shown.
@@ -276,7 +276,7 @@ bool UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place, UlxLuaValu
|
|||||||
}
|
}
|
||||||
ElxSuccessOrWrongType Status;
|
ElxSuccessOrWrongType Status;
|
||||||
FString ErrorMessage;
|
FString ErrorMessage;
|
||||||
ReturnArray->ReadString(Status, ErrorMessage, false);
|
ReturnArray->ReadString(Status, ErrorMessage);
|
||||||
if (Status != ElxSuccessOrWrongType::Success)
|
if (Status != ElxSuccessOrWrongType::Success)
|
||||||
{
|
{
|
||||||
UE_LOG(LogLuprexIntegration, Error, TEXT("lua probe should always return an error message (possibly empty) as the first parameter"));
|
UE_LOG(LogLuprexIntegration, Error, TEXT("lua probe should always return an error message (possibly empty) as the first parameter"));
|
||||||
@@ -289,6 +289,7 @@ bool UlxLuaCallLibrary::LuaCallProbe(UObject *context, AActor *place, UlxLuaValu
|
|||||||
ReturnArray = nullptr;
|
ReturnArray = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
ReturnArray->DiscardBeforeCursor();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +384,6 @@ bool UlxLuaValues::Initialize(std::string_view data)
|
|||||||
while (!Decoder.empty())
|
while (!Decoder.empty())
|
||||||
{
|
{
|
||||||
LuaValueType Tag = Decoder.read_lua_value_type();
|
LuaValueType Tag = Decoder.read_lua_value_type();
|
||||||
|
|
||||||
int64 Pos = Decoder.total_reads();
|
int64 Pos = Decoder.total_reads();
|
||||||
ElxLuaValueType Type;
|
ElxLuaValueType Type;
|
||||||
switch (Tag)
|
switch (Tag)
|
||||||
@@ -411,7 +411,7 @@ FString UlxLuaValues::DebugString() const
|
|||||||
Output << TEXT("{ ");
|
Output << TEXT("{ ");
|
||||||
for (int i = 0; i < Types.Num(); i++)
|
for (int i = 0; i < Types.Num(); i++)
|
||||||
{
|
{
|
||||||
if (i > 0) Output << TEXT(", ");
|
if (i > 0) Output << TEXT(" ");
|
||||||
|
|
||||||
if (i == Cursor) Output << TEXT("^ ");
|
if (i == Cursor) Output << TEXT("^ ");
|
||||||
|
|
||||||
@@ -442,31 +442,15 @@ FString UlxLuaValues::DebugString() const
|
|||||||
return Output.ToString();
|
return Output.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
ElxSuccessOrWrongType UlxLuaValues::CheckType(bool LogErrorOnWrongType, ElxLuaValueType Type, ElxLuaValueType Desired)
|
ElxSuccessOrWrongType UlxLuaValues::CheckType(ElxLuaValueType Type, ElxLuaValueType Desired)
|
||||||
{
|
{
|
||||||
if (Type != Desired)
|
if (Type != Desired)
|
||||||
{
|
{
|
||||||
if (LogErrorOnWrongType)
|
|
||||||
{
|
|
||||||
FString TypeName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Type)).ToString();
|
|
||||||
FString DesiredName = StaticEnum<ElxLuaValueType>()->GetDisplayNameTextByValue(int64(Desired)).ToString();
|
|
||||||
UE_LOG(LogBlueprint, Error, TEXT("Expected a value of type %s, but found %s instead."), *DesiredName, *TypeName);
|
|
||||||
}
|
|
||||||
return ElxSuccessOrWrongType::WrongType;
|
return ElxSuccessOrWrongType::WrongType;
|
||||||
}
|
}
|
||||||
return ElxSuccessOrWrongType::Success;
|
return ElxSuccessOrWrongType::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::DiscardBeforeCursor()
|
|
||||||
{
|
|
||||||
if (Cursor <= 0) return;
|
|
||||||
int Discard = Cursor;
|
|
||||||
if (Discard > Types.Num()) Discard = Types.Num();
|
|
||||||
Types.RemoveAt(0, Discard);
|
|
||||||
Data.RemoveAt(0, Discard);
|
|
||||||
Cursor -= Discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
ElxLuaValueType UlxLuaValues::NextType() const
|
ElxLuaValueType UlxLuaValues::NextType() const
|
||||||
{
|
{
|
||||||
if (Cursor < 0) return ElxLuaValueType::End;
|
if (Cursor < 0) return ElxLuaValueType::End;
|
||||||
@@ -474,78 +458,90 @@ ElxLuaValueType UlxLuaValues::NextType() const
|
|||||||
return Types[Cursor];
|
return Types[Cursor];
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadString(ElxSuccessOrWrongType &Status, FString &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::DiscardBeforeCursor()
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::String);
|
if (Cursor > 0)
|
||||||
|
{
|
||||||
|
Types.RemoveAt(0, Cursor);
|
||||||
|
Data.RemoveAt(0, Cursor);
|
||||||
|
SavedCursor = FMath::Max(0, SavedCursor - Cursor);
|
||||||
|
Cursor = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UlxLuaValues::ReadString(ElxSuccessOrWrongType &Status, FString &Result)
|
||||||
|
{
|
||||||
|
Status = CheckType(NextType(), ElxLuaValueType::String);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result.Empty(); return;
|
Cursor = SavedCursor; Result.Empty(); return;
|
||||||
}
|
}
|
||||||
Result = FlxStreamBuffer(Data[Cursor++]).read_fstring();
|
Result = FlxStreamBuffer(Data[Cursor++]).read_fstring();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadName(ElxSuccessOrWrongType &Status, FName &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadName(ElxSuccessOrWrongType &Status, FName &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Name);
|
Status = CheckType(NextType(), ElxLuaValueType::Name);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = FName(); return;
|
Cursor = SavedCursor; Result = FName(); return;
|
||||||
}
|
}
|
||||||
Result = FlxStreamBuffer(Data[Cursor++]).read_fname();
|
Result = FlxStreamBuffer(Data[Cursor++]).read_fname();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadFloat(ElxSuccessOrWrongType &Status, double &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadFloat(ElxSuccessOrWrongType &Status, double &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Float);
|
Status = CheckType(NextType(), ElxLuaValueType::Float);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = 0.0; return;
|
Cursor = SavedCursor; Result = 0.0; return;
|
||||||
}
|
}
|
||||||
Result = FlxStreamBuffer(Data[Cursor++]).read_double();
|
Result = FlxStreamBuffer(Data[Cursor++]).read_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadInt(ElxSuccessOrWrongType &Status, int &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadInt(ElxSuccessOrWrongType &Status, int &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Float);
|
Status = CheckType(NextType(), ElxLuaValueType::Float);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = 0.0; return;
|
Cursor = SavedCursor; Result = 0; return;
|
||||||
}
|
}
|
||||||
double dvalue = FlxStreamBuffer(Data[Cursor++]).read_double();
|
double dvalue = FlxStreamBuffer(Data[Cursor++]).read_double();
|
||||||
Result = int(dvalue);
|
Result = int(dvalue);
|
||||||
if (double(Result) != dvalue)
|
if (double(Result) != dvalue)
|
||||||
{
|
{
|
||||||
Result = 0; Status = ElxSuccessOrWrongType::WrongType; return;
|
Status = ElxSuccessOrWrongType::WrongType;
|
||||||
|
Cursor = SavedCursor; Result = 0; return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadVector(ElxSuccessOrWrongType &Status, FVector &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadVector(ElxSuccessOrWrongType &Status, FVector &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Vector);
|
Status = CheckType(NextType(), ElxLuaValueType::Vector);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = FVector(); return;
|
Cursor = SavedCursor; Result = FVector(); return;
|
||||||
}
|
}
|
||||||
Result = FlxStreamBuffer(Data[Cursor++]).read_fvector();
|
Result = FlxStreamBuffer(Data[Cursor++]).read_fvector();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadVector2D(ElxSuccessOrWrongType &Status, FVector2D &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadVector2D(ElxSuccessOrWrongType &Status, FVector2D &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Vector);
|
Status = CheckType(NextType(), ElxLuaValueType::Vector);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = FVector2D(); return;
|
Cursor = SavedCursor; Result = FVector2D(); return;
|
||||||
}
|
}
|
||||||
FVector VValue = FlxStreamBuffer(Data[Cursor++]).read_fvector();
|
FVector VValue = FlxStreamBuffer(Data[Cursor++]).read_fvector();
|
||||||
Result = FVector2D(VValue.X, VValue.Y);
|
Result = FVector2D(VValue.X, VValue.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UlxLuaValues::ReadBoolean(ElxSuccessOrWrongType &Status, bool &Result, bool LogErrorOnMismatch)
|
void UlxLuaValues::ReadBoolean(ElxSuccessOrWrongType &Status, bool &Result)
|
||||||
{
|
{
|
||||||
Status = CheckType(LogErrorOnMismatch, NextType(), ElxLuaValueType::Boolean);
|
Status = CheckType(NextType(), ElxLuaValueType::Boolean);
|
||||||
if (Status == ElxSuccessOrWrongType::WrongType)
|
if (Status == ElxSuccessOrWrongType::WrongType)
|
||||||
{
|
{
|
||||||
Result = false; return;
|
Cursor = SavedCursor; Result = false; return;
|
||||||
}
|
}
|
||||||
Result = FlxStreamBuffer(Data[Cursor++]).read_bool();
|
Result = FlxStreamBuffer(Data[Cursor++]).read_bool();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,74 +227,116 @@ private:
|
|||||||
|
|
||||||
// The current cursor.
|
// The current cursor.
|
||||||
//
|
//
|
||||||
int Cursor;
|
int Cursor = 0;
|
||||||
|
|
||||||
|
// Saved cursor for rollback on error.
|
||||||
|
//
|
||||||
|
int SavedCursor = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Clear everything.
|
// Clear everything.
|
||||||
//
|
//
|
||||||
void Empty();
|
void Empty();
|
||||||
|
|
||||||
// Compare two types. If they aren't equal,
|
// Compare two types for equality.
|
||||||
// possibly log an error, and return a status
|
|
||||||
// code.
|
|
||||||
//
|
//
|
||||||
static ElxSuccessOrWrongType CheckType(bool LogErrorOnWrongType, ElxLuaValueType Type, ElxLuaValueType Desired);
|
static ElxSuccessOrWrongType CheckType(ElxLuaValueType Type, ElxLuaValueType Desired);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UlxLuaValues() { Cursor = 0; }
|
UlxLuaValues() {}
|
||||||
|
|
||||||
// Copies the data, then preprocesses it to make
|
// Copies the data, then preprocesses it to make
|
||||||
// sure it's all valid. Returns false if invalid.
|
// sure it's all valid. Returns false if invalid.
|
||||||
//
|
//
|
||||||
bool Initialize(std::string_view data);
|
bool Initialize(std::string_view data);
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
// Remove all elements before the cursor.
|
||||||
|
//
|
||||||
void DiscardBeforeCursor();
|
void DiscardBeforeCursor();
|
||||||
|
|
||||||
|
// Convert a lua values array into a string.
|
||||||
|
// The string shows all the values, including those
|
||||||
|
// before the cursor, and the cursor as well.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
FString DebugString() const;
|
FString DebugString() const;
|
||||||
|
|
||||||
|
// Return the number of elements remaining after the cursor.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
int Length() const { return Types.Num(); }
|
int Length() const { return Types.Num() - Cursor; }
|
||||||
|
|
||||||
|
// Return the total number of elements, including both those
|
||||||
|
// before and after the cursor.
|
||||||
|
//
|
||||||
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
|
int TotalLength() const { return Types.Num(); }
|
||||||
|
|
||||||
|
// Get the current position of the cursor.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
int GetCursor() const { return Cursor; }
|
int GetCursor() const { return Cursor; }
|
||||||
|
|
||||||
|
// Set the position of the cursor. The value is clamped to
|
||||||
|
// be within the array.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintCallable, Category = "Luprex|Lua Value Array")
|
||||||
void SetCursor(int n) { Cursor = n; }
|
void SetCursor(int n) { Cursor = FMath::Clamp(n, 0, Types.Num()); }
|
||||||
|
|
||||||
|
// Get the type of the next element.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
ElxLuaValueType NextType() const;
|
ElxLuaValueType NextType() const;
|
||||||
|
|
||||||
|
// Return true if the type of the next element is what you say.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, Category = "Luprex|Lua Value Array")
|
||||||
bool IsNextType(ElxLuaValueType Type) const { return NextType() == Type; }
|
bool IsNextType(ElxLuaValueType Type) const { return NextType() == Type; }
|
||||||
|
|
||||||
|
// Switch-statement that depends on the type of the next element.
|
||||||
|
//
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"), Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "ReturnValue"), Category = "Luprex|Lua Value Array")
|
||||||
ElxLuaValueType SwitchNextType() { return NextType(); }
|
ElxLuaValueType SwitchNextType() { return NextType(); }
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadString(ElxSuccessOrWrongType &Status, FString &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadName(ElxSuccessOrWrongType &Status, FName &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadFloat(ElxSuccessOrWrongType &Status, double &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadInt(ElxSuccessOrWrongType &Status, int &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadVector(ElxSuccessOrWrongType &Status, FVector &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadVector2D(ElxSuccessOrWrongType &Status, FVector2D &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
|
||||||
void ReadBoolean(ElxSuccessOrWrongType &Status, bool &Result, bool LogErrorOnWrongType = false);
|
|
||||||
|
|
||||||
// Allows you to pass a LuaValues to Format Message.
|
// Allows you to pass a LuaValues to Format Message.
|
||||||
//
|
//
|
||||||
UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Lua Value Array")
|
UFUNCTION(BlueprintPure, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Lua Value Array")
|
||||||
static FFormatArgumentData FormatArgumentDataLuaValues(const UlxLuaValues *AutoConvertedValue, const FString &Name);
|
static FFormatArgumentData FormatArgumentDataLuaValues(const UlxLuaValues *AutoConvertedValue, const FString &Name);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Routines that are used by the ReadLuaValues K2Node
|
||||||
|
// to read values out.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadString(ElxSuccessOrWrongType &Status, FString &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadName(ElxSuccessOrWrongType &Status, FName &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadFloat(ElxSuccessOrWrongType &Status, double &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadInt(ElxSuccessOrWrongType &Status, int &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadVector(ElxSuccessOrWrongType &Status, FVector &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadVector2D(ElxSuccessOrWrongType &Status, FVector2D &Result);
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (ExpandEnumAsExecs = "Status"), Category = "Luprex|Lua Value Array")
|
||||||
|
void ReadBoolean(ElxSuccessOrWrongType &Status, bool &Result);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Other routines used by the ReadLuaValues K2Node
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true"), Category = "Luprex|Lua Value Array")
|
||||||
|
UlxLuaValues* SaveCursor() { SavedCursor = Cursor; return this; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -232,15 +232,11 @@ void UK2Node_LuaInvoke::ExpandNode(class FKismetCompilerContext& CompilerContext
|
|||||||
ThenPin = ChainExecPin(ThenPin, UnpackNode, TEXT("Success"));
|
ThenPin = ChainExecPin(ThenPin, UnpackNode, TEXT("Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an extra results pin, hook it up.
|
// If there is an extra results pin, pass through the LuaValues object.
|
||||||
if (ParsedProto.ExtraReturnValues)
|
if (ParsedProto.ExtraReturnValues)
|
||||||
{
|
{
|
||||||
UEdGraphPin *ExtraPin = FindPinChecked(ExtraResultsPinName);
|
UEdGraphPin *ExtraResultsPin = FindPinChecked(ExtraResultsPinName);
|
||||||
UFunction *DiscardFunc = UlxLuaValues::StaticClass()->FindFunctionByName(TEXT("DiscardBeforeCursor"));
|
CompilerContext.MovePinLinksToIntermediate(*ExtraResultsPin, *ReturnArrayPin);
|
||||||
UK2Node_CallFunction *DiscardNode = MakeCallFunctionNode(CompilerContext, SourceGraph, DiscardFunc);
|
|
||||||
ReturnArrayPin->MakeLinkTo(DiscardNode->FindPinChecked(UEdGraphSchema_K2::PN_Self));
|
|
||||||
ThenPin = ChainExecPin(ThenPin, DiscardNode, TEXT("Then"));
|
|
||||||
CompilerContext.MovePinLinksToIntermediate(*ExtraPin, *ReturnArrayPin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
||||||
|
|
||||||
|
|
||||||
#include "ReadLuaValues.h"
|
#include "ReadLuaValues.h"
|
||||||
@@ -6,58 +5,42 @@
|
|||||||
#include "BlueprintActionDatabaseRegistrar.h"
|
#include "BlueprintActionDatabaseRegistrar.h"
|
||||||
#include "BlueprintNodeSpawner.h"
|
#include "BlueprintNodeSpawner.h"
|
||||||
#include "EdGraphSchema_K2.h"
|
#include "EdGraphSchema_K2.h"
|
||||||
#include "GameFramework/Actor.h"
|
|
||||||
#include "K2Node_CallFunction.h"
|
#include "K2Node_CallFunction.h"
|
||||||
#include "KismetCompiler.h"
|
#include "KismetCompiler.h"
|
||||||
#include "LuaCall.h"
|
#include "LuaCall.h"
|
||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "LuaCall"
|
#define LOCTEXT_NAMESPACE "ReadLuaValues"
|
||||||
|
|
||||||
// All argument pins will have internal Names that start with "A:"
|
const FName UK2Node_ReadLuaValues::PrototypePinName(TEXT("Prototype"));
|
||||||
|
const FName UK2Node_ReadLuaValues::InputValuesPinName(TEXT("Input Values"));
|
||||||
const FName UK2Node_ReadLuaValues::FunctionPinName(TEXT("Lua Function Prototype"));
|
const FName UK2Node_ReadLuaValues::RemainingPinName(TEXT("Remaining"));
|
||||||
const FName UK2Node_ReadLuaValues::PlacePinName(TEXT("Place Tangible"));
|
|
||||||
const FName UK2Node_ReadLuaValues::ExtraResultsPinName(TEXT("Extra Results"));
|
|
||||||
const FName UK2Node_ReadLuaValues::ErrorPinName(TEXT("Error"));
|
const FName UK2Node_ReadLuaValues::ErrorPinName(TEXT("Error"));
|
||||||
|
|
||||||
FText UK2Node_ReadLuaValues::GetTooltipText() const
|
FText UK2Node_ReadLuaValues::GetTooltipText() const
|
||||||
{
|
{
|
||||||
static FText Tooltip = FText::FromString(FString::Printf(TEXT(
|
static FText Tooltip = FText::FromString(FString::Printf(TEXT(
|
||||||
"Call a Lua function.\n"
|
"Read typed values from a Lua Values array.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"The lua function prototype must be a hardwired string which must look like\n"
|
"The value prototype must be a hardwired string listing the\n"
|
||||||
"one of the following:\n"
|
"types and names of the values to read, for example:\n"
|
||||||
"\n"
|
"\n"
|
||||||
" classname.funcname(int arg1, int arg2)\n"
|
" string x, float y, int z\n"
|
||||||
" classname.funcname(int arg1, int arg2) : int ret1, int ret2\n"
|
|
||||||
" classname.funcname(int arg1, int arg2) : int ret1, int ret2, ...\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"You must specify types for the argument and return value pins. The\n"
|
"If you add '...' at the end, any remaining values will\n"
|
||||||
"types that you may specify are:\n"
|
"be available through the Remaining output pin.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Arguments: %s\n"
|
"Supported types: %s\n"),
|
||||||
"Return Values: %s\n"
|
*UlxLuaCallLibrary::AllKnownReturnValueTypes()));
|
||||||
"\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"
|
|
||||||
"return values. If the function has no return values, you can omit those\n"
|
|
||||||
"from the proto. If you put an ellipsis at the end of the return values,\n"
|
|
||||||
"then any additional return values will be collected into a\n"
|
|
||||||
"dynamically typed array of values which you can iterate over later.\n"
|
|
||||||
"\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"), *UlxLuaCallLibrary::AllKnownArgumentTypes(), *UlxLuaCallLibrary::AllKnownReturnValueTypes()));
|
|
||||||
return Tooltip;
|
return Tooltip;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UK2Node_ReadLuaValues::ReconstructNode()
|
void UK2Node_ReadLuaValues::ReconstructNode()
|
||||||
{
|
{
|
||||||
// Save the value of the Prototype Pin before it gets reconstructed.
|
// Save the value of the Prototype Pin before it gets reconstructed.
|
||||||
UEdGraphPin* FunctionPin = FindPin(FunctionPinName);
|
UEdGraphPin* PrototypePin = FindPin(PrototypePinName);
|
||||||
if (FunctionPin != nullptr)
|
if (PrototypePin != nullptr)
|
||||||
{
|
{
|
||||||
LuaFunctionPrototype = FunctionPin->DefaultValue;
|
ValuePrototype = PrototypePin->DefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Super::ReconstructNode();
|
Super::ReconstructNode();
|
||||||
@@ -68,48 +51,29 @@ void UK2Node_ReadLuaValues::AllocateDefaultPins()
|
|||||||
Pins.Reset();
|
Pins.Reset();
|
||||||
Super::AllocateDefaultPins();
|
Super::AllocateDefaultPins();
|
||||||
|
|
||||||
// Parse the lua function prototype.
|
// Parse the value prototype string.
|
||||||
// Note that we use the saved value of the function
|
FlxParsedProto ParsedProto = FlxParsedProto::ParseReturnValuesOnly(ValuePrototype);
|
||||||
// prototype, because the function prototype pin
|
|
||||||
// has been deleted at this point.
|
|
||||||
FlxParsedProto ParsedProto = FlxParsedProto::ParsePrototype(LuaFunctionPrototype);
|
|
||||||
if (!ParsedProto.ErrorMessage.IsEmpty())
|
if (!ParsedProto.ErrorMessage.IsEmpty())
|
||||||
{
|
{
|
||||||
SetErrorMsg(FString::Printf(TEXT("Syntax error in lua function prototype: %s"), *ParsedProto.ErrorMessage));
|
SetErrorMsg(FString::Printf(TEXT("Syntax error in value prototype: %s"), *ParsedProto.ErrorMessage));
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Execute);
|
||||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, UEdGraphSchema_K2::PN_Then);
|
||||||
|
|
||||||
if (!IsInvoke())
|
|
||||||
{
|
|
||||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, ErrorPinName);
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Exec, ErrorPinName);
|
||||||
}
|
|
||||||
|
|
||||||
UEdGraphPin *FunctionPin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, FunctionPinName);
|
UEdGraphPin *PrototypePin = CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_String, PrototypePinName);
|
||||||
FunctionPin->DefaultValue = LuaFunctionPrototype;
|
PrototypePin->DefaultValue = ValuePrototype;
|
||||||
|
|
||||||
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, AActor::StaticClass(), PlacePinName);
|
CreatePin(EGPD_Input, UEdGraphSchema_K2::PC_Object, UlxLuaValues::StaticClass(), InputValuesPinName);
|
||||||
|
|
||||||
// Create argument pins.
|
// Create output pins for each value.
|
||||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.Arguments)
|
|
||||||
{
|
|
||||||
FName PrefixedName = AddPrefix(Pin.Name, 'A');
|
|
||||||
UFunction *Accessor = UlxLuaCallLibrary::GetArgumentPacker(Pin.Type);
|
|
||||||
if (Accessor == nullptr) {
|
|
||||||
SetErrorMsg(FString::Printf(TEXT("Unknown argument type: %s"), *Pin.Type));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
CreatePin(EGPD_Input, PropertyToPinType(Accessor->FindPropertyByName(TEXT("Value"))), PrefixedName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create return value pins.
|
|
||||||
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
for (const FlxParsedProto::Pin & Pin : ParsedProto.ReturnValues)
|
||||||
{
|
{
|
||||||
FName PrefixedName = AddPrefix(Pin.Name, 'R');
|
FName PrefixedName = AddPrefix(Pin.Name, 'R');
|
||||||
UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type);
|
UFunction *Accessor = UlxLuaCallLibrary::GetReturnValueUnpacker(Pin.Type);
|
||||||
if (Accessor == nullptr) {
|
if (Accessor == nullptr) {
|
||||||
SetErrorMsg(FString::Printf(TEXT("Unknown return value type: %s"), *Pin.Type));
|
SetErrorMsg(FString::Printf(TEXT("Unknown value type: %s"), *Pin.Type));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
CreatePin(EGPD_Output, PropertyToPinType(Accessor->FindPropertyByName(TEXT("Result"))), PrefixedName);
|
CreatePin(EGPD_Output, PropertyToPinType(Accessor->FindPropertyByName(TEXT("Result"))), PrefixedName);
|
||||||
@@ -117,21 +81,14 @@ void UK2Node_ReadLuaValues::AllocateDefaultPins()
|
|||||||
|
|
||||||
if (ParsedProto.ExtraReturnValues)
|
if (ParsedProto.ExtraReturnValues)
|
||||||
{
|
{
|
||||||
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UlxLuaValues::StaticClass(), ExtraResultsPinName);
|
CreatePin(EGPD_Output, UEdGraphSchema_K2::PC_Object, UlxLuaValues::StaticClass(), RemainingPinName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FText UK2Node_ReadLuaValues::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
FText UK2Node_ReadLuaValues::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
||||||
{
|
{
|
||||||
if (IsInvoke())
|
return LOCTEXT("ReadLuaValues_Title", "Read Lua Values");
|
||||||
{
|
|
||||||
return LOCTEXT("LuaInvoke_Title", "Invoke a Lua Function");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return LOCTEXT("LuaProbe_Title", "Probe a Lua Function");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FText UK2Node_ReadLuaValues::GetPinDisplayName(const UEdGraphPin* Pin) const
|
FText UK2Node_ReadLuaValues::GetPinDisplayName(const UEdGraphPin* Pin) const
|
||||||
@@ -139,116 +96,73 @@ FText UK2Node_ReadLuaValues::GetPinDisplayName(const UEdGraphPin* Pin) const
|
|||||||
// These pins don't need labels.
|
// These pins don't need labels.
|
||||||
if ((Pin->PinName == UEdGraphSchema_K2::PN_Execute) ||
|
if ((Pin->PinName == UEdGraphSchema_K2::PN_Execute) ||
|
||||||
(Pin->PinName == UEdGraphSchema_K2::PN_Then) ||
|
(Pin->PinName == UEdGraphSchema_K2::PN_Then) ||
|
||||||
(Pin->PinName == FunctionPinName))
|
(Pin->PinName == PrototypePinName))
|
||||||
{
|
{
|
||||||
return FText::GetEmpty();
|
return FText::GetEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pin name, removing A: or R: if present.
|
// Return the pin name, removing R: prefix if present.
|
||||||
return FText::FromName(RemovePrefix(Pin->PinName));
|
return FText::FromName(RemovePrefix(Pin->PinName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UK2Node_ReadLuaValues::PinDefaultValueChanged(UEdGraphPin* Pin)
|
void UK2Node_ReadLuaValues::PinDefaultValueChanged(UEdGraphPin* Pin)
|
||||||
{
|
{
|
||||||
if ((Pin->PinName == FunctionPinName) && (Pin->DefaultValue != LuaFunctionPrototype))
|
if ((Pin->PinName == PrototypePinName) && (Pin->DefaultValue != ValuePrototype))
|
||||||
{
|
{
|
||||||
ReconstructNode();
|
ReconstructNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define LuaCallLibraryFunction(name) (UlxLuaCallLibrary::StaticClass()->FindFunctionByName(GET_MEMBER_NAME_CHECKED(UlxLuaCallLibrary, name)))
|
|
||||||
|
|
||||||
|
|
||||||
void UK2Node_ReadLuaValues::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
void UK2Node_ReadLuaValues::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
||||||
{
|
{
|
||||||
Super::ExpandNode(CompilerContext, SourceGraph);
|
Super::ExpandNode(CompilerContext, SourceGraph);
|
||||||
// The BeginNode function packs the class name and function name into the call buffer.
|
|
||||||
FlxParsedProto ParsedProto = FlxParsedProto::ParsePrototype(LuaFunctionPrototype);
|
|
||||||
const UEdGraphSchema_K2* CCSchema = CompilerContext.GetSchema();
|
|
||||||
UK2Node_CallFunction* BeginNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallBegin));
|
|
||||||
CCSchema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("ClassName")), ParsedProto.ClassName);
|
|
||||||
CCSchema->TrySetDefaultValue(*BeginNode->FindPinChecked(TEXT("FunctionName")), ParsedProto.FunctionName);
|
|
||||||
UEdGraphPin *ThenPin = BeginNode->GetThenPin();
|
|
||||||
|
|
||||||
// Add Packing operations for all argument pins.
|
FlxParsedProto ParsedProto = FlxParsedProto::ParseReturnValuesOnly(ValuePrototype);
|
||||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.Arguments)
|
UEdGraphPin *InputInputValuesCopyPin = FindPinChecked(InputValuesPinName);
|
||||||
{
|
|
||||||
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'A'));
|
|
||||||
UFunction *PackingFunc = UlxLuaCallLibrary::GetArgumentPacker(PinInfo.Type);
|
|
||||||
if (PackingFunc == nullptr)
|
|
||||||
{
|
|
||||||
// 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(CompilerContext, SourceGraph, PackingFunc);
|
|
||||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *PackNode->FindPinChecked(TEXT("Value")));
|
|
||||||
ThenPin = ChainExecPin(ThenPin, PackNode, TEXT("Then"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the invoke or probe node.
|
// Save the cursor so we can restore it on error.
|
||||||
UEdGraphPin *ReturnArrayPin = nullptr;
|
// SaveCursor returns the UlxLuaValues*, which we use as the
|
||||||
if (IsInvoke())
|
// intermediate pin for all subsequent nodes.
|
||||||
{
|
UFunction *SaveCursorFunc = UlxLuaValues::StaticClass()->FindFunctionByName(TEXT("SaveCursor"));
|
||||||
UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallInvoke));
|
UK2Node_CallFunction *SaveCursorNode = MakeCallFunctionNode(CompilerContext, SourceGraph, SaveCursorFunc);
|
||||||
CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(PlacePinName), *ActionNode->FindPinChecked(TEXT("Place")));
|
CompilerContext.MovePinLinksToIntermediate(*InputInputValuesCopyPin, *SaveCursorNode->FindPinChecked(UEdGraphSchema_K2::PN_Self));
|
||||||
ThenPin = ChainExecPin(ThenPin, ActionNode, TEXT("Then"));
|
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *SaveCursorNode->GetExecPin());
|
||||||
}
|
UEdGraphPin *InputValuesCopyPin = SaveCursorNode->GetReturnValuePin();
|
||||||
else
|
UEdGraphPin *ThenPin = SaveCursorNode->GetThenPin();
|
||||||
{
|
|
||||||
UK2Node_CallFunction* ActionNode = MakeCallFunctionNode(CompilerContext, SourceGraph, LuaCallLibraryFunction(LuaCallProbe));
|
|
||||||
CompilerContext.MovePinLinksToIntermediate(*FindPinChecked(PlacePinName), *ActionNode->FindPinChecked(TEXT("Place")));
|
|
||||||
CompilerContext.CopyPinLinksToIntermediate(*FindPinChecked(ErrorPinName), *ActionNode->FindPinChecked(TEXT("False")));
|
|
||||||
ReturnArrayPin = ActionNode->FindPinChecked(TEXT("ReturnArray"));
|
|
||||||
ThenPin = ChainExecPin(ThenPin, ActionNode, TEXT("True"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsInvoke())
|
// The Read functions automatically restore the cursor on failure,
|
||||||
{
|
// so we just need a pin to wire WrongType outputs to.
|
||||||
// Make sure we didn't have return values for an invoke.
|
UEdGraphPin *ErrorExecPin = FindPinChecked(ErrorPinName);
|
||||||
if ((ParsedProto.ReturnValues.Num() > 0) || (ParsedProto.ExtraReturnValues))
|
|
||||||
{
|
// Add Unpacking operations for all output pins.
|
||||||
CompilerContext.MessageLog.Error(TEXT("Lua Call in Invoke mode does not support return values"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add Unpacking operations for all return value pins.
|
|
||||||
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
for (const FlxParsedProto::Pin &PinInfo : ParsedProto.ReturnValues)
|
||||||
{
|
{
|
||||||
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'R'));
|
UEdGraphPin *Pin = FindPinChecked(AddPrefix(PinInfo.Name, 'R'));
|
||||||
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
UFunction *UnpackingFunc = UlxLuaCallLibrary::GetReturnValueUnpacker(PinInfo.Type);
|
||||||
if (UnpackingFunc == nullptr)
|
if (UnpackingFunc == nullptr)
|
||||||
{
|
{
|
||||||
// This codepath should be unreachable, but just in case.
|
CompilerContext.MessageLog.Error(TEXT("All value pins must have known types."));
|
||||||
CompilerContext.MessageLog.Error(TEXT("All return value pins must have known types."));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(CompilerContext, SourceGraph, UnpackingFunc);
|
UK2Node_CallFunction *UnpackNode = MakeCallFunctionNode(CompilerContext, SourceGraph, UnpackingFunc);
|
||||||
ReturnArrayPin->MakeLinkTo(UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_Self));
|
InputValuesCopyPin->MakeLinkTo(UnpackNode->FindPinChecked(UEdGraphSchema_K2::PN_Self));
|
||||||
CompilerContext.CopyPinLinksToIntermediate(*FindPinChecked(ErrorPinName), *UnpackNode->FindPinChecked(TEXT("WrongType")));
|
CompilerContext.CopyPinLinksToIntermediate(*ErrorExecPin, *UnpackNode->FindPinChecked(TEXT("WrongType")));
|
||||||
CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(TEXT("Result")));
|
CompilerContext.MovePinLinksToIntermediate(*Pin, *UnpackNode->FindPinChecked(TEXT("Result")));
|
||||||
ThenPin = ChainExecPin(ThenPin, UnpackNode, TEXT("Success"));
|
ThenPin = ChainExecPin(ThenPin, UnpackNode, TEXT("Success"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an extra results pin, hook it up.
|
// If there is a Remaining output pin, pass through the LuaValues object.
|
||||||
|
// The cursor is already past the consumed values.
|
||||||
if (ParsedProto.ExtraReturnValues)
|
if (ParsedProto.ExtraReturnValues)
|
||||||
{
|
{
|
||||||
UEdGraphPin *ExtraPin = FindPinChecked(ExtraResultsPinName);
|
UEdGraphPin *RemainingPin = FindPinChecked(RemainingPinName);
|
||||||
UFunction *DiscardFunc = UlxLuaValues::StaticClass()->FindFunctionByName(TEXT("DiscardBeforeCursor"));
|
CompilerContext.MovePinLinksToIntermediate(*RemainingPin, *InputValuesCopyPin);
|
||||||
UK2Node_CallFunction *DiscardNode = MakeCallFunctionNode(CompilerContext, SourceGraph, DiscardFunc);
|
|
||||||
ReturnArrayPin->MakeLinkTo(DiscardNode->FindPinChecked(UEdGraphSchema_K2::PN_Self));
|
|
||||||
ThenPin = ChainExecPin(ThenPin, DiscardNode, TEXT("Then"));
|
|
||||||
CompilerContext.MovePinLinksToIntermediate(*ExtraPin, *ReturnArrayPin);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link up the Exec pins.
|
// Link up the output exec pin.
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetExecPin(), *BeginNode->GetExecPin());
|
|
||||||
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *ThenPin);
|
CompilerContext.MovePinLinksToIntermediate(*GetThenPin(), *ThenPin);
|
||||||
|
|
||||||
|
|
||||||
BreakAllNodeLinks();
|
BreakAllNodeLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,10 +181,10 @@ UK2Node::ERedirectType UK2Node_ReadLuaValues::DoPinsMatchForReconstruction(const
|
|||||||
|
|
||||||
bool UK2Node_ReadLuaValues::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
bool UK2Node_ReadLuaValues::IsConnectionDisallowed(const UEdGraphPin* MyPin, const UEdGraphPin* OtherPin, FString& OutReason) const
|
||||||
{
|
{
|
||||||
// The function pin cannot be connected.
|
// The prototype pin cannot be connected.
|
||||||
if (MyPin->PinName == FunctionPinName)
|
if (MyPin->PinName == PrototypePinName)
|
||||||
{
|
{
|
||||||
OutReason = LOCTEXT("Error_FunctionPrototypeMustBeHardwired", "Lua function prototype must be a hardwired constant.").ToString();
|
OutReason = LOCTEXT("Error_PrototypeMustBeHardwired", "Value prototype must be a hardwired constant.").ToString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ReadLuaValues.h
|
||||||
|
//
|
||||||
|
// K2Node that reads typed values from a UlxLuaValues array.
|
||||||
|
// Takes a prototype string like "string x, float y, int z"
|
||||||
|
// and creates output pins with the appropriate types.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -10,10 +19,6 @@ class FString;
|
|||||||
class UEdGraph;
|
class UEdGraph;
|
||||||
class UObject;
|
class UObject;
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// The Lua Call K2Node.
|
|
||||||
//
|
|
||||||
UCLASS(MinimalAPI)
|
UCLASS(MinimalAPI)
|
||||||
class UK2Node_ReadLuaValues : public UlxK2Node
|
class UK2Node_ReadLuaValues : public UlxK2Node
|
||||||
{
|
{
|
||||||
@@ -42,24 +47,20 @@ public:
|
|||||||
//~ End UK2Node Interface.
|
//~ End UK2Node Interface.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const FName PrototypePinName;
|
||||||
virtual bool IsInvoke() const { return true; }
|
static const FName InputValuesPinName;
|
||||||
|
static const FName RemainingPinName;
|
||||||
/** Pin Names for the three built-in Pins **/
|
|
||||||
static const FName FunctionPinName;
|
|
||||||
static const FName PlacePinName;
|
|
||||||
static const FName ExtraResultsPinName;
|
|
||||||
static const FName ErrorPinName;
|
static const FName ErrorPinName;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Whenever the function value changes, we call
|
// Whenever the prototype pin value changes, we call
|
||||||
// ReconstructNode, which backs up the value into this
|
// ReconstructNode, which backs up the value into this
|
||||||
// property. This cache is needed because during
|
// property. This cache is needed because during
|
||||||
// ReconstructNode, we blow away the function pin. The
|
// ReconstructNode, we blow away the prototype pin. The
|
||||||
// function pin is also absent when the node is first
|
// prototype pin is also absent when the node is first
|
||||||
// created.
|
// created.
|
||||||
//
|
//
|
||||||
UPROPERTY()
|
UPROPERTY()
|
||||||
FString LuaFunctionPrototype = TEXT("class.func(int arg1, int arg2) : int ret1, int ret2");
|
FString ValuePrototype = TEXT("string x, float y, int z");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user