Files
UnrealEngine/Engine/Plugins/Runtime/Metasound/Source/MetasoundEditor/Private/MetasoundAssetDefinitions.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

820 lines
33 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MetasoundAssetDefinitions.h"
#include "AssetDefinitionRegistry.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "AudioEditorSettings.h"
#include "Components/AudioComponent.h"
#include "ContentBrowserMenuContexts.h"
#include "ContentBrowserModule.h"
#include "Editor/EditorPerProjectUserSettings.h"
#include "FileHelpers.h"
#include "IAssetTools.h"
#include "IContentBrowserSingleton.h"
#include "ISourceControlModule.h"
#include "Metasound.h"
#include "MetasoundAssetBase.h"
#include "MetasoundAssetManager.h"
#include "MetasoundAssetSubsystem.h"
#include "MetasoundBuilderSubsystem.h"
#include "MetasoundDocumentInterface.h"
#include "MetasoundEditor.h"
#include "MetasoundEditorGraphBuilder.h"
#include "MetasoundEditorModule.h"
#include "MetasoundEditorSettings.h"
#include "MetasoundEditorSubsystem.h"
#include "MetasoundFactory.h"
#include "MetasoundSource.h"
#include "MetasoundUObjectRegistry.h"
#include "Misc/AssetRegistryInterface.h"
#include "Modules/ModuleManager.h"
#include "ObjectEditorUtils.h"
#include "Styling/AppStyle.h"
#include "Styling/CoreStyle.h"
#include "Styling/ISlateStyle.h"
#include "Styling/SlateStyleRegistry.h"
#include "Styling/SlateTypes.h"
#include "ToolMenus.h"
#include "ToolMenuSection.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/SOverlay.h"
#include UE_INLINE_GENERATED_CPP_BY_NAME(MetasoundAssetDefinitions)
#define LOCTEXT_NAMESPACE "MetaSoundEditor"
namespace Metasound::Editor
{
namespace AssetDefinitionsPrivate
{
const FSlateBrush* GetClassBrush(const FAssetData& InAssetData, FName InClassName, bool bIsThumbnail = false)
{
using namespace Frontend;
const FMetaSoundAssetClassInfo ClassInfo(InAssetData);
if (!ClassInfo.bIsValid)
{
UE_LOG(LogMetaSound, VeryVerbose,
TEXT("ClassBrush for asset '%s' may return incorrect preset icon. Asset requires reserialization."),
*InAssetData.GetObjectPathString());
}
FString BrushName = FString::Printf(TEXT("MetasoundEditor.%s"), *InClassName.ToString());
if (ClassInfo.DocInfo.bIsPreset)
{
BrushName += TEXT(".Preset");
}
BrushName += bIsThumbnail ? TEXT(".Thumbnail") : TEXT(".Icon");
return &Metasound::Editor::Style::GetSlateBrushSafe(FName(*BrushName));
}
void ExecuteBrowseToPresetParentAsset(const FToolMenuContext& InContext)
{
using namespace Metasound;
if (UObject* MetaSound = UContentBrowserAssetContextMenuContext::LoadSingleSelectedAsset<UObject>(InContext))
{
if (UAssetEditorSubsystem* AssetSubsystem = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>())
{
FMetaSoundFrontendDocumentBuilder& DocumentBuilder = Frontend::IDocumentBuilderRegistry::GetChecked().FindOrBeginBuilding(MetaSound);
if (const FMetasoundAssetBase* MetaSoundAsset = DocumentBuilder.GetReferencedPresetAsset())
{
if (GEditor)
{
GEditor->SyncBrowserToObjects({ MetaSoundAsset->GetOwningAsset() });
}
}
}
}
}
void ExecuteOpenPresetParentAsset(const FToolMenuContext& InContext)
{
using namespace Metasound;
if (UObject* MetaSound = UContentBrowserAssetContextMenuContext::LoadSingleSelectedAsset<UObject>(InContext))
{
if (UAssetEditorSubsystem* AssetSubsystem = GEditor->GetEditorSubsystem<UAssetEditorSubsystem>())
{
FMetaSoundFrontendDocumentBuilder& DocumentBuilder = Frontend::IDocumentBuilderRegistry::GetChecked().FindOrBeginBuilding(MetaSound);
if (const FMetasoundAssetBase* MetaSoundAsset = DocumentBuilder.GetReferencedPresetAsset())
{
AssetSubsystem->OpenEditorForAsset(MetaSoundAsset->GetOwningAsset());
}
}
}
}
template <typename TClass, typename TFactoryClass>
void ExecuteCreateMetaSoundPreset(const FToolMenuContext& MenuContext)
{
if (const UContentBrowserAssetContextMenuContext* Context = UContentBrowserAssetContextMenuContext::FindContextWithAssets(MenuContext))
{
using namespace Metasound::Editor;
TArray<UObject*> ObjectsToSync;
for (TClass* ReferencedMetaSound : Context->LoadSelectedObjects<TClass>())
{
FString PackagePath;
FString AssetName;
UObject* NewMetaSound = nullptr;
IAssetTools::Get().CreateUniqueAssetName(ReferencedMetaSound->GetOutermost()->GetName(), TEXT("_Preset"), PackagePath, AssetName);
Metasound::Editor::IMetasoundEditorModule& MetaSoundEditorModule = FModuleManager::GetModuleChecked<Metasound::Editor::IMetasoundEditorModule>("MetaSoundEditor");
if (MetaSoundEditorModule.IsRestrictedMode())
{
// Cannot duplicate cooked assets in restricted mode, so create new object and copy over properties
// for sources in InitAsset below. Since copying properties is done manually,
// SetSoundWaveSettingsFromTemplate may need to be updated with properties to be copied.
UMetaSoundBaseFactory* Factory = NewObject<TFactoryClass>();
Factory->ReferencedMetaSoundObject = ReferencedMetaSound;
NewMetaSound = IAssetTools::Get().CreateAssetWithDialog(AssetName, FPackageName::GetLongPackagePath(PackagePath), Factory->GetSupportedClass(), Factory);
}
else
{
// Duplicate asset to preserve properties from referenced asset (ex. quality settings, soundwave properties)
NewMetaSound = IAssetTools::Get().DuplicateAssetWithDialogAndTitle(AssetName, FPackageName::GetLongPackagePath(PackagePath), ReferencedMetaSound, LOCTEXT("CreateMetaSoundPresetTitle", "Create MetaSound Preset"));
}
if (NewMetaSound)
{
UMetaSoundEditorSubsystem::GetChecked().InitAsset(*NewMetaSound, ReferencedMetaSound, /*bClearDocument=*/true);
FGraphBuilder::RegisterGraphWithFrontend(*NewMetaSound);
ObjectsToSync.Add(NewMetaSound);
}
else
{
UE_LOG(LogMetaSound, Display, TEXT("Error creating new asset when creating preset '%s' or asset creation was canceled by user."), *AssetName);
}
}
// Sync content browser to newly created valid assets
// Assets can be invalid if multiple assets are created with the same name
// then force overwritten within the same operation
ObjectsToSync.RemoveAllSwap([](const UObject* InObject)
{
return !InObject || !InObject->IsValidLowLevelFast();
});
if (ObjectsToSync.Num() > 0)
{
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
ContentBrowserModule.Get().SyncBrowserToAssets(ObjectsToSync);
// Save happened in Create/Duplicate asset calls above but
// need to save again after register graph with frontend (which applies preset transform)
for (UObject* InObject : ObjectsToSync)
{
if (ISourceControlModule::Get().IsEnabled())
{
constexpr bool bCheckDirty = false;
constexpr bool bPromptToSave = false;
TArray<UPackage*> OutermostPackagesToSave;
OutermostPackagesToSave.Add(InObject->GetOutermost());
FEditorFileUtils::PromptForCheckoutAndSave(OutermostPackagesToSave, bCheckDirty, bPromptToSave);
}
};
}
}
}
bool IsPreset(const FToolMenuContext& InContext)
{
using namespace Metasound::Frontend;
if (const UContentBrowserAssetContextMenuContext* CBContext = UContentBrowserAssetContextMenuContext::FindContextWithAssets(InContext))
{
if (CBContext->SelectedAssets.Num() == 1)
{
return FMetaSoundAssetClassInfo(CBContext->SelectedAssets.Last()).DocInfo.bIsPreset;
}
}
return false;
}
void AddMetaSoundActions(const FSlateIcon& AssetIcon, const UClass& Class, FToolUIAction CreatePresetAction)
{
const FText ClassName = Class.GetDisplayNameText();
const UAssetDefinition* AssetDefinition = UAssetDefinitionRegistry::Get()->GetAssetDefinitionForClass(&Class);
FToolMenuSection* Section = CastChecked<UAssetDefinition_SoundAssetBase>(AssetDefinition)->FindSoundContextMenuSection("MetaSound");
check(Section);
Section->AddDynamicEntry(NAME_None, FNewToolMenuSectionDelegate::CreateLambda([CreateAction = MoveTemp(CreatePresetAction), ClassName, AssetIcon](FToolMenuSection& InSection)
{
using namespace Metasound::Editor;
{
const TAttribute<FText> Label = FText::Format(LOCTEXT("MetaSound_CreatePreset", "Create Preset..."), ClassName);
const TAttribute<FText> ToolTip = FText::Format(LOCTEXT("MetaSound_CreatePresetToolTipFormat", "Creates a {0} Preset using the selected MetaSound as a reference (parent)."), ClassName);
InSection.AddMenuEntry("MetaSound_CreatePreset", Label, ToolTip, AssetIcon, CreateAction);
}
{
const TAttribute<FText> Label = LOCTEXT("MetaSound_BrowseToPresetParentFormat", "Browse To Preset Parent");
const TAttribute<FText> ToolTip = FText::Format(LOCTEXT("MetaSound_BrowseToPresetParentToolTipFormat", "Browses to the selected {0} preset's referenced parent asset in the content browser."), ClassName);
const FSlateIcon FindInContentBrowserIcon(FAppStyle::GetAppStyleSetName(), "SystemWideCommands.FindInContentBrowser");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&AssetDefinitionsPrivate::ExecuteBrowseToPresetParentAsset);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&AssetDefinitionsPrivate::IsPreset);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateStatic(&AssetDefinitionsPrivate::IsPreset);
InSection.AddMenuEntry("MetaSoundSource_BrowseToPresetParent", Label, ToolTip, FindInContentBrowserIcon, UIAction);
}
IMetasoundEditorModule& EditorModule = FModuleManager::GetModuleChecked<Metasound::Editor::IMetasoundEditorModule>("MetaSoundEditor");
if (!EditorModule.IsRestrictedMode())
{
const TAttribute<FText> Label = LOCTEXT("MetaSound_EditPresetParentFormat", "Edit Preset Parent...");
const TAttribute<FText> ToolTip = FText::Format(LOCTEXT("MetaSound_OpenPresetParentToolTipFormat", "Opens the selected {0} preset's parent MetaSound asset."), ClassName);
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&AssetDefinitionsPrivate::ExecuteOpenPresetParentAsset);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&AssetDefinitionsPrivate::IsPreset);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateStatic(&AssetDefinitionsPrivate::IsPreset);
InSection.AddMenuEntry("MetaSoundSource_OpenToPresetParent", Label, ToolTip, FSlateIcon(FAppStyle::GetAppStyleSetName(), "Icons.Edit"), UIAction);
}
}));
}
void AddMetaSoundContextMenuAction(const UClass& MetaSoundClass, TArray<FToolMenuSection*>& OutSections)
{
const UAudioEditorSettings* EdSettings = GetDefault<UAudioEditorSettings>();
check(EdSettings);
auto GetSection = [&](FName SectionName) -> FToolMenuSection*
{
auto MatchesName = [&SectionName](const FToolMenuSection* Section)
{
return Section->Name == SectionName;
};
if (FToolMenuSection** SectionPtr = OutSections.FindByPredicate(MatchesName))
{
check(*SectionPtr);
return *SectionPtr;
}
return nullptr;
};
FToolMenuSection* PlaybackSection = GetSection("Playback");
FToolMenuSection* SoundSection = GetSection("Sound");
UToolMenu* Menu = UE::ContentBrowser::ExtendToolMenu_AssetContextMenu(&MetaSoundClass);
check(Menu);
const UEnum* EnumClass = StaticEnum<EToolMenuInsertType>();
check(EnumClass);
const EToolMenuInsertType InsertType = static_cast<EToolMenuInsertType>(EnumClass->GetValueByName(EdSettings->MenuPosition));
FToolMenuSection& MetaSoundSection = Menu->FindOrAddSection("MetaSound");
MetaSoundSection.Label = MetaSoundClass.GetDisplayNameText();
if (SoundSection)
{
if (PlaybackSection)
{
MetaSoundSection.InsertPosition = FToolMenuInsert(
PlaybackSection->Name,
InsertType == EToolMenuInsertType::Last
? EToolMenuInsertType::Before
: EToolMenuInsertType::After);
SoundSection->InsertPosition = FToolMenuInsert(
MetaSoundSection.Name,
InsertType == EToolMenuInsertType::Last
? EToolMenuInsertType::Before
: EToolMenuInsertType::After);
}
else
{
MetaSoundSection.InsertPosition = FToolMenuInsert({ }, InsertType);
SoundSection->InsertPosition = FToolMenuInsert(
MetaSoundSection.Name,
InsertType == EToolMenuInsertType::Last
? EToolMenuInsertType::Before
: EToolMenuInsertType::After);
}
}
else
{
MetaSoundSection.InsertPosition = FToolMenuInsert({ }, InsertType);
}
OutSections.Add(&MetaSoundSection);
}
} // namespace AssetDefinitionsPrivate
} // namespace Metasound::Editor
FLinearColor UAssetDefinition_MetaSoundPatch::GetAssetColor() const
{
if (const ISlateStyle* MetasoundStyle = FSlateStyleRegistry::FindSlateStyle("MetaSoundStyle"))
{
return MetasoundStyle->GetColor("MetaSoundPatch.Color").ToFColorSRGB();
}
return FColor::White;
}
TSoftClassPtr<UObject> UAssetDefinition_MetaSoundPatch::GetAssetClass() const
{
return UMetaSoundPatch::StaticClass();
}
TConstArrayView<FAssetCategoryPath> UAssetDefinition_MetaSoundPatch::GetAssetCategories() const
{
static const auto Pinned_Categories = { EAssetCategoryPaths::Audio };
static const auto Categories = { EAssetCategoryPaths::Audio / LOCTEXT("AssetSoundMetaSoundsSubMenu", "MetaSounds") };
if (GetDefault<UMetasoundEditorSettings>()->bPinMetaSoundPatchInAssetMenu)
{
return Pinned_Categories;
}
return Categories;
}
EAssetCommandResult UAssetDefinition_MetaSoundPatch::OpenAssets(const FAssetOpenArgs& OpenArgs) const
{
Metasound::Editor::IMetasoundEditorModule& MetaSoundEditorModule = FModuleManager::GetModuleChecked<Metasound::Editor::IMetasoundEditorModule>("MetaSoundEditor");
if (!MetaSoundEditorModule.IsRestrictedMode())
{
for (UMetaSoundPatch* Metasound : OpenArgs.LoadObjects<UMetaSoundPatch>())
{
TSharedRef<Metasound::Editor::FEditor> NewEditor = MakeShared<Metasound::Editor::FEditor>();
NewEditor->InitMetasoundEditor(OpenArgs.GetToolkitMode(), OpenArgs.ToolkitHost, Metasound);
}
}
return EAssetCommandResult::Handled;
}
const FSlateBrush* UAssetDefinition_MetaSoundPatch::GetThumbnailBrush(const FAssetData& InAssetData, const FName InClassName) const
{
using namespace Metasound::Editor;
constexpr bool bIsThumbnail = true;
return AssetDefinitionsPrivate::GetClassBrush(InAssetData, InClassName, bIsThumbnail);
}
const FSlateBrush* UAssetDefinition_MetaSoundPatch::GetIconBrush(const FAssetData& InAssetData, const FName InClassName) const
{
using namespace Metasound::Editor;
return AssetDefinitionsPrivate::GetClassBrush(InAssetData, InClassName);
}
TArray<FToolMenuSection*> UAssetDefinition_MetaSoundPatch::RebuildSoundContextMenuSections() const
{
using namespace Metasound::Editor;
TArray<FToolMenuSection*> Sections = Super::RebuildSoundContextMenuSections();
if (const UClass* MetaSoundClass = GetAssetClass().Get())
{
AssetDefinitionsPrivate::AddMetaSoundContextMenuAction(*MetaSoundClass, Sections);
}
return Sections;
}
FLinearColor UAssetDefinition_MetaSoundSource::GetAssetColor() const
{
if (const ISlateStyle* MetasoundStyle = FSlateStyleRegistry::FindSlateStyle("MetaSoundStyle"))
{
return MetasoundStyle->GetColor("MetaSoundSource.Color").ToFColorSRGB();
}
return FColor::White;
}
TSoftClassPtr<UObject> UAssetDefinition_MetaSoundSource::GetAssetClass() const
{
return UMetaSoundSource::StaticClass();
}
TConstArrayView<FAssetCategoryPath> UAssetDefinition_MetaSoundSource::GetAssetCategories() const
{
static const auto Pinned_Categories = { EAssetCategoryPaths::Audio };
static const auto Categories = { EAssetCategoryPaths::Audio / LOCTEXT("AssetSoundMetaSoundSourceSubMenu", "MetaSounds") };
if (GetDefault<UMetasoundEditorSettings>()->bPinMetaSoundSourceInAssetMenu)
{
return Pinned_Categories;
}
return Categories;
}
EAssetCommandResult UAssetDefinition_MetaSoundSource::OpenAssets(const FAssetOpenArgs& OpenArgs) const
{
using namespace Metasound;
for (const FAssetData& AssetData : OpenArgs.Assets)
{
const UClass* AssetClass = AssetData.GetClass();
if (AssetClass && IMetasoundUObjectRegistry::Get().IsRegisteredClass(*AssetClass))
{
Engine::FMetaSoundAssetManager& AssetManager = Engine::FMetaSoundAssetManager::GetChecked();
TWeakPtr<IToolkitHost> ToolkitHost = OpenArgs.ToolkitHost;
const bool bHostNull = !OpenArgs.ToolkitHost.IsValid();
AssetManager.AddOrLoadAndUpdateFromObjectAsync(AssetData, [ToolkitMode = OpenArgs.GetToolkitMode(), bHostNull, ToolkitHost](FMetaSoundAssetKey, UObject& MetaSoundObject)
{
TSharedPtr<IToolkitHost> HostPtr = ToolkitHost.Pin();
if (bHostNull || HostPtr)
{
Editor::IMetasoundEditorModule* EditorModule = FModuleManager::GetModulePtr<Editor::IMetasoundEditorModule>("MetaSoundEditor");
if (EditorModule)
{
if (EditorModule->IsRestrictedMode())
{
TScriptInterface<const IMetaSoundDocumentInterface> DocInterface(&MetaSoundObject);
check(DocInterface.GetObject());
const Frontend::FMetaSoundAssetClassInfo ClassInfo(*DocInterface.GetInterface());
if (!ClassInfo.bIsValid || !ClassInfo.DocInfo.bIsPreset)
{
return;
}
}
TSharedRef<Editor::FEditor> NewEditor = MakeShared<Editor::FEditor>();
NewEditor->InitMetasoundEditor(ToolkitMode, HostPtr, &MetaSoundObject);
}
}
});
}
}
return EAssetCommandResult::Handled;
}
const FSlateBrush* UAssetDefinition_MetaSoundSource::GetThumbnailBrush(const FAssetData& InAssetData, const FName InClassName) const
{
using namespace Metasound::Editor;
constexpr bool bIsThumbnail = true;
return AssetDefinitionsPrivate::GetClassBrush(InAssetData, InClassName, bIsThumbnail);
}
const FSlateBrush* UAssetDefinition_MetaSoundSource::GetIconBrush(const FAssetData& InAssetData, const FName InClassName) const
{
using namespace Metasound::Editor;
return AssetDefinitionsPrivate::GetClassBrush(InAssetData, InClassName);
}
void UAssetDefinition_MetaSoundSource::ExecutePlaySound(const FToolMenuContext& InContext)
{
if (UMetaSoundSource* MetaSoundSource = UContentBrowserAssetContextMenuContext::LoadSingleSelectedAsset<UMetaSoundSource>(InContext))
{
// If editor is open, call into it to play to start all visualization requirements therein
// specific to auditioning MetaSounds (ex. priming audio bus used for volume metering, playtime
// widget, etc.)
TSharedPtr<Metasound::Editor::FEditor> Editor = Metasound::Editor::FGraphBuilder::GetEditorForMetasound(*MetaSoundSource);
if (Editor.IsValid())
{
Editor->Play();
return;
}
Metasound::Editor::FGraphBuilder::FGraphBuilder::RegisterGraphWithFrontend(*MetaSoundSource);
UAssetDefinition_SoundBase::ExecutePlaySound(InContext);
}
}
void UAssetDefinition_MetaSoundSource::ExecuteStopSound(const FToolMenuContext& InContext)
{
if (UMetaSoundSource* MetaSoundSource = UContentBrowserAssetContextMenuContext::LoadSingleSelectedAsset<UMetaSoundSource>(InContext))
{
TSharedPtr<Metasound::Editor::FEditor> Editor = Metasound::Editor::FGraphBuilder::GetEditorForMetasound(*MetaSoundSource);
if (Editor.IsValid())
{
Editor->Stop();
return;
}
UAssetDefinition_SoundBase::ExecuteStopSound(InContext);
}
}
bool UAssetDefinition_MetaSoundSource::CanExecutePlayCommand(const FToolMenuContext& InContext)
{
return UAssetDefinition_SoundBase::CanExecutePlayCommand(InContext);
}
ECheckBoxState UAssetDefinition_MetaSoundSource::IsActionCheckedMute(const FToolMenuContext& InContext)
{
return UAssetDefinition_SoundBase::IsActionCheckedMute(InContext);
}
ECheckBoxState UAssetDefinition_MetaSoundSource::IsActionCheckedSolo(const FToolMenuContext& InContext)
{
return UAssetDefinition_SoundBase::IsActionCheckedSolo(InContext);
}
void UAssetDefinition_MetaSoundSource::ExecuteMuteSound(const FToolMenuContext& InContext)
{
UAssetDefinition_SoundBase::ExecuteMuteSound(InContext);
}
void UAssetDefinition_MetaSoundSource::ExecuteSoloSound(const FToolMenuContext& InContext)
{
UAssetDefinition_SoundBase::ExecuteSoloSound(InContext);
}
bool UAssetDefinition_MetaSoundSource::CanExecuteMuteCommand(const FToolMenuContext& InContext)
{
return UAssetDefinition_SoundBase::CanExecuteMuteCommand(InContext);
}
bool UAssetDefinition_MetaSoundSource::CanExecuteSoloCommand(const FToolMenuContext& InContext)
{
return UAssetDefinition_SoundBase::CanExecuteSoloCommand(InContext);
}
TSharedPtr<SWidget> UAssetDefinition_MetaSoundSource::GetThumbnailOverlay(const FAssetData& InAssetData) const
{
auto OnClickedLambdaOverride = [InAssetData]() -> FReply
{
TSharedPtr<Metasound::Editor::FEditor> Editor = Metasound::Editor::FGraphBuilder::GetEditorForMetasound(*InAssetData.GetAsset());
if (UE::AudioEditor::IsSoundPlaying(InAssetData))
{
if (Editor.IsValid())
{
Editor->Stop();
}
else
{
UE::AudioEditor::StopSound();
}
}
else
{
if (Editor.IsValid())
{
Editor->Play();
}
else
{
// Load and play sound
UE::AudioEditor::PlaySound(Cast<USoundBase>(InAssetData.GetAsset()));
}
}
return FReply::Handled();
};
return UAssetDefinition_SoundBase::GetSoundBaseThumbnailOverlay(InAssetData, MoveTemp(OnClickedLambdaOverride));
}
bool UAssetDefinition_MetaSoundSource::GetThumbnailActionOverlay(const FAssetData& InAssetData, FAssetActionThumbnailOverlayInfo& OutActionOverlayInfo) const
{
auto OnGetDisplayBrushLambda = [InAssetData]() -> const FSlateBrush*
{
if (UE::AudioEditor::IsSoundPlaying(InAssetData))
{
return FAppStyle::GetBrush("ContentBrowser.AssetAction.StopIcon");
}
return FAppStyle::GetBrush("ContentBrowser.AssetAction.PlayIcon");
};
OutActionOverlayInfo.ActionImageWidget = SNew(SImage).Image_Lambda(OnGetDisplayBrushLambda);
auto OnToolTipTextLambda = [InAssetData]() -> FText
{
if (UE::AudioEditor::IsSoundPlaying(InAssetData))
{
return LOCTEXT("Thumbnail_StopSoundToolTip", "Stop selected sound");
}
return LOCTEXT("Thumbnail_PlaySoundToolTip", "Play selected sound");
};
auto OnClickedLambda = [InAssetData]() -> FReply
{
TSharedPtr<Metasound::Editor::FEditor> Editor = Metasound::Editor::FGraphBuilder::GetEditorForMetasound(*InAssetData.GetAsset());
if (UE::AudioEditor::IsSoundPlaying(InAssetData))
{
if (Editor.IsValid())
{
Editor->Stop();
}
else
{
UE::AudioEditor::StopSound();
}
}
else
{
if (Editor.IsValid())
{
Editor->Play();
}
else
{
// Load and play sound
UE::AudioEditor::PlaySound(Cast<USoundBase>(InAssetData.GetAsset()));
}
}
return FReply::Handled();
};
OutActionOverlayInfo.ActionButtonArgs = SButton::FArguments()
.ToolTipText_Lambda(OnToolTipTextLambda)
.OnClicked_Lambda(OnClickedLambda);
return true;
}
EAssetCommandResult UAssetDefinition_MetaSoundSource::ActivateAssets(const FAssetActivateArgs& ActivateArgs) const
{
if (ActivateArgs.ActivationMethod == EAssetActivationMethod::Previewed)
{
if (UMetaSoundSource* MetaSoundSource = ActivateArgs.LoadFirstValid<UMetaSoundSource>())
{
TSharedPtr<Metasound::Editor::FEditor> Editor = Metasound::Editor::FGraphBuilder::GetEditorForMetasound(*MetaSoundSource);
UAudioComponent* PreviewComp = GEditor->GetPreviewAudioComponent();
// If the editor is open, we need to stop or start the editor so it can light up while previewing it in the CB
if (Editor.IsValid())
{
if (PreviewComp && PreviewComp->IsPlaying())
{
if (!MetaSoundSource || PreviewComp->Sound == MetaSoundSource)
{
Editor->Stop();
}
}
else
{
Editor->Play();
}
return EAssetCommandResult::Handled;
}
else
{
return UAssetDefinition_SoundBase::ActivateSoundBase(ActivateArgs);
}
}
}
return EAssetCommandResult::Unhandled;
}
void UAssetDefinition_MetaSoundSource::GetAssetActionButtonExtensions(const FAssetData& InAssetData, TArray<FAssetButtonActionExtension>& OutExtensions) const
{
UAssetDefinition_SoundBase::GetSoundBaseAssetActionButtonExtensions(InAssetData, OutExtensions);
}
TArray<FToolMenuSection*> UAssetDefinition_MetaSoundSource::RebuildSoundContextMenuSections() const
{
using namespace Metasound::Editor;
TArray<FToolMenuSection*> Sections = Super::RebuildSoundContextMenuSections();
if (const UClass* MetaSoundClass = GetAssetClass().Get())
{
AssetDefinitionsPrivate::AddMetaSoundContextMenuAction(*MetaSoundClass, Sections);
}
return Sections;
}
namespace MenuExtension_MetaSoundSourceTemplate
{
static FDelayedAutoRegisterHelper DelayedAutoRegister(EDelayedRegisterRunPhase::EndOfEngineInit, []
{
if (!UToolMenus::IsToolMenuUIEnabled())
{
return;
}
UToolMenus::RegisterStartupCallback(FSimpleMulticastDelegate::FDelegate::CreateLambda([]()
{
using namespace Metasound::Editor;
FToolMenuOwnerScoped OwnerScoped(UE_MODULE_NAME);
{
const UClass* MetaSoundClass = UMetaSoundSource::StaticClass();
check(MetaSoundClass);
FToolUIAction CreateAction;
CreateAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&AssetDefinitionsPrivate::ExecuteCreateMetaSoundPreset<UMetaSoundSource, UMetaSoundSourceFactory>);
const FSlateIcon AssetIcon = Metasound::Editor::Style::CreateSlateIcon("ClassIcon.MetasoundSource");
AssetDefinitionsPrivate::AddMetaSoundActions(AssetIcon, *MetaSoundClass, MoveTemp(CreateAction));
{
const UAssetDefinition* AssetDefinition = UAssetDefinitionRegistry::Get()->GetAssetDefinitionForClass(MetaSoundClass);
FToolMenuSection* PlaybackSection = CastChecked<UAssetDefinition_SoundAssetBase>(AssetDefinition)->FindSoundContextMenuSection("Playback");
check(PlaybackSection);
PlaybackSection->AddDynamicEntry(NAME_None, FNewToolMenuSectionDelegate::CreateLambda([AssetIcon](FToolMenuSection& InSection)
{
auto IsPlayingThis = [](const FToolMenuContext& InContext) { return UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, true /* bMustMatchContext */); };
auto IsNotPlayingThis = [](const FToolMenuContext& InContext) { return !UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, true /* bMustMatchContext */); };
auto IsNotPlayingAny = [](const FToolMenuContext& InContext) { return !UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, false /* bMustMatchContext */); };
auto IsPlayingAny = [](const FToolMenuContext& InContext) { return UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, false /* bMustMatchContext */); };
auto IsPlayingOther = [](const FToolMenuContext& InContext) { return UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, false /* bMustMatchContext */) && !UAssetDefinition_SoundBase::IsPlayingContextAsset(InContext, true /* bMustMatchContext */); };
{
const TAttribute<FText> Label = LOCTEXT("Sound_PlaySound" , "Play");
const TAttribute<FText> ToolTip = LOCTEXT("Sound_PlaySoundTooltip", "Plays the selected sound.");
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "MediaAsset.AssetActions.Play.Small");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecutePlaySound);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::CanExecutePlayCommand);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateLambda(IsNotPlayingThis);
InSection.AddMenuEntry("Sound_PlaySound", Label, ToolTip, Icon, UIAction);
}
{
const TAttribute<FText> Label = LOCTEXT("Sound_RestartSound", "Restart");
const TAttribute<FText> ToolTip = LOCTEXT("Sound_RestartSoundTooltip", "Restarts the selected sound.");
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "Cascade.RestartInLevel.Small");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecutePlaySound);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::CanExecutePlayCommand);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateLambda(IsPlayingThis);
InSection.AddMenuEntry("Sound_RestartSound", Label, ToolTip, Icon, UIAction);
}
{ // Stop
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "MediaAsset.AssetActions.Stop.Small");
{ // Selected
const TAttribute<FText> StopSelectedToolTip = LOCTEXT("Sound_StopSoundTooltip", "Stops the selected sound.");
{
const TAttribute<FText> Label = LOCTEXT("Sound_StopSoundDisabled", "Stop");
FToolUIAction UIAction;
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateLambda(IsPlayingThis);
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecuteStopSound);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateLambda([IsNotPlayingAny, IsPlayingThis](const FToolMenuContext& Context) { return IsNotPlayingAny(Context) || IsPlayingThis(Context); });
InSection.AddMenuEntry("Sound_StopSound", Label, StopSelectedToolTip, Icon, UIAction);
}
}
{ // Other
const TAttribute<FText> Label = TAttribute<FText>::CreateLambda([]()
{
if (const USoundBase* OtherSound = UAssetDefinition_SoundBase::GetPlayingSound())
{
return FText::Format(LOCTEXT("Sound_StopSoundOtherFormat", "Stop ({0})"), FText::FromName(OtherSound->GetFName()));
}
return LOCTEXT("Sound_StopSoundOther", "Stop (Other)");
});
const TAttribute<FText> ToolTip = LOCTEXT("Sound_StopOtherSoundTooltip", "Stops the currently previewing (other) sound.");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecuteStopSound);
UIAction.IsActionVisibleDelegate = FToolMenuIsActionButtonVisible::CreateLambda(IsPlayingOther);
InSection.AddMenuEntry("Sound_StopOtherSound", Label, ToolTip, Icon, UIAction);
}
}
{
const TAttribute<FText> Label = LOCTEXT("Sound_MuteSound", "Mute");
const TAttribute<FText> ToolTip = LOCTEXT("Sound_MuteSoundTooltip", "Mutes the selected sounds.");
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "MediaAsset.AssetActions.Mute.Small");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecuteMuteSound);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::CanExecuteMuteCommand);
UIAction.GetActionCheckState = FToolMenuGetActionCheckState::CreateStatic(&UAssetDefinition_MetaSoundSource::IsActionCheckedMute);
InSection.AddMenuEntry("Sound_SoundMute", Label, ToolTip, Icon, UIAction, EUserInterfaceActionType::ToggleButton);
}
{
const TAttribute<FText> Label = LOCTEXT("Sound_SoloSound", "Solo");
const TAttribute<FText> ToolTip = LOCTEXT("Sound_SoloSoundTooltip", "Solos the selected sounds.");
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "MediaAsset.AssetActions.Solo.Small");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::ExecuteSoloSound);
UIAction.CanExecuteAction = FToolMenuCanExecuteAction::CreateStatic(&UAssetDefinition_MetaSoundSource::CanExecuteSoloCommand);
UIAction.GetActionCheckState = FToolMenuGetActionCheckState::CreateStatic(&UAssetDefinition_MetaSoundSource::IsActionCheckedSolo);
InSection.AddMenuEntry("Sound_StopSolo", Label, ToolTip, Icon, UIAction, EUserInterfaceActionType::ToggleButton);
}
{
const TAttribute<FText> Label = LOCTEXT("Sound_ClearMutedSoloed", "Clear Muted/Soloed");
const TAttribute<FText> ToolTip = LOCTEXT("Sound_ClearMutedSoloedTooltip", "Clear all flags to mute/solo specific assets.");
const FSlateIcon Icon = FSlateIcon(FAppStyle::GetAppStyleSetName(), "PropertyWindow.DiffersFromDefault");
FToolUIAction UIAction;
UIAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&UAssetDefinition_SoundBase::ExecuteClearMutesAndSolos);
UIAction.IsActionVisibleDelegate = FToolMenuCanExecuteAction::CreateStatic(&UAssetDefinition_SoundBase::CanExecuteClearMutesAndSolos);
InSection.AddMenuEntry("Sound_ClearMuteSoloSettings", Label, ToolTip, Icon, UIAction);
}
}));
}
}
{
const UClass* MetaSoundClass = UMetaSoundPatch::StaticClass();
check(MetaSoundClass);
FToolUIAction CreateAction;
CreateAction.ExecuteAction = FToolMenuExecuteAction::CreateStatic(&AssetDefinitionsPrivate::ExecuteCreateMetaSoundPreset<UMetaSoundPatch, UMetaSoundFactory>);
const FSlateIcon AssetIcon = Metasound::Editor::Style::CreateSlateIcon("ClassIcon.MetasoundPatch");
AssetDefinitionsPrivate::AddMetaSoundActions(AssetIcon, *MetaSoundClass, MoveTemp(CreateAction));
}
}));
});
} // namespace MenuExtension_MetaSoundSourceTemplate
#undef LOCTEXT_NAMESPACE //MetaSoundEditor