Download

GENERIC GRAPH / Custom Editor, how do I make new Nodes?

Hi I am using GitHub - jinyuliao/GenericGraph: Generic graph data structure plugin for ue4 but having trouble to create new Nodes.
I made classes which inherent from those following classes

Editor Module
-UEdNode_GenericGraphNode
-SEdNode_GenericGraphNode
Runtime Module
-UGenericGraphNode

I made a new FGraphPanelNodeFactory

class FGraphPanelNodeFactory_GenericGraphAnswer : public FGraphPanelNodeFactory
{
	virtual TSharedPtr<class SGraphNode> CreateNode(UEdGraphNode* Node) const override
	{
		if (UEdNode_Answer* EdNode_GraphNodeAnwser = Cast<UEdNode_Answer>(Node))
		{
			return SNew(SedNode_Answer, EdNode_GraphNodeAnwser);
		}
		else if (UEdNode_GenericGraphEdge* EdNode_Edge = Cast<UEdNode_GenericGraphEdge>(Node))
		{
			return SNew(SEdNode_GenericGraphEdge, EdNode_Edge);
		}
		return nullptr;
	}
};

And also a FEdGraphSchemaAction.h

USTRUCT()
struct FAssetSchemaAction_GenericGraphAnwser_NewNode : public FEdGraphSchemaAction
{
	GENERATED_USTRUCT_BODY();

public:
	FAssetSchemaAction_GenericGraphAnswer_NewNode(): NodeTemplate(nullptr) {}

	FAssetSchemaAction_GenericGraphAnswer_NewNode(const FText& InNodeCategory, const FText& InMenuDesc, const FText& InToolTip, const int32 InGrouping)
		: FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping), NodeTemplate(nullptr) {}

	virtual UEdGraphNode* PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
	virtual void AddReferencedObjects(FReferenceCollector& Collector) override;

	UEdNode_Answer* NodeTemplate;
};

And I use the FEdGraphSchemaAction in the UAssetGraphSchema_GenericGraph::GetGraphContextActions

if (!Graph->NodeType->HasAnyClassFlags(CLASS_Abstract))
	{
		//Og Node
		TSharedPtr<FAssetSchemaAction_GenericGraph_NewNode> NewNodeAction(new FAssetSchemaAction_GenericGraph_NewNode(LOCTEXT("GenericGraphNodeAction", "Generic Graph Node Tooltip"), Desc, AddToolTip, 0));
		NewNodeAction->NodeTemplate = NewObject<UEdNode_GenericGraphNode>(ContextMenuBuilder.OwnerOfTemporaries);
		NewNodeAction->NodeTemplate->GenericGraphNode = NewObject<UGenericGraphNode>(NewNodeAction->NodeTemplate, Graph->NodeType);
		NewNodeAction->NodeTemplate->GenericGraphNode->Graph = Graph;
		ContextMenuBuilder.AddAction(NewNodeAction);

		//My new Node <-----------
		TSharedPtr<FAssetSchemaAction_GenericGraphAnswer_NewNode> NewNodeAction2(new FAssetSchemaAction_GenericGraphAnswer_NewNode(LOCTEXT("GenericGraphNodeAction2", "Generic Graph Node Tooltip2"), Desc, AddToolTip, 0));
		NewNodeAction2->NodeTemplate = NewObject<UEdNode_Answer>(ContextMenuBuilder.OwnerOfTemporaries);
		NewNodeAction2->NodeTemplate->GenericGraphNode = NewObject<UGenericGraphNodeAnswer>(NewNodeAction2->NodeTemplate, Graph->NodeType);
		NewNodeAction2->NodeTemplate->GenericGraphNode->Graph = Graph;
		ContextMenuBuilder.AddAction(NewNodeAction2);

		Visited.Add(Graph->NodeType);
	}

If I implement it like this, UE crashes and says that the line is wrong, where I use my runtime class inherented from UGenericGraphNode.

NewNodeAction2->NodeTemplate->GenericGraphNode = NewObject<UGenericGraphNodeAnswer>(NewNodeAction2->NodeTemplate, Graph->NodeType);

The weird thing is that It works, if I use my original runtime class (clearly not the result I want)

NewNodeAction2->NodeTemplate->GenericGraphNode = NewObject<UGenericGraphNode>(NewNodeAction2->NodeTemplate, Graph->NodeType);

What do I do wrong?

I could be wrong but maybe The first parameter should be EdGraphNode that instead of Template?
NewNodeAction2->NodeTemplate->GenericGraphNode is the runtime node data?

I made my own GraphEditor and I find Generic Graph very complex for no reason. Here is how I create my Node. I have in C++ all registered Classes Of Runtime Node. Here is my code and How I do it.

H

USTRUCT()
struct FLUIDARCHITECTCOREEDITOR_API FFluidArchitectEditorEdGraphSchemaAction : public FEdGraphSchemaAction
{
	GENERATED_USTRUCT_BODY();

public:
	FFluidArchitectEditorEdGraphSchemaAction() {}

	FFluidArchitectEditorEdGraphSchemaAction(const FText& InNodeCategory, const FText& InMenuDesc, const FText& InToolTip, const int32 InGrouping)
		: FEdGraphSchemaAction(InNodeCategory, InMenuDesc, InToolTip, InGrouping) {}
	virtual UEdGraphNode* PerformAction(class UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode = true) override;
	TSubclassOf<UFluidArchitectCoreGraphNodeEvent> GraphNodeEventClass;
};

CPP

UEdGraphNode* FFluidArchitectEditorEdGraphSchemaAction::PerformAction(UEdGraph* ParentGraph, UEdGraphPin* FromPin, const FVector2D Location, bool bSelectNewNode)
{
	UFluidArchitectEditorEdGraphNode* Node = UFluidArchitectEditorEdGraph::CreateTemplateEdGraphNode(ParentGraph);
	Node->GraphNodeEvent = NewObject<UFluidArchitectCoreGraphNodeEvent>(Node,GraphNodeEventClass);
	ParentGraph->AddNode(Node);
	return Node;
}


void UFluidArchitectEditorEdGraphSchema::GetGraphContextActions(FGraphContextMenuBuilder& ContextMenuBuilder) const
{
	auto CurrentAsset = FluidArchitectCoreEditorProfile::CurrentAsset;
	if (!CurrentAsset)
		return;
	
        ContextMenuBuilder.Empty();	
	for (int i = 0; i < CurrentAsset->RegistredGraphNodeEventClasses.Num();i++)
	{
		auto Action = new FFluidArchitectEditorEdGraphSchemaAction(FText::FromString(""), FText::FromString(CurrentAsset->RegistredGraphNodeEventClasses[i].GetDefaultObject()->GetSearchName().ToString()), FText::FromString(""), 0);
		Action->GraphNodeEventClass = CurrentAsset->RegistredGraphNodeEventClasses[i];
		TSharedPtr<FFluidArchitectEditorEdGraphSchemaAction> NewEventNodeAction(Action);
		ContextMenuBuilder.AddAction(NewEventNodeAction);
	}
}

As you can see I have one Action for all my nodes and the Class I want to use is inside it. Than in GetGraphContextActions I add multiple actions of it with “GraphNodeEventClass” variable being set and setting action name based on class.

Thanks for the help, your code brought me on to the right track. The issue was the “Graph->NodeType” in NewNodeAction2->NodeTemplate->GenericGraphNode = NewObject<UGenericGraphNode>(NewNodeAction2->NodeTemplate, Graph->NodeType); It’s kinda silly to get the NodeType from the Graph, so I removed the “Graph->NodeType” and it works.

1 Like

Happy to hear that. Good luck. Unreal has a lot of silly things in there API I feel like.