2021-03-19 15:10:57 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundNodeDetailCustomization.h"
2022-10-10 15:21:30 -04:00
# include "Analysis/MetasoundFrontendAnalyzerAddress.h"
2021-04-06 01:41:29 -04:00
# include "Components/AudioComponent.h"
2021-03-19 15:10:57 -04:00
# include "Containers/Set.h"
# include "Delegates/Delegate.h"
# include "Framework/Notifications/NotificationManager.h"
2024-02-01 19:54:26 -05:00
# include "HAL/PlatformApplicationMisc.h"
2021-03-19 15:10:57 -04:00
# include "IDetailChildrenBuilder.h"
# include "IDetailGroup.h"
# include "Internationalization/Text.h"
2021-04-07 02:59:10 -04:00
# include "MetasoundDataReference.h"
2021-12-13 18:15:01 -05:00
# include "MetasoundDataReferenceMacro.h"
2022-07-18 17:14:25 -04:00
# include "MetasoundEditorGraphBuilder.h"
2021-12-13 18:15:01 -05:00
# include "MetasoundEditorGraphInputNode.h"
2021-11-07 23:43:01 -05:00
# include "MetasoundEditorGraphSchema.h"
2021-03-19 15:10:57 -04:00
# include "MetasoundFrontend.h"
# include "MetasoundFrontendController.h"
2021-12-13 18:15:01 -05:00
# include "MetasoundFrontendDataTypeRegistry.h"
2021-03-19 15:10:57 -04:00
# include "MetasoundFrontendRegistries.h"
2024-04-30 02:33:39 -04:00
# include "MetasoundEditorSettings.h"
2022-03-22 14:01:46 -04:00
# include "Modules/ModuleManager.h"
2021-03-19 15:10:57 -04:00
# include "PropertyCustomizationHelpers.h"
# include "PropertyEditorDelegates.h"
2022-01-04 15:17:54 -05:00
# include "SAssetDropTarget.h"
2021-11-07 23:43:01 -05:00
# include "SMetasoundActionMenu.h"
2021-04-07 02:59:10 -04:00
# include "SMetasoundGraphNode.h"
2021-11-07 23:43:01 -05:00
# include "SSearchableComboBox.h"
2022-10-19 06:39:08 -04:00
# include "Styling/SlateColor.h"
2021-03-19 15:10:57 -04:00
# include "Templates/Casts.h"
# include "Templates/SharedPointer.h"
2022-03-22 14:01:46 -04:00
# include "Templates/UniquePtr.h"
2021-03-19 15:10:57 -04:00
# include "UObject/WeakObjectPtr.h"
# include "UObject/WeakObjectPtrTemplates.h"
2021-03-25 23:46:38 -04:00
# include "Widgets/Images/SImage.h"
# include "Widgets/Input/SButton.h"
2021-03-19 15:10:57 -04:00
# include "Widgets/Notifications/SNotificationList.h"
# include "Widgets/SToolTip.h"
# include "Widgets/SWidget.h"
# include "Widgets/Text/STextBlock.h"
2021-04-02 03:03:27 -04:00
# define LOCTEXT_NAMESPACE "MetaSoundEditor"
2021-03-19 15:10:57 -04:00
namespace Metasound
{
namespace Editor
{
2021-10-25 20:05:28 -04:00
namespace MemberCustomizationPrivate
2021-03-19 15:10:57 -04:00
{
2021-04-06 21:02:21 -04:00
/** Set of input types which are valid registered types, but should
* not show up as an input type option in the MetaSound editor . */
static const TSet < FName > HiddenInputTypeNames =
{
" Audio:Mono " ,
2022-10-10 15:21:30 -04:00
" Audio:Stereo " ,
2022-12-15 17:03:02 -05:00
GetMetasoundDataTypeName < Frontend : : FAnalyzerAddress > ( ) ,
" MetasoundParameterPack "
2021-04-06 21:02:21 -04:00
} ;
2022-01-04 15:17:54 -05:00
2022-02-09 12:52:07 -05:00
static const FText OverrideInputDefaultText = LOCTEXT ( " OverridePresetInputDefault " , " Override Inherited Default " ) ;
static const FText OverrideInputDefaultTooltip = LOCTEXT ( " OverridePresetInputTooltip " ,
2022-04-25 13:29:29 -04:00
" Enables overriding the input's inherited default value otherwise provided by the referenced graph. Setting to true disables auto-updating the input's default value if modified on the referenced asset. " ) ;
static const FText ConstructorPinText = LOCTEXT ( " ConstructorPinText " , " Is Constructor Pin " ) ;
static const FText ConstructorPinTooltip = LOCTEXT ( " ConstructorPinTooltip " ,
2022-08-23 18:22:57 -04:00
" Whether this input or output is a constructor pin. Constructor values are only read on construction (on play), and are not dynamically updated at runtime. " ) ;
2024-08-20 03:27:21 -04:00
static const FText AdvancedPinText = LOCTEXT ( " AdvancedPinText " , " Is Advanced Pin " ) ;
static const FText AdvancedPinTooltip = LOCTEXT ( " AdvancedPinTooltip " ,
" Advanced Pins are hidden by default on the node when this MetaSound is used in other graphs. " ) ;
2022-02-09 12:52:07 -05:00
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
// Retrieves the data type info if the literal property's member is found. Returns if the associated member is found, false if not.
bool GetDataTypeFromElementPropertyHandle ( TSharedPtr < IPropertyHandle > ElementPropertyHandle , Frontend : : FDataTypeRegistryInfo & OutDataTypeInfo )
2022-01-04 15:17:54 -05:00
{
using namespace Frontend ;
2024-09-10 10:26:02 -04:00
if ( ! ElementPropertyHandle . IsValid ( ) )
{
return false ;
}
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
OutDataTypeInfo = { } ;
2022-01-04 15:17:54 -05:00
TArray < UObject * > OuterObjects ;
ElementPropertyHandle - > GetOuterObjects ( OuterObjects ) ;
if ( OuterObjects . Num ( ) = = 1 )
{
UObject * Outer = OuterObjects . Last ( ) ;
if ( const UMetasoundEditorGraphMemberDefaultLiteral * DefaultLiteral = Cast < UMetasoundEditorGraphMemberDefaultLiteral > ( Outer ) )
{
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
if ( const UMetasoundEditorGraphMember * Member = DefaultLiteral - > FindMember ( ) )
2022-01-04 15:17:54 -05:00
{
2022-07-14 17:51:07 -04:00
FName DataTypeName = Member - > GetDataType ( ) ;
ensure ( IDataTypeRegistry : : Get ( ) . GetDataTypeInfo ( DataTypeName , OutDataTypeInfo ) ) ;
if ( OutDataTypeInfo . bIsArrayType )
{
DataTypeName = CreateElementTypeNameFromArrayTypeName ( DataTypeName ) ;
const bool bIsHiddenType = HiddenInputTypeNames . Contains ( DataTypeName ) ;
OutDataTypeInfo = { } ;
if ( ! bIsHiddenType )
{
ensure ( IDataTypeRegistry : : Get ( ) . GetDataTypeInfo ( DataTypeName , OutDataTypeInfo ) ) ;
}
}
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
return true ;
2022-01-04 15:17:54 -05:00
}
}
}
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
return false ;
2022-01-04 15:17:54 -05:00
}
// If DataType is an array type, creates & returns the array's
// element type. Otherwise, returns this type's DataTypeName.
FName GetPrimitiveTypeName ( const Frontend : : FDataTypeRegistryInfo & InDataTypeInfo )
{
2022-07-14 17:51:07 -04:00
return InDataTypeInfo . bIsArrayType
2022-01-04 15:17:54 -05:00
? CreateElementTypeNameFromArrayTypeName ( InDataTypeInfo . DataTypeName )
: InDataTypeInfo . DataTypeName ;
}
2024-02-20 18:20:16 -05:00
// Paste execute action for object member default values
2024-09-10 10:26:02 -04:00
FExecuteAction CreateDefaultValueObjectPasteExecuteAction ( TSharedPtr < IPropertyHandle > PropertyHandle )
2024-02-20 18:20:16 -05:00
{
2024-09-10 10:26:02 -04:00
return FExecuteAction : : CreateLambda ( [ PropertyHandle ] ( )
2024-02-20 18:20:16 -05:00
{
const FScopedTransaction Transaction ( LOCTEXT ( " PasteObjectArrayProperty " , " Paste Property " ) ) ;
FString ClipboardValue ;
FPlatformApplicationMisc : : ClipboardPaste ( ClipboardValue ) ;
if ( ClipboardValue . IsEmpty ( ) )
{
return ;
}
Frontend : : FDataTypeRegistryInfo DataTypeInfo ;
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
const bool bMemberFound = MemberCustomizationPrivate : : GetDataTypeFromElementPropertyHandle ( PropertyHandle , DataTypeInfo ) ;
2024-02-20 18:20:16 -05:00
UClass * ProxyGenClass = DataTypeInfo . ProxyGeneratorClass ;
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
if ( ! bMemberFound | | ! ProxyGenClass )
2024-02-20 18:20:16 -05:00
{
return ;
}
FTopLevelAssetPath ClassPath = ProxyGenClass - > GetClassPathName ( ) ;
// Try to reformat string
// Split into array of objects
TArray < FString > Values ;
// Copying from other MS, still parse to verify object type
// or copying from BP
if ( ( ClipboardValue . StartsWith ( " (( " ) & & ClipboardValue . EndsWith ( " )) " ) ) | |
( ClipboardValue . StartsWith ( " ( \" " ) & & ClipboardValue . EndsWith ( " \" ) " ) ) )
{
// Remove first and last parentheses
ClipboardValue . LeftChop ( 1 ) . RightChop ( 1 ) . ParseIntoArrayWS ( Values , TEXT ( " , " ) , true ) ;
}
// Copying from content browser
else
{
ClipboardValue . ParseIntoArrayWS ( Values , TEXT ( " , " ) , true ) ;
}
2024-09-10 10:26:02 -04:00
if ( ! Values . IsEmpty ( ) )
2024-02-20 18:20:16 -05:00
{
2024-09-10 10:26:02 -04:00
const bool bIsArray = PropertyHandle - > AsArray ( ) . IsValid ( ) ;
2024-02-20 18:20:16 -05:00
TStringBuilder < 512 > Builder ;
if ( bIsArray )
{
Builder < < TEXT ( " ( " ) ;
}
for ( FString & Value : Values )
{
// Remove (Object= ) wrapper (other MetaSound case)
if ( Value . Contains ( TEXT ( " Object= " ) ) )
{
Value = Value . LeftChop ( 2 ) . RightChop ( 9 ) ;
}
// Validate the class path (before the first ')
FString ValueClassPath = Value . Left ( Value . Find ( " ' " ) ) ;
// Remove beginning quote (BP case)
if ( ValueClassPath . StartsWith ( TEXT ( " \" " ) ) )
{
ValueClassPath . RightChopInline ( 1 ) ;
}
// Wrap objects in (Object=*)
if ( ValueClassPath = = ClassPath . ToString ( ) )
{
Builder < < TEXT ( " (Object= " ) ;
Builder < < Value ;
Builder < < TEXT ( " ), " ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to paste object of type %s which does not match default value type %s " ) , * ValueClassPath , * ClassPath . ToString ( ) ) ;
return ;
}
}
// Remove last comma
if ( Builder . Len ( ) > 0 )
{
Builder . RemoveSuffix ( 1 ) ;
}
if ( bIsArray )
{
Builder < < TEXT ( " ) " ) ;
}
FString FormattedString = Builder . ToString ( ) ;
PropertyHandle - > SetValueFromFormattedString ( FormattedString , EPropertyValueSetFlags : : InstanceObjects ) ;
}
} ) ;
}
// Create copy/paste actions for member default value for object and object array types
2024-09-10 10:26:02 -04:00
void CreateDefaultValueObjectCopyPasteActions ( FDetailWidgetRow & InWidgetRow , TSharedPtr < IPropertyHandle > PropertyHandle )
2024-02-20 18:20:16 -05:00
{
// Copy action
FUIAction CopyAction ;
2024-09-10 10:26:02 -04:00
CopyAction . ExecuteAction = FExecuteAction : : CreateLambda ( [ PropertyHandle ] ( )
2024-02-20 18:20:16 -05:00
{
FString Value ;
if ( PropertyHandle - > GetValueAsFormattedString ( Value , PPF_Copy ) = = FPropertyAccess : : Success )
{
FPlatformApplicationMisc : : ClipboardCopy ( * Value ) ;
}
} ) ;
// Paste action
TArray < UObject * > OuterObjects ;
UMetasoundEditorGraphMember * GraphMember = nullptr ;
PropertyHandle - > GetOuterObjects ( OuterObjects ) ;
if ( ! OuterObjects . IsEmpty ( ) )
{
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
if ( UMetasoundEditorGraphMemberDefaultLiteral * Literal = Cast < UMetasoundEditorGraphMemberDefaultLiteral > ( OuterObjects [ 0 ] ) )
{
GraphMember = Literal - > FindMember ( ) ;
}
2024-02-20 18:20:16 -05:00
}
FUIAction PasteAction ;
// Paste only enabled if graph is editable (for variables/outputs)
// or if graph is editable and input is not an interface member and is overridden (for inputs)
PasteAction . CanExecuteAction = FCanExecuteAction : : CreateLambda ( [ GraphMember = GraphMember ] ( )
{
if ( ! GraphMember ) { return false ; }
const bool bIsGraphEditable = GraphMember - > GetOwningGraph ( ) - > IsEditable ( ) ;
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( GraphMember ) )
{
Frontend : : FConstNodeHandle InputNodeHandle = Input - > GetConstNodeHandle ( ) ;
const TSet < FName > & InputsInheritingDefault = InputNodeHandle - > GetOwningGraph ( ) - > GetInputsInheritingDefault ( ) ;
FName NodeName = InputNodeHandle - > GetNodeName ( ) ;
return ! Input - > IsInterfaceMember ( ) & & ( bIsGraphEditable | | ! InputsInheritingDefault . Contains ( NodeName ) ) ;
}
else
{
return bIsGraphEditable ;
}
} ) ;
2024-09-10 10:26:02 -04:00
PasteAction . ExecuteAction = CreateDefaultValueObjectPasteExecuteAction ( PropertyHandle ) ;
2024-02-20 18:20:16 -05:00
InWidgetRow . CopyAction ( CopyAction ) ;
InWidgetRow . PasteAction ( PasteAction ) ;
}
2021-10-25 20:05:28 -04:00
} // namespace MemberCustomizationPrivate
2021-10-12 21:21:22 -04:00
FMetasoundFloatLiteralCustomization : : ~ FMetasoundFloatLiteralCustomization ( )
{
if ( FloatLiteral . IsValid ( ) )
{
2021-12-13 18:15:01 -05:00
FloatLiteral - > OnClampChanged . Remove ( OnClampChangedDelegateHandle ) ;
2021-10-12 21:21:22 -04:00
}
}
2024-08-27 19:05:41 -04:00
void FMetasoundFloatLiteralCustomization : : CustomizeDefaults ( UMetasoundEditorGraphMemberDefaultLiteral & InLiteral , IDetailLayoutBuilder & InDetailLayout )
2021-10-12 21:21:22 -04:00
{
2022-01-04 15:17:54 -05:00
check ( DefaultCategoryBuilder ) ;
2021-10-12 21:21:22 -04:00
2024-08-27 19:05:41 -04:00
TArray < UObject * > EditLiterals ;
if ( UMetasoundEditorGraphMemberDefaultFloat * CastLiteral = Cast < UMetasoundEditorGraphMemberDefaultFloat > ( & InLiteral ) ; ensure ( CastLiteral ) )
2021-10-12 21:21:22 -04:00
{
2024-08-27 19:05:41 -04:00
EditLiterals = { CastLiteral } ;
FloatLiteral = CastLiteral ;
2021-10-12 21:21:22 -04:00
}
2024-08-27 19:05:41 -04:00
else
2022-01-04 15:17:54 -05:00
{
2024-08-27 19:05:41 -04:00
FloatLiteral . Reset ( ) ;
return ;
2022-01-04 15:17:54 -05:00
}
2024-08-27 19:05:41 -04:00
FMetasoundDefaultLiteralCustomizationBase : : CustomizeDefaults ( InLiteral , InDetailLayout ) ;
2022-01-14 14:01:09 -05:00
2024-08-27 19:05:41 -04:00
TAttribute < EVisibility > DefaultVisibility = GetDefaultVisibility ( ) ;
IDetailCategoryBuilder & EditorOptionsBuilder = InDetailLayout . EditCategory ( " DefaultEditorOptions " ) ;
auto AddOptionPropRow = [ & ] ( FName PropertyName )
2021-10-12 21:21:22 -04:00
{
2024-08-27 19:05:41 -04:00
IDetailPropertyRow * Row = EditorOptionsBuilder . AddExternalObjectProperty ( EditLiterals , PropertyName ) ;
if ( ensure ( Row ) )
2021-10-12 21:21:22 -04:00
{
2024-08-27 19:05:41 -04:00
Row - > Visibility ( DefaultVisibility ) ;
2024-09-19 16:31:42 -04:00
Row - > IsEnabled ( GetEnabled ( ) ) ;
2024-08-27 19:05:41 -04:00
}
return Row ;
} ;
if ( IDetailPropertyRow * ClampRow = AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , ClampDefault ) ) )
{
2024-09-19 16:31:42 -04:00
// Apply the clamp range to the default value if using a widget or ClampDefault is otherwise true
// Only show clamp row if not using a widget (widgets always require a clamp and range)
2024-10-01 19:06:30 -04:00
// Presets and non inputs are an exception, because they may have a widget inherited, but that doesn't apply and isn't editable,
2024-08-27 19:05:41 -04:00
const bool bUsingWidget = FloatLiteral - > WidgetType ! = EMetasoundMemberDefaultWidget : : None ;
2024-09-19 16:31:42 -04:00
const UMetasoundEditorGraphMember * Member = FloatLiteral - > FindMember ( ) ;
const bool bIsPreset = Member ? Member - > GetFrontendBuilderChecked ( ) . IsPreset ( ) : false ;
2024-10-01 19:06:30 -04:00
const bool bIsInput = Member ? Cast < UMetasoundEditorGraphInput > ( Member ) ! = nullptr : true ;
const bool bClampActiveWithoutWidget = ! bUsingWidget | | bIsPreset | | ! bIsInput ;
const bool bApplyRange = FloatLiteral - > ClampDefault | | ! bClampActiveWithoutWidget ;
2024-09-19 16:31:42 -04:00
2024-10-01 19:06:30 -04:00
ClampRow - > Visibility ( bClampActiveWithoutWidget ? DefaultVisibility : EVisibility : : Hidden ) ;
2024-08-27 19:05:41 -04:00
for ( TSharedPtr < IPropertyHandle > & DefaultValueHandle : DefaultProperties )
{
if ( DefaultValueHandle . IsValid ( ) )
2022-02-09 12:52:07 -05:00
{
2024-09-19 16:31:42 -04:00
if ( bApplyRange )
2024-08-27 19:05:41 -04:00
{
FVector2D Range = FloatLiteral - > GetRange ( ) ;
DefaultValueHandle - > SetInstanceMetaData ( " ClampMin " , FString : : Printf ( TEXT ( " %f " ) , Range . X ) ) ;
DefaultValueHandle - > SetInstanceMetaData ( " ClampMax " , FString : : Printf ( TEXT ( " %f " ) , Range . Y ) ) ;
}
else // Stop clamping
{
DefaultValueHandle - > SetInstanceMetaData ( " ClampMin " , " " ) ;
DefaultValueHandle - > SetInstanceMetaData ( " ClampMax " , " " ) ;
}
2022-02-09 12:52:07 -05:00
}
2021-10-12 21:21:22 -04:00
}
2024-08-27 19:05:41 -04:00
FloatLiteral - > OnClampChanged . Remove ( OnClampChangedDelegateHandle ) ;
OnClampChangedDelegateHandle = FloatLiteral - > OnClampChanged . AddLambda ( [ this ] ( bool ClampInput )
2021-10-12 21:21:22 -04:00
{
if ( FloatLiteral . IsValid ( ) )
{
2021-12-13 18:15:01 -05:00
FloatLiteral - > OnClampChanged . Remove ( OnClampChangedDelegateHandle ) ;
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
if ( const UMetasoundEditorGraphMember * Member = FloatLiteral - > FindMember ( ) )
2021-10-12 21:21:22 -04:00
{
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
FMetasoundAssetBase & MetasoundAsset = Editor : : FGraphBuilder : : GetOutermostMetaSoundChecked ( * FloatLiteral ) ;
MetasoundAsset . GetModifyContext ( ) . AddMemberIDsModified ( { Member - > GetMemberID ( ) } ) ;
2021-10-12 21:21:22 -04:00
}
}
} ) ;
2022-01-14 14:01:09 -05:00
2024-09-19 16:31:42 -04:00
if ( bApplyRange )
2022-01-14 14:01:09 -05:00
{
2024-08-27 19:05:41 -04:00
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , Range ) ) ;
2022-01-14 14:01:09 -05:00
}
}
2024-05-29 15:33:29 -04:00
// Enable widget options for editable inputs only
2022-06-16 12:30:27 -04:00
bool bShowWidgetOptions = false ;
2024-05-29 15:33:29 -04:00
if ( const UMetasoundEditorGraphInput * ParentMember = Cast < UMetasoundEditorGraphInput > ( InLiteral . FindMember ( ) ) )
2022-01-14 14:01:09 -05:00
{
if ( const UMetasoundEditorGraph * OwningGraph = ParentMember - > GetOwningGraph ( ) )
{
2024-05-27 02:59:37 -04:00
bShowWidgetOptions = OwningGraph - > IsEditable ( ) ;
2022-01-14 14:01:09 -05:00
}
2021-10-12 21:21:22 -04:00
}
2022-01-04 15:17:54 -05:00
// add input widget properties
2022-06-16 12:30:27 -04:00
if ( bShowWidgetOptions )
2022-01-14 14:01:09 -05:00
{
2024-08-27 19:05:41 -04:00
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , WidgetType ) ) ;
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , WidgetOrientation ) ) ;
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , WidgetUnitValueType ) ) ;
if ( FloatLiteral - > WidgetType ! = EMetasoundMemberDefaultWidget : : None & & FloatLiteral - > WidgetUnitValueType = = EAudioUnitsValueType : : Volume )
2022-01-14 14:01:09 -05:00
{
2024-08-27 19:05:41 -04:00
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , VolumeWidgetUseLinearOutput ) ) ;
if ( FloatLiteral - > VolumeWidgetUseLinearOutput )
2022-10-19 15:34:44 -04:00
{
2024-08-27 19:05:41 -04:00
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultFloat , VolumeWidgetDecibelRange ) ) ;
2022-10-19 15:34:44 -04:00
}
2022-01-14 14:01:09 -05:00
}
}
2021-03-23 17:55:31 -04:00
}
2024-04-16 05:09:28 -04:00
FMetasoundBoolLiteralCustomization : : ~ FMetasoundBoolLiteralCustomization ( )
{
}
2024-08-27 19:05:41 -04:00
void FMetasoundBoolLiteralCustomization : : CustomizeDefaults ( UMetasoundEditorGraphMemberDefaultLiteral & InLiteral , IDetailLayoutBuilder & InDetailLayout )
2024-04-16 05:09:28 -04:00
{
check ( DefaultCategoryBuilder ) ;
2024-09-11 20:41:47 -04:00
TArray < UObject * > EditLiterals ;
if ( UMetasoundEditorGraphMemberDefaultBool * CastLiteral = Cast < UMetasoundEditorGraphMemberDefaultBool > ( & InLiteral ) ; ensure ( CastLiteral ) )
2024-04-16 05:09:28 -04:00
{
2024-09-11 20:41:47 -04:00
EditLiterals = { CastLiteral } ;
BoolLiteral = CastLiteral ;
}
else
{
BoolLiteral . Reset ( ) ;
2024-08-27 19:05:41 -04:00
return ;
2024-04-16 05:09:28 -04:00
}
2024-10-18 13:20:42 -04:00
bool bIsTrigger = false ;
const UMetasoundEditorGraphMember * Member = BoolLiteral - > FindMember ( ) ;
if ( ! Member )
{
return ;
}
// Non-input members don't show any options for inputs, so early out if trigger.
bIsTrigger = Member - > GetDataType ( ) = = Metasound : : GetMetasoundDataTypeName < Metasound : : FTrigger > ( ) ;
if ( bIsTrigger & & ! Member - > IsA < UMetasoundEditorGraphInput > ( ) )
{
return ;
}
2024-09-11 20:41:47 -04:00
FMetasoundDefaultLiteralCustomizationBase : : CustomizeDefaults ( InLiteral , InDetailLayout ) ;
TAttribute < EVisibility > DefaultVisibility = GetDefaultVisibility ( ) ;
IDetailCategoryBuilder & EditorOptionsBuilder = InDetailLayout . EditCategory ( " DefaultEditorOptions " ) ;
auto AddOptionPropRow = [ & ] ( FName PropertyName )
2024-04-16 05:09:28 -04:00
{
2024-09-11 20:41:47 -04:00
IDetailPropertyRow * Row = EditorOptionsBuilder . AddExternalObjectProperty ( EditLiterals , PropertyName ) ;
if ( ensure ( Row ) )
2024-04-16 05:09:28 -04:00
{
2024-09-11 20:41:47 -04:00
Row - > Visibility ( DefaultVisibility ) ;
2024-08-27 20:01:10 -04:00
}
2024-09-11 20:41:47 -04:00
return Row ;
} ;
2024-08-27 20:01:10 -04:00
2024-09-11 20:41:47 -04:00
bool bShowWidgetOptions = false ;
2024-09-17 17:44:21 -04:00
const UMetasoundEditorSettings * EditorSettings = GetDefault < UMetasoundEditorSettings > ( ) ;
check ( EditorSettings ) ;
if ( EditorSettings - > bUseAudioMaterialWidgets )
2024-09-11 20:41:47 -04:00
{
2024-10-18 13:20:42 -04:00
if ( ! bIsTrigger )
2024-08-27 20:01:10 -04:00
{
2024-10-18 13:20:42 -04:00
if ( const UMetasoundEditorGraph * OwningGraph = Member - > GetOwningGraph ( ) )
2024-09-17 17:44:21 -04:00
{
2024-10-18 13:20:42 -04:00
bShowWidgetOptions = OwningGraph - > IsEditable ( ) ;
2024-09-17 17:44:21 -04:00
}
2024-09-11 20:41:47 -04:00
}
}
2024-08-27 20:01:10 -04:00
2024-09-11 20:41:47 -04:00
if ( bShowWidgetOptions )
{
2024-10-18 13:20:42 -04:00
AddOptionPropRow ( GET_MEMBER_NAME_CHECKED ( UMetasoundEditorGraphMemberDefaultBool , WidgetType ) ) ;
}
}
TAttribute < EVisibility > FMetasoundBoolLiteralCustomization : : GetDefaultVisibility ( ) const
{
if ( UMetasoundEditorGraphMemberDefaultBool * DefaultBool = BoolLiteral . Pin ( ) . Get ( ) )
{
UMetasoundEditorGraphMember * Member = DefaultBool - > FindMember ( ) ;
if ( Member - > IsA < UMetasoundEditorGraphInput > ( ) )
2024-09-11 20:41:47 -04:00
{
2024-10-18 13:20:42 -04:00
return FMetasoundDefaultLiteralCustomizationBase : : GetDefaultVisibility ( ) ;
}
else
{
const bool bIsTrigger = Member - > GetDataType ( ) = = Metasound : : GetMetasoundDataTypeName < Metasound : : FTrigger > ( ) ;
if ( bIsTrigger )
{
return EVisibility : : Collapsed ;
}
2024-04-16 05:09:28 -04:00
}
}
2024-10-18 13:20:42 -04:00
return FMetasoundDefaultLiteralCustomizationBase : : GetDefaultVisibility ( ) ;
2024-04-16 05:09:28 -04:00
}
2024-08-27 19:05:41 -04:00
void FMetasoundObjectArrayLiteralCustomization : : CustomizeDefaults ( UMetasoundEditorGraphMemberDefaultLiteral & InLiteral , IDetailLayoutBuilder & InDetailLayout )
2021-03-23 17:55:31 -04:00
{
2022-01-04 15:17:54 -05:00
check ( DefaultCategoryBuilder ) ;
2021-03-23 17:55:31 -04:00
2024-09-10 10:26:02 -04:00
FMetasoundDefaultLiteralCustomizationBase : : CustomizePageDefaultRows ( InLiteral , InDetailLayout ) ;
2021-03-23 17:55:31 -04:00
}
2024-10-09 16:06:12 -04:00
void FMetasoundObjectArrayLiteralCustomization : : BuildDefaultValueWidget ( IDetailPropertyRow & ValueRow , TSharedPtr < IPropertyHandle > ValueProperty )
{
if ( ! ValueProperty . IsValid ( ) )
{
return ;
}
( * ValueRow . CustomValueWidget ( ) )
[
SNew ( SAssetDropTarget )
. bSupportsMultiDrop ( true )
. OnAreAssetsAcceptableForDropWithReason_Lambda ( [ this , ValueProperty ] ( TArrayView < FAssetData > InAssets , FText & OutReason )
{
Frontend : : FDataTypeRegistryInfo DataTypeInfo ;
const bool bMemberFound = MemberCustomizationPrivate : : GetDataTypeFromElementPropertyHandle ( ValueProperty , DataTypeInfo ) ;
bool bCanDrop = bMemberFound ;
if ( UClass * ProxyGenClass = DataTypeInfo . ProxyGeneratorClass ; bCanDrop & & bMemberFound )
{
bCanDrop = true ;
for ( const FAssetData & AssetData : InAssets )
{
if ( UClass * Class = AssetData . GetClass ( ) )
{
if ( DataTypeInfo . bIsExplicit )
{
bCanDrop & = Class = = DataTypeInfo . ProxyGeneratorClass ;
}
else
{
bCanDrop & = Class - > IsChildOf ( DataTypeInfo . ProxyGeneratorClass ) ;
}
}
}
}
return bCanDrop ;
} )
. OnAssetsDropped_Lambda ( [ this , ValueProperty ] ( const FDragDropEvent & DragDropEvent , TArrayView < FAssetData > InAssets )
{
TSharedPtr < IPropertyHandleArray > ArrayProperty = ValueProperty - > AsArray ( ) ;
if ( ArrayProperty . IsValid ( ) )
{
FScopedTransaction Transaction ( LOCTEXT ( " DragDropInputAssets " , " Drop Asset(s) on MetaSound Input " )) ;
for ( const FAssetData & AssetData : InAssets )
{
uint32 AddIndex = INDEX_NONE ;
ArrayProperty - > GetNumElements ( AddIndex ) ;
ArrayProperty - > AddItem ( ) ;
TSharedPtr < IPropertyHandle > ElementHandle = ArrayProperty - > GetElement ( static_cast < int32 > ( AddIndex ) ) ;
TSharedPtr < IPropertyHandle > ObjectHandle = ElementHandle - > GetChildHandle ( GET_MEMBER_NAME_CHECKED ( FMetasoundEditorGraphMemberDefaultObjectRef , Object ) ) ;
ObjectHandle - > SetValue ( AssetData . GetAsset ( ) ) ;
}
}
} )
[
ValueProperty - > CreatePropertyValueWidget ( )
]
] ;
}
2021-12-13 18:15:01 -05:00
FText FMetasoundMemberDefaultBoolDetailCustomization : : GetPropertyNameOverride ( ) const
2021-03-23 17:55:31 -04:00
{
2022-01-04 15:17:54 -05:00
using namespace MemberCustomizationPrivate ;
if ( GetPrimitiveTypeName ( DataTypeInfo ) = = Metasound : : GetMetasoundDataTypeName < Metasound : : FTrigger > ( ) )
2021-03-23 17:55:31 -04:00
{
return LOCTEXT ( " TriggerInput_SimulateTitle " , " Simulate " ) ;
}
return FText : : GetEmpty ( ) ;
}
2021-12-13 18:15:01 -05:00
TSharedRef < SWidget > FMetasoundMemberDefaultBoolDetailCustomization : : CreateStructureWidget ( TSharedPtr < IPropertyHandle > & StructPropertyHandle ) const
2021-03-23 17:55:31 -04:00
{
using namespace Frontend ;
2022-01-04 15:17:54 -05:00
using namespace MemberCustomizationPrivate ;
2021-03-23 17:55:31 -04:00
2021-12-13 18:15:01 -05:00
TSharedPtr < IPropertyHandle > ValueProperty = StructPropertyHandle - > GetChildHandle ( GET_MEMBER_NAME_CHECKED ( FMetasoundEditorGraphMemberDefaultBoolRef , Value ) ) ;
if ( ValueProperty . IsValid ( ) )
2021-03-23 17:55:31 -04:00
{
2021-12-13 18:15:01 -05:00
// Not a trigger, so just display as underlying literal type (bool)
2022-01-04 15:17:54 -05:00
if ( GetPrimitiveTypeName ( DataTypeInfo ) ! = Metasound : : GetMetasoundDataTypeName < Metasound : : FTrigger > ( ) )
2021-03-23 17:55:31 -04:00
{
2021-12-13 18:15:01 -05:00
return ValueProperty - > CreatePropertyValueWidget ( ) ;
}
2021-03-23 17:55:31 -04:00
2021-12-13 18:15:01 -05:00
TAttribute < bool > EnablementAttribute = false ;
TAttribute < EVisibility > VisibilityAttribute = EVisibility : : Visible ;
TArray < UObject * > OuterObjects ;
ValueProperty - > GetOuterObjects ( OuterObjects ) ;
if ( ! OuterObjects . IsEmpty ( ) )
{
if ( UMetasoundEditorGraphMemberDefaultLiteral * Literal = Cast < UMetasoundEditorGraphMemberDefaultLiteral > ( OuterObjects . Last ( ) ) )
2021-04-07 02:59:10 -04:00
{
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( Literal - > FindMember ( ) ) )
2021-04-07 02:59:10 -04:00
{
2021-12-13 18:15:01 -05:00
// Don't display trigger simulation widget if its a trigger
// provided by an interface that does not support transmission.
const FInterfaceRegistryKey Key = GetInterfaceRegistryKey ( Input - > GetInterfaceVersion ( ) ) ;
const IInterfaceRegistryEntry * Entry = IInterfaceRegistry : : Get ( ) . FindInterfaceRegistryEntry ( Key ) ;
if ( ! Entry | | Entry - > GetRouterName ( ) = = Audio : : IParameterTransmitter : : RouterName )
{
EnablementAttribute = true ;
return SMetaSoundGraphNode : : CreateTriggerSimulationWidget ( * Literal , MoveTemp ( VisibilityAttribute ) , MoveTemp ( EnablementAttribute ) ) ;
}
const FText DisabledToolTip = LOCTEXT ( " NonTransmittibleInputTriggerSimulationDisabledTooltip " , " Trigger simulation disabled: Parent interface does not support being updated by game thread parameters. " ) ;
return SMetaSoundGraphNode : : CreateTriggerSimulationWidget ( * Literal , MoveTemp ( VisibilityAttribute ) , MoveTemp ( EnablementAttribute ) , & DisabledToolTip ) ;
2021-04-07 02:59:10 -04:00
}
}
2021-03-23 17:55:31 -04:00
}
}
return SNullWidget : : NullWidget ;
2021-03-19 15:10:57 -04:00
}
2021-12-13 18:15:01 -05:00
TSharedRef < SWidget > FMetasoundMemberDefaultIntDetailCustomization : : CreateStructureWidget ( TSharedPtr < IPropertyHandle > & StructPropertyHandle ) const
2021-03-19 15:10:57 -04:00
{
using namespace Frontend ;
2022-01-04 15:17:54 -05:00
using namespace MemberCustomizationPrivate ;
2021-03-19 15:10:57 -04:00
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
// DataType can be reset during deletion of a literal value. Customization can repaint briefly before the literal is removed,
// so just ignores if DataType is invalid.
const bool bIsValidDataType = ! DataTypeInfo . DataTypeName . IsNone ( ) ;
if ( bIsValidDataType )
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
TSharedPtr < IPropertyHandle > ValueProperty = StructPropertyHandle - > GetChildHandle ( GET_MEMBER_NAME_CHECKED ( FMetasoundEditorGraphMemberDefaultIntRef , Value ) ) ;
2021-03-19 15:10:57 -04:00
if ( ValueProperty . IsValid ( ) )
{
2022-01-04 15:17:54 -05:00
TSharedPtr < const IEnumDataTypeInterface > EnumInterface = IDataTypeRegistry : : Get ( ) . GetEnumInterfaceForDataType ( GetPrimitiveTypeName ( DataTypeInfo ) ) ;
2021-03-19 15:10:57 -04:00
// Not an enum, so just display as underlying type (int32)
if ( ! EnumInterface . IsValid ( ) )
{
return ValueProperty - > CreatePropertyValueWidget ( ) ;
}
auto GetAll = [ Interface = EnumInterface ] ( TArray < TSharedPtr < FString > > & OutStrings , TArray < TSharedPtr < SToolTip > > & OutTooltips , TArray < bool > & )
{
for ( const IEnumDataTypeInterface : : FGenericInt32Entry & i : Interface - > GetAllEntries ( ) )
{
OutTooltips . Emplace ( SNew ( SToolTip ) . Text ( i . Tooltip ) ) ;
OutStrings . Emplace ( MakeShared < FString > ( i . DisplayName . ToString ( ) ) ) ;
}
} ;
auto GetValue = [ Interface = EnumInterface , Prop = ValueProperty ] ( )
{
int32 IntValue ;
if ( Prop - > GetValue ( IntValue ) ! = FPropertyAccess : : Success )
{
IntValue = Interface - > GetDefaultValue ( ) ;
2021-03-31 00:23:34 -04:00
UE_LOG ( LogMetasoundEditor , Warning , TEXT ( " Failed to read int Property '%s', defaulting. " ) , * GetNameSafe ( Prop - > GetProperty ( ) ) ) ;
2021-03-19 15:10:57 -04:00
}
if ( TOptional < IEnumDataTypeInterface : : FGenericInt32Entry > Result = Interface - > FindByValue ( IntValue ) )
{
return Result - > DisplayName . ToString ( ) ;
}
2021-03-31 00:23:34 -04:00
UE_LOG ( LogMetasoundEditor , Warning , TEXT ( " Failed to resolve int value '%d' to a valid enum value for enum '%s' " ) ,
2021-03-19 15:10:57 -04:00
IntValue , * Interface - > GetNamespace ( ) . ToString ( ) ) ;
// Return default (should always succeed as we can't have empty Enums and we must have a default).
return Interface - > FindByValue ( Interface - > GetDefaultValue ( ) ) - > DisplayName . ToString ( ) ;
} ;
auto SelectedValue = [ Interface = EnumInterface , Prop = ValueProperty ] ( const FString & InSelected )
{
TOptional < IEnumDataTypeInterface : : FGenericInt32Entry > Found =
Interface - > FindEntryBy ( [ TextSelected = FText : : FromString ( InSelected ) ] ( const IEnumDataTypeInterface : : FGenericInt32Entry & i )
{
return i . DisplayName . EqualTo ( TextSelected ) ;
} ) ;
if ( Found )
{
// Only save the changes if its different and we can read the old value to check that.
int32 CurrentValue ;
bool bReadCurrentValue = Prop - > GetValue ( CurrentValue ) = = FPropertyAccess : : Success ;
if ( ( bReadCurrentValue & & CurrentValue ! = Found - > Value ) | | ! bReadCurrentValue )
{
ensure ( Prop - > SetValue ( Found - > Value ) = = FPropertyAccess : : Success ) ;
}
}
else
{
2021-03-31 00:23:34 -04:00
UE_LOG ( LogMetasoundEditor , Warning , TEXT ( " Failed to Set Valid Value for Property '%s' with Value of '%s', writing default. " ) ,
2021-03-19 15:10:57 -04:00
* GetNameSafe ( Prop - > GetProperty ( ) ) , * InSelected ) ;
ensure ( Prop - > SetValue ( Interface - > GetDefaultValue ( ) ) = = FPropertyAccess : : Success ) ;
}
} ;
return PropertyCustomizationHelpers : : MakePropertyComboBox (
nullptr ,
FOnGetPropertyComboBoxStrings : : CreateLambda ( GetAll ) ,
FOnGetPropertyComboBoxValue : : CreateLambda ( GetValue ) ,
FOnPropertyComboBoxValueSelected : : CreateLambda ( SelectedValue )
) ;
}
}
return SNullWidget : : NullWidget ;
}
2021-12-13 18:15:01 -05:00
TSharedRef < SWidget > FMetasoundMemberDefaultObjectDetailCustomization : : CreateStructureWidget ( TSharedPtr < IPropertyHandle > & StructPropertyHandle ) const
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
TSharedPtr < IPropertyHandle > PropertyHandle = StructPropertyHandle - > GetChildHandle ( GET_MEMBER_NAME_CHECKED ( FMetasoundEditorGraphMemberDefaultObjectRef , Object ) ) ;
2021-03-19 15:10:57 -04:00
2021-11-07 23:43:01 -05:00
const IMetasoundEditorModule & EditorModule = FModuleManager : : GetModuleChecked < IMetasoundEditorModule > ( " MetaSoundEditor " ) ;
2023-05-26 13:55:21 -04:00
auto FilterAsset = [ InEditorModule = & EditorModule , & InDataTypeInfo = DataTypeInfo ] ( const FAssetData & InAsset )
2021-03-19 15:10:57 -04:00
{
2023-05-26 13:55:21 -04:00
if ( InDataTypeInfo . ProxyGeneratorClass )
2021-03-19 15:10:57 -04:00
{
2021-11-07 23:43:01 -05:00
if ( UClass * Class = InAsset . GetClass ( ) )
2021-03-19 15:10:57 -04:00
{
2023-05-26 13:55:21 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
if ( InEditorModule - > IsExplicitProxyClass ( * InDataTypeInfo . ProxyGeneratorClass ) )
2021-11-07 23:43:01 -05:00
{
2023-05-26 13:55:21 -04:00
return Class ! = InDataTypeInfo . ProxyGeneratorClass ;
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
if ( InDataTypeInfo . bIsExplicit )
{
return Class ! = InDataTypeInfo . ProxyGeneratorClass ;
2021-11-07 23:43:01 -05:00
}
2023-05-26 13:55:21 -04:00
return ! Class - > IsChildOf ( InDataTypeInfo . ProxyGeneratorClass ) ;
2021-03-19 15:10:57 -04:00
}
}
2021-11-07 23:43:01 -05:00
return true ;
} ;
auto ValidateAsset = [ FilterAsset ] ( const FAssetData & InAsset )
{
2022-01-04 15:17:54 -05:00
// A null asset reference is a valid default
return InAsset . IsValid ( ) ? ! FilterAsset ( InAsset ) : true ;
2021-03-19 15:10:57 -04:00
} ;
auto GetAssetPath = [ PropertyHandle = PropertyHandle ] ( )
{
UObject * Object = nullptr ;
if ( PropertyHandle - > GetValue ( Object ) = = FPropertyAccess : : Success )
{
return Object - > GetPathName ( ) ;
}
return FString ( ) ;
} ;
return SNew ( SObjectPropertyEntryBox )
2021-04-05 19:26:15 -04:00
. AllowClear ( true )
2022-01-04 15:17:54 -05:00
. AllowedClass ( DataTypeInfo . ProxyGeneratorClass )
2021-03-19 15:10:57 -04:00
. DisplayBrowse ( true )
. DisplayThumbnail ( true )
2021-08-18 15:16:57 -04:00
. DisplayUseSelected ( true )
2022-01-04 15:17:54 -05:00
. NewAssetFactories ( PropertyCustomizationHelpers : : GetNewAssetFactoriesForClasses ( { DataTypeInfo . ProxyGeneratorClass } ) )
2021-08-18 15:16:57 -04:00
. ObjectPath_Lambda ( GetAssetPath )
. OnShouldFilterAsset_Lambda ( FilterAsset )
. OnShouldSetAsset_Lambda ( ValidateAsset )
. PropertyHandle ( PropertyHandle ) ;
2021-03-19 15:10:57 -04:00
}
2022-01-04 15:17:54 -05:00
TSharedRef < SWidget > FMetasoundDefaultMemberElementDetailCustomizationBase : : CreateNameWidget ( TSharedPtr < IPropertyHandle > StructPropertyHandle ) const
2021-03-23 17:55:31 -04:00
{
const FText PropertyName = GetPropertyNameOverride ( ) ;
if ( ! PropertyName . IsEmpty ( ) )
{
return SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( PropertyName ) ;
}
return SNew ( STextBlock )
2021-12-13 18:15:01 -05:00
. Text ( MemberCustomizationStyle : : DefaultPropertyText )
2021-03-23 17:55:31 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) ) ;
}
2022-01-04 15:17:54 -05:00
TSharedRef < SWidget > FMetasoundDefaultMemberElementDetailCustomizationBase : : CreateValueWidget ( TSharedPtr < IPropertyHandleArray > ParentPropertyHandleArray , TSharedPtr < IPropertyHandle > StructPropertyHandle ) const
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
return CreateStructureWidget ( StructPropertyHandle ) ;
2021-03-19 15:10:57 -04:00
}
2022-01-04 15:17:54 -05:00
void FMetasoundDefaultMemberElementDetailCustomizationBase : : CustomizeChildren ( TSharedRef < IPropertyHandle > StructPropertyHandle , IDetailChildrenBuilder & ChildBuilder , IPropertyTypeCustomizationUtils & StructCustomizationUtils )
2021-03-19 15:10:57 -04:00
{
2022-01-04 15:17:54 -05:00
TSharedPtr < IPropertyHandleArray > ParentPropertyHandleArray ;
2024-09-10 10:26:02 -04:00
TSharedRef < IPropertyHandle > ElementPropertyHandle = StructPropertyHandle ;
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
TSharedPtr < IPropertyHandle > ParentProperty = StructPropertyHandle - > GetParentHandle ( ) ;
2024-08-27 19:05:41 -04:00
if ( ParentProperty . IsValid ( ) & & ParentProperty - > GetProperty ( ) ! = nullptr )
2021-03-19 15:10:57 -04:00
{
2022-01-04 15:17:54 -05:00
ParentPropertyHandleArray = ParentProperty - > AsArray ( ) ;
if ( ParentPropertyHandleArray . IsValid ( ) )
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
ElementPropertyHandle = ParentProperty . ToSharedRef ( ) ;
2021-03-19 15:10:57 -04:00
}
}
}
2022-07-14 17:51:07 -04:00
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
const bool bMemberFound = MemberCustomizationPrivate : : GetDataTypeFromElementPropertyHandle ( ElementPropertyHandle , DataTypeInfo ) ;
2024-09-10 10:26:02 -04:00
ensureAlways ( bMemberFound ) ;
2021-03-19 15:10:57 -04:00
2024-09-10 10:26:02 -04:00
IDetailPropertyRow & ValueRow = ChildBuilder . AddProperty ( StructPropertyHandle ) ;
TSharedPtr < SWidget > NameWidget ;
TSharedPtr < SWidget > ValueWidget ;
ValueRow . GetDefaultWidgets ( NameWidget , ValueWidget ) ;
constexpr bool bShowChildren = false ;
ValueRow . CustomWidget ( bShowChildren ) ;
2022-01-04 15:17:54 -05:00
if ( ParentPropertyHandleArray . IsValid ( ) )
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
( * ValueRow . CustomNameWidget ( ) )
2021-03-19 15:10:57 -04:00
[
StructPropertyHandle - > CreatePropertyNameWidget ( )
] ;
}
else
{
2024-09-10 10:26:02 -04:00
( * ValueRow . CustomNameWidget ( ) )
2021-03-19 15:10:57 -04:00
[
2021-03-23 17:55:31 -04:00
CreateNameWidget ( StructPropertyHandle )
2021-03-19 15:10:57 -04:00
] ;
}
{
2024-09-10 10:26:02 -04:00
TArray < UObject * > OuterObjects ;
StructPropertyHandle - > GetOuterObjects ( OuterObjects ) ;
TArray < TWeakObjectPtr < UMetasoundEditorGraphInput > > Inputs ;
for ( UObject * Object : OuterObjects )
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( Object ) )
2021-03-19 15:10:57 -04:00
{
2024-09-10 10:26:02 -04:00
Inputs . Add ( Input ) ;
2021-03-19 15:10:57 -04:00
}
}
2024-09-10 10:26:02 -04:00
FSimpleDelegate UpdateFrontendDefaultLiteral = FSimpleDelegate : : CreateLambda ( [ InInputs = MoveTemp ( Inputs ) ] ( )
{
for ( const TWeakObjectPtr < UMetasoundEditorGraphInput > & GraphInput : InInputs )
{
if ( GraphInput . IsValid ( ) )
{
constexpr bool bPostTransaction = true ;
GraphInput - > UpdateFrontendDefaultLiteral ( bPostTransaction ) ;
}
}
} ) ;
StructPropertyHandle - > SetOnChildPropertyValueChanged ( UpdateFrontendDefaultLiteral ) ;
}
( * ValueRow . CustomValueWidget ( ) )
2021-03-19 15:10:57 -04:00
[
2024-09-10 10:26:02 -04:00
CreateValueWidget ( ParentPropertyHandleArray , StructPropertyHandle )
2021-03-19 15:10:57 -04:00
] ;
}
2022-01-04 15:17:54 -05:00
void FMetasoundDefaultMemberElementDetailCustomizationBase : : CustomizeHeader ( TSharedRef < IPropertyHandle > StructPropertyHandle , FDetailWidgetRow & HeaderRow , IPropertyTypeCustomizationUtils & StructCustomizationUtils )
2021-03-19 15:10:57 -04:00
{
}
2021-11-07 23:43:01 -05:00
FName FMetasoundDataTypeSelector : : GetDataType ( ) const
{
if ( GraphMember . IsValid ( ) )
{
2021-12-13 18:15:01 -05:00
return GraphMember - > GetDataType ( ) ;
2021-11-07 23:43:01 -05:00
}
return FName ( ) ;
}
void FMetasoundDataTypeSelector : : OnDataTypeSelected ( FName InSelectedTypeName )
{
FName NewDataTypeName ;
2021-12-13 18:15:01 -05:00
FName ArrayDataTypeName = CreateArrayTypeNameFromElementTypeName ( InSelectedTypeName ) ;
2021-11-07 23:43:01 -05:00
// Update data type based on "Is Array" checkbox and support for arrays.
// If an array type is not supported, default to the base data type.
if ( DataTypeArrayCheckbox - > GetCheckedState ( ) = = ECheckBoxState : : Checked )
{
2022-05-19 15:24:49 -04:00
if ( Frontend : : IDataTypeRegistry : : Get ( ) . IsRegistered ( ArrayDataTypeName ) )
2021-11-07 23:43:01 -05:00
{
NewDataTypeName = ArrayDataTypeName ;
}
else
{
2022-05-19 15:24:49 -04:00
ensure ( Frontend : : IDataTypeRegistry : : Get ( ) . IsRegistered ( InSelectedTypeName ) ) ;
2021-11-07 23:43:01 -05:00
NewDataTypeName = InSelectedTypeName ;
}
}
else
{
2022-05-19 15:24:49 -04:00
if ( Frontend : : IDataTypeRegistry : : Get ( ) . IsRegistered ( InSelectedTypeName ) )
2021-11-07 23:43:01 -05:00
{
NewDataTypeName = InSelectedTypeName ;
}
else
{
2022-05-19 15:24:49 -04:00
ensure ( Frontend : : IDataTypeRegistry : : Get ( ) . IsRegistered ( ArrayDataTypeName ) ) ;
2021-11-07 23:43:01 -05:00
NewDataTypeName = ArrayDataTypeName ;
}
}
2021-12-13 18:15:01 -05:00
if ( NewDataTypeName = = GraphMember - > GetDataType ( ) )
2021-11-07 23:43:01 -05:00
{
return ;
}
// Have to stop playback to avoid attempting to change live edit data on invalid input type.
check ( GEditor ) ;
GEditor - > ResetPreviewAudioComponent ( ) ;
if ( GraphMember . IsValid ( ) )
{
GraphMember - > SetDataType ( NewDataTypeName ) ;
2021-12-13 18:15:01 -05:00
}
2021-11-07 23:43:01 -05:00
}
2021-10-25 20:05:28 -04:00
void FMetasoundDataTypeSelector : : AddDataTypeSelector ( IDetailLayoutBuilder & InDetailLayout , const FText & InRowName , TWeakObjectPtr < UMetasoundEditorGraphMember > InGraphMember , bool bIsEnabled )
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
using namespace Frontend ;
2021-11-07 23:43:01 -05:00
if ( ! InGraphMember . IsValid ( ) )
{
return ;
}
GraphMember = InGraphMember ;
2021-03-19 15:10:57 -04:00
2021-12-13 18:15:01 -05:00
FDataTypeRegistryInfo DataTypeInfo ;
if ( ! ensure ( IDataTypeRegistry : : Get ( ) . GetDataTypeInfo ( InGraphMember - > GetDataType ( ) , DataTypeInfo ) ) )
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
return ;
}
2022-07-14 17:51:07 -04:00
if ( DataTypeInfo . bIsArrayType )
2021-12-13 18:15:01 -05:00
{
ArrayTypeName = GraphMember - > GetDataType ( ) ;
BaseTypeName = CreateElementTypeNameFromArrayTypeName ( InGraphMember - > GetDataType ( ) ) ;
}
else
{
ArrayTypeName = CreateArrayTypeNameFromElementTypeName ( InGraphMember - > GetDataType ( ) ) ;
BaseTypeName = GraphMember - > GetDataType ( ) ;
2021-03-19 15:10:57 -04:00
}
2021-04-02 03:03:27 -04:00
IMetasoundEditorModule & EditorModule = FModuleManager : : GetModuleChecked < IMetasoundEditorModule > ( " MetaSoundEditor " ) ;
2021-04-06 21:02:21 -04:00
// Not all types have an equivalent array type. Base types without array
2021-12-13 18:15:01 -05:00
// types should have the "Is Array" checkbox disabled.
2022-07-14 17:51:07 -04:00
const bool bIsArrayTypeRegistered = IDataTypeRegistry : : Get ( ) . IsRegistered ( ArrayTypeName ) ;
2021-12-13 18:15:01 -05:00
const bool bIsArrayTypeRegisteredHidden = MemberCustomizationPrivate : : HiddenInputTypeNames . Contains ( ArrayTypeName ) ;
2021-04-06 21:02:21 -04:00
2021-12-02 14:23:45 -05:00
TArray < FName > BaseDataTypes ;
2021-12-13 18:15:01 -05:00
IDataTypeRegistry : : Get ( ) . IterateDataTypeInfo ( [ & BaseDataTypes ] ( const FDataTypeRegistryInfo & RegistryInfo )
2021-03-19 15:10:57 -04:00
{
2022-07-14 17:51:07 -04:00
// Hide the type from the combo selector if any of the following is true
2021-12-13 18:15:01 -05:00
const bool bIsHiddenType = MemberCustomizationPrivate : : HiddenInputTypeNames . Contains ( RegistryInfo . DataTypeName ) ;
2022-07-14 17:51:07 -04:00
const bool bHideBaseType = RegistryInfo . bIsArrayType | | RegistryInfo . bIsVariable | | bIsHiddenType ;
2021-12-02 14:23:45 -05:00
if ( ! bHideBaseType )
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
BaseDataTypes . Add ( RegistryInfo . DataTypeName ) ;
2021-04-07 22:22:52 -04:00
}
2021-03-19 15:10:57 -04:00
} ) ;
2021-12-02 14:23:45 -05:00
BaseDataTypes . Sort ( [ ] ( const FName & DataTypeNameL , const FName & DataTypeNameR )
2021-03-19 15:10:57 -04:00
{
2021-11-07 23:43:01 -05:00
return DataTypeNameL . LexicalLess ( DataTypeNameR ) ;
2021-03-19 15:10:57 -04:00
} ) ;
2021-12-02 14:23:45 -05:00
Algo : : Transform ( BaseDataTypes , ComboOptions , [ ] ( const FName & Name ) { return MakeShared < FString > ( Name . ToString ( ) ) ; } ) ;
2021-11-07 23:43:01 -05:00
2021-12-02 14:23:45 -05:00
InDetailLayout . EditCategory ( " General " ) . AddCustomRow ( InRowName )
2021-07-27 15:36:03 -04:00
. IsEnabled ( bIsEnabled )
2021-03-19 15:10:57 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Text ( InRowName )
2022-04-25 13:29:29 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
2021-03-19 15:10:57 -04:00
]
. ValueContent ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2021-11-07 23:43:01 -05:00
. AutoWidth ( )
. HAlign ( HAlign_Left )
2021-03-19 15:10:57 -04:00
. VAlign ( VAlign_Center )
2021-11-07 23:43:01 -05:00
. Padding ( 1.0f , 0.0f , 0.0f , 0.0f )
2021-03-19 15:10:57 -04:00
[
2021-11-07 23:43:01 -05:00
SAssignNew ( DataTypeComboBox , SSearchableComboBox )
. OptionsSource ( & ComboOptions )
. OnGenerateWidget_Lambda ( [ ] ( TSharedPtr < FString > InItem )
2021-03-19 15:10:57 -04:00
{
2021-11-07 23:43:01 -05:00
return SNew ( STextBlock )
. Text ( FText : : FromString ( * InItem ) ) ;
2021-03-19 15:10:57 -04:00
} )
2021-11-07 23:43:01 -05:00
. OnSelectionChanged_Lambda ( [ this ] ( TSharedPtr < FString > InNewName , ESelectInfo : : Type InSelectInfo )
{
if ( InSelectInfo ! = ESelectInfo : : OnNavigation )
{
OnDataTypeSelected ( FName ( * InNewName ) ) ;
}
} )
2024-06-18 04:56:33 -04:00
. bAlwaysSelectItem ( true )
2021-11-07 23:43:01 -05:00
. Content ( )
[
SNew ( STextBlock )
. Text_Lambda ( [ this ] ( )
{
2021-12-13 18:15:01 -05:00
return FText : : FromName ( BaseTypeName ) ;
2021-11-07 23:43:01 -05:00
} )
]
2021-03-19 15:10:57 -04:00
]
+ SHorizontalBox : : Slot ( )
2021-11-07 23:43:01 -05:00
. AutoWidth ( )
. HAlign ( HAlign_Right )
2021-03-19 15:10:57 -04:00
. VAlign ( VAlign_Center )
2021-11-07 23:43:01 -05:00
. Padding ( 2.0f , 0.0f , 0.0f , 0.0f )
2021-03-19 15:10:57 -04:00
[
SAssignNew ( DataTypeArrayCheckbox , SCheckBox )
2021-04-08 14:10:56 -04:00
. IsEnabled ( bIsArrayTypeRegistered & & ! bIsArrayTypeRegisteredHidden )
2021-10-25 20:05:28 -04:00
. IsChecked_Lambda ( [ this , InGraphMember ] ( )
2021-03-19 15:10:57 -04:00
{
2021-10-25 20:05:28 -04:00
return OnGetDataTypeArrayCheckState ( InGraphMember ) ;
2021-03-19 15:10:57 -04:00
} )
2021-10-25 20:05:28 -04:00
. OnCheckStateChanged_Lambda ( [ this , InGraphMember ] ( ECheckBoxState InNewState )
2021-03-19 15:10:57 -04:00
{
2021-10-25 20:05:28 -04:00
OnDataTypeArrayChanged ( InGraphMember , InNewState ) ;
2021-03-19 15:10:57 -04:00
} )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " Node_IsArray " , " Is Array " ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
]
] ;
2021-11-07 23:43:01 -05:00
2021-12-13 18:15:01 -05:00
auto NameMatchesPredicate = [ TypeString = BaseTypeName . ToString ( ) ] ( const TSharedPtr < FString > & Item ) { return * Item = = TypeString ; } ;
2021-11-07 23:43:01 -05:00
const TSharedPtr < FString > * SelectedItem = ComboOptions . FindByPredicate ( NameMatchesPredicate ) ;
if ( ensure ( SelectedItem ) )
{
2022-03-22 14:01:46 -04:00
DataTypeComboBox - > SetSelectedItem ( * SelectedItem , ESelectInfo : : Direct ) ;
2021-11-07 23:43:01 -05:00
}
2021-03-19 15:10:57 -04:00
}
2021-10-25 20:05:28 -04:00
ECheckBoxState FMetasoundDataTypeSelector : : OnGetDataTypeArrayCheckState ( TWeakObjectPtr < UMetasoundEditorGraphMember > InGraphMember ) const
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
using namespace Frontend ;
2021-10-25 20:05:28 -04:00
if ( InGraphMember . IsValid ( ) )
2021-03-19 15:10:57 -04:00
{
2021-12-13 18:15:01 -05:00
FDataTypeRegistryInfo DataTypeInfo ;
if ( ensure ( IDataTypeRegistry : : Get ( ) . GetDataTypeInfo ( InGraphMember - > GetDataType ( ) , DataTypeInfo ) ) )
{
2022-07-14 17:51:07 -04:00
return DataTypeInfo . bIsArrayType ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2021-12-13 18:15:01 -05:00
}
2021-03-19 15:10:57 -04:00
}
return ECheckBoxState : : Undetermined ;
}
2021-10-25 20:05:28 -04:00
void FMetasoundDataTypeSelector : : OnDataTypeArrayChanged ( TWeakObjectPtr < UMetasoundEditorGraphMember > InGraphMember , ECheckBoxState InNewState )
2021-03-19 15:10:57 -04:00
{
2021-11-07 23:43:01 -05:00
if ( InGraphMember . IsValid ( ) & & DataTypeComboBox . IsValid ( ) )
2021-03-19 15:10:57 -04:00
{
TSharedPtr < FString > DataTypeRoot = DataTypeComboBox - > GetSelectedItem ( ) ;
if ( ensure ( DataTypeRoot . IsValid ( ) ) )
{
2021-03-24 16:42:25 -04:00
// Have to stop playback to avoid attempting to change live edit data on invalid input type.
check ( GEditor ) ;
GEditor - > ResetPreviewAudioComponent ( ) ;
2021-12-13 18:15:01 -05:00
const FName DataType = InNewState = = ECheckBoxState : : Checked ? ArrayTypeName : BaseTypeName ;
InGraphMember - > SetDataType ( DataType ) ;
2021-03-19 15:10:57 -04:00
}
}
}
2022-04-06 14:52:43 -04:00
void FMetasoundMemberDetailCustomization : : UpdateRenameDelegate ( UMetasoundEditorGraphMember & InMember )
2022-03-01 16:31:55 -05:00
{
2022-04-06 14:52:43 -04:00
if ( InMember . CanRename ( ) )
2022-03-01 16:31:55 -05:00
{
2022-04-06 14:52:43 -04:00
if ( ! RenameRequestedHandle . IsValid ( ) )
2022-03-01 16:31:55 -05:00
{
2022-04-06 14:52:43 -04:00
InMember . OnRenameRequested . Clear ( ) ;
RenameRequestedHandle = InMember . OnRenameRequested . AddLambda ( [ this ] ( )
2022-03-01 16:31:55 -05:00
{
2022-04-06 14:52:43 -04:00
FSlateApplication : : Get ( ) . SetKeyboardFocus ( NameEditableTextBox . ToSharedRef ( ) , EFocusCause : : SetDirectly ) ;
} ) ;
2022-03-01 16:31:55 -05:00
}
}
}
void FMetasoundMemberDetailCustomization : : CacheMemberData ( IDetailLayoutBuilder & InDetailLayout )
{
TArray < TWeakObjectPtr < UObject > > Objects ;
InDetailLayout . GetObjectsBeingCustomized ( Objects ) ;
if ( ! Objects . IsEmpty ( ) )
{
GraphMember = Cast < UMetasoundEditorGraphMember > ( Objects . Last ( ) . Get ( ) ) ;
TSharedPtr < IPropertyHandle > LiteralHandle = InDetailLayout . GetProperty ( UMetasoundEditorGraphMember : : GetLiteralPropertyName ( ) ) ;
if ( ensure ( GraphMember . IsValid ( ) ) & & ensure ( LiteralHandle . IsValid ( ) ) )
{
// Always hide, even if no customization (LiteralObject isn't found) as this is the case
// where the default object is not required (i.e. Default Member is default constructed)
LiteralHandle - > MarkHiddenByCustomization ( ) ;
}
}
}
2024-08-27 19:05:41 -04:00
void FMetasoundMemberDetailCustomization : : CustomizeDefaultCategory ( IDetailLayoutBuilder & InDetailLayout )
2022-03-01 16:31:55 -05:00
{
if ( ! GraphMember . IsValid ( ) )
{
2024-08-27 19:05:41 -04:00
return ;
2022-03-01 16:31:55 -05:00
}
2022-04-06 14:52:43 -04:00
UpdateRenameDelegate ( * GraphMember ) ;
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphMemberDefaultLiteral * MemberDefaultLiteral = GraphMember - > GetLiteral ( ) )
{
UClass * MemberClass = MemberDefaultLiteral - > GetClass ( ) ;
check ( MemberClass ) ;
IDetailCategoryBuilder & DefaultCategoryBuilder = GetDefaultCategoryBuilder ( InDetailLayout ) ;
IMetasoundEditorModule & EditorModule = FModuleManager : : GetModuleChecked < IMetasoundEditorModule > ( " MetaSoundEditor " ) ;
2024-08-27 19:05:41 -04:00
LiteralCustomization = EditorModule . CreateMemberDefaultLiteralCustomization ( * MemberClass , DefaultCategoryBuilder ) ;
2024-10-03 14:33:23 -04:00
TAttribute < EVisibility > Visibility = TAttribute < EVisibility > : : CreateSPLambda ( AsShared ( ) , [ this ] ( )
2024-08-27 19:05:41 -04:00
{
return GetDefaultVisibility ( ) ;
} ) ;
2022-03-01 16:31:55 -05:00
if ( LiteralCustomization . IsValid ( ) )
{
2024-08-27 19:05:41 -04:00
LiteralCustomization - > SetDefaultVisibility ( Visibility ) ;
LiteralCustomization - > SetEnabled ( GetEnabled ( ) ) ;
LiteralCustomization - > SetResetOverride ( GetResetOverride ( ) ) ;
LiteralCustomization - > CustomizeDefaults ( * MemberDefaultLiteral , InDetailLayout ) ;
2022-03-01 16:31:55 -05:00
}
else
{
IDetailPropertyRow * DefaultPropertyRow = DefaultCategoryBuilder . AddExternalObjectProperty ( TArray < UObject * > ( { MemberDefaultLiteral } ) , " Default " ) ;
2024-08-27 19:05:41 -04:00
if ( ensureMsgf ( DefaultPropertyRow , TEXT ( " Class '%s' missing expected 'Default' member. "
2022-03-01 16:31:55 -05:00
" Either add/rename default member or register customization to display default value/opt out appropriately. " ) ,
2024-08-27 19:05:41 -04:00
* MemberClass - > GetName ( ) ) )
2022-03-04 03:48:32 -05:00
{
2024-08-27 19:05:41 -04:00
DefaultPropertyRow - > Visibility ( Visibility ) ;
DefaultPropertyRow - > IsEnabled ( GetEnabled ( ) ) ;
}
2022-03-04 03:48:32 -05:00
}
}
2022-03-01 16:31:55 -05:00
}
void FMetasoundMemberDetailCustomization : : CustomizeGeneralCategory ( IDetailLayoutBuilder & InDetailLayout )
{
IDetailCategoryBuilder & CategoryBuilder = GetGeneralCategoryBuilder ( InDetailLayout ) ;
2024-02-01 19:54:26 -05:00
const bool bIsReadOnly = IsInterfaceMember ( ) | | ! IsGraphEditable ( ) ;
// Override row copy action if it's disabled by the edit condition
auto GenerateCopyPasteActions = [ ] ( FDetailWidgetRow & Row , const FString & Value )
{
FUIAction CopyAction ( FExecuteAction : : CreateLambda ( [ Value ] ( )
{
FPlatformApplicationMisc : : ClipboardCopy ( * Value ) ;
} ) ) ;
Row . CopyAction ( CopyAction ) ;
// Create a dummy paste action
// Needed because the custom copy action will only be set
// if both the copy and paste actions are bound
// Pasting is still available directly via the text box if editable
const static FUIAction PasteAction ( FExecuteAction : : CreateLambda ( [ ] ( ) { } ) , FCanExecuteAction : : CreateLambda ( [ ] ( ) { return false ; } ) ) ;
Row . PasteAction ( PasteAction ) ;
} ;
2022-03-01 16:31:55 -05:00
NameEditableTextBox = SNew ( SEditableTextBox )
. Text ( this , & FMetasoundMemberDetailCustomization : : GetName )
. OnTextChanged ( this , & FMetasoundMemberDetailCustomization : : OnNameChanged )
. OnTextCommitted ( this , & FMetasoundMemberDetailCustomization : : OnNameCommitted )
2024-02-01 19:54:26 -05:00
. IsReadOnly ( bIsReadOnly )
2022-03-01 16:31:55 -05:00
. SelectAllTextWhenFocused ( true )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) ) ;
static const FText MemberNameToolTipFormat = LOCTEXT ( " GraphMember_NameDescriptionFormat " , " Name used within the MetaSounds editor(s) and transacting systems (ex. Blueprints) if applicable to reference the given {0}. " ) ;
2024-02-01 19:54:26 -05:00
FDetailWidgetRow & NameRow = CategoryBuilder . AddCustomRow ( LOCTEXT ( " GraphMember_NameProperty " , " Name " ) )
. EditCondition ( ! bIsReadOnly , nullptr )
2022-03-01 16:31:55 -05:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
. Text ( GraphMember - > GetGraphMemberLabel ( ) )
. ToolTipText ( FText : : Format ( MemberNameToolTipFormat , GraphMember - > GetGraphMemberLabel ( ) ) )
]
. ValueContent ( )
[
NameEditableTextBox . ToSharedRef ( )
] ;
2024-02-01 19:54:26 -05:00
GenerateCopyPasteActions ( NameRow , GetName ( ) . ToString ( ) ) ;
2022-03-01 16:31:55 -05:00
static const FText MemberDisplayNameText = LOCTEXT ( " GraphMember_DisplayNameProperty " , " Display Name " ) ;
static const FText MemberDisplayNameToolTipFormat = LOCTEXT ( " GraphMember_DisplayNameDescriptionFormat " , " Optional, localized name used within the MetaSounds editor(s) to describe the given {0}. " ) ;
const FText MemberDisplayNameTooltipText = FText : : Format ( MemberDisplayNameToolTipFormat , GraphMember - > GetGraphMemberLabel ( ) ) ;
2024-02-01 19:54:26 -05:00
TSharedRef < FGraphMemberEditableTextDisplayName > DisplayNameValueText = MakeShared < FGraphMemberEditableTextDisplayName > ( GraphMember , MemberDisplayNameTooltipText ) ;
FDetailWidgetRow & DisplayNameRow = CategoryBuilder . AddCustomRow ( MemberDisplayNameText )
. EditCondition ( ! bIsReadOnly , nullptr )
2022-03-01 16:31:55 -05:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
. Text ( MemberDisplayNameText )
. ToolTipText ( MemberDisplayNameTooltipText )
]
. ValueContent ( )
[
2024-02-01 19:54:26 -05:00
SNew ( STextPropertyEditableTextBox , DisplayNameValueText )
2022-03-01 16:31:55 -05:00
. WrapTextAt ( 500 )
. MinDesiredWidth ( 25.0f )
. MaxDesiredHeight ( 200 )
] ;
2024-02-01 19:54:26 -05:00
GenerateCopyPasteActions ( DisplayNameRow , DisplayNameValueText - > GetText ( 0 ) . ToString ( ) ) ;
2022-03-01 16:31:55 -05:00
static const FText MemberDescriptionText = LOCTEXT ( " Member_DescriptionPropertyName " , " Description " ) ;
static const FText MemberDescriptionToolTipFormat = LOCTEXT ( " Member_DescriptionToolTipFormat " , " Description for {0}. For example, used as a tooltip when displayed on another graph's referencing node. " ) ;
const FText MemberDescriptionToolTipText = FText : : Format ( MemberDescriptionToolTipFormat , GraphMember - > GetGraphMemberLabel ( ) ) ;
2024-02-01 19:54:26 -05:00
TSharedRef < FGraphMemberEditableTextDescription > DescriptionValueText = MakeShared < FGraphMemberEditableTextDescription > ( GraphMember , MemberDescriptionToolTipText ) ;
FDetailWidgetRow & DescriptionRow = CategoryBuilder . AddCustomRow ( MemberDescriptionText )
. IsEnabled ( true )
. EditCondition ( ! bIsReadOnly , nullptr )
2022-03-01 16:31:55 -05:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
. Text ( MemberDescriptionText )
. ToolTipText ( MemberDescriptionToolTipText )
]
. ValueContent ( )
[
2024-02-01 19:54:26 -05:00
SNew ( STextPropertyEditableTextBox , DescriptionValueText )
2022-03-01 16:31:55 -05:00
. WrapTextAt ( 500 )
. MinDesiredWidth ( 25.0f )
. MaxDesiredHeight ( 200 )
] ;
2024-02-01 19:54:26 -05:00
GenerateCopyPasteActions ( DescriptionRow , DescriptionValueText - > GetText ( 0 ) . ToString ( ) ) ;
2022-03-01 16:31:55 -05:00
2024-02-01 19:54:26 -05:00
DataTypeSelector . AddDataTypeSelector ( InDetailLayout , MemberCustomizationStyle : : DataTypeNameText , GraphMember , ! bIsReadOnly ) ;
2022-03-01 16:31:55 -05:00
}
void FMetasoundMemberDetailCustomization : : CustomizeDetails ( IDetailLayoutBuilder & InDetailLayout )
{
CacheMemberData ( InDetailLayout ) ;
if ( GraphMember . IsValid ( ) )
{
CustomizeGeneralCategory ( InDetailLayout ) ;
CustomizeDefaultCategory ( InDetailLayout ) ;
}
}
void FMetasoundMemberDetailCustomization : : OnNameChanged ( const FText & InNewName )
{
using namespace Frontend ;
bIsNameInvalid = false ;
NameEditableTextBox - > SetError ( FText : : GetEmpty ( ) ) ;
if ( ! ensure ( GraphMember . IsValid ( ) ) )
{
return ;
}
FText Error ;
if ( ! GraphMember - > CanRename ( InNewName , Error ) )
{
bIsNameInvalid = true ;
NameEditableTextBox - > SetError ( Error ) ;
}
}
FText FMetasoundMemberDetailCustomization : : GetName ( ) const
{
if ( GraphMember . IsValid ( ) )
{
return FText : : FromName ( GraphMember - > GetMemberName ( ) ) ;
}
return FText : : GetEmpty ( ) ;
}
2022-03-04 03:48:32 -05:00
Frontend : : FDocumentHandle FMetasoundMemberDetailCustomization : : GetDocumentHandle ( ) const
{
if ( GraphMember . IsValid ( ) )
{
if ( UMetasoundEditorGraph * Graph = GraphMember - > GetOwningGraph ( ) )
{
return Graph - > GetDocumentHandle ( ) ;
}
}
return Frontend : : IDocumentController : : GetInvalidHandle ( ) ;
}
2022-03-01 16:31:55 -05:00
bool FMetasoundMemberDetailCustomization : : IsGraphEditable ( ) const
{
if ( GraphMember . IsValid ( ) )
{
if ( const UMetasoundEditorGraph * OwningGraph = GraphMember - > GetOwningGraph ( ) )
{
return OwningGraph - > IsEditable ( ) ;
}
}
return false ;
}
FText FMetasoundMemberDetailCustomization : : GetDisplayName ( ) const
{
using namespace Frontend ;
if ( GraphMember . IsValid ( ) )
{
return GraphMember - > GetDisplayName ( ) ;
}
return FText : : GetEmpty ( ) ;
}
void FMetasoundMemberDetailCustomization : : OnTooltipCommitted ( const FText & InNewText , ETextCommit : : Type InTextCommit )
{
using namespace Frontend ;
if ( GraphMember . IsValid ( ) )
{
constexpr bool bPostTransaction = true ;
GraphMember - > SetDescription ( InNewText , bPostTransaction ) ;
}
}
FText FMetasoundMemberDetailCustomization : : GetTooltip ( ) const
{
if ( GraphMember . IsValid ( ) )
{
return GraphMember - > GetDescription ( ) ;
}
return FText : : GetEmpty ( ) ;
}
2022-03-04 03:48:32 -05:00
EVisibility FMetasoundVertexDetailCustomization : : GetDefaultVisibility ( ) const
{
using namespace Frontend ;
if ( GraphMember . IsValid ( ) )
{
bool bIsInputConnected = false ;
FConstNodeHandle NodeHandle = CastChecked < UMetasoundEditorGraphVertex > ( GraphMember ) - > GetConstNodeHandle ( ) ;
if ( NodeHandle - > IsValid ( ) )
{
NodeHandle - > IterateConstInputs ( [ & bIsInputConnected ] ( FConstInputHandle InputHandle )
{
bIsInputConnected | = InputHandle - > IsConnectionUserModifiable ( ) & & InputHandle - > IsConnected ( ) ;
} ) ;
}
return bIsInputConnected ? EVisibility : : Collapsed : EVisibility : : Visible ;
}
return EVisibility : : Collapsed ;
}
2022-03-01 16:31:55 -05:00
void FMetasoundMemberDetailCustomization : : OnNameCommitted ( const FText & InNewName , ETextCommit : : Type InTextCommit )
{
using namespace Frontend ;
if ( ! bIsNameInvalid & & GraphMember . IsValid ( ) )
{
2024-06-11 18:27:11 -04:00
if ( GraphMember - > GetMemberName ( ) = = InNewName . ToString ( ) )
{
return ;
}
2022-03-01 16:31:55 -05:00
const FText TransactionLabel = FText : : Format ( LOCTEXT ( " RenameGraphMember_Format " , " Set MetaSound {0}'s Name " ) , GraphMember - > GetGraphMemberLabel ( ) ) ;
const FScopedTransaction Transaction ( TransactionLabel ) ;
constexpr bool bPostTransaction = false ;
GraphMember - > SetDisplayName ( FText : : GetEmpty ( ) , bPostTransaction ) ;
GraphMember - > SetMemberName ( * InNewName . ToString ( ) , bPostTransaction ) ;
}
NameEditableTextBox - > SetError ( FText : : GetEmpty ( ) ) ;
bIsNameInvalid = false ;
}
2022-07-18 17:14:25 -04:00
void FMetasoundVertexDetailCustomization : : AddConstructorPinRow ( IDetailLayoutBuilder & InDetailLayout )
{
2024-09-13 19:05:03 -04:00
InDetailLayout . EditCategory ( " General " ) . AddCustomRow ( MemberCustomizationPrivate : : ConstructorPinText )
. IsEnabled ( IsGraphEditable ( ) & & ! IsInterfaceMember ( ) )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( MemberCustomizationPrivate : : ConstructorPinText )
. ToolTipText ( MemberCustomizationPrivate : : ConstructorPinTooltip )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
]
. ValueContent ( )
[
SAssignNew ( ConstructorPinCheckbox , SCheckBox )
. IsChecked_Lambda ( [ this ] ( )
{
if ( UMetasoundEditorGraphVertex * Vertex = Cast < UMetasoundEditorGraphVertex > ( GraphMember . Get ( ) ) )
2022-07-18 17:14:25 -04:00
{
return OnGetConstructorPinCheckboxState ( Vertex ) ;
2024-09-13 19:05:03 -04:00
}
return ECheckBoxState : : Undetermined ;
} )
. OnCheckStateChanged_Lambda ( [ this ] ( ECheckBoxState InNewState )
{
if ( UMetasoundEditorGraphVertex * Vertex = Cast < UMetasoundEditorGraphVertex > ( GraphMember . Get ( ) ) )
2022-07-18 17:14:25 -04:00
{
OnConstructorPinStateChanged ( Vertex , InNewState ) ;
2024-09-13 19:05:03 -04:00
}
} )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
2022-07-18 17:14:25 -04:00
}
2024-08-20 03:27:21 -04:00
# if WITH_EDITORONLY_DATA
void FMetasoundVertexDetailCustomization : : AddAdvancedPinRow ( IDetailLayoutBuilder & InDetailLayout )
{
//only add row if input or output
2024-09-13 19:05:03 -04:00
InDetailLayout . EditCategory ( " General " ) . AddCustomRow ( MemberCustomizationPrivate : : AdvancedPinText )
. IsEnabled ( IsGraphEditable ( ) & & ! IsInterfaceMember ( ) )
. NameContent ( )
2024-08-20 03:27:21 -04:00
[
2024-09-13 19:05:03 -04:00
SNew ( STextBlock )
. Text ( MemberCustomizationPrivate : : AdvancedPinText )
. ToolTipText ( MemberCustomizationPrivate : : AdvancedPinTooltip )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
]
. ValueContent ( )
[
SAssignNew ( AdvancedPinCheckbox , SCheckBox )
. IsChecked_Lambda ( [ this ] ( )
{
if ( UMetasoundEditorGraphVertex * Vertex = Cast < UMetasoundEditorGraphVertex > ( GraphMember . Get ( ) ) )
2024-08-20 03:27:21 -04:00
{
return OnGetAdvancedPinCheckboxState ( Vertex ) ;
2024-09-13 19:05:03 -04:00
}
return ECheckBoxState : : Undetermined ;
} )
. OnCheckStateChanged_Lambda ( [ this ] ( ECheckBoxState InNewState )
{
if ( UMetasoundEditorGraphVertex * Vertex = Cast < UMetasoundEditorGraphVertex > ( GraphMember . Get ( ) ) )
2024-08-20 03:27:21 -04:00
{
OnAdvancedPinStateChanged ( Vertex , InNewState ) ;
2024-09-13 19:05:03 -04:00
}
} )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
2024-08-20 03:27:21 -04:00
}
# endif // WITH_EDITORONLY_DATA
2022-03-01 16:31:55 -05:00
void FMetasoundVertexDetailCustomization : : CustomizeGeneralCategory ( IDetailLayoutBuilder & InDetailLayout )
{
FMetasoundMemberDetailCustomization : : CustomizeGeneralCategory ( InDetailLayout ) ;
UMetasoundEditorGraphVertex * Vertex = Cast < UMetasoundEditorGraphVertex > ( GraphMember . Get ( ) ) ;
2022-07-18 17:14:25 -04:00
if ( ! ensure ( Vertex ) )
2022-03-01 16:31:55 -05:00
{
2022-07-18 17:14:25 -04:00
return ;
2022-03-01 16:31:55 -05:00
}
2022-07-18 17:14:25 -04:00
// Constructor pin
2022-08-19 11:39:24 -04:00
Frontend : : FDataTypeRegistryInfo DataTypeInfo ;
Frontend : : IDataTypeRegistry : : Get ( ) . GetDataTypeInfo ( Vertex - > GetDataType ( ) , DataTypeInfo ) ;
if ( DataTypeInfo . bIsConstructorType )
2022-07-18 17:14:25 -04:00
{
2022-08-19 11:39:24 -04:00
AddConstructorPinRow ( InDetailLayout ) ;
2022-07-18 17:14:25 -04:00
}
2024-08-20 03:27:21 -04:00
2024-09-13 19:05:03 -04:00
AddAdvancedPinRow ( InDetailLayout ) ;
2022-07-18 17:14:25 -04:00
// Sort order
IDetailCategoryBuilder & CategoryBuilder = FMetasoundMemberDetailCustomization : : GetGeneralCategoryBuilder ( InDetailLayout ) ;
TWeakObjectPtr < UMetasoundEditorGraphVertex > VertexPtr = Vertex ;
static const FText SortOrderText = LOCTEXT ( " Vertex_SortOrderPropertyName " , " Sort Order " ) ;
static const FText SortOrderToolTipFormat = LOCTEXT ( " Vertex_SortOrderToolTipFormat " , " Sort Order for {0}. Used to organize pins in node view. The higher the number, the lower in the list. " ) ;
const FText SortOrderToolTipText = FText : : Format ( SortOrderToolTipFormat , GraphMember - > GetGraphMemberLabel ( ) ) ;
CategoryBuilder . AddCustomRow ( SortOrderText )
. EditCondition ( IsGraphEditable ( ) , nullptr )
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
. Text ( SortOrderText )
. ToolTipText ( SortOrderToolTipText )
]
. ValueContent ( )
[
SNew ( SNumericEntryBox < int32 > )
2024-09-13 19:05:03 -04:00
. Value_Lambda ( [ VertexPtr ] ( )
{
if ( VertexPtr . IsValid ( ) )
{
return VertexPtr - > GetSortOrderIndex ( ) ;
}
return 0 ;
} )
2022-07-18 17:14:25 -04:00
. AllowSpin ( false )
. UndeterminedString ( LOCTEXT ( " Vertex_SortOrder_MultipleValues " , " Multiple " ) )
. OnValueCommitted_Lambda ( [ VertexPtr ] ( int32 NewValue , ETextCommit : : Type CommitInfo )
{
if ( ! VertexPtr . IsValid ( ) )
{
return ;
}
const FText TransactionTitle = FText : : Format ( LOCTEXT ( " SetVertexSortOrderFormat " , " Set MetaSound Graph {0} '{1}' SortOrder to {2} " ) ,
VertexPtr - > GetGraphMemberLabel ( ) ,
VertexPtr - > GetDisplayName ( ) ,
FText : : AsNumber ( NewValue ) ) ;
FScopedTransaction Transaction ( TransactionTitle ) ;
UObject * MetaSoundObject = VertexPtr - > GetOutermostObject ( ) ;
FMetasoundAssetBase * MetaSoundAsset = Metasound : : IMetasoundUObjectRegistry : : Get ( ) . GetObjectAsAssetBase ( MetaSoundObject ) ;
check ( MetaSoundAsset ) ;
MetaSoundObject - > Modify ( ) ;
MetaSoundAsset - > GetGraphChecked ( ) . Modify ( ) ;
VertexPtr - > Modify ( ) ;
VertexPtr - > SetSortOrderIndex ( NewValue ) ;
constexpr bool bInForceViewSynchronization = true ;
FGraphBuilder : : RegisterGraphWithFrontend ( * MetaSoundObject , bInForceViewSynchronization ) ;
} )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
] ;
2022-03-01 16:31:55 -05:00
}
2021-12-13 18:15:01 -05:00
2022-03-04 03:48:32 -05:00
bool FMetasoundVertexDetailCustomization : : IsInterfaceMember ( ) const
2022-02-09 12:52:07 -05:00
{
2022-03-01 16:31:55 -05:00
if ( GraphMember . IsValid ( ) )
2022-02-09 12:52:07 -05:00
{
2022-03-04 03:48:32 -05:00
return CastChecked < UMetasoundEditorGraphVertex > ( GraphMember ) - > IsInterfaceMember ( ) ;
2022-02-09 12:52:07 -05:00
}
2022-03-04 03:48:32 -05:00
return false ;
2022-02-09 12:52:07 -05:00
}
bool FMetasoundInputDetailCustomization : : GetInputInheritsDefault ( ) const
{
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( GraphMember . Get ( ) ) )
2022-02-09 12:52:07 -05:00
{
const TSet < FName > & InputsInheritingDefault = GetDocumentHandle ( ) - > GetRootGraph ( ) - > GetInputsInheritingDefault ( ) ;
2022-03-01 16:31:55 -05:00
FName NodeName = Input - > GetConstNodeHandle ( ) - > GetNodeName ( ) ;
2022-02-09 12:52:07 -05:00
return InputsInheritingDefault . Contains ( NodeName ) ;
}
return false ;
}
void FMetasoundInputDetailCustomization : : SetInputInheritsDefault ( )
{
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( GraphMember . Get ( ) ) )
2022-02-09 12:52:07 -05:00
{
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphMemberDefaultLiteral * MemberDefaultLiteral = Input - > GetLiteral ( ) )
2022-02-09 12:52:07 -05:00
{
2022-03-01 16:31:55 -05:00
FScopedTransaction Transaction ( LOCTEXT ( " SetPresetInputOverrideTransaction " , " Set MetaSound Preset Input Overridden " ) ) ;
Input - > GetOutermost ( ) - > Modify ( ) ;
Input - > Modify ( ) ;
MemberDefaultLiteral - > Modify ( ) ;
constexpr bool bDefaultIsInherited = true ;
const FName NodeName = Input - > GetConstNodeHandle ( ) - > GetNodeName ( ) ;
GetDocumentHandle ( ) - > GetRootGraph ( ) - > SetInputInheritsDefault ( NodeName , bDefaultIsInherited ) ;
if ( UObject * Metasound = Input - > GetOutermostObject ( ) )
{
FGraphBuilder : : RegisterGraphWithFrontend ( * Metasound ) ;
}
2022-02-09 12:52:07 -05:00
}
}
}
void FMetasoundInputDetailCustomization : : ClearInputInheritsDefault ( )
{
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( GraphMember . Get ( ) ) )
2022-02-09 12:52:07 -05:00
{
2022-03-01 16:31:55 -05:00
if ( UMetasoundEditorGraphMemberDefaultLiteral * MemberDefaultLiteral = Input - > GetLiteral ( ) )
2022-02-09 12:52:07 -05:00
{
2022-03-01 16:31:55 -05:00
FScopedTransaction Transaction ( LOCTEXT ( " ClearPresetInputOverrideTransaction " , " Clear MetaSound Preset Input Overridden " ) ) ;
2022-02-09 12:52:07 -05:00
2022-03-01 16:31:55 -05:00
Input - > GetOutermost ( ) - > Modify ( ) ;
Input - > Modify ( ) ;
MemberDefaultLiteral - > Modify ( ) ;
constexpr bool bDefaultIsInherited = false ;
const FName NodeName = Input - > GetConstNodeHandle ( ) - > GetNodeName ( ) ;
GetDocumentHandle ( ) - > GetRootGraph ( ) - > SetInputInheritsDefault ( NodeName , bDefaultIsInherited ) ;
Input - > UpdateFrontendDefaultLiteral ( false /* bPostTransaction */ ) ;
if ( UMetasoundEditorGraphMemberDefaultLiteral * Literal = Input - > GetLiteral ( ) )
{
Literal - > ForceRefresh ( ) ;
}
if ( UObject * Metasound = Input - > GetOutermostObject ( ) )
{
FGraphBuilder : : RegisterGraphWithFrontend ( * Metasound ) ;
}
2022-02-09 12:52:07 -05:00
}
}
}
2022-07-14 17:51:07 -04:00
2022-07-18 17:14:25 -04:00
ECheckBoxState FMetasoundVertexDetailCustomization : : OnGetConstructorPinCheckboxState ( TWeakObjectPtr < UMetasoundEditorGraphVertex > InGraphVertex ) const
2022-04-25 13:29:29 -04:00
{
2022-07-18 17:14:25 -04:00
if ( InGraphVertex . IsValid ( ) )
2022-04-25 13:29:29 -04:00
{
2022-07-18 17:14:25 -04:00
return InGraphVertex - > GetVertexAccessType ( ) = = EMetasoundFrontendVertexAccessType : : Value ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
}
return ECheckBoxState : : Undetermined ;
}
2024-08-20 03:27:21 -04:00
# if WITH_EDITORONLY_DATA
ECheckBoxState FMetasoundVertexDetailCustomization : : OnGetAdvancedPinCheckboxState ( TWeakObjectPtr < UMetasoundEditorGraphVertex > InGraphVertex ) const
{
if ( InGraphVertex . IsValid ( ) )
{
FMetaSoundFrontendDocumentBuilder & DocumentBuilder = InGraphVertex - > GetFrontendBuilderChecked ( ) ;
return DocumentBuilder . GetIsAdvancedDisplay ( InGraphVertex - > GetMemberName ( ) , InGraphVertex - > GetClassType ( ) ) ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
}
return ECheckBoxState : : Undetermined ;
}
# endif // WITH_EDITORONLY_DATA
2022-07-18 17:14:25 -04:00
void FMetasoundVertexDetailCustomization : : OnConstructorPinStateChanged ( TWeakObjectPtr < UMetasoundEditorGraphVertex > InGraphVertex , ECheckBoxState InNewState )
{
if ( InGraphVertex . IsValid ( ) & & ConstructorPinCheckbox . IsValid ( ) )
{
EMetasoundFrontendVertexAccessType NewAccessType = InNewState = = ECheckBoxState : : Checked ?
EMetasoundFrontendVertexAccessType : : Value : EMetasoundFrontendVertexAccessType : : Reference ;
if ( InGraphVertex - > GetVertexAccessType ( ) = = NewAccessType )
{
return ;
}
// Have to stop playback to avoid attempting to change live edit data on invalid input type.
check ( GEditor ) ;
GEditor - > ResetPreviewAudioComponent ( ) ;
InGraphVertex - > SetVertexAccessType ( NewAccessType ) ;
if ( FMetasoundAssetBase * MetasoundAsset = Metasound : : IMetasoundUObjectRegistry : : Get ( ) . GetObjectAsAssetBase ( GraphMember - > GetOutermostObject ( ) ) )
{
2022-09-22 15:02:24 -04:00
MetasoundAsset - > GetModifyContext ( ) . AddMemberIDsModified ( { GraphMember - > GetMemberID ( ) } ) ;
2022-07-18 17:14:25 -04:00
}
2022-04-25 13:29:29 -04:00
}
}
2022-02-09 12:52:07 -05:00
2024-08-20 03:27:21 -04:00
# if WITH_EDITORONLY_DATA
void FMetasoundVertexDetailCustomization : : OnAdvancedPinStateChanged ( TWeakObjectPtr < UMetasoundEditorGraphVertex > InGraphVertex , ECheckBoxState InNewState )
{
if ( InGraphVertex . IsValid ( ) & & AdvancedPinCheckbox . IsValid ( ) )
{
bool Checked = InNewState = = ECheckBoxState : : Checked ;
InGraphVertex - > SetIsAdvancedDisplay ( Checked ) ;
if ( FMetasoundAssetBase * MetasoundAsset = Metasound : : IMetasoundUObjectRegistry : : Get ( ) . GetObjectAsAssetBase ( GraphMember - > GetOutermostObject ( ) ) )
{
MetasoundAsset - > GetModifyContext ( ) . AddMemberIDsModified ( { GraphMember - > GetMemberID ( ) } ) ;
}
}
}
# endif // WITH_EDITORONLY_DATA
2022-02-09 12:52:07 -05:00
void FMetasoundInputDetailCustomization : : CustomizeDetails ( IDetailLayoutBuilder & InDetailLayout )
{
CacheMemberData ( InDetailLayout ) ;
if ( ! GraphMember . IsValid ( ) )
{
return ;
}
CustomizeGeneralCategory ( InDetailLayout ) ;
2022-03-01 16:31:55 -05:00
UMetasoundEditorGraphMemberDefaultLiteral * MemberDefaultLiteral = GraphMember - > GetLiteral ( ) ;
if ( ! MemberDefaultLiteral )
2022-02-09 12:52:07 -05:00
{
return ;
}
// Build preset row first if graph has managed interface, not default constructed, & not a trigger
const bool bIsPreset = GetDocumentHandle ( ) - > GetRootGraphClass ( ) . PresetOptions . bIsPreset ;
const bool bIsDefaultConstructed = MemberDefaultLiteral - > GetLiteralType ( ) = = EMetasoundFrontendLiteralType : : None ;
const bool bIsTriggerDataType = GraphMember - > GetDataType ( ) = = GetMetasoundDataTypeName < FTrigger > ( ) ;
if ( bIsPreset & & ! bIsDefaultConstructed & & ! bIsTriggerDataType )
{
GetDefaultCategoryBuilder ( InDetailLayout )
. AddCustomRow ( MemberCustomizationPrivate : : OverrideInputDefaultText )
. NameContent ( )
[
SNew ( STextBlock )
. Text ( MemberCustomizationPrivate : : OverrideInputDefaultText )
. Font ( IDetailLayoutBuilder : : GetDetailFontBold ( ) )
. ToolTipText ( MemberCustomizationPrivate : : OverrideInputDefaultTooltip )
]
. ValueContent ( )
[
SNew ( SCheckBox )
. OnCheckStateChanged_Lambda ( [ this ] ( ECheckBoxState State )
{
switch ( State )
{
case ECheckBoxState : : Checked :
{
ClearInputInheritsDefault ( ) ;
break ;
}
case ECheckBoxState : : Unchecked :
case ECheckBoxState : : Undetermined :
default :
{
SetInputInheritsDefault ( ) ;
}
}
} )
. IsChecked_Lambda ( [ this ] ( ) { return GetInputInheritsDefault ( ) ? ECheckBoxState : : Unchecked : ECheckBoxState : : Checked ; } )
. ToolTipText ( MemberCustomizationPrivate : : OverrideInputDefaultTooltip )
] ;
}
2024-08-27 19:05:41 -04:00
if ( bIsPreset )
2022-02-09 12:52:07 -05:00
{
2024-08-27 19:05:41 -04:00
if ( ! bIsDefaultConstructed & & ! bIsTriggerDataType )
2022-02-09 12:52:07 -05:00
{
2024-08-27 19:05:41 -04:00
const UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( MemberDefaultLiteral - > FindMember ( ) ) ;
if ( Input )
2022-02-09 12:52:07 -05:00
{
2024-10-03 14:33:23 -04:00
Enabled = TAttribute < bool > : : CreateSPLambda ( AsShared ( ) , [ this ] { return ! GetInputInheritsDefault ( ) ; } ) ;
2024-08-27 19:05:41 -04:00
ResetOverride = FResetToDefaultOverride : : Create (
2024-10-03 14:33:23 -04:00
FIsResetToDefaultVisible : : CreateSPLambda ( AsShared ( ) , [ this ] ( TSharedPtr < IPropertyHandle > /* PropertyHandle */ ) { return ! GetInputInheritsDefault ( ) ; } ) ,
FResetToDefaultHandler : : CreateSPLambda ( AsShared ( ) , [ this ] ( TSharedPtr < IPropertyHandle > /* PropertyHandle */ ) { SetInputInheritsDefault ( ) ; } ) ) ;
2022-02-09 12:52:07 -05:00
}
}
- Fix for attempting to access EngineSubsystem during MetaSound versioning (serialization), which can assert when apparently certain commands in certain contexts can attempt to preload assets prior to the init phase.
- Minor Fix for LocText duplication
#tests BuildCookRun, -game, version MetaSounds assets in editor, PIE
[FYI] bob.tellez
Original CL Desc
-----------------------------------------------------------------
[Backout] - CL33084850
[FYI] Rob.Gay
Original CL Desc
-----------------------------------------------------------------
Version Metasound Document to include all ed data and make all Metasound EdGraph data transient
- Add input template nodes
- Add comment node data to document
- Keep references to member literal data (i.e. knob/slider ranges) in document metadata to ensure continued serialization and flexibility to add more editor-only fields and literal metadata
- Misc builder API updates, bug fixes and migration of controllers to builder API in anticipation of pages
- Sunset non-deterministic guid cvar
#rb phil.popp, helen.yang
[FYI] sondra.moyls
#tests Standard Automated Audio Tests, EngineTests, Offline QA Smoke pass, CPR, etc., extensive MetaSound Editor use, -game MetaSound qa levels, AudioUnitTests
#jira UE-194159
[CL 33102023 by rob gay in ue5-main branch]
2024-04-19 10:09:04 -04:00
}
2024-08-27 19:05:41 -04:00
else
2022-07-18 17:14:25 -04:00
{
2024-10-03 14:33:23 -04:00
Enabled = TAttribute < bool > : : CreateSPLambda ( AsShared ( ) , [ this ]
2022-07-18 17:14:25 -04:00
{
2024-09-13 19:05:03 -04:00
if ( GraphMember . IsValid ( ) )
2022-07-18 17:14:25 -04:00
{
2024-09-13 19:05:03 -04:00
if ( UMetasoundEditorGraphMemberDefaultLiteral * MemberDefaultLiteral = GraphMember - > GetLiteral ( ) )
2022-07-18 17:14:25 -04:00
{
2024-09-13 19:05:03 -04:00
// Make default value uneditable while playing for constructor inputs
const UMetasoundEditorGraphInput * Input = Cast < UMetasoundEditorGraphInput > ( MemberDefaultLiteral - > FindMember ( ) ) ;
if ( Input )
2022-07-18 17:14:25 -04:00
{
2024-09-13 19:05:03 -04:00
if ( Input - > GetVertexAccessType ( ) = = EMetasoundFrontendVertexAccessType : : Value )
{
UObject * MetaSoundObject = Input - > GetOutermostObject ( ) ;
if ( TSharedPtr < FEditor > MetaSoundEditor = FGraphBuilder : : GetEditorForMetasound ( * MetaSoundObject ) )
{
return ! MetaSoundEditor - > IsPlaying ( ) ;
}
}
2022-07-18 17:14:25 -04:00
}
}
2024-09-13 19:05:03 -04:00
}
return true ;
} ) ;
2022-02-09 12:52:07 -05:00
}
2024-08-27 19:05:41 -04:00
CustomizeDefaultCategory ( InDetailLayout ) ;
}
TAttribute < bool > FMetasoundInputDetailCustomization : : GetEnabled ( ) const
{
return Enabled ;
2022-02-09 12:52:07 -05:00
}
bool FMetasoundInputDetailCustomization : : IsDefaultEditable ( ) const
{
return ! GetInputInheritsDefault ( ) ;
}
2022-03-04 03:48:32 -05:00
EVisibility FMetasoundVariableDetailCustomization : : GetDefaultVisibility ( ) const
2021-12-13 18:15:01 -05:00
{
2022-03-04 03:48:32 -05:00
using namespace Frontend ;
2021-12-13 18:15:01 -05:00
if ( GraphMember . IsValid ( ) )
{
2022-03-04 03:48:32 -05:00
bool bIsInputConnected = false ;
const UMetasoundEditorGraphVariable * Variable = CastChecked < UMetasoundEditorGraphVariable > ( GraphMember ) ;
FConstNodeHandle NodeHandle = Variable - > GetConstVariableHandle ( ) - > FindMutatorNode ( ) ;
if ( NodeHandle - > IsValid ( ) )
{
NodeHandle - > IterateConstInputs ( [ & bIsInputConnected ] ( FConstInputHandle InputHandle )
{
bIsInputConnected | = InputHandle - > IsConnectionUserModifiable ( ) & & InputHandle - > IsConnected ( ) ;
} ) ;
}
return bIsInputConnected ? EVisibility : : Collapsed : EVisibility : : Visible ;
2021-12-13 18:15:01 -05:00
}
2022-03-04 03:48:32 -05:00
return EVisibility : : Collapsed ;
2021-12-13 18:15:01 -05:00
}
2024-02-20 18:20:16 -05:00
bool FMetaSoundNodeExtensionHandler : : IsPropertyExtendable ( const UClass * InObjectClass , const IPropertyHandle & PropertyHandle ) const
{
return InObjectClass = = UMetasoundEditorGraphMemberDefaultObjectArray : : StaticClass ( ) ;
}
void FMetaSoundNodeExtensionHandler : : ExtendWidgetRow ( FDetailWidgetRow & InWidgetRow , const IDetailLayoutBuilder & InDetailBuilder , const UClass * InObjectClass , TSharedPtr < IPropertyHandle > PropertyHandle )
{
2024-09-10 10:26:02 -04:00
MemberCustomizationPrivate : : CreateDefaultValueObjectCopyPasteActions ( InWidgetRow , PropertyHandle ) ;
2024-02-20 18:20:16 -05:00
}
2021-03-19 15:10:57 -04:00
} // namespace Editor
} // namespace Metasound
# undef LOCTEXT_NAMESPACE