- I want to remove the toolbar and the parent controls below to make this window a truly empty window
2. I want to add a custom widget, for example, I write an SCompoundWidget to fill this window (after removing the parent widgets of the toolbar and detail widgets)
- I want to have two tabs on the right side, like in the animation mode?
Regarding the third point, I imitated FControlRigEditModeToolkit and wrote:
.h
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
/**
* This is the module definition for the editor mode. You can implement custom functionality
* as your plugin module starts up and shuts down. See IModuleInterface for more extensibility options.
*/
class FDigitalHumanEditorModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};
.cpp:
// Copyright Epic Games, Inc. All Rights Reserved.
#include "DigitalHumanEditorEditorModeToolkit.h"
#include "DigitalHumanEditorEditorMode.h"
#include "Engine/Selection.h"
#include "Modules/ModuleManager.h"
#include "PropertyEditorModule.h"
#include "IDetailsView.h"
#include "EditorModeManager.h"
#include "Toolkits/AssetEditorModeUILayer.h"
#define LOCTEXT_NAMESPACE "DigitalHumanEditorEditorModeToolkit"
FDigitalHumanEditorEditorModeToolkit::FDigitalHumanEditorEditorModeToolkit()
{
}
void FDigitalHumanEditorEditorModeToolkit::Init(const TSharedPtr<IToolkitHost>& InitToolkitHost, TWeakObjectPtr<UEdMode> InOwningMode)
{
FModeToolkit::Init(InitToolkitHost, InOwningMode);
RequestModeUITabs();
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
if (ModeUILayerPtr.IsValid())
{
ModeUILayerPtr->GetTabManager()->TryInvokeTab(FName(TEXT("DigitalHumanOutlinerTab")));
}
}
void FDigitalHumanEditorEditorModeToolkit::GetToolPaletteNames(TArray<FName>& PaletteNames) const
{
PaletteNames.Add(NAME_Default);
}
FName FDigitalHumanEditorEditorModeToolkit::GetToolkitFName() const
{
return FName("DigitalHumanEditorEditorMode");
}
FText FDigitalHumanEditorEditorModeToolkit::GetBaseToolkitName() const
{
return LOCTEXT("DisplayName", "DigitalHumanEditorEditorMode Toolkit");
}
void FDigitalHumanEditorEditorModeToolkit::RequestModeUITabs()
{
if (ModeUILayer.IsValid())
{
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
TSharedRef<FWorkspaceItem> MenuGroup = ModeUILayerPtr->GetModeMenuCategory().ToSharedRef();
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(FName(TEXT("DigitalHumanOutlinerTab")));
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(FName(TEXT("DigitalHumanOutlinerTab")), FOnSpawnTab::CreateStatic(&FDigitalHumanEditorEditorModeToolkit::SpawnOutlinerTab))
.SetDisplayName(LOCTEXT("DigitalHumanOutlinerTab", "Digital Human Outliner"))
.SetTooltipText(LOCTEXT("DigitalHumanOutlinerTabTooltip", "Show Digital Human Outliner."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("DigitalHumanEditorStyle"), TEXT("DigitalHuman.Outliner")));
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(FName(TEXT("DigitalHumanSpacePickerTab")));
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(FName(TEXT("DigitalHumanSpacePickerTab")), FOnSpawnTab::CreateStatic(&FDigitalHumanEditorEditorModeToolkit::SpawnSpacePickerTab))
.SetDisplayName(LOCTEXT("DigitalHumanSpacePickerTab", "Digital Human Space Picker"))
.SetTooltipText(LOCTEXT("DigitalHumanSpacePickerTabTooltip", "Show Digital Human Space Picker."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("DigitalHumanEditorStyle"), TEXT("DigitalHuman.SpacePicker")));
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(FName(TEXT("DigitalHumanDetailsTab")));
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(FName(TEXT("DigitalHumanDetailsTab")), FOnSpawnTab::CreateStatic(&FDigitalHumanEditorEditorModeToolkit::SpawnDetailsTab))
.SetDisplayName(LOCTEXT("DigitalHumanDetailsTab", "Digital Human Details"))
.SetTooltipText(LOCTEXT("DigitalHumanDetailsTabTooltip", "Show Digital Human Details."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("DigitalHumanEditorStyle"), TEXT("DigitalHuman.Details")));
}
}
TSharedRef<SDockTab> FDigitalHumanEditorEditorModeToolkit::SpawnOutlinerTab(const FSpawnTabArgs& Args)
{
UE_LOG(LogTemp, Warning, TEXT("SpawnOutlinerTab called"));
return SNew(SDockTab)
[
SNew(STextBlock).Text(LOCTEXT("DigitalHumanOutlinerTabContent", "Digital Human Outliner Content"))
];
}
TSharedRef<SDockTab> FDigitalHumanEditorEditorModeToolkit::SpawnSpacePickerTab(const FSpawnTabArgs& Args)
{
UE_LOG(LogTemp, Warning, TEXT("SpawnOutlinerTab called"));
return SNew(SDockTab)
[
SNew(STextBlock).Text(LOCTEXT("DigitalHumanSpacePickerTabContent", "Digital Human Space Picker Content"))
];
}
TSharedRef<SDockTab> FDigitalHumanEditorEditorModeToolkit::SpawnDetailsTab(const FSpawnTabArgs& Args)
{
UE_LOG(LogTemp, Warning, TEXT("SpawnOutlinerTab called"));
return SNew(SDockTab)
[
SNew(STextBlock).Text(LOCTEXT("DigitalHumanDetailsTabContent", "Digital Human Details Content"))
];
}
#undef LOCTEXT_NAMESPACE
But now there is a problem, as long as the RequestMode Tabs function is there, no matter whether there is code in this function, switching modes will not have any effect.
References:
ControlRigEditModeToolkit.h
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SWidget.h"
#include "EditorModes.h"
#include "Toolkits/BaseToolkit.h"
#include "EditorModeManager.h"
#include "EditMode/SControlRigEditModeTools.h"
#include "EditMode/ControlRigEditMode.h"
class SControlRigTweenWidget;
class FControlRigEditModeToolkit : public FModeToolkit
{
public:
friend class SControlRigTweenWidget;
FControlRigEditModeToolkit(FControlRigEditMode& InEditMode)
: EditMode(InEditMode)
{
}
/** IToolkit interface */
virtual FName GetToolkitFName() const override { return FName("AnimationMode"); }
virtual FText GetBaseToolkitName() const override { return NSLOCTEXT("AnimationModeToolkit", "DisplayName", "Animation"); }
virtual class FEdMode* GetEditorMode() const override { return &EditMode; }
virtual TSharedPtr<class SWidget> GetInlineContent() const override { return ModeTools; }
virtual bool ProcessCommandBindings(const FKeyEvent& InKeyEvent) const override
{
if (EditMode.GetCommandBindings() && EditMode.GetCommandBindings()->ProcessCommandBindings(InKeyEvent))
{
return true;
}
return false;
}
virtual void Init(const TSharedPtr<IToolkitHost>& InitToolkitHost) override;
/** Mode Toolbar Palettes **/
virtual void GetToolPaletteNames(TArray<FName>& InPaletteName) const override;
virtual FText GetToolPaletteDisplayName(FName PaletteName) const override;
virtual void BuildToolPalette(FName PaletteName, class FToolBarBuilder& ToolbarBuilder) override;
/** Modes Panel Header Information **/
virtual FText GetActiveToolDisplayName() const override;
virtual FText GetActiveToolMessage() const override;
virtual void OnToolPaletteChanged(FName PaletteName) override;
void TryInvokeToolkitUI(const FName InName);
bool IsToolkitUIActive(const FName InName) const;
/** For updating tween values via hot keys*/
void GetToNextActiveSlider();
bool CanChangeAnimSliderTool() const;
void DragAnimSliderTool(double Val);
void ResetAnimSlider();
void StartAnimSliderTool();
public:
static const FName PoseTabName;
static const FName MotionTrailTabName;
static const FName TweenOverlayName;
static const FName SnapperTabName;
static const FName DetailsTabName;
static const FName OutlinerTabName;
static const FName SpacePickerTabName;
protected:
void CreateAndShowTweenOverlay();
void TryShowTweenOverlay();
void RemoveAndDestroyTweenOverlay();
void TryRemoveTweenOverlay();
void UpdateTweenWidgetLocation(const FVector2D InLocation);
FMargin GetTweenWidgetPadding() const;
/* FModeToolkit Interface */
virtual void RequestModeUITabs() override;
virtual void InvokeUI() override;
void UnregisterAndRemoveFloatingTabs();
private:
private:
/** The edit mode we are bound to */
FControlRigEditMode& EditMode;
TSharedPtr<SWidget> TweenWidgetParent;
TSharedPtr<SControlRigTweenWidget> TweenWidget;
FVector2D InViewportTweenWidgetLocation;
/** The tools widget */
TSharedPtr<SControlRigEditModeTools> ModeTools;
};
ControlRigEditModeToolkit.cpp
// Copyright Epic Games, Inc. All Rights Reserved.
/**
* Control Rig Edit Mode Toolkit
*/
#include "EditMode/ControlRigEditModeToolkit.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/SWidget.h"
#include "EditorModes.h"
#include "Toolkits/BaseToolkit.h"
#include "EditorModeManager.h"
#include "EditMode/SControlRigEditModeTools.h"
#include "EditMode/ControlRigEditMode.h"
#include "Modules/ModuleManager.h"
#include "EditMode/SControlRigBaseListWidget.h"
#include "EditMode/SControlRigTweenWidget.h"
#include "EditMode/SControlRigSnapper.h"
#include "Tools/SMotionTrailOptions.h"
#include "Toolkits/AssetEditorModeUILayer.h"
#include "Widgets/Docking/SDockTab.h"
#include "EditMode/ControlRigEditModeSettings.h"
#include "EditMode/SControlRigDetails.h"
#include "EditMode/SControlRigOutliner.h"
#include "EditMode/SControlRigSpacePicker.h"
#include "LevelEditor.h"
#include "SLevelViewport.h"
#define LOCTEXT_NAMESPACE "FControlRigEditModeToolkit"
namespace
{
static const FName AnimationName(TEXT("Animation"));
const TArray<FName> AnimationPaletteNames = { AnimationName };
}
const FName FControlRigEditModeToolkit::PoseTabName = FName(TEXT("PoseTab"));
const FName FControlRigEditModeToolkit::MotionTrailTabName = FName(TEXT("MotionTrailTab"));
const FName FControlRigEditModeToolkit::SnapperTabName = FName(TEXT("SnapperTab"));
const FName FControlRigEditModeToolkit::TweenOverlayName = FName(TEXT("TweenOverlay"));
const FName FControlRigEditModeToolkit::OutlinerTabName = FName(TEXT("ControlRigOutlinerTab"));
const FName FControlRigEditModeToolkit::DetailsTabName = FName(TEXT("ControlRigDetailsTab"));
const FName FControlRigEditModeToolkit::SpacePickerTabName = FName(TEXT("ControlRigSpacePicker"));
void FControlRigEditModeToolkit::Init(const TSharedPtr<IToolkitHost>& InitToolkitHost)
{
SAssignNew(ModeTools, SControlRigEditModeTools, SharedThis(this), EditMode, EditMode.GetWorld());
FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked<FPropertyEditorModule>("PropertyEditor");
FDetailsViewArgs DetailsViewArgs;
DetailsViewArgs.bUpdatesFromSelection = false;
DetailsViewArgs.bLockable = false;
DetailsViewArgs.bAllowSearch = false;
DetailsViewArgs.NameAreaSettings = FDetailsViewArgs::HideNameArea;
DetailsViewArgs.bHideSelectionTip = true;
DetailsViewArgs.bSearchInitialKeyFocus = false;
DetailsViewArgs.DefaultsOnlyVisibility = EEditDefaultsOnlyNodeVisibility::Automatic;
DetailsViewArgs.bShowOptions = false;
DetailsViewArgs.bAllowMultipleTopLevelObjects = true;
DetailsView = PropertyEditorModule.CreateDetailView(DetailsViewArgs);
FModeToolkit::Init(InitToolkitHost);
}
void FControlRigEditModeToolkit::GetToolPaletteNames(TArray<FName>& InPaletteName) const
{
InPaletteName = AnimationPaletteNames;
}
FText FControlRigEditModeToolkit::GetToolPaletteDisplayName(FName PaletteName) const
{
if (PaletteName == AnimationName)
{
FText::FromName(AnimationName);
}
return FText();
}
void FControlRigEditModeToolkit::BuildToolPalette(FName PaletteName, class FToolBarBuilder& ToolBarBuilder)
{
if (PaletteName == AnimationName)
{
ModeTools->CustomizeToolBarPalette(ToolBarBuilder);
}
}
void FControlRigEditModeToolkit::OnToolPaletteChanged(FName PaletteName)
{
}
void FControlRigEditModeToolkit::TryInvokeToolkitUI(const FName InName)
{
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
if (InName == MotionTrailTabName)
{
FTabId TabID(MotionTrailTabName);
ModeUILayerPtr->GetTabManager()->TryInvokeTab(TabID);
}
else if (InName == PoseTabName)
{
FTabId TabID(PoseTabName);
ModeUILayerPtr->GetTabManager()->TryInvokeTab(TabID);
}
else if (InName == SnapperTabName)
{
FTabId TabID(SnapperTabName);
ModeUILayerPtr->GetTabManager()->TryInvokeTab(TabID);
}
else if (InName == OutlinerTabName)
{
ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::TopRightTabID);
}
else if (InName == SpacePickerTabName)
{
ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::BottomLeftTabID);
}
else if (InName == DetailsTabName)
{
ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::BottomRightTabID);
}
else if (InName == TweenOverlayName)
{
if(TweenWidgetParent)
{
RemoveAndDestroyTweenOverlay();
}
else
{
CreateAndShowTweenOverlay();
}
}
}
bool FControlRigEditModeToolkit::IsToolkitUIActive(const FName InName) const
{
if (InName == TweenOverlayName)
{
return TweenWidgetParent.IsValid();
}
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
return ModeUILayerPtr->GetTabManager()->FindExistingLiveTab(FTabId(InName)).IsValid();
}
FText FControlRigEditModeToolkit::GetActiveToolDisplayName() const
{
return ModeTools->GetActiveToolName();
}
FText FControlRigEditModeToolkit::GetActiveToolMessage() const
{
return ModeTools->GetActiveToolMessage();
}
TSharedRef<SDockTab> SpawnPoseTab(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
[
SNew(SControlRigBaseListWidget)
];
}
TSharedRef<SDockTab> SpawnSnapperTab(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
[
SNew(SControlRigSnapper)
];
}
TSharedRef<SDockTab> SpawnMotionTrailTab(const FSpawnTabArgs& Args)
{
return SNew(SDockTab)
[
SNew(SMotionTrailOptions)
];
}
TSharedRef<SDockTab> SpawnOutlinerTab(const FSpawnTabArgs& Args, FControlRigEditMode* InEditorMode)
{
return SNew(SDockTab)
[
SNew(SControlRigOutliner, *InEditorMode)
];
}
TSharedRef<SDockTab> SpawnSpacePickerTab(const FSpawnTabArgs& Args, FControlRigEditMode* InEditorMode)
{
return SNew(SDockTab)
[
SNew(SControlRigSpacePicker, *InEditorMode)
];
}
TSharedRef<SDockTab> SpawnDetailsTab(const FSpawnTabArgs& Args, FControlRigEditMode* InEditorMode)
{
return SNew(SDockTab)
[
SNew(SControlRigDetails, *InEditorMode)
];
}
void FControlRigEditModeToolkit::CreateAndShowTweenOverlay()
{
FVector2D NewTweenWidgetLocation = GetDefault<UControlRigEditModeSettings>()->LastInViewportTweenWidgetLocation;
if (NewTweenWidgetLocation.IsZero())
{
const FVector2D ActiveViewportSize = GetToolkitHost()->GetActiveViewportSize();
NewTweenWidgetLocation.X = ActiveViewportSize.X / 2.0f;
NewTweenWidgetLocation.Y = ActiveViewportSize.Y - 100.0f;
}
UpdateTweenWidgetLocation(NewTweenWidgetLocation);
SAssignNew(TweenWidgetParent, SHorizontalBox)
+ SHorizontalBox::Slot()
.FillWidth(1.0f)
.VAlign(VAlign_Top)
.HAlign(HAlign_Left)
.Padding(TAttribute<FMargin>(this, &FControlRigEditModeToolkit::GetTweenWidgetPadding))
[
SAssignNew(TweenWidget, SControlRigTweenWidget)
.InOwningToolkit(SharedThis(this))
];
TryShowTweenOverlay();
}
void FControlRigEditModeToolkit::GetToNextActiveSlider()
{
if (TweenWidgetParent && TweenWidget)
{
TweenWidget->GetToNextActiveSlider();
}
}
bool FControlRigEditModeToolkit::CanChangeAnimSliderTool() const
{
return (TweenWidgetParent && TweenWidget);
}
void FControlRigEditModeToolkit::DragAnimSliderTool(double Val)
{
if (TweenWidgetParent && TweenWidget)
{
TweenWidget->DragAnimSliderTool(Val);
}
}
void FControlRigEditModeToolkit::ResetAnimSlider()
{
if (TweenWidgetParent && TweenWidget)
{
TweenWidget->ResetAnimSlider();
}
}
void FControlRigEditModeToolkit::StartAnimSliderTool()
{
if (TweenWidgetParent && TweenWidget)
{
TweenWidget->StartAnimSliderTool();
}
}
void FControlRigEditModeToolkit::TryShowTweenOverlay()
{
if (TweenWidgetParent)
{
GetToolkitHost()->AddViewportOverlayWidget(TweenWidgetParent.ToSharedRef());
}
}
void FControlRigEditModeToolkit::RemoveAndDestroyTweenOverlay()
{
TryRemoveTweenOverlay();
if (TweenWidgetParent)
{
TweenWidgetParent.Reset();
TweenWidget.Reset();
}
}
void FControlRigEditModeToolkit::TryRemoveTweenOverlay()
{
if (IsHosted() && TweenWidgetParent)
{
if (FLevelEditorModule* LevelEditorModule = FModuleManager::GetModulePtr<FLevelEditorModule>(TEXT("LevelEditor")))
{
if (TSharedPtr<ILevelEditor> LevelEditor = LevelEditorModule->GetFirstLevelEditor())
{
for (TSharedPtr<SLevelViewport> LevelViewport : LevelEditor->GetViewports())
{
if (LevelViewport.IsValid())
{
if (TweenWidgetParent)
{
LevelViewport->RemoveOverlayWidget(TweenWidgetParent.ToSharedRef());
}
}
}
}
}
}
}
void FControlRigEditModeToolkit::UpdateTweenWidgetLocation(const FVector2D InLocation)
{
const FVector2D ActiveViewportSize = GetToolkitHost()->GetActiveViewportSize();
FVector2D ScreenPos = InLocation;
const float EdgeFactor = 0.97f;
const float MinX = ActiveViewportSize.X * (1 - EdgeFactor);
const float MinY = ActiveViewportSize.Y * (1 - EdgeFactor);
const float MaxX = ActiveViewportSize.X * EdgeFactor;
const float MaxY = ActiveViewportSize.Y * EdgeFactor;
const bool bOutside = ScreenPos.X < MinX || ScreenPos.X > MaxX || ScreenPos.Y < MinY || ScreenPos.Y > MaxY;
if (bOutside)
{
// reset the location if it was placed out of bounds
ScreenPos.X = ActiveViewportSize.X / 2.0f;
ScreenPos.Y = ActiveViewportSize.Y - 100.0f;
}
InViewportTweenWidgetLocation = ScreenPos;
UControlRigEditModeSettings* ControlRigEditModeSettings = GetMutableDefault<UControlRigEditModeSettings>();
ControlRigEditModeSettings->LastInViewportTweenWidgetLocation = ScreenPos;
ControlRigEditModeSettings->SaveConfig();
}
FMargin FControlRigEditModeToolkit::GetTweenWidgetPadding() const
{
return FMargin(InViewportTweenWidgetLocation.X, InViewportTweenWidgetLocation.Y, 0, 0);
}
void FControlRigEditModeToolkit::RequestModeUITabs()
{
FModeToolkit::RequestModeUITabs();
if (ModeUILayer.IsValid())
{
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
TSharedRef<FWorkspaceItem> MenuGroup = ModeUILayerPtr->GetModeMenuCategory().ToSharedRef();
FMinorTabConfig DetailTabInfo;
DetailTabInfo.OnSpawnTab = FOnSpawnTab::CreateStatic(&SpawnDetailsTab, &EditMode);
DetailTabInfo.TabLabel = LOCTEXT("ControlRigDetailTab", "Anim Details");
DetailTabInfo.TabTooltip = LOCTEXT("ControlRigDetailTabTooltip", "Show Details For Selected Controls.");
ModeUILayerPtr->SetModePanelInfo(UAssetEditorUISubsystem::BottomRightTabID, DetailTabInfo);
FMinorTabConfig OutlinerTabInfo;
OutlinerTabInfo.OnSpawnTab = FOnSpawnTab::CreateStatic(&SpawnOutlinerTab, &EditMode);
OutlinerTabInfo.TabLabel = LOCTEXT("AnimationOutlinerTab", "Anim Outliner");
OutlinerTabInfo.TabTooltip = LOCTEXT("AnimationOutlinerTabTooltip", "Control Rig Controls");
ModeUILayerPtr->SetModePanelInfo(UAssetEditorUISubsystem::TopRightTabID, OutlinerTabInfo);
/* doesn't work as expected
FMinorTabConfig SpawnSpacePickerTabInfo;
SpawnSpacePickerTabInfo.OnSpawnTab = FOnSpawnTab::CreateStatic(&SpawnSpacePickerTab, &EditMode);
SpawnSpacePickerTabInfo.TabLabel = LOCTEXT("ControlRigSpacePickerTab", "Control Rig Space Picker");
SpawnSpacePickerTabInfo.TabTooltip = LOCTEXT("ControlRigSpacePickerTabTooltip", "Control Rig Space Picker");
ModeUILayerPtr->SetModePanelInfo(UAssetEditorUISubsystem::TopLeftTabID, SpawnSpacePickerTabInfo);
*/
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(SnapperTabName);
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(SnapperTabName, FOnSpawnTab::CreateStatic(&SpawnSnapperTab))
.SetDisplayName(LOCTEXT("ControlRigSnapperTab", "Control Rig Snapper"))
.SetTooltipText(LOCTEXT("ControlRigSnapperTabTooltip", "Snap child objects to a parent object over a set of frames."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("ControlRigEditorStyle"), TEXT("ControlRig.SnapperTool")));
ModeUILayerPtr->GetTabManager()->RegisterDefaultTabWindowSize(SnapperTabName, FVector2D(300, 325));
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(PoseTabName);
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(PoseTabName, FOnSpawnTab::CreateStatic(&SpawnPoseTab))
.SetDisplayName(LOCTEXT("ControlRigPoseTab", "Control Rig Pose"))
.SetTooltipText(LOCTEXT("ControlRigPoseTabTooltip", "Show Poses."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("ControlRigEditorStyle"), TEXT("ControlRig.PoseTool")));
ModeUILayerPtr->GetTabManager()->RegisterDefaultTabWindowSize(PoseTabName, FVector2D(675, 625));
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(MotionTrailTabName);
ModeUILayerPtr->GetTabManager()->RegisterTabSpawner(MotionTrailTabName, FOnSpawnTab::CreateStatic(&SpawnMotionTrailTab))
.SetDisplayName(LOCTEXT("MotionTrailTab", "Motion Trail"))
.SetTooltipText(LOCTEXT("MotionTrailTabTooltip", "Display motion trails for animated objects."))
.SetGroup(MenuGroup)
.SetIcon(FSlateIcon(TEXT("ControlRigEditorStyle"), TEXT("ControlRig.EditableMotionTrails")));
ModeUILayerPtr->GetTabManager()->RegisterDefaultTabWindowSize(MotionTrailTabName, FVector2D(425, 575));
ModeUILayer.Pin()->ToolkitHostShutdownUI().BindSP(this, &FControlRigEditModeToolkit::UnregisterAndRemoveFloatingTabs);
}
};
void FControlRigEditModeToolkit::InvokeUI()
{
FModeToolkit::InvokeUI();
if (ModeUILayer.IsValid())
{
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::TopRightTabID);
// doesn't work as expected todo ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::TopLeftTabID);
ModeUILayerPtr->GetTabManager()->TryInvokeTab(UAssetEditorUISubsystem::BottomRightTabID);
}
}
void FControlRigEditModeToolkit::UnregisterAndRemoveFloatingTabs()
{
if (FSlateApplication::IsInitialized())
{
RemoveAndDestroyTweenOverlay();
if (ModeUILayer.IsValid())
{
TSharedPtr<FAssetEditorModeUILayer> ModeUILayerPtr = ModeUILayer.Pin();
TSharedPtr<SDockTab> MotionTrailTab = ModeUILayerPtr->GetTabManager()->FindExistingLiveTab(FTabId(MotionTrailTabName));
if (MotionTrailTab)
{
MotionTrailTab->RequestCloseTab();
}
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(MotionTrailTabName);
TSharedPtr<SDockTab> SnapperTab = ModeUILayerPtr->GetTabManager()->FindExistingLiveTab(FTabId(SnapperTabName));
if (SnapperTab)
{
SnapperTab->RequestCloseTab();
}
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(SnapperTabName);
TSharedPtr<SDockTab> PoseTab = ModeUILayerPtr->GetTabManager()->FindExistingLiveTab(FTabId(PoseTabName));
if (PoseTab)
{
PoseTab->RequestCloseTab();
}
ModeUILayerPtr->GetTabManager()->UnregisterTabSpawner(PoseTabName);
}
}
}
#undef LOCTEXT_NAMESPACE
Two Chinese posts: