Having trouble with a custom asset editor.

hi, I’m trying to create a simple custom asset editor but I’m having problems with the creation of the new window for the editor.
I already created a new custom asset, its factory and a new class that inherits FAssetTypeActions_Base and support my new asset.
I also created a new class that inherit FAssetEditorToolkit. One told me to create a simple widget and to register it within RegisterTabSpawners() function. Problem is, the engine crashes when it reach SNew(SGraphEditor) in my CreateViewportEditor() function and I don’t know what to do.
I tried commenting the line and return an empty pointer but it crashes anyway so I don’t really know what I’m doing wrong.
here’s the code if it can help:
.h


#pragma once

#include "CoreMinimal.h"
#include "AssetEditorToolkit.h"
#include "NotifyHook.h"
#include "GCObject.h"
#include "GraphEditor.h"
#include "PropertyEditorModule.h"
#include "ModuleManager.h"

/**
 * 
 */
class NOTANOTHERGRAPHASSISTANT_API AssetEditorGenericGraph:public FAssetEditorToolkit, public FNotifyHook, public FGCObject
{
public:
    AssetEditorGenericGraph();
    ~AssetEditorGenericGraph();

    // Inherited via FAssetEditorToolkit
    virtual FName GetToolkitFName() const override;
    virtual FText GetBaseToolkitName() const override;
    virtual FText GetToolkitName() const override;
    virtual FText GetToolkitToolTipText() const override;
    virtual FLinearColor GetWorldCentricTabColorScale() const override;
    virtual FString GetWorldCentricTabPrefix() const override;
    virtual FString GetDocumentationLink() const override;
    virtual void SaveAsset_Execute() override;

    // IToolkit interface
    virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
    virtual void UnregisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;

    // Inherited via FGCObject
    virtual void AddReferencedObjects(FReferenceCollector & Collector) override;

private:

    TSharedPtr<SGraphEditor>ViewportEditor;
    TSharedPtr<class IDetailsView> PropertyWidget;
    TSharedPtr<class IDetailsView> EditorSettingsWidget;

    TSharedPtr<SGraphEditor>CreateViewportEditor();

    TSharedRef<SDockTab> SpawnTab_Viewport(const FSpawnTabArgs & Args);

};


.cpp



#include "AssetEditorGenericGraph.h"

#define LOCTEXT_NAMESPACE "AssetEditorGenericGraph"

AssetEditorGenericGraph::AssetEditorGenericGraph()
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor costructor"));
    CreateViewportEditor();
}

AssetEditorGenericGraph::~AssetEditorGenericGraph()
{
}

FName AssetEditorGenericGraph::GetToolkitFName() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetToolkitFName"));
    return FName();
}

FText AssetEditorGenericGraph::GetBaseToolkitName() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetBaseToolkitName"));
    return FText();
}

FText AssetEditorGenericGraph::GetToolkitName() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetToolkitName"));
    return FText();
}

FText AssetEditorGenericGraph::GetToolkitToolTipText() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetToolkitToolTipText"));
    return FText();
}

FLinearColor AssetEditorGenericGraph::GetWorldCentricTabColorScale() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetWorldCentricTabColorScale"));
    return FLinearColor();
}

FString AssetEditorGenericGraph::GetWorldCentricTabPrefix() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetWorldCentricTabPrefix"));
    return FString();
}

FString AssetEditorGenericGraph::GetDocumentationLink() const
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor GetDocumentationLink"));
    return FString();
}

void AssetEditorGenericGraph::SaveAsset_Execute()
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor SaveAsset_Execute"));
}

void AssetEditorGenericGraph::RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager)
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor RegisterTabSpawners"));

    WorkspaceMenuCategory = TabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("WorkspaceMenuAssetEditorGenericGraph", "Generic Graph Editor"));
    auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();

    FAssetEditorToolkit::RegisterTabSpawners(TabManager);
    TabManager->RegisterTabSpawner(TEXT("TABID"), FOnSpawnTab::CreateSP(this, &AssetEditorGenericGraph::SpawnTab_Viewport)).SetDisplayName(LOCTEXT("GraphCanvasTab", "Viewport"));

}

void AssetEditorGenericGraph::UnregisterTabSpawners(const TSharedRef<FTabManager>& TabManager)
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor UnregisterTabSpawners"));
}

void AssetEditorGenericGraph::AddReferencedObjects(FReferenceCollector & Collector)
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor AddReferencedObjects"));
}

TSharedPtr<SGraphEditor> AssetEditorGenericGraph::CreateViewportEditor()
{
    UE_LOG(LogTemp, Warning, TEXT("Asset editor START CreateViewportEditor"));

    FGraphAppearanceInfo AppearanceInfo;
    AppearanceInfo.CornerText = LOCTEXT("AppearanceCornerTextAssetEditorGenericGraph", "Generic Graph");

    ViewportEditor = SNew(SGraphEditor);


    FDetailsViewArgs Args;
    Args.bHideSelectionTip = true;
    Args.NotifyHook = this;

    FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
    PropertyWidget = PropertyModule.CreateDetailView(Args);
    EditorSettingsWidget = PropertyModule.CreateDetailView(Args);

    return ViewportEditor;
}
TSharedRef<SDockTab> AssetEditorGenericGraph::SpawnTab_Viewport(const FSpawnTabArgs& Args)
{

    TSharedRef<SDockTab> SpawnedTab = SNew(SDockTab).Label(LOCTEXT("ViewportTab_Title", "Viewport"));

    if (ViewportEditor.IsValid())
    {
        SpawnedTab->SetContent(ViewportEditor.ToSharedRef());
    }

    return SpawnedTab;
}

I also need a bit of help understanding what I need to implement in order to achieve a simple graph editor, i tried looking for documentation but I found almost nothing.

So I think I found the problems. I rewrote the class removing everything I could and I found that I wasn’t creating properly the slate interface.
With this new AssetEditorToolkit

.h




#pragma once

#include "CoreMinimal.h"
#include "AssetEditorToolkit.h"
#include "GenericGraph.h"
#include "GraphEditor.h"
#include "SDockTab.h"

/**
 * 
 */
class FGenericGraphEditorToolkit : public FAssetEditorToolkit, public FGCObject
{
public:
    FGenericGraphEditorToolkit();
    ~FGenericGraphEditorToolkit();

    UGenericGraph* Graph;

    TSharedRef<SDockTab> HandleTabManagerSpawnTab(const FSpawnTabArgs& Args, FName TabIdentifier);

    // Inherited via FAssetEditorToolkit
    virtual FLinearColor GetWorldCentricTabColorScale() const override;
    virtual FName GetToolkitFName() const override;
    virtual FText GetBaseToolkitName() const override;
    virtual FString GetWorldCentricTabPrefix() const override;
    virtual void RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
    virtual void UnregisterTabSpawners(const TSharedRef<FTabManager>& TabManager) override;
    virtual void InitAssetEditor(const EToolkitMode::Type InMode, const TSharedPtr<class IToolkitHost>& InToolkitHost, UGenericGraph* InGraph);


    // Inherited via FGCObject
    virtual void AddReferencedObjects(FReferenceCollector & Collector) override;


};


.cpp


#include "GenericGraphEditorToolkit.h"

#define LOCTEXT_NAMESPACE "AssetEditorToolkit"

FGenericGraphEditorToolkit::FGenericGraphEditorToolkit()
{
}

FGenericGraphEditorToolkit::~FGenericGraphEditorToolkit()
{
}

TSharedRef<SDockTab> FGenericGraphEditorToolkit::HandleTabManagerSpawnTab(const FSpawnTabArgs & Args, FName TabIdentifier)
{
    TSharedPtr<SWidget>Tab = SNullWidget::NullWidget;
    if (TabIdentifier== FName("GraphEditorId"))
    {
        //Tab = SNew(SGraphEditor);
    }
    return SNew(SDockTab)
        .TabRole(ETabRole::PanelTab)
        
            Tab.ToSharedRef()
        ];
}

FLinearColor FGenericGraphEditorToolkit::GetWorldCentricTabColorScale() const
{
    return FLinearColor::Blue;
}

FName FGenericGraphEditorToolkit::GetToolkitFName() const
{
    return FName("Generic Graph Editor");
}

FText FGenericGraphEditorToolkit::GetBaseToolkitName() const
{
    return LOCTEXT("AppLabel", "Generic graph Editor");
}

FString FGenericGraphEditorToolkit::GetWorldCentricTabPrefix() const
{
    return LOCTEXT("WorldCentricTabPrefix", "Generic Graph ").ToString();
}

void FGenericGraphEditorToolkit::InitAssetEditor(const EToolkitMode::Type InMode, const TSharedPtr<class IToolkitHost>& InToolkitHost, UGenericGraph * InGraph)
{
    Graph = InGraph;
    TSharedRef<FTabManager::FLayout>Layout = FTabManager::NewLayout("Layout")
        ->AddArea
        (
            FTabManager::NewPrimaryArea()
            ->SetOrientation(Orient_Vertical)
            ->Split
            (
                FTabManager::NewSplitter()
                ->SetOrientation(Orient_Vertical)
                ->SetSizeCoefficient(0.66f)
                ->Split
                (
                    FTabManager::NewStack()
                    ->AddTab(GetToolbarTabId(), ETabState::OpenedTab)
                    ->SetHideTabWell(true)
                    ->SetSizeCoefficient(0.1f)
                )
                ->Split
                (
                    FTabManager::NewStack()
                    ->AddTab(FName("GraphEditorId"), ETabState::OpenedTab)
                    ->SetHideTabWell(true)
                    ->SetSizeCoefficient(0.9f)
                )
            )
        );
    FAssetEditorToolkit::InitAssetEditor(InMode, InToolkitHost, FName("GraphEditorIdentifier"), Layout, true, true, Graph);
}

void FGenericGraphEditorToolkit::RegisterTabSpawners(const TSharedRef<FTabManager>& TabManager)
{
    WorkspaceMenuCategory = TabManager->AddLocalWorkspaceMenuCategory(LOCTEXT("GenericGraphToolkitWorkspaceMenu", "Graph Editor"));
    auto WorkspaceMenuCategoryRef = WorkspaceMenuCategory.ToSharedRef();
    FAssetEditorToolkit::RegisterTabSpawners(TabManager);

    TabManager->RegisterTabSpawner(FName("GraphEditorId"), FOnSpawnTab::CreateSP(this,&FGenericGraphEditorToolkit::HandleTabManagerSpawnTab, FName("GraphEditorId")))
        .SetDisplayName(LOCTEXT("GraphEditorTabName", "Graph Editor"))
        .SetGroup(WorkspaceMenuCategoryRef);
}

void FGenericGraphEditorToolkit::UnregisterTabSpawners(const TSharedRef<FTabManager>& TabManager)
{
}

void FGenericGraphEditorToolkit::AddReferencedObjects(FReferenceCollector & Collector)
{
}

#undef LOCTEXT_NAMESPACE

the window opens properly

But only as long as I don’t try to create a SGraphEditor widget.


TSharedRef<SDockTab> FGenericGraphEditorToolkit::HandleTabManagerSpawnTab(const FSpawnTabArgs & Args, FName TabIdentifier)
{
    TSharedPtr<SWidget>Tab = SNullWidget::NullWidget;
    if (TabIdentifier== FName("GraphEditorId"))
    {
        //Tab = SNew(SGraphEditor);
    }
    return SNew(SDockTab)
        .TabRole(ETabRole::PanelTab)
        
            Tab.ToSharedRef()
        ];
}

So I think I’m using wrong that specific widget. The API page doesn’t tell me anything about the proper use of SGraphEditor, I was expecting an empty blueprint graph window, so I don’t know how I misused it.
Does anyone know how to use it properly?

So it turns out that you need to give him an EdGraph otherwise the slate widget won’t load and will stop the creation of the window.
Using FBlueprintEditorUtils::CreateNewGraph you will also need a EdGraphSchema. Both classes (EdGraph and EdGraphSchema) are the bare minimum, can be inherited and left empty and the slate widget should load properly.



TSharedRef<SDockTab> FGenericGraphEditorToolkit::HandleTabManagerSpawnTabGraphTabId(const FSpawnTabArgs & Args, FName TabIdentifier)
{
    TSharedPtr<SWidget>Tab = SNullWidget::NullWidget;
    if (TabIdentifier == GraphTabId)
    {
       GraphAsset->EdGraph = CastChecked<UGenericGraphEdGraph>(FBlueprintEditorUtils::CreateNewGraph(GraphAsset, NAME_None, UGenericGraphEdGraph::StaticClass(), UGenericGraphEdGraphSchema::StaticClass()));
        Tab = SNew(SGraphEditor).GraphToEdit(GraphAsset->EdGraph);
    }
    return SNew(SDockTab)
        .TabRole(ETabRole::PanelTab)
        
            Tab.ToSharedRef()
        ];
} 
 

Good job!! I also have the same problem.Think you for help me…

Keep it!