You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Graph Visualizer: Replacing Control Rig AST visualizer with common service
#rb halfdan.ingvarsson #jira na #preflight https://horde.devtools.epicgames.com/job/614382398169560001036499 #ROBOMERGE-AUTHOR: helge.mathee #ROBOMERGE-SOURCE: CL 17735754 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v879-17706426) [CL 17735765 by helge mathee in ue5-release-engine-test branch]
This commit is contained in:
360
Engine/Source/Developer/VisualGraphUtils/Private/VisualGraph.cpp
Normal file
360
Engine/Source/Developer/VisualGraphUtils/Private/VisualGraph.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VisualGraph.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// FVisualGraphSubGraph
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FString FVisualGraphSubGraph::DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const
|
||||
{
|
||||
FString EdgeContent;
|
||||
|
||||
if(!Nodes.IsEmpty())
|
||||
{
|
||||
for(const FVisualGraphEdge& Edge : InGraph->GetEdges())
|
||||
{
|
||||
if(Nodes.Contains(Edge.GetSourceNode()) &&
|
||||
Nodes.Contains(Edge.GetTargetNode()))
|
||||
{
|
||||
EdgeContent += Edge.DumpDot(InGraph, InIndendation + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FString SubGraphContent;
|
||||
for(const FVisualGraphSubGraph& SubGraph : InGraph->GetSubGraphs())
|
||||
{
|
||||
if(SubGraph.GetParentGraphIndex() == GetIndex())
|
||||
{
|
||||
SubGraphContent += SubGraph.DumpDot(InGraph, InIndendation + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if(EdgeContent.IsEmpty() && SubGraphContent.IsEmpty())
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
|
||||
const FString Indentation1 = DumpDotIndentation(InIndendation);
|
||||
const FString Indentation2 = DumpDotIndentation(InIndendation + 1);
|
||||
const FString ColorContent = DumpDotColor(GetColor());
|
||||
const FString StyleContent = DumpDotStyle(GetStyle());
|
||||
|
||||
FString AttributeContent;
|
||||
if(DisplayName.IsSet())
|
||||
{
|
||||
AttributeContent += FString::Printf(TEXT("%slabel = \"%s\";\n"),
|
||||
*Indentation2, *DisplayName.GetValue().ToString());
|
||||
}
|
||||
if(!ColorContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += FString::Printf(TEXT("%scolor = %s;\n"),
|
||||
*Indentation2, *ColorContent);
|
||||
}
|
||||
if(!StyleContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += FString::Printf(TEXT("%sstyle = %s;\n"),
|
||||
*Indentation2, *StyleContent);
|
||||
}
|
||||
|
||||
return FString::Printf(TEXT("%ssubgraph cluster_%s {\n%s%s%s%s}\n"),
|
||||
*Indentation1, *GetName().ToString(),
|
||||
*AttributeContent,
|
||||
*EdgeContent,
|
||||
*SubGraphContent,
|
||||
*Indentation1
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// FVisualGraph
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FVisualGraph::FVisualGraph(const FName& InName, const FName& InDisplayName)
|
||||
{
|
||||
Name = InName;
|
||||
DisplayName = InDisplayName;
|
||||
Style = EVisualGraphStyle::Filled;
|
||||
}
|
||||
|
||||
int32 FVisualGraph::AddNode(const FName& InName, TOptional<FName> InDisplayName, TOptional<FLinearColor> InColor,
|
||||
TOptional<EVisualGraphShape> InShape, TOptional<EVisualGraphStyle> InStyle)
|
||||
{
|
||||
RefreshNameMapIfNeeded(Nodes, NodeNameMap);
|
||||
|
||||
const FName UniqueName = GetUniqueName(InName, NodeNameMap);
|
||||
FVisualGraphNode Node;
|
||||
Node.Name = UniqueName;
|
||||
Node.DisplayName = InDisplayName;
|
||||
Node.Color = InColor;
|
||||
Node.Shape = InShape;
|
||||
Node.Style = InStyle;
|
||||
Node.SubGraphIndex = INDEX_NONE;
|
||||
|
||||
return AddElement(Node, Nodes, NodeNameMap);
|
||||
}
|
||||
|
||||
int32 FVisualGraph::AddEdge(int32 InSourceNode, int32 InTargetNode, EVisualGraphEdgeDirection InDirection,
|
||||
const FName& InName, TOptional<FName> InDisplayName, TOptional<FLinearColor> InColor,
|
||||
TOptional<EVisualGraphStyle> InStyle)
|
||||
{
|
||||
RefreshNameMapIfNeeded(Edges, EdgeNameMap);
|
||||
|
||||
FName DesiredName = InName;
|
||||
if(DesiredName.IsNone())
|
||||
{
|
||||
DesiredName = TEXT("Edge");
|
||||
}
|
||||
|
||||
const FName UniqueName = GetUniqueName(DesiredName, EdgeNameMap);
|
||||
FVisualGraphEdge Edge;
|
||||
Edge.Name = UniqueName;
|
||||
Edge.DisplayName = InDisplayName;
|
||||
Edge.Color = InColor;
|
||||
Edge.Style = InStyle;
|
||||
Edge.SourceNode = InSourceNode;
|
||||
Edge.TargetNode = InTargetNode;
|
||||
Edge.Direction = InDirection;
|
||||
|
||||
return AddElement(Edge, Edges, EdgeNameMap);
|
||||
}
|
||||
|
||||
int32 FVisualGraph::AddSubGraph(const FName& InName, TOptional<FName> InDisplayName, int32 InParentGraphIndex,
|
||||
TOptional<FLinearColor> InColor, TOptional<EVisualGraphStyle> InStyle, const TArray<int32> InNodes)
|
||||
{
|
||||
RefreshNameMapIfNeeded(SubGraphs, SubGraphNameMap);
|
||||
|
||||
const FName UniqueName = GetUniqueName(InName, SubGraphNameMap);
|
||||
FVisualGraphSubGraph SubGraph;
|
||||
SubGraph.Name = UniqueName;
|
||||
SubGraph.DisplayName = InDisplayName;
|
||||
SubGraph.Color = InColor;
|
||||
SubGraph.Style = InStyle;
|
||||
SubGraph.ParentGraphIndex = InParentGraphIndex;
|
||||
|
||||
const int32 SubGraphIndex = AddElement(SubGraph, SubGraphs, SubGraphNameMap);
|
||||
|
||||
for(const int32 Node : InNodes)
|
||||
{
|
||||
AddNodeToSubGraph(Node, SubGraphIndex);
|
||||
}
|
||||
|
||||
return SubGraphIndex;
|
||||
}
|
||||
|
||||
int32 FVisualGraph::FindNode(const FName& InName) const
|
||||
{
|
||||
if(const int32* IndexPtr= NodeNameMap.Find(InName))
|
||||
{
|
||||
return *IndexPtr;
|
||||
}
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
int32 FVisualGraph::FindEdge(const FName& InName) const
|
||||
{
|
||||
if(const int32* IndexPtr= EdgeNameMap.Find(InName))
|
||||
{
|
||||
return *IndexPtr;
|
||||
}
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
int32 FVisualGraph::FindSubGraph(const FName& InName) const
|
||||
{
|
||||
if(const int32* IndexPtr= SubGraphNameMap.Find(InName))
|
||||
{
|
||||
return *IndexPtr;
|
||||
}
|
||||
return INDEX_NONE;
|
||||
}
|
||||
|
||||
bool FVisualGraph::AddNodeToSubGraph(int32 InNodeIndex, int32 InSubGraphIndex)
|
||||
{
|
||||
if(!Nodes.IsValidIndex(InNodeIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!SubGraphs.IsValidIndex(InSubGraphIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RemoveNodeFromSubGraph(InNodeIndex);
|
||||
SubGraphs[InSubGraphIndex].Nodes.Add(InNodeIndex);
|
||||
Nodes[InNodeIndex].SubGraphIndex = InSubGraphIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FVisualGraph::RemoveNodeFromSubGraph(int32 InNodeIndex)
|
||||
{
|
||||
if(!Nodes.IsValidIndex(InNodeIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(Nodes[InNodeIndex].SubGraphIndex == INDEX_NONE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!SubGraphs.IsValidIndex(Nodes[InNodeIndex].SubGraphIndex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SubGraphs[Nodes[InNodeIndex].SubGraphIndex].Nodes.Remove(InNodeIndex);
|
||||
Nodes[InNodeIndex].SubGraphIndex = INDEX_NONE;
|
||||
return true;
|
||||
}
|
||||
|
||||
FString FVisualGraph::DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const
|
||||
{
|
||||
check(InGraph == this);
|
||||
|
||||
const FString Indentation = DumpDotIndentation(InIndendation);
|
||||
const FString Indentation2 = DumpDotIndentation(InIndendation + 1);
|
||||
|
||||
const FString ColorContent = DumpDotColor(GetColor());
|
||||
const FString StyleContent = DumpDotStyle(GetStyle());
|
||||
FString AttributeContent;
|
||||
if(!ColorContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("color = %s"), *ColorContent);
|
||||
}
|
||||
if(!StyleContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("style = %s"), *StyleContent);
|
||||
}
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent = FString::Printf(TEXT("%snode [ %s ];\n"), *Indentation2, *AttributeContent);
|
||||
}
|
||||
|
||||
FString SubGraphContent;
|
||||
for(const FVisualGraphSubGraph& SubGraph : SubGraphs)
|
||||
{
|
||||
if(SubGraph.GetParentGraphIndex() == INDEX_NONE)
|
||||
{
|
||||
SubGraphContent += SubGraph.DumpDot(this, InIndendation + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool bIsDirectedGraph = true;
|
||||
FString EdgeContent;
|
||||
for(const FVisualGraphEdge& Edge : Edges)
|
||||
{
|
||||
if(Edge.GetDirection() == EVisualGraphEdgeDirection::BothWays)
|
||||
{
|
||||
bIsDirectedGraph = false;
|
||||
}
|
||||
|
||||
const FVisualGraphNode& SourceNode = Nodes[Edge.GetSourceNode()];
|
||||
const FVisualGraphNode& TargetNode = Nodes[Edge.GetTargetNode()];
|
||||
|
||||
// if both source and target node are within the same subgraph
|
||||
if((SourceNode.SubGraphIndex == TargetNode.SubGraphIndex) &&
|
||||
(SourceNode.SubGraphIndex != INDEX_NONE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EdgeContent += Edge.DumpDot(this, InIndendation + 1);
|
||||
}
|
||||
|
||||
FString NodeContent;
|
||||
for(const FVisualGraphNode& Node : Nodes)
|
||||
{
|
||||
NodeContent += Node.DumpDot(this, InIndendation + 1);
|
||||
}
|
||||
|
||||
const FString GraphToken = bIsDirectedGraph ? TEXT("digraph") : TEXT("graph");
|
||||
return FString::Printf(TEXT("%s%s %s {\n%srankdir=\"LR\";\n%s%s%s%s%s}\n"),
|
||||
*Indentation, *GraphToken, *GetName().ToString(),
|
||||
*Indentation2,
|
||||
*AttributeContent,
|
||||
*SubGraphContent,
|
||||
*EdgeContent,
|
||||
*NodeContent,
|
||||
*Indentation
|
||||
);
|
||||
}
|
||||
|
||||
bool FVisualGraph::IsNameAvailable(const FName& InName, const TMap<FName, int32>& InMap)
|
||||
{
|
||||
return !InMap.Contains(InName);
|
||||
}
|
||||
|
||||
FName FVisualGraph::GetUniqueName(const FName& InName, const TMap<FName, int32>& InMap)
|
||||
{
|
||||
const FName DesiredName = InName;
|
||||
FName Name = DesiredName;
|
||||
int32 Suffix = 0;
|
||||
while (!IsNameAvailable(Name, InMap))
|
||||
{
|
||||
Suffix++;
|
||||
Name = *FString::Printf(TEXT("%s_%d"), *DesiredName.ToString(), Suffix);
|
||||
}
|
||||
return Name;
|
||||
}
|
||||
|
||||
void FVisualGraph::TransitiveReduction(TFunction<bool(FVisualGraphEdge&)> KeepEdgeFunction)
|
||||
{
|
||||
// mark up all valid edges
|
||||
TArray<int32> ValidEdge;
|
||||
ValidEdge.AddUninitialized(Nodes.Num() * Nodes.Num());
|
||||
for(int32 EdgeIndex = 0; EdgeIndex < ValidEdge.Num(); EdgeIndex++)
|
||||
{
|
||||
ValidEdge[EdgeIndex] = -1;
|
||||
}
|
||||
for(const FVisualGraphEdge& Edge : Edges)
|
||||
{
|
||||
const int32 EdgeIndex = Edge.GetSourceNode() * Nodes.Num() + Edge.GetTargetNode();
|
||||
ValidEdge[EdgeIndex] = Edge.GetIndex();
|
||||
}
|
||||
|
||||
|
||||
TArray<int32> EdgesToRemove;
|
||||
|
||||
// perform transitive reduction on the graph
|
||||
for(const FVisualGraphNode& NodeA : Nodes)
|
||||
{
|
||||
for(const FVisualGraphNode& NodeB : Nodes)
|
||||
{
|
||||
for(const FVisualGraphNode& NodeC : Nodes)
|
||||
{
|
||||
const int32 EdgeIndexAB = NodeA.GetIndex() * Nodes.Num() + NodeB.GetIndex();
|
||||
const int32 EdgeIndexBC = NodeB.GetIndex() * Nodes.Num() + NodeC.GetIndex();
|
||||
const int32 EdgeIndexAC = NodeA.GetIndex() * Nodes.Num() + NodeC.GetIndex();
|
||||
|
||||
if(ValidEdge[EdgeIndexAC] != INDEX_NONE &&
|
||||
ValidEdge[EdgeIndexAB] != INDEX_NONE &&
|
||||
ValidEdge[EdgeIndexBC] != INDEX_NONE)
|
||||
{
|
||||
const int32 EdgeIndex = ValidEdge[EdgeIndexAC];
|
||||
if(!KeepEdgeFunction(Edges[EdgeIndex]))
|
||||
{
|
||||
EdgesToRemove.AddUnique(EdgeIndex);
|
||||
}
|
||||
ValidEdge[EdgeIndexAC] = INDEX_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Algo::Sort(EdgesToRemove);
|
||||
Algo::Reverse(EdgesToRemove);
|
||||
|
||||
for(const int32 EdgeToRemove : EdgesToRemove)
|
||||
{
|
||||
Edges.RemoveAt(EdgeToRemove);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
#include "VisualGraphEdge.h"
|
||||
#include "VisualGraph.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// FVisualGraphEdge
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FString FVisualGraphEdge::DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const
|
||||
{
|
||||
const FString Indentation = DumpDotIndentation(InIndendation);
|
||||
const FString ColorContent = DumpDotColor(GetColor());
|
||||
const FString StyleContent = DumpDotStyle(GetStyle());
|
||||
|
||||
static const FString DigraphConnector = TEXT("->");
|
||||
static const FString GraphConnector = TEXT("--");
|
||||
const FString& ConnectorContent = (GetDirection() == EVisualGraphEdgeDirection::BothWays) ? GraphConnector : DigraphConnector;
|
||||
|
||||
FString SourceNodeName = InGraph->GetNodes()[GetSourceNode()].GetName().ToString();
|
||||
FString TargetNodeName = InGraph->GetNodes()[GetTargetNode()].GetName().ToString();
|
||||
|
||||
if(GetDirection() == EVisualGraphEdgeDirection::SourceToTarget)
|
||||
{
|
||||
Swap(SourceNodeName, TargetNodeName);
|
||||
}
|
||||
|
||||
FString AttributeContent;
|
||||
if(DisplayName.IsSet())
|
||||
{
|
||||
AttributeContent += FString::Printf(TEXT("label = \"%s\""), *DisplayName.GetValue().ToString());
|
||||
}
|
||||
if(Tooltip.IsSet())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("tooltip = \"%s\""), *Tooltip.GetValue());
|
||||
}
|
||||
if(!ColorContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("color = %s"), *ColorContent);
|
||||
}
|
||||
if(!StyleContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("style = %s"), *StyleContent);
|
||||
}
|
||||
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent = FString::Printf(TEXT(" [ %s ]"), *AttributeContent);
|
||||
}
|
||||
|
||||
return FString::Printf(TEXT("%s%s %s %s%s;\n"),
|
||||
*Indentation, *SourceNodeName, *ConnectorContent, *TargetNodeName, *AttributeContent);
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VisualGraphElement.h"
|
||||
#include "VisualGraph.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// FVisualGraphElement
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FString FVisualGraphElement::DumpDotIndentation(int32 InIndentation)
|
||||
{
|
||||
check(InIndentation >= 0);
|
||||
|
||||
static TArray<FString> Indentations;
|
||||
while(Indentations.Num() <= InIndentation)
|
||||
{
|
||||
const int32 Indentation = Indentations.Num();
|
||||
if(Indentation == 0)
|
||||
{
|
||||
Indentations.Add(FString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Indentations.Add(Indentations[Indentation - 1] + TEXT(" "));
|
||||
}
|
||||
}
|
||||
|
||||
return Indentations[InIndentation];
|
||||
}
|
||||
|
||||
FString FVisualGraphElement::DumpDotColor(const TOptional<FLinearColor>& InColor)
|
||||
{
|
||||
if(!InColor.IsSet())
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
|
||||
const FLinearColor Color = InColor.GetValue();
|
||||
|
||||
static TMap<FName, FLinearColor> ColorScheme;
|
||||
if(ColorScheme.IsEmpty())
|
||||
{
|
||||
ColorScheme.Add(TEXT("alice blue"), FColor::FromHex(TEXT("#F0F8FF")));
|
||||
ColorScheme.Add(TEXT("antique white"), FColor::FromHex(TEXT("#FAEBD7")));
|
||||
//ColorScheme.Add(TEXT("aqua"), FColor::FromHex(TEXT("#00FFFF")));
|
||||
ColorScheme.Add(TEXT("aquamarine"), FColor::FromHex(TEXT("#7FFFD4")));
|
||||
ColorScheme.Add(TEXT("azure"), FColor::FromHex(TEXT("#F0FFFF")));
|
||||
ColorScheme.Add(TEXT("beige"), FColor::FromHex(TEXT("#F5F5DC")));
|
||||
ColorScheme.Add(TEXT("bisque"), FColor::FromHex(TEXT("#FFE4C4")));
|
||||
ColorScheme.Add(TEXT("black"), FColor::FromHex(TEXT("#000000")));
|
||||
ColorScheme.Add(TEXT("blanched almond"), FColor::FromHex(TEXT("#FFEBCD")));
|
||||
ColorScheme.Add(TEXT("blue"), FColor::FromHex(TEXT("#0000FF")));
|
||||
ColorScheme.Add(TEXT("blue violet"), FColor::FromHex(TEXT("#8A2BE2")));
|
||||
ColorScheme.Add(TEXT("brown"), FColor::FromHex(TEXT("#A52A2A")));
|
||||
ColorScheme.Add(TEXT("burlywood"), FColor::FromHex(TEXT("#DEB887")));
|
||||
ColorScheme.Add(TEXT("cadet blue"), FColor::FromHex(TEXT("#5F9EA0")));
|
||||
ColorScheme.Add(TEXT("chartreuse"), FColor::FromHex(TEXT("#7FFF00")));
|
||||
ColorScheme.Add(TEXT("chocolate"), FColor::FromHex(TEXT("#D2691E")));
|
||||
ColorScheme.Add(TEXT("coral"), FColor::FromHex(TEXT("#FF7F50")));
|
||||
ColorScheme.Add(TEXT("cornflower blue"), FColor::FromHex(TEXT("#6495ED")));
|
||||
ColorScheme.Add(TEXT("cornsilk"), FColor::FromHex(TEXT("#FFF8DC")));
|
||||
ColorScheme.Add(TEXT("crimson"), FColor::FromHex(TEXT("#DC143C")));
|
||||
ColorScheme.Add(TEXT("cyan"), FColor::FromHex(TEXT("#00FFFF")));
|
||||
ColorScheme.Add(TEXT("dark blue"), FColor::FromHex(TEXT("#00008B")));
|
||||
ColorScheme.Add(TEXT("dark cyan"), FColor::FromHex(TEXT("#008B8B")));
|
||||
ColorScheme.Add(TEXT("dark goldenrod"), FColor::FromHex(TEXT("#B8860B")));
|
||||
ColorScheme.Add(TEXT("dark gray"), FColor::FromHex(TEXT("#A9A9A9")));
|
||||
ColorScheme.Add(TEXT("dark green"), FColor::FromHex(TEXT("#006400")));
|
||||
ColorScheme.Add(TEXT("dark khaki"), FColor::FromHex(TEXT("#BDB76B")));
|
||||
ColorScheme.Add(TEXT("dark magenta"), FColor::FromHex(TEXT("#8B008B")));
|
||||
ColorScheme.Add(TEXT("dark olive green"), FColor::FromHex(TEXT("#556B2F")));
|
||||
ColorScheme.Add(TEXT("dark orange"), FColor::FromHex(TEXT("#FF8C00")));
|
||||
ColorScheme.Add(TEXT("dark orchid"), FColor::FromHex(TEXT("#9932CC")));
|
||||
ColorScheme.Add(TEXT("dark red"), FColor::FromHex(TEXT("#8B0000")));
|
||||
ColorScheme.Add(TEXT("dark salmon"), FColor::FromHex(TEXT("#E9967A")));
|
||||
ColorScheme.Add(TEXT("dark sea green"), FColor::FromHex(TEXT("#8FBC8F")));
|
||||
ColorScheme.Add(TEXT("dark slate blue"), FColor::FromHex(TEXT("#483D8B")));
|
||||
ColorScheme.Add(TEXT("dark slate gray"), FColor::FromHex(TEXT("#2F4F4F")));
|
||||
ColorScheme.Add(TEXT("dark turquoise"), FColor::FromHex(TEXT("#00CED1")));
|
||||
ColorScheme.Add(TEXT("dark violet"), FColor::FromHex(TEXT("#9400D3")));
|
||||
ColorScheme.Add(TEXT("deep pink"), FColor::FromHex(TEXT("#FF1493")));
|
||||
ColorScheme.Add(TEXT("deep sky blue"), FColor::FromHex(TEXT("#00BFFF")));
|
||||
ColorScheme.Add(TEXT("dim gray"), FColor::FromHex(TEXT("#696969")));
|
||||
ColorScheme.Add(TEXT("dodger blue"), FColor::FromHex(TEXT("#1E90FF")));
|
||||
ColorScheme.Add(TEXT("firebrick"), FColor::FromHex(TEXT("#B22222")));
|
||||
ColorScheme.Add(TEXT("floral white"), FColor::FromHex(TEXT("#FFFAF0")));
|
||||
ColorScheme.Add(TEXT("forest green"), FColor::FromHex(TEXT("#228B22")));
|
||||
ColorScheme.Add(TEXT("fuchsia"), FColor::FromHex(TEXT("#FF00FF")));
|
||||
ColorScheme.Add(TEXT("gainsboro"), FColor::FromHex(TEXT("#DCDCDC")));
|
||||
ColorScheme.Add(TEXT("ghost white"), FColor::FromHex(TEXT("#F8F8FF")));
|
||||
ColorScheme.Add(TEXT("gold"), FColor::FromHex(TEXT("#FFD700")));
|
||||
ColorScheme.Add(TEXT("goldenrod"), FColor::FromHex(TEXT("#DAA520")));
|
||||
ColorScheme.Add(TEXT("gray"), FColor::FromHex(TEXT("#BEBEBE")));
|
||||
ColorScheme.Add(TEXT("web gray"), FColor::FromHex(TEXT("#808080")));
|
||||
ColorScheme.Add(TEXT("green"), FColor::FromHex(TEXT("#00FF00")));
|
||||
ColorScheme.Add(TEXT("web green"), FColor::FromHex(TEXT("#008000")));
|
||||
ColorScheme.Add(TEXT("green yellow"), FColor::FromHex(TEXT("#ADFF2F")));
|
||||
ColorScheme.Add(TEXT("honeydew"), FColor::FromHex(TEXT("#F0FFF0")));
|
||||
ColorScheme.Add(TEXT("hot pink"), FColor::FromHex(TEXT("#FF69B4")));
|
||||
ColorScheme.Add(TEXT("indian red"), FColor::FromHex(TEXT("#CD5C5C")));
|
||||
ColorScheme.Add(TEXT("indigo"), FColor::FromHex(TEXT("#4B0082")));
|
||||
ColorScheme.Add(TEXT("ivory"), FColor::FromHex(TEXT("#FFFFF0")));
|
||||
ColorScheme.Add(TEXT("khaki"), FColor::FromHex(TEXT("#F0E68C")));
|
||||
ColorScheme.Add(TEXT("lavender"), FColor::FromHex(TEXT("#E6E6FA")));
|
||||
ColorScheme.Add(TEXT("lavender blush"), FColor::FromHex(TEXT("#FFF0F5")));
|
||||
ColorScheme.Add(TEXT("lawn green"), FColor::FromHex(TEXT("#7CFC00")));
|
||||
ColorScheme.Add(TEXT("lemon chiffon"), FColor::FromHex(TEXT("#FFFACD")));
|
||||
ColorScheme.Add(TEXT("light blue"), FColor::FromHex(TEXT("#ADD8E6")));
|
||||
ColorScheme.Add(TEXT("light coral"), FColor::FromHex(TEXT("#F08080")));
|
||||
ColorScheme.Add(TEXT("light cyan"), FColor::FromHex(TEXT("#E0FFFF")));
|
||||
ColorScheme.Add(TEXT("light goldenrod"), FColor::FromHex(TEXT("#FAFAD2")));
|
||||
ColorScheme.Add(TEXT("light gray"), FColor::FromHex(TEXT("#D3D3D3")));
|
||||
ColorScheme.Add(TEXT("light green"), FColor::FromHex(TEXT("#90EE90")));
|
||||
ColorScheme.Add(TEXT("light pink"), FColor::FromHex(TEXT("#FFB6C1")));
|
||||
ColorScheme.Add(TEXT("light salmon"), FColor::FromHex(TEXT("#FFA07A")));
|
||||
ColorScheme.Add(TEXT("light sea green"), FColor::FromHex(TEXT("#20B2AA")));
|
||||
ColorScheme.Add(TEXT("light sky blue"), FColor::FromHex(TEXT("#87CEFA")));
|
||||
ColorScheme.Add(TEXT("light slate gray"), FColor::FromHex(TEXT("#778899")));
|
||||
ColorScheme.Add(TEXT("light steel blue"), FColor::FromHex(TEXT("#B0C4DE")));
|
||||
ColorScheme.Add(TEXT("light yellow"), FColor::FromHex(TEXT("#FFFFE0")));
|
||||
ColorScheme.Add(TEXT("lime"), FColor::FromHex(TEXT("#00FF00")));
|
||||
ColorScheme.Add(TEXT("lime green"), FColor::FromHex(TEXT("#32CD32")));
|
||||
ColorScheme.Add(TEXT("linen"), FColor::FromHex(TEXT("#FAF0E6")));
|
||||
ColorScheme.Add(TEXT("magenta"), FColor::FromHex(TEXT("#FF00FF")));
|
||||
ColorScheme.Add(TEXT("maroon"), FColor::FromHex(TEXT("#B03060")));
|
||||
ColorScheme.Add(TEXT("web maroon"), FColor::FromHex(TEXT("#800000")));
|
||||
ColorScheme.Add(TEXT("medium aquamarine"), FColor::FromHex(TEXT("#66CDAA")));
|
||||
ColorScheme.Add(TEXT("medium blue"), FColor::FromHex(TEXT("#0000CD")));
|
||||
ColorScheme.Add(TEXT("medium orchid"), FColor::FromHex(TEXT("#BA55D3")));
|
||||
ColorScheme.Add(TEXT("medium purple"), FColor::FromHex(TEXT("#9370DB")));
|
||||
ColorScheme.Add(TEXT("medium sea green"), FColor::FromHex(TEXT("#3CB371")));
|
||||
ColorScheme.Add(TEXT("medium slate blue"), FColor::FromHex(TEXT("#7B68EE")));
|
||||
ColorScheme.Add(TEXT("medium spring green"), FColor::FromHex(TEXT("#00FA9A")));
|
||||
ColorScheme.Add(TEXT("medium turquoise"), FColor::FromHex(TEXT("#48D1CC")));
|
||||
ColorScheme.Add(TEXT("medium violet red"), FColor::FromHex(TEXT("#C71585")));
|
||||
ColorScheme.Add(TEXT("midnight blue"), FColor::FromHex(TEXT("#191970")));
|
||||
ColorScheme.Add(TEXT("mint cream"), FColor::FromHex(TEXT("#F5FFFA")));
|
||||
ColorScheme.Add(TEXT("misty rose"), FColor::FromHex(TEXT("#FFE4E1")));
|
||||
ColorScheme.Add(TEXT("moccasin"), FColor::FromHex(TEXT("#FFE4B5")));
|
||||
ColorScheme.Add(TEXT("navajo white"), FColor::FromHex(TEXT("#FFDEAD")));
|
||||
ColorScheme.Add(TEXT("navy blue"), FColor::FromHex(TEXT("#000080")));
|
||||
ColorScheme.Add(TEXT("old lace"), FColor::FromHex(TEXT("#FDF5E6")));
|
||||
ColorScheme.Add(TEXT("olive"), FColor::FromHex(TEXT("#808000")));
|
||||
ColorScheme.Add(TEXT("olive drab"), FColor::FromHex(TEXT("#6B8E23")));
|
||||
ColorScheme.Add(TEXT("orange"), FColor::FromHex(TEXT("#FFA500")));
|
||||
ColorScheme.Add(TEXT("orange red"), FColor::FromHex(TEXT("#FF4500")));
|
||||
ColorScheme.Add(TEXT("orchid"), FColor::FromHex(TEXT("#DA70D6")));
|
||||
ColorScheme.Add(TEXT("pale goldenrod"), FColor::FromHex(TEXT("#EEE8AA")));
|
||||
ColorScheme.Add(TEXT("pale green"), FColor::FromHex(TEXT("#98FB98")));
|
||||
ColorScheme.Add(TEXT("pale turquoise"), FColor::FromHex(TEXT("#AFEEEE")));
|
||||
ColorScheme.Add(TEXT("pale violet red"), FColor::FromHex(TEXT("#DB7093")));
|
||||
ColorScheme.Add(TEXT("papaya whip"), FColor::FromHex(TEXT("#FFEFD5")));
|
||||
ColorScheme.Add(TEXT("peach puff"), FColor::FromHex(TEXT("#FFDAB9")));
|
||||
ColorScheme.Add(TEXT("peru"), FColor::FromHex(TEXT("#CD853F")));
|
||||
ColorScheme.Add(TEXT("pink"), FColor::FromHex(TEXT("#FFC0CB")));
|
||||
ColorScheme.Add(TEXT("plum"), FColor::FromHex(TEXT("#DDA0DD")));
|
||||
ColorScheme.Add(TEXT("powder blue"), FColor::FromHex(TEXT("#B0E0E6")));
|
||||
ColorScheme.Add(TEXT("purple"), FColor::FromHex(TEXT("#A020F0")));
|
||||
ColorScheme.Add(TEXT("web purple"), FColor::FromHex(TEXT("#800080")));
|
||||
ColorScheme.Add(TEXT("rebecca purple"), FColor::FromHex(TEXT("#663399")));
|
||||
ColorScheme.Add(TEXT("red"), FColor::FromHex(TEXT("#FF0000")));
|
||||
ColorScheme.Add(TEXT("rosy brown"), FColor::FromHex(TEXT("#BC8F8F")));
|
||||
ColorScheme.Add(TEXT("royal blue"), FColor::FromHex(TEXT("#4169E1")));
|
||||
ColorScheme.Add(TEXT("saddle brown"), FColor::FromHex(TEXT("#8B4513")));
|
||||
ColorScheme.Add(TEXT("salmon"), FColor::FromHex(TEXT("#FA8072")));
|
||||
ColorScheme.Add(TEXT("sandy brown"), FColor::FromHex(TEXT("#F4A460")));
|
||||
ColorScheme.Add(TEXT("sea green"), FColor::FromHex(TEXT("#2E8B57")));
|
||||
ColorScheme.Add(TEXT("seashell"), FColor::FromHex(TEXT("#FFF5EE")));
|
||||
ColorScheme.Add(TEXT("sienna"), FColor::FromHex(TEXT("#A0522D")));
|
||||
ColorScheme.Add(TEXT("silver"), FColor::FromHex(TEXT("#C0C0C0")));
|
||||
ColorScheme.Add(TEXT("sky blue"), FColor::FromHex(TEXT("#87CEEB")));
|
||||
ColorScheme.Add(TEXT("slate blue"), FColor::FromHex(TEXT("#6A5ACD")));
|
||||
ColorScheme.Add(TEXT("slate gray"), FColor::FromHex(TEXT("#708090")));
|
||||
ColorScheme.Add(TEXT("snow"), FColor::FromHex(TEXT("#FFFAFA")));
|
||||
ColorScheme.Add(TEXT("spring green"), FColor::FromHex(TEXT("#00FF7F")));
|
||||
ColorScheme.Add(TEXT("steel blue"), FColor::FromHex(TEXT("#4682B4")));
|
||||
ColorScheme.Add(TEXT("tan"), FColor::FromHex(TEXT("#D2B48C")));
|
||||
ColorScheme.Add(TEXT("teal"), FColor::FromHex(TEXT("#008080")));
|
||||
ColorScheme.Add(TEXT("thistle"), FColor::FromHex(TEXT("#D8BFD8")));
|
||||
ColorScheme.Add(TEXT("tomato"), FColor::FromHex(TEXT("#FF6347")));
|
||||
ColorScheme.Add(TEXT("turquoise"), FColor::FromHex(TEXT("#40E0D0")));
|
||||
ColorScheme.Add(TEXT("violet"), FColor::FromHex(TEXT("#EE82EE")));
|
||||
ColorScheme.Add(TEXT("wheat"), FColor::FromHex(TEXT("#F5DEB3")));
|
||||
ColorScheme.Add(TEXT("white"), FColor::FromHex(TEXT("#FFFFFF")));
|
||||
ColorScheme.Add(TEXT("white smoke"), FColor::FromHex(TEXT("#F5F5F5")));
|
||||
ColorScheme.Add(TEXT("yellow"), FColor::FromHex(TEXT("#FFFF00")));
|
||||
ColorScheme.Add(TEXT("yellow green"), FColor::FromHex(TEXT("#9ACD32")));
|
||||
}
|
||||
|
||||
FName SchemeName = NAME_None;
|
||||
float MinDelta = FLT_MAX;
|
||||
for(const TPair<FName, FLinearColor>& Pair : ColorScheme)
|
||||
{
|
||||
const float Delta = FLinearColor::Dist(Pair.Value, Color);
|
||||
if(MinDelta > Delta)
|
||||
{
|
||||
MinDelta = Delta;
|
||||
SchemeName = Pair.Key;
|
||||
}
|
||||
}
|
||||
|
||||
FString SchemeString = SchemeName.ToString();
|
||||
SchemeString.RemoveSpacesInline();
|
||||
return SchemeString;
|
||||
}
|
||||
|
||||
FString FVisualGraphElement::DumpDotShape(const TOptional<EVisualGraphShape>& InShape)
|
||||
{
|
||||
if(!InShape.IsSet())
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
return StaticEnum<EVisualGraphShape>()->GetDisplayNameTextByValue((int64)InShape.GetValue()).ToString().ToLower();
|
||||
}
|
||||
|
||||
FString FVisualGraphElement::DumpDotStyle(const TOptional<EVisualGraphStyle>& InStyle)
|
||||
{
|
||||
if(!InStyle.IsSet())
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
return StaticEnum<EVisualGraphStyle>()->GetDisplayNameTextByValue((int64)InStyle.GetValue()).ToString().ToLower();
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VisualGraphNode.h"
|
||||
#include "VisualGraph.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/// FVisualGraphNode
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FString FVisualGraphNode::DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const
|
||||
{
|
||||
const FString Indentation = DumpDotIndentation(InIndendation);
|
||||
const FString StyleContent = DumpDotStyle(GetStyle());
|
||||
const FString ShapeContent = DumpDotShape(GetShape());
|
||||
const FString ColorContent = DumpDotColor(GetColor());
|
||||
|
||||
FString AttributeContent;
|
||||
if(DisplayName.IsSet())
|
||||
{
|
||||
AttributeContent += FString::Printf(TEXT("label = \"%s\""), *DisplayName.GetValue().ToString());
|
||||
}
|
||||
if(Tooltip.IsSet())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("tooltip = \"%s\""), *Tooltip.GetValue());
|
||||
}
|
||||
if(!StyleContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("style = %s"), *StyleContent);
|
||||
}
|
||||
if(!ShapeContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("shape = %s"), *ShapeContent);
|
||||
}
|
||||
if(!ColorContent.IsEmpty())
|
||||
{
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent += TEXT(", ");
|
||||
}
|
||||
AttributeContent += FString::Printf(TEXT("color = %s"), *ColorContent);
|
||||
|
||||
if(GetColor().IsSet())
|
||||
{
|
||||
if(!GetStyle().IsSet() || GetStyle().GetValue() == EVisualGraphStyle::Filled)
|
||||
{
|
||||
const FLinearColor CurrentColor = GetColor().GetValue();
|
||||
const float Brightness = (0.299f * CurrentColor.R + 0.587f * CurrentColor.G + 0.114f * CurrentColor.B);
|
||||
if(Brightness < 0.5f)
|
||||
{
|
||||
AttributeContent += TEXT(", fontcolor = white");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!AttributeContent.IsEmpty())
|
||||
{
|
||||
AttributeContent = FString::Printf(TEXT(" [ %s ]"), *AttributeContent);
|
||||
}
|
||||
|
||||
return FString::Printf(TEXT("%s%s%s;\n"), *Indentation, *GetName().ToString(), *AttributeContent);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#include "VisualGraphUtilsModule.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
IMPLEMENT_MODULE(FDefaultModuleImpl, VisualGraphUtils);
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogVisualGraphUtils);
|
||||
135
Engine/Source/Developer/VisualGraphUtils/Public/VisualGraph.h
Normal file
135
Engine/Source/Developer/VisualGraphUtils/Public/VisualGraph.h
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VisualGraphElement.h"
|
||||
#include "VisualGraphNode.h"
|
||||
#include "VisualGraphEdge.h"
|
||||
|
||||
class FVisualGraph;
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraphSubGraph : public FVisualGraphElement
|
||||
{
|
||||
public:
|
||||
|
||||
FVisualGraphSubGraph()
|
||||
: FVisualGraphElement()
|
||||
, ParentGraphIndex(INDEX_NONE)
|
||||
{}
|
||||
|
||||
virtual ~FVisualGraphSubGraph() override {}
|
||||
|
||||
int32 GetParentGraphIndex() const { return ParentGraphIndex; }
|
||||
const TArray<int32>& GetNodes() const { return Nodes; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual FString DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const override;
|
||||
|
||||
int32 ParentGraphIndex;
|
||||
TArray<int32> Nodes;
|
||||
|
||||
friend class FVisualGraph;
|
||||
};
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraph : public FVisualGraphElement
|
||||
{
|
||||
public:
|
||||
|
||||
FVisualGraph()
|
||||
: FVisualGraphElement()
|
||||
{}
|
||||
|
||||
virtual ~FVisualGraph() override {}
|
||||
|
||||
FVisualGraph(const FName& InName, const FName& InDisplayName = NAME_None);
|
||||
|
||||
const TArray<FVisualGraphNode>& GetNodes() const { return Nodes; }
|
||||
const TArray<FVisualGraphEdge>& GetEdges() const { return Edges; }
|
||||
const TArray<FVisualGraphSubGraph>& GetSubGraphs() const { return SubGraphs; }
|
||||
|
||||
int32 AddNode(
|
||||
const FName& InName,
|
||||
TOptional<FName> InDisplayName = TOptional<FName>(),
|
||||
TOptional<FLinearColor> InColor = TOptional<FLinearColor>(),
|
||||
TOptional<EVisualGraphShape> InShape = TOptional<EVisualGraphShape>(),
|
||||
TOptional<EVisualGraphStyle> InStyle = TOptional<EVisualGraphStyle>());
|
||||
|
||||
int32 AddEdge(
|
||||
int32 InSourceNode,
|
||||
int32 InTargetNode,
|
||||
EVisualGraphEdgeDirection InDirection,
|
||||
const FName& InName = NAME_None,
|
||||
TOptional<FName> InDisplayName = TOptional<FName>(),
|
||||
TOptional<FLinearColor> InColor = TOptional<FLinearColor>(),
|
||||
TOptional<EVisualGraphStyle> InStyle = TOptional<EVisualGraphStyle>());
|
||||
|
||||
int32 AddSubGraph(
|
||||
const FName& InName,
|
||||
TOptional<FName> InDisplayName = TOptional<FName>(),
|
||||
int32 InParentGraphIndex = INDEX_NONE,
|
||||
TOptional<FLinearColor> InColor = TOptional<FLinearColor>(),
|
||||
TOptional<EVisualGraphStyle> InStyle = TOptional<EVisualGraphStyle>(),
|
||||
const TArray<int32> InNodes = TArray<int32>());
|
||||
|
||||
int32 FindNode(const FName& InName) const;
|
||||
int32 FindEdge(const FName& InName) const;
|
||||
int32 FindSubGraph(const FName& InName) const;
|
||||
|
||||
bool AddNodeToSubGraph(int32 InNodeIndex, int32 InSubGraphIndex);
|
||||
bool RemoveNodeFromSubGraph(int32 InNodeIndex);
|
||||
|
||||
void TransitiveReduction(TFunction<bool(FVisualGraphEdge&)> KeepEdgeFunction);
|
||||
|
||||
FORCEINLINE FString DumpDot() const
|
||||
{
|
||||
return DumpDot(this, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual FString DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const override;
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE static void RefreshNameMap(const TArray<T>& InElements, TMap<FName, int32>& OutMap)
|
||||
{
|
||||
OutMap.Reset();
|
||||
for(const T& Element: InElements)
|
||||
{
|
||||
OutMap.Add(Element.Name, Element.Index);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE static void RefreshNameMapIfNeeded(const TArray<T>& InElements, TMap<FName, int32>& OutMap)
|
||||
{
|
||||
if(OutMap.Num() == InElements.Num())
|
||||
{
|
||||
return;
|
||||
}
|
||||
RefreshNameMap(InElements, OutMap);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
FORCEINLINE static int32 AddElement(const T& InElement, TArray<T>& OutElements, TMap<FName, int32>& OutMap)
|
||||
{
|
||||
const int32 AddedIndex = OutElements.Add(InElement);
|
||||
if(OutElements.IsValidIndex(AddedIndex))
|
||||
{
|
||||
OutElements[AddedIndex].Index = AddedIndex;
|
||||
OutMap.Add(InElement.Name, AddedIndex);
|
||||
}
|
||||
return AddedIndex;
|
||||
}
|
||||
|
||||
static bool IsNameAvailable(const FName& InName, const TMap<FName, int32>& InMap);
|
||||
static FName GetUniqueName(const FName& InName, const TMap<FName, int32>& InMap);
|
||||
|
||||
TArray<FVisualGraphNode> Nodes;
|
||||
TArray<FVisualGraphEdge> Edges;
|
||||
TArray<FVisualGraphSubGraph> SubGraphs;
|
||||
|
||||
TMap<FName,int32> NodeNameMap;
|
||||
TMap<FName,int32> EdgeNameMap;
|
||||
TMap<FName,int32> SubGraphNameMap;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VisualGraphElement.h"
|
||||
#include "VisualGraphEdge.generated.h"
|
||||
|
||||
UENUM()
|
||||
enum class EVisualGraphEdgeDirection : uint8
|
||||
{
|
||||
SourceToTarget,
|
||||
TargetToSource,
|
||||
BothWays
|
||||
};
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraphEdge : public FVisualGraphElement
|
||||
{
|
||||
public:
|
||||
|
||||
FVisualGraphEdge()
|
||||
: FVisualGraphElement()
|
||||
, Direction(EVisualGraphEdgeDirection::SourceToTarget)
|
||||
{}
|
||||
|
||||
virtual ~FVisualGraphEdge() override {}
|
||||
|
||||
int32 GetSourceNode() const { return SourceNode; }
|
||||
int32 GetTargetNode() const { return TargetNode; }
|
||||
EVisualGraphEdgeDirection GetDirection() const { return Direction; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual FString DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const override;
|
||||
|
||||
int32 SourceNode;
|
||||
int32 TargetNode;
|
||||
EVisualGraphEdgeDirection Direction;
|
||||
|
||||
friend class FVisualGraph;
|
||||
friend class FVisualGraphSubGraph;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "VisualGraphElement.generated.h"
|
||||
|
||||
class FVisualGraph;
|
||||
|
||||
UENUM()
|
||||
enum class EVisualGraphShape : uint8
|
||||
{
|
||||
Box,
|
||||
Polygon,
|
||||
Ellipse,
|
||||
Circle,
|
||||
Triangle,
|
||||
PlainText,
|
||||
Diamond,
|
||||
Parallelogram,
|
||||
House
|
||||
};
|
||||
|
||||
UENUM()
|
||||
enum class EVisualGraphStyle : uint8
|
||||
{
|
||||
Filled,
|
||||
Diagonals,
|
||||
Rounded,
|
||||
Dashed,
|
||||
Dotted,
|
||||
Solid,
|
||||
Bold
|
||||
};
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraphElement
|
||||
{
|
||||
public:
|
||||
|
||||
FVisualGraphElement()
|
||||
: Name(NAME_None)
|
||||
, DisplayName()
|
||||
, Index(INDEX_NONE)
|
||||
, Color()
|
||||
, Style()
|
||||
{}
|
||||
|
||||
virtual ~FVisualGraphElement() {}
|
||||
|
||||
FName GetName() const { return Name; }
|
||||
FName GetDisplayName() const { return DisplayName.IsSet() ? DisplayName.GetValue() : Name; }
|
||||
TOptional<FString> GetTooltip() const { return Tooltip; }
|
||||
void SetTooltip(const FString& InTooltip) const { Tooltip = InTooltip; }
|
||||
int32 GetIndex() const { return Index; }
|
||||
TOptional<FLinearColor> GetColor() const { return Color; }
|
||||
void SetColor(FLinearColor InValue) { Color = InValue; }
|
||||
TOptional<EVisualGraphStyle> GetStyle() const { return Style; }
|
||||
void SetStyle(EVisualGraphStyle InValue) { Style = InValue; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual FString DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const = 0;
|
||||
static FString DumpDotIndentation(int32 InIndentation);
|
||||
static FString DumpDotColor(const TOptional<FLinearColor>& InColor);
|
||||
static FString DumpDotShape(const TOptional<EVisualGraphShape>& InShape);
|
||||
static FString DumpDotStyle(const TOptional<EVisualGraphStyle>& InStyle);
|
||||
|
||||
FName Name;
|
||||
TOptional<FName> DisplayName;
|
||||
mutable TOptional<FString> Tooltip;
|
||||
int32 Index;
|
||||
TOptional<FLinearColor> Color;
|
||||
TOptional<EVisualGraphStyle> Style;
|
||||
|
||||
friend class FVisualGraph;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VisualGraphElement.h"
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraphNode : public FVisualGraphElement
|
||||
{
|
||||
public:
|
||||
|
||||
FVisualGraphNode()
|
||||
: FVisualGraphElement()
|
||||
, Shape()
|
||||
, SubGraphIndex(INDEX_NONE)
|
||||
{}
|
||||
|
||||
virtual ~FVisualGraphNode() override {}
|
||||
|
||||
TOptional<EVisualGraphShape> GetShape() const { return Shape; }
|
||||
void SetShape(EVisualGraphShape InValue) { Shape = InValue; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual FString DumpDot(const FVisualGraph* InGraph, int32 InIndendation) const override;
|
||||
|
||||
TOptional<EVisualGraphShape> Shape;
|
||||
int32 SubGraphIndex;
|
||||
|
||||
friend class FVisualGraph;
|
||||
friend class FVisualGraphSubGraph;
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VisualGraph.h"
|
||||
|
||||
class VISUALGRAPHUTILS_API FVisualGraphObjectUtils
|
||||
{
|
||||
public:
|
||||
|
||||
static FVisualGraph TraverseUObjectReferences(
|
||||
const TArray<UObject*>& InObjects,
|
||||
const TArray<UClass*>& InClassesToSkip = TArray<UClass*>(),
|
||||
const TArray<UObject*>& InOutersToSkip = TArray<UObject*>(),
|
||||
const TArray<UObject*>& InOutersToUse = TArray<UObject*>(),
|
||||
bool bTraverseObjectsInOuter = true,
|
||||
bool bCollectReferencesBySerialize = true,
|
||||
bool bRecursive = true
|
||||
);
|
||||
|
||||
static FVisualGraph TraverseTickOrder(
|
||||
const TArray<UObject*>& InObjects
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "VisualGraphNode.h"
|
||||
#include "VisualGraphEdge.h"
|
||||
#include "VisualGraph.h"
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogVisualGraphUtils, Log, All);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class VisualGraphUtils : ModuleRules
|
||||
{
|
||||
public VisualGraphUtils(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[] {
|
||||
"Core",
|
||||
"CoreUObject",
|
||||
"Engine",
|
||||
}
|
||||
);
|
||||
|
||||
if (Target.bBuildEditor == true)
|
||||
{
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"ApplicationCore",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user