2020-07-22 14:52:03 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundDetailCustomization.h"
2020-08-05 12:47:19 -04:00
# include "Containers/Set.h"
2020-07-30 16:57:04 -04:00
# include "Delegates/Delegate.h"
2020-07-22 14:52:03 -04:00
# include "DetailCategoryBuilder.h"
# include "DetailLayoutBuilder.h"
2020-07-30 16:57:04 -04:00
# include "DetailWidgetRow.h"
2021-01-20 00:42:47 -04:00
# include "Framework/Notifications/NotificationManager.h"
2021-12-10 20:37:31 -05:00
# include "IAudioParameterInterfaceRegistry.h"
2021-11-22 15:55:50 -05:00
# include "IAudioParameterTransmitter.h"
2020-07-23 16:39:56 -04:00
# include "IDetailGroup.h"
2021-03-19 15:10:57 -04:00
# include "Input/Events.h"
2023-03-13 17:23:05 -04:00
# include "Interfaces/MetasoundFrontendInterfaceRegistry.h"
2020-07-30 16:57:04 -04:00
# include "MetasoundAssetBase.h"
2023-05-10 20:28:39 -04:00
# include "MetasoundBuilderSubsystem.h"
2024-06-10 13:41:25 -04:00
# include "MetasoundDocumentBuilderRegistry.h"
2021-09-20 13:55:48 -04:00
# include "MetasoundEditor.h"
# include "MetasoundEditorGraphBuilder.h"
2024-08-30 12:53:13 -04:00
# include "MetasoundEditorModule.h"
2021-03-24 16:42:25 -04:00
# include "MetasoundEditorSettings.h"
2024-07-16 12:40:36 -04:00
# include "MetasoundEditorSubsystem.h"
2020-08-05 12:47:19 -04:00
# include "MetasoundFrontend.h"
2021-01-23 12:59:01 -04:00
# include "MetasoundFrontendController.h"
2021-11-22 15:55:50 -05:00
# include "MetasoundFrontendSearchEngine.h"
2024-06-20 15:27:03 -04:00
# include "MetasoundSettings.h"
2021-08-18 15:16:57 -04:00
# include "MetasoundSource.h"
2020-12-14 15:48:27 -04:00
# include "MetasoundUObjectRegistry.h"
2021-11-22 15:55:50 -05:00
# include "PropertyCustomizationHelpers.h"
2020-07-22 14:52:03 -04:00
# include "PropertyEditorDelegates.h"
# include "PropertyHandle.h"
2021-01-20 00:42:47 -04:00
# include "PropertyRestriction.h"
2021-03-19 15:10:57 -04:00
# include "SGraphPalette.h"
2022-10-19 06:39:08 -04:00
# include "ScopedTransaction.h"
2021-03-24 18:13:33 -04:00
# include "Sound/SoundWave.h"
2022-10-19 06:39:08 -04:00
# include "Styling/CoreStyle.h"
# include "Styling/SlateColor.h"
# include "Styling/SlateTypes.h"
2024-08-30 12:53:13 -04:00
# include "Styling/StyleColors.h"
2020-07-22 14:52:03 -04:00
# include "Templates/Casts.h"
# include "Templates/SharedPointer.h"
2020-08-05 12:47:19 -04:00
# include "UObject/WeakObjectPtr.h"
2020-07-30 16:57:04 -04:00
# include "UObject/WeakObjectPtrTemplates.h"
2022-10-19 06:39:08 -04:00
# include "Widgets/Input/SCheckBox.h"
2021-01-20 00:42:47 -04:00
# include "Widgets/Notifications/SNotificationList.h"
2020-07-31 11:59:52 -04:00
# include "Widgets/Text/STextBlock.h"
2020-07-22 14:52:03 -04:00
2021-04-02 03:03:27 -04:00
# define LOCTEXT_NAMESPACE "MetaSoundEditor"
2020-07-23 16:39:56 -04:00
2021-01-23 12:59:01 -04:00
2024-06-10 13:41:25 -04:00
namespace Metasound : : Editor
2020-07-30 16:57:04 -04:00
{
2024-08-14 13:27:46 -04:00
const FName GetMissingPageName ( const FGuid & InPageID )
{
return FName ( * FString : : Printf ( TEXT ( " Invalid (...%s) " ), *InPageID.ToString().Mid(28, 8))) ;
}
2024-06-10 13:41:25 -04:00
FName BuildChildPath ( const FString & InBasePath , FName InPropertyName )
2020-07-30 16:57:04 -04:00
{
2024-06-10 13:41:25 -04:00
return FName ( InBasePath + TEXT ( " . " ) + InPropertyName . ToString ( ) ) ;
}
2020-07-30 16:57:04 -04:00
2024-06-10 13:41:25 -04:00
FName BuildChildPath ( const FName & InBasePath , FName InPropertyName )
{
return FName ( InBasePath . ToString ( ) + TEXT ( " . " ) + InPropertyName . ToString ( ) ) ;
}
2020-07-30 16:57:04 -04:00
2024-06-10 13:41:25 -04:00
UObject * FMetaSoundDetailCustomizationBase : : GetMetaSound ( ) const
{
if ( Builder . IsValid ( ) )
2020-08-05 12:47:19 -04:00
{
2024-06-10 13:41:25 -04:00
const FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
if ( DocBuilder . IsValid ( ) )
2021-11-22 15:55:50 -05:00
{
2024-06-10 13:41:25 -04:00
return & DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
2021-11-22 15:55:50 -05:00
}
2024-06-10 13:41:25 -04:00
}
2021-08-18 15:16:57 -04:00
2024-06-10 13:41:25 -04:00
return nullptr ;
}
2021-08-18 15:16:57 -04:00
2024-06-10 13:41:25 -04:00
void FMetaSoundDetailCustomizationBase : : InitBuilder ( UObject & MetaSound )
{
using namespace Engine ;
Builder . Reset ( & FDocumentBuilderRegistry : : GetChecked ( ) . FindOrBeginBuilding ( MetaSound ) ) ;
2024-06-17 14:50:21 -04:00
}
2024-06-10 13:41:25 -04:00
2024-06-17 14:50:21 -04:00
bool FMetaSoundDetailCustomizationBase : : IsGraphEditable ( ) const
{
using namespace Engine ;
if ( Builder . IsValid ( ) )
2024-06-10 13:41:25 -04:00
{
2024-06-17 14:50:21 -04:00
const FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetConstBuilder ( ) ;
if ( DocBuilder . IsValid ( ) )
2023-11-13 17:11:15 -05:00
{
2024-06-17 14:50:21 -04:00
return DocBuilder . FindConstBuildGraphChecked ( ) . Style . bIsGraphEditable ;
2023-11-13 17:11:15 -05:00
}
2024-06-17 14:50:21 -04:00
}
2023-11-13 17:11:15 -05:00
2024-06-17 14:50:21 -04:00
return false ;
2024-06-10 13:41:25 -04:00
}
FMetasoundDetailCustomization : : FMetasoundDetailCustomization ( FName InDocumentPropertyName )
: DocumentPropertyName ( InDocumentPropertyName )
{
}
2024-06-20 15:27:03 -04:00
FName FMetasoundDetailCustomization : : GetInterfaceVersionsPropertyPath ( ) const
2024-06-10 13:41:25 -04:00
{
return BuildChildPath ( DocumentPropertyName , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendDocument , Interfaces ) ) ;
}
2024-06-20 15:27:03 -04:00
FName FMetasoundDetailCustomization : : GetRootClassPropertyPath ( ) const
2024-06-10 13:41:25 -04:00
{
return BuildChildPath ( DocumentPropertyName , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendDocument , RootGraph ) ) ;
}
FName FMetasoundDetailCustomization : : GetMetadataPropertyPath ( ) const
{
2024-06-20 15:27:03 -04:00
const FName RootClass = FName ( GetRootClassPropertyPath ( ) ) ;
2024-06-10 13:41:25 -04:00
return BuildChildPath ( RootClass , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendClass , Metadata ) ) ;
}
void FMetasoundDetailCustomization : : CustomizeDetails ( IDetailLayoutBuilder & DetailLayout )
{
using namespace Frontend ;
TArray < TWeakObjectPtr < UObject > > Objects ;
DetailLayout . GetObjectsBeingCustomized ( Objects ) ;
// Only support modifying a single MetaSound at a time (Multiple
// MetaSound editing will be covered most likely by separate tool).
if ( Objects . Num ( ) > 1 | | ! Objects . Last ( ) . IsValid ( ) )
{
return ;
}
UObject & MetaSound = * Objects . Last ( ) . Get ( ) ;
InitBuilder ( MetaSound ) ;
TWeakObjectPtr < UMetaSoundSource > MetaSoundSource = Cast < UMetaSoundSource > ( & MetaSound ) ;
// MetaSound patches don't have source settings, so view MetaSound settings by default
EMetasoundActiveDetailView DetailsView = EMetasoundActiveDetailView : : Metasound ;
if ( MetaSoundSource . IsValid ( ) )
{
// Show source settings by default unless previously set
DetailsView = EMetasoundActiveDetailView : : General ;
if ( const UMetasoundEditorSettings * EditorSettings = GetDefault < UMetasoundEditorSettings > ( ) )
2021-03-24 16:42:25 -04:00
{
2024-06-10 13:41:25 -04:00
DetailsView = EditorSettings - > DetailView ;
}
}
switch ( DetailsView )
{
case EMetasoundActiveDetailView : : Metasound :
{
IDetailCategoryBuilder & GeneralCategoryBuilder = DetailLayout . EditCategory ( " MetaSound " ) ;
const FName AuthorPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetAuthorPropertyName ( ) ) ;
const FName CategoryHierarchyPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetCategoryHierarchyPropertyName ( ) ) ;
2024-06-20 15:27:03 -04:00
const FName ClassNamePropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetClassNamePropertyName ( ) ) ;
2024-06-10 13:41:25 -04:00
const FName DescPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetDescriptionPropertyName ( ) ) ;
const FName DisplayNamePropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetDisplayNamePropertyName ( ) ) ;
const FName KeywordsPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetKeywordsPropertyName ( ) ) ;
const FName IsDeprecatedPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetIsDeprecatedPropertyName ( ) ) ;
2024-06-20 15:27:03 -04:00
const FName VersionPropertyPath = BuildChildPath ( GetMetadataPropertyPath ( ) , FMetasoundFrontendClassMetadata : : GetVersionPropertyName ( ) ) ;
2024-06-10 13:41:25 -04:00
const FName ClassNameNamePropertyPath = BuildChildPath ( ClassNamePropertyPath , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendClassName , Name ) ) ;
const FName MajorVersionPropertyPath = BuildChildPath ( VersionPropertyPath , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendVersionNumber , Major ) ) ;
const FName MinorVersionPropertyPath = BuildChildPath ( VersionPropertyPath , GET_MEMBER_NAME_CHECKED ( FMetasoundFrontendVersionNumber , Minor ) ) ;
2024-06-20 15:27:03 -04:00
const FName InterfaceVersionsPropertyPath = GetInterfaceVersionsPropertyPath ( ) ;
2024-06-10 13:41:25 -04:00
TSharedPtr < IPropertyHandle > AuthorHandle = DetailLayout . GetProperty ( AuthorPropertyPath ) ;
TSharedPtr < IPropertyHandle > CategoryHierarchyHandle = DetailLayout . GetProperty ( CategoryHierarchyPropertyPath ) ;
TSharedPtr < IPropertyHandle > ClassNameHandle = DetailLayout . GetProperty ( ClassNameNamePropertyPath ) ;
TSharedPtr < IPropertyHandle > DisplayNameHandle = DetailLayout . GetProperty ( DisplayNamePropertyPath ) ;
TSharedPtr < IPropertyHandle > DescHandle = DetailLayout . GetProperty ( DescPropertyPath ) ;
TSharedPtr < IPropertyHandle > KeywordsHandle = DetailLayout . GetProperty ( KeywordsPropertyPath ) ;
TSharedPtr < IPropertyHandle > IsDeprecatedHandle = DetailLayout . GetProperty ( IsDeprecatedPropertyPath ) ;
TSharedPtr < IPropertyHandle > InterfaceVersionsHandle = DetailLayout . GetProperty ( InterfaceVersionsPropertyPath ) ;
TSharedPtr < IPropertyHandle > MajorVersionHandle = DetailLayout . GetProperty ( MajorVersionPropertyPath ) ;
TSharedPtr < IPropertyHandle > MinorVersionHandle = DetailLayout . GetProperty ( MinorVersionPropertyPath ) ;
// Invalid for UMetaSounds
TSharedPtr < IPropertyHandle > OutputFormat = DetailLayout . GetProperty ( GET_MEMBER_NAME_CHECKED ( UMetaSoundSource , OutputFormat ) ) ;
if ( OutputFormat . IsValid ( ) )
2021-03-24 16:42:25 -04:00
{
2024-06-10 13:41:25 -04:00
if ( MetaSoundSource . IsValid ( ) )
2021-08-18 15:16:57 -04:00
{
2024-06-10 13:41:25 -04:00
OutputFormat - > SetOnPropertyValuePreChange ( FSimpleDelegate : : CreateLambda ( [ Source = MetaSoundSource ] ( )
2021-09-20 13:55:48 -04:00
{
2024-06-10 13:41:25 -04:00
if ( Source . IsValid ( ) )
2021-09-20 13:55:48 -04:00
{
2024-06-10 13:41:25 -04:00
TSharedPtr < FEditor > ParentEditor = FGraphBuilder : : GetEditorForMetasound ( * Source . Get ( ) ) ;
if ( ParentEditor . IsValid ( ) )
2021-09-20 13:55:48 -04:00
{
2024-06-10 13:41:25 -04:00
ParentEditor - > Stop ( ) ;
} ;
}
} ) ) ;
2021-09-20 13:55:48 -04:00
2024-06-10 13:41:25 -04:00
OutputFormat - > SetOnPropertyValueChanged ( FSimpleDelegate : : CreateLambda ( [ Source = MetaSoundSource ] ( )
{
if ( Source . IsValid ( ) )
2021-09-20 13:55:48 -04:00
{
2024-06-10 13:41:25 -04:00
TSharedPtr < FEditor > ParentEditor = FGraphBuilder : : GetEditorForMetasound ( * Source . Get ( ) ) ;
if ( ParentEditor . IsValid ( ) )
2021-09-20 13:55:48 -04:00
{
2024-06-10 13:41:25 -04:00
ParentEditor - > CreateAnalyzers ( * Source . Get ( ) ) ;
} ;
}
} ) ) ;
2021-08-18 15:16:57 -04:00
}
2024-06-10 13:41:25 -04:00
TSharedRef < SWidget > OutputFormatValueWidget = OutputFormat - > CreatePropertyValueWidget ( ) ;
2024-06-17 14:50:21 -04:00
OutputFormatValueWidget - > SetEnabled ( TAttribute < bool > : : Create ( TAttribute < bool > : : FGetter : : CreateSP ( this , & FMetaSoundDetailCustomizationBase : : IsGraphEditable ) ) ) ;
2022-02-02 02:19:16 -05:00
2024-06-10 13:41:25 -04:00
static const FText OutputFormatName = LOCTEXT ( " MetasoundOutputFormatPropertyName " , " Output Format " ) ;
GeneralCategoryBuilder . AddCustomRow ( OutputFormatName )
. NameContent ( )
2021-08-09 15:13:40 -04:00
[
2024-06-10 13:41:25 -04:00
OutputFormat - > CreatePropertyNameWidget ( )
2021-08-09 15:13:40 -04:00
]
. ValueContent ( )
[
2024-06-10 13:41:25 -04:00
OutputFormatValueWidget
2021-08-09 15:13:40 -04:00
] ;
2024-06-10 13:41:25 -04:00
OutputFormat - > MarkHiddenByCustomization ( ) ;
2021-03-24 16:42:25 -04:00
}
2020-07-23 16:39:56 -04:00
2024-06-10 13:41:25 -04:00
// Updates FText properties on open editors if required
{
FSimpleDelegate RegisterOnChange = FSimpleDelegate : : CreateLambda ( [ this ] ( )
2022-09-08 13:29:35 -04:00
{
2024-06-10 13:41:25 -04:00
if ( Builder . IsValid ( ) )
2022-09-08 13:29:35 -04:00
{
2024-06-10 13:41:25 -04:00
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
if ( DocBuilder . IsValid ( ) )
2022-09-08 13:29:35 -04:00
{
2024-06-10 13:41:25 -04:00
DocBuilder . GetConstDocumentChecked ( ) . RootGraph . Style . UpdateChangeID ( ) ;
2022-09-08 13:29:35 -04:00
}
2024-06-10 13:41:25 -04:00
constexpr bool bForceViewSynchronization = true ;
FGraphBuilder : : RegisterGraphWithFrontend ( DocBuilder . CastDocumentObjectChecked < UObject > ( ) , bForceViewSynchronization ) ;
2022-09-08 13:29:35 -04:00
}
2024-06-10 13:41:25 -04:00
} ) ;
AuthorHandle - > SetOnChildPropertyValueChanged ( RegisterOnChange ) ;
DescHandle - > SetOnPropertyValueChanged ( RegisterOnChange ) ;
DisplayNameHandle - > SetOnPropertyValueChanged ( RegisterOnChange ) ;
KeywordsHandle - > SetOnPropertyValueChanged ( RegisterOnChange ) ;
KeywordsHandle - > SetOnChildPropertyValueChanged ( RegisterOnChange ) ;
IsDeprecatedHandle - > SetOnPropertyValueChanged ( RegisterOnChange ) ;
}
2021-03-24 18:13:33 -04:00
2024-06-10 13:41:25 -04:00
GeneralCategoryBuilder . AddProperty ( DisplayNameHandle ) ;
GeneralCategoryBuilder . AddProperty ( DescHandle ) ;
GeneralCategoryBuilder . AddProperty ( AuthorHandle ) ;
GeneralCategoryBuilder . AddProperty ( IsDeprecatedHandle ) ;
GeneralCategoryBuilder . AddProperty ( MajorVersionHandle ) ;
GeneralCategoryBuilder . AddProperty ( MinorVersionHandle ) ;
2021-03-24 18:13:33 -04:00
2024-06-10 13:41:25 -04:00
static const FText ClassGuidName = LOCTEXT ( " MetasoundClassGuidPropertyName " , " Class Guid " ) ;
GeneralCategoryBuilder . AddCustomRow ( ClassGuidName ) . NameContent ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Text ( ClassGuidName )
. Font ( FAppStyle : : GetFontStyle ( TEXT ( " PropertyWindow.NormalFont " ) ) )
]
]
. ValueContent ( )
[
ClassNameHandle - > CreatePropertyValueWidget ( )
] ;
GeneralCategoryBuilder . AddProperty ( CategoryHierarchyHandle ) ;
GeneralCategoryBuilder . AddProperty ( KeywordsHandle ) ;
2021-03-24 16:42:25 -04:00
2024-06-10 13:41:25 -04:00
DetailLayout . HideCategory ( " Attenuation " ) ;
DetailLayout . HideCategory ( " Developer " ) ;
DetailLayout . HideCategory ( " Effects " ) ;
DetailLayout . HideCategory ( " Loading " ) ;
DetailLayout . HideCategory ( " Modulation " ) ;
DetailLayout . HideCategory ( " Sound " ) ;
DetailLayout . HideCategory ( " Voice Management " ) ;
2021-03-24 16:42:25 -04:00
}
2024-06-10 13:41:25 -04:00
break ;
2020-08-05 12:47:19 -04:00
2024-06-10 13:41:25 -04:00
case EMetasoundActiveDetailView : : General :
default :
DetailLayout . HideCategory ( " MetaSound " ) ;
2020-08-05 12:47:19 -04:00
2024-06-10 13:41:25 -04:00
TArray < TSharedRef < IPropertyHandle > > DeveloperProperties ;
TArray < TSharedRef < IPropertyHandle > > SoundProperties ;
DetailLayout . EditCategory ( " Sound " )
. GetDefaultProperties ( SoundProperties ) ;
DetailLayout . EditCategory ( " Developer " )
. GetDefaultProperties ( DeveloperProperties ) ;
auto HideProperties = [ ] ( const TSet < FName > & PropsToHide , const TArray < TSharedRef < IPropertyHandle > > & Properties )
{
for ( TSharedRef < IPropertyHandle > Property : Properties )
{
if ( PropsToHide . Contains ( Property - > GetProperty ( ) - > GetFName ( ) ) )
{
Property - > MarkHiddenByCustomization ( ) ;
}
}
} ;
static const TSet < FName > SoundPropsToHide =
{
GET_MEMBER_NAME_CHECKED ( USoundWave , bLooping ) ,
GET_MEMBER_NAME_CHECKED ( USoundWave , SoundGroup )
} ;
HideProperties ( SoundPropsToHide , SoundProperties ) ;
static const TSet < FName > DeveloperPropsToHide =
{
GET_MEMBER_NAME_CHECKED ( USoundBase , Duration ) ,
GET_MEMBER_NAME_CHECKED ( USoundBase , MaxDistance ) ,
GET_MEMBER_NAME_CHECKED ( USoundBase , TotalSamples )
} ;
HideProperties ( DeveloperPropsToHide , DeveloperProperties ) ;
break ;
2020-08-05 12:47:19 -04:00
}
2022-03-01 14:29:17 -05:00
2024-06-10 13:41:25 -04:00
// Hack to hide parent structs for nested metadata properties
DetailLayout . HideCategory ( " CustomView " ) ;
DetailLayout . HideCategory ( " Analysis " ) ;
DetailLayout . HideCategory ( " Curves " ) ;
DetailLayout . HideCategory ( " File Path " ) ;
DetailLayout . HideCategory ( " Format " ) ;
DetailLayout . HideCategory ( " Info " ) ;
DetailLayout . HideCategory ( " Loading " ) ;
DetailLayout . HideCategory ( " Playback " ) ;
DetailLayout . HideCategory ( " Subtitles " ) ;
DetailLayout . HideCategory ( " Waveform Processing " ) ;
}
2024-06-20 15:27:03 -04:00
FMetasoundPagesDetailCustomization : : FMetasoundPagesDetailCustomization ( )
{
}
void FMetasoundPagesDetailCustomization : : CustomizeDetails ( IDetailLayoutBuilder & DetailLayout )
{
using namespace Engine ;
using namespace Frontend ;
TArray < TWeakObjectPtr < UObject > > Objects ;
DetailLayout . GetObjectsBeingCustomized ( Objects ) ;
// Only support modifying a single MetaSound at a time (Multiple
// MetaSound editing will be covered most likely by separate tool).
if ( Objects . Num ( ) > 1 )
{
return ;
}
if ( UMetaSoundSettings * Settings = GetMutableDefault < UMetaSoundSettings > ( ) )
{
2024-06-21 14:37:29 -04:00
Settings - > GetOnPageSettingsUpdatedDelegate ( ) . AddSPLambda ( this , [ this ] ( )
2024-06-20 15:27:03 -04:00
{
UpdateItemNames ( ) ;
if ( ComboBox . IsValid ( ) )
{
ComboBox - > RefreshOptions ( ) ;
}
} ) ;
}
SAssignNew ( ComboBox , SSearchableComboBox )
. OptionsSource ( & AddableItems )
. OnGenerateWidget_Lambda ( [ ] ( TSharedPtr < FString > InItem )
{
return SNew ( STextBlock ) . Text ( FText : : FromString ( * InItem ) ) ;
} )
. OnSelectionChanged_Lambda ( [ this ] ( TSharedPtr < FString > NameToAdd , ESelectInfo : : Type InSelectInfo )
{
using namespace Engine ;
using namespace Frontend ;
if ( InSelectInfo ! = ESelectInfo : : OnNavigation )
{
UObject & MetaSound = GetMetaSound ( ) ;
2024-08-23 23:03:23 -04:00
const FScopedTransaction Transaction ( FText : : Format ( LOCTEXT ( " AddPageTransactionFormat " , " Add MetaSound Page Graph '{0}' " ) , FText : : FromString ( * NameToAdd ) ) ) ;
2024-06-20 15:27:03 -04:00
MetaSound . Modify ( ) ;
// Underlying DocBuilder's pageID is a property that is tracked by transaction stack, so signal as modifying behavior
Builder - > Modify ( ) ;
constexpr bool bDuplicateLastGraph = true ;
constexpr bool bSetAsBuildGraph = true ;
EMetaSoundBuilderResult Result = EMetaSoundBuilderResult : : Failed ;
Builder - > AddGraphPage ( FName ( * NameToAdd . Get ( ) ) , bDuplicateLastGraph , bSetAsBuildGraph , Result ) ;
}
} )
. Content ( )
[
SNew ( STextBlock )
2024-08-23 23:03:23 -04:00
. Text ( LOCTEXT ( " AddPageGraphAction " , " Add Page Graph... " ) )
2024-06-20 15:27:03 -04:00
. IsEnabled ( TAttribute < bool > : : Create ( TAttribute < bool > : : FGetter : : CreateSP ( this , & FMetaSoundDetailCustomizationBase : : IsGraphEditable ) ) )
] ;
TSharedRef < SWidget > Utilities = SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
ComboBox - > AsShared ( )
]
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
PropertyCustomizationHelpers : : MakeDeleteButton ( FSimpleDelegate : : CreateLambda ( [ this ] ( )
{
using namespace Frontend ;
UObject & MetaSound = GetMetaSound ( ) ;
2024-08-23 23:03:23 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " ResetGraphPagesTransaction " , " Reset MetaSound Graph Pages " ) ) ;
2024-06-20 15:27:03 -04:00
MetaSound . Modify ( ) ;
2024-08-19 17:06:23 -04:00
constexpr bool bClearDefaultGraph = false ;
2024-06-20 15:27:03 -04:00
// Underlying DocBuilder's pageID is a property that is tracked by transaction stack, so signal as modifying behavior
Builder - > Modify ( ) ;
2024-08-19 17:06:23 -04:00
Builder - > ResetGraphPages ( bClearDefaultGraph ) ;
2024-06-20 15:27:03 -04:00
UpdateItemNames ( ) ;
ComboBox - > RefreshOptions ( ) ;
FGraphBuilder : : RegisterGraphWithFrontend ( MetaSound ) ;
2024-08-27 19:05:41 -04:00
} ) , LOCTEXT ( " ResetGraphPagesTooltip " , " Removes all page graphs from the given MetaSound defined in the MetaSound project settings (does not remove the required 'Default' graph). " ) )
2024-06-20 15:27:03 -04:00
] ;
Utilities - > SetEnabled ( TAttribute < bool > : : Create ( TAttribute < bool > : : FGetter : : CreateSP ( this , & FMetaSoundDetailCustomizationBase : : IsGraphEditable ) ) ) ;
2024-08-13 15:48:07 -04:00
{
2024-08-23 23:03:23 -04:00
const FText HeaderName = LOCTEXT ( " PageGraphsDisplayName " , " Graphs " ) ;
IDetailCategoryBuilder & Category = DetailLayout . EditCategory ( " Graphs " , HeaderName ) ;
2024-08-13 15:48:07 -04:00
Category . AddCustomRow ( HeaderName ) [ Utilities ] ;
Category . AddCustomRow ( LOCTEXT ( " ImplementedPagesLabel " , " Graphs " ) ) [ SAssignNew ( EntryWidgets , SVerticalBox ) ] ;
}
2024-07-16 12:40:36 -04:00
// Registration of page listener instance calls OnReload which in turn causes RefreshView, so no need to call directly
if ( UMetasoundEditorViewBase * View = CastChecked < UMetasoundEditorViewBase > ( Objects . Last ( ) ) )
{
if ( UObject * MetaSound = View - > GetMetasound ( ) )
{
InitBuilder ( * MetaSound ) ;
PageListener = MakeShared < FPageListener > ( StaticCastSharedRef < FMetasoundPagesDetailCustomization > ( AsShared ( ) ) ) ;
Builder - > AddTransactionListener ( PageListener - > AsShared ( ) ) ;
}
}
2024-06-20 15:27:03 -04:00
}
UObject & FMetasoundPagesDetailCustomization : : GetMetaSound ( ) const
{
return Builder - > GetBuilder ( ) . CastDocumentObjectChecked < UObject > ( ) ;
}
void FMetasoundPagesDetailCustomization : : RebuildImplemented ( )
{
EntryWidgets - > ClearChildren ( ) ;
2024-08-14 13:27:46 -04:00
TSet < FGuid > ImplementedGuids ;
const FMetasoundFrontendDocument & Document = Builder - > GetBuilder ( ) . GetConstDocumentChecked ( ) ;
Document . RootGraph . IterateGraphPages ( [ & ImplementedGuids ] ( const FMetasoundFrontendGraph & Graph )
{
ImplementedGuids . Add ( Graph . PageID ) ;
} ) ;
auto CreateEntryWidget = [ this ] ( bool bIsDefault , const FGuid & InEntryPageID , FName InName ) - > TSharedRef < SWidget >
2024-06-20 15:27:03 -04:00
{
using namespace Frontend ;
2024-08-30 12:53:13 -04:00
TSharedRef < SHorizontalBox > EntryWidget = SNew ( SHorizontalBox ) ;
2024-06-20 15:27:03 -04:00
2024-08-30 12:53:13 -04:00
// Page Focus
{
TSharedRef < SWidget > SelectButtonWidget = PropertyCustomizationHelpers : : MakeUseSelectedButton (
FSimpleDelegate : : CreateLambda ( [ this , PageID = InEntryPageID , InName ] ( )
{
constexpr bool bOpenEditor = false ; // Already focused by user action
UMetaSoundEditorSubsystem : : GetConstChecked ( ) . SetFocusedPage ( * Builder . Get ( ) , PageID , bOpenEditor ) ;
BuildPageName = InName ;
} ) ,
TAttribute < FText > : : Create ( [ this , InName ] ( )
{
return BuildPageName = = InName
? LOCTEXT ( " FocusedPageTooltip " , " Currently focused page. " )
: LOCTEXT ( " SetFocusedPageTooltip " , " Sets the actively focused graph page of the MetaSound. " ) ;
} ) ,
TAttribute < bool > : : Create ( [ this , InName ] ( )
{
return BuildPageName ! = InName ;
} ) ) ;
EntryWidget - > AddSlot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. AutoWidth ( ) [ SelectButtonWidget ] ;
}
// Page Name
{
EntryWidget - > AddSlot ( )
2024-06-20 15:27:03 -04:00
. Padding ( 2.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
SNew ( STextBlock )
. Text ( FText : : FromName ( InName ) )
] ;
2024-08-30 12:53:13 -04:00
}
2024-06-20 15:27:03 -04:00
2024-08-30 12:53:13 -04:00
// Page Remove
2024-06-20 15:27:03 -04:00
if ( ! bIsDefault )
{
2024-08-30 12:53:13 -04:00
TSharedRef < SWidget > RemoveButtonWidget = PropertyCustomizationHelpers : : MakeDeleteButton (
FSimpleDelegate : : CreateLambda ( [ this , InName , InEntryPageID ] ( )
2024-06-20 15:27:03 -04:00
{
2024-08-30 12:53:13 -04:00
using namespace Frontend ;
const FScopedTransaction Transaction ( FText : : Format ( LOCTEXT ( " RemovePageTransactionFormat " , " Remove MetaSound Page '{0}' " ) , FText : : FromName ( InName ) ) ) ;
UObject & MetaSound = GetMetaSound ( ) ;
MetaSound . Modify ( ) ;
// Removal may modify the builder's build page ID if it is the currently set value
Builder - > Modify ( ) ;
const bool bGraphRemoved = Builder - > GetBuilder ( ) . RemoveGraphPage ( InEntryPageID ) ;
if ( bGraphRemoved )
{
UpdateItemNames ( ) ;
ComboBox - > RefreshOptions ( ) ;
RebuildImplemented ( ) ;
}
} ) , LOCTEXT ( " RemovePageGraphTooltip " , " Removes the associated page graph from the MetaSound. " ) ) ;
2024-06-20 15:27:03 -04:00
EntryWidget - > AddSlot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
2024-08-30 12:53:13 -04:00
. AutoWidth ( ) [ RemoveButtonWidget ] ;
2024-06-20 15:27:03 -04:00
}
2024-08-30 12:53:13 -04:00
// Page Playing Icon
{
TAttribute < FText > ToolTip = LOCTEXT ( " MetaSound_ExecutingPageGraphTooltip " , " Currently executing graph. " ) ;
2024-10-03 14:33:23 -04:00
TAttribute < EVisibility > Visibility = TAttribute < EVisibility > : : CreateSPLambda ( AsShared ( ) , [ this , PageID = InEntryPageID ] ( )
2024-08-30 12:53:13 -04:00
{
if ( Builder . IsValid ( ) )
{
const bool bIsPreviewing = IsPreviewingPageGraph ( Builder - > GetConstBuilder ( ) , PageID ) ;
return bIsPreviewing ? EVisibility : : Visible : EVisibility : : Collapsed ;
}
return EVisibility : : Collapsed ;
} ) ;
TSharedRef < SWidget > ExecImageWidget = SNew ( SImage )
. Image ( Style : : CreateSlateIcon ( " MetasoundEditor.Page.Executing " ) . GetIcon ( ) )
2024-09-19 17:46:22 -04:00
. ColorAndOpacity ( Style : : GetPageExecutingColor ( ) )
2024-08-30 12:53:13 -04:00
. Visibility ( MoveTemp ( Visibility ) ) ;
EntryWidget - > AddSlot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. AutoWidth ( ) [ ExecImageWidget ] ;
}
2024-06-20 15:27:03 -04:00
EntryWidget - > SetEnabled ( TAttribute < bool > : : Create ( TAttribute < bool > : : FGetter : : CreateSP ( this , & FMetaSoundDetailCustomizationBase : : IsGraphEditable ) ) ) ;
return EntryWidget ;
} ;
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
2024-08-23 21:59:54 -04:00
Settings - > IteratePageSettings ( [ & ] ( const FMetaSoundPageSettings & PageSettings )
2024-06-20 15:27:03 -04:00
{
2024-08-14 13:27:46 -04:00
if ( ImplementedGuids . Remove ( PageSettings . UniqueId ) > 0 )
2024-06-20 15:27:03 -04:00
{
2024-08-14 13:27:46 -04:00
const bool bIsDefault = PageSettings . UniqueId = = Frontend : : DefaultPageID ;
2024-06-20 15:27:03 -04:00
EntryWidgets - > AddSlot ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoHeight ( )
[
2024-08-14 13:27:46 -04:00
CreateEntryWidget ( bIsDefault , PageSettings . UniqueId , PageSettings . Name )
2024-06-20 15:27:03 -04:00
] ;
}
2024-08-23 21:59:54 -04:00
} ) ;
2024-08-14 13:27:46 -04:00
for ( const FGuid & MissingPageID : ImplementedGuids )
{
constexpr bool bIsDefault = false ;
const FName MissingName = Editor : : GetMissingPageName ( MissingPageID ) ;
EntryWidgets - > AddSlot ( )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoHeight ( )
[
CreateEntryWidget ( bIsDefault , MissingPageID , MissingName )
] ;
}
2024-06-20 15:27:03 -04:00
}
2024-07-16 12:40:36 -04:00
void FMetasoundPagesDetailCustomization : : RefreshView ( )
{
if ( Builder . IsValid ( ) )
{
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
const FGuid & PageID = DocBuilder . GetBuildPageID ( ) ;
2024-08-14 13:27:46 -04:00
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
2024-07-16 12:40:36 -04:00
if ( const FMetaSoundPageSettings * PageSettings = Settings - > FindPageSettings ( PageID ) )
{
BuildPageName = PageSettings - > Name ;
}
else
{
2024-08-14 13:27:46 -04:00
constexpr bool bOpenEditor = false ; // Already open/focused by user action
2024-08-30 12:53:13 -04:00
UMetaSoundEditorSubsystem : : GetConstChecked ( ) . SetFocusedPage ( * Builder . Get ( ) , PageID , bOpenEditor ) ;
BuildPageName = GetMissingPageName ( PageID ) ;
2024-07-16 12:40:36 -04:00
}
}
else
{
2024-07-26 14:23:35 -04:00
BuildPageName = Frontend : : DefaultPageName ;
2024-07-16 12:40:36 -04:00
}
UpdateItemNames ( ) ;
ComboBox - > RefreshOptions ( ) ;
RebuildImplemented ( ) ;
}
2024-06-20 15:27:03 -04:00
void FMetasoundPagesDetailCustomization : : UpdateItemNames ( )
{
AddableItems . Reset ( ) ;
ImplementedNames . Reset ( ) ;
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
2024-08-14 13:27:46 -04:00
TSet < FGuid > ImplementedGuids ;
2024-06-20 15:27:03 -04:00
const FMetasoundFrontendDocument & Document = Builder - > GetBuilder ( ) . GetConstDocumentChecked ( ) ;
Document . RootGraph . IterateGraphPages ( [ & ImplementedGuids ] ( const FMetasoundFrontendGraph & Graph )
{
ImplementedGuids . Add ( Graph . PageID ) ;
} ) ;
2024-08-23 21:59:54 -04:00
Settings - > IteratePageSettings ( [ this , & ImplementedGuids ] ( const FMetaSoundPageSettings & Page )
{
if ( ! ImplementedGuids . Contains ( Page . UniqueId ) )
{
AddableItems . Add ( MakeShared < FString > ( Page . Name . ToString ( ) ) ) ;
}
} ) ;
2024-06-20 15:27:03 -04:00
auto GetPageName = [ & Settings ] ( const FGuid & PageID )
{
const FMetaSoundPageSettings * Page = Settings - > FindPageSettings ( PageID ) ;
2024-08-14 13:27:46 -04:00
if ( Page )
2024-06-20 15:27:03 -04:00
{
return Page - > Name ;
}
2024-08-14 13:27:46 -04:00
return GetMissingPageName ( PageID ) ;
2024-06-20 15:27:03 -04:00
} ;
Algo : : Transform ( ImplementedGuids , ImplementedNames , GetPageName ) ;
}
2024-07-16 12:40:36 -04:00
void FMetasoundPagesDetailCustomization : : FPageListener : : OnBuilderReloaded ( Frontend : : FDocumentModifyDelegates & OutDelegates )
{
if ( TSharedPtr < FMetasoundPagesDetailCustomization > ParentPtr = Parent . Pin ( ) )
{
ParentPtr - > RefreshView ( ) ;
}
OutDelegates . PageDelegates . OnPageAdded . AddSP ( this , & FPageListener : : OnPageAdded ) ;
OutDelegates . PageDelegates . OnPageSet . AddSP ( this , & FPageListener : : OnPageSet ) ;
OutDelegates . PageDelegates . OnRemovingPage . AddSP ( this , & FPageListener : : OnRemovingPage ) ;
}
void FMetasoundPagesDetailCustomization : : FPageListener : : OnPageAdded ( const Frontend : : FDocumentMutatePageArgs & Args )
{
if ( TSharedPtr < FMetasoundPagesDetailCustomization > ParentPtr = Parent . Pin ( ) )
{
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
if ( const FMetaSoundPageSettings * PageSettings = Settings - > FindPageSettings ( Args . PageID ) )
{
if ( PageSettings - > Name ! = ParentPtr - > BuildPageName )
{
ParentPtr - > BuildPageName = PageSettings - > Name ;
FGraphBuilder : : RegisterGraphWithFrontend ( ParentPtr - > GetMetaSound ( ) ) ;
}
ParentPtr - > AddableItems . RemoveAll ( [ & PageSettings ] ( const TSharedPtr < FString > & Item ) { return Item - > Compare ( PageSettings - > Name . ToString ( ) ) = = 0 ; } ) ;
ParentPtr - > ImplementedNames . Add ( PageSettings - > Name ) ;
ParentPtr - > ComboBox - > RefreshOptions ( ) ;
ParentPtr - > RebuildImplemented ( ) ;
}
}
}
void FMetasoundPagesDetailCustomization : : FPageListener : : OnPageSet ( const Frontend : : FDocumentMutatePageArgs & Args )
{
if ( TSharedPtr < FMetasoundPagesDetailCustomization > ParentPtr = Parent . Pin ( ) )
{
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
if ( const FMetaSoundPageSettings * PageSettings = Settings - > FindPageSettings ( Args . PageID ) )
{
ParentPtr - > BuildPageName = PageSettings - > Name ;
ParentPtr - > ComboBox - > RefreshOptions ( ) ;
ParentPtr - > RebuildImplemented ( ) ;
}
}
}
void FMetasoundPagesDetailCustomization : : FPageListener : : OnRemovingPage ( const Frontend : : FDocumentMutatePageArgs & Args )
{
if ( TSharedPtr < FMetasoundPagesDetailCustomization > ParentPtr = Parent . Pin ( ) )
{
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
if ( const FMetaSoundPageSettings * PageSettings = Settings - > FindPageSettings ( Args . PageID ) )
{
if ( PageSettings - > Name ! = ParentPtr - > BuildPageName )
{
ParentPtr - > BuildPageName = PageSettings - > Name ;
FGraphBuilder : : RegisterGraphWithFrontend ( ParentPtr - > GetMetaSound ( ) ) ;
}
ParentPtr - > AddableItems . Add ( MakeShared < FString > ( PageSettings - > Name . ToString ( ) ) ) ;
ParentPtr - > ImplementedNames . Remove ( PageSettings - > Name ) ;
ParentPtr - > ComboBox - > RefreshOptions ( ) ;
ParentPtr - > RebuildImplemented ( ) ;
}
}
}
2024-06-10 13:41:25 -04:00
void FMetasoundInterfacesDetailCustomization : : CustomizeDetails ( IDetailLayoutBuilder & DetailLayout )
{
TArray < TWeakObjectPtr < UObject > > Objects ;
DetailLayout . GetObjectsBeingCustomized ( Objects ) ;
// Only support modifying a single MetaSound at a time (Multiple
// MetaSound editing will be covered most likely by separate tool).
if ( Objects . Num ( ) > 1 )
2022-03-01 14:29:17 -05:00
{
2024-06-10 13:41:25 -04:00
return ;
}
2024-08-27 19:05:41 -04:00
2024-06-10 13:41:25 -04:00
if ( UMetasoundInterfacesView * InterfacesView = CastChecked < UMetasoundInterfacesView > ( Objects . Last ( ) ) )
{
2024-06-20 15:27:03 -04:00
if ( UObject * MetaSound = InterfacesView - > GetMetasound ( ) )
2024-06-10 13:41:25 -04:00
{
InitBuilder ( * MetaSound ) ;
}
}
2024-08-27 19:05:41 -04:00
TAttribute < bool > IsGraphEditableAttribute = TAttribute < bool > : : Create ( TAttribute < bool > : : FGetter : : CreateSP
(
this , & FMetaSoundDetailCustomizationBase : : IsGraphEditable
) ) ;
2024-06-10 13:41:25 -04:00
UpdateInterfaceNames ( ) ;
SAssignNew ( InterfaceComboBox , SSearchableComboBox )
. OptionsSource ( & AddableInterfaceNames )
. OnGenerateWidget_Lambda ( [ ] ( TSharedPtr < FString > InItem )
{
return SNew ( STextBlock )
. Text ( FText : : FromString ( * InItem ) ) ;
} )
. OnSelectionChanged_Lambda ( [ this ] ( TSharedPtr < FString > NameToAdd , ESelectInfo : : Type InSelectInfo )
2022-03-01 14:29:17 -05:00
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2024-06-10 13:41:25 -04:00
if ( Builder . IsValid ( ) & & InSelectInfo ! = ESelectInfo : : OnNavigation )
2022-03-01 14:29:17 -05:00
{
2024-06-10 13:41:25 -04:00
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
UObject & MetaSound = DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
FMetasoundFrontendInterface InterfaceToAdd ;
const FName InterfaceName { * NameToAdd . Get ( ) } ;
if ( ensure ( ISearchEngine : : Get ( ) . FindInterfaceWithHighestVersion ( InterfaceName , InterfaceToAdd ) ) )
2022-03-01 14:29:17 -05:00
{
2024-06-10 13:41:25 -04:00
const FScopedTransaction Transaction ( FText : : Format ( LOCTEXT ( " AddInterfaceTransactionFormat " , " Add MetaSound Interface '{0}' " ) , FText : : FromString ( InterfaceToAdd . Version . ToString ( ) ) ) ) ;
MetaSound . Modify ( ) ;
FModifyInterfaceOptions Options ( { } , { InterfaceToAdd } ) ;
Options . bSetDefaultNodeLocations = false ; // Don't automatically add nodes to ed graph
DocBuilder . ModifyInterfaces ( MoveTemp ( Options ) ) ;
2022-03-01 14:29:17 -05:00
}
UpdateInterfaceNames ( ) ;
InterfaceComboBox - > RefreshOptions ( ) ;
2024-06-10 13:41:25 -04:00
FGraphBuilder : : RegisterGraphWithFrontend ( MetaSound ) ;
}
} )
. Content ( )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " UpdateInterfaceAction " , " Add Interface... " ) )
. IsEnabled ( IsGraphEditableAttribute )
] ;
2022-06-09 20:28:06 -04:00
2024-06-10 13:41:25 -04:00
TSharedRef < SWidget > InterfaceUtilities = SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
InterfaceComboBox - > AsShared ( )
]
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
PropertyCustomizationHelpers : : MakeDeleteButton ( FSimpleDelegate : : CreateLambda ( [ this ] ( )
2022-03-01 14:29:17 -05:00
{
2023-04-04 19:14:26 -04:00
using namespace Frontend ;
2022-03-01 14:29:17 -05:00
2024-06-10 13:41:25 -04:00
if ( ! Builder . IsValid ( ) )
2022-03-01 14:29:17 -05:00
{
2024-06-10 13:41:25 -04:00
return ;
2022-03-01 14:29:17 -05:00
}
2024-06-10 13:41:25 -04:00
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
if ( ! DocBuilder . IsValid ( ) )
{
return ;
}
2022-03-01 14:29:17 -05:00
2024-06-10 13:41:25 -04:00
TArray < FMetasoundFrontendInterface > ImplementedInterfaces ;
Algo : : Transform ( ImplementedInterfaceNames , ImplementedInterfaces , [ ] ( const FName & Name )
{
FMetasoundFrontendInterface Interface ;
ISearchEngine : : Get ( ) . FindInterfaceWithHighestVersion ( Name , Interface ) ;
return Interface ;
} ) ;
2022-03-01 14:29:17 -05:00
2024-06-10 13:41:25 -04:00
UObject & MetaSound = DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
{
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveAllInterfacesTransaction " , " Remove All MetaSound Interfaces " ) ) ;
MetaSound . Modify ( ) ;
FModifyInterfaceOptions Options ( ImplementedInterfaces , { } ) ;
Options . bSetDefaultNodeLocations = false ; // Don't automatically add nodes to ed graph
DocBuilder . ModifyInterfaces ( MoveTemp ( Options ) ) ;
}
UpdateInterfaceNames ( ) ;
InterfaceComboBox - > RefreshOptions ( ) ;
FGraphBuilder : : RegisterGraphWithFrontend ( MetaSound ) ;
} ) , LOCTEXT ( " RemoveInterfaceTooltip1 " , " Removes all interfaces from the given MetaSound. " ) )
] ;
InterfaceUtilities - > SetEnabled ( IsGraphEditableAttribute ) ;
const FText HeaderName = LOCTEXT ( " InterfacesGroupDisplayName " , " Interfaces " ) ;
IDetailCategoryBuilder & InterfaceCategory = DetailLayout . EditCategory ( " Interfaces " , HeaderName ) ;
InterfaceCategory . AddCustomRow ( HeaderName )
[
InterfaceUtilities
] ;
auto CreateInterfaceEntryWidget = [ & ] ( FName InInterfaceName ) - > TSharedRef < SWidget >
{
using namespace Frontend ;
FMetasoundFrontendInterface InterfaceEntry ;
if ( ! ensure ( ISearchEngine : : Get ( ) . FindInterfaceWithHighestVersion ( InInterfaceName , InterfaceEntry ) ) )
{
return SNullWidget : : NullWidget ;
}
TSharedRef < SWidget > RemoveButtonWidget = PropertyCustomizationHelpers : : MakeDeleteButton ( FSimpleDelegate : : CreateLambda ( [ this , InInterfaceName , InterfaceEntry ] ( )
{
using namespace Frontend ;
if ( ! Builder . IsValid ( ) )
2022-03-01 14:29:17 -05:00
{
2024-06-10 13:41:25 -04:00
return ;
2022-03-01 14:29:17 -05:00
}
2023-03-07 17:01:52 -05:00
2024-06-10 13:41:25 -04:00
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetBuilder ( ) ;
if ( ! DocBuilder . IsValid ( ) )
{
return ;
}
UObject & MetaSound = DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
{
const FScopedTransaction Transaction ( FText : : Format ( LOCTEXT ( " RemoveInterfaceTransactionFormat " , " Remove MetaSound Interface '{0}' " ) , FText : : FromString ( InterfaceEntry . Version . ToString ( ) ) ) ) ;
MetaSound . Modify ( ) ;
FModifyInterfaceOptions Options ( { InterfaceEntry } , { } ) ;
Options . bSetDefaultNodeLocations = false ; // Don't automatically add nodes to ed graph
DocBuilder . ModifyInterfaces ( MoveTemp ( Options ) ) ;
}
UpdateInterfaceNames ( ) ;
InterfaceComboBox - > RefreshOptions ( ) ;
FGraphBuilder : : RegisterGraphWithFrontend ( MetaSound ) ;
} ) , LOCTEXT ( " RemoveInterfaceTooltip2 " , " Removes the associated interface from the MetaSound. " ) ) ;
TSharedRef < SWidget > EntryWidget = SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
SNew ( STextBlock )
. Text ( FText : : FromName ( InterfaceEntry . Version . Name ) )
]
+ SHorizontalBox : : Slot ( )
. Padding ( 2.0f )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. AutoWidth ( )
[
RemoveButtonWidget
] ;
EntryWidget - > SetEnabled ( IsGraphEditableAttribute ) ;
return EntryWidget ;
} ;
TArray < FName > InterfaceNames = ImplementedInterfaceNames . Array ( ) ;
InterfaceNames . Sort ( [ ] ( const FName & A , const FName & B ) { return A . LexicalLess ( B ) ; } ) ;
for ( const FName & InterfaceName : InterfaceNames )
{
InterfaceCategory . AddCustomRow ( FText : : FromName ( InterfaceName ) )
[
CreateInterfaceEntryWidget ( InterfaceName )
] ;
2022-03-01 14:29:17 -05:00
}
2024-06-10 13:41:25 -04:00
}
void FMetasoundInterfacesDetailCustomization : : UpdateInterfaceNames ( )
{
AddableInterfaceNames . Reset ( ) ;
ImplementedInterfaceNames . Reset ( ) ;
if ( const UObject * MetaSoundObject = GetMetaSound ( ) )
{
auto GetVersionName = [ ] ( const FMetasoundFrontendVersion & Version ) { return Version . Name ; } ;
const UClass * MetaSoundClass = MetaSoundObject - > GetClass ( ) ;
auto CanAddOrRemoveInterface = [ ClassName = MetaSoundClass - > GetClassPathName ( ) ] ( const FMetasoundFrontendVersion & Version )
{
using namespace Frontend ;
const FInterfaceRegistryKey Key = GetInterfaceRegistryKey ( Version ) ;
if ( const IInterfaceRegistryEntry * Entry = IInterfaceRegistry : : Get ( ) . FindInterfaceRegistryEntry ( Key ) )
{
if ( const FMetasoundFrontendInterfaceUClassOptions * Options = Entry - > GetInterface ( ) . FindClassOptions ( ClassName ) )
{
return Options - > bIsModifiable ;
}
// If no options are found for the given class, interface is modifiable by default.
return true ;
}
return false ;
} ;
const TSet < FMetasoundFrontendVersion > & ImplementedInterfaces = Builder - > GetBuilder ( ) . GetConstDocumentChecked ( ) . Interfaces ;
Algo : : TransformIf ( ImplementedInterfaces , ImplementedInterfaceNames , CanAddOrRemoveInterface , GetVersionName ) ;
TArray < FMetasoundFrontendInterface > Interfaces = Frontend : : ISearchEngine : : Get ( ) . FindAllInterfaces ( ) ;
for ( const FMetasoundFrontendInterface & Interface : Interfaces )
{
if ( ! ImplementedInterfaceNames . Contains ( Interface . Version . Name ) )
{
if ( CanAddOrRemoveInterface ( Interface . Version ) )
{
FString Name = Interface . Version . Name . ToString ( ) ;
AddableInterfaceNames . Add ( MakeShared < FString > ( MoveTemp ( Name ) ) ) ;
}
}
}
AddableInterfaceNames . Sort ( [ ] ( const TSharedPtr < FString > & A , const TSharedPtr < FString > & B ) { return A - > Compare ( * B ) < 0 ; } ) ;
}
}
} // namespace Metasound::Editor
2020-07-31 11:59:52 -04:00
# undef LOCTEXT_NAMESPACE