├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── Resources
└── Icon128.png
├── Source
├── YetAnotherGraphEditor
│ ├── Private
│ │ ├── AssetTypeActions
│ │ │ ├── YetOtherAssetTypeActions.cpp
│ │ │ └── YetOtherAssetTypeActions.h
│ │ ├── EditorGraph
│ │ │ ├── EditorNodes
│ │ │ │ ├── FlowControlEdGraphNode.cpp
│ │ │ │ ├── FlowControlEdGraphNode.h
│ │ │ │ ├── YetAnotherEdGraphNode.cpp
│ │ │ │ └── YetAnotherEdGraphNode.h
│ │ │ ├── SchemaActions
│ │ │ │ ├── FlowControlSchemaAction_NewNode.cpp
│ │ │ │ ├── FlowControlSchemaAction_NewNode.h
│ │ │ │ ├── YAEdGraphSchemaAction_NewNode.cpp
│ │ │ │ └── YAEdGraphSchemaAction_NewNode.h
│ │ │ ├── SlateWidgets
│ │ │ │ ├── SYAGraphNode.cpp
│ │ │ │ ├── SYAGraphNode.h
│ │ │ │ ├── SYetAnotherGraphPin.cpp
│ │ │ │ └── SYetAnotherGraphPin.h
│ │ │ ├── YAConnectionDrawingPolicy.cpp
│ │ │ ├── YAConnectionDrawingPolicy.h
│ │ │ ├── YAEdGraph.cpp
│ │ │ ├── YAEdGraph.h
│ │ │ ├── YetAnotherEdGraphSchema.cpp
│ │ │ └── YetAnotherEdGraphSchema.h
│ │ ├── Factories
│ │ │ ├── YetAnotherAssetFactory.cpp
│ │ │ └── YetAnotherAssetFactory.h
│ │ ├── Toolkits
│ │ │ ├── YetAnotherGraphEditorToolkit.cpp
│ │ │ └── YetAnotherGraphEditorToolkit.h
│ │ ├── Utility
│ │ │ ├── EditorLogger.cpp
│ │ │ ├── EditorLogger.h
│ │ │ ├── YetAnotherNodeClassHelper.cpp
│ │ │ └── YetAnotherNodeClassHelper.h
│ │ └── YetAnotherGraphEditor.cpp
│ ├── Public
│ │ └── YetAnotherGraphEditor.h
│ └── YetAnotherGraphEditor.Build.cs
└── YetOtherGraphAssets
│ ├── Private
│ ├── Graphs
│ │ └── YAGraph.cpp
│ ├── Nodes
│ │ ├── ActionNodes
│ │ │ ├── ActionNode.cpp
│ │ │ └── Implementations
│ │ │ │ ├── StoreBoolean.cpp
│ │ │ │ └── StoreInteger.cpp
│ │ ├── EmptyNodes
│ │ │ ├── SimpleNode.cpp
│ │ │ └── StartNode.cpp
│ │ ├── FlowControlNodes
│ │ │ ├── BinarySelectNode.cpp
│ │ │ ├── FlowControlNode.cpp
│ │ │ ├── Implementations
│ │ │ │ ├── BooleanSelector.cpp
│ │ │ │ └── NthSelector.cpp
│ │ │ └── MultiNodeSelector.cpp
│ │ └── YANode.cpp
│ ├── Utility
│ │ ├── GraphSupportComponent.cpp
│ │ ├── GraphSupportComponentInterface.cpp
│ │ ├── Logger.cpp
│ │ └── YetAnotherGraphInterface.cpp
│ └── YetOtherGraphAssets.cpp
│ ├── Public
│ ├── Graphs
│ │ └── YAGraph.h
│ ├── Nodes
│ │ ├── ActionNodes
│ │ │ ├── ActionNode.h
│ │ │ └── Implementations
│ │ │ │ ├── StoreBoolean.h
│ │ │ │ └── StoreInteger.h
│ │ ├── EmptyNodes
│ │ │ ├── SimpleNode.h
│ │ │ └── StartNode.h
│ │ ├── FlowControlNodes
│ │ │ ├── BinarySelectNode.h
│ │ │ ├── FlowControlNode.h
│ │ │ ├── Implementations
│ │ │ │ ├── BooleanSelector.h
│ │ │ │ └── NthSelector.h
│ │ │ └── MultiNodeSelector.h
│ │ └── YANode.h
│ ├── Utility
│ │ ├── GraphSupportComponent.h
│ │ ├── GraphSupportComponentInterface.h
│ │ ├── Logger.h
│ │ └── YetAnotherGraphInterface.h
│ └── YetOtherGraphAssets.h
│ └── YetOtherGraphAssets.Build.cs
├── YetAnotherGraphPlugin.uplugin
└── docs
└── images
├── BooleanSelector.png
├── Categories.png
├── CreatingTheAssetGraph.png
├── CreatingTheNewAssetNode.png
├── CustomizingTheNewNode.png
├── EditingTheGraph.png
├── EmptyNodes.png
├── NamedNodes.png
├── NodeCategory.png
├── NthSelectorNode.png
├── RenamingNode.png
├── Screenshot1.png
├── Screenshot2.png
├── SelectingTheNode.png
├── StoreBooleanNode.png
└── StoreIntegerNode.png
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /Binaries
2 | /Intermediate
3 |
4 | # Prerequisites
5 | *.d
6 |
7 | # Compiled Object files
8 | *.slo
9 | *.lo
10 | *.o
11 | *.obj
12 |
13 | # Precompiled Headers
14 | *.gch
15 | *.pch
16 |
17 | # Compiled Dynamic libraries
18 | *.so
19 | *.dylib
20 | *.dll
21 |
22 | # Fortran module files
23 | *.mod
24 | *.smod
25 |
26 | # Compiled Static libraries
27 | *.lai
28 | *.la
29 | *.a
30 | *.lib
31 |
32 | # Executables
33 | *.exe
34 | *.out
35 | *.app
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Jhonny
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # YetAnotherGraphPlugin
2 | ### Making graphs effortless.
3 |
4 | A plugin for Unreal Engine 4 that allows to create graph-like assets.
5 |
6 |
7 |
8 |
9 |
10 |
11 | ## Getting started
12 |
13 | - Clone or copy the plugin into the "Plugins" folder of your project. Create one if there is none.
14 | - Generate Visual Studio project files.
15 |
16 | ## Native Features
17 |
18 | ### Naming Nodes
19 | Is now possible to name nodes. Named nodes can be accessed directly using the `NamedNodes` property of the graph asset
20 |
21 |
22 |
23 |
24 |
25 | ### Native Nodes
26 | The Plugin comes with 6 different nodes for basic graph creations. They are divided into 3 groups:
27 |
28 | * Empty Nodes: This nodes don't have any property and are to be used as parent class of the nodes that will store the informations.
29 |
30 |
31 |
32 |
33 | * Action Nodes: This are transparent nodes. In other words they aren't visible when navigating the graph using the function `GetChildren` of a node and at their place there will be their subnode. Before returning the subnode they perform a blueprintable function. With the plugin there are 2 implementation that store a named variable and its value on the external `UObject` owner of the graph that __must__ implement the `YetAnotherGraphInterface` interface (for exchanging informations between graphs and objects). If there isn't just a single subnode (there are 0 or more then 1 subnodes) the node will not perform the action and will not return its subnode. The two implementation are:
34 |
35 | * `Store Boolean`: stores a named boolean variable
36 | * `Store Integer`: stores a named integer.
37 |
38 |
39 |
40 |
41 |
42 |
43 | * Flow Control: The task of this nodes is to change dinamically the node they return when navigating the graph. Much like the action nodes they're completely transparent when using the graph. When using the function `GetChildren` on any node if among those subnodes there is a Flow Control node it will not be seen. Instead, in place of the flow control node, there will be one of its subnodes, depending on the specific result of the evaluation implemented. There are 2 flow control abstract classes you can inherit: `BinarySelector` and `MultiNodeSelector`. But there are 2 implementations that take advantage of the action nodes:
44 |
45 | * `Boolean Selector` will look up the boolean value associated with the variable name and that returns one of at most two nodes. On true it will return the node on the left. If there are 0 or more than 2 nodes or the evaluation turns out to be false on a single subnode, it will not return anything.
46 |
47 | * `Nth Selector` will look up the integer associated with the variable name and return the nth-subnode, counting them from left to right and starting from 0. If there are 0 nodes or the evaluation calculate an index outside the number of nodes, it will not return anything.
48 |
49 |
50 |
51 |
52 |
53 |
54 | If a flow control node doesn't return any node, it won't appear among the children of the node that called the function.
55 | If needed it's still possible to have a reference of this nodes. They are present in the 'Nodes' property of the graph asset, and they can be named and referenced directly using the `NamedNodes` map property.
56 |
57 | ### Creating new graphs and nodes
58 |
59 | - Create a new Blueprint Graph asset.
60 |
61 |
62 |
63 |
64 |
65 | - Create a new blueprint that inherits `SimpleNode` or `StartNode` blueprintable classes.
66 |
67 |
68 |
69 |
70 |
71 | - Customize the new blueprint node. overriding few functions.
72 | - `GetTitleNode` to change the name displayed int he graph editor.
73 | - `HasOutpitPins` to remove the bottom area of the node, usually dedicated to the output pins.
74 | - `HasInputPins` to remove the upper area of the node, usually dedicated to the input pins.
75 | - Add any kind of new variable that you wish.
76 |
77 |
78 |
79 |
80 |
81 | - Add your categories separated by a `|` for creating your own list on the graph
82 |
83 |
84 |
85 |
86 |
87 |
88 | - Spawn the node in the graph editor by dragging an arrow from its parent or by right clicking on the graph editor.
89 |
90 |
91 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
92 |
--------------------------------------------------------------------------------
/Resources/Icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/Resources/Icon128.png
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/AssetTypeActions/YetOtherAssetTypeActions.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetOtherAssetTypeActions.h"
3 | #include "YAGraph.h"
4 | #include "YetAnotherGraphEditorToolkit.h"
5 | #include "ModuleManager.h"
6 | #include "YetAnotherGraphEditor.h"
7 |
8 | #define LOCTEXT_NAMESPACE "YetOtherAssetTypeActions"
9 |
10 | FYetOtherAssetTypeActions::FYetOtherAssetTypeActions()
11 | {
12 | }
13 |
14 | FText FYetOtherAssetTypeActions::GetName() const
15 | {
16 | return NSLOCTEXT("AssetTypeActions", "GraphTypeActions", "Graph");
17 | }
18 |
19 | UClass * FYetOtherAssetTypeActions::GetSupportedClass() const
20 | {
21 | return UYAGraph::StaticClass();
22 | }
23 |
24 | FColor FYetOtherAssetTypeActions::GetTypeColor() const
25 | {
26 | return FColor::Red;
27 | }
28 |
29 | uint32 FYetOtherAssetTypeActions::GetCategories()
30 | {
31 | return EAssetTypeCategories::Blueprint;
32 | }
33 |
34 | bool FYetOtherAssetTypeActions::HasActions(const TArray& InObjects) const
35 | {
36 | return false;
37 | }
38 |
39 | void FYetOtherAssetTypeActions::OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor)
40 | {
41 | FYetAnotherGraphEditorModule& Helper= FModuleManager::LoadModuleChecked("YetAnotherGraphEditor");
42 | Helper.StartNodeHelper();
43 |
44 | EToolkitMode::Type Mode = EditWithinLevelEditor.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;
45 | for (auto Object = InObjects.CreateConstIterator(); Object; Object++)
46 | {
47 | auto Graph = Cast(*Object);
48 | if (Graph != nullptr)
49 | {
50 | TSharedRefEditorToolkit = MakeShareable(new FYetAnotherGraphEditorToolkit());
51 | EditorToolkit->InitGraphAssetEditor(Mode, EditWithinLevelEditor, Graph);
52 | }
53 | }
54 | }
55 |
56 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/AssetTypeActions/YetOtherAssetTypeActions.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "AssetTypeActions_Base.h"
8 |
9 | /**
10 | *
11 | */
12 | class FYetOtherAssetTypeActions : public FAssetTypeActions_Base
13 | {
14 | public:
15 | FYetOtherAssetTypeActions();
16 |
17 | // Inherited via FAssetTypeActions_Base
18 | virtual FText GetName() const override;
19 | virtual UClass * GetSupportedClass() const override;
20 | virtual FColor GetTypeColor() const override;
21 | virtual uint32 GetCategories() override;
22 | virtual bool HasActions(const TArray& InObjects) const override;
23 | virtual void OpenAssetEditor(const TArray& InObjects, TSharedPtr EditWithinLevelEditor = TSharedPtr()) override;
24 |
25 | };
26 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/EditorNodes/FlowControlEdGraphNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #include "FlowControlEdGraphNode.h"
5 |
6 | void UFlowControlEdGraphNode::SaveNodesAsChildren(TArray& Children)
7 | {
8 | while (Children.Num()>0)
9 | {
10 | UEdGraphNode* Node = GetMostLeftNode(Children);
11 | if(UYetAnotherEdGraphNode* YaNode = Cast(Node))
12 | AssetNode->LinkArgumentNodeAsChild(YaNode->AssetNode);
13 | Children.Remove(Node);
14 | }
15 | }
16 |
17 | UEdGraphNode * UFlowControlEdGraphNode::GetMostLeftNode(TArray& Nodes)
18 | {
19 | auto* Node = Nodes[0] ? Nodes[0] : nullptr;
20 | for (auto* N : Nodes)
21 | {
22 | if (N->NodePosX < Node->NodePosX)
23 | Node = N;
24 | }
25 | return Node;
26 | }
27 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/EditorNodes/FlowControlEdGraphNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "YetAnotherEdGraphNode.h"
6 | #include "FlowControlEdGraphNode.generated.h"
7 |
8 | /**
9 | *
10 | */
11 | UCLASS()
12 | class UFlowControlEdGraphNode : public UYetAnotherEdGraphNode
13 | {
14 | GENERATED_BODY()
15 |
16 | //Inherited from UYetAnotherEdGraphNode
17 | void SaveNodesAsChildren(TArray& Children) override; //we are going to save the nodes in order from left to right
18 |
19 | virtual UEdGraphNode* GetMostLeftNode(TArray& Nodes);
20 | };
21 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/EditorNodes/YetAnotherEdGraphNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherEdGraphNode.h"
3 | #include "YANode.h"
4 | #include "YAGraph.h"
5 | #include "YAEdGraph.h"
6 | #include "SYAGraphNode.h"
7 | #include "IDetailsView.h"
8 | #include "PropertyEditorModule.h"
9 | #include "ModuleManager.h"
10 | #include "EditorLogger.h"
11 |
12 | #define LOCTEXT_NAMESPACE "YetAnotherEdGraphNode"
13 |
14 | UYetAnotherEdGraphNode::UYetAnotherEdGraphNode(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer){}
15 |
16 |
17 | TSharedPtr UYetAnotherEdGraphNode::CreateVisualWidget()
18 | {
19 | SlateNode= SNew(SYAGraphNode, this);
20 | return SlateNode;
21 | }
22 |
23 | TSharedPtr UYetAnotherEdGraphNode::GetContentWidget()
24 | {
25 | FDetailsViewArgs DetailsViewArgs;
26 | DetailsViewArgs.bAllowSearch = false;
27 | DetailsViewArgs.bLockable = false;
28 | DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
29 |
30 | FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked("PropertyEditor");
31 | TSharedPtr View = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
32 | View->SetObject(AssetNode);
33 | return View;
34 | }
35 |
36 | void UYetAnotherEdGraphNode::UpdateVisualNode()
37 | {
38 | SlateNode->UpdateGraphNode();
39 | }
40 |
41 | void UYetAnotherEdGraphNode::SaveNodesAsChildren(TArray& Children)
42 | {
43 | for (UEdGraphNode* Child : Children)
44 | {
45 | UYetAnotherEdGraphNode* Node = Cast(Child);
46 | if (Node)
47 | AssetNode->LinkArgumentNodeAsChild(Node->AssetNode);
48 | }
49 | }
50 |
51 | bool UYetAnotherEdGraphNode::HasOutputPins()
52 | {
53 | return AssetNode ? AssetNode->HasOutputPins() : true;
54 | }
55 |
56 | bool UYetAnotherEdGraphNode::HasInputPins()
57 | {
58 | return AssetNode ? AssetNode->HasInputPins() : true;
59 | }
60 |
61 | void UYetAnotherEdGraphNode::AllocateDefaultPins()
62 | {
63 | UEdGraphNode::AllocateDefaultPins();
64 | if (HasInputPins())
65 | CreatePin(EGPD_Input, FName("InCategory"), FName("InPinName"));
66 | if (HasOutputPins())
67 | CreatePin(EGPD_Output, FName("OutCategory"), FName("OutPinName"));
68 | }
69 |
70 | FText UYetAnotherEdGraphNode::GetNodeTitle(ENodeTitleType::Type TitleType) const
71 | {
72 | switch (TitleType)
73 | {
74 | case ENodeTitleType::Type::MenuTitle:
75 | return AssetNode->GetNodeTitle();
76 | default:
77 | FText Title = GetEdNodeName();
78 | return Title.IsEmpty() ? AssetNode->GetNodeTitle() : Title;
79 | }
80 | }
81 |
82 | void UYetAnotherEdGraphNode::PrepareForCopying()
83 | {
84 | if (AssetNode)
85 | AssetNode->Rename(nullptr, this, REN_DontCreateRedirectors | REN_DoNotDirty);
86 | UEdGraphNode::PrepareForCopying();
87 | }
88 |
89 | void UYetAnotherEdGraphNode::DestroyNode()
90 | {
91 | if (AssetNode)
92 | {
93 | AssetNode->GetGraph()->RemoveNode(AssetNode);
94 | AssetNode->ConditionalBeginDestroy();
95 | AssetNode = nullptr;
96 | }
97 | UEdGraphNode::DestroyNode();
98 | }
99 |
100 | void UYetAnotherEdGraphNode::AutowireNewNode(UEdGraphPin * FromPin)
101 | {
102 | if (FromPin)
103 | {
104 | UEdGraphNode::AutowireNewNode(FromPin);
105 | if (FromPin->Direction == EEdGraphPinDirection::EGPD_Input)
106 | {
107 | if (GetSchema()->TryCreateConnection(FromPin, FindPin(FName("OutPinName"))))
108 | {
109 | FromPin->GetOwningNode()->NodeConnectionListChanged();
110 | }
111 | }
112 | if (FromPin->Direction == EEdGraphPinDirection::EGPD_Output)
113 | {
114 | if (GetSchema()->TryCreateConnection(FromPin, FindPin(FName("InPinName"))))
115 | {
116 | FromPin->GetOwningNode()->NodeConnectionListChanged();
117 | }
118 | }
119 | }
120 | }
121 |
122 | void UYetAnotherEdGraphNode::SetAssetNode(UYANode * InNode)
123 | {
124 | AssetNode = InNode;
125 | }
126 |
127 | UYANode * UYetAnotherEdGraphNode::GetAssetNode()
128 | {
129 | return AssetNode;
130 | }
131 |
132 | void UYetAnotherEdGraphNode::PostCopyNode()
133 | {
134 | if (AssetNode)
135 | {
136 | UEdGraph* EdGraph = GetGraph();
137 | UObject* ParentAsset = EdGraph ? EdGraph->GetOuter() : nullptr;
138 | AssetNode->Rename(nullptr, ParentAsset, REN_DontCreateRedirectors | REN_DoNotDirty);
139 | AssetNode->ClearFlags(RF_Transient);
140 | }
141 | }
142 |
143 | bool UYetAnotherEdGraphNode::RenameUniqueNode(const FText & NewName)
144 | {
145 | bool bRenamedNode = false;
146 |
147 | UYAEdGraph* EdGraph = Cast(GetGraph());
148 |
149 | if (EdGraph->IsNameUnique(NewName))
150 | {
151 | Modify();
152 | SetEdNodeName(NewName);
153 | bRenamedNode = true;
154 | }
155 | return bRenamedNode;
156 | }
157 | FText UYetAnotherEdGraphNode::GetEdNodeName() const
158 | {
159 | return EdNodeName;
160 | }
161 | void UYetAnotherEdGraphNode::SetEdNodeName(const FText & Name)
162 | {
163 | EdNodeName = Name;
164 | }
165 |
166 | void UYetAnotherEdGraphNode::SetEdNodeName(const FName & Name)
167 | {
168 | SetEdNodeName(FText::FromName(Name));
169 | }
170 |
171 |
172 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/EditorNodes/YetAnotherEdGraphNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "EdGraph/EdGraphNode.h"
8 | #include "YANode.h"
9 | #include "SubclassOf.h"
10 | #include "YetAnotherEdGraphNode.generated.h"
11 |
12 | /**
13 | *
14 | */
15 | UCLASS()
16 | class UYetAnotherEdGraphNode : public UEdGraphNode
17 | {
18 | GENERATED_UCLASS_BODY()
19 |
20 | public:
21 |
22 | // Inherited via EdGraphNode.h
23 | TSharedPtr CreateVisualWidget() override; /** Create a visual widget to represent this node in a graph editor or graph panel. If not implemented, the default node factory will be used. */
24 | void AllocateDefaultPins() override;
25 | FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;
26 | void PrepareForCopying() override;
27 | void DestroyNode() override;
28 | void AutowireNewNode(UEdGraphPin* FromPin) override;
29 |
30 |
31 | virtual void SetAssetNode(UYANode* InNode);
32 | virtual UYANode* GetAssetNode();
33 |
34 | virtual void PostCopyNode();
35 |
36 | virtual bool RenameUniqueNode(const FText& NewName);
37 |
38 | virtual FText GetEdNodeName() const;
39 | virtual void SetEdNodeName(const FText& Name);
40 | virtual void SetEdNodeName(const FName& Name);
41 |
42 | virtual TSharedPtr GetContentWidget();
43 |
44 | virtual void UpdateVisualNode();
45 |
46 | virtual void SaveNodesAsChildren(TArray& Children);
47 |
48 | protected:
49 |
50 | virtual bool HasOutputPins();
51 | virtual bool HasInputPins();
52 | TSharedPtrSlateNode;
53 |
54 | public:
55 |
56 | UPROPERTY(Instanced)
57 | UYANode* AssetNode = nullptr;
58 |
59 | protected:
60 | UPROPERTY()
61 | FText EdNodeName;
62 |
63 | };
64 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SchemaActions/FlowControlSchemaAction_NewNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "FlowControlSchemaAction_NewNode.h"
3 | #include "EdGraph/EdGraph.h"
4 |
5 | UEdGraphNode * FFlowControlSchemaAction_NewNode::CreateEditorNode(UEdGraph * ParentGraph, bool bSelectNewNode, UYANode * AssetNode)
6 | {
7 | FGraphNodeCreatorCreator(*ParentGraph);
8 | UFlowControlEdGraphNode* EdNode = Creator.CreateNode(bSelectNewNode);
9 | EdNode->SetAssetNode(AssetNode);
10 | Creator.Finalize();
11 | return EdNode;
12 | }
13 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SchemaActions/FlowControlSchemaAction_NewNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "YAEdGraphSchemaAction_NewNode.h"
6 | #include "FlowControlEdGraphNode.h"
7 | #include "FlowControlSchemaAction_NewNode.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | USTRUCT()
13 | struct FFlowControlSchemaAction_NewNode : public FYAEdGraphSchemaAction_NewNode
14 | {
15 | public:
16 |
17 | GENERATED_USTRUCT_BODY()
18 |
19 | FFlowControlSchemaAction_NewNode() :FYAEdGraphSchemaAction_NewNode() {}
20 | FFlowControlSchemaAction_NewNode(FText InNodeCategory, FText InMenuDesc, FText InToolTip, const int32 InGrouping, TSubclassOf InNodeClass) :FYAEdGraphSchemaAction_NewNode(InNodeCategory, InMenuDesc, InToolTip, InGrouping, InNodeClass) {}
21 |
22 |
23 | //Inherited from FYAEdGraphSchemaAction_NewNode
24 | UEdGraphNode* CreateEditorNode(UEdGraph * ParentGraph, bool bSelectNewNode, UYANode* AssetNode) override;
25 | };
26 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SchemaActions/YAEdGraphSchemaAction_NewNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YAEdGraphSchemaAction_NewNode.h"
3 | #include "YAGraph.h"
4 | #include "YetAnotherEdGraphNode.h"
5 | #include "EdGraph/EdGraph.h"
6 |
7 | #define LOCTEXT_NAMESPACE "YAEdGraphSchemaAction_NewNode"
8 |
9 | UEdGraphNode * FYAEdGraphSchemaAction_NewNode::PerformAction(UEdGraph * ParentGraph, UEdGraphPin * FromPin, const FVector2D Location, bool bSelectNewNode)
10 | {
11 | check(ParentGraph);
12 |
13 | ParentGraph->Modify();
14 |
15 |
16 | UYAGraph* GraphAsset = CastChecked(ParentGraph->GetOuter());
17 | GraphAsset->Modify();
18 |
19 | UYANode* AssetNode = GraphAsset->SpawnNodeInsideGraph(NewNodeClass);
20 |
21 | UEdGraphNode* EditorNode=CreateEditorNode(ParentGraph,bSelectNewNode,AssetNode);
22 |
23 | //EditorNode->AllocateDefaultPins(); for some reason it was called 2 times even if I only call it here
24 | EditorNode->AutowireNewNode(FromPin);
25 | EditorNode->NodePosX = Location.X;
26 | EditorNode->NodePosY = Location.Y;
27 |
28 | return EditorNode;
29 | }
30 | UEdGraphNode * FYAEdGraphSchemaAction_NewNode::CreateEditorNode(UEdGraph * ParentGraph, bool bSelectNewNode, UYANode* AssetNode)
31 | {
32 | FGraphNodeCreatorCreator(*ParentGraph);
33 | UYetAnotherEdGraphNode* EdNode = Creator.CreateNode(bSelectNewNode);
34 | EdNode->SetAssetNode(AssetNode);
35 | Creator.Finalize();
36 | return EdNode;
37 | }
38 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SchemaActions/YAEdGraphSchemaAction_NewNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "EdGraph/EdGraphSchema.h"
6 | #include "SubclassOf.h"
7 | #include "YANode.h"
8 | #include "YAEdGraphSchemaAction_NewNode.generated.h"
9 |
10 | /**
11 | *
12 | */
13 | USTRUCT()
14 | struct FYAEdGraphSchemaAction_NewNode : public FEdGraphSchemaAction
15 | {
16 | public:
17 | GENERATED_USTRUCT_BODY()
18 |
19 | FYAEdGraphSchemaAction_NewNode() :FEdGraphSchemaAction(), NewNodeClass(nullptr) {}
20 | FYAEdGraphSchemaAction_NewNode(FText InNodeCategory, FText InMenuDesc, FText InToolTip, const int32 InGrouping, TSubclassOf InNodeClass) :FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping), NewNodeClass(InNodeClass) {}
21 |
22 | /** Execute this action, given the graph and schema, and possibly a pin that we were dragged from. Returns a node that was created by this action (if any). */
23 | UEdGraphNode* PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
24 |
25 | virtual UEdGraphNode* CreateEditorNode(UEdGraph * ParentGraph, bool bSelectNewNode, UYANode* AssetNode);
26 | TSubclassOfNewNodeClass;
27 |
28 |
29 | };
30 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SlateWidgets/SYAGraphNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "SYAGraphNode.h"
3 | #include "Slate.h"
4 | #include "YetAnotherEdGraphNode.h"
5 | #include "SGraphPin.h"
6 | #include "SYetAnotherGraphPin.h"
7 | #include "EditorLogger.h"
8 |
9 | #define LOCTEXT_NAMESPACE "SYAGraphNode"
10 |
11 | void SYAGraphNode::Construct(const FArguments & InArgs, UEdGraphNode * InNode)
12 | {
13 | GraphNode = InNode;
14 | UpdateGraphNode();
15 | }
16 |
17 | BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
18 |
19 | void SYAGraphNode::UpdateGraphNode()
20 | {
21 |
22 | const FMargin NodePadding = FMargin(2.0f);
23 |
24 | InputPins.Empty();
25 | OutputPins.Empty();
26 |
27 | RightNodeBox.Reset();
28 | LeftNodeBox.Reset();
29 |
30 | TSharedPtr NodeTitle = SNew(SNodeTitle, GraphNode);
31 |
32 | this->ContentScale.Bind(this, &SGraphNode::GetContentScale);
33 |
34 | this->GetOrAddSlot(ENodeZone::Center)
35 | .HAlign(HAlign_Fill)
36 | .VAlign(VAlign_Center)
37 | [
38 | SNew(SBorder)
39 | .BorderImage(FEditorStyle::GetBrush("Graph.StateNode.Body"))
40 | .Padding(FMargin(10.0f))
41 | .BorderBackgroundColor(FLinearColor(0.1f, 0.1f, 0.1f))
42 | [
43 | SAssignNew(ErrorBorder,SBorder)
44 | .BorderImage(FEditorStyle::GetBrush("Graph.StateNode.Body"))
45 | .BorderBackgroundColor(FLinearColor(0.1f, 0.1f, 0.1f))
46 | [
47 | SNew(SBorder)
48 | .BorderImage(FEditorStyle::GetBrush("Graph.StateNode.Body"))
49 | .Padding(FMargin(10.0f))
50 | .BorderBackgroundColor(FLinearColor(0.1f, 0.1f, 0.1f))
51 | [
52 | SNew(SVerticalBox)
53 | + SVerticalBox::Slot()
54 | .AutoHeight()
55 | [
56 | SAssignNew(LeftNodeBox, SVerticalBox)
57 | ]
58 | + SVerticalBox::Slot()
59 | .HAlign(HAlign_Center)
60 | .AutoHeight()
61 | [
62 | SAssignNew(NodeHeader, STextBlock)
63 | ]
64 | + SVerticalBox::Slot()
65 | .HAlign(HAlign_Center)
66 | .AutoHeight()
67 | [
68 | SAssignNew(InlineEditableText, SInlineEditableTextBlock)
69 | .Style(FEditorStyle::Get(), "Graph.StateNode.NodeTitleInlineEditableText")
70 | .Text(NodeTitle.Get(), &SNodeTitle::GetHeadTitle)
71 | .IsReadOnly(this, &SYAGraphNode::IsNameReadOnly)
72 | .OnTextCommitted(this, &SYAGraphNode::OnNameTextCommited)
73 | .OnVerifyTextChanged(this, &SYAGraphNode::OnVerifyNameTextChanged)
74 | ]
75 | + SVerticalBox::Slot()
76 | .AutoHeight()
77 | [
78 | NodeTitle.ToSharedRef()
79 | ]
80 | + SVerticalBox::Slot()
81 | .AutoHeight()
82 | [
83 | SAssignNew(ContentWidget, SVerticalBox)
84 | ]
85 | + SVerticalBox::Slot()
86 | .AutoHeight()
87 | [
88 | SAssignNew(RightNodeBox, SVerticalBox)
89 | ]
90 | ]
91 | ]
92 | ]
93 | ];
94 |
95 | CreatePinWidgets();
96 | CreateContent();
97 | CreateHeader();
98 | }
99 |
100 | void SYAGraphNode::CreatePinWidgets()
101 | {
102 | UYetAnotherEdGraphNode* EdNode = CastChecked(GraphNode);
103 | for (int32 i = 0; i < EdNode->Pins.Num(); ++i)
104 | {
105 | UEdGraphPin* Pin = EdNode->Pins[i];
106 | if (!Pin->bHidden)
107 | {
108 | TSharedPtrNewPin = SNew(SYetAnotherGraphPin, Pin);
109 | AddPin(NewPin.ToSharedRef());
110 | }
111 | }
112 | }
113 |
114 | void SYAGraphNode::AddPin(const TSharedRef& PinToAdd)
115 | {
116 | PinToAdd->SetOwner(SharedThis(this));
117 | if (PinToAdd->GetDirection() == EEdGraphPinDirection::EGPD_Input)
118 | {
119 | LeftNodeBox->AddSlot()
120 | .HAlign(HAlign_Fill)
121 | .VAlign(VAlign_Fill)
122 | .FillHeight(1.0f)
123 | .Padding(20.0f, 0.0f)
124 | [
125 | PinToAdd
126 | ];
127 | InputPins.Add(PinToAdd);
128 | }
129 | else if (PinToAdd->GetDirection() == EEdGraphPinDirection::EGPD_Output)
130 | {
131 | RightNodeBox->AddSlot()
132 | .HAlign(HAlign_Fill)
133 | .VAlign(VAlign_Fill)
134 | .FillHeight(1.0f)
135 | .Padding(20.0f, 0.0f)
136 | [
137 | PinToAdd
138 | ];
139 | OutputPins.Add(PinToAdd);
140 | }
141 | else
142 | {
143 | UE_LOG(LogTemp, Error, TEXT("No direction found"));
144 | }
145 | }
146 |
147 | bool SYAGraphNode::IsNameReadOnly() const
148 | {
149 | return false;
150 | }
151 |
152 | void SYAGraphNode::OnNameTextCommited(const FText & InText, ETextCommit::Type CommitInfo)
153 | {
154 | UYetAnotherEdGraphNode* UEdNode = CastChecked(GraphNode);
155 |
156 | if (UEdNode)
157 | if (UEdNode->RenameUniqueNode(InText))
158 | {
159 | UpdateGraphNode();
160 | NodeHeader.Get()->SetVisibility(EVisibility::Visible);
161 | SGraphNode::OnNameTextCommited(InText, CommitInfo);
162 | }
163 |
164 | }
165 | void SYAGraphNode::CreateContent()
166 | {
167 | UYetAnotherEdGraphNode* Node = Cast(GraphNode);
168 |
169 | ContentWidget->AddSlot()
170 | [
171 | Node->GetContentWidget().ToSharedRef()
172 | ];
173 | }
174 | void SYAGraphNode::CreateHeader()
175 | {
176 | NodeHeader.Get()->SetText(GraphNode->GetNodeTitle(ENodeTitleType::MenuTitle));
177 |
178 | UYetAnotherEdGraphNode* UEdNode = CastChecked(GraphNode);
179 |
180 | if (UEdNode)
181 | NodeHeader.Get()->SetVisibility((UEdNode->GetEdNodeName().IsEmpty()) ? EVisibility::Collapsed : EVisibility::Visible);
182 | else
183 | EDELog("An error occurred when creating the slate node headers");
184 | }
185 |
186 | END_SLATE_FUNCTION_BUILD_OPTIMIZATION
187 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SlateWidgets/SYAGraphNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "SGraphNode.h"
6 | #include "NotifyHook.h"
7 | #include "IDetailsView.h"
8 |
9 | /**
10 | *
11 | */
12 | class SYAGraphNode : public SGraphNode, public FNotifyHook
13 | {
14 | public:
15 | SLATE_BEGIN_ARGS(SYAGraphNode) {}
16 | SLATE_END_ARGS()
17 |
18 | // Inherited via SGraphNode
19 | void Construct(const FArguments& InArgs, UEdGraphNode* InNode);
20 | void UpdateGraphNode() override;
21 | void CreatePinWidgets() override;
22 | void AddPin(const TSharedRef& PinToAdd) override;
23 | bool IsNameReadOnly() const override;
24 | void OnNameTextCommited(const FText& InText, ETextCommit::Type CommitInfo);
25 |
26 | protected:
27 |
28 | TSharedPtr ContentWidget;
29 | TSharedPtr ErrorBorder;
30 | TSharedPtr NodeHeader;
31 |
32 | virtual void CreateContent();
33 | virtual void CreateHeader();
34 | };
35 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SlateWidgets/SYetAnotherGraphPin.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "SYetAnotherGraphPin.h"
3 |
4 | void SYetAnotherGraphPin::Construct(const FArguments & InArgs, UEdGraphPin * InPin)
5 | {
6 | this->SetCursor(EMouseCursor::Default);
7 |
8 | bShowLabel = true;
9 |
10 | GraphPinObj = InPin;
11 |
12 | SBorder::FArguments Arguments;
13 | Arguments.OnMouseButtonDown(this, &SYetAnotherGraphPin::OnPinMouseDown);
14 | Arguments.Cursor(this, &SYetAnotherGraphPin::GetPinCursor);
15 | Arguments.Padding(FMargin(10.0f));
16 |
17 | SBorder::Construct(Arguments);
18 | }
19 |
20 | TSharedRef SYetAnotherGraphPin::GetDefaultValueWidget()
21 | {
22 | return SNew(STextBlock);
23 | }
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/SlateWidgets/SYetAnotherGraphPin.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "SGraphPin.h"
6 |
7 | #define LOCTEXT_NAMESPACE "SYetAnotherGraphPin"
8 |
9 | /**
10 | *
11 | */
12 | class SYetAnotherGraphPin : public SGraphPin
13 | {
14 | public:
15 | void Construct(const FArguments& InArgs, UEdGraphPin* InPin);
16 | virtual TSharedRef GetDefaultValueWidget() override;
17 | };
18 |
19 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YAConnectionDrawingPolicy.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YAConnectionDrawingPolicy.h"
3 | #include "DrawElements.h"
4 |
5 | FYAConnectionDrawingPolicy::FYAConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj)
6 | : FConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, ZoomFactor, InClippingRect, InDrawElements)
7 | , GraphObj(InGraphObj)
8 | {
9 | }
10 |
11 | void FYAConnectionDrawingPolicy::DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params)
12 | {
13 | Params.AssociatedPin1 = OutputPin;
14 | Params.AssociatedPin2 = InputPin;
15 | Params.WireThickness = 1.5f;
16 |
17 | const bool bDeemphasizeUnhoveredPins = HoveredPins.Num() > 0;
18 | if (bDeemphasizeUnhoveredPins)
19 | {
20 | ApplyHoverDeemphasis(OutputPin, InputPin, /*inout*/ Params.WireThickness, /*inout*/ Params.WireColor);
21 | }
22 | }
23 |
24 | void FYAConnectionDrawingPolicy::Draw(TMap, FArrangedWidget>& InPinGeometries, FArrangedChildren& ArrangedNodes)
25 | {
26 | // Build an acceleration structure to quickly find geometry for the nodes
27 | NodeWidgetMap.Empty();
28 | for (int32 NodeIndex = 0; NodeIndex < ArrangedNodes.Num(); ++NodeIndex)
29 | {
30 | FArrangedWidget& CurWidget = ArrangedNodes[NodeIndex];
31 | TSharedRef ChildNode = StaticCastSharedRef(CurWidget.Widget);
32 | NodeWidgetMap.Add(ChildNode->GetNodeObj(), NodeIndex);
33 | }
34 |
35 | // Now draw
36 | FConnectionDrawingPolicy::Draw(InPinGeometries, ArrangedNodes);
37 | }
38 |
39 | void FYAConnectionDrawingPolicy::DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin)
40 | {
41 | FConnectionParams Params;
42 | DetermineWiringStyle(Pin, nullptr, /*inout*/ Params);
43 |
44 | if (Pin->Direction == EEdGraphPinDirection::EGPD_Output)
45 | {
46 | DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, EndPoint), EndPoint, Params);
47 | }
48 | else
49 | {
50 | DrawSplineWithArrow(FGeometryHelper::FindClosestPointOnGeom(PinGeometry, StartPoint), StartPoint, Params);
51 | }
52 | }
53 |
54 | void FYAConnectionDrawingPolicy::DrawSplineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
55 | {
56 | // bUserFlag1 indicates that we need to reverse the direction of connection (used by debugger)
57 | const FVector2D& P0 = Params.bUserFlag1 ? EndAnchorPoint : StartAnchorPoint;
58 | const FVector2D& P1 = Params.bUserFlag1 ? StartAnchorPoint : EndAnchorPoint;
59 |
60 | Internal_DrawLineWithArrow(P0, P1, Params);
61 | }
62 |
63 | void FYAConnectionDrawingPolicy::Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params)
64 | {
65 | //@TODO: Should this be scaled by zoom factor?
66 | const float LineSeparationAmount = 4.5f;
67 |
68 | const FVector2D DeltaPos = EndAnchorPoint - StartAnchorPoint;
69 | const FVector2D UnitDelta = DeltaPos.GetSafeNormal();
70 | const FVector2D Normal = FVector2D(DeltaPos.Y, -DeltaPos.X).GetSafeNormal();
71 |
72 | // Come up with the final start/end points
73 | const FVector2D DirectionBias = Normal * LineSeparationAmount;
74 | const FVector2D LengthBias = ArrowRadius.X * UnitDelta;
75 | const FVector2D StartPoint = StartAnchorPoint + DirectionBias + LengthBias;
76 | const FVector2D EndPoint = EndAnchorPoint + DirectionBias - LengthBias;
77 |
78 | // Draw a line/spline
79 | DrawConnection(WireLayerID, StartPoint, EndPoint, Params);
80 |
81 | // Draw the arrow
82 | const FVector2D ArrowDrawPos = EndPoint - ArrowRadius;
83 | const float AngleInRadians = FMath::Atan2(DeltaPos.Y, DeltaPos.X);
84 |
85 | FSlateDrawElement::MakeRotatedBox(
86 | DrawElementsList,
87 | ArrowLayerID,
88 | FPaintGeometry(ArrowDrawPos, ArrowImage->ImageSize * ZoomFactor, ZoomFactor),
89 | ArrowImage,
90 | ESlateDrawEffect::None,
91 | AngleInRadians,
92 | TOptional(),
93 | FSlateDrawElement::RelativeToElement,
94 | Params.WireColor
95 | );
96 | }
97 |
98 | void FYAConnectionDrawingPolicy::DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params)
99 | {
100 | // Get a reasonable seed point (halfway between the boxes)
101 | const FVector2D StartCenter = FGeometryHelper::CenterOf(StartGeom);
102 | const FVector2D EndCenter = FGeometryHelper::CenterOf(EndGeom);
103 | const FVector2D SeedPoint = (StartCenter + EndCenter) * 0.5f;
104 |
105 | // Find the (approximate) closest points between the two boxes
106 | const FVector2D StartAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(StartGeom, SeedPoint);
107 | const FVector2D EndAnchorPoint = FGeometryHelper::FindClosestPointOnGeom(EndGeom, SeedPoint);
108 |
109 | DrawSplineWithArrow(StartAnchorPoint, EndAnchorPoint, Params);
110 | }
111 |
112 | FVector2D FYAConnectionDrawingPolicy::ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const
113 | {
114 | const FVector2D Delta = End - Start;
115 | const FVector2D NormDelta = Delta.GetSafeNormal();
116 |
117 | return NormDelta;
118 | }
119 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YAConnectionDrawingPolicy.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "ConnectionDrawingPolicy.h"
8 |
9 | /**
10 | *
11 | */
12 | class FYAConnectionDrawingPolicy : public FConnectionDrawingPolicy
13 | {
14 |
15 | protected:
16 | UEdGraph * GraphObj;
17 | TMap NodeWidgetMap;
18 |
19 | public:
20 | FYAConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float ZoomFactor, const FSlateRect& InClippingRect, FSlateWindowElementList& InDrawElements, UEdGraph* InGraphObj);
21 |
22 | // FConnectionDrawingPolicy interface
23 | virtual void DetermineWiringStyle(UEdGraphPin* OutputPin, UEdGraphPin* InputPin, /*inout*/ FConnectionParams& Params) override;
24 | virtual void Draw(TMap, FArrangedWidget>& PinGeometries, FArrangedChildren& ArrangedNodes) override;
25 | virtual void DrawSplineWithArrow(const FGeometry& StartGeom, const FGeometry& EndGeom, const FConnectionParams& Params) override;
26 | virtual void DrawSplineWithArrow(const FVector2D& StartPoint, const FVector2D& EndPoint, const FConnectionParams& Params) override;
27 | virtual void DrawPreviewConnector(const FGeometry& PinGeometry, const FVector2D& StartPoint, const FVector2D& EndPoint, UEdGraphPin* Pin) override;
28 | virtual FVector2D ComputeSplineTangent(const FVector2D& Start, const FVector2D& End) const override;
29 | // End of FConnectionDrawingPolicy interface
30 |
31 | protected:
32 | void Internal_DrawLineWithArrow(const FVector2D& StartAnchorPoint, const FVector2D& EndAnchorPoint, const FConnectionParams& Params);
33 | };
34 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YAEdGraph.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YAEdGraph.h"
3 | #include "YANode.h"
4 | #include "YetAnotherEdGraphNode.h"
5 | #include "EditorLogger.h"
6 | #include "EdGraph/EdGraphPin.h"
7 | #include "YAGraph.h"
8 |
9 | bool UYAEdGraph::IsNameUnique(const FText & InName)
10 | {
11 | bool bUnique = true;
12 | for (UEdGraphNode* Node : Nodes)
13 | {
14 | UYetAnotherEdGraphNode* PNode = Cast(Node);
15 | FText NodeName = PNode->GetEdNodeName();
16 | if (bUnique==true && !NodeName.IsEmpty())
17 | {
18 | if (NodeName.EqualToCaseIgnored(InName))
19 | {
20 | EDWLog("I found another node with the same name: %s.", *NodeName.ToString());
21 | bUnique = false;
22 | }
23 | }
24 | }
25 | return bUnique;
26 | }
27 |
28 | void UYAEdGraph::SaveGraph()
29 | {
30 | LinkAssetNodes();
31 | MapNamedNodes();
32 | }
33 |
34 | void UYAEdGraph::ClearOldLinks()
35 | {
36 | for (UEdGraphNode* EditorNode : Nodes)
37 | {
38 | UYetAnotherEdGraphNode* EdNode = Cast(EditorNode);
39 | if (EdNode)
40 | EdNode->AssetNode->ClearLinks();
41 | }
42 | }
43 |
44 | void UYAEdGraph::LinkAssetNodes()
45 | {
46 | ClearOldLinks();
47 | EDLLog("Starting to link all asset nodes from the editor graph links.");
48 | for (UEdGraphNode* EditorNode : Nodes)
49 | {
50 | if (UYetAnotherEdGraphNode* EdNode = Cast(EditorNode))
51 | {
52 | UYANode* NodeAsset = EdNode->AssetNode;
53 | if (NodeAsset != nullptr)
54 | {
55 |
56 | TArray& EdPinsParent = EdNode->Pins;
57 | TArrayChildren;
58 |
59 | for (UEdGraphPin* Pin : EdPinsParent)
60 | {
61 | //Take only the output pins
62 | if (Pin->Direction == EEdGraphPinDirection::EGPD_Output)
63 | {
64 |
65 | TArray& EdPinsChildren = Pin->LinkedTo;
66 | for (UEdGraphPin* LinkedPin : EdPinsChildren)
67 | Children.Add(LinkedPin->GetOwningNode());
68 |
69 | }
70 |
71 | }
72 |
73 | EdNode->SaveNodesAsChildren(Children);
74 | }
75 | else
76 | {
77 | EDELog("There is no asset node linked to this editor node.");
78 | }
79 | }
80 | else
81 | {
82 | EDWLog("An unknow EdNode has been found.");
83 | }
84 | }
85 |
86 | }
87 |
88 | void UYAEdGraph::RefreshNodes()
89 | {
90 | for (UEdGraphNode* Node : Nodes)
91 | {
92 | if (UYetAnotherEdGraphNode* YANode = Cast(Node))
93 | YANode->UpdateVisualNode();
94 | }
95 | }
96 |
97 | void UYAEdGraph::MapNamedNodes()
98 | {
99 | UYAGraph* Graph = GetGraphAsset();
100 | Graph->NamedNodes.Empty();
101 | Graph->NodesNames.Empty();
102 |
103 | for (UEdGraphNode* Node : Nodes)
104 | {
105 | if (UYetAnotherEdGraphNode* YANode = Cast(Node))
106 | {
107 | FText Name = YANode->GetEdNodeName();
108 | if (!Name.IsEmpty())
109 | {
110 | Graph->NamedNodes.Add(Name.ToString(), YANode->AssetNode);
111 | Graph->NodesNames.Add(YANode->AssetNode, Name.ToString());
112 | }
113 | }
114 | }
115 | }
116 |
117 | UYAGraph * UYAEdGraph::GetGraphAsset()
118 | {
119 | return Cast(GetOuter());
120 | }
121 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YAEdGraph.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "EdGraph/EdGraph.h"
8 | #include "YAEdGraph.generated.h"
9 |
10 | /**
11 | *
12 | */
13 | class UYAGraph;
14 |
15 | UCLASS()
16 | class UYAEdGraph : public UEdGraph
17 | {
18 | GENERATED_BODY()
19 |
20 | public:
21 |
22 | virtual bool IsNameUnique(const FText& InName);
23 | virtual void SaveGraph();
24 | virtual void ClearOldLinks();
25 | virtual void LinkAssetNodes();
26 | virtual void RefreshNodes();
27 | virtual void MapNamedNodes();
28 | virtual UYAGraph* GetGraphAsset();
29 | };
30 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YetAnotherEdGraphSchema.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherEdGraphSchema.h"
3 | #include "SubclassOf.h"
4 | #include "EditorLogger.h"
5 | #include "YAConnectionDrawingPolicy.h"
6 | #include "UObjectIterator.h"
7 | #include "YAEdGraphSchemaAction_NewNode.h"
8 | #include "EdGraph/EdGraph.h"
9 | #include "StartNode.h"
10 | #include "YAGraph.h"
11 | #include "YetAnotherEdGraphNode.h"
12 | #include "YetAnotherNodeClassHelper.h"
13 | #include "ModuleManager.h"
14 | #include "YetAnotherGraphEditor.h"
15 | #include "FlowControlNode.h"
16 | #include "FlowControlSchemaAction_NewNode.h"
17 |
18 | #define LOCTEXT_NAMESPACE "YetAnotherEdGraphSchema"
19 |
20 | UYetAnotherEdGraphSchema::UYetAnotherEdGraphSchema(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer){}
21 |
22 | void UYetAnotherEdGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder & ContextMenuBuilder) const
23 | {
24 |
25 | FText ToolTip = LOCTEXT("NewYetAnotherNodeTooltip", "Add a {NodeName} to the graph.");
26 | FText MenuDesc = LOCTEXT("NewYetAnotherNodeDescription", "{NodeName}");
27 |
28 | FYetAnotherGraphEditorModule& YAModule = FModuleManager::GetModuleChecked("YetAnotherGraphEditor");
29 | TSharedPtr Helper = YAModule.GetHelper();
30 |
31 | //Gathering C++ classes
32 |
33 | FCategorizedGraphActionListBuilder BaseBuilder(TEXT("Base Nodes"));
34 |
35 | TArray NativeClasses;
36 | Helper->GatherClasses(UYANode::StaticClass(),NativeClasses);
37 |
38 | for (auto& NativeClassData : NativeClasses)
39 | {
40 | if (NativeClassData.GetClass()->HasAnyClassFlags(CLASS_Native))
41 | {
42 | FFormatNamedArguments Arguments;
43 | Arguments.Add(TEXT("NodeName"), NativeClassData.GetClass()->GetDisplayNameText());
44 | TSharedPtr NewNodeAction;
45 |
46 | if (NativeClassData.GetClass()->IsChildOf(UFlowControlNode::StaticClass()))
47 | {
48 | NewNodeAction = MakeShareable(new FFlowControlSchemaAction_NewNode(NativeClassData.GetCategory(), FText::Format(MenuDesc, Arguments), FText::Format(ToolTip, Arguments), 0, NativeClassData.GetClass()));
49 | }
50 | else
51 | {
52 | NewNodeAction = MakeShareable(new FYAEdGraphSchemaAction_NewNode(NativeClassData.GetCategory(), FText::Format(MenuDesc, Arguments), FText::Format(ToolTip, Arguments), 0, NativeClassData.GetClass()));
53 | }
54 |
55 | BaseBuilder.AddAction(NewNodeAction);
56 | }
57 | }
58 |
59 | ContextMenuBuilder.Append(BaseBuilder);
60 |
61 | //Gathering child blueprints
62 |
63 | TArray BlueprintClasses;
64 | Helper->GatherClasses(USimpleNode::StaticClass(), BlueprintClasses);
65 | Helper->GatherClasses(UFlowControlNode::StaticClass(), BlueprintClasses);
66 |
67 | FCategorizedGraphActionListBuilder BlueprintBuilder(TEXT("UserDefinedNodes"));
68 |
69 | for (auto& BlueprintClassData : BlueprintClasses)
70 | {
71 | if (!BlueprintClassData.GetClass()->HasAnyClassFlags(CLASS_Native))
72 | {
73 | FFormatNamedArguments Arguments;
74 | Arguments.Add(TEXT("NodeName"), BlueprintClassData.GetClass()->GetDisplayNameText());
75 | TSharedPtr NewNodeAction;
76 |
77 | if (BlueprintClassData.GetClass()->IsChildOf(UFlowControlNode::StaticClass()))
78 | {
79 | NewNodeAction = MakeShareable(new FFlowControlSchemaAction_NewNode(BlueprintClassData.GetCategory(), FText::Format(MenuDesc, Arguments), FText::Format(ToolTip, Arguments), 0, BlueprintClassData.GetClass()));
80 | }
81 | else
82 | {
83 | NewNodeAction = MakeShareable(new FYAEdGraphSchemaAction_NewNode(BlueprintClassData.GetCategory(), FText::Format(MenuDesc, Arguments), FText::Format(ToolTip, Arguments), 0, BlueprintClassData.GetClass()));
84 | }
85 |
86 | BlueprintBuilder.AddAction(NewNodeAction);
87 | }
88 | }
89 |
90 | ContextMenuBuilder.Append(BlueprintBuilder);
91 | }
92 |
93 | void UYetAnotherEdGraphSchema::GetContextMenuActions(const UEdGraph * CurrentGraph, const UEdGraphNode * InGraphNode, const UEdGraphPin * InGraphPin, FMenuBuilder * MenuBuilder, bool bIsDebugging) const
94 | {
95 | }
96 |
97 | const FPinConnectionResponse UYetAnotherEdGraphSchema::CanCreateConnection(const UEdGraphPin * A, const UEdGraphPin * B) const
98 | {
99 | if(!(A && B))
100 | return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("Both pins must be available."));
101 |
102 | if (A->GetOwningNode() == B->GetOwningNode())
103 | return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("You can't connect a node to itself."));
104 |
105 | if (A->Direction == EGPD_Input && B->Direction == EGPD_Input)
106 | return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("You can't connect an input pin to another input pin."));
107 |
108 | if (A->Direction == EGPD_Output && B->Direction == EGPD_Output)
109 | return FPinConnectionResponse(CONNECT_RESPONSE_DISALLOW, TEXT("You can't connect an output pin to another output pin"));
110 |
111 | return FPinConnectionResponse(CONNECT_RESPONSE_MAKE, TEXT(""));
112 | }
113 |
114 | FConnectionDrawingPolicy * UYetAnotherEdGraphSchema::CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect & InClippingRect, FSlateWindowElementList & InDrawElements, UEdGraph * InGraphObj) const
115 | {
116 | return new FYAConnectionDrawingPolicy(InBackLayerID, InFrontLayerID, InZoomFactor, InClippingRect, InDrawElements, InGraphObj);
117 | }
118 |
119 | void UYetAnotherEdGraphSchema::CreateDefaultNodesForGraph(UEdGraph & Graph) const
120 | {
121 | if (Graph.Nodes.Num() == 0)
122 | {
123 | UYAGraph* GraphAsset = Cast(Graph.GetOuter());
124 |
125 | GraphAsset->Modify();
126 | Graph.Modify();
127 |
128 | UYANode* AssetNode = GraphAsset->SpawnNodeInsideGraph(UStartNode::StaticClass());
129 |
130 |
131 | FGraphNodeCreatorCreator(Graph);
132 | UYetAnotherEdGraphNode* EdNode = Creator.CreateNode();
133 | EdNode->SetAssetNode(AssetNode);
134 | EdNode->AllocateDefaultPins();
135 |
136 | Creator.Finalize();
137 |
138 | EdNode->NodePosX = 0;
139 | EdNode->NodePosY = 0;
140 | }
141 | }
142 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/EditorGraph/YetAnotherEdGraphSchema.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "EdGraph/EdGraphSchema.h"
8 | #include "YANode.h"
9 | #include "YetAnotherEdGraphSchema.generated.h"
10 |
11 | /**
12 | *
13 | */
14 | UCLASS()
15 | class UYetAnotherEdGraphSchema : public UEdGraphSchema
16 | {
17 | GENERATED_UCLASS_BODY()
18 |
19 | public:
20 |
21 | /**
22 | * Get all actions that can be performed when right clicking on a graph or drag-releasing on a graph from a pin
23 | *
24 | * @param [in,out] ContextMenuBuilder The context (graph, dragged pin, etc...) and output menu builder.
25 | */
26 | void GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const override;
27 |
28 | /**
29 | * Gets actions that should be added to the right-click context menu for a node or pin
30 | *
31 | * @param CurrentGraph The current graph.
32 | * @param InGraphNode The node to get the context menu for, if any.
33 | * @param InGraphPin The pin clicked on, if any, to provide additional context
34 | * @param MenuBuilder The menu builder to append actions to.
35 | * @param bIsDebugging Is the graph editor currently part of a debugging session (any non-debugging commands should be disabled)
36 | */
37 | void GetContextMenuActions(const UEdGraph* CurrentGraph, const UEdGraphNode* InGraphNode, const UEdGraphPin* InGraphPin, class FMenuBuilder* MenuBuilder, bool bIsDebugging) const override;
38 |
39 | /**
40 | * Determine if a connection can be created between two pins.
41 | *
42 | * @param A The first pin.
43 | * @param B The second pin.
44 | *
45 | * @return An empty string if the connection is legal, otherwise a message describing why the connection would fail.
46 | */
47 | virtual const FPinConnectionResponse CanCreateConnection(const UEdGraphPin* A, const UEdGraphPin* B) const override;
48 |
49 | /* returns new FConnectionDrawingPolicy from this schema */
50 | virtual class FConnectionDrawingPolicy* CreateConnectionDrawingPolicy(int32 InBackLayerID, int32 InFrontLayerID, float InZoomFactor, const FSlateRect& InClippingRect, class FSlateWindowElementList& InDrawElements, class UEdGraph* InGraphObj) const override;
51 |
52 | /**
53 | * Populate new graph with any default nodes
54 | *
55 | * @param Graph Graph to add the default nodes to
56 | * @param ContextClass If specified, the graph terminators will use this class to search for context for signatures (i.e. interface functions)
57 | */
58 | virtual void CreateDefaultNodesForGraph(UEdGraph& Graph) const override;
59 |
60 | };
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Factories/YetAnotherAssetFactory.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherAssetFactory.h"
3 | #include "YAGraph.h"
4 |
5 | UYetAnotherAssetFactory::UYetAnotherAssetFactory()
6 | {
7 | SupportedClass = UYAGraph::StaticClass();
8 | bCreateNew = true;
9 | bEditAfterNew = true;
10 | }
11 |
12 | UObject* UYetAnotherAssetFactory::FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
13 | {
14 | return NewObject(InParent, InClass, InName, Flags);
15 | }
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Factories/YetAnotherAssetFactory.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "Factories/Factory.h"
6 | #include "YetAnotherAssetFactory.generated.h"
7 |
8 | /**
9 | *
10 | */
11 | UCLASS()
12 | class UYetAnotherAssetFactory : public UFactory
13 | {
14 | GENERATED_BODY()
15 |
16 | public:
17 | UYetAnotherAssetFactory();
18 | /**
19 | * Create a new object by class.
20 | *
21 | * @param InClass
22 | * @param InParent
23 | * @param InName
24 | * @param Flags
25 | * @param Context
26 | * @param Warn
27 | * @return The new object.
28 | */
29 | virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn);
30 |
31 |
32 |
33 | };
34 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Toolkits/YetAnotherGraphEditorToolkit.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherGraphEditorToolkit.h"
3 | #include "EditorLogger.h"
4 | #include "PropertyEditorModule.h"
5 | #include "ModuleManager.h"
6 | #include "Slate.h"
7 | #include "BlueprintEditorUtils.h"
8 | #include "GraphEditorActions.h"
9 | #include "YAEdGraph.h"
10 | #include "YetAnotherEdGraphSchema.h"
11 | #include "EdGraphUtilities.h"
12 | #include "PlatformApplicationMisc.h"
13 | #include "YetAnotherEdGraphNode.h"
14 | #include "Editor.h"
15 |
16 |
17 | #define LOCTEXT_NAMESPACE "YetAnotherGraphEditorToolkit"
18 |
19 | const FName FYetAnotherGraphEditorToolkit::DetailsTabId(TEXT("YetAnotherGraphEditorToolkitDetailsTabId"));
20 | const FName FYetAnotherGraphEditorToolkit::GraphTabId(TEXT("YetAnotherGraphEditorToolkitGraphTabId"));
21 |
22 |
23 | FYetAnotherGraphEditorToolkit::FYetAnotherGraphEditorToolkit()
24 | {
25 | GEditor->OnBlueprintCompiled().AddRaw(this,&FYetAnotherGraphEditorToolkit::BlueprintCompiled);
26 | }
27 |
28 | FYetAnotherGraphEditorToolkit::~FYetAnotherGraphEditorToolkit()
29 | {
30 | GEditor->OnBlueprintCompiled().RemoveAll(this);
31 | }
32 |
33 |
34 |
35 | FGraphPanelSelectionSet FYetAnotherGraphEditorToolkit::GetSelectedNodes()
36 | {
37 | return EdGraphEditor->GetSelectedNodes();
38 | }
39 |
40 | TSharedRef FYetAnotherGraphEditorToolkit::HandleTabManagerSpawnTabDetails(const FSpawnTabArgs & Args)
41 | {
42 |
43 | FDetailsViewArgs DetailsViewArgs;
44 | DetailsViewArgs.bUpdatesFromSelection = false;
45 | DetailsViewArgs.bCustomNameAreaLocation = false;
46 | DetailsViewArgs.bLockable = false;
47 | DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
48 | DetailsViewArgs.NotifyHook = this;
49 |
50 | FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked("PropertyEditor");
51 |
52 | DetailsWidget = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
53 | DetailsWidget->SetObject(GraphAsset);
54 |
55 | return SNew(SDockTab)
56 | .TabRole(ETabRole::PanelTab)
57 | [
58 | DetailsWidget.ToSharedRef()
59 | ];
60 | }
61 |
62 | TSharedRef FYetAnotherGraphEditorToolkit::HandleTabManagerSpawnTabGraph(const FSpawnTabArgs & Args)
63 | {
64 |
65 | if (GraphAsset->EdGraph != nullptr)
66 | {
67 | EdGraphEditor = SNew(SGraphEditor)
68 | .AdditionalCommands(GraphEditorCommands)
69 | .GraphToEdit(GraphAsset->EdGraph);
70 | }
71 | else
72 | {
73 | EDELog("There is no editor graph inside the graph asset.");
74 | }
75 | return SNew(SDockTab)
76 | .TabRole(ETabRole::PanelTab)
77 | [
78 | EdGraphEditor.ToSharedRef()
79 | ];
80 | }
81 |
82 | FLinearColor FYetAnotherGraphEditorToolkit::GetWorldCentricTabColorScale() const
83 | {
84 | return FLinearColor::Blue;
85 | }
86 |
87 | FName FYetAnotherGraphEditorToolkit::GetToolkitFName() const
88 | {
89 | return FName("Graph Editor");
90 | }
91 |
92 | FText FYetAnotherGraphEditorToolkit::GetBaseToolkitName() const
93 | {
94 | return LOCTEXT("AppLabel", "Graph Editor");
95 | }
96 |
97 | FString FYetAnotherGraphEditorToolkit::GetWorldCentricTabPrefix() const
98 | {
99 | return LOCTEXT("WorldCentricTabPrefix", "Graph").ToString();
100 | }
101 |
102 | void FYetAnotherGraphEditorToolkit::InitGraphAssetEditor(const EToolkitMode::Type InMode, const TSharedPtr& InToolkitHost, UYAGraph * InGraph)
103 | {
104 | GraphAsset = InGraph;
105 | if (GraphAsset->EdGraph == nullptr)
106 | {
107 | EDLLog("Creating a new graph.");
108 | GraphAsset->EdGraph = CastChecked(FBlueprintEditorUtils::CreateNewGraph(GraphAsset, NAME_None, UYAEdGraph::StaticClass(), UYetAnotherEdGraphSchema::StaticClass()));
109 | GraphAsset->EdGraph->bAllowDeletion = false;
110 |
111 | //Give the schema a chance to fill out any required nodes (like the results node)
112 | const UEdGraphSchema* Schema = GraphAsset->EdGraph->GetSchema();
113 | Schema->CreateDefaultNodesForGraph(*GraphAsset->EdGraph);
114 | }
115 |
116 | FGenericCommands::Register();
117 | FGraphEditorCommands::Register();
118 | BindToolkitCommands();
119 |
120 | TSharedRefLayout = FTabManager::NewLayout("LayoutName")
121 | ->AddArea
122 | (
123 | FTabManager::NewPrimaryArea()
124 | ->SetOrientation(Orient_Vertical)
125 | ->Split
126 | (
127 | FTabManager::NewStack()
128 | ->AddTab(GetToolbarTabId(), ETabState::OpenedTab)
129 | ->SetHideTabWell(true)
130 | ->SetSizeCoefficient(0.2f)
131 | )
132 | ->Split
133 | (
134 | FTabManager::NewSplitter()
135 | ->SetOrientation(Orient_Horizontal)
136 | ->SetSizeCoefficient(0.8f)
137 | ->Split
138 | (
139 | FTabManager::NewStack()
140 | ->AddTab(DetailsTabId, ETabState::OpenedTab)
141 | ->SetHideTabWell(true)
142 | ->SetSizeCoefficient(0.15f)
143 | )
144 | ->Split
145 | (
146 | FTabManager::NewStack()
147 | ->AddTab(GraphTabId, ETabState::OpenedTab)
148 | ->SetHideTabWell(true)
149 | ->SetSizeCoefficient(0.85f)
150 | )
151 | )
152 | );
153 |
154 | FAssetEditorToolkit::InitAssetEditor(InMode, InToolkitHost, FName("GraphEditorIdentifier"), Layout, true, true, GraphAsset);
155 | }
156 |
157 | void FYetAnotherGraphEditorToolkit::BlueprintCompiled()
158 | {
159 | UEdGraph* EdGraph = EdGraphEditor->GetCurrentGraph();
160 | if (UYAEdGraph* MyGraph = Cast(EdGraph))
161 | MyGraph->RefreshNodes();
162 | }
163 |
164 | void FYetAnotherGraphEditorToolkit::SaveAsset_Execute()
165 | {
166 | if (GraphAsset && GraphAsset->EdGraph)
167 | {
168 | UYAEdGraph* EdGraph = Cast(GraphAsset->EdGraph);
169 | EdGraph->SaveGraph();
170 | }
171 | FAssetEditorToolkit::SaveAsset_Execute();
172 | }
173 |
174 | void FYetAnotherGraphEditorToolkit::RegisterTabSpawners(const TSharedRef& TabManager)
175 | {
176 |
177 | WorkspaceMenuCategory = TabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("YetAnotherToolkitWorkspaceMenu", "Graph Editor"));
178 | auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();
179 |
180 | TabManager->RegisterTabSpawner(DetailsTabId, FOnSpawnTab::CreateSP(this, &FYetAnotherGraphEditorToolkit::HandleTabManagerSpawnTabDetails))
181 | .SetDisplayName(LOCTEXT("DetailsTab", "Details"))
182 | .SetGroup(WorkspaceMenuCategoryRef);
183 | TabManager->RegisterTabSpawner(GraphTabId, FOnSpawnTab::CreateSP(this, &FYetAnotherGraphEditorToolkit::HandleTabManagerSpawnTabGraph))
184 | .SetDisplayName(LOCTEXT("GraphTab", "Graph Editor"))
185 | .SetGroup(WorkspaceMenuCategoryRef);
186 |
187 | FAssetEditorToolkit::RegisterTabSpawners(TabManager);
188 | }
189 |
190 | void FYetAnotherGraphEditorToolkit::UnregisterTabSpawners(const TSharedRef& TabManager)
191 | {
192 | FAssetEditorToolkit::UnregisterTabSpawners(TabManager);
193 | TabManager->UnregisterTabSpawner(DetailsTabId);
194 | TabManager->UnregisterTabSpawner(GraphTabId);
195 | }
196 |
197 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
198 | // Commands and Bindings
199 | void FYetAnotherGraphEditorToolkit::BindToolkitCommands()
200 | {
201 | if (!GraphEditorCommands.IsValid())
202 | {
203 | GraphEditorCommands = MakeShareable(new FUICommandList());
204 |
205 | GraphEditorCommands->MapAction
206 | (
207 | FGenericCommands::Get().SelectAll,
208 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandSelectAllNodes),
209 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanSelectAllNodes)
210 | );
211 |
212 | GraphEditorCommands->MapAction
213 | (
214 | FGenericCommands::Get().Cut,
215 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandCut),
216 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanCutNodes)
217 | );
218 |
219 | GraphEditorCommands->MapAction
220 | (
221 | FGenericCommands::Get().Copy,
222 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandCopy),
223 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanCopyNodes)
224 | );
225 |
226 | GraphEditorCommands->MapAction
227 | (
228 | FGenericCommands::Get().Paste,
229 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandPaste),
230 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanPasteNodes)
231 | );
232 |
233 | GraphEditorCommands->MapAction
234 | (
235 | FGenericCommands::Get().Duplicate,
236 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandDuplicate),
237 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanDuplicateNodes)
238 | );
239 |
240 | GraphEditorCommands->MapAction
241 | (
242 | FGenericCommands::Get().Delete,
243 | FExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::OnCommandDelete),
244 | FCanExecuteAction::CreateRaw(this, &FYetAnotherGraphEditorToolkit::CanDeleteNodes)
245 | );
246 |
247 | }
248 | }
249 |
250 | void FYetAnotherGraphEditorToolkit::OnCommandSelectAllNodes()
251 | {
252 | if (EdGraphEditor.IsValid())
253 | EdGraphEditor->SelectAllNodes();
254 | }
255 |
256 | bool FYetAnotherGraphEditorToolkit::CanSelectAllNodes()
257 | {
258 | return true;
259 | }
260 |
261 | void FYetAnotherGraphEditorToolkit::OnCommandCut()
262 | {
263 | OnCommandCopy();
264 |
265 | const FGraphPanelSelectionSet OldSelectedNodes = EdGraphEditor->GetSelectedNodes();
266 | EdGraphEditor->ClearSelectionSet();
267 | for (FGraphPanelSelectionSet::TConstIterator It(OldSelectedNodes); It; ++It)
268 | {
269 | UEdGraphNode* Node = Cast(*It);
270 | if (Node && Node->CanDuplicateNode())
271 | {
272 | EdGraphEditor->SetNodeSelection(Node, true);
273 | }
274 | }
275 |
276 | OnCommandDelete();
277 |
278 | EdGraphEditor->ClearSelectionSet();
279 |
280 | for (FGraphPanelSelectionSet::TConstIterator It(OldSelectedNodes); It; ++It)
281 | {
282 | UEdGraphNode* Node = Cast(*It);
283 | if (Node)
284 | EdGraphEditor->SetNodeSelection(Node, true);
285 | }
286 | }
287 |
288 | bool FYetAnotherGraphEditorToolkit::CanCutNodes()
289 | {
290 | return true;
291 | }
292 |
293 | void FYetAnotherGraphEditorToolkit::OnCommandCopy()
294 | {
295 | FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes();
296 | FString ExportedText;
297 |
298 | for (FGraphPanelSelectionSet::TIterator it(SelectedNodes); it; ++it)
299 | {
300 | UEdGraphNode* Node = Cast(*it);
301 | if (Node)
302 | Node->PrepareForCopying();
303 | else
304 | it.RemoveCurrent();
305 | }
306 |
307 | FEdGraphUtilities::ExportNodesToText(SelectedNodes, ExportedText);
308 | FPlatformApplicationMisc::ClipboardCopy(*ExportedText);
309 |
310 | for (FGraphPanelSelectionSet::TIterator it(SelectedNodes); it; ++it)
311 | {
312 | UYetAnotherEdGraphNode* Node = Cast(*it);
313 | if (Node)
314 | Node->PostCopyNode();
315 | }
316 | }
317 |
318 | bool FYetAnotherGraphEditorToolkit::CanCopyNodes()
319 | {
320 | return true;
321 | }
322 |
323 | void FYetAnotherGraphEditorToolkit::OnCommandPaste()
324 | {
325 |
326 | const FVector2D PasteLocation = EdGraphEditor->GetPasteLocation();
327 |
328 | UEdGraph* EdGraph = EdGraphEditor->GetCurrentGraph();
329 | EdGraph->Modify();
330 | EdGraphEditor->ClearSelectionSet();
331 |
332 | FString ExportedText;
333 | FPlatformApplicationMisc::ClipboardPaste(ExportedText);
334 | TSet ImportedNodes;
335 | FEdGraphUtilities::ImportNodesFromText(EdGraph, ExportedText, ImportedNodes);
336 |
337 | for (TSet::TIterator It(ImportedNodes); It; ++It)
338 | {
339 | UYetAnotherEdGraphNode* Node = Cast(*It);
340 | GraphAsset->AddNode(Node->AssetNode);
341 | }
342 |
343 | FVector2D AvgNodePosition(0.0f, 0.0f);
344 |
345 | for (TSet::TIterator It(ImportedNodes); It; ++It)
346 | {
347 | UEdGraphNode* Node = *It;
348 | AvgNodePosition.X += Node->NodePosX;
349 | AvgNodePosition.Y += Node->NodePosY;
350 | }
351 |
352 | float InvNumNodes = 1.0f / float(ImportedNodes.Num());
353 | AvgNodePosition.X *= InvNumNodes;
354 | AvgNodePosition.Y *= InvNumNodes;
355 |
356 | for (TSet::TIterator It(ImportedNodes); It; ++It)
357 | {
358 | UEdGraphNode* Node = *It;
359 | EdGraphEditor->SetNodeSelection(Node, true);
360 |
361 | Node->NodePosX = (Node->NodePosX - AvgNodePosition.X) + PasteLocation.X;
362 | Node->NodePosY = (Node->NodePosY - AvgNodePosition.Y) + PasteLocation.Y;
363 |
364 | Node->SnapToGrid(16);
365 |
366 | // Give new node a different Guid from the old one
367 | Node->CreateNewGuid();
368 | }
369 |
370 | EdGraphEditor->NotifyGraphChanged();
371 |
372 | UObject* GraphOwner = EdGraph->GetOuter();
373 | if (GraphOwner)
374 | {
375 | GraphOwner->PostEditChange();
376 | GraphOwner->MarkPackageDirty();
377 | }
378 |
379 | }
380 |
381 | bool FYetAnotherGraphEditorToolkit::CanPasteNodes()
382 | {
383 | return true;
384 | }
385 |
386 | void FYetAnotherGraphEditorToolkit::OnCommandDuplicate()
387 | {
388 | OnCommandCopy();
389 | OnCommandPaste();
390 | }
391 |
392 | bool FYetAnotherGraphEditorToolkit::CanDuplicateNodes()
393 | {
394 | return true;
395 | }
396 |
397 | void FYetAnotherGraphEditorToolkit::OnCommandDelete()
398 | {
399 |
400 | EdGraphEditor->GetCurrentGraph()->Modify();
401 |
402 | const FGraphPanelSelectionSet SelectedNodes = GetSelectedNodes();
403 | EdGraphEditor->ClearSelectionSet();
404 |
405 | for (FGraphPanelSelectionSet::TConstIterator It(SelectedNodes); It; ++It)
406 | {
407 | if (UEdGraphNode* Node = Cast(*It))
408 | {
409 | Node->Modify();
410 | Node->DestroyNode();
411 | }
412 | }
413 | }
414 |
415 | bool FYetAnotherGraphEditorToolkit::CanDeleteNodes()
416 | {
417 | return true;
418 | }
419 |
420 | // END Commands and binding
421 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
422 |
423 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Toolkits/YetAnotherGraphEditorToolkit.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "AssetEditorToolkit.h"
6 | #include "NotifyHook.h"
7 | #include "GraphEditor.h"
8 | #include "IDetailsView.h"
9 | #include "YAGraph.h"
10 |
11 | /**
12 | *
13 | */
14 | class FYetAnotherGraphEditorToolkit : public FAssetEditorToolkit, public FNotifyHook
15 | {
16 | public:
17 | FYetAnotherGraphEditorToolkit();
18 | ~FYetAnotherGraphEditorToolkit();
19 |
20 | // Inherited via FAssetEditorToolkit
21 | virtual FLinearColor GetWorldCentricTabColorScale() const override;
22 | virtual FName GetToolkitFName() const override;
23 | virtual FText GetBaseToolkitName() const override;
24 | virtual FString GetWorldCentricTabPrefix() const override;
25 | virtual void RegisterTabSpawners(const TSharedRef& TabManager) override;
26 | virtual void UnregisterTabSpawners(const TSharedRef& TabManager) override;
27 | virtual void SaveAsset_Execute() override;
28 |
29 | virtual void InitGraphAssetEditor(const EToolkitMode::Type InMode, const TSharedPtr& InToolkitHost, UYAGraph* InGraph);
30 | virtual void BlueprintCompiled();
31 | private:
32 |
33 | static const FName DetailsTabId;
34 | static const FName GraphTabId;
35 |
36 | UYAGraph* GraphAsset;
37 | TSharedPtr EdGraphEditor;
38 | TSharedPtr DetailsWidget;
39 |
40 | TSharedPtr GraphEditorCommands;
41 |
42 | FGraphPanelSelectionSet GetSelectedNodes();
43 | TSharedRef HandleTabManagerSpawnTabDetails(const FSpawnTabArgs& Args);
44 | TSharedRef HandleTabManagerSpawnTabGraph(const FSpawnTabArgs& Args);
45 | void BindToolkitCommands();
46 |
47 | //Delegates
48 | void OnCommandSelectAllNodes();
49 | bool CanSelectAllNodes();
50 |
51 | void OnCommandCopy();
52 | bool CanCopyNodes();
53 |
54 | void OnCommandPaste();
55 | bool CanPasteNodes();
56 |
57 | void OnCommandCut();
58 | bool CanCutNodes();
59 |
60 | void OnCommandDuplicate();
61 | bool CanDuplicateNodes();
62 |
63 | void OnCommandDelete();
64 | bool CanDeleteNodes();
65 |
66 | };
67 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Utility/EditorLogger.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "EditorLogger.h"
3 |
4 | DEFINE_LOG_CATEGORY(LogYetAnotherGraphEditor);
5 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Utility/EditorLogger.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | DECLARE_LOG_CATEGORY_EXTERN(LogYetAnotherGraphEditor, Verbose, All);
6 | #define EDLLog(Message,...) UE_LOG(LogYetAnotherGraphEditor, Log, TEXT(Message), ##__VA_ARGS__)
7 | #define EDDLog(Message,...) UE_LOG(LogYetAnotherGraphEditor, Display, TEXT(Message), ##__VA_ARGS__)
8 | #define EDWLog(Message,...) UE_LOG(LogYetAnotherGraphEditor, Warning, TEXT(Message), ##__VA_ARGS__)
9 | #define EDELog(Message,...) UE_LOG(LogYetAnotherGraphEditor, Error, TEXT(Message), ##__VA_ARGS__)
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Utility/YetAnotherNodeClassHelper.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherNodeClassHelper.h"
3 | #include "Class.h"
4 | #include "FeedbackContext.h"
5 | #include "Package.h"
6 | #include "Engine/Blueprint.h"
7 | #include "AssetRegistryModule.h"
8 | #include "HotReloadInterface.h"
9 | #include "Editor.h"
10 | #include "ConstructorHelpers.h"
11 | #include "EditorLogger.h"
12 |
13 | #define LOCTEXT_NAMESPACE "YetAnotherNodeClassHelper"
14 |
15 |
16 | FYetAnotherNodeClassData::FYetAnotherNodeClassData(UClass* InClass, const FString& InDeprecatedMessage) :
17 | bIsHidden(0),
18 | bHideParent(0),
19 | Class(InClass),
20 | DeprecatedMessage(InDeprecatedMessage)
21 | {
22 | Category = GetCategory();
23 |
24 | if (InClass)
25 | {
26 | ClassName = InClass->GetName();
27 | }
28 | }
29 |
30 | FYetAnotherNodeClassData::FYetAnotherNodeClassData(const FString& InAssetName, const FString& InGeneratedClassPackage, const FString& InClassName, UClass* InClass) :
31 | bIsHidden(0),
32 | bHideParent(0),
33 | Class(InClass),
34 | AssetName(InAssetName),
35 | GeneratedClassPackage(InGeneratedClassPackage),
36 | ClassName(InClassName)
37 | {
38 | Category = GetCategory();
39 | }
40 |
41 | FString FYetAnotherNodeClassData::ToString() const
42 | {
43 | FString ShortName = GetDisplayName();
44 | if (!ShortName.IsEmpty())
45 | {
46 | return ShortName;
47 | }
48 |
49 | UClass* MyClass = Class.Get();
50 | if (MyClass)
51 | {
52 | FString ClassDesc = MyClass->GetName();
53 |
54 | if (MyClass->HasAnyClassFlags(CLASS_CompiledFromBlueprint))
55 | {
56 | return ClassDesc.LeftChop(2);
57 | }
58 |
59 | const int32 ShortNameIdx = ClassDesc.Find(TEXT("_"));
60 | if (ShortNameIdx != INDEX_NONE)
61 | {
62 | ClassDesc = ClassDesc.Mid(ShortNameIdx + 1);
63 | }
64 |
65 | return ClassDesc;
66 | }
67 |
68 | return AssetName;
69 | }
70 |
71 | FString FYetAnotherNodeClassData::GetClassName() const
72 | {
73 | return Class.IsValid() ? Class->GetName() : ClassName;
74 | }
75 |
76 | FString FYetAnotherNodeClassData::GetDisplayName() const
77 | {
78 | return Class.IsValid() ? Class->GetMetaData(TEXT("DisplayName")) : FString();
79 | }
80 |
81 | FText FYetAnotherNodeClassData::GetCategory() const
82 | {
83 | return Class.IsValid() ? Class->GetMetaDataText(TEXT("Category"), TEXT("UObjectCategory"), Class->GetFullGroupName(false)) : Category;
84 | }
85 |
86 | bool FYetAnotherNodeClassData::IsAbstract() const
87 | {
88 | return Class.IsValid() ? Class.Get()->HasAnyClassFlags(CLASS_Abstract) : false;
89 | }
90 |
91 | UClass* FYetAnotherNodeClassData::GetClass(bool bSilent)
92 | {
93 | UClass* RetClass = Class.Get();
94 | if (RetClass == NULL && GeneratedClassPackage.Len())
95 | {
96 | GWarn->BeginSlowTask(LOCTEXT("LoadPackage", "Loading Package..."), true);
97 |
98 | UPackage* Package = LoadPackage(NULL, *GeneratedClassPackage, LOAD_NoRedirects);
99 | if (Package)
100 | {
101 | Package->FullyLoad();
102 |
103 | UObject* Object = FindObject(Package, *AssetName);
104 |
105 | GWarn->EndSlowTask();
106 |
107 | UBlueprint* BlueprintOb = Cast(Object);
108 | RetClass = BlueprintOb ? *BlueprintOb->GeneratedClass :
109 | Object ? Object->GetClass() :
110 | NULL;
111 |
112 | Class = RetClass;
113 | }
114 | }
115 |
116 | return RetClass;
117 | }
118 |
119 | //////////////////////////////////////////////////////////////////////////
120 | TArray FYetAnotherNodeClassHelper::UnknownPackages;
121 | TMap FYetAnotherNodeClassHelper::BlueprintClassCount;
122 | FYetAnotherNodeClassHelper::FOnPackageListUpdated FYetAnotherNodeClassHelper::OnPackageListUpdated;
123 |
124 | FYetAnotherNodeClassHelper::FYetAnotherNodeClassHelper(UClass* InRootClass)
125 | {
126 | RootNodeClass = InRootClass;
127 | // Register with the Asset Registry to be informed when it is done loading up files.
128 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked(TEXT("AssetRegistry"));
129 | AssetRegistryModule.Get().OnFilesLoaded().AddRaw(this, &FYetAnotherNodeClassHelper::InvalidateCache);
130 | AssetRegistryModule.Get().OnAssetAdded().AddRaw(this, &FYetAnotherNodeClassHelper::OnAssetAdded);
131 | AssetRegistryModule.Get().OnAssetRemoved().AddRaw(this, &FYetAnotherNodeClassHelper::OnAssetRemoved);
132 |
133 | // Register to have Populate called when doing a Hot Reload.
134 | IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked("HotReload");
135 | HotReloadSupport.OnHotReload().AddRaw(this, &FYetAnotherNodeClassHelper::OnHotReload);
136 |
137 | // Register to have Populate called when a Blueprint is compiled.
138 | GEditor->OnBlueprintCompiled().AddRaw(this, &FYetAnotherNodeClassHelper::InvalidateCache);
139 | GEditor->OnClassPackageLoadedOrUnloaded().AddRaw(this, &FYetAnotherNodeClassHelper::InvalidateCache);
140 |
141 | UpdateAvailableBlueprintClasses();
142 | }
143 |
144 | FYetAnotherNodeClassHelper::~FYetAnotherNodeClassHelper()
145 | {
146 | // Unregister with the Asset Registry to be informed when it is done loading up files.
147 | if (FModuleManager::Get().IsModuleLoaded(TEXT("AssetRegistry")))
148 | {
149 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked(TEXT("AssetRegistry"));
150 | AssetRegistryModule.Get().OnFilesLoaded().RemoveAll(this);
151 | AssetRegistryModule.Get().OnAssetAdded().RemoveAll(this);
152 | AssetRegistryModule.Get().OnAssetRemoved().RemoveAll(this);
153 |
154 | // Unregister to have Populate called when doing a Hot Reload.
155 | if (FModuleManager::Get().IsModuleLoaded(TEXT("HotReload")))
156 | {
157 | IHotReloadInterface& HotReloadSupport = FModuleManager::GetModuleChecked("HotReload");
158 | HotReloadSupport.OnHotReload().RemoveAll(this);
159 | }
160 |
161 | // Unregister to have Populate called when a Blueprint is compiled.
162 | if (UObjectInitialized())
163 | {
164 | // GEditor can't have been destructed before we call this or we'll crash.
165 | GEditor->OnBlueprintCompiled().RemoveAll(this);
166 | GEditor->OnClassPackageLoadedOrUnloaded().RemoveAll(this);
167 | }
168 | }
169 | }
170 |
171 | void FYetAnotherNodeClassNode::AddUniqueSubNode(TSharedPtr SubNode)
172 | {
173 | for (int32 Idx = 0; Idx < SubNodes.Num(); Idx++)
174 | {
175 | if (SubNode->Data.GetClassName() == SubNodes[Idx]->Data.GetClassName())
176 | {
177 | return;
178 | }
179 | }
180 |
181 | SubNodes.Add(SubNode);
182 | }
183 |
184 | void FYetAnotherNodeClassHelper::GatherClasses(const UClass* BaseClass, TArray& AvailableClasses)
185 | {
186 | const FString BaseClassName = BaseClass->GetName();
187 | if (!RootNode.IsValid())
188 | {
189 | BuildClassGraph();
190 | }
191 |
192 | TSharedPtr BaseNode = FindBaseClassNode(RootNode, BaseClassName);
193 | FindAllSubClasses(BaseNode, AvailableClasses);
194 | }
195 |
196 | FString FYetAnotherNodeClassHelper::GetDeprecationMessage(const UClass* Class)
197 | {
198 | static FName MetaDeprecated = TEXT("DeprecatedNode");
199 | static FName MetaDeprecatedMessage = TEXT("DeprecationMessage");
200 | FString DefDeprecatedMessage("Please remove it!");
201 | FString DeprecatedPrefix("DEPRECATED");
202 | FString DeprecatedMessage;
203 |
204 | if (Class && Class->HasAnyClassFlags(CLASS_Native) && Class->HasMetaData(MetaDeprecated))
205 | {
206 | DeprecatedMessage = DeprecatedPrefix + TEXT(": ");
207 | DeprecatedMessage += Class->HasMetaData(MetaDeprecatedMessage) ? Class->GetMetaData(MetaDeprecatedMessage) : DefDeprecatedMessage;
208 | }
209 |
210 | return DeprecatedMessage;
211 | }
212 |
213 | bool FYetAnotherNodeClassHelper::IsClassKnown(const FYetAnotherNodeClassData& ClassData)
214 | {
215 | return !ClassData.IsBlueprint() || !UnknownPackages.Contains(*ClassData.GetPackageName());
216 | }
217 |
218 | void FYetAnotherNodeClassHelper::AddUnknownClass(const FYetAnotherNodeClassData& ClassData)
219 | {
220 | if (ClassData.IsBlueprint())
221 | {
222 | UnknownPackages.AddUnique(*ClassData.GetPackageName());
223 | }
224 | }
225 |
226 | bool FYetAnotherNodeClassHelper::IsHidingParentClass(UClass* Class)
227 | {
228 | static FName MetaHideParent = TEXT("HideParentNode");
229 | return Class && Class->HasAnyClassFlags(CLASS_Native) && Class->HasMetaData(MetaHideParent);
230 | }
231 |
232 | bool FYetAnotherNodeClassHelper::IsHidingClass(UClass* Class)
233 | {
234 | static FName MetaHideInEditor = TEXT("HiddenNode");
235 | return Class && Class->HasAnyClassFlags(CLASS_Native) && Class->HasMetaData(MetaHideInEditor);
236 | }
237 |
238 | bool FYetAnotherNodeClassHelper::IsPackageSaved(FName PackageName)
239 | {
240 | const bool bFound = FPackageName::SearchForPackageOnDisk(PackageName.ToString());
241 | return bFound;
242 | }
243 |
244 | void FYetAnotherNodeClassHelper::OnAssetAdded(const struct FAssetData& AssetData)
245 | {
246 | TSharedPtr Node = CreateClassDataNode(AssetData);
247 |
248 | TSharedPtr ParentNode;
249 | if (Node.IsValid())
250 | {
251 | ParentNode = FindBaseClassNode(RootNode, Node->ParentClassName);
252 |
253 | if (!IsPackageSaved(AssetData.PackageName))
254 | {
255 | UnknownPackages.AddUnique(AssetData.PackageName);
256 | }
257 | else
258 | {
259 | const int32 PrevListCount = UnknownPackages.Num();
260 | UnknownPackages.RemoveSingleSwap(AssetData.PackageName);
261 |
262 | if (UnknownPackages.Num() != PrevListCount)
263 | {
264 | OnPackageListUpdated.Broadcast();
265 | }
266 | }
267 | }
268 |
269 | if (ParentNode.IsValid())
270 | {
271 | ParentNode->AddUniqueSubNode(Node);
272 | Node->ParentNode = ParentNode;
273 | }
274 |
275 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry"));
276 | if (!AssetRegistryModule.Get().IsLoadingAssets())
277 | {
278 | UpdateAvailableBlueprintClasses();
279 | }
280 | }
281 |
282 | void FYetAnotherNodeClassHelper::OnAssetRemoved(const struct FAssetData& AssetData)
283 | {
284 | FString AssetClassName;
285 | if (AssetData.GetTagValue(FBlueprintTags::GeneratedClassPath, AssetClassName))
286 | {
287 | ConstructorHelpers::StripObjectClass(AssetClassName);
288 | AssetClassName = FPackageName::ObjectPathToObjectName(*AssetClassName);
289 |
290 | TSharedPtr Node = FindBaseClassNode(RootNode, AssetClassName);
291 | if (Node.IsValid() && Node->ParentNode.IsValid())
292 | {
293 | Node->ParentNode->SubNodes.RemoveSingleSwap(Node);
294 | }
295 | }
296 |
297 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry"));
298 | if (!AssetRegistryModule.Get().IsLoadingAssets())
299 | {
300 | UpdateAvailableBlueprintClasses();
301 | }
302 | }
303 |
304 | void FYetAnotherNodeClassHelper::InvalidateCache()
305 | {
306 | RootNode.Reset();
307 | UpdateAvailableBlueprintClasses();
308 | }
309 |
310 | void FYetAnotherNodeClassHelper::OnHotReload(bool bWasTriggeredAutomatically)
311 | {
312 | InvalidateCache();
313 | }
314 |
315 | TSharedPtr FYetAnotherNodeClassHelper::CreateClassDataNode(const struct FAssetData& AssetData)
316 | {
317 | TSharedPtr Node;
318 |
319 | FString AssetClassName;
320 | FString AssetParentClassName;
321 | if (AssetData.GetTagValue(FBlueprintTags::GeneratedClassPath, AssetClassName) && AssetData.GetTagValue(FBlueprintTags::ParentClassPath, AssetParentClassName))
322 | {
323 | UObject* Outer1(NULL);
324 | ResolveName(Outer1, AssetClassName, false, false);
325 |
326 | UObject* Outer2(NULL);
327 | ResolveName(Outer2, AssetParentClassName, false, false);
328 |
329 | Node = MakeShareable(new FYetAnotherNodeClassNode);
330 | Node->ParentClassName = AssetParentClassName;
331 |
332 | UObject* AssetOb = AssetData.IsAssetLoaded() ? AssetData.GetAsset() : NULL;
333 | UBlueprint* AssetBP = Cast(AssetOb);
334 | UClass* AssetClass = AssetBP ? *AssetBP->GeneratedClass : AssetOb ? AssetOb->GetClass() : NULL;
335 |
336 | FYetAnotherNodeClassData NewData(AssetData.AssetName.ToString(), AssetData.PackageName.ToString(), AssetClassName, AssetClass);
337 | Node->Data = NewData;
338 | }
339 |
340 | return Node;
341 | }
342 |
343 | TSharedPtr FYetAnotherNodeClassHelper::FindBaseClassNode(TSharedPtr Node, const FString& ClassName)
344 | {
345 | TSharedPtr RetNode;
346 | if (Node.IsValid())
347 | {
348 | if (Node->Data.GetClassName() == ClassName)
349 | {
350 | return Node;
351 | }
352 |
353 | for (int32 i = 0; i < Node->SubNodes.Num(); i++)
354 | {
355 | RetNode = FindBaseClassNode(Node->SubNodes[i], ClassName);
356 | if (RetNode.IsValid())
357 | {
358 | break;
359 | }
360 | }
361 | }
362 |
363 | return RetNode;
364 | }
365 |
366 | void FYetAnotherNodeClassHelper::FindAllSubClasses(TSharedPtr Node, TArray& AvailableClasses)
367 | {
368 | if (Node.IsValid())
369 | {
370 | if (!Node->Data.IsAbstract() && !Node->Data.IsDeprecated() && !Node->Data.bIsHidden)
371 | {
372 | AvailableClasses.Add(Node->Data);
373 | }
374 |
375 | for (int32 i = 0; i < Node->SubNodes.Num(); i++)
376 | {
377 | FindAllSubClasses(Node->SubNodes[i], AvailableClasses);
378 | }
379 | }
380 | }
381 |
382 | UClass* FYetAnotherNodeClassHelper::FindAssetClass(const FString& GeneratedClassPackage, const FString& AssetName)
383 | {
384 | UPackage* Package = FindPackage(NULL, *GeneratedClassPackage);
385 | if (Package)
386 | {
387 | UObject* Object = FindObject(Package, *AssetName);
388 | if (Object)
389 | {
390 | UBlueprint* BlueprintOb = Cast(Object);
391 | return BlueprintOb ? *BlueprintOb->GeneratedClass : Object->GetClass();
392 | }
393 | }
394 |
395 | return NULL;
396 | }
397 |
398 | void FYetAnotherNodeClassHelper::BuildClassGraph()
399 | {
400 | TArray > NodeList;
401 | TArray HideParentList;
402 | RootNode.Reset();
403 |
404 | // gather all native classes
405 | for (TObjectIterator It; It; ++It)
406 | {
407 | UClass* TestClass = *It;
408 | if (TestClass->HasAnyClassFlags(CLASS_Native) && TestClass->IsChildOf(RootNodeClass))
409 | {
410 | TSharedPtr NewNode = MakeShareable(new FYetAnotherNodeClassNode);
411 | NewNode->ParentClassName = TestClass->GetSuperClass()->GetName();
412 |
413 | FString DeprecatedMessage = GetDeprecationMessage(TestClass);
414 | FYetAnotherNodeClassData NewData(TestClass, DeprecatedMessage);
415 |
416 | NewData.bHideParent = IsHidingParentClass(TestClass);
417 | if (NewData.bHideParent)
418 | {
419 | HideParentList.Add(TestClass->GetSuperClass());
420 | }
421 |
422 | NewData.bIsHidden = IsHidingClass(TestClass);
423 |
424 | NewNode->Data = NewData;
425 |
426 | if (TestClass == RootNodeClass)
427 | {
428 | RootNode = NewNode;
429 | }
430 |
431 | NodeList.Add(NewNode);
432 | }
433 | }
434 |
435 | // find all hidden parent classes
436 | for (int32 i = 0; i < NodeList.Num(); i++)
437 | {
438 | TSharedPtr TestNode = NodeList[i];
439 | if (HideParentList.Contains(TestNode->Data.GetClass()))
440 | {
441 | TestNode->Data.bIsHidden = true;
442 | }
443 | }
444 |
445 | // gather all blueprints
446 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked(TEXT("AssetRegistry"));
447 | TArray BlueprintList;
448 |
449 | FARFilter Filter;
450 | Filter.ClassNames.Add(UBlueprint::StaticClass()->GetFName());
451 | AssetRegistryModule.Get().GetAssets(Filter, BlueprintList);
452 |
453 | for (int32 i = 0; i < BlueprintList.Num(); i++)
454 | {
455 | TSharedPtr NewNode = CreateClassDataNode(BlueprintList[i]);
456 | NodeList.Add(NewNode);
457 | }
458 |
459 | // build class tree
460 | AddClassGraphChildren(RootNode, NodeList);
461 | }
462 |
463 | void FYetAnotherNodeClassHelper::AddClassGraphChildren(TSharedPtr Node, TArray >& NodeList)
464 | {
465 | if (!Node.IsValid())
466 | {
467 | return;
468 | }
469 |
470 | const FString NodeClassName = Node->Data.GetClassName();
471 | for (int32 i = NodeList.Num() - 1; i >= 0; i--)
472 | {
473 | if (NodeList[i]->ParentClassName == NodeClassName)
474 | {
475 | TSharedPtr MatchingNode = NodeList[i];
476 | NodeList.RemoveAt(i);
477 |
478 | MatchingNode->ParentNode = Node;
479 | Node->SubNodes.Add(MatchingNode);
480 |
481 | AddClassGraphChildren(MatchingNode, NodeList);
482 | }
483 | }
484 | }
485 |
486 | int32 FYetAnotherNodeClassHelper::GetObservedBlueprintClassCount(UClass* BaseNativeClass)
487 | {
488 | return BlueprintClassCount.FindRef(BaseNativeClass);
489 | }
490 |
491 | void FYetAnotherNodeClassHelper::AddObservedBlueprintClasses(UClass* BaseNativeClass)
492 | {
493 | BlueprintClassCount.Add(BaseNativeClass, 0);
494 | }
495 |
496 | void FYetAnotherNodeClassHelper::UpdateAvailableBlueprintClasses()
497 | {
498 | if (FModuleManager::Get().IsModuleLoaded(TEXT("AssetRegistry")))
499 | {
500 | FAssetRegistryModule& AssetRegistryModule = FModuleManager::GetModuleChecked(TEXT("AssetRegistry"));
501 | const bool bSearchSubClasses = true;
502 |
503 | TArray ClassNames;
504 | TSet DerivedClassNames;
505 |
506 | for (TMap::TIterator It(BlueprintClassCount); It; ++It)
507 | {
508 | ClassNames.Reset();
509 | ClassNames.Add(It.Key()->GetFName());
510 |
511 | DerivedClassNames.Empty(DerivedClassNames.Num());
512 | AssetRegistryModule.Get().GetDerivedClassNames(ClassNames, TSet(), DerivedClassNames);
513 |
514 | int32& Count = It.Value();
515 | Count = DerivedClassNames.Num();
516 | }
517 | }
518 | }
519 |
520 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/Utility/YetAnotherNodeClassHelper.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "UObject/ObjectMacros.h"
6 | #include "UObject/WeakObjectPtr.h"
7 | #include "YetAnotherNodeClassHelper.generated.h"
8 |
9 | /**
10 | *
11 | */
12 |
13 | USTRUCT()
14 | struct FYetAnotherNodeClassData
15 | {
16 | GENERATED_USTRUCT_BODY()
17 |
18 | FYetAnotherNodeClassData() {}
19 | FYetAnotherNodeClassData(UClass* InClass, const FString& InDeprecatedMessage);
20 | FYetAnotherNodeClassData(const FString& InAssetName, const FString& InGeneratedClassPackage, const FString& InClassName, UClass* InClass);
21 |
22 | FString ToString() const;
23 | FString GetClassName() const;
24 | FText GetCategory() const;
25 | FString GetDisplayName() const;
26 | UClass* GetClass(bool bSilent = false);
27 | bool IsAbstract() const;
28 |
29 | FORCEINLINE bool IsBlueprint() const { return AssetName.Len() > 0; }
30 | FORCEINLINE bool IsDeprecated() const { return DeprecatedMessage.Len() > 0; }
31 | FORCEINLINE FString GetDeprecatedMessage() const { return DeprecatedMessage; }
32 | FORCEINLINE FString GetPackageName() const { return GeneratedClassPackage; }
33 |
34 | /** set when child class masked this one out (e.g. always use game specific class instead of engine one) */
35 | uint32 bIsHidden : 1;
36 |
37 | /** set when class wants to hide parent class from selection (just one class up hierarchy) */
38 | uint32 bHideParent : 1;
39 |
40 | private:
41 |
42 | /** pointer to uclass */
43 | TWeakObjectPtr Class;
44 |
45 | /** path to class if it's not loaded yet */
46 | UPROPERTY()
47 | FString AssetName;
48 |
49 | UPROPERTY()
50 | FString GeneratedClassPackage;
51 |
52 | /** resolved name of class from asset data */
53 | UPROPERTY()
54 | FString ClassName;
55 |
56 | /** User-defined category for this class */
57 | UPROPERTY()
58 | FText Category;
59 |
60 | /** message for deprecated class */
61 | FString DeprecatedMessage;
62 | };
63 |
64 | struct FYetAnotherNodeClassNode
65 | {
66 | FYetAnotherNodeClassData Data;
67 | FString ParentClassName;
68 |
69 | TSharedPtr ParentNode;
70 | TArray > SubNodes;
71 |
72 | void AddUniqueSubNode(TSharedPtr SubNode);
73 | };
74 |
75 | struct FYetAnotherNodeClassHelper
76 | {
77 | public:
78 | DECLARE_MULTICAST_DELEGATE(FOnPackageListUpdated);
79 |
80 | FYetAnotherNodeClassHelper(UClass* InRootClass);
81 | ~FYetAnotherNodeClassHelper();
82 |
83 | void GatherClasses(const UClass* BaseClass, TArray& AvailableClasses);
84 | static FString GetDeprecationMessage(const UClass* Class);
85 |
86 | void OnAssetAdded(const struct FAssetData& AssetData);
87 | void OnAssetRemoved(const struct FAssetData& AssetData);
88 | void InvalidateCache();
89 | void OnHotReload(bool bWasTriggeredAutomatically);
90 |
91 | static void AddUnknownClass(const FYetAnotherNodeClassData& ClassData);
92 | static bool IsClassKnown(const FYetAnotherNodeClassData& ClassData);
93 | static FOnPackageListUpdated OnPackageListUpdated;
94 |
95 | static int32 GetObservedBlueprintClassCount(UClass* BaseNativeClass);
96 | static void AddObservedBlueprintClasses(UClass* BaseNativeClass);
97 | void UpdateAvailableBlueprintClasses();
98 |
99 | private:
100 |
101 | UClass* RootNodeClass;
102 | TSharedPtr RootNode;
103 | static TArray UnknownPackages;
104 | static TMap BlueprintClassCount;
105 |
106 | TSharedPtr CreateClassDataNode(const struct FAssetData& AssetData);
107 | TSharedPtr FindBaseClassNode(TSharedPtr Node, const FString& ClassName);
108 | void FindAllSubClasses(TSharedPtr Node, TArray& AvailableClasses);
109 |
110 | UClass* FindAssetClass(const FString& GeneratedClassPackage, const FString& AssetName);
111 | void BuildClassGraph();
112 | void AddClassGraphChildren(TSharedPtr Node, TArray >& NodeList);
113 |
114 | bool IsHidingClass(UClass* Class);
115 | bool IsHidingParentClass(UClass* Class);
116 | bool IsPackageSaved(FName PackageName);
117 | };
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Private/YetAnotherGraphEditor.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YetAnotherGraphEditor.h"
3 | #include "ModuleManager.h"
4 | #include "IAssetTools.h"
5 | #include "AssetToolsModule.h"
6 | #include "YetOtherAssetTypeActions.h"
7 | #include "EditorLogger.h"
8 | #include "YetAnotherNodeClassHelper.h"
9 | #include "YANode.h"
10 | #include "SimpleNode.h"
11 |
12 |
13 | #define LOCTEXT_NAMESPACE "FYetAnotherGraphEditorModule"
14 |
15 | void FYetAnotherGraphEditorModule::StartupModule()
16 | {
17 |
18 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
19 | IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get();
20 | TSharedRef Actions = MakeShareable(new FYetOtherAssetTypeActions());
21 | AssetTools.RegisterAssetTypeActions(Actions);
22 |
23 | EDLLog("Module loaded");
24 |
25 | }
26 |
27 | void FYetAnotherGraphEditorModule::ShutdownModule()
28 | {
29 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
30 | // we call this function before unloading the module.
31 | EDLLog("Module unloaded");
32 | NodeHelper.Reset();
33 | }
34 |
35 | void FYetAnotherGraphEditorModule::StartNodeHelper()
36 | {
37 | if (!NodeHelper.IsValid())
38 | {
39 | NodeHelper = MakeShareable(new FYetAnotherNodeClassHelper(UYANode::StaticClass()));
40 | FYetAnotherNodeClassHelper::AddObservedBlueprintClasses(USimpleNode::StaticClass());
41 | }
42 | }
43 |
44 | #undef LOCTEXT_NAMESPACE
45 |
46 | IMPLEMENT_MODULE(FYetAnotherGraphEditorModule, YetAnotherGraphPlugin)
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/Public/YetAnotherGraphEditor.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "Modules/ModuleManager.h"
6 |
7 | class FYetAnotherGraphEditorModule : public IModuleInterface
8 | {
9 | public:
10 |
11 | /** IModuleInterface implementation */
12 | virtual void StartupModule() override;
13 | virtual void ShutdownModule() override;
14 |
15 | virtual void StartNodeHelper();
16 | virtual TSharedPtr GetHelper() { return NodeHelper; }
17 |
18 | private:
19 | TSharedPtrNodeHelper;
20 | };
21 |
--------------------------------------------------------------------------------
/Source/YetAnotherGraphEditor/YetAnotherGraphEditor.Build.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | using UnrealBuildTool;
3 |
4 | public class YetAnotherGraphEditor : ModuleRules
5 | {
6 | public YetAnotherGraphEditor(ReadOnlyTargetRules Target) : base(Target)
7 | {
8 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
9 |
10 | PublicIncludePaths.AddRange(
11 | new string[] {
12 | // ... add public include paths required here ...
13 | }
14 | );
15 |
16 |
17 | PrivateIncludePaths.AddRange(
18 | new string[] {
19 | // ... add other private include paths required here ...
20 | "YetAnotherGraphEditor/Private",
21 | "YetAnotherGraphEditor/Private/Utility",
22 | "YetAnotherGraphEditor/Private/Toolkits",
23 | "YetAnotherGraphEditor/Private/AssetTypeActions",
24 | "YetAnotherGraphEditor/Private/EditorGraph",
25 | "YetAnotherGraphEditor/Private/Factories",
26 | "YetAnotherGraphEditor/Private/EditorGraph/SchemaActions",
27 | "YetAnotherGraphEditor/Private/EditorGraph/EditorNodes",
28 | "YetAnotherGraphEditor/Private/EditorGraph/SlateWidgets",
29 |
30 | }
31 | );
32 |
33 |
34 | PublicDependencyModuleNames.AddRange(
35 | new string[]
36 | {
37 | "Core",
38 | // ... add other public dependencies that you statically link with here ...
39 | }
40 | );
41 |
42 |
43 | PrivateDependencyModuleNames.AddRange(
44 | new string[]
45 | {
46 | "YetOtherGraphAssets",
47 | "CoreUObject",
48 | "Engine",
49 | "Slate",
50 | "SlateCore",
51 | "EditorStyle",
52 | "UnrealEd",
53 | "AssetTools",
54 | "GraphEditor",
55 | "ApplicationCore",
56 | // ... add private dependencies that you statically link with here ...
57 | }
58 | );
59 |
60 |
61 | DynamicallyLoadedModuleNames.AddRange(
62 | new string[]
63 | {
64 | // ... add any modules that your module loads dynamically here ...
65 | }
66 | );
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Graphs/YAGraph.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YAGraph.h"
3 | #include "YANode.h"
4 | #include "StartNode.h"
5 | #include "Components/ActorComponent.h"
6 | #include "GameFramework/Actor.h"
7 |
8 | #define LOCTEXT_NAMESPACE "UYAGraph"
9 |
10 | UYAGraph::UYAGraph()
11 | {
12 |
13 | #if WITH_EDITORONLY_DATA
14 | EdGraph = nullptr;
15 | #endif
16 |
17 | }
18 |
19 | TArray UYAGraph::GetStartingNodes()
20 | {
21 | TArrayNodesArray;
22 | for (UYANode* Node:Nodes)
23 | {
24 | if (UStartNode* StartNode = Cast(Node))
25 | NodesArray.Add(StartNode);
26 | }
27 | return NodesArray;
28 | }
29 |
30 | void UYAGraph::InitGraph(UObject * ParentObject)
31 | {
32 | Owner = ParentObject;
33 | //it seems that a Rename after the asset has already been assigned in a variable prevents referencing it properly on runtime
34 | //Rename(nullptr, ParentObject);
35 | }
36 |
37 |
38 | #if WITH_ENGINE
39 |
40 | UWorld * UYAGraph::GetWorld() const
41 | {
42 | if (Owner->IsA(UActorComponent::StaticClass()) || Owner->IsA(AActor::StaticClass()))
43 | {
44 | return Owner->GetWorld();
45 | }
46 |
47 | ELog("It hasn't been possible to retrieve the world context from %s for %s", *Owner->GetFullName(), *GetFullName());
48 | return nullptr;
49 |
50 | }
51 |
52 | #endif
53 |
54 | #if WITH_EDITORONLY_DATA
55 | void UYAGraph::AddNode(UYANode * InNode)
56 | {
57 | InNode->SetGraph(this);
58 | InNode->Rename(nullptr, this);
59 | int32 Index = Nodes.Add(InNode);
60 | LLog("Spawned node at index %d", Index);
61 | }
62 |
63 | void UYAGraph::RemoveNode(UYANode * NodeToRemove)
64 | {
65 | for (UYANode* Node : Nodes)
66 | {
67 | Node->RemoveLinkedNode(NodeToRemove);
68 | }
69 |
70 | int32 Removed=Nodes.Remove(NodeToRemove);
71 |
72 | if (Removed > 0)
73 | {
74 | LLog("Node Removed.");
75 | }
76 | else
77 | {
78 | ELog("The node is not present inside the graph.");
79 | }
80 | }
81 | #endif
82 |
83 | #undef LOCTEXT_NAMESPACE
84 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/ActionNodes/ActionNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "ActionNode.h"
4 | #include "Logger.h"
5 | #include "Array.h"
6 |
7 | #define LOCTEXT_NAMESPACE "ActionNode"
8 |
9 | UActionNode::UActionNode()
10 | {
11 | DefaultNodeTitle= LOCTEXT("ActionNode", "Action Node");
12 | }
13 |
14 | UYANode * UActionNode::GetNodePointer_Implementation()
15 | {
16 | if (ChildNodes.Num() <= 1)
17 | {
18 | ActionToPerform(Graph->Owner);
19 | return (ChildNodes.IsValidIndex(0)) ? ChildNodes[0]->GetNodePointer() : nullptr;
20 | }
21 | else
22 | {
23 | ELog("There should be at most one subnode on an ActionNode");
24 | return nullptr;
25 | }
26 | }
27 |
28 | #undef LOCTEXT_NAMESPACE
29 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/ActionNodes/Implementations/StoreBoolean.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "StoreBoolean.h"
4 | #include "YetAnotherGraphInterface.h"
5 | #include "GraphSupportComponent.h"
6 | #include "GraphSupportComponentInterface.h"
7 |
8 | #define LOCTEXT_NAMESPACE "StoreBoolean"
9 |
10 | UStoreBoolean::UStoreBoolean()
11 | {
12 | DefaultNodeTitle= LOCTEXT("StoreBoolean", "Store Boolean");
13 | }
14 | void UStoreBoolean::ActionToPerform_Implementation(UObject * GraphOwner)
15 | {
16 |
17 | if (Name.IsValid())
18 | {
19 |
20 | UObject* Support = nullptr;
21 |
22 | if (GraphOwner->GetClass()->ImplementsInterface(UGraphSupportComponentInterface::StaticClass()))
23 | {
24 | IGraphSupportComponentInterface* Interface = Cast(GraphOwner);
25 | Support = Interface->Execute_GetGraphSupportComponent(GraphOwner);
26 | }
27 | else
28 | {
29 |
30 | if (GraphOwner->GetClass()->ImplementsInterface(UYetAnotherGraphInterface::StaticClass()))
31 | Support = GraphOwner;
32 |
33 | }
34 |
35 | if (Support!=nullptr)
36 | {
37 | IYetAnotherGraphInterface* Interface = Cast(Support);
38 | if (Interface)
39 | Interface->Execute_SetBooleanVariable(Support, Name, true);
40 | }
41 | else
42 | ELog("No graph interfaces has been found.");
43 |
44 | }
45 | else
46 | {
47 | ELog("The variable name isn't valid.");
48 | }
49 | }
50 |
51 | #undef LOCTEXT_NAMESPACE
52 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/ActionNodes/Implementations/StoreInteger.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "StoreInteger.h"
4 | #include "YetAnotherGraphInterface.h"
5 | #include "GraphSupportComponent.h"
6 | #include "GraphSupportComponentInterface.h"
7 |
8 | #define LOCTEXT_NAMESPACE "StoreInteger"
9 |
10 | UStoreInteger::UStoreInteger()
11 | {
12 | DefaultNodeTitle= LOCTEXT("StoreInteger", "Store Integer");
13 | }
14 | void UStoreInteger::ActionToPerform_Implementation(UObject * GraphOwner)
15 | {
16 | if (Name.IsValid())
17 | {
18 | UObject* Support = nullptr;
19 |
20 | if (GraphOwner->GetClass()->ImplementsInterface(UGraphSupportComponentInterface::StaticClass()))
21 | {
22 | IGraphSupportComponentInterface* Interface = Cast(GraphOwner);
23 | Support = Interface->Execute_GetGraphSupportComponent(GraphOwner);
24 | }
25 | else
26 | if (GraphOwner->GetClass()->ImplementsInterface(UYetAnotherGraphInterface::StaticClass()))
27 | Support = GraphOwner;
28 |
29 | if (Support != nullptr)
30 | {
31 | IYetAnotherGraphInterface* Interface = Cast(Support);
32 | if (Interface)
33 | Interface->Execute_SetIntegerVariable(Support, Name, Value);
34 | }
35 | else
36 | ELog("No graph interfaces has been found.");
37 | }
38 | else
39 | {
40 | ELog("The variable name isn't valid.");
41 | }
42 | }
43 |
44 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/EmptyNodes/SimpleNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "SimpleNode.h"
3 |
4 | #define LOCTEXT_NAMESPACE "SimpleNode"
5 |
6 | USimpleNode::USimpleNode()
7 | {
8 | DefaultNodeTitle = LOCTEXT("Simple Node Title", "Simple Node");
9 | }
10 |
11 |
12 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/EmptyNodes/StartNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "StartNode.h"
3 |
4 | #define LOCTEXT_NAMESPACE "StartNode"
5 |
6 | UStartNode::UStartNode()
7 | {
8 | bHasInputPins = false;
9 | DefaultNodeTitle = LOCTEXT("Start Node Title", "Start");
10 | }
11 |
12 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/FlowControlNodes/BinarySelectNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "BinarySelectNode.h"
3 | #include "Logger.h"
4 | #include "YAGraph.h"
5 |
6 | #define LOCTEXT_NAMESPACE "BinarySelectNode"
7 |
8 | UBinarySelectNode::UBinarySelectNode()
9 | {
10 | DefaultNodeTitle = LOCTEXT("BinarySelectNode", "Binary Select");
11 | }
12 |
13 |
14 |
15 | UYANode * UBinarySelectNode::GetNodePointer_Implementation()
16 | {
17 | if (ChildNodes.Num() == 1) return BooleanEvaluation(Graph->Owner) ? ChildNodes[0]->GetNodePointer() : nullptr;
18 | if (ChildNodes.Num() == 2) return BooleanEvaluation(Graph->Owner) ? ChildNodes[0]->GetNodePointer() : ChildNodes[1]->GetNodePointer();
19 | ELog("There are %d subnode on a binary select node.", ChildNodes.Num());
20 | return nullptr;
21 | }
22 |
23 |
24 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/FlowControlNodes/FlowControlNode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #include "FlowControlNode.h"
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/FlowControlNodes/Implementations/BooleanSelector.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "BooleanSelector.h"
4 | #include "YAGraph.h"
5 | #include "YetAnotherGraphInterface.h"
6 | #include "Logger.h"
7 | #include "GraphSupportComponent.h"
8 | #include "GraphSupportComponentInterface.h"
9 |
10 | #define LOCTEXT_NAMESPACE "BooleanSelector"
11 |
12 | UBooleanSelector::UBooleanSelector()
13 | {
14 | DefaultNodeTitle = LOCTEXT("BooleanSelector", "Boolean Selector");
15 | }
16 |
17 | bool UBooleanSelector::BooleanEvaluation_Implementation(UObject* GraphOwner)
18 | {
19 | bool Result = false;
20 | UObject* Support = nullptr;
21 |
22 | if (GraphOwner->GetClass()->ImplementsInterface(UGraphSupportComponentInterface::StaticClass()))
23 | {
24 | IGraphSupportComponentInterface* Interface = Cast(GraphOwner);
25 | Support = Interface->Execute_GetGraphSupportComponent(GraphOwner);
26 | }
27 | else
28 | if (GraphOwner->GetClass()->ImplementsInterface(UYetAnotherGraphInterface::StaticClass()))
29 | Support = GraphOwner;
30 |
31 | if (Support != nullptr)
32 | {
33 | IYetAnotherGraphInterface* Interface = Cast(Support);
34 | if (Interface)
35 | Result = Interface->Execute_GetBooleanVariable(Support, Name);
36 | }
37 | else
38 | ELog("No graph interfaces has been found.");
39 |
40 |
41 | return Result;
42 | }
43 |
44 | #undef LOCTEXT_NAMESPACE
45 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/FlowControlNodes/Implementations/NthSelector.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "NthSelector.h"
4 | #include "YAGraph.h"
5 | #include "Logger.h"
6 | #include "YetAnotherGraphInterface.h"
7 | #include "GraphSupportComponent.h"
8 | #include "GraphSupportComponentInterface.h"
9 |
10 | #define LOCTEXT_NAMESPACE "NthSelector"
11 |
12 | UNthSelector::UNthSelector()
13 | {
14 | DefaultNodeTitle= LOCTEXT("NthSelector", "'Nth Selector");
15 | }
16 |
17 | int32 UNthSelector::IndexEvaluation_Implementation(UObject* GraphOwner)
18 | {
19 | int32 Integer = 0;
20 | bool Result = false;
21 | UObject* Support=nullptr;
22 |
23 | if (GraphOwner->GetClass()->ImplementsInterface(UGraphSupportComponentInterface::StaticClass()))
24 | {
25 | IGraphSupportComponentInterface* Interface = Cast(GraphOwner);
26 | Support = Interface->Execute_GetGraphSupportComponent(GraphOwner);
27 | }
28 | else
29 | if (GraphOwner->GetClass()->ImplementsInterface(UYetAnotherGraphInterface::StaticClass()))
30 | Support = GraphOwner;
31 |
32 | if (Support != nullptr)
33 | {
34 | IYetAnotherGraphInterface* Interface = Cast(Support);
35 | if (Interface)
36 | Integer = Interface->Execute_GetIntegerVariable(Support, IndexName, Result);
37 | }
38 | else
39 | ELog("No graph interfaces has been found.");
40 |
41 | if (!Result)
42 | ELog("%s:Error upon looking for an integer", *GraphOwner->GetClass()->GetDisplayNameText().ToString());
43 |
44 |
45 | return Integer;
46 | }
47 |
48 | #undef LOCTEXT_NAMESPACE
49 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/FlowControlNodes/MultiNodeSelector.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "MultiNodeSelector.h"
3 | #include "Logger.h"
4 |
5 | #define LOCTEXT_NAMESPACE "MultiNodeSelector"
6 |
7 | UYANode * UMultiNodeSelector::GetNodePointer_Implementation()
8 | {
9 | int32 Index = IndexEvaluation(Graph->Owner);
10 | if ((ChildNodes.Num() == 0) || Index >= ChildNodes.Num())
11 | {
12 | ELog("There are %d nodes linked to a '%s' node and the index evaluated is &d.", ChildNodes.Num(), *StaticClass()->GetDisplayNameText().ToString(), Index);
13 | return nullptr;
14 | }
15 | return (ChildNodes.IsValidIndex(Index)) ? ChildNodes[Index]->GetNodePointer() : nullptr;
16 | }
17 |
18 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Nodes/YANode.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "YANode.h"
3 | #include "YAGraph.h"
4 | #include "Components/ActorComponent.h"
5 | #include "GameFramework/Actor.h"
6 |
7 | #define LOCTEXT_NAMESPACE "YANode"
8 |
9 | UYANode::UYANode()
10 | {
11 | DefaultNodeTitle = LOCTEXT("Node Title", "Node");
12 | }
13 |
14 | UYANode * UYANode::GetNodePointer_Implementation()
15 | {
16 | return this;
17 | }
18 |
19 | void UYANode::SetGraph(UYAGraph * InGraph)
20 | {
21 | Graph = InGraph;
22 | }
23 |
24 | UYAGraph * UYANode::GetGraph()
25 | {
26 | return Graph;
27 | }
28 |
29 | FText UYANode::GetNodeTitle_Implementation()
30 | {
31 | return DefaultNodeTitle.IsEmpty() ? LOCTEXT("Node Title", "Node") : DefaultNodeTitle;
32 | }
33 |
34 | TArray UYANode::GetChildren()
35 | {
36 | TArrayReturnArray;
37 | for (UYANode* Node : ChildNodes)
38 | {
39 | auto* object = Node->GetNodePointer();
40 | if(object)ReturnArray.Add(object);
41 | }
42 | return ReturnArray;
43 | }
44 |
45 | TArray UYANode::GetParents()
46 | {
47 | return ParentNodes;
48 | }
49 |
50 | bool UYANode::HasInputPins_Implementation()
51 | {
52 | return bHasInputPins;
53 | }
54 |
55 | bool UYANode::HasOutputPins_Implementation()
56 | {
57 | return bHasOutputPins;
58 | }
59 |
60 | void UYANode::AddToChildren(UYANode * NewSubNode)
61 | {
62 | ChildNodes.Add(NewSubNode);
63 | }
64 |
65 | void UYANode::AddToParent(UYANode * NewParentNode)
66 | {
67 | ParentNodes.Add(NewParentNode);
68 | }
69 |
70 | bool UYANode::HasParentNodes()
71 | {
72 | return ParentNodes.Num() > 0;
73 | }
74 |
75 | void UYANode::LinkArgumentNodeAsChild(UYANode * Child)
76 | {
77 | AddToChildren(Child);
78 | Child->AddToParent(this);
79 | }
80 |
81 | void UYANode::ClearLinks()
82 | {
83 | ParentNodes.Empty();
84 | ChildNodes.Empty();
85 | }
86 |
87 | bool UYANode::RemoveLinkedNode(UYANode * NodeToRemove)
88 | {
89 | return RemoveNodeFromParents(NodeToRemove) || RemoveNodeFromChilds(NodeToRemove);
90 | }
91 |
92 | bool UYANode::RemoveNodeFromParents(UYANode * NodeToRemove)
93 | {
94 | return ParentNodes.Remove(NodeToRemove);
95 | }
96 |
97 | bool UYANode::RemoveNodeFromChilds(UYANode * NodeToRemove)
98 | {
99 | return ChildNodes.Remove(NodeToRemove);
100 | }
101 |
102 | #if WITH_ENGINE
103 |
104 | UWorld * UYANode::GetWorld() const
105 | {
106 | return (Graph) ? Graph->GetWorld() : nullptr;
107 | }
108 |
109 | #endif
110 |
111 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Utility/GraphSupportComponent.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "GraphSupportComponent.h"
4 | #include "Logger.h"
5 | #include "Map.h"
6 |
7 |
8 | // Sets default values for this component's properties
9 | UGraphSupportComponent::UGraphSupportComponent()
10 | {
11 | // Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
12 | // off to improve performance if you don't need them.
13 | PrimaryComponentTick.bCanEverTick = false;
14 | Owner = Cast(GetOuter());
15 |
16 | // ...
17 | }
18 |
19 |
20 |
21 | // Called when the game starts
22 | void UGraphSupportComponent::BeginPlay()
23 | {
24 | Super::BeginPlay();
25 |
26 | // ...
27 |
28 | }
29 |
30 |
31 | // Called every frame
32 | void UGraphSupportComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
33 | {
34 | Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
35 |
36 | // ...
37 | }
38 |
39 | bool UGraphSupportComponent::SetBooleanVariable_Implementation(FName BooleanName, bool Value)
40 | {
41 | NamedBooleans.Add(BooleanName, Value);
42 | return false;
43 | }
44 |
45 | bool UGraphSupportComponent::GetBooleanVariable_Implementation(FName BooleanName) const
46 | {
47 | return NamedBooleans.Find(BooleanName);
48 | }
49 |
50 | bool UGraphSupportComponent::SetIntegerVariable_Implementation(FName IntegerName, int32 Value)
51 | {
52 | NamedIntegers.Add(IntegerName, Value);
53 | return false;
54 | }
55 |
56 | int32 UGraphSupportComponent::GetIntegerVariable_Implementation(FName IntegerName, bool& Result) const
57 | {
58 | Result = NamedIntegers.Contains(IntegerName);
59 | return NamedIntegers.Contains(IntegerName)?*NamedIntegers.Find(IntegerName):0;
60 | }
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Utility/GraphSupportComponentInterface.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "GraphSupportComponentInterface.h"
4 |
5 |
6 | // Add default functionality here for any IGraphSupportComponentInterface functions that are not pure virtual.
7 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Utility/Logger.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #include "Logger.h"
3 | DEFINE_LOG_CATEGORY(LogYetOtherGraphAssets);
4 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/Utility/YetAnotherGraphInterface.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #include "YetAnotherGraphInterface.h"
4 |
5 |
6 | // Add default functionality here for any IYetAnotherGraphInterface functions that are not pure virtual.
7 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Private/YetOtherGraphAssets.cpp:
--------------------------------------------------------------------------------
1 | #include "YetOtherGraphAssets.h"
2 | #include "Logger.h"
3 |
4 | #define LOCTEXT_NAMESPACE "FYetOtherGraphAssetsModule"
5 |
6 | void FYetOtherGraphAssetsModule::StartupModule()
7 | {
8 | // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
9 | LLog("Module loaded.");
10 | }
11 |
12 | void FYetOtherGraphAssetsModule::ShutdownModule()
13 | {
14 | // This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
15 | // we call this function before unloading the module.
16 | LLog("Module unloaded.");
17 | }
18 |
19 | #undef LOCTEXT_NAMESPACE
20 |
21 | IMPLEMENT_MODULE(FYetOtherGraphAssetsModule, YetAnotherGraphPlugin)
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Graphs/YAGraph.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "UObject/NoExportTypes.h"
6 | #include "SubclassOf.h"
7 | #include "Logger.h"
8 | #include "YAGraph.generated.h"
9 |
10 | #define LOCTEXT_NAMESPACE "UYAGraph"
11 |
12 | class UYANode;
13 | class UStartNode;
14 |
15 | /**
16 | *
17 | */
18 | UCLASS(Blueprintable,BlueprintType)
19 | class YETOTHERGRAPHASSETS_API UYAGraph : public UObject
20 | {
21 | GENERATED_BODY()
22 |
23 | public:
24 | UYAGraph();
25 |
26 | UPROPERTY(BlueprintReadOnly, Category = "Graph Data")
27 | TArrayNodes;
28 |
29 | UPROPERTY(BlueprintReadOnly, Category = "Graph Data")
30 | TMapNamedNodes;
31 |
32 | UPROPERTY(BlueprintReadOnly, Category = "Graph Data")
33 | TMapNodesNames;
34 |
35 | UPROPERTY(BlueprintReadWrite, Category = "Graph Data")
36 | UObject* Owner;
37 |
38 | UFUNCTION(BlueprintPure, Category = "Graph Data")
39 | TArray GetStartingNodes();
40 |
41 | UFUNCTION(BlueprintCallable, Category = "Graph Data")
42 | void InitGraph(UObject* ParentObject);
43 |
44 |
45 | #if WITH_ENGINE
46 | //we need this because otherwise during visual scripting with blueprints we can't use anything from WorldContextObject like "get game mode" or "get player controller"
47 | virtual class UWorld* GetWorld() const override;
48 | #endif
49 |
50 |
51 | #if WITH_EDITORONLY_DATA
52 |
53 | public:
54 |
55 | UPROPERTY()
56 | class UEdGraph* EdGraph;
57 |
58 | template
59 | T* SpawnNodeInsideGraph(TSubclassOf InNodeClass)
60 | {
61 | T* SpawenNode = NewObject(this, InNodeClass, NAME_None, RF_Transactional);
62 | AddNode(SpawenNode);
63 | return SpawenNode;
64 | }
65 |
66 |
67 | virtual void AddNode(UYANode* InNode);
68 | virtual void RemoveNode(UYANode* NodeToRemove);
69 |
70 | #endif
71 | };
72 |
73 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/ActionNodes/ActionNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "SimpleNode.h"
7 | #include "YAGraph.h"
8 | #include "ActionNode.generated.h"
9 |
10 | /**
11 | *
12 | */
13 | UCLASS(Abstract)
14 | class YETOTHERGRAPHASSETS_API UActionNode : public USimpleNode
15 | {
16 | GENERATED_BODY()
17 |
18 | public:
19 | UActionNode();
20 |
21 | UFUNCTION(BlueprintNativeEvent, Category = "Action Node")
22 | void ActionToPerform(UObject* GraphOwner);
23 | virtual void ActionToPerform_Implementation(UObject* GraphOwner) {}
24 |
25 | //Inherited from UYANode
26 | UYANode* GetNodePointer_Implementation() override;
27 | };
28 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/ActionNodes/Implementations/StoreBoolean.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "ActionNode.h"
7 | #include "StoreBoolean.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS(meta = (Category = "ActionNodes"))
13 | class YETOTHERGRAPHASSETS_API UStoreBoolean : public UActionNode
14 | {
15 | GENERATED_BODY()
16 |
17 | public:
18 | UStoreBoolean();
19 |
20 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Informations")
21 | FName Name;
22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Informations")
23 | bool Value;
24 |
25 | //Inherited from UActionNode
26 | void ActionToPerform_Implementation(UObject* GraphOwner) override;
27 |
28 | };
29 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/ActionNodes/Implementations/StoreInteger.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "ActionNode.h"
7 | #include "StoreInteger.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS(meta = (Category = "ActionNodes"))
13 | class YETOTHERGRAPHASSETS_API UStoreInteger : public UActionNode
14 | {
15 | GENERATED_BODY()
16 |
17 | public:
18 | UStoreInteger();
19 |
20 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Informations")
21 | FName Name;
22 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Informations")
23 | int32 Value;
24 |
25 | //Inherited from UActionNode
26 | void ActionToPerform_Implementation(UObject* GraphOwner) override;
27 |
28 | };
29 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/EmptyNodes/SimpleNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 |
4 | #pragma once
5 |
6 | #include "CoreMinimal.h"
7 | #include "YANode.h"
8 | #include "SimpleNode.generated.h"
9 |
10 | /**
11 | * Base node, used for storing information or change the topography of the graph
12 | */
13 | UCLASS(meta = (Category = "EmptyNodes"))
14 | class YETOTHERGRAPHASSETS_API USimpleNode : public UYANode
15 | {
16 | GENERATED_BODY()
17 |
18 | public:
19 | USimpleNode();
20 |
21 |
22 |
23 | };
24 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/EmptyNodes/StartNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "SimpleNode.h"
7 | #include "StartNode.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS(meta = (Category = "EmptyNodes"))
13 | class YETOTHERGRAPHASSETS_API UStartNode : public USimpleNode
14 | {
15 | GENERATED_BODY()
16 | public:
17 | UStartNode();
18 |
19 |
20 |
21 | };
22 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/FlowControlNodes/BinarySelectNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "FlowControlNode.h"
6 | #include "BinarySelectNode.generated.h"
7 |
8 | /**
9 | *
10 | */
11 | UCLASS(Abstract)
12 | class YETOTHERGRAPHASSETS_API UBinarySelectNode : public UFlowControlNode
13 | {
14 | GENERATED_BODY()
15 |
16 | public:
17 | UBinarySelectNode();
18 |
19 | UFUNCTION(BlueprintNativeEvent, Category = "Binary Selector")
20 | bool BooleanEvaluation(UObject* GraphOwner);
21 | virtual bool BooleanEvaluation_Implementation(UObject* GraphOwner) { return false; }
22 |
23 |
24 | //inherited from YANode
25 | UYANode* GetNodePointer_Implementation() override;
26 |
27 | protected:
28 | UPROPERTY()
29 | int32 MaxNumberOfSubNodes = 2;
30 |
31 | };
32 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/FlowControlNodes/FlowControlNode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "YANode.h"
6 | #include "FlowControlNode.generated.h"
7 |
8 | /**
9 | * Base abstract class for every node that return a different node when called depending on runtime evalutation.
10 | * Its subnodes are saved in order from left to right.
11 | */
12 | UCLASS(Abstract)
13 | class YETOTHERGRAPHASSETS_API UFlowControlNode : public UYANode
14 | {
15 | GENERATED_BODY()
16 |
17 | };
18 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/FlowControlNodes/Implementations/BooleanSelector.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "BinarySelectNode.h"
7 | #include "BooleanSelector.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS(meta = (Category = "FlowControl"))
13 | class YETOTHERGRAPHASSETS_API UBooleanSelector : public UBinarySelectNode
14 | {
15 | GENERATED_BODY()
16 |
17 | public:
18 |
19 | UBooleanSelector();
20 |
21 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Boolean Selector")
22 | FName Name;
23 |
24 | //Inherited from BinarySelectNode
25 | bool BooleanEvaluation_Implementation(UObject* GraphOwner) override;
26 |
27 | };
28 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/FlowControlNodes/Implementations/NthSelector.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "MultiNodeSelector.h"
7 | #include "NthSelector.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS(meta = (Category = "FlowControl"))
13 | class YETOTHERGRAPHASSETS_API UNthSelector : public UMultiNodeSelector
14 | {
15 | GENERATED_BODY()
16 |
17 | public:
18 |
19 | UNthSelector();
20 |
21 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Nth Selector")
22 | FName IndexName;
23 |
24 | //Inherited from UMultiNodeSelector
25 | int32 IndexEvaluation_Implementation(UObject* GraphOwner) override;
26 |
27 | };
28 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/FlowControlNodes/MultiNodeSelector.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "FlowControlNode.h"
6 | #include "YAGraph.h"
7 | #include "MultiNodeSelector.generated.h"
8 |
9 | #define LOCTEXT_NAMESPACE "MultiNodeSelector"
10 |
11 | /**
12 | *
13 | */
14 | UCLASS(Abstract)
15 | class YETOTHERGRAPHASSETS_API UMultiNodeSelector : public UFlowControlNode
16 | {
17 | GENERATED_BODY()
18 |
19 | public:
20 |
21 | UFUNCTION(BlueprintNativeEvent, Category = "Multi Node Selector")
22 | int32 IndexEvaluation(UObject* GraphOwner);
23 | virtual int32 IndexEvaluation_Implementation(UObject* GraphOwner) { return 0; }
24 |
25 |
26 | //inherited from YANode
27 | UYANode* GetNodePointer_Implementation() override;
28 |
29 |
30 | };
31 |
32 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Nodes/YANode.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "UObject/NoExportTypes.h"
6 | #include "YANode.generated.h"
7 |
8 | #define LOCTEXT_NAMESPACE "UYANode"
9 |
10 | class UYAGraph;
11 | /**
12 | * Base abstract class for every node of the graph.
13 | */
14 | UCLASS(Abstract, Blueprintable, BlueprintType)
15 | class YETOTHERGRAPHASSETS_API UYANode : public UObject
16 | {
17 | GENERATED_BODY()
18 |
19 | public:
20 | UYANode();
21 |
22 |
23 | UFUNCTION(BlueprintPure, Category = "Node Data")
24 | TArray GetChildren();
25 |
26 | UFUNCTION(BlueprintPure, Category = "Node Data")
27 | TArray GetParents();
28 |
29 | UFUNCTION(BlueprintNativeEvent, BlueprintPure, Category = "Node Data")
30 | FText GetNodeTitle();
31 | virtual FText GetNodeTitle_Implementation();
32 |
33 | UFUNCTION(BlueprintNativeEvent, BlueprintPure, Category = "Node Data")
34 | bool HasInputPins();
35 |
36 | UFUNCTION(BlueprintNativeEvent, BlueprintPure, Category = "Node Data")
37 | bool HasOutputPins();
38 |
39 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Node Data")
40 | UYANode* GetNodePointer();
41 | virtual UYANode* GetNodePointer_Implementation();
42 |
43 |
44 | virtual void SetGraph(UYAGraph* InGraph);
45 | virtual UYAGraph* GetGraph();
46 | virtual void AddToChildren(UYANode* NewChildNode);
47 | virtual void AddToParent(UYANode* NewParentNode);
48 | virtual bool HasParentNodes();
49 | virtual void LinkArgumentNodeAsChild(UYANode* Child);
50 | virtual void ClearLinks();
51 | virtual bool RemoveLinkedNode(UYANode* NodeToRemove);
52 | virtual bool RemoveNodeFromParents(UYANode* NodeToRemove);
53 | virtual bool RemoveNodeFromChilds(UYANode* NodeToRemove);
54 |
55 |
56 | #if WITH_ENGINE
57 | //we need this because otherwise during visual scripting with blueprints we can't use anything from WorldContextObject like "get game mode" or "get player controller"
58 | virtual class UWorld* GetWorld() const override;
59 | #endif
60 |
61 | protected:
62 | UPROPERTY()
63 | UYAGraph * Graph = nullptr;
64 | UPROPERTY()
65 | TArray ParentNodes;
66 | UPROPERTY()
67 | TArray ChildNodes;
68 | UPROPERTY()
69 | bool bHasInputPins = true;
70 | UPROPERTY()
71 | bool bHasOutputPins = true;
72 | UPROPERTY()
73 | FText DefaultNodeTitle = FText();
74 |
75 |
76 | };
77 |
78 | #undef LOCTEXT_NAMESPACE
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Utility/GraphSupportComponent.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "Components/ActorComponent.h"
7 | #include "YetAnotherGraphInterface.h"
8 | #include "GraphSupportComponent.generated.h"
9 |
10 |
11 | UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
12 | class YETOTHERGRAPHASSETS_API UGraphSupportComponent : public UActorComponent, public IYetAnotherGraphInterface
13 | {
14 | GENERATED_BODY()
15 |
16 | public:
17 | // Sets default values for this component's properties
18 | UGraphSupportComponent();
19 |
20 |
21 |
22 | UPROPERTY(BlueprintReadOnly, Category = "Graph Support")
23 | TMapNamedBooleans;
24 |
25 | UPROPERTY(BlueprintReadOnly, Category = "Graph Support")
26 | TMapNamedIntegers;
27 |
28 | UPROPERTY()
29 | AActor* Owner;
30 |
31 | // Inherited from YetAnotherGraphInterface
32 | bool SetBooleanVariable_Implementation(FName BooleanName, bool Value) override;
33 | bool GetBooleanVariable_Implementation(FName BooleanName) const override;
34 | bool SetIntegerVariable_Implementation(FName IntegerName, int32 Value) override;
35 | int32 GetIntegerVariable_Implementation(FName IntegerName, bool& Result) const override;
36 |
37 | protected:
38 | // Called when the game starts
39 | virtual void BeginPlay() override;
40 |
41 | public:
42 | // Called every frame
43 | virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
44 |
45 |
46 |
47 | };
48 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Utility/GraphSupportComponentInterface.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "UObject/Interface.h"
7 | #include "GraphSupportComponent.h"
8 | #include "GraphSupportComponentInterface.generated.h"
9 |
10 | // This class does not need to be modified.
11 | UINTERFACE(MinimalAPI)
12 | class UGraphSupportComponentInterface : public UInterface
13 | {
14 | GENERATED_BODY()
15 | };
16 |
17 | /**
18 | *
19 | */
20 | class YETOTHERGRAPHASSETS_API IGraphSupportComponentInterface
21 | {
22 | GENERATED_BODY()
23 |
24 | // Add interface functions to this class. This is the class that will be inherited to implement this interface.
25 | public:
26 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Graph Support Interface")
27 | UGraphSupportComponent* GetGraphSupportComponent();
28 | virtual UGraphSupportComponent* GetGraphSupportComponent_Implementation() = 0;
29 |
30 | };
31 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Utility/Logger.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | DECLARE_LOG_CATEGORY_EXTERN(LogYetOtherGraphAssets, Verbose, All);
6 | #define LLog(Message,...) UE_LOG(LogYetOtherGraphAssets, Log, TEXT(Message), ##__VA_ARGS__)
7 | #define DLog(Message,...) UE_LOG(LogYetOtherGraphAssets, Display, TEXT(Message), ##__VA_ARGS__)
8 | #define WLog(Message,...) UE_LOG(LogYetOtherGraphAssets, Warning, TEXT(Message), ##__VA_ARGS__)
9 | #define ELog(Message,...) UE_LOG(LogYetOtherGraphAssets, Error, TEXT(Message), ##__VA_ARGS__)
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/Utility/YetAnotherGraphInterface.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "UObject/Interface.h"
7 | #include "YetAnotherGraphInterface.generated.h"
8 |
9 | // This class does not need to be modified.
10 | UINTERFACE(Blueprintable)
11 | class UYetAnotherGraphInterface : public UInterface
12 | {
13 | GENERATED_BODY()
14 | };
15 |
16 | /**
17 | * This interface is used to exchange informations between Graphs. used mostly on dynamic nodes to avoid having to create new child blueprints or new c++ classes just for simple checks
18 | */
19 | class YETOTHERGRAPHASSETS_API IYetAnotherGraphInterface
20 | {
21 | GENERATED_BODY()
22 |
23 | // Add interface functions to this class. This is the class that will be inherited to implement this interface.
24 | public:
25 |
26 | // The boolean returns shouldn't be used and they're here only to aggregate all the functions under the "Intefaces" section of blueprints
27 |
28 |
29 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Graph interface")
30 | bool SetBooleanVariable(FName BooleanName,bool Value); // unused return
31 | virtual bool SetBooleanVariable_Implementation(FName BooleanName, bool Value) { return false; }
32 |
33 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Graph interface")
34 | bool GetBooleanVariable(FName BooleanName) const;
35 | virtual bool GetBooleanVariable_Implementation(FName BooleanName) const { return false; }
36 |
37 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Graph interface")
38 | bool SetIntegerVariable(FName IntegerName, int32 Value); // unused return
39 | virtual bool SetIntegerVariable_Implementation(FName IntegerName, int32 Value) { return false; }
40 |
41 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Graph interface")
42 | int32 GetIntegerVariable(FName IntegerName, bool& Result) const;
43 | virtual int32 GetIntegerVariable_Implementation(FName IntegerName,bool& Result) const { return 0; }
44 |
45 |
46 |
47 | };
48 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/Public/YetOtherGraphAssets.h:
--------------------------------------------------------------------------------
1 | // Copyright 1998-2018 Epic Games, Inc. All Rights Reserved.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "Modules/ModuleManager.h"
7 |
8 | class FYetOtherGraphAssetsModule : public IModuleInterface
9 | {
10 | public:
11 |
12 | /** IModuleInterface implementation */
13 | virtual void StartupModule() override;
14 | virtual void ShutdownModule() override;
15 | };
16 |
--------------------------------------------------------------------------------
/Source/YetOtherGraphAssets/YetOtherGraphAssets.Build.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2018 Jhonny Hueller
2 | using UnrealBuildTool;
3 |
4 | public class YetOtherGraphAssets : ModuleRules
5 | {
6 | public YetOtherGraphAssets(ReadOnlyTargetRules Target) : base(Target)
7 | {
8 | PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
9 |
10 | PublicIncludePaths.AddRange(
11 | new string[] {
12 | // ... add public include paths required here ...
13 | }
14 | );
15 |
16 |
17 | PrivateIncludePaths.AddRange(
18 | new string[] {
19 | // ... add other private include paths required here ...
20 | "YetOtherGraphAssets/Private",
21 | "YetOtherGraphAssets/Private/Graphs",
22 | "YetOtherGraphAssets/Private/Nodes",
23 | "YetOtherGraphAssets/Private/Nodes/ActionNodes",
24 | "YetOtherGraphAssets/Private/Nodes/ActionNodes/Implementations",
25 | "YetOtherGraphAssets/Private/Nodes/EmptyNodes",
26 | "YetOtherGraphAssets/Private/Nodes/FlowControlNodes",
27 | "YetOtherGraphAssets/Private/Nodes/FlowControlNodes/Implementations",
28 | "YetOtherGraphAssets/Private/Utility",
29 | }
30 | );
31 |
32 |
33 | PublicDependencyModuleNames.AddRange(
34 | new string[]
35 | {
36 | "Core",
37 | // ... add other public dependencies that you statically link with here ...
38 | }
39 | );
40 |
41 |
42 | PrivateDependencyModuleNames.AddRange(
43 | new string[]
44 | {
45 | "CoreUObject",
46 | "Engine",
47 | "Slate",
48 | "SlateCore",
49 | // ... add private dependencies that you statically link with here ...
50 | }
51 | );
52 |
53 |
54 | DynamicallyLoadedModuleNames.AddRange(
55 | new string[]
56 | {
57 | // ... add any modules that your module loads dynamically here ...
58 | }
59 | );
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/YetAnotherGraphPlugin.uplugin:
--------------------------------------------------------------------------------
1 | {
2 | "FileVersion": 3,
3 | "Version": 1,
4 | "VersionName": "1.0",
5 | "FriendlyName": "Yet Another Graph Plugin",
6 | "Description": "A plugin for creating graphs.",
7 | "Category": "Other",
8 | "CreatedBy": "Jhonny Hueller",
9 | "CreatedByURL": "",
10 | "DocsURL": "",
11 | "MarketplaceURL": "",
12 | "SupportURL": "",
13 | "CanContainContent": true,
14 | "IsBetaVersion": false,
15 | "Installed": false,
16 | "Modules": [
17 | {
18 | "Name": "YetAnotherGraphEditor",
19 | "Type": "Developer",
20 | "LoadingPhase": "Default"
21 | },
22 | {
23 | "Name": "YetOtherGraphAssets",
24 | "Type": "Runtime",
25 | "LoadingPhase": "Default"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/docs/images/BooleanSelector.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/BooleanSelector.png
--------------------------------------------------------------------------------
/docs/images/Categories.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/Categories.png
--------------------------------------------------------------------------------
/docs/images/CreatingTheAssetGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/CreatingTheAssetGraph.png
--------------------------------------------------------------------------------
/docs/images/CreatingTheNewAssetNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/CreatingTheNewAssetNode.png
--------------------------------------------------------------------------------
/docs/images/CustomizingTheNewNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/CustomizingTheNewNode.png
--------------------------------------------------------------------------------
/docs/images/EditingTheGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/EditingTheGraph.png
--------------------------------------------------------------------------------
/docs/images/EmptyNodes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/EmptyNodes.png
--------------------------------------------------------------------------------
/docs/images/NamedNodes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/NamedNodes.png
--------------------------------------------------------------------------------
/docs/images/NodeCategory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/NodeCategory.png
--------------------------------------------------------------------------------
/docs/images/NthSelectorNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/NthSelectorNode.png
--------------------------------------------------------------------------------
/docs/images/RenamingNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/RenamingNode.png
--------------------------------------------------------------------------------
/docs/images/Screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/Screenshot1.png
--------------------------------------------------------------------------------
/docs/images/Screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/Screenshot2.png
--------------------------------------------------------------------------------
/docs/images/SelectingTheNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/SelectingTheNode.png
--------------------------------------------------------------------------------
/docs/images/StoreBooleanNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/StoreBooleanNode.png
--------------------------------------------------------------------------------
/docs/images/StoreIntegerNode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LazyTurtle/YetAnotherGraphPlugin/5a947ea166140a9f941b0bc19597e2909eeeab45/docs/images/StoreIntegerNode.png
--------------------------------------------------------------------------------