How do I reference the currently open asset?

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?

1 Like

https://docs.unrealengine.com/latest/INT/API/Editor/UnrealEd/Toolkits/FAssetEditorManager/OnAssetEditorOpened/index.html

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 :smiley: 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);
}
2 Likes