// 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(InContext)) { if (UAssetEditorSubsystem* AssetSubsystem = GEditor->GetEditorSubsystem()) { 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(InContext)) { if (UAssetEditorSubsystem* AssetSubsystem = GEditor->GetEditorSubsystem()) { FMetaSoundFrontendDocumentBuilder& DocumentBuilder = Frontend::IDocumentBuilderRegistry::GetChecked().FindOrBeginBuilding(MetaSound); if (const FMetasoundAssetBase* MetaSoundAsset = DocumentBuilder.GetReferencedPresetAsset()) { AssetSubsystem->OpenEditorForAsset(MetaSoundAsset->GetOwningAsset()); } } } } template void ExecuteCreateMetaSoundPreset(const FToolMenuContext& MenuContext) { if (const UContentBrowserAssetContextMenuContext* Context = UContentBrowserAssetContextMenuContext::FindContextWithAssets(MenuContext)) { using namespace Metasound::Editor; TArray ObjectsToSync; for (TClass* ReferencedMetaSound : Context->LoadSelectedObjects()) { FString PackagePath; FString AssetName; UObject* NewMetaSound = nullptr; IAssetTools::Get().CreateUniqueAssetName(ReferencedMetaSound->GetOutermost()->GetName(), TEXT("_Preset"), PackagePath, AssetName); Metasound::Editor::IMetasoundEditorModule& MetaSoundEditorModule = FModuleManager::GetModuleChecked("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(); 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("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 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(AssetDefinition)->FindSoundContextMenuSection("MetaSound"); check(Section); Section->AddDynamicEntry(NAME_None, FNewToolMenuSectionDelegate::CreateLambda([CreateAction = MoveTemp(CreatePresetAction), ClassName, AssetIcon](FToolMenuSection& InSection) { using namespace Metasound::Editor; { const TAttribute Label = FText::Format(LOCTEXT("MetaSound_CreatePreset", "Create Preset..."), ClassName); const TAttribute 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 Label = LOCTEXT("MetaSound_BrowseToPresetParentFormat", "Browse To Preset Parent"); const TAttribute 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("MetaSoundEditor"); if (!EditorModule.IsRestrictedMode()) { const TAttribute Label = LOCTEXT("MetaSound_EditPresetParentFormat", "Edit Preset Parent..."); const TAttribute 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& OutSections) { const UAudioEditorSettings* EdSettings = GetDefault(); 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(); check(EnumClass); const EToolMenuInsertType InsertType = static_cast(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 UAssetDefinition_MetaSoundPatch::GetAssetClass() const { return UMetaSoundPatch::StaticClass(); } TConstArrayView UAssetDefinition_MetaSoundPatch::GetAssetCategories() const { static const auto Pinned_Categories = { EAssetCategoryPaths::Audio }; static const auto Categories = { EAssetCategoryPaths::Audio / LOCTEXT("AssetSoundMetaSoundsSubMenu", "MetaSounds") }; if (GetDefault()->bPinMetaSoundPatchInAssetMenu) { return Pinned_Categories; } return Categories; } EAssetCommandResult UAssetDefinition_MetaSoundPatch::OpenAssets(const FAssetOpenArgs& OpenArgs) const { Metasound::Editor::IMetasoundEditorModule& MetaSoundEditorModule = FModuleManager::GetModuleChecked("MetaSoundEditor"); if (!MetaSoundEditorModule.IsRestrictedMode()) { for (UMetaSoundPatch* Metasound : OpenArgs.LoadObjects()) { TSharedRef NewEditor = MakeShared(); 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 UAssetDefinition_MetaSoundPatch::RebuildSoundContextMenuSections() const { using namespace Metasound::Editor; TArray 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 UAssetDefinition_MetaSoundSource::GetAssetClass() const { return UMetaSoundSource::StaticClass(); } TConstArrayView UAssetDefinition_MetaSoundSource::GetAssetCategories() const { static const auto Pinned_Categories = { EAssetCategoryPaths::Audio }; static const auto Categories = { EAssetCategoryPaths::Audio / LOCTEXT("AssetSoundMetaSoundSourceSubMenu", "MetaSounds") }; if (GetDefault()->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 ToolkitHost = OpenArgs.ToolkitHost; const bool bHostNull = !OpenArgs.ToolkitHost.IsValid(); AssetManager.AddOrLoadAndUpdateFromObjectAsync(AssetData, [ToolkitMode = OpenArgs.GetToolkitMode(), bHostNull, ToolkitHost](FMetaSoundAssetKey, UObject& MetaSoundObject) { TSharedPtr HostPtr = ToolkitHost.Pin(); if (bHostNull || HostPtr) { Editor::IMetasoundEditorModule* EditorModule = FModuleManager::GetModulePtr("MetaSoundEditor"); if (EditorModule) { if (EditorModule->IsRestrictedMode()) { TScriptInterface DocInterface(&MetaSoundObject); check(DocInterface.GetObject()); const Frontend::FMetaSoundAssetClassInfo ClassInfo(*DocInterface.GetInterface()); if (!ClassInfo.bIsValid || !ClassInfo.DocInfo.bIsPreset) { return; } } TSharedRef NewEditor = MakeShared(); 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(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 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(InContext)) { TSharedPtr 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 UAssetDefinition_MetaSoundSource::GetThumbnailOverlay(const FAssetData& InAssetData) const { auto OnClickedLambdaOverride = [InAssetData]() -> FReply { TSharedPtr 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(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 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(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()) { TSharedPtr 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& OutExtensions) const { UAssetDefinition_SoundBase::GetSoundBaseAssetActionButtonExtensions(InAssetData, OutExtensions); } TArray UAssetDefinition_MetaSoundSource::RebuildSoundContextMenuSections() const { using namespace Metasound::Editor; TArray 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); 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(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 Label = LOCTEXT("Sound_PlaySound" , "Play"); const TAttribute 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 Label = LOCTEXT("Sound_RestartSound", "Restart"); const TAttribute 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 StopSelectedToolTip = LOCTEXT("Sound_StopSoundTooltip", "Stops the selected sound."); { const TAttribute 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 Label = TAttribute::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 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 Label = LOCTEXT("Sound_MuteSound", "Mute"); const TAttribute 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 Label = LOCTEXT("Sound_SoloSound", "Solo"); const TAttribute 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 Label = LOCTEXT("Sound_ClearMutedSoloed", "Clear Muted/Soloed"); const TAttribute 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); const FSlateIcon AssetIcon = Metasound::Editor::Style::CreateSlateIcon("ClassIcon.MetasoundPatch"); AssetDefinitionsPrivate::AddMetaSoundActions(AssetIcon, *MetaSoundClass, MoveTemp(CreateAction)); } })); }); } // namespace MenuExtension_MetaSoundSourceTemplate #undef LOCTEXT_NAMESPACE //MetaSoundEditor