More work on variables
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingServer.h"
|
||||||
|
#include "WingHandler.h"
|
||||||
|
#include "WingFetcher.h"
|
||||||
|
#include "WingVariables.h"
|
||||||
|
#include "BlueprintVariable_Remove.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class UWing_BlueprintVariable_Remove : public UObject, public IWingHandler
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(meta=(Description="Blueprint path"))
|
||||||
|
FString Blueprint;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Description="Variable names to remove, comma-separated"))
|
||||||
|
FString Variables;
|
||||||
|
|
||||||
|
virtual FString GetDescription() const override
|
||||||
|
{
|
||||||
|
return TEXT("Remove member variables from a Blueprint.");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Handle() override
|
||||||
|
{
|
||||||
|
WingFetcher F;
|
||||||
|
UBlueprint* BP = F.Walk(Blueprint).Cast<UBlueprint>();
|
||||||
|
if (!BP) return;
|
||||||
|
|
||||||
|
WingVariables Vars(BP);
|
||||||
|
if (!Vars.BlueprintVariables.ParseNamesString(Variables)) return;
|
||||||
|
if (!Vars.Remove()) return;
|
||||||
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "WingServer.h"
|
||||||
|
#include "WingHandler.h"
|
||||||
|
#include "WingFetcher.h"
|
||||||
|
#include "WingVariables.h"
|
||||||
|
#include "GraphVariables_Remove.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
UCLASS()
|
||||||
|
class UWing_GraphVariables_Remove : public UObject, public IWingHandler
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
UPROPERTY(meta=(Description="Path to a function or macro graph"))
|
||||||
|
FString Graph;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Input variable names to remove, comma-separated"))
|
||||||
|
FString InputVariables;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Output variable names to remove, comma-separated"))
|
||||||
|
FString OutputVariables;
|
||||||
|
|
||||||
|
UPROPERTY(meta=(Optional, Description="Local variable names to remove, comma-separated"))
|
||||||
|
FString LocalVariables;
|
||||||
|
|
||||||
|
virtual FString GetDescription() const override
|
||||||
|
{
|
||||||
|
return TEXT("Remove inputs, outputs, and local variables from a graph.");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Handle() override
|
||||||
|
{
|
||||||
|
WingFetcher F;
|
||||||
|
UEdGraph* G = F.Walk(Graph).Cast<UEdGraph>();
|
||||||
|
if (!G) return;
|
||||||
|
|
||||||
|
WingVariables Vars(G);
|
||||||
|
if (!Vars.InputVariables.ParseNamesString(InputVariables)) return;
|
||||||
|
if (!Vars.OutputVariables.ParseNamesString(OutputVariables)) return;
|
||||||
|
if (!Vars.LocalVariables.ParseNamesString(LocalVariables)) return;
|
||||||
|
if (!Vars.Remove()) return;
|
||||||
|
UWingServer::Printf(TEXT("Success.\n"));
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -386,37 +386,25 @@ bool WingVariables::Modify()
|
|||||||
bool WingVariables::ModifyBlueprint()
|
bool WingVariables::ModifyBlueprint()
|
||||||
{
|
{
|
||||||
if (!CheckBlueprint()) return false;
|
if (!CheckBlueprint()) return false;
|
||||||
ClearLinks();
|
if (LinkBlueprintVariables()) return false;
|
||||||
|
|
||||||
// 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)
|
for (Var &V : BlueprintVariables.Variables)
|
||||||
{
|
{
|
||||||
V.BPVar->VarType = V.Type;
|
V.BPVar->VarType = V.Type;
|
||||||
ModifyBlueprintVariableFlags(V);
|
ModifyBlueprintVariableFlags(V);
|
||||||
if (V.DefaultSpecified) AnyDefaults = true;
|
|
||||||
}
|
}
|
||||||
|
if (!ModifyBlueprintDefaults()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Next step not needed if no defaults specified.
|
bool WingVariables::LinkBlueprintVariables()
|
||||||
if (!AnyDefaults) return true;
|
{
|
||||||
|
ClearLinks();
|
||||||
FKismetEditorUtilities::CompileBlueprint(Blueprint);
|
for (Var &V : BlueprintVariables.Variables)
|
||||||
|
|
||||||
UObject *CDO = WingUtils::GetGeneratedCDO(Blueprint);
|
|
||||||
if (!CDO)
|
|
||||||
{
|
{
|
||||||
UWingServer::Printf(TEXT("Cannot store variable defaults, blueprint didn't compile"));
|
V.BPVar = WingUtils::FindOneWithInternalID(
|
||||||
return false;
|
V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"));
|
||||||
|
if (V.BPVar == nullptr) return false;
|
||||||
}
|
}
|
||||||
if (!ModifyDefaultsAsProperties(BlueprintVariables, CDO)) return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,9 +439,22 @@ void WingVariables::ModifyBlueprintVariableFlags(Var &Input)
|
|||||||
Out.RemoveMetaData(FBlueprintMetadata::MD_Private);
|
Out.RemoveMetaData(FBlueprintMetadata::MD_Private);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WingVariables::ModifyDefaultsAsProperties(WingVariableList &List, UObject *CDO)
|
bool WingVariables::ModifyBlueprintDefaults()
|
||||||
{
|
{
|
||||||
for (Var &Input : List.Variables)
|
bool AnySpecified = false;
|
||||||
|
for (Var &Input : BlueprintVariables.Variables)
|
||||||
|
if (Input.DefaultSpecified) AnySpecified = true;
|
||||||
|
if (!AnySpecified) return true;
|
||||||
|
|
||||||
|
FKismetEditorUtilities::CompileBlueprint(Blueprint);
|
||||||
|
UObject *CDO = WingUtils::GetGeneratedCDO(Blueprint);
|
||||||
|
if (!CDO)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("Blueprint didn't compile, cannot store default values"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Var &Input : BlueprintVariables.Variables)
|
||||||
{
|
{
|
||||||
if (Input.DefaultSpecified)
|
if (Input.DefaultSpecified)
|
||||||
{
|
{
|
||||||
@@ -548,30 +549,169 @@ bool WingVariables::GetGraphNodes(
|
|||||||
LocalNode = Locals;
|
LocalNode = Locals;
|
||||||
return true;
|
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.
|
bool WingVariables::Create()
|
||||||
// TSet<FName> Names;
|
{
|
||||||
// FBlueprintEditorUtils::GetClassVariableList(BP, Names);
|
if (Blueprint) return CreateBlueprint();
|
||||||
// if (!WingUtils::FindNoDuplicateNames(Names, Vars.GetVariables(), TEXT("variable or component"))) return;
|
if (Graph) return CreateGraph();
|
||||||
|
check(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::CreateBlueprint()
|
||||||
|
{
|
||||||
|
if (!CheckBlueprint()) return false;
|
||||||
|
ClearLinks();
|
||||||
|
|
||||||
// // Check for duplicate names against existing pins and locals.
|
// Check for name collisions against existing variables, components, and the like.
|
||||||
// TSet<FName> Names;
|
TSet<FName> Names;
|
||||||
// WingUtils::FindNoDuplicateNames(Names, EntryNode->UserDefinedPins, TEXT("local variables"));
|
FBlueprintEditorUtils::GetClassVariableList(Blueprint, Names);
|
||||||
// WingUtils::FindNoDuplicateNames(Names, ResultNode->UserDefinedPins, TEXT("local variables"));
|
if (!WingUtils::FindNoDuplicateNames(Names, BlueprintVariables.Variables, TEXT("variable or component"))) return false;
|
||||||
// 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;
|
|
||||||
|
|
||||||
|
// Create the variables.
|
||||||
|
for (const WingVariables::Var& V : BlueprintVariables.Variables)
|
||||||
|
{
|
||||||
|
if (!FBlueprintEditorUtils::AddMemberVariable(Blueprint, V.Name, V.Type))
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("ERROR: Failed to add variable '%s'\n"),
|
||||||
|
*WingUtils::ExternalizeID(V.Name));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LinkBlueprintVariables()) return false;
|
||||||
|
for (Var &V : BlueprintVariables.Variables) ModifyBlueprintVariableFlags(V);
|
||||||
|
if (!ModifyBlueprintDefaults()) return false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::CreateGraph()
|
||||||
|
{
|
||||||
|
if (!CheckGraph()) return false;
|
||||||
|
ClearLinks();
|
||||||
|
|
||||||
|
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||||
|
UK2Node_FunctionEntry *LocalNode;
|
||||||
|
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||||
|
|
||||||
|
// Check for name collisions against existing local variables.
|
||||||
|
const TCHAR *ctx = TEXT("local, function input, and function output variables");
|
||||||
|
TSet<FName> Names;
|
||||||
|
if (InputNode && !WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, InputNode->UserDefinedPins, ctx)) return false;
|
||||||
|
if (OutputNode && !WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, OutputNode->UserDefinedPins, ctx)) return false;
|
||||||
|
if (LocalNode && !WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, LocalNode->LocalVariables, ctx)) return false;
|
||||||
|
if (!WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, InputVariables.Variables, ctx)) return false;
|
||||||
|
if (!WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, OutputVariables.Variables, ctx)) return false;
|
||||||
|
if (!WingUtils::FindNoDuplicateNames(
|
||||||
|
Names, LocalVariables.Variables, ctx)) return false;
|
||||||
|
|
||||||
|
// Create input pins on the input node.
|
||||||
|
for (const Var& V : InputVariables.Variables)
|
||||||
|
AddUserPinInfo(V, EGPD_Output, InputNode);
|
||||||
|
|
||||||
|
// Create output pins on the output node.
|
||||||
|
for (const Var& V : OutputVariables.Variables)
|
||||||
|
AddUserPinInfo(V, EGPD_Input, OutputNode);
|
||||||
|
|
||||||
|
// Create local variables via the proper API.
|
||||||
|
UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForGraph(Graph);
|
||||||
|
for (const Var& V : LocalVariables.Variables)
|
||||||
|
{
|
||||||
|
if (!FBlueprintEditorUtils::AddLocalVariable(BP, Graph, V.Name, V.Type, V.DefaultValue))
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("ERROR: Failed to create local variable '%s'\n"),
|
||||||
|
*WingUtils::ExternalizeID(V.Name));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputNode) InputNode->ReconstructNode();
|
||||||
|
if (OutputNode) OutputNode->ReconstructNode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WingVariables::AddUserPinInfo(const Var &V, EEdGraphPinDirection Dir, UK2Node_EditablePinBase *Node)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo> Result = MakeShareable( new FUserPinInfo() );
|
||||||
|
Result->PinName = V.Name;
|
||||||
|
Result->PinType = V.Type;
|
||||||
|
Result->PinDefaultValue = V.DefaultValue;
|
||||||
|
Result->DesiredPinDirection = Dir;
|
||||||
|
Node->UserDefinedPins.Add(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::Remove()
|
||||||
|
{
|
||||||
|
if (Blueprint) return RemoveBlueprint();
|
||||||
|
if (Graph) return RemoveGraph();
|
||||||
|
check(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::RemoveBlueprint()
|
||||||
|
{
|
||||||
|
// Verify that all named variables exist.
|
||||||
|
TArray<FName> Names;
|
||||||
|
for (const Var& V : BlueprintVariables.Variables)
|
||||||
|
{
|
||||||
|
FBPVariableDescription* Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, Blueprint->NewVariables, TEXT("non-inherited variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
Names.Add(V.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove them.
|
||||||
|
FBlueprintEditorUtils::BulkRemoveMemberVariables(Blueprint, Names);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WingVariables::RemoveGraph()
|
||||||
|
{
|
||||||
|
UK2Node_EditablePinBase *InputNode, *OutputNode;
|
||||||
|
UK2Node_FunctionEntry *LocalNode;
|
||||||
|
if (!GetGraphNodes(InputNode, OutputNode, LocalNode)) return false;
|
||||||
|
|
||||||
|
// Verify that all named variables exist before removing anything.
|
||||||
|
for (const Var& V : InputVariables.Variables)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo>* Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, InputNode->UserDefinedPins, TEXT("input variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
}
|
||||||
|
for (const Var& V : OutputVariables.Variables)
|
||||||
|
{
|
||||||
|
TSharedPtr<FUserPinInfo>* Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, OutputNode->UserDefinedPins, TEXT("output variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
}
|
||||||
|
for (const Var& V : LocalVariables.Variables)
|
||||||
|
{
|
||||||
|
FBPVariableDescription* Found =
|
||||||
|
WingUtils::FindOneWithInternalID(V.Name, LocalNode->LocalVariables, TEXT("local variable"));
|
||||||
|
if (!Found) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove input and output pins.
|
||||||
|
for (const Var& V : InputVariables.Variables)
|
||||||
|
InputNode->RemoveUserDefinedPinByName(V.Name);
|
||||||
|
for (const Var& V : OutputVariables.Variables)
|
||||||
|
OutputNode->RemoveUserDefinedPinByName(V.Name);
|
||||||
|
|
||||||
|
// Remove local variables.
|
||||||
|
UBlueprint* BP = FBlueprintEditorUtils::FindBlueprintForGraph(Graph);
|
||||||
|
for (const Var& V : LocalVariables.Variables)
|
||||||
|
{
|
||||||
|
LocalNode->LocalVariables.RemoveAll(
|
||||||
|
[&](const FBPVariableDescription& Desc) { return Desc.VarName == V.Name; });
|
||||||
|
FBlueprintEditorUtils::RemoveVariableNodes(BP, V.Name, true, Graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputNode) InputNode->ReconstructNode();
|
||||||
|
if (OutputNode) OutputNode->ReconstructNode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,7 +124,11 @@ public:
|
|||||||
|
|
||||||
// Create every variable in the workspace in the backing store.
|
// Create every variable in the workspace in the backing store.
|
||||||
|
|
||||||
bool Create() { return true; }
|
bool Create();
|
||||||
|
|
||||||
|
// Remove every variable mentioned in the workspace from the backing store.
|
||||||
|
|
||||||
|
bool Remove();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadBlueprint();
|
void LoadBlueprint();
|
||||||
@@ -138,14 +142,24 @@ private:
|
|||||||
bool CheckGraph();
|
bool CheckGraph();
|
||||||
|
|
||||||
bool ModifyBlueprint();
|
bool ModifyBlueprint();
|
||||||
|
bool LinkBlueprintVariables();
|
||||||
void ModifyBlueprintVariableFlags(Var &Input);
|
void ModifyBlueprintVariableFlags(Var &Input);
|
||||||
bool ModifyDefaultsAsProperties(WingVariableList &List, UObject *CDO);
|
bool ModifyBlueprintDefaults();
|
||||||
|
|
||||||
bool ModifyGraph();
|
bool ModifyGraph();
|
||||||
|
|
||||||
|
bool CreateBlueprint();
|
||||||
|
|
||||||
|
bool CreateGraph();
|
||||||
|
|
||||||
|
bool RemoveBlueprint();
|
||||||
|
bool RemoveGraph();
|
||||||
|
|
||||||
bool GetGraphNodes(
|
bool GetGraphNodes(
|
||||||
UK2Node_EditablePinBase *&InputNode,
|
UK2Node_EditablePinBase *&InputNode,
|
||||||
UK2Node_EditablePinBase *&OutputNode,
|
UK2Node_EditablePinBase *&OutputNode,
|
||||||
UK2Node_FunctionEntry *&LocalNode);
|
UK2Node_FunctionEntry *&LocalNode);
|
||||||
|
|
||||||
|
void AddUserPinInfo(const Var &V, EEdGraphPinDirection Dir, UK2Node_EditablePinBase *Node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user