More progress on variables
This commit is contained in:
BIN
Content/Testing/BP_Test.uasset
LFS
BIN
Content/Testing/BP_Test.uasset
LFS
Binary file not shown.
@@ -12,7 +12,6 @@
|
|||||||
#include "Kismet2/KismetEditorUtilities.h"
|
#include "Kismet2/KismetEditorUtilities.h"
|
||||||
#include "BlueprintVariable_Create.generated.h"
|
#include "BlueprintVariable_Create.generated.h"
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -23,15 +22,16 @@ class UWing_BlueprintVariable_Create : public UObject, public IWingHandler
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(meta=(Description="Blueprint name or package path"))
|
UPROPERTY(meta=(Description="Blueprint path"))
|
||||||
FString Blueprint;
|
FString Blueprint;
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Variable declarations, one per line. Format: type name (flags) = default"))
|
UPROPERTY(meta=(Description="Variable declarations"))
|
||||||
FString Variables;
|
FString Variables;
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
virtual FString GetDescription() const override
|
||||||
{
|
{
|
||||||
return TEXT("Add new member variables to a Blueprint. Format: 'type name (flags) = default', one per line.");
|
return TEXT("Add new member variables to a Blueprint. "
|
||||||
|
"Format: 'type name (flags) = default', one per line.");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Handle() override
|
virtual void Handle() override
|
||||||
@@ -41,31 +41,10 @@ public:
|
|||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Parse the variable declarations.
|
// Parse the variable declarations.
|
||||||
WingVariables Vars;
|
WingVariables Vars(BP);
|
||||||
if (!Vars.ParseString(Variables)) return;
|
if (!Vars.BlueprintVariables.ParseString(Variables)) return;
|
||||||
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
if (!Vars.Check()) return;
|
||||||
|
if (!Vars.Create()) return;
|
||||||
// Check for name collisions against existing variables, components, and the like.
|
|
||||||
TSet<FName> Names;
|
|
||||||
FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
|
||||||
if (!WingUtils::FindNoDuplicateNames(Names, Vars.GetVariables(), TEXT("variable or component"))) return;
|
|
||||||
|
|
||||||
// Create the variables.
|
|
||||||
for (const WingVariables::Var& V : Vars.GetVariables())
|
|
||||||
{
|
|
||||||
if (!FBlueprintEditorUtils::AddMemberVariable(BP, V.Name, V.Type))
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Failed to add variable '%s'\n"),
|
|
||||||
*WingUtils::ExternalizeID(V.Name));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update everything.
|
|
||||||
if (!Vars.AssociateBlueprintVariables(BP)) return;
|
|
||||||
Vars.UpdateVariableFlags();
|
|
||||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
|
||||||
if (!Vars.UpdateVariableDefaults()) return;
|
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,9 +32,8 @@ public:
|
|||||||
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
WingVariables Vars;
|
WingVariables Vars(BP);
|
||||||
Vars.LoadBlueprintVariables(BP);
|
Vars.Load();
|
||||||
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("No variables.\n")); return; }
|
Vars.Print(UWingServer::GetPrintBuffer());
|
||||||
Vars.PrintAll(UWingServer::GetPrintBuffer(), true, TEXT("Blueprint Variables:"));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,20 +39,10 @@ public:
|
|||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Parse the variable declarations.
|
// Parse the variable declarations.
|
||||||
WingVariables Vars;
|
WingVariables Vars(BP);
|
||||||
if (!Vars.ParseString(Variables)) return;
|
if (!Vars.BlueprintVariables.ParseString(Variables)) return;
|
||||||
if (Vars.IsEmpty()) { UWingServer::Print(TEXT("ERROR: No variables specified.\n")); return; }
|
if (!Vars.Check()) return;
|
||||||
if (!Vars.CheckSanity(WingVariables::Cat::BlueprintVariables)) return;
|
if (!Vars.Modify()) return;
|
||||||
|
|
||||||
// Associate with existing blueprint variables.
|
|
||||||
if (!Vars.AssociateBlueprintVariables(BP)) return;
|
|
||||||
|
|
||||||
// Update types and flags, compile, then update defaults.
|
|
||||||
Vars.UpdateVariableTypes();
|
|
||||||
Vars.UpdateVariableFlags();
|
|
||||||
FKismetEditorUtilities::CompileBlueprint(BP);
|
|
||||||
if (!Vars.UpdateVariableDefaults()) return;
|
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -84,9 +84,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Variables (new format)
|
// Variables (new format)
|
||||||
WingVariables BlueprintVars;
|
WingVariables BlueprintVars(BP);
|
||||||
BlueprintVars.LoadBlueprintVariables(BP);
|
BlueprintVars.Load();
|
||||||
BlueprintVars.PrintAll(UWingServer::GetPrintBuffer(), true, TEXT("Blueprint Variables 2:"));
|
BlueprintVars.Print(UWingServer::GetPrintBuffer());
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
TArray<UWingComponentReference*> Components3 = UWingComponentReference::GetAll(BP);
|
TArray<UWingComponentReference*> Components3 = UWingComponentReference::GetAll(BP);
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingHandler.h"
|
||||||
|
#include "WingServer.h"
|
||||||
|
#include "WingFetcher.h"
|
||||||
|
#include "WingVariables.h"
|
||||||
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
|
#include "Kismet2/KismetEditorUtilities.h"
|
||||||
|
#include "K2Node_EditablePinBase.h"
|
||||||
|
#include "K2Node_FunctionEntry.h"
|
||||||
|
#include "GraphVariables_Create.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class UWing_GraphVariables_Create : public UObject, public IWingHandler
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(meta=(Description="Path to a function or macro graph (e.g. '/Game/MyBP,graph:MyFunction')"))
|
||||||
|
FString Graph;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Inputs to the graph"))
|
||||||
|
FString InputVariables;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Outputs to the graph"))
|
||||||
|
FString OutputVariables;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Locals to the graph"))
|
||||||
|
FString LocalVariables;
|
||||||
|
|
||||||
|
virtual FString GetDescription() const override
|
||||||
|
{
|
||||||
|
return TEXT("Add new inputs, outputs, and local variables to a graph. "
|
||||||
|
"Format: 'type name (flags) = default', one per line");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Handle() override
|
||||||
|
{
|
||||||
|
WingFetcher F;
|
||||||
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
|
if (!G) return;
|
||||||
|
|
||||||
|
WingVariables Vars(G);
|
||||||
|
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||||
|
if (!Vars.OutputVariables.ParseString(OutputVariables)) return;
|
||||||
|
if (!Vars.LocalVariables.ParseString(LocalVariables)) return;
|
||||||
|
if (!Vars.Check()) return;
|
||||||
|
if (!Vars.Create()) return;
|
||||||
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -33,8 +33,8 @@ public:
|
|||||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
if (!G) return;
|
if (!G) return;
|
||||||
|
|
||||||
WingGraphVariables Vars;
|
WingVariables Vars(G);
|
||||||
Vars.LoadGraph(G);
|
Vars.Load();
|
||||||
Vars.PrintAll(UWingServer::GetPrintBuffer(), true);
|
Vars.Print(UWingServer::GetPrintBuffer());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,13 +21,13 @@ public:
|
|||||||
UPROPERTY(meta=(Description="Path to a graph"))
|
UPROPERTY(meta=(Description="Path to a graph"))
|
||||||
FString Graph;
|
FString Graph;
|
||||||
|
|
||||||
UPROPERTY(meta=(Optional, Description="Argument declarations, one per line."))
|
UPROPERTY(meta=(Optional, Description="Inputs to the graph"))
|
||||||
FString Arguments;
|
FString InputVariables;
|
||||||
|
|
||||||
UPROPERTY(meta=(Optional, Description="Return Value declarations, one per line."))
|
UPROPERTY(meta=(Optional, Description="Outputs to the graph"))
|
||||||
FString ReturnValues;
|
FString OutputVariables;
|
||||||
|
|
||||||
UPROPERTY(meta=(Optional, Description="Local Variable declarations, one per line."))
|
UPROPERTY(meta=(Optional, Description="Locals to the graph"))
|
||||||
FString LocalVariables;
|
FString LocalVariables;
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
virtual FString GetDescription() const override
|
||||||
@@ -41,14 +41,12 @@ public:
|
|||||||
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
if (!G) return;
|
if (!G) return;
|
||||||
|
|
||||||
WingGraphVariables Vars;
|
WingVariables Vars(G);
|
||||||
if (!Vars.ParseStrings(Arguments, ReturnValues, LocalVariables)) return;
|
if (!Vars.InputVariables.ParseString(InputVariables)) return;
|
||||||
if (!Vars.CheckSanity(G)) return;
|
if (!Vars.OutputVariables.ParseString(OutputVariables)) return;
|
||||||
if (!Vars.AssociateGraph(G)) return;
|
if (!Vars.LocalVariables.ParseString(LocalVariables)) return;
|
||||||
Vars.UpdateVariableTypes();
|
if (!Vars.Check()) return;
|
||||||
Vars.UpdateVariableFlags();
|
if (!Vars.Modify()) return;
|
||||||
Vars.UpdateVariableDefaults();
|
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Success.\n"));
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -289,9 +289,9 @@ void WingGraphExport::EmitMaterialProperties(UEdGraphNode* Node, FStringBuilderB
|
|||||||
|
|
||||||
void WingGraphExport::EmitLocalVariables()
|
void WingGraphExport::EmitLocalVariables()
|
||||||
{
|
{
|
||||||
WingGraphVariables Vars;
|
WingVariables Vars(Graph);
|
||||||
Vars.LoadGraph(Graph);
|
Vars.Load();
|
||||||
Vars.PrintAll(Output, false);
|
Vars.Print(Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingGraphExport::EmitGraph()
|
void WingGraphExport::EmitGraph()
|
||||||
|
|||||||
@@ -476,6 +476,12 @@ TArray<UBlueprint*> WingUtils::GetAncestorBlueprints(UBlueprint *BP, bool Oldest
|
|||||||
return Blueprints;
|
return Blueprints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UObject *WingUtils::GetGeneratedCDO(UBlueprint *BP)
|
||||||
|
{
|
||||||
|
if (BP->GeneratedClass == nullptr) return nullptr;
|
||||||
|
return BP->GeneratedClass->GetDefaultObject();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Material helpers
|
// Material helpers
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "K2Node_Tunnel.h"
|
#include "K2Node_Tunnel.h"
|
||||||
#include "K2Node_EditablePinBase.h"
|
#include "K2Node_EditablePinBase.h"
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
|
#include "Kismet2/KismetEditorUtilities.h"
|
||||||
|
|
||||||
// Flag names used for blueprint variables.
|
// Flag names used for blueprint variables.
|
||||||
static const FName Flag_InstanceEditable(TEXT("InstanceEditable"));
|
static const FName Flag_InstanceEditable(TEXT("InstanceEditable"));
|
||||||
@@ -22,197 +23,58 @@ 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 };
|
||||||
|
|
||||||
const TSet<FName> &WingVariables::GetRelevantFlagSet(WingVariables::Cat C)
|
|
||||||
|
|
||||||
|
void WingVariableList::Print(FStringBuilderBase &Out)
|
||||||
{
|
{
|
||||||
switch (C)
|
if (Variables.IsEmpty()) return;
|
||||||
|
Out.Append(ListName);
|
||||||
|
Out.AppendChar(':');
|
||||||
|
Out.AppendChar('\n');
|
||||||
|
for (const Var& V : Variables)
|
||||||
{
|
{
|
||||||
case Cat::BlueprintVariables: return Flags_BlueprintVariables;
|
FString TypeStr = UWingTypes::TypeToText(V.Type);
|
||||||
case Cat::LocalVariables: return Flags_None;
|
FString NameStr = WingUtils::ExternalizeID(V.Name);
|
||||||
case Cat::FunctionArguments: return Flags_None;
|
|
||||||
case Cat::FunctionReturnValues: return Flags_None;
|
// Build flags string.
|
||||||
case Cat::MacroEntry: return Flags_None;
|
FString FlagsStr;
|
||||||
case Cat::MacroExit: return Flags_None;
|
if (V.Flags.Num() > 0)
|
||||||
|
{
|
||||||
|
TArray<FName> Sorted = V.Flags.Array();
|
||||||
|
Sorted.Sort(FNameLexicalLess());
|
||||||
|
for (const FName& Flag : Sorted)
|
||||||
|
{
|
||||||
|
if (!FlagsStr.IsEmpty()) FlagsStr += TEXT(", ");
|
||||||
|
FlagsStr += Flag.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print: type name (flags) = defaultvalue
|
||||||
|
Out.Appendf(TEXT(" %s %s"), *TypeStr, *NameStr);
|
||||||
|
if (!FlagsStr.IsEmpty())
|
||||||
|
Out.Appendf(TEXT(" (%s)"), *FlagsStr);
|
||||||
|
if (!V.DefaultValue.IsEmpty())
|
||||||
|
Out.Appendf(TEXT(" = %s"), *V.DefaultValue);
|
||||||
|
Out.Append(TEXT("\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::Var::AddFlagIfRelevant(FName Flag, WingVariables::Cat C)
|
void WingVariableList::ClearLinks()
|
||||||
{
|
{
|
||||||
if (GetRelevantFlagSet(C).Contains(Flag)) Flags.Add(Flag);
|
for (Var &V : Variables)
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::Clear()
|
|
||||||
{
|
|
||||||
Variables.Empty();
|
|
||||||
Blueprint = nullptr;
|
|
||||||
FuncEntry = nullptr;
|
|
||||||
PinBase = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::ClearAssociation()
|
|
||||||
{
|
|
||||||
for (Var V : Variables)
|
|
||||||
{
|
{
|
||||||
V.BPVar = nullptr;
|
V.BPVar = nullptr;
|
||||||
V.Pin = nullptr;
|
V.Pin = nullptr;
|
||||||
}
|
}
|
||||||
Blueprint = nullptr;
|
|
||||||
FuncEntry = nullptr;
|
|
||||||
PinBase = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::LoadBlueprintVariables(UBlueprint *BP)
|
bool WingVariableList::CheckSanity(const TSet<FName> &GoodFlags, bool Allow)
|
||||||
{
|
{
|
||||||
Clear();
|
if ((!Allow) && (!Variables.IsEmpty()))
|
||||||
for (FBPVariableDescription& Desc : BP->NewVariables)
|
|
||||||
{
|
{
|
||||||
// Skip event dispatchers.
|
UWingServer::Printf(TEXT("In this context, %s must be empty."), ListName);
|
||||||
if (Desc.VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate) continue;
|
|
||||||
|
|
||||||
// Parse the bulk of the flags.
|
|
||||||
Var V = ParseVariableDescription(Desc, Cat::BlueprintVariables);
|
|
||||||
|
|
||||||
// Read default value from CDO if available.
|
|
||||||
if (BP->GeneratedClass)
|
|
||||||
{
|
|
||||||
UObject* CDO = BP->GeneratedClass->GetDefaultObject();
|
|
||||||
FProperty* Prop = BP->GeneratedClass->FindPropertyByName(Desc.VarName);
|
|
||||||
if (CDO && Prop)
|
|
||||||
{
|
|
||||||
V.DefaultValue = FWingProperty(Prop, CDO).GetText();
|
|
||||||
V.DefaultSpecified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Variables.Add(MoveTemp(V));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::LoadLocalVariables(UK2Node_EditablePinBase *Node)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
|
||||||
{
|
|
||||||
for (FBPVariableDescription& Desc : Func->LocalVariables)
|
|
||||||
{
|
|
||||||
Var V = ParseVariableDescription(Desc, Cat::LocalVariables);
|
|
||||||
V.DefaultValue = Desc.DefaultValue;
|
|
||||||
V.DefaultSpecified = true;
|
|
||||||
Variables.Add(MoveTemp(V));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::LoadEditablePinBase(UK2Node_EditablePinBase* Node)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
if (Node != nullptr)
|
|
||||||
{
|
|
||||||
for (const TSharedPtr<FUserPinInfo>& PinInfo : Node->UserDefinedPins)
|
|
||||||
{
|
|
||||||
Var V;
|
|
||||||
V.Name = PinInfo->PinName;
|
|
||||||
V.Type = PinInfo->PinType;
|
|
||||||
V.DefaultValue = PinInfo->PinDefaultValue;
|
|
||||||
V.DefaultSpecified = true;
|
|
||||||
Variables.Add(MoveTemp(V));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::AssociateBlueprintVariables(UBlueprint *BP)
|
|
||||||
{
|
|
||||||
ClearAssociation();
|
|
||||||
Blueprint = BP;
|
|
||||||
for (Var &V : Variables)
|
|
||||||
{
|
|
||||||
FBPVariableDescription *Desc = WingUtils::FindOneWithInternalID(V.Name, BP->NewVariables, TEXT("non-inherited variable"));
|
|
||||||
if (Desc == nullptr) return false;
|
|
||||||
V.BPVar = Desc;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::AssociateLocalVariables(UK2Node_EditablePinBase *Node)
|
|
||||||
{
|
|
||||||
ClearAssociation();
|
|
||||||
if (UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node))
|
|
||||||
{
|
|
||||||
FuncEntry = Func;
|
|
||||||
for (Var &V : Variables)
|
|
||||||
{
|
|
||||||
FBPVariableDescription *Desc = WingUtils::FindOneWithInternalID(V.Name, Func->LocalVariables, TEXT("local variable"));
|
|
||||||
if (Desc == nullptr) return false;
|
|
||||||
V.BPVar = Desc;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Variables.IsEmpty()) { return true; }
|
|
||||||
UWingServer::Printf(TEXT("Graph can't have local variables, not a function graph: %s\n"),
|
|
||||||
*WingUtils::FormatName(Node->GetGraph()));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::AssociateEditablePinBase(UK2Node_EditablePinBase *Node)
|
|
||||||
{
|
|
||||||
ClearAssociation();
|
|
||||||
if (Node != nullptr)
|
|
||||||
{
|
|
||||||
PinBase = Node;
|
|
||||||
for (Var &V : Variables)
|
|
||||||
{
|
|
||||||
TSharedPtr<FUserPinInfo> *Found = WingUtils::FindOneWithInternalID(V.Name, Node->UserDefinedPins, TEXT("pin"));
|
|
||||||
if (!Found) return false;
|
|
||||||
V.Pin = *Found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (Variables.IsEmpty()) return true;
|
|
||||||
UWingServer::Printf(TEXT("Cannot modify variables, graph node does not exist yet"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateVariableTypes()
|
|
||||||
{
|
|
||||||
if (Blueprint) return UpdateBlueprintVariableTypes();
|
|
||||||
if (FuncEntry) return UpdateLocalVariableTypes();
|
|
||||||
if (PinBase) return UpdateEditablePinBaseTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateVariableFlags()
|
|
||||||
{
|
|
||||||
if (Blueprint) return UpdateBlueprintVariableFlags();
|
|
||||||
if (FuncEntry) return UpdateLocalVariableFlags();
|
|
||||||
if (PinBase) return UpdateEditablePinBaseFlags();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::UpdateVariableDefaults()
|
|
||||||
{
|
|
||||||
if (Blueprint) return UpdateBlueprintVariableDefaults();
|
|
||||||
if (FuncEntry) return UpdateLocalVariableDefaults();
|
|
||||||
if (PinBase) return UpdateEditablePinBaseDefaults();
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
const TSet<FName> &Relevant = GetRelevantFlagSet(Category);
|
|
||||||
for (const Var &Variable : Variables)
|
for (const Var &Variable : Variables)
|
||||||
{
|
{
|
||||||
FString VarName = WingUtils::ExternalizeID(Variable.Name);
|
FString VarName = WingUtils::ExternalizeID(Variable.Name);
|
||||||
@@ -229,10 +91,10 @@ bool WingVariables::CheckSanity(Cat Category)
|
|||||||
}
|
}
|
||||||
for (FName Flag : Variable.Flags)
|
for (FName Flag : Variable.Flags)
|
||||||
{
|
{
|
||||||
if (!Relevant.Contains(Flag))
|
if (!GoodFlags.Contains(Flag))
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Flag %s is not valid here. Valid flags are:"), *Flag.ToString());
|
UWingServer::Printf(TEXT("Flag %s is not valid here. Valid flags are:"), *Flag.ToString());
|
||||||
for (FName Rel : Relevant) UWingServer::Printf(TEXT(" %s\n"), *Rel.ToString());
|
for (FName Rel : GoodFlags) UWingServer::Printf(TEXT(" %s\n"), *Rel.ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,28 +102,51 @@ bool WingVariables::CheckSanity(Cat Category)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
bool WingVariableList::ParseString(const FString &Input)
|
||||||
{
|
{
|
||||||
Tok.Advance(); // Step over open-paren
|
Variables.Empty();
|
||||||
while (Tok.TokenIs(Tok.Identifier))
|
|
||||||
|
TArray<FString> Lines;
|
||||||
|
Input.ParseIntoArrayLines(Lines);
|
||||||
|
|
||||||
|
for (const FString& Line : Lines)
|
||||||
{
|
{
|
||||||
Out.Add(Tok.NextName());
|
WingTokenizer Tok(Line);
|
||||||
Tok.Advance();
|
if (Tok.NextType() == 0) continue;
|
||||||
// Commas are optional.
|
Var V;
|
||||||
if (Tok.TokenIs(',')) Tok.Advance();
|
V.DefaultSpecified = false;
|
||||||
|
if (!ParseOneVariable(Tok, V)) return false;
|
||||||
|
Variables.Add(MoveTemp(V));
|
||||||
}
|
}
|
||||||
if (!Tok.TokenIs(')'))
|
|
||||||
{
|
|
||||||
Tok.SaveCursor(NAME_None);
|
|
||||||
UWingServer::Printf(TEXT("ERROR: flag list contains invalid token '%s'\n"),
|
|
||||||
*FString(Tok.GetRange(NAME_None, 1)));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Tok.Advance(); // Step over close-paren
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
bool WingVariableList::ParseNamesString(const FString &Input)
|
||||||
|
{
|
||||||
|
Variables.Empty();
|
||||||
|
WingTokenizer Tok(Input);
|
||||||
|
while (Tok.TokenIs(Tok.Identifier))
|
||||||
|
{
|
||||||
|
FName Name = Tok.NextName();
|
||||||
|
Var V;
|
||||||
|
V.Name = Name;
|
||||||
|
Variables.Add(V);
|
||||||
|
V.DefaultSpecified = false;
|
||||||
|
Tok.Advance();
|
||||||
|
if (Tok.TokenIs(',')) Tok.Advance();
|
||||||
|
}
|
||||||
|
if (!Tok.TokenIs(0))
|
||||||
|
{
|
||||||
|
Tok.SaveCursor(NAME_None);
|
||||||
|
UWingServer::Printf(TEXT("Unexpected token %s in variable list"),
|
||||||
|
*FString(Tok.GetRange(NAME_None, 1)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariableList::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
||||||
{
|
{
|
||||||
// Parse type.
|
// Parse type.
|
||||||
UWingTypes::Requirements Req;
|
UWingTypes::Requirements Req;
|
||||||
@@ -306,287 +191,387 @@ bool WingVariables::ParseOneVariable(WingTokenizer &Tok, Var &V)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::ParseString(const FString &Input)
|
bool WingVariableList::ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out)
|
||||||
{
|
{
|
||||||
Variables.Empty();
|
Tok.Advance(); // Step over open-paren
|
||||||
|
while (Tok.TokenIs(Tok.Identifier))
|
||||||
TArray<FString> Lines;
|
|
||||||
Input.ParseIntoArrayLines(Lines);
|
|
||||||
|
|
||||||
for (const FString& Line : Lines)
|
|
||||||
{
|
{
|
||||||
WingTokenizer Tok(Line);
|
Out.Add(Tok.NextName());
|
||||||
if (Tok.NextType() == 0) continue;
|
Tok.Advance();
|
||||||
Var V;
|
// Commas are optional.
|
||||||
V.DefaultSpecified = false;
|
if (Tok.TokenIs(',')) Tok.Advance();
|
||||||
if (!ParseOneVariable(Tok, V)) return false;
|
|
||||||
Variables.Add(MoveTemp(V));
|
|
||||||
}
|
}
|
||||||
|
if (!Tok.TokenIs(')'))
|
||||||
|
{
|
||||||
|
Tok.SaveCursor(NAME_None);
|
||||||
|
UWingServer::Printf(TEXT("ERROR: flag list contains invalid token '%s'\n"),
|
||||||
|
*FString(Tok.GetRange(NAME_None, 1)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Tok.Advance(); // Step over close-paren
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
WingVariables::Var WingVariables::ParseVariableDescription(const FBPVariableDescription &Desc, WingVariables::Cat Category)
|
void WingVariables::Empty()
|
||||||
|
{
|
||||||
|
BlueprintVariables.Empty();
|
||||||
|
LocalVariables.Empty();
|
||||||
|
InputVariables.Empty();
|
||||||
|
OutputVariables.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::ClearLinks()
|
||||||
|
{
|
||||||
|
BlueprintVariables.ClearLinks();
|
||||||
|
LocalVariables.ClearLinks();
|
||||||
|
InputVariables.ClearLinks();
|
||||||
|
OutputVariables.ClearLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::Print(FStringBuilderBase &Out)
|
||||||
|
{
|
||||||
|
BlueprintVariables.Print(Out);
|
||||||
|
LocalVariables.Print(Out);
|
||||||
|
InputVariables.Print(Out);
|
||||||
|
OutputVariables.Print(Out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::Load()
|
||||||
|
{
|
||||||
|
Empty();
|
||||||
|
if (Blueprint != nullptr) return LoadBlueprint();
|
||||||
|
if (Graph != nullptr) return LoadGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::LoadBlueprint()
|
||||||
|
{
|
||||||
|
UObject *CDO = WingUtils::GetGeneratedCDO(Blueprint);
|
||||||
|
|
||||||
|
for (FBPVariableDescription& Desc : Blueprint->NewVariables)
|
||||||
|
{
|
||||||
|
// Skip event dispatchers.
|
||||||
|
if (Desc.VarType.PinCategory == UEdGraphSchema_K2::PC_MCDelegate) continue;
|
||||||
|
// Load up the variable.
|
||||||
|
Var V = LoadBlueprintVariableDescription(Desc, CDO);
|
||||||
|
BlueprintVariables.Variables.Add(MoveTemp(V));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::LoadGraph()
|
||||||
|
{
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
|
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
||||||
|
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
||||||
|
if (EntryNode.IsValid()) LoadEditablePinBase(EntryNode.Get(), InputVariables);
|
||||||
|
if (ResultNode.IsValid()) LoadEditablePinBase(ResultNode.Get(), OutputVariables);
|
||||||
|
LoadLocalVariables(EntryNode.Get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::LoadLocalVariables(UK2Node_EditablePinBase *Node)
|
||||||
|
{
|
||||||
|
UK2Node_FunctionEntry *Func = Cast<UK2Node_FunctionEntry>(Node);
|
||||||
|
if (Func == nullptr) return;
|
||||||
|
for (FBPVariableDescription& Desc : Func->LocalVariables)
|
||||||
|
{
|
||||||
|
Var V = LoadLocalVariableDescription(Desc);
|
||||||
|
LocalVariables.Variables.Add(MoveTemp(V));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WingVariables::Var WingVariables::LoadBlueprintVariableDescription(FBPVariableDescription &Desc, UObject *CDO)
|
||||||
{
|
{
|
||||||
Var Result;
|
Var Result;
|
||||||
Result.Name = Desc.VarName;
|
Result.Name = Desc.VarName;
|
||||||
Result.Type = Desc.VarType;
|
Result.Type = Desc.VarType;
|
||||||
|
|
||||||
if (!(Desc.PropertyFlags & CPF_DisableEditOnInstance))
|
if (!(Desc.PropertyFlags & CPF_DisableEditOnInstance))
|
||||||
Result.AddFlagIfRelevant(Flag_InstanceEditable, Category);
|
Result.Flags.Add(Flag_InstanceEditable);
|
||||||
|
|
||||||
if (Desc.PropertyFlags & CPF_BlueprintReadOnly)
|
if (Desc.PropertyFlags & CPF_BlueprintReadOnly)
|
||||||
Result.AddFlagIfRelevant(Flag_BlueprintReadOnly, Category);
|
Result.Flags.Add(Flag_BlueprintReadOnly);
|
||||||
|
|
||||||
if (Desc.PropertyFlags & CPF_Interp)
|
if (Desc.PropertyFlags & CPF_Interp)
|
||||||
Result.AddFlagIfRelevant(Flag_ExposeToCinematics, Category);
|
Result.Flags.Add(Flag_ExposeToCinematics);
|
||||||
|
|
||||||
if (Desc.HasMetaData(FBlueprintMetadata::MD_ExposeOnSpawn))
|
if (Desc.HasMetaData(FBlueprintMetadata::MD_ExposeOnSpawn))
|
||||||
Result.AddFlagIfRelevant(Flag_ExposeOnSpawn, Category);
|
Result.Flags.Add(Flag_ExposeOnSpawn);
|
||||||
|
|
||||||
if (Desc.HasMetaData(FBlueprintMetadata::MD_Private))
|
if (Desc.HasMetaData(FBlueprintMetadata::MD_Private))
|
||||||
Result.AddFlagIfRelevant(Flag_Private, Category);
|
Result.Flags.Add(Flag_Private);
|
||||||
|
|
||||||
|
// Read default value from CDO if available.
|
||||||
|
if (CDO)
|
||||||
|
{
|
||||||
|
FProperty* Prop = CDO->GetClass()->FindPropertyByName(Desc.VarName);
|
||||||
|
if (Prop)
|
||||||
|
{
|
||||||
|
Result.DefaultValue = FWingProperty(Prop, CDO).GetText();
|
||||||
|
Result.DefaultSpecified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::PrintAll(FStringBuilderBase &Out, bool Always, const TCHAR *Header)
|
WingVariables::Var WingVariables::LoadLocalVariableDescription(FBPVariableDescription &Desc)
|
||||||
{
|
{
|
||||||
if (Header != nullptr)
|
Var Result;
|
||||||
{
|
Result.Name = Desc.VarName;
|
||||||
if (Always || (!Variables.IsEmpty()))
|
Result.Type = Desc.VarType;
|
||||||
{
|
Result.DefaultValue = Desc.DefaultValue;
|
||||||
Out.Append(Header);
|
Result.DefaultSpecified = true;
|
||||||
Out.AppendChar('\n');
|
return Result;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (const Var& V : Variables)
|
|
||||||
{
|
|
||||||
FString TypeStr = UWingTypes::TypeToText(V.Type);
|
|
||||||
FString NameStr = WingUtils::ExternalizeID(V.Name);
|
|
||||||
|
|
||||||
// Build flags string.
|
void WingVariables::LoadEditablePinBase(UK2Node_EditablePinBase* Node, WingVariableList &List)
|
||||||
FString FlagsStr;
|
{
|
||||||
if (V.Flags.Num() > 0)
|
if (Node == nullptr) return;
|
||||||
{
|
for (const TSharedPtr<FUserPinInfo>& PinInfo : Node->UserDefinedPins)
|
||||||
TArray<FName> Sorted = V.Flags.Array();
|
{
|
||||||
Sorted.Sort(FNameLexicalLess());
|
Var V;
|
||||||
for (const FName& Flag : Sorted)
|
V.Name = PinInfo->PinName;
|
||||||
{
|
V.Type = PinInfo->PinType;
|
||||||
if (!FlagsStr.IsEmpty()) FlagsStr += TEXT(", ");
|
V.DefaultValue = PinInfo->PinDefaultValue;
|
||||||
FlagsStr += Flag.ToString();
|
V.DefaultSpecified = true;
|
||||||
}
|
List.Variables.Add(MoveTemp(V));
|
||||||
}
|
|
||||||
|
|
||||||
// Print: type name (flags) = defaultvalue
|
|
||||||
Out.Appendf(TEXT(" %s %s"), *TypeStr, *NameStr);
|
|
||||||
if (!FlagsStr.IsEmpty())
|
|
||||||
Out.Appendf(TEXT(" (%s)"), *FlagsStr);
|
|
||||||
if (!V.DefaultValue.IsEmpty())
|
|
||||||
Out.Appendf(TEXT(" = %s"), *V.DefaultValue);
|
|
||||||
Out.Append(TEXT("\n"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::UpdateBlueprintVariableTypes()
|
bool WingVariables::Check()
|
||||||
{
|
{
|
||||||
for (const Var &Input : Variables)
|
if (Blueprint) return CheckBlueprint();
|
||||||
{
|
if (Graph) return CheckGraph();
|
||||||
Input.BPVar->VarType = Input.Type;
|
check(false);
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::UpdateBlueprintVariableFlags()
|
bool WingVariables::CheckBlueprint()
|
||||||
{
|
{
|
||||||
for (const Var &Input : Variables)
|
bool OK = true;
|
||||||
{
|
if (!BlueprintVariables.CheckSanity(Flags_BlueprintVariables, true)) OK = false;
|
||||||
FBPVariableDescription &Out = *Input.BPVar;
|
if (!LocalVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||||
|
if (!InputVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||||
// InstanceEditable: absence means CPF_DisableEditOnInstance is set
|
if (!OutputVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||||
if (Input.Flags.Contains(Flag_InstanceEditable))
|
return OK;
|
||||||
Out.PropertyFlags &= ~CPF_DisableEditOnInstance;
|
|
||||||
else
|
|
||||||
Out.PropertyFlags |= CPF_DisableEditOnInstance;
|
|
||||||
|
|
||||||
if (Input.Flags.Contains(Flag_BlueprintReadOnly))
|
|
||||||
Out.PropertyFlags |= CPF_BlueprintReadOnly;
|
|
||||||
else
|
|
||||||
Out.PropertyFlags &= ~CPF_BlueprintReadOnly;
|
|
||||||
|
|
||||||
if (Input.Flags.Contains(Flag_ExposeToCinematics))
|
|
||||||
Out.PropertyFlags |= CPF_Interp;
|
|
||||||
else
|
|
||||||
Out.PropertyFlags &= ~CPF_Interp;
|
|
||||||
|
|
||||||
if (Input.Flags.Contains(Flag_ExposeOnSpawn))
|
|
||||||
Out.SetMetaData(FBlueprintMetadata::MD_ExposeOnSpawn, TEXT("true"));
|
|
||||||
else
|
|
||||||
Out.RemoveMetaData(FBlueprintMetadata::MD_ExposeOnSpawn);
|
|
||||||
|
|
||||||
if (Input.Flags.Contains(Flag_Private))
|
|
||||||
Out.SetMetaData(FBlueprintMetadata::MD_Private, TEXT("true"));
|
|
||||||
else
|
|
||||||
Out.RemoveMetaData(FBlueprintMetadata::MD_Private);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::UpdateBlueprintVariableDefaults()
|
bool WingVariables::CheckGraph()
|
||||||
{
|
{
|
||||||
UObject *CDO = nullptr;
|
EGraphType T = Graph->GetSchema()->GetGraphType(Graph);
|
||||||
if (Blueprint->GeneratedClass) CDO = Blueprint->GeneratedClass->GetDefaultObject();
|
bool AllowLocal = (T == EGraphType::GT_Function);
|
||||||
if (CDO == nullptr)
|
bool AllowInput = (T == EGraphType::GT_Function) || (T == EGraphType::GT_Macro);
|
||||||
|
bool AllowOutput = (T == EGraphType::GT_Function) || (T == EGraphType::GT_Macro);
|
||||||
|
if ((!AllowLocal) && (!AllowInput) && (!AllowOutput))
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Blueprint is not compiled, cannot update variable defaults."));
|
UWingServer::Printf(TEXT("This graph has no editable variables."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int OK = true;
|
|
||||||
for (const Var &Input : Variables)
|
bool OK = true;
|
||||||
|
if (!BlueprintVariables.CheckSanity(Flags_None, false)) OK = false;
|
||||||
|
if (!LocalVariables.CheckSanity(Flags_None, AllowLocal)) OK = false;
|
||||||
|
if (!InputVariables.CheckSanity(Flags_None, AllowInput)) OK = false;
|
||||||
|
if (!OutputVariables.CheckSanity(Flags_None, AllowOutput)) OK = false;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::Modify()
|
||||||
|
{
|
||||||
|
if (Blueprint) return ModifyBlueprint();
|
||||||
|
if (Graph) return ModifyGraph();
|
||||||
|
check(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::ModifyBlueprint()
|
||||||
|
{
|
||||||
|
if (!CheckBlueprint()) return false;
|
||||||
|
ClearLinks();
|
||||||
|
|
||||||
|
// Link our variables to blueprint variable descriptions.
|
||||||
|
for (Var &V : BlueprintVariables.Variables)
|
||||||
|
{
|
||||||
|
V.BPVar = WingUtils::FindOneWithInternalID(V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"));
|
||||||
|
if (V.BPVar == nullptr) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the type and the flags.
|
||||||
|
bool AnyDefaults = false;
|
||||||
|
for (Var &V : BlueprintVariables.Variables)
|
||||||
|
{
|
||||||
|
V.BPVar->VarType = V.Type;
|
||||||
|
ModifyBlueprintVariableFlags(V);
|
||||||
|
if (V.DefaultSpecified) AnyDefaults = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next step not needed if no defaults specified.
|
||||||
|
if (!AnyDefaults) return true;
|
||||||
|
|
||||||
|
FKismetEditorUtilities::CompileBlueprint(Blueprint);
|
||||||
|
|
||||||
|
UObject *CDO = WingUtils::GetGeneratedCDO(Blueprint);
|
||||||
|
if (!CDO)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("Cannot store variable defaults, blueprint didn't compile"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ModifyDefaultsAsProperties(BlueprintVariables, CDO)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::ModifyBlueprintVariableFlags(Var &Input)
|
||||||
|
{
|
||||||
|
FBPVariableDescription &Out = *Input.BPVar;
|
||||||
|
|
||||||
|
// InstanceEditable: absence means CPF_DisableEditOnInstance is set
|
||||||
|
if (Input.Flags.Contains(Flag_InstanceEditable))
|
||||||
|
Out.PropertyFlags &= ~CPF_DisableEditOnInstance;
|
||||||
|
else
|
||||||
|
Out.PropertyFlags |= CPF_DisableEditOnInstance;
|
||||||
|
|
||||||
|
if (Input.Flags.Contains(Flag_BlueprintReadOnly))
|
||||||
|
Out.PropertyFlags |= CPF_BlueprintReadOnly;
|
||||||
|
else
|
||||||
|
Out.PropertyFlags &= ~CPF_BlueprintReadOnly;
|
||||||
|
|
||||||
|
if (Input.Flags.Contains(Flag_ExposeToCinematics))
|
||||||
|
Out.PropertyFlags |= CPF_Interp;
|
||||||
|
else
|
||||||
|
Out.PropertyFlags &= ~CPF_Interp;
|
||||||
|
|
||||||
|
if (Input.Flags.Contains(Flag_ExposeOnSpawn))
|
||||||
|
Out.SetMetaData(FBlueprintMetadata::MD_ExposeOnSpawn, TEXT("true"));
|
||||||
|
else
|
||||||
|
Out.RemoveMetaData(FBlueprintMetadata::MD_ExposeOnSpawn);
|
||||||
|
|
||||||
|
if (Input.Flags.Contains(Flag_Private))
|
||||||
|
Out.SetMetaData(FBlueprintMetadata::MD_Private, TEXT("true"));
|
||||||
|
else
|
||||||
|
Out.RemoveMetaData(FBlueprintMetadata::MD_Private);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::ModifyDefaultsAsProperties(WingVariableList &List, UObject *CDO)
|
||||||
|
{
|
||||||
|
for (Var &Input : List.Variables)
|
||||||
{
|
{
|
||||||
if (Input.DefaultSpecified)
|
if (Input.DefaultSpecified)
|
||||||
{
|
{
|
||||||
FProperty* Prop = Blueprint->GeneratedClass->FindPropertyByName(Input.Name);
|
FProperty* Prop = CDO->GetClass()->FindPropertyByName(Input.Name);
|
||||||
if (!Prop)
|
if (!Prop)
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Variable exists in blueprint, but not the generated class, which is weird: %s."),
|
UWingServer::Printf(TEXT("Variable exists in blueprint, but not the generated class, which is weird: %s."),
|
||||||
*WingTokenizer::ExternalizeID(Input.Name));
|
*WingTokenizer::ExternalizeID(Input.Name));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!FWingProperty(Prop, CDO).SetText(Input.DefaultValue)) OK = false;
|
if (!FWingProperty(Prop, CDO).SetText(Input.DefaultValue)) return false;
|
||||||
}
|
|
||||||
}
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateLocalVariableTypes()
|
|
||||||
{
|
|
||||||
for (const Var &Input : Variables)
|
|
||||||
{
|
|
||||||
Input.BPVar->VarType = Input.Type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateLocalVariableFlags()
|
|
||||||
{
|
|
||||||
for (const Var &Input : Variables)
|
|
||||||
{
|
|
||||||
FBPVariableDescription &Out = *Input.BPVar;
|
|
||||||
// Currently, no supported flags for local variables.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::UpdateLocalVariableDefaults()
|
|
||||||
{
|
|
||||||
for (const Var &Input : Variables)
|
|
||||||
{
|
|
||||||
if (Input.DefaultSpecified)
|
|
||||||
{
|
|
||||||
Input.BPVar->DefaultValue = Input.DefaultValue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingVariables::UpdateEditablePinBaseTypes()
|
bool WingVariables::ModifyGraph()
|
||||||
{
|
{
|
||||||
for (const Var &Input : Variables)
|
if (!CheckGraph()) return false;
|
||||||
Input.Pin->PinType = Input.Type;
|
ClearLinks();
|
||||||
PinBase->ReconstructNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WingVariables::UpdateEditablePinBaseFlags()
|
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||||
{
|
UK2Node_FunctionEntry *LocalNode;
|
||||||
// Currently no flags apply to editable pin base pins.
|
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||||
}
|
|
||||||
|
|
||||||
bool WingVariables::UpdateEditablePinBaseDefaults()
|
for (Var &V : LocalVariables.Variables)
|
||||||
{
|
|
||||||
for (const Var &Input : Variables)
|
|
||||||
{
|
{
|
||||||
if (Input.DefaultSpecified)
|
FBPVariableDescription *Desc =
|
||||||
Input.Pin->PinDefaultValue = Input.DefaultValue;
|
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"));
|
||||||
|
if (Desc == nullptr) return false;
|
||||||
|
Desc->VarType = V.Type;
|
||||||
|
if (V.DefaultSpecified) Desc->DefaultValue = V.DefaultValue;
|
||||||
}
|
}
|
||||||
PinBase->ReconstructNode();
|
for (Var &V : InputVariables.Variables)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo> *Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, InputNode->UserDefinedPins, TEXT("input variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
(*Found)->PinType = V.Type;
|
||||||
|
if (V.DefaultSpecified) (*Found)->PinDefaultValue = V.DefaultValue;
|
||||||
|
}
|
||||||
|
for (Var &V : OutputVariables.Variables)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo> *Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, OutputNode->UserDefinedPins, TEXT("output variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
(*Found)->PinType = V.Type;
|
||||||
|
if (V.DefaultSpecified) (*Found)->PinDefaultValue = V.DefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputNode) InputNode->ReconstructNode();
|
||||||
|
if (OutputNode) OutputNode->ReconstructNode();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WingGraphVariables::LoadGraph(const UEdGraph *Graph)
|
bool WingVariables::GetGraphNodes(
|
||||||
|
UK2Node_EditablePinBase *&InputNode,
|
||||||
|
UK2Node_EditablePinBase *&OutputNode,
|
||||||
|
UK2Node_FunctionEntry *&LocalNode)
|
||||||
{
|
{
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
// In theory, none of these errors should trigger, because
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
// we call CheckSanity before calling this function. But
|
||||||
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
// you never know.
|
||||||
Arguments.LoadEditablePinBase(EntryNode.Get());
|
InputNode = nullptr;
|
||||||
ReturnValues.LoadEditablePinBase(ResultNode.Get());
|
OutputNode = nullptr;
|
||||||
LocalVariables.LoadLocalVariables(EntryNode.Get());
|
LocalNode = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
bool WingGraphVariables::ParseStrings(const FString &A, const FString &R, const FString &L)
|
TWeakObjectPtr<UK2Node_EditablePinBase> Inputs, Outputs;
|
||||||
{
|
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, Inputs, Outputs);
|
||||||
if (!Arguments.ParseString(A)) return false;
|
if (!Inputs.IsValid())
|
||||||
if (!ReturnValues.ParseString(R)) return false;
|
|
||||||
if (!LocalVariables.ParseString(L)) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WingGraphVariables::AssociateGraph(const UEdGraph *Graph)
|
|
||||||
{
|
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> ResultNode;
|
|
||||||
FBlueprintEditorUtils::GetEntryAndResultNodes(Graph, EntryNode, ResultNode);
|
|
||||||
bool OK = true;
|
|
||||||
if (!Arguments.AssociateEditablePinBase(EntryNode.Get())) OK = false;
|
|
||||||
if (!ReturnValues.AssociateEditablePinBase(ResultNode.Get())) OK = false;
|
|
||||||
if (!LocalVariables.AssociateLocalVariables(EntryNode.Get())) OK = false;
|
|
||||||
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) &&
|
UWingServer::Printf(TEXT("ERROR: no function entry node for graph."));
|
||||||
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!Outputs.IsValid() && (!OutputVariables.Variables.IsEmpty()))
|
||||||
|
{
|
||||||
|
Outputs = FBlueprintEditorUtils::FindOrCreateFunctionResultNode(Inputs.Get());
|
||||||
|
if (!Outputs.IsValid())
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("ERROR: couldn't create result node for graph."));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UK2Node_FunctionEntry *Locals = Cast<UK2Node_FunctionEntry>(Inputs.Get());
|
||||||
|
if (!Locals && (!LocalVariables.Variables.IsEmpty()))
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("ERROR: function doesn't have a proper entry node for local variables"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
InputNode = Inputs.Get();
|
||||||
|
OutputNode = Outputs.Get();
|
||||||
|
LocalNode = Locals;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
// // Create the variables.
|
||||||
|
// for (const WingVariables::Var& V : Vars.GetVariables())
|
||||||
|
// {
|
||||||
|
// if (!FBlueprintEditorUtils::AddMemberVariable(BP, V.Name, V.Type))
|
||||||
|
// {
|
||||||
|
// UWingServer::Printf(TEXT("ERROR: Failed to add variable '%s'\n"),
|
||||||
|
// *WingUtils::ExternalizeID(V.Name));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Check for name collisions against existing variables, components, and the like.
|
||||||
|
// TSet<FName> Names;
|
||||||
|
// FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
||||||
|
// if (!WingUtils::FindNoDuplicateNames(Names, Vars.GetVariables(), TEXT("variable or component"))) return;
|
||||||
|
|
||||||
|
|
||||||
|
// // Check for duplicate names against existing pins and locals.
|
||||||
|
// TSet<FName> Names;
|
||||||
|
// WingUtils::FindNoDuplicateNames(Names, EntryNode->UserDefinedPins, TEXT("local variables"));
|
||||||
|
// WingUtils::FindNoDuplicateNames(Names, ResultNode->UserDefinedPins, TEXT("local variables"));
|
||||||
|
// if (UK2Node_FunctionEntry* FuncEntry = Cast<UK2Node_FunctionEntry>(EntryNode.Get()))
|
||||||
|
// WingUtils::FindNoDuplicateNames(Names, FuncEntry->LocalVariables, TEXT("local variables"));
|
||||||
|
// if (!WingUtils::FindNoDuplicateNames(Names, Vars.Arguments.GetVariables(), TEXT("local variables"))) return;
|
||||||
|
// if (!WingUtils::FindNoDuplicateNames(Names, Vars.ReturnValues.GetVariables(), TEXT("local variables"))) return;
|
||||||
|
// if (!WingUtils::FindNoDuplicateNames(Names, Vars.LocalVariables.GetVariables(), TEXT("local variables"))) return;
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ public:
|
|||||||
static TArray<UEdGraphNode*> AllNodes(UBlueprint* BP);
|
static TArray<UEdGraphNode*> AllNodes(UBlueprint* BP);
|
||||||
static TArray<UEdGraphNode*> AllNodes(UEdGraph *Graph);
|
static TArray<UEdGraphNode*> AllNodes(UEdGraph *Graph);
|
||||||
static TArray<UBlueprint*> GetAncestorBlueprints(UBlueprint *BP, bool OldestFirst = false);
|
static TArray<UBlueprint*> GetAncestorBlueprints(UBlueprint *BP, bool OldestFirst = false);
|
||||||
|
static UObject *GetGeneratedCDO(UBlueprint *BP);
|
||||||
|
|
||||||
// ----- Material helpers -----
|
// ----- Material helpers -----
|
||||||
static void EnsureMaterialGraph(UMaterial* Material);
|
static void EnsureMaterialGraph(UMaterial* Material);
|
||||||
|
|||||||
@@ -7,23 +7,12 @@
|
|||||||
struct WingTokenizer;
|
struct WingTokenizer;
|
||||||
class UK2Node_EditablePinBase;
|
class UK2Node_EditablePinBase;
|
||||||
class UK2Node_FunctionEntry;
|
class UK2Node_FunctionEntry;
|
||||||
|
struct FUserPinInfo;
|
||||||
|
|
||||||
UENUM()
|
|
||||||
enum class EWingVariableCategory : uint8
|
|
||||||
{
|
|
||||||
BlueprintVariables,
|
|
||||||
LocalVariables,
|
|
||||||
FunctionArguments,
|
|
||||||
FunctionReturnValues,
|
|
||||||
MacroEntry,
|
|
||||||
MacroExit
|
|
||||||
};
|
|
||||||
|
|
||||||
class WingVariables
|
class WingVariableList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Cat = EWingVariableCategory;
|
|
||||||
|
|
||||||
struct Var
|
struct Var
|
||||||
{
|
{
|
||||||
// Internal name.
|
// Internal name.
|
||||||
@@ -36,7 +25,7 @@ public:
|
|||||||
FString DefaultValue;
|
FString DefaultValue;
|
||||||
|
|
||||||
// When parsing a string, true if default was specified.
|
// When parsing a string, true if default was specified.
|
||||||
bool DefaultSpecified = true;
|
bool DefaultSpecified = false;
|
||||||
|
|
||||||
// Boolean flags.
|
// Boolean flags.
|
||||||
TSet<FName> Flags;
|
TSet<FName> Flags;
|
||||||
@@ -48,109 +37,115 @@ public:
|
|||||||
// This is only populated if these variables are associated
|
// This is only populated if these variables are associated
|
||||||
// with an editable pin base.
|
// with an editable pin base.
|
||||||
TSharedPtr<FUserPinInfo> Pin = nullptr;
|
TSharedPtr<FUserPinInfo> Pin = nullptr;
|
||||||
|
|
||||||
// Add the flag if it's relevant to category C.
|
|
||||||
void AddFlagIfRelevant(FName Flag, Cat C);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
public:
|
||||||
// A list of all the variables.
|
// The actual list of variables.
|
||||||
TArray<Var> Variables;
|
TArray<Var> Variables;
|
||||||
|
|
||||||
// A pointer to a blueprint.
|
// The list has a name, which is used for generating good messages.
|
||||||
UBlueprint *Blueprint = nullptr;
|
const TCHAR *ListName;
|
||||||
|
|
||||||
// A pointer to a Function entry node.
|
// Constructor.
|
||||||
UK2Node_FunctionEntry *FuncEntry = nullptr;
|
WingVariableList(const TCHAR *MyListName) : ListName(MyListName) {}
|
||||||
|
|
||||||
// A pointer to an editable pin base.
|
// Return true if the variables are empty.
|
||||||
UK2Node_EditablePinBase* PinBase = nullptr;
|
void Empty() { Variables.Empty(); }
|
||||||
|
|
||||||
public:
|
// Print the variables to a string builder.
|
||||||
// Get the variables.
|
void Print(FStringBuilderBase &Out);
|
||||||
const TArray<Var> GetVariables() { return Variables; }
|
|
||||||
|
|
||||||
// Returns the set of flags that are supported by this variable category.
|
// Clear the BPVar and Pin fields.
|
||||||
static const TSet<FName> &GetRelevantFlagSet(Cat C);
|
void ClearLinks();
|
||||||
|
|
||||||
// Check if the variable list is empty.
|
// Check the sanity of the vars in the array. If allow
|
||||||
bool IsEmpty() const { return Variables.IsEmpty(); }
|
// is false, then no variables are allowed in the array.
|
||||||
|
bool CheckSanity(const TSet<FName> &GoodFlags, bool Allow);
|
||||||
|
|
||||||
// Print all the variables to a string builder.
|
// Parse variables from a string.
|
||||||
void PrintAll(FStringBuilderBase &Out, bool Always, const TCHAR *Header);
|
|
||||||
|
|
||||||
// Clear everything
|
|
||||||
void Clear();
|
|
||||||
|
|
||||||
// Clear any association.
|
|
||||||
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.
|
|
||||||
// Format: type name (flag1, flag2) = defaultvalue
|
|
||||||
// Returns false on parse error.
|
|
||||||
bool ParseString(const FString &Input);
|
bool ParseString(const FString &Input);
|
||||||
|
|
||||||
// Make a best effort to load all available existing state.
|
// Parse variable names only from a string.
|
||||||
// This does not associate the variables. If you want to manipulate
|
bool ParseNamesString(const FString &Input);
|
||||||
// the variables, you'll have to associate them.
|
|
||||||
void LoadBlueprintVariables(UBlueprint *BP);
|
|
||||||
void LoadLocalVariables(UK2Node_EditablePinBase* Node);
|
|
||||||
void LoadEditablePinBase(UK2Node_EditablePinBase* Node);
|
|
||||||
|
|
||||||
// Associate every variable in the list with an existing
|
|
||||||
// variable in a blueprint or graph.
|
|
||||||
bool AssociateBlueprintVariables(UBlueprint *BP);
|
|
||||||
bool AssociateLocalVariables(UK2Node_EditablePinBase* Node);
|
|
||||||
bool AssociateEditablePinBase(UK2Node_EditablePinBase* Node);
|
|
||||||
|
|
||||||
// Copy data from these variables into their associated blueprint variables.
|
|
||||||
void UpdateVariableTypes();
|
|
||||||
void UpdateVariableFlags();
|
|
||||||
bool UpdateVariableDefaults();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Var ParseVariableDescription(const FBPVariableDescription &V, Cat C);
|
bool ParseOneVariable(WingTokenizer &Tok, Var &V);
|
||||||
static bool ParseOneVariable(WingTokenizer &Tok, Var &Out);
|
bool ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out);
|
||||||
static bool ParseVariableFlags(WingTokenizer &Tok, TSet<FName> &Out);
|
|
||||||
|
|
||||||
void UpdateBlueprintVariableTypes();
|
|
||||||
void UpdateBlueprintVariableFlags();
|
|
||||||
bool UpdateBlueprintVariableDefaults();
|
|
||||||
void UpdateLocalVariableTypes();
|
|
||||||
void UpdateLocalVariableFlags();
|
|
||||||
bool UpdateLocalVariableDefaults();
|
|
||||||
void UpdateEditablePinBaseTypes();
|
|
||||||
void UpdateEditablePinBaseFlags();
|
|
||||||
bool UpdateEditablePinBaseDefaults();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WingGraphVariables
|
class WingVariables
|
||||||
{
|
{
|
||||||
WingVariables Arguments;
|
public:
|
||||||
WingVariables ReturnValues;
|
using Var = WingVariableList::Var;
|
||||||
WingVariables LocalVariables;
|
|
||||||
|
|
||||||
WingGraphVariables() {}
|
// The backing store. Only one of these should be set.
|
||||||
|
|
||||||
using Cat = WingVariables::Cat;
|
UBlueprint *Blueprint = nullptr;
|
||||||
|
UEdGraph *Graph = nullptr;
|
||||||
|
|
||||||
void LoadGraph(const UEdGraph *Graph);
|
// The Workspace. At any given time, these may or may not contain
|
||||||
bool AssociateGraph(const UEdGraph *Graph);
|
// the same data as the backing store.
|
||||||
bool ParseStrings(const FString &A, const FString &R, const FString &L);
|
|
||||||
void PrintAll(FStringBuilderBase &Out, bool Always);
|
WingVariableList BlueprintVariables{TEXT("Blueprint Variables")};
|
||||||
void UpdateVariableTypes();
|
WingVariableList LocalVariables{TEXT("Local Variables")};
|
||||||
void UpdateVariableFlags();
|
WingVariableList InputVariables{TEXT("Input Variables")};
|
||||||
bool UpdateVariableDefaults();
|
WingVariableList OutputVariables{TEXT("Output Variables")};
|
||||||
bool CheckSanity(const UEdGraph *Graph);
|
|
||||||
|
// Constructors. Just initialize the pointers to the backing store.
|
||||||
|
|
||||||
|
WingVariables(UBlueprint *BP) : Blueprint(BP) {}
|
||||||
|
WingVariables(UEdGraph *G) : Graph(G) {}
|
||||||
|
|
||||||
|
// Clear the workspace. Doesn't affect the backing store.
|
||||||
|
|
||||||
|
void Empty();
|
||||||
|
|
||||||
|
// Clear the BPVar and Pin fields.
|
||||||
|
|
||||||
|
void ClearLinks();
|
||||||
|
|
||||||
|
// Print the contents of the workspace.
|
||||||
|
|
||||||
|
void Print(FStringBuilderBase &Out);
|
||||||
|
|
||||||
|
// Load: clear the workspace, then
|
||||||
|
// copy everything from the backing store into the workspace.
|
||||||
|
|
||||||
|
void Load();
|
||||||
|
|
||||||
|
// Check: make sure the contents of the workspace makes sense
|
||||||
|
// given the type of backing store.
|
||||||
|
|
||||||
|
bool Check();
|
||||||
|
|
||||||
|
// Use the variables in the workspace to modify the backing store.
|
||||||
|
|
||||||
|
bool Modify();
|
||||||
|
|
||||||
|
// Create every variable in the workspace in the backing store.
|
||||||
|
|
||||||
|
bool Create() { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Cat GraphEntryCategory(const UEdGraph *Graph);
|
void LoadBlueprint();
|
||||||
static Cat GraphExitCategory(const UEdGraph *Graph);
|
void LoadGraph();
|
||||||
|
void LoadLocalVariables(UK2Node_EditablePinBase *Node);
|
||||||
|
Var LoadBlueprintVariableDescription(FBPVariableDescription &Desc, UObject *CDO);
|
||||||
|
Var LoadLocalVariableDescription(FBPVariableDescription &Desc);
|
||||||
|
void LoadEditablePinBase(UK2Node_EditablePinBase *Node, WingVariableList &List);
|
||||||
|
|
||||||
|
bool CheckBlueprint();
|
||||||
|
bool CheckGraph();
|
||||||
|
|
||||||
|
bool ModifyBlueprint();
|
||||||
|
void ModifyBlueprintVariableFlags(Var &Input);
|
||||||
|
bool ModifyDefaultsAsProperties(WingVariableList &List, UObject *CDO);
|
||||||
|
|
||||||
|
bool ModifyGraph();
|
||||||
|
|
||||||
|
bool GetGraphNodes(
|
||||||
|
UK2Node_EditablePinBase *&InputNode,
|
||||||
|
UK2Node_EditablePinBase *&OutputNode,
|
||||||
|
UK2Node_FunctionEntry *&LocalNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user