There was a problem when repeating the BehaviorTreeEditor module. For some reason, the “Document” tab is called. As I managed to find out, an additional area is being created somewhere. This can be seen in the EditorLayout.json, despite the unambiguity of the mod and its Layout.
During the study, it was revealed that when finding this Layout in the config(EditorLayout.json), it loads all the information from there. However, even when cleaning, there are no changes.
What does the problem look like:
In addition, the tabs are not attached yet. However, in the other mode (Inkwell) everything works as it should:
The logs also show that something should have happened, but it didn’t work out:
The tab "Document" attempted to spawn in layout 'Standalone_NarrativeTree_Layout_v1' but failed for some reason. An "unrecognized tab" will be returned instead.
EditorInit:
void FNarrativeTreeEditor::InitNarrativeTreeEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost>& InitToolkitHost,
UObject* InObject)
{
UE_LOG(LogNarrativeTreeEditor, Log, TEXT("InitNarrativeTreeEditor"));
auto* NarrativeTreeToEdit = Cast<UNarrativeTree>(InObject);
if (NarrativeTreeToEdit)
{
NarrativeTree = NarrativeTreeToEdit;
}
TSharedPtr<FNarrativeTreeEditor> ThisPtr(SharedThis(this));
if (!DocumentManager.IsValid())
{
DocumentManager = MakeShareable(new FDocumentTracker);
DocumentManager->Initialize(ThisPtr);
// Register the document factories
TSharedRef<FDocumentTabFactory> GraphEditorFactory = MakeShareable(new FNTGraphEditorSummoner(
ThisPtr,
FNTGraphEditorSummoner::FOnCreateGraphEditorWidget::CreateSP(this, &FNarrativeTreeEditor::CreateGraphEditorWidget)));
GraphEditorTabFactoryPtr = GraphEditorFactory;
DocumentManager->RegisterDocumentFactory(GraphEditorFactory);
}
TArray<UObject*> ObjectsToEdit;
if (NarrativeTree)
{
ObjectsToEdit.Add(NarrativeTree);
}
if (!ToolbarBuilder.IsValid())
{
ToolbarBuilder = MakeShareable(new FNarrativeTreeEditorToolbar(ThisPtr));
}
const TArray<UObject*>* EditedObjects = GetObjectsCurrentlyBeingEdited();
if (!EditedObjects || EditedObjects->Num() == 0)
{
FGraphEditorCommands::Register();
InitAssetEditor(
Mode,
InitToolkitHost,
FNarrativeTreeEditorModule::NarrativeTreeEditorAppIdentifier,
FTabManager::FLayout::NullLayout,
true,
true,
ObjectsToEdit);
FNarrativeTreeEditorModule& NarrativeTreeEditorModule = FModuleManager::LoadModuleChecked<FNarrativeTreeEditorModule>(
"NarrativeTreeEditor");
AddMenuExtender(
NarrativeTreeEditorModule.GetMenuExtensibilityManager()->GetAllExtenders(GetToolkitCommands(), GetEditingObjects()));
AddApplicationMode(NarrativeTreeMode, MakeShareable(new FNarrativeTreeEditorApplicationMode(ThisPtr)));
AddApplicationMode(InkwellMode, MakeShareable(new FInkwellEditorApplicationMode(ThisPtr)));
}
else
{
for (UObject* ObjectToEdit : ObjectsToEdit)
{
if (!EditedObjects->Contains(ObjectToEdit))
{
AddEditingObject(ObjectToEdit);
}
}
}
if (NarrativeTreeToEdit)
{
SetCurrentMode(NarrativeTreeMode);
}
RegenerateMenusAndToolbars();
}
Mode:
FNarrativeTreeEditorApplicationMode::FNarrativeTreeEditorApplicationMode(TSharedPtr<FNarrativeTreeEditor> InNarrativeTreeEditor)
: FApplicationMode(FNarrativeTreeEditor::NarrativeTreeMode, FNarrativeTreeEditor::GetLocalizedMode)
{
NarrativeTreeEditor = InNarrativeTreeEditor;
TabLayout = FTabManager::NewLayout("Standalone_NarrativeTree_Layout_v1")
->AddArea
(
FTabManager::NewPrimaryArea()->SetOrientation(Orient_Vertical)
->Split
(
FTabManager::NewStack()
->AddTab(FNarrativeTreeEditorTabs::GraphEditorID,
ETabState::ClosedTab)
)
);
InNarrativeTreeEditor->GetToolbarBuilder()->AddModesToolbar(ToolbarExtender);
InNarrativeTreeEditor->GetToolbarBuilder()->AddNarrativeTreeToolbar(ToolbarExtender);
}
EditorLayout.json:
"Standalone_NarrativeTree_Layout_v1":
{
"Type": "Layout",
"Name": "Standalone_NarrativeTree_Layout_v1",
"PrimaryAreaIndex": 0,
"Areas": [
{
"SizeCoefficient": 1,
"Type": "Area",
"Orientation": "Orient_Vertical",
"WindowPlacement": "Placement_NoWindow",
"Nodes": [
{
"SizeCoefficient": 1,
"Type": "Stack",
"HideTabWell": false,
"ForegroundTab": "None",
"Tabs": [
{
"TabId": "NarrativeTreeGraph",
"TabState": "ClosedTab"
}
]
}
]
},
{
"SizeCoefficient": 1,
"Type": "Area",
"Orientation": "Orient_Horizontal",
"WindowPlacement": "Placement_Specified",
"WindowPosition_X": 457,
"WindowPosition_Y": 217,
"WindowSize_X": 1000,
"WindowSize_Y": 600,
"bIsMaximized": false,
"Nodes": [
{
"SizeCoefficient": 1,
"Type": "Stack",
"HideTabWell": false,
"ForegroundTab": "Document",
"Tabs": [
{
"TabId": "Document",
"TabState": "OpenedTab"
}
]
}
]
}
]
}
It seems that the problem lies in the difference of tab summoners. However, everything works in the reference version, and as I understand it, this class is necessary for graphs:
struct FInkwellEditorSummoner : public FWorkflowTabFactory
{
public:
FInkwellEditorSummoner(TSharedPtr<class FNarrativeTreeEditor> InNarrativeTreeEditorPtr);
virtual TSharedRef<SWidget> CreateTabBody(const FWorkflowTabSpawnInfo& Info) const override;
virtual FText GetTabToolTipText(const FWorkflowTabSpawnInfo& Info) const override;
protected:
TWeakPtr<class FNarrativeTreeEditor> NarrativeTreeEditorPtr;
};
struct FNTGraphEditorSummoner : public FDocumentTabFactoryForObjects<UEdGraph>
{
public:
DECLARE_DELEGATE_RetVal_OneParam(TSharedRef<SGraphEditor>, FOnCreateGraphEditorWidget, UEdGraph*);
public:
FNTGraphEditorSummoner(TSharedPtr<class FNarrativeTreeEditor> InNarrativeTreeEditorPtr, FOnCreateGraphEditorWidget CreateGraphEditorWidgetCallback);
virtual void OnTabActivated(TSharedPtr<SDockTab> Tab) const override;
virtual void OnTabRefreshed(TSharedPtr<SDockTab> Tab) const override;
protected:
virtual TAttribute<FText> ConstructTabNameForObject(UEdGraph* DocumentID) const override;
virtual TSharedRef<SWidget> CreateTabBodyForObject(const FWorkflowTabSpawnInfo& Info, UEdGraph* DocumentID) const override;
virtual const FSlateBrush* GetTabIconForObject(const FWorkflowTabSpawnInfo& Info, UEdGraph* DocumentID) const override;
virtual void SaveState(TSharedPtr<SDockTab> Tab, TSharedPtr<FTabPayload> Payload) const override;
protected:
TWeakPtr<class FNarrativeTreeEditor> NarrativeTreeEditorPtr;
FOnCreateGraphEditorWidget OnCreateGraphEditorWidget;
};