I’m building a plugin which lives in the menubar of the StaticMeshEditor and must do something with the currently open Static Mesh (UStaticMesh
). How do I get a reference to this object from the code that implements my plugin action?
Since you doing a plugin I assume thats enough information. If not leave a comment.
Thank you. Unfortunately that doesn’t give me the final piece of the puzzle. Given a reference to the current StaticMeshEditor, I can get a reference to the StaticMesh. But how do I tell from the toolbar button’s UI action which StaticMeshEditor launched it, especially if multiple StaticMeshEditors are open at the same time?
OnAssetEditorOpened you get the Asset I belive. From there you can call FAssetEditorManager::Get().FindEditorsForAsset(Asset); to get the Editor you can Cast it to IStaticMeshEditor.
Now you should have those 2 refferences on Hand, good start so far. Next step is to extend the Menu/Toolbar or whatever you like (Extenders Menu/ToolbarBuilder etc.). There you get the chance to Bind a delegate and you simply pass the refference(s) to the Binding. And thats more or less it you got a callback now.
If I missed something or messed up sry in a hurry lemme know if you get it to work.
EDIT: I think I figured it out. I will write it up.
Thank you. I’m a little further along thanks to your help. Unfortunately, when I open the Static Mesh Editor, it blows up with an invalid TSharedPtr<FUICommandInfo>
. I think I’m wiring up the action wrong in Builder.AddToolBarButton
, though I’m not sure the right way to do it.
void FMyModule::HandleAssetOpenedInEditor(UObject * Asset, IAssetEditorInstance *Editor)
{
auto Mesh = Cast<UStaticMesh>(Asset);
// This function runs on every opened asset, so the asset we have *might* not be a Static Mesh
if (!Mesh)
return;
TSharedPtr<FExtender> ToolbarExtender = MakeShared<FExtender>();
ToolbarExtender->AddToolBarExtension("UV", EExtensionHook::After, PluginCommands, FToolBarExtensionDelegate::CreateRaw(this, &FMyModule::AddStaticMeshEditorToolbarExtension, MeshEditor));
MeshEditor->AddToolbarExtender(ToolbarExtender);
}
void FMyModule::AddStaticMeshEditorToolbarExtension(FToolBarBuilder& Builder, IStaticMeshEditor *MeshEditor)
{
TSharedRef<IStaticMeshEditor> MESP = MakeShareable(MeshEditor);
// todo: I think there is something wrong with this line:
Builder.AddToolBarButton(FExecuteAction::CreateRaw(this, &FMyModule::PluginButtonClickedFromStaticMeshEditor, MESP));
}
void FMyModule::PluginButtonClickedFromStaticMeshEditor(TSharedRef<IStaticMeshEditor> MeshEditor){
// do some stuff...
}
partial stack trace:
[Inline Frame] UE4Editor-Slate.dll!FWindowsPlatformMisc::DebugBreak() Line 57 C++ Symbols loaded.
> [Inline Frame] UE4Editor-Slate.dll!TSharedPtr<FUICommandInfo const ,0>::operator->() Line 835 C++ Symbols loaded.
UE4Editor-Slate.dll!SToolBarButtonBlock::BuildMultiBlockWidget(const ISlateStyle * StyleSet, const FName & StyleName) Line 144 C++ Symbols loaded.
UE4Editor-Slate.dll!FMultiBlock::MakeWidget(TSharedRef<SMultiBoxWidget,0> InOwnerMultiBoxWidget, EMultiBlockLocation::Type InLocation, bool bSectionContainsIcons) Line 155 C++ Symbols loaded.
UE4Editor-Slate.dll!SMultiBoxWidget::AddBlockWidget(const FMultiBlock & Block, TSharedPtr<SHorizontalBox,0> HorizontalBox, TSharedPtr<SVerticalBox,0> VerticalBox, EMultiBlockLocation::Type InLocation, bool bSectionContainsIcons) Line 472 C++ Symbols loaded.
UE4Editor-Slate.dll!SMultiBoxWidget::BuildMultiBoxWidget() Line 672 C++ Symbols loaded.
UE4Editor-Slate.dll!FMultiBox::MakeWidget(bool bSearchable, TBaseDelegate<void,TSharedRef<FMultiBox,0> const &,TSharedRef<SMultiBoxWidget,0> const &> * InMakeMultiBoxBuilderOverride) Line 291 C++ Symbols loaded.
UE4Editor-Slate.dll!FMultiBoxBuilder::MakeWidget(TBaseDelegate<void,TSharedRef<FMultiBox,0> const &,TSharedRef<SMultiBoxWidget,0> const &> * InMakeMultiBoxBuilderOverride) Line 88 C++ Symbols loaded.
UE4Editor-UnrealEd.dll!FAssetEditorToolkit::GenerateToolbar() Line 997 C++ Symbols loaded.
UE4Editor-UnrealEd.dll!FAssetEditorToolkit::RegenerateMenusAndToolbars() Line 1047 C++ Symbols loaded.
UE4Editor-StaticMeshEditor.dll!FStaticMeshEditor::InitStaticMeshEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost,0> & InitToolkitHost, UStaticMesh * ObjectToEdit) Line 208 C++ Symbols loaded.
UE4Editor-StaticMeshEditor.dll!FStaticMeshEditorModule::CreateStaticMeshEditor(const EToolkitMode::Type Mode, const TSharedPtr<IToolkitHost,0> & InitToolkitHost, UStaticMesh * StaticMesh) Line 49 C++ Symbols loaded.
The tricky bit was to create the FUICommandList
inside HandleAssetOpenedInEditor
. Thank you for your help!
void FMyModule::StartupModule()
{
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
FMyStyle::Initialize();
FMyStyle::ReloadTextures();
FMyCommands::Register();
IStaticMeshEditorModule *StaticMeshEditorModule = &FModuleManager::LoadModuleChecked<IStaticMeshEditorModule>("StaticMeshEditor");
{
FAssetEditorManager::Get().OnAssetOpenedInEditor().AddRaw(this, &FMyModule::HandleAssetOpenedInEditor);
}
}
void FMyModule::HandleAssetOpenedInEditor(UObject * Asset, IAssetEditorInstance *Editor)
{
// use this instead of HandleAssetEditorOpened because it has access to the editor
auto Mesh = Cast<UStaticMesh>(Asset);
// This function runs on every opened asset, so the asset we have *might* not be a Static Mesh
if (!Mesh)
return;
check(Editor->GetEditorName() == "StaticMeshEditor"); // i.e. == FStaticMeshEditor::GetToolkitFName()
auto MeshEditor = StaticCast<IStaticMeshEditor *>(Editor); // This cast is not safe, which is why we check GetEditorName
{
auto StaticMeshEditorCommands = MakeShared<FUICommandList>();
StaticMeshEditorCommands->MapAction(
FMyCommands::Get().DoMagic,
FExecuteAction::CreateRaw(this, &FMyModule::PluginButtonClickedFromStaticMeshEditor, MeshEditor),
FCanExecuteAction());
// Extend the UV section of the toolbar:
auto ToolbarExtender = MakeShared<FExtender>();
ToolbarExtender->AddToolBarExtension("UV", EExtensionHook::After, StaticMeshEditorCommands, FToolBarExtensionDelegate::CreateRaw(this, &FMyModule::AddStaticMeshEditorToolbarExtension));
MeshEditor->AddToolbarExtender(ToolbarExtender);
}
}
void FMyModule::AddStaticMeshEditorToolbarExtension(FToolBarBuilder& Builder)
{
Builder.AddToolBarButton(FMyCommands::Get().DoMagic);
}