Progress on variable modification
This commit is contained in:
BIN
Content/Testing/BP_Test.uasset
LFS
BIN
Content/Testing/BP_Test.uasset
LFS
Binary file not shown.
@@ -41,18 +41,17 @@ public:
|
|||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Parse the variable declarations.
|
// Parse the variable declarations.
|
||||||
WingVariables Parsed;
|
WingVariables Vars;
|
||||||
if (!WingVariables::ParseString(Variables, Parsed)) return;
|
if (!Vars.ParseString(Variables)) return;
|
||||||
if (Parsed.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
||||||
if (!Parsed.CheckSanity(WingVariables::Cat::Blueprint)) return;
|
|
||||||
|
|
||||||
// Check for name collisions against existing variables, components, and the like.
|
// Check for name collisions against existing variables, components, and the like.
|
||||||
TSet<FName> Names;
|
TSet<FName> Names;
|
||||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||||
if (!WingUtils::FindNoDuplicateNames(Names, Parsed.GetVariables(), TEXT("variable or component"))) return;
|
if (!WingUtils::FindNoDuplicateNames(Names, Vars.GetVariables(), TEXT("variable or component"))) return;
|
||||||
|
|
||||||
// Create the variables.
|
// Create the variables.
|
||||||
for (const WingVariables::Var& V : Parsed.GetVariables())
|
for (const WingVariables::Var& V : Vars.GetVariables())
|
||||||
{
|
{
|
||||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, V.Name, V.Type))
|
if (!FBlueprintEditorUtils::AddMemberVariable(BP, V.Name, V.Type))
|
||||||
{
|
{
|
||||||
@@ -63,10 +62,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update everything.
|
// Update everything.
|
||||||
if (!Parsed.AssociateBlueprintNewVariables(BP)) return;
|
if (!Vars.AssociateBlueprintVariables(BP)) return;
|
||||||
Parsed.UpdateVariableFlags();
|
Vars.UpdateVariableFlags();
|
||||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
FKismetEditorUtilities::CompileBlueprint(BP);
|
||||||
if (!Parsed.UpdateVariableDefaults()) return;
|
if (!Vars.UpdateVariableDefaults()) return;
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,8 +32,9 @@ public:
|
|||||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
WingVariables Vars = WingVariables::ParseBlueprintVariables(BP);
|
WingVariables Vars;
|
||||||
|
Vars.LoadBlueprintVariables(BP);
|
||||||
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("No variables.\n")); return; }
|
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("No variables.\n")); return; }
|
||||||
Vars.PrintAll();
|
Vars.PrintAll(UWingServer::GetPrintBuffer(), true, TEXT("Blueprint Variables:"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,19 +39,19 @@ public:
|
|||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Parse the variable declarations.
|
// Parse the variable declarations.
|
||||||
WingVariables Parsed;
|
WingVariables Vars;
|
||||||
if (!WingVariables::ParseString(Variables, Parsed)) return;
|
if (!Vars.ParseString(Variables)) return;
|
||||||
if (Parsed.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
||||||
if (!Parsed.CheckSanity(WingVariables::Cat::Blueprint)) return;
|
if (!Vars.CheckSanity(WingVariables::Cat::BlueprintVariables)) return;
|
||||||
|
|
||||||
// Associate with existing blueprint variables.
|
// Associate with existing blueprint variables.
|
||||||
if (!Parsed.AssociateBlueprintNewVariables(BP)) return;
|
if (!Vars.AssociateBlueprintVariables(BP)) return;
|
||||||
|
|
||||||
// Update types and flags, compile, then update defaults.
|
// Update types and flags, compile, then update defaults.
|
||||||
Parsed.UpdateVariableTypes();
|
Vars.UpdateVariableTypes();
|
||||||
Parsed.UpdateVariableFlags();
|
Vars.UpdateVariableFlags();
|
||||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
FKismetEditorUtilities::CompileBlueprint(BP);
|
||||||
if (!Parsed.UpdateVariableDefaults()) return;
|
if (!Vars.UpdateVariableDefaults()) return;
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,12 +84,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Variables (new format)
|
// Variables (new format)
|
||||||
WingVariables BlueprintVars = WingVariables::ParseBlueprintVariables(BP);
|
WingVariables BlueprintVars;
|
||||||
if (!BlueprintVars.IsEmpty())
|
BlueprintVars.LoadBlueprintVariables(BP);
|
||||||
{
|
BlueprintVars.PrintAll(UWingServer::GetPrintBuffer(), true, TEXT("Blueprint Variables 2:"));
|
||||||
UWingServer::Print(TEXT("\nVariables (new format):\n"));
|
|
||||||
BlueprintVars.PrintAll(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
TArray<UWingComponentReference*> Components3 = UWingComponentReference::GetAll(BP);
|
TArray<UWingComponentReference*> Components3 = UWingComponentReference::GetAll(BP);
|
||||||
|
|||||||
@@ -33,27 +33,8 @@ public:
|
|||||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
if (!G) return;
|
if (!G) return;
|
||||||
|
|
||||||
FStringBuilderBase &Output = UWingServer::GetPrintBuffer();
|
WingGraphVariables Vars;
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
Vars.LoadGraph(G);
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
Vars.PrintAll(UWingServer::GetPrintBuffer(), true);
|
||||||
FBlueprintEditorUtils::GetEntryAndResultNodes(G, EntryNode, ResultNode);
|
|
||||||
WingVariables Arguments = WingVariables::ParseEditablePinBase(EntryNode.Get());
|
|
||||||
WingVariables ReturnValues = WingVariables::ParseEditablePinBase(EntryNode.Get());
|
|
||||||
WingVariables Locals = WingVariables::ParseFunctionLocalVariables(EntryNode.Get());
|
|
||||||
if (!Arguments.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("Arguments:\n"));
|
|
||||||
Arguments.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
if (!ReturnValues.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("ReturnValues:\n"));
|
|
||||||
ReturnValues.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
if (!Locals.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("LocalVariables:\n"));
|
|
||||||
Locals.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,15 +18,21 @@ class UWing_GraphVariables_Modify : public UObject, public IWingHandler
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(meta=(Description="Path to a function graph (e.g. '/Game/MyBP,graph:MyFunction')"))
|
UPROPERTY(meta=(Description="Path to a graph"))
|
||||||
FString Graph;
|
FString Graph;
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Variable declarations, one per line. Format: type name = default"))
|
UPROPERTY(meta=(Optional, Description="Argument declarations, one per line."))
|
||||||
FString Variables;
|
FString Arguments;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Return Value declarations, one per line."))
|
||||||
|
FString ReturnValues;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Local Variable declarations, one per line."))
|
||||||
|
FString LocalVariables;
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
virtual FString GetDescription() const override
|
||||||
{
|
{
|
||||||
return TEXT("Modify existing local variables of a function graph.");
|
return TEXT("Modify existing arguments, return values, and local variables of a graph.");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Handle() override
|
virtual void Handle() override
|
||||||
@@ -35,15 +41,13 @@ public:
|
|||||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
if (!G) return;
|
if (!G) return;
|
||||||
|
|
||||||
WingVariables Parsed;
|
WingGraphVariables Vars;
|
||||||
if (!WingVariables::ParseString(Variables, Parsed)) return;
|
if (!Vars.ParseStrings(Arguments, ReturnValues, LocalVariables)) return;
|
||||||
if (Parsed.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
if (!Vars.CheckSanity(G)) return;
|
||||||
if (!Parsed.CheckSanity(WingVariables::Cat::FunctionLocal)) return;
|
if (!Vars.AssociateGraph(G)) return;
|
||||||
|
Vars.UpdateVariableTypes();
|
||||||
if (!Parsed.AssociateFunctionLocalVariables(G)) return;
|
Vars.UpdateVariableFlags();
|
||||||
Parsed.UpdateVariableTypes();
|
Vars.UpdateVariableDefaults();
|
||||||
Parsed.UpdateVariableFlags();
|
|
||||||
Parsed.UpdateVariableDefaults();
|
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingVariables.h"
|
|
||||||
#include "Test_ParseVariables.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_Test_ParseVariables : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Variable declarations, one per line. Format: type name (flags) = default"))
|
|
||||||
FString Variables;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("Test: parse variable declarations and print them back out.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingVariables Parsed;
|
|
||||||
if (!WingVariables::ParseString(Variables, Parsed)) return;
|
|
||||||
|
|
||||||
UWingServer::Print(TEXT("Parsed variables:\n"));
|
|
||||||
Parsed.PrintAll(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -289,27 +289,9 @@ void WingGraphExport::EmitMaterialProperties(UEdGraphNode* Node, FStringBuilderB
|
|||||||
|
|
||||||
void WingGraphExport::EmitLocalVariables()
|
void WingGraphExport::EmitLocalVariables()
|
||||||
{
|
{
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
WingGraphVariables Vars;
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
Vars.LoadGraph(Graph);
|
||||||
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
Vars.PrintAll(Output, false);
|
||||||
WingVariables Arguments = WingVariables::ParseEditablePinBase(EntryNode.Get());
|
|
||||||
WingVariables ReturnValues = WingVariables::ParseEditablePinBase(EntryNode.Get());
|
|
||||||
WingVariables Locals = WingVariables::ParseFunctionLocalVariables(EntryNode.Get());
|
|
||||||
if (!Arguments.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("Arguments:\n"));
|
|
||||||
Arguments.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
if (!ReturnValues.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("ReturnValues:\n"));
|
|
||||||
ReturnValues.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
if (!Locals.GetVariables().IsEmpty())
|
|
||||||
{
|
|
||||||
Output.Appendf(TEXT("LocalVariables:\n"));
|
|
||||||
Locals.PrintAll(Output, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingGraphExport::EmitGraph()
|
void WingGraphExport::EmitGraph()
|
||||||
|
|||||||
@@ -21,15 +21,17 @@ static const FName Flag_ExposeToCinematics(TEXT("ExposeToCinematics"));
|
|||||||
|
|
||||||
static TSet<FName> Flags_None = { };
|
static TSet<FName> Flags_None = { };
|
||||||
static TSet<FName> Flags_BlueprintVariables = { Flag_InstanceEditable, Flag_BlueprintReadOnly, Flag_ExposeOnSpawn, Flag_Private, Flag_ExposeToCinematics };
|
static TSet<FName> Flags_BlueprintVariables = { Flag_InstanceEditable, Flag_BlueprintReadOnly, Flag_ExposeOnSpawn, Flag_Private, Flag_ExposeToCinematics };
|
||||||
static TSet<FName> Flags_FunctionLocalVariables = { };
|
|
||||||
|
|
||||||
const TSet<FName> &WingVariables::GetRelevantFlagSet(WingVariables::Cat C)
|
const TSet<FName> &WingVariables::GetRelevantFlagSet(WingVariables::Cat C)
|
||||||
{
|
{
|
||||||
switch (C)
|
switch (C)
|
||||||
{
|
{
|
||||||
case Cat::Blueprint: return Flags_BlueprintVariables;
|
case Cat::BlueprintVariables: return Flags_BlueprintVariables;
|
||||||
case Cat::FunctionLocal: return Flags_FunctionLocalVariables;
|
case Cat::LocalVariables: return Flags_None;
|
||||||
default: return Flags_None;
|
case Cat::FunctionArguments: return Flags_None;
|
||||||
|
case Cat::FunctionReturnValues: return Flags_None;
|
||||||
|
case Cat::MacroEntry: return Flags_None;
|
||||||
|
case Cat::MacroExit: return Flags_None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,19 +40,36 @@ void WingVariables::Var::AddFlagIfRelevant(FName Flag, WingVariables::Cat C)
|
|||||||
if (GetRelevantFlagSet(C).Contains(Flag)) Flags.Add(Flag);
|
if (GetRelevantFlagSet(C).Contains(Flag)) Flags.Add(Flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
WingVariables WingVariables::ParseBlueprintVariables(UBlueprint *BP)
|
void WingVariables::Clear()
|
||||||
{
|
{
|
||||||
WingVariables Result;
|
Variables.Empty();
|
||||||
Result.Category = Cat::Blueprint;
|
Blueprint = nullptr;
|
||||||
Result.Blueprint = BP;
|
FuncEntry = nullptr;
|
||||||
|
PinBase = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::ClearAssociation()
|
||||||
|
{
|
||||||
|
for (Var V : Variables)
|
||||||
|
{
|
||||||
|
V.BPVar = nullptr;
|
||||||
|
V.Pin = nullptr;
|
||||||
|
}
|
||||||
|
Blueprint = nullptr;
|
||||||
|
FuncEntry = nullptr;
|
||||||
|
PinBase = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::LoadBlueprintVariables(UBlueprint *BP)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
for (FBPVariableDescription& Desc : BP->NewVariables)
|
for (FBPVariableDescription& Desc : BP->NewVariables)
|
||||||
{
|
{
|
||||||
// Skip event dispatchers.
|
// Skip event dispatchers.
|
||||||
if (Desc.VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate) continue;
|
if (Desc.VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate) continue;
|
||||||
|
|
||||||
// Parse the bulk of the flags.
|
// Parse the bulk of the flags.
|
||||||
Var V = ParseVariableDescription(Desc, Cat::Blueprint);
|
Var V = ParseVariableDescription(Desc, Cat::BlueprintVariables);
|
||||||
V.BPVar = &Desc;
|
|
||||||
|
|
||||||
// Read default value from CDO if available.
|
// Read default value from CDO if available.
|
||||||
if (BP->GeneratedClass)
|
if (BP->GeneratedClass)
|
||||||
@@ -58,63 +77,51 @@ WingVariables WingVariables::ParseBlueprintVariables(UBlueprint *BP)
|
|||||||
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
||||||
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc.VarName);
|
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc.VarName);
|
||||||
if (CDO && Prop)
|
if (CDO && Prop)
|
||||||
|
{
|
||||||
V.DefaultValue = FWingProperty(Prop, CDO).GetText();
|
V.DefaultValue = FWingProperty(Prop, CDO).GetText();
|
||||||
|
V.DefaultSpecified = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result.Variables.Add(MoveTemp(V));
|
Variables.Add(MoveTemp(V));
|
||||||
}
|
}
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WingVariables WingVariables::ParseFunctionLocalVariables(UK2Node_EditablePinBase *Node)
|
void WingVariables::LoadLocalVariables(UK2Node_EditablePinBase *Node)
|
||||||
{
|
{
|
||||||
WingVariables Result;
|
Clear();
|
||||||
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
||||||
{
|
{
|
||||||
Result.Category = Cat::FunctionLocal;
|
|
||||||
Result.PinBase = Node;
|
|
||||||
for (FBPVariableDescription& Desc : Func->LocalVariables)
|
for (FBPVariableDescription& Desc : Func->LocalVariables)
|
||||||
{
|
{
|
||||||
Var V = ParseVariableDescription(Desc, Cat::FunctionLocal);
|
Var V = ParseVariableDescription(Desc, Cat::LocalVariables);
|
||||||
V.DefaultValue = Desc.DefaultValue;
|
V.DefaultValue = Desc.DefaultValue;
|
||||||
V.BPVar = &Desc;
|
V.DefaultSpecified = true;
|
||||||
Result.Variables.Add(MoveTemp(V));
|
Variables.Add(MoveTemp(V));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Result.Category = Cat::Empty;
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WingVariables WingVariables::ParseEditablePinBase(UK2Node_EditablePinBase* Node)
|
void WingVariables::LoadEditablePinBase(UK2Node_EditablePinBase* Node)
|
||||||
{
|
{
|
||||||
WingVariables Result;
|
Clear();
|
||||||
if (Node != nullptr)
|
if (Node != nullptr)
|
||||||
{
|
{
|
||||||
Result.Category = Cat::EditablePinBase;
|
|
||||||
Result.PinBase = Node;
|
|
||||||
for (const TSharedPtr<FUserPinInfo>& PinInfo : Node->UserDefinedPins)
|
for (const TSharedPtr<FUserPinInfo>& PinInfo : Node->UserDefinedPins)
|
||||||
{
|
{
|
||||||
Var V;
|
Var V;
|
||||||
V.Name = PinInfo->PinName;
|
V.Name = PinInfo->PinName;
|
||||||
V.Type = PinInfo->PinType;
|
V.Type = PinInfo->PinType;
|
||||||
V.DefaultValue = PinInfo->PinDefaultValue;
|
V.DefaultValue = PinInfo->PinDefaultValue;
|
||||||
V.Pin = PinInfo;
|
V.DefaultSpecified = true;
|
||||||
Result.Variables.Add(MoveTemp(V));
|
Variables.Add(MoveTemp(V));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Result.Category = Cat::Empty;
|
|
||||||
}
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::AssociateBlueprintNewVariables(UBlueprint *BP)
|
bool WingVariables::AssociateBlueprintVariables(UBlueprint *BP)
|
||||||
{
|
{
|
||||||
Category = Cat::Blueprint;
|
ClearAssociation();
|
||||||
Blueprint = BP;
|
Blueprint = BP;
|
||||||
for (Var &V : Variables)
|
for (Var &V : Variables)
|
||||||
{
|
{
|
||||||
@@ -122,15 +129,15 @@ bool WingVariables::AssociateBlueprintNewVariables(UBlueprint *BP)
|
|||||||
if (Desc == nullptr) return false;
|
if (Desc == nullptr) return false;
|
||||||
V.BPVar = Desc;
|
V.BPVar = Desc;
|
||||||
}
|
}
|
||||||
Blueprint = BP;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::AssociateFunctionLocalVariables(UK2Node_EditablePinBase *Node)
|
bool WingVariables::AssociateLocalVariables(UK2Node_EditablePinBase *Node)
|
||||||
{
|
{
|
||||||
Category = Cat::FunctionLocal;
|
ClearAssociation();
|
||||||
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
||||||
{
|
{
|
||||||
|
FuncEntry = Func;
|
||||||
for (Var &V : Variables)
|
for (Var &V : Variables)
|
||||||
{
|
{
|
||||||
FBPVariableDescription *Desc = WingUtils::FindOneWithInternalID(V.Name, Func->LocalVariables, TEXT("local variable"));
|
FBPVariableDescription *Desc = WingUtils::FindOneWithInternalID(V.Name, Func->LocalVariables, TEXT("local variable"));
|
||||||
@@ -141,77 +148,75 @@ bool WingVariables::AssociateFunctionLocalVariables(UK2Node_EditablePinBase *Nod
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (Variables.IsEmpty()) { return true; }
|
||||||
UWingServer::Printf(TEXT("Graph can't have local variables, not a function graph: %s\n"),
|
UWingServer::Printf(TEXT("Graph can't have local variables, not a function graph: %s\n"),
|
||||||
*WingUtils::FormatName(Node->GetGraph()));
|
*WingUtils::FormatName(Node->GetGraph()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::AssociateEditablePinBase(UK2Node_EditablePinBase *InPinBase)
|
bool WingVariables::AssociateEditablePinBase(UK2Node_EditablePinBase *Node)
|
||||||
{
|
{
|
||||||
if (!InPinBase || !InPinBase->IsEditable())
|
ClearAssociation();
|
||||||
|
if (Node != nullptr)
|
||||||
{
|
{
|
||||||
UWingServer::Print(TEXT("ERROR: Node does not have editable pins.\n"));
|
PinBase = Node;
|
||||||
return false;
|
for (Var &V : Variables)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo> *Found = WingUtils::FindOneWithInternalID(V.Name, Node->UserDefinedPins, TEXT("pin"));
|
||||||
|
if (!Found) return false;
|
||||||
|
V.Pin = *Found;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Category = Cat::EditablePinBase;
|
else
|
||||||
PinBase = InPinBase;
|
|
||||||
for (Var &V : Variables)
|
|
||||||
{
|
{
|
||||||
TSharedPtr<FUserPinInfo> *Found = WingUtils::FindOneWithInternalID(V.Name, InPinBase->UserDefinedPins, TEXT("pin"));
|
if (Variables.IsEmpty()) return true;
|
||||||
if (!Found) return false;
|
UWingServer::Printf(TEXT("Cannot modify variables, graph node does not exist yet"));
|
||||||
V.Pin = *Found;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::UpdateVariableTypes()
|
void WingVariables::UpdateVariableTypes()
|
||||||
{
|
{
|
||||||
switch (Category)
|
if (Blueprint) return UpdateBlueprintVariableTypes();
|
||||||
{
|
if (FuncEntry) return UpdateLocalVariableTypes();
|
||||||
case Cat::Blueprint: UpdateBlueprintVariableTypes(); break;
|
if (PinBase) return UpdateEditablePinBaseTypes();
|
||||||
case Cat::FunctionLocal: UpdateLocalVariableTypes(); break;
|
|
||||||
case Cat::EditablePinBase: UpdateEditablePinBaseTypes(); break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::UpdateVariableFlags()
|
void WingVariables::UpdateVariableFlags()
|
||||||
{
|
{
|
||||||
switch (Category)
|
if (Blueprint) return UpdateBlueprintVariableFlags();
|
||||||
{
|
if (FuncEntry) return UpdateLocalVariableFlags();
|
||||||
case Cat::Blueprint: UpdateBlueprintVariableFlags(); break;
|
if (PinBase) return UpdateEditablePinBaseFlags();
|
||||||
case Cat::FunctionLocal: UpdateLocalVariableFlags(); break;
|
|
||||||
case Cat::EditablePinBase: UpdateEditablePinBaseFlags(); break;
|
|
||||||
default: return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::UpdateVariableDefaults()
|
bool WingVariables::UpdateVariableDefaults()
|
||||||
{
|
{
|
||||||
switch (Category)
|
if (Blueprint) return UpdateBlueprintVariableDefaults();
|
||||||
{
|
if (FuncEntry) return UpdateLocalVariableDefaults();
|
||||||
case Cat::Blueprint: return UpdateBlueprintVariableDefaults(); break;
|
if (PinBase) return UpdateEditablePinBaseDefaults();
|
||||||
case Cat::FunctionLocal: return UpdateLocalVariableDefaults(); break;
|
return true;
|
||||||
case Cat::EditablePinBase: return UpdateEditablePinBaseDefaults(); break;
|
|
||||||
default: return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WingVariables::CheckEmpty(Cat Category)
|
||||||
|
{
|
||||||
|
if (!Variables.IsEmpty())
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("This kind of graph is not allowed to have %s"),
|
||||||
|
*StaticEnum<EWingVariableCategory>()->GetNameStringByValue(int(Category)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool WingVariables::CheckSanity(Cat Category)
|
bool WingVariables::CheckSanity(Cat Category)
|
||||||
{
|
{
|
||||||
const TSet<FName> &Relevant = GetRelevantFlagSet(Category);
|
const TSet<FName> &Relevant = GetRelevantFlagSet(Category);
|
||||||
TSet<FName> NamesUsed;
|
|
||||||
for (const Var &Variable : Variables)
|
for (const Var &Variable : Variables)
|
||||||
{
|
{
|
||||||
FString VarName = WingUtils::ExternalizeID(Variable.Name);
|
FString VarName = WingUtils::ExternalizeID(Variable.Name);
|
||||||
FString TypeText = UWingTypes::TypeToText(Variable.Type);
|
FString TypeText = UWingTypes::TypeToText(Variable.Type);
|
||||||
if (NamesUsed.Contains(Variable.Name))
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("Variable name appears twice: %s\n"), *VarName);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (TypeText.IsEmpty())
|
if (TypeText.IsEmpty())
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Type of variable %s is not valid for unknown reasons\n"), *VarName);
|
UWingServer::Printf(TEXT("Type of variable %s is not valid for unknown reasons\n"), *VarName);
|
||||||
@@ -235,7 +240,6 @@ bool WingVariables::CheckSanity(Cat Category)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WingVariables::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
bool WingVariables::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
||||||
{
|
{
|
||||||
Tok.Advance(); // Step over open-paren
|
Tok.Advance(); // Step over open-paren
|
||||||
@@ -346,11 +350,16 @@ WingVariables::Var WingVariables::ParseVariableDescription(const FBPVariableDesc
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::PrintAll(FStringBuilderBase &Out, int32 Indent)
|
void WingVariables::PrintAll(FStringBuilderBase &Out, bool Always, const TCHAR *Header)
|
||||||
{
|
{
|
||||||
FString Prefix;
|
if (Header != nullptr)
|
||||||
for (int32 i = 0; i < Indent; i++) Prefix += TEXT(" ");
|
{
|
||||||
|
if (Always || (!Variables.IsEmpty()))
|
||||||
|
{
|
||||||
|
Out.Append(Header);
|
||||||
|
Out.AppendChar('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const Var& V : Variables)
|
for (const Var& V : Variables)
|
||||||
{
|
{
|
||||||
FString TypeStr = UWingTypes::TypeToText(V.Type);
|
FString TypeStr = UWingTypes::TypeToText(V.Type);
|
||||||
@@ -370,7 +379,7 @@ void WingVariables::PrintAll(FStringBuilderBase &Out, int32 Indent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print: type name (flags) = defaultvalue
|
// Print: type name (flags) = defaultvalue
|
||||||
Out.Appendf(TEXT("%s%s %s"), *Prefix, *TypeStr, *NameStr);
|
Out.Appendf(TEXT(" %s %s"), *TypeStr, *NameStr);
|
||||||
if (!FlagsStr.IsEmpty())
|
if (!FlagsStr.IsEmpty())
|
||||||
Out.Appendf(TEXT(" (%s)"), *FlagsStr);
|
Out.Appendf(TEXT(" (%s)"), *FlagsStr);
|
||||||
if (!V.DefaultValue.IsEmpty())
|
if (!V.DefaultValue.IsEmpty())
|
||||||
@@ -379,11 +388,6 @@ void WingVariables::PrintAll(FStringBuilderBase &Out, int32 Indent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::PrintAll(int32 Indent)
|
|
||||||
{
|
|
||||||
PrintAll(UWingServer::GetPrintBuffer(), Indent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateBlueprintVariableTypes()
|
void WingVariables::UpdateBlueprintVariableTypes()
|
||||||
{
|
{
|
||||||
for (const Var &Input : Variables)
|
for (const Var &Input : Variables)
|
||||||
@@ -505,17 +509,17 @@ bool WingVariables::UpdateEditablePinBaseDefaults()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingGraphVariables::ParseGraph(const UEdGraph *Graph)
|
void WingGraphVariables::LoadGraph(const UEdGraph *Graph)
|
||||||
{
|
{
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||||
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
||||||
Arguments = WingVariables::ParseEditablePinBase(EntryNode.Get());
|
Arguments.LoadEditablePinBase(EntryNode.Get());
|
||||||
ReturnValues = WingVariables::ParseEditablePinBase(ResultNode.Get());
|
ReturnValues.LoadEditablePinBase(ResultNode.Get());
|
||||||
LocalVariables = WingVariables::ParseLocalVariables(EntryNode.Get());
|
LocalVariables.LoadLocalVariables(EntryNode.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingGraphVariables::ParseAll(const FString &A, const FString &R, const FString &L)
|
bool WingGraphVariables::ParseStrings(const FString &A, const FString &R, const FString &L)
|
||||||
{
|
{
|
||||||
if (!Arguments.ParseString(A)) return false;
|
if (!Arguments.ParseString(A)) return false;
|
||||||
if (!ReturnValues.ParseString(R)) return false;
|
if (!ReturnValues.ParseString(R)) return false;
|
||||||
@@ -523,7 +527,7 @@ bool WingGraphVariables::ParseAll(const FString &A, const FString &R, const FStr
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingGraphVariables::AssociateAll(const UEdGraph *Graph)
|
bool WingGraphVariables::AssociateGraph(const UEdGraph *Graph)
|
||||||
{
|
{
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||||
@@ -534,3 +538,55 @@ bool WingGraphVariables::AssociateAll(const UEdGraph *Graph)
|
|||||||
if (!LocalVariables.AssociateLocalVariables(EntryNode.Get())) OK = false;
|
if (!LocalVariables.AssociateLocalVariables(EntryNode.Get())) OK = false;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WingGraphVariables::PrintAll(FStringBuilderBase &Out, bool Always)
|
||||||
|
{
|
||||||
|
Arguments.PrintAll(Out, Always, TEXT("Arguments:"));
|
||||||
|
ReturnValues.PrintAll(Out, Always, TEXT("ReturnValues:"));
|
||||||
|
LocalVariables.PrintAll(Out, Always, TEXT("LocalVariables:"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingGraphVariables::UpdateVariableTypes()
|
||||||
|
{
|
||||||
|
Arguments.UpdateVariableTypes();
|
||||||
|
ReturnValues.UpdateVariableTypes();
|
||||||
|
LocalVariables.UpdateVariableTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingGraphVariables::UpdateVariableFlags()
|
||||||
|
{
|
||||||
|
Arguments.UpdateVariableFlags();
|
||||||
|
ReturnValues.UpdateVariableFlags();
|
||||||
|
LocalVariables.UpdateVariableFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingGraphVariables::UpdateVariableDefaults()
|
||||||
|
{
|
||||||
|
return Arguments.UpdateVariableDefaults() &&
|
||||||
|
ReturnValues.UpdateVariableDefaults() &&
|
||||||
|
LocalVariables.UpdateVariableDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingGraphVariables::CheckSanity(const UEdGraph *Graph)
|
||||||
|
{
|
||||||
|
EGraphType Type = Graph->GetSchema()->GetGraphType(Graph);
|
||||||
|
if (Type == EGraphType::GT_Function)
|
||||||
|
{
|
||||||
|
return Arguments.CheckSanity(Cat::FunctionArguments) &&
|
||||||
|
ReturnValues.CheckSanity(Cat::FunctionReturnValues) &&
|
||||||
|
LocalVariables.CheckSanity(Cat::LocalVariables);
|
||||||
|
}
|
||||||
|
else if (Type == EGraphType::GT_Macro)
|
||||||
|
{
|
||||||
|
return Arguments.CheckSanity(Cat::MacroEntry) &&
|
||||||
|
ReturnValues.CheckSanity(Cat::MacroExit) &&
|
||||||
|
LocalVariables.CheckEmpty(Cat::LocalVariables);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UWingServer::Printf(
|
||||||
|
TEXT("Graphs of this type may not have arguments, return values, or local variables."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,20 +3,26 @@
|
|||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "EdGraph/EdGraphPin.h"
|
#include "EdGraph/EdGraphPin.h"
|
||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
#include "K2Node_EditablePinBase.h"
|
|
||||||
|
|
||||||
struct WingTokenizer;
|
struct WingTokenizer;
|
||||||
|
class UK2Node_EditablePinBase;
|
||||||
|
class UK2Node_FunctionEntry;
|
||||||
|
|
||||||
|
UENUM()
|
||||||
|
enum class EWingVariableCategory : uint8
|
||||||
|
{
|
||||||
|
BlueprintVariables,
|
||||||
|
LocalVariables,
|
||||||
|
FunctionArguments,
|
||||||
|
FunctionReturnValues,
|
||||||
|
MacroEntry,
|
||||||
|
MacroExit
|
||||||
|
};
|
||||||
|
|
||||||
class WingVariables
|
class WingVariables
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Cat
|
using Cat = EWingVariableCategory;
|
||||||
{
|
|
||||||
Empty,
|
|
||||||
Blueprint,
|
|
||||||
LocalVariable,
|
|
||||||
EditablePinBase,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Var
|
struct Var
|
||||||
{
|
{
|
||||||
@@ -48,15 +54,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The category of these variables.
|
|
||||||
Cat Category;
|
|
||||||
|
|
||||||
// A list of all the variables.
|
// A list of all the variables.
|
||||||
TArray<Var> Variables;
|
TArray<Var> Variables;
|
||||||
|
|
||||||
// A pointer to a blueprint.
|
// A pointer to a blueprint.
|
||||||
UBlueprint *Blueprint = nullptr;
|
UBlueprint *Blueprint = nullptr;
|
||||||
|
|
||||||
|
// A pointer to a Function entry node.
|
||||||
|
UK2Node_FunctionEntry *FuncEntry = nullptr;
|
||||||
|
|
||||||
// A pointer to an editable pin base.
|
// A pointer to an editable pin base.
|
||||||
UK2Node_EditablePinBase* PinBase = nullptr;
|
UK2Node_EditablePinBase* PinBase = nullptr;
|
||||||
|
|
||||||
@@ -71,26 +77,35 @@ public:
|
|||||||
bool IsEmpty() const { return Variables.IsEmpty(); }
|
bool IsEmpty() const { return Variables.IsEmpty(); }
|
||||||
|
|
||||||
// Print all the variables to a string builder.
|
// Print all the variables to a string builder.
|
||||||
void PrintAll(FStringBuilderBase &Out, int32 Indent = 0);
|
void PrintAll(FStringBuilderBase &Out, bool Always, const TCHAR *Header);
|
||||||
|
|
||||||
// Print all the variables via UWingServer.
|
// Clear everything
|
||||||
void PrintAll(int32 Indent = 0);
|
void Clear();
|
||||||
|
|
||||||
// Make sure that this variable list makes sense for the given context.
|
// Clear any association.
|
||||||
bool CheckSanity(Cat Category);
|
void ClearAssociation();
|
||||||
|
|
||||||
|
// Check the sanity.
|
||||||
|
bool CheckSanity(Cat C);
|
||||||
|
|
||||||
|
// Check that the variables are empty.
|
||||||
|
bool CheckEmpty(Cat C);
|
||||||
|
|
||||||
// Parse variables from a string. One variable per line.
|
// Parse variables from a string. One variable per line.
|
||||||
// Format: type name (flag1, flag2) = defaultvalue
|
// Format: type name (flag1, flag2) = defaultvalue
|
||||||
// Returns false on parse error.
|
// Returns false on parse error.
|
||||||
bool ParseString(const FString &Input);
|
bool ParseString(const FString &Input);
|
||||||
|
|
||||||
// Parse variables from a given source.
|
// Make a best effort to load all available existing state.
|
||||||
static WingVariables ParseBlueprintVariables(UBlueprint *BP);
|
// This does not associate the variables. If you want to manipulate
|
||||||
static WingVariables ParseLocalVariables(UK2Node_EditablePinBase* Node);
|
// the variables, you'll have to associate them.
|
||||||
static WingVariables ParseEditablePinBase(UK2Node_EditablePinBase* Node);
|
void LoadBlueprintVariables(UBlueprint *BP);
|
||||||
|
void LoadLocalVariables(UK2Node_EditablePinBase* Node);
|
||||||
|
void LoadEditablePinBase(UK2Node_EditablePinBase* Node);
|
||||||
|
|
||||||
// Associate every variable in the list with an existing blueprint variable.
|
// Associate every variable in the list with an existing
|
||||||
bool AssociateBlueprintNewVariables(UBlueprint *BP);
|
// variable in a blueprint or graph.
|
||||||
|
bool AssociateBlueprintVariables(UBlueprint *BP);
|
||||||
bool AssociateLocalVariables(UK2Node_EditablePinBase* Node);
|
bool AssociateLocalVariables(UK2Node_EditablePinBase* Node);
|
||||||
bool AssociateEditablePinBase(UK2Node_EditablePinBase* Node);
|
bool AssociateEditablePinBase(UK2Node_EditablePinBase* Node);
|
||||||
|
|
||||||
@@ -123,8 +138,19 @@ struct WingGraphVariables
|
|||||||
|
|
||||||
WingGraphVariables() {}
|
WingGraphVariables() {}
|
||||||
|
|
||||||
void ParseGraph(const UEdGraph *Graph);
|
using Cat = WingVariables::Cat;
|
||||||
bool ParseStrings(const FString &A, const FString &R, const FString &L);
|
|
||||||
|
void LoadGraph(const UEdGraph *Graph);
|
||||||
bool AssociateGraph(const UEdGraph *Graph);
|
bool AssociateGraph(const UEdGraph *Graph);
|
||||||
|
bool ParseStrings(const FString &A, const FString &R, const FString &L);
|
||||||
|
void PrintAll(FStringBuilderBase &Out, bool Always);
|
||||||
|
void UpdateVariableTypes();
|
||||||
|
void UpdateVariableFlags();
|
||||||
|
bool UpdateVariableDefaults();
|
||||||
|
bool CheckSanity(const UEdGraph *Graph);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Cat GraphEntryCategory(const UEdGraph *Graph);
|
||||||
|
static Cat GraphExitCategory(const UEdGraph *Graph);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user