├── .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 --------------------------------------------------------------------------------