2023-03-07 17:01:52 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundBuilderSubsystem.h"
2023-03-09 17:56:53 -05:00
# include "Algo/Find.h"
2023-03-07 17:01:52 -05:00
# include "Algo/Transform.h"
2023-12-01 12:57:59 -05:00
# include "AudioDevice.h"
2023-03-07 17:01:52 -05:00
# include "Components/AudioComponent.h"
2024-10-08 18:08:08 -04:00
# include "CoreGlobals.h"
2023-05-10 20:28:39 -04:00
# include "Engine/Engine.h"
2023-03-07 17:01:52 -05:00
# include "HAL/IConsoleManager.h"
# include "Interfaces/MetasoundOutputFormatInterfaces.h"
# include "Interfaces/MetasoundFrontendSourceInterface.h"
# include "Metasound.h"
2023-06-15 13:50:27 -04:00
# include "MetasoundAssetSubsystem.h"
2023-06-16 17:48:20 -04:00
# include "MetasoundDataReference.h"
2024-05-08 14:53:53 -04:00
# include "MetasoundDocumentBuilderRegistry.h"
# include "MetasoundDocumentInterface.h"
2023-06-16 17:48:20 -04:00
# include "MetasoundDynamicOperatorTransactor.h"
# include "MetasoundFrontendDataTypeRegistry.h"
2023-03-07 17:01:52 -05:00
# include "MetasoundFrontendDocument.h"
2023-09-05 17:54:02 -04:00
# include "MetasoundFrontendDocumentIdGenerator.h"
2023-03-23 14:04:36 -04:00
# include "MetasoundFrontendRegistries.h"
2023-03-07 17:01:52 -05:00
# include "MetasoundFrontendSearchEngine.h"
# include "MetasoundFrontendTransform.h"
# include "MetasoundGeneratorHandle.h"
# include "MetasoundLog.h"
# include "MetasoundParameterTransmitter.h"
2024-05-08 14:53:53 -04:00
# include "MetasoundSettings.h"
2023-03-07 17:01:52 -05:00
# include "MetasoundSource.h"
# include "MetasoundTrace.h"
# include "MetasoundUObjectRegistry.h"
2023-06-16 17:48:20 -04:00
# include "MetasoundVertex.h"
- 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
# include "NodeTemplates/MetasoundFrontendNodeTemplateInput.h"
2024-05-03 09:13:43 -04:00
# include "UObject/PerPlatformProperties.h"
2023-03-07 17:01:52 -05:00
# include UE_INLINE_GENERATED_CPP_BY_NAME(MetasoundBuilderSubsystem)
namespace Metasound : : Engine
{
2024-08-23 21:59:54 -04:00
FAutoConsoleCommand CVarMetaSoundSetTargetPage (
TEXT ( " au.MetaSound.Pages.SetTarget " ) ,
TEXT ( " Sets the target page to that with the given name. If name not specified or not found, command is ignored. \n " ) ,
FConsoleCommandWithArgsDelegate : : CreateLambda ( [ ] ( const TArray < FString > & Args )
{
if ( ! Args . IsEmpty ( ) )
{
if ( UMetaSoundBuilderSubsystem * Subsystem = GEngine - > GetEngineSubsystem < UMetaSoundBuilderSubsystem > ( ) )
{
Subsystem - > SetTargetPage ( FName { * Args . Last ( ) } ) ;
}
}
} )
) ;
2023-03-07 17:01:52 -05:00
namespace BuilderSubsystemPrivate
{
template < typename TLiteralType >
FMetasoundFrontendLiteral CreatePODMetaSoundLiteral ( const TLiteralType & Value , FName & OutDataType )
{
OutDataType = GetMetasoundDataTypeName < TLiteralType > ( ) ;
FMetasoundFrontendLiteral Literal ;
Literal . Set ( Value ) ;
return Literal ;
}
2023-03-09 17:56:53 -05:00
2023-06-16 17:48:20 -04:00
TUniquePtr < INode > CreateDynamicNodeFromFrontendLiteral ( const FName DataType , const FMetasoundFrontendLiteral & InLiteral )
{
using namespace Frontend ;
FLiteral ValueLiteral = InLiteral . ToLiteral ( DataType ) ;
// TODO: Node name "Literal" is always the same. Consolidate and deprecate providing unique node name to avoid unnecessary FName table bloat.
FLiteralNodeConstructorParams Params { " Literal " , FGuid : : NewGuid ( ) , MoveTemp ( ValueLiteral ) } ;
return IDataTypeRegistry : : Get ( ) . CreateLiteralNode ( DataType , MoveTemp ( Params ) ) ;
}
2024-08-13 14:58:36 -04:00
TOptional < FMetasoundFrontendLiteral > TryResolveNodeInputDefault ( const FMetaSoundFrontendDocumentBuilder & Builder , const FGuid & InNodeID , FName VertexName )
{
TOptional < FMetasoundFrontendLiteral > DefaultLiteral ;
if ( const FMetasoundFrontendVertexLiteral * InputDefault = Builder . FindNodeInputDefault ( InNodeID , VertexName ) )
{
DefaultLiteral = InputDefault - > Value ;
}
else if ( const TArray < FMetasoundFrontendClassInputDefault > * ClassDefaults = Builder . FindNodeClassInputDefaults ( InNodeID , VertexName ) )
{
2024-08-23 21:59:54 -04:00
const FGuid PageID = FDocumentBuilderRegistry : : GetChecked ( ) . ResolveTargetPageID ( * ClassDefaults ) ;
auto MatchesPageID = [ & PageID ] ( const FMetasoundFrontendClassInputDefault & InputDefault ) { return InputDefault . PageID = = PageID ; } ;
if ( const FMetasoundFrontendClassInputDefault * ClassDefault = ClassDefaults - > FindByPredicate ( MatchesPageID ) )
2024-08-13 14:58:36 -04:00
{
2024-08-23 21:59:54 -04:00
DefaultLiteral = ClassDefault - > Literal ;
2024-08-13 14:58:36 -04:00
}
}
return DefaultLiteral ;
}
2023-03-07 17:01:52 -05:00
} // namespace BuilderSubsystemPrivate
} // namespace Metasound::Engine
2024-10-01 19:51:34 -04:00
void UMetaSoundPatchBuilder : : BuildAndOverwriteMetaSoundInternal ( TScriptInterface < IMetaSoundDocumentInterface > ExistingMetaSound , bool bForceUniqueClassName ) const
2023-03-07 17:01:52 -05:00
{
2024-10-01 19:02:59 -04:00
FMetaSoundBuilderOptions Options ;
Options . ExistingMetaSound = ExistingMetaSound ;
Options . bForceUniqueClassName = bForceUniqueClassName ;
constexpr UObject * Parent = nullptr ;
BuildInternal < UMetaSoundPatch > ( Parent , Options ) ;
}
TScriptInterface < IMetaSoundDocumentInterface > UMetaSoundPatchBuilder : : BuildNewMetaSound ( FName NameBase ) const
{
FMetaSoundBuilderOptions Options ;
Options . Name = NameBase ;
constexpr UObject * Parent = nullptr ;
return & BuildInternal < UMetaSoundPatch > ( Parent , Options ) ;
2023-03-07 17:01:52 -05:00
}
2024-05-08 14:53:53 -04:00
const UClass & UMetaSoundPatchBuilder : : GetBaseMetaSoundUClass ( ) const
2023-04-06 16:32:00 -04:00
{
return * UMetaSoundPatch : : StaticClass ( ) ;
}
2024-05-08 14:53:53 -04:00
void UMetaSoundPatchBuilder : : OnAssetReferenceAdded ( TScriptInterface < IMetaSoundDocumentInterface > DocInterface )
{
2024-05-10 12:40:21 -04:00
using namespace Metasound : : Frontend ;
2024-05-08 14:53:53 -04:00
check ( DocInterface . GetObject ( ) ) ;
2024-05-10 12:40:21 -04:00
UMetaSoundPatch & Patch = Builder . CastDocumentObjectChecked < UMetaSoundPatch > ( ) ;
Patch . ReferencedAssetClassObjects . Add ( DocInterface . GetObject ( ) ) ;
2024-05-20 17:08:47 -04:00
const FNodeRegistryKey RegistryKey ( DocInterface - > GetConstDocument ( ) . RootGraph ) ;
2024-05-10 12:40:21 -04:00
Patch . ReferencedAssetClassKeys . Add ( RegistryKey . ToString ( ) ) ;
2024-05-08 14:53:53 -04:00
}
void UMetaSoundPatchBuilder : : OnRemovingAssetReference ( TScriptInterface < IMetaSoundDocumentInterface > DocInterface )
{
2024-05-10 12:40:21 -04:00
using namespace Metasound : : Frontend ;
2024-05-08 14:53:53 -04:00
check ( DocInterface . GetObject ( ) ) ;
2024-05-10 12:40:21 -04:00
UMetaSoundPatch & Patch = Builder . CastDocumentObjectChecked < UMetaSoundPatch > ( ) ;
Patch . ReferencedAssetClassObjects . Remove ( DocInterface . GetObject ( ) ) ;
2024-05-20 17:08:47 -04:00
const FNodeRegistryKey RegistryKey ( DocInterface - > GetConstDocument ( ) . RootGraph ) ;
2024-05-10 12:40:21 -04:00
Patch . ReferencedAssetClassKeys . Remove ( RegistryKey . ToString ( ) ) ;
2024-05-08 14:53:53 -04:00
}
2023-06-16 17:48:20 -04:00
UMetaSoundBuilderBase & UMetaSoundBuilderSubsystem : : AttachBuilderToAssetChecked ( UObject & InObject ) const
2023-03-07 17:01:52 -05:00
{
2023-06-16 17:48:20 -04:00
const UClass * BaseClass = InObject . GetClass ( ) ;
if ( BaseClass = = UMetaSoundSource : : StaticClass ( ) )
{
2024-05-08 14:53:53 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2023-06-16 17:48:20 -04:00
UMetaSoundSourceBuilder * NewBuilder = AttachSourceBuilderToAsset ( CastChecked < UMetaSoundSource > ( & InObject ) ) ;
2024-05-08 14:53:53 -04:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2023-06-16 17:48:20 -04:00
return * NewBuilder ;
}
else if ( BaseClass = = UMetaSoundPatch : : StaticClass ( ) )
{
2024-05-08 14:53:53 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2023-06-16 17:48:20 -04:00
UMetaSoundPatchBuilder * NewBuilder = AttachPatchBuilderToAsset ( CastChecked < UMetaSoundPatch > ( & InObject ) ) ;
2024-05-08 14:53:53 -04:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2023-06-16 17:48:20 -04:00
return * NewBuilder ;
}
else
{
checkf ( false , TEXT ( " UClass '%s' is not a base MetaSound that supports attachment via the MetaSoundBuilderSubsystem " ) , * BaseClass - > GetFullName ( ) ) ;
2023-09-13 20:11:49 -04:00
return * NewObject < UMetaSoundPatchBuilder > ( ) ;
2023-06-16 17:48:20 -04:00
}
}
UMetaSoundPatchBuilder * UMetaSoundBuilderSubsystem : : AttachPatchBuilderToAsset ( UMetaSoundPatch * InPatch ) const
{
2024-05-08 14:53:53 -04:00
# if WITH_EDITORONLY_DATA
using namespace Metasound : : Engine ;
2023-06-16 17:48:20 -04:00
if ( InPatch )
{
2024-05-08 14:53:53 -04:00
return & FDocumentBuilderRegistry : : GetChecked ( ) . FindOrBeginBuilding < UMetaSoundPatchBuilder > ( * InPatch ) ;
2023-06-16 17:48:20 -04:00
}
2024-05-08 14:53:53 -04:00
# endif // WITH_EDITORONLY_DATA
2023-06-16 17:48:20 -04:00
return nullptr ;
}
UMetaSoundSourceBuilder * UMetaSoundBuilderSubsystem : : AttachSourceBuilderToAsset ( UMetaSoundSource * InSource ) const
{
2024-05-08 14:53:53 -04:00
# if WITH_EDITORONLY_DATA
using namespace Metasound : : Engine ;
2023-06-16 17:48:20 -04:00
if ( InSource )
{
2024-05-08 14:53:53 -04:00
UMetaSoundSourceBuilder & SourceBuilder = FDocumentBuilderRegistry : : GetChecked ( ) . FindOrBeginBuilding < UMetaSoundSourceBuilder > ( * InSource ) ;
2023-06-16 17:48:20 -04:00
return & SourceBuilder ;
}
2024-05-08 14:53:53 -04:00
# endif // WITH_EDITORONLY_DATA
2023-06-16 17:48:20 -04:00
return nullptr ;
}
void UMetaSoundSourceBuilder : : Audition ( UObject * Parent , UAudioComponent * AudioComponent , FOnCreateAuditionGeneratorHandleDelegate CreateGenerator , bool bLiveUpdatesEnabled )
{
2023-09-13 20:11:49 -04:00
using namespace Metasound ;
using namespace Metasound : : DynamicGraph ;
2023-06-16 17:48:20 -04:00
using namespace Metasound : : Engine ;
2023-03-07 17:01:52 -05:00
using namespace Metasound : : Frontend ;
2023-03-23 14:04:36 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( UMetaSoundSourceBuilder : : Audition ) ;
2023-03-07 17:01:52 -05:00
if ( ! AudioComponent )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Failed to audition MetaSoundBuilder '%s': No AudioComponent supplied " ) , * GetFullName ( ) ) ;
return ;
}
2023-09-13 20:11:49 -04:00
UMetaSoundSource & MetaSoundSource = GetMetaSoundSource ( ) ;
2023-10-31 17:16:11 -04:00
RegisterGraphIfOutstandingTransactions ( MetaSoundSource ) ;
2023-06-16 17:48:20 -04:00
2023-09-13 20:11:49 -04:00
// Must be called post register as register ensures cached runtime data passed to transactor is up-to-date
2024-05-08 14:53:53 -04:00
MetaSoundSource . SetDynamicGeneratorEnabled ( bLiveUpdatesEnabled ) ;
- 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
MetaSoundSource . ConformObjectToDocument ( ) ;
2023-03-07 17:01:52 -05:00
2023-09-13 20:11:49 -04:00
AudioComponent - > SetSound ( & MetaSoundSource ) ;
2023-06-16 17:48:20 -04:00
2023-03-07 17:01:52 -05:00
if ( CreateGenerator . IsBound ( ) )
{
UMetasoundGeneratorHandle * NewHandle = UMetasoundGeneratorHandle : : CreateMetaSoundGeneratorHandle ( AudioComponent ) ;
checkf ( NewHandle , TEXT ( " BindToGeneratorDelegate Failed when attempting to audition MetaSoundSource builder '%s' " ) , * GetName ( ) ) ;
CreateGenerator . Execute ( NewHandle ) ;
}
2023-12-01 12:57:59 -05:00
if ( bLiveUpdatesEnabled )
{
LiveComponentIDs . Add ( AudioComponent - > GetAudioComponentID ( ) ) ;
LiveComponentHandle = AudioComponent - > OnAudioFinishedNative . AddUObject ( this , & UMetaSoundSourceBuilder : : OnLiveComponentFinished ) ;
}
2023-03-07 17:01:52 -05:00
AudioComponent - > Play ( ) ;
}
2023-12-01 12:57:59 -05:00
void UMetaSoundSourceBuilder : : OnLiveComponentFinished ( UAudioComponent * AudioComponent )
{
2024-01-19 16:41:35 -05:00
LiveComponentIDs . RemoveSwap ( AudioComponent - > GetAudioComponentID ( ) , EAllowShrinking : : No ) ;
2023-12-01 12:57:59 -05:00
if ( LiveComponentIDs . IsEmpty ( ) )
{
AudioComponent - > OnAudioFinishedNative . Remove ( LiveComponentHandle ) ;
}
}
2023-06-16 17:48:20 -04:00
bool UMetaSoundSourceBuilder : : ExecuteAuditionableTransaction ( FAuditionableTransaction Transaction ) const
{
using namespace Metasound : : Engine : : BuilderSubsystemPrivate ;
using namespace Metasound : : DynamicGraph ;
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( UMetaSoundSourceBuilder : : ExecuteAuditionableTransaction ) ;
2024-10-08 18:08:08 -04:00
checkf ( ! IsRunningCookCommandlet ( ) ,
TEXT ( " ExecuteAuditionableTransaction cannot be called while running cook. " )
TEXT ( " Requires resolved graph which should not be relied on while cooking as it can mutate depending on cook's " )
TEXT ( " target platform, which is independent of targetable page(s) " ) ) ;
2023-09-13 20:11:49 -04:00
TSharedPtr < FDynamicOperatorTransactor > Transactor = GetMetaSoundSource ( ) . GetDynamicGeneratorTransactor ( ) ;
if ( Transactor . IsValid ( ) )
2023-06-16 17:48:20 -04:00
{
2023-09-13 20:11:49 -04:00
return Transaction ( * Transactor ) ;
2023-06-16 17:48:20 -04:00
}
return false ;
}
2024-10-01 19:51:34 -04:00
void UMetaSoundSourceBuilder : : BuildAndOverwriteMetaSoundInternal ( TScriptInterface < IMetaSoundDocumentInterface > ExistingMetaSound , bool bForceUniqueClassName ) const
2023-03-07 17:01:52 -05:00
{
2024-10-01 19:02:59 -04:00
FMetaSoundBuilderOptions Options ;
Options . ExistingMetaSound = ExistingMetaSound ;
Options . bForceUniqueClassName = bForceUniqueClassName ;
constexpr UObject * Parent = nullptr ;
BuildInternal < UMetaSoundSource > ( Parent , Options ) ;
}
TScriptInterface < IMetaSoundDocumentInterface > UMetaSoundSourceBuilder : : BuildNewMetaSound ( FName NameBase ) const
{
FMetaSoundBuilderOptions Options ;
Options . Name = NameBase ;
constexpr UObject * Parent = nullptr ;
return & BuildInternal < UMetaSoundSource > ( Parent , Options ) ;
2023-06-16 17:48:20 -04:00
}
2023-03-07 17:01:52 -05:00
const Metasound : : Engine : : FOutputAudioFormatInfoPair * UMetaSoundSourceBuilder : : FindOutputAudioFormatInfo ( ) const
{
using namespace Metasound : : Engine ;
const FOutputAudioFormatInfoMap & FormatInfo = GetOutputAudioFormatInfo ( ) ;
auto Predicate = [ this ] ( const FOutputAudioFormatInfoPair & Pair )
{
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Document = Builder . GetConstDocumentChecked ( ) ;
2023-03-07 17:01:52 -05:00
return Document . Interfaces . Contains ( Pair . Value . InterfaceVersion ) ;
} ;
return Algo : : FindByPredicate ( FormatInfo , Predicate ) ;
}
2024-05-08 14:53:53 -04:00
const UClass & UMetaSoundSourceBuilder : : GetBaseMetaSoundUClass ( ) const
2023-04-06 16:32:00 -04:00
{
return * UMetaSoundSource : : StaticClass ( ) ;
}
2023-06-16 17:48:20 -04:00
bool UMetaSoundSourceBuilder : : GetLiveUpdatesEnabled ( ) const
{
2023-09-13 20:11:49 -04:00
return GetMetaSoundSource ( ) . GetDynamicGeneratorTransactor ( ) . IsValid ( ) ;
}
2023-06-16 17:48:20 -04:00
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendGraph & UMetaSoundSourceBuilder : : GetConstTargetPageGraphChecked ( ) const
{
const FMetasoundFrontendGraphClass & RootGraph = Builder . GetConstDocumentChecked ( ) . RootGraph ;
return RootGraph . FindConstGraphChecked ( TargetPageID ) ;
}
2023-09-13 20:11:49 -04:00
const UMetaSoundSource & UMetaSoundSourceBuilder : : GetMetaSoundSource ( ) const
{
return GetConstBuilder ( ) . CastDocumentObjectChecked < UMetaSoundSource > ( ) ;
}
UMetaSoundSource & UMetaSoundSourceBuilder : : GetMetaSoundSource ( )
{
return Builder . CastDocumentObjectChecked < UMetaSoundSource > ( ) ;
2023-06-16 17:48:20 -04:00
}
2023-12-01 12:57:59 -05:00
void UMetaSoundSourceBuilder : : InitDelegates ( Metasound : : Frontend : : FDocumentModifyDelegates & OutDocumentDelegates )
2023-06-16 17:48:20 -04:00
{
2024-05-08 14:53:53 -04:00
Super : : InitDelegates ( OutDocumentDelegates ) ;
2024-10-08 18:08:08 -04:00
if ( ! IsRunningCookCommandlet ( ) )
{
OutDocumentDelegates . PageDelegates . OnPageAdded . AddUObject ( this , & UMetaSoundSourceBuilder : : OnPageAdded ) ;
OutDocumentDelegates . PageDelegates . OnRemovingPage . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemovingPage ) ;
2023-06-16 17:48:20 -04:00
2024-10-08 18:08:08 -04:00
OutDocumentDelegates . InterfaceDelegates . OnInputAdded . AddUObject ( this , & UMetaSoundSourceBuilder : : OnInputAdded ) ;
OutDocumentDelegates . InterfaceDelegates . OnOutputAdded . AddUObject ( this , & UMetaSoundSourceBuilder : : OnOutputAdded ) ;
OutDocumentDelegates . InterfaceDelegates . OnRemovingInput . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemovingInput ) ;
OutDocumentDelegates . InterfaceDelegates . OnRemovingOutput . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemovingOutput ) ;
2023-06-16 17:48:20 -04:00
2024-10-08 18:08:08 -04:00
InitTargetPageDelegates ( OutDocumentDelegates ) ;
}
2024-06-18 16:47:21 -04:00
}
2024-06-27 23:26:57 -04:00
void UMetaSoundSourceBuilder : : InitTargetPageDelegates ( Metasound : : Frontend : : FDocumentModifyDelegates & OutDocumentDelegates )
2024-06-18 16:47:21 -04:00
{
using namespace Metasound : : DynamicGraph ;
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
// If currently executing live audition, must call stop as provided transactions may
// get corrupted by the fact that the executable page ID may now resolve to a different value.
ExecuteAuditionableTransaction ( [ this ] ( FDynamicOperatorTransactor & Transactor )
{
bool bComponentsStopped = false ;
for ( uint64 AudioComponentID : LiveComponentIDs )
{
if ( UAudioComponent * AudioComponent = UAudioComponent : : GetAudioComponentFromID ( AudioComponentID ) )
{
AudioComponent - > Stop ( ) ;
bComponentsStopped = true ;
}
}
return bComponentsStopped ;
} ) ;
OutDocumentDelegates . IterateGraphNodeDelegates ( [ this ] ( FNodeModifyDelegates & NodeDelegates )
{
NodeDelegates . OnNodeAdded . RemoveAll ( this ) ;
NodeDelegates . OnNodeInputLiteralSet . RemoveAll ( this ) ;
NodeDelegates . OnRemoveSwappingNode . RemoveAll ( this ) ;
NodeDelegates . OnRemovingNodeInputLiteral . RemoveAll ( this ) ;
} ) ;
OutDocumentDelegates . IterateGraphEdgeDelegates ( [ this ] ( FEdgeModifyDelegates & EdgeDelegates )
{
EdgeDelegates . OnEdgeAdded . RemoveAll ( this ) ;
EdgeDelegates . OnRemoveSwappingEdge . RemoveAll ( this ) ;
} ) ;
2024-06-27 23:26:57 -04:00
const IMetaSoundDocumentInterface & DocInterface = GetConstBuilder ( ) . GetConstDocumentInterfaceChecked ( ) ;
2024-08-23 21:59:54 -04:00
TargetPageID = FDocumentBuilderRegistry : : GetChecked ( ) . ResolveTargetPageID ( DocInterface . GetConstDocument ( ) . RootGraph ) ;
2024-06-18 16:47:21 -04:00
2024-08-23 21:59:54 -04:00
FEdgeModifyDelegates & EdgeDelegates = OutDocumentDelegates . FindEdgeDelegatesChecked ( TargetPageID ) ;
EdgeDelegates . OnEdgeAdded . AddUObject ( this , & UMetaSoundSourceBuilder : : OnEdgeAdded ) ;
EdgeDelegates . OnRemoveSwappingEdge . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemoveSwappingEdge ) ;
FNodeModifyDelegates & NodeDelegates = OutDocumentDelegates . FindNodeDelegatesChecked ( TargetPageID ) ;
NodeDelegates . OnNodeAdded . AddUObject ( this , & UMetaSoundSourceBuilder : : OnNodeAdded ) ;
NodeDelegates . OnNodeInputLiteralSet . AddUObject ( this , & UMetaSoundSourceBuilder : : OnNodeInputLiteralSet ) ;
NodeDelegates . OnRemoveSwappingNode . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemoveSwappingNode ) ;
NodeDelegates . OnRemovingNodeInputLiteral . AddUObject ( this , & UMetaSoundSourceBuilder : : OnRemovingNodeInputLiteral ) ;
2023-06-16 17:48:20 -04:00
}
2024-05-08 14:53:53 -04:00
void UMetaSoundSourceBuilder : : OnAssetReferenceAdded ( TScriptInterface < IMetaSoundDocumentInterface > DocInterface )
{
2024-05-10 12:40:21 -04:00
using namespace Metasound : : Frontend ;
2024-05-08 14:53:53 -04:00
check ( DocInterface . GetObject ( ) ) ;
2024-05-10 12:40:21 -04:00
UMetaSoundSource & Source = GetMetaSoundSource ( ) ;
Source . ReferencedAssetClassObjects . Add ( DocInterface . GetObject ( ) ) ;
2024-05-20 17:08:47 -04:00
const FNodeRegistryKey RegistryKey ( DocInterface - > GetConstDocument ( ) . RootGraph ) ;
2024-05-10 12:40:21 -04:00
Source . ReferencedAssetClassKeys . Add ( RegistryKey . ToString ( ) ) ;
2024-05-08 14:53:53 -04:00
}
2023-06-16 17:48:20 -04:00
void UMetaSoundSourceBuilder : : OnEdgeAdded ( int32 EdgeIndex ) const
{
using namespace Metasound : : DynamicGraph ;
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendEdge & NewEdge = GetConstTargetPageGraphChecked ( ) . Edges [ EdgeIndex ] ;
2023-06-16 17:48:20 -04:00
ExecuteAuditionableTransaction ( [ this , & NewEdge ] ( Metasound : : DynamicGraph : : FDynamicOperatorTransactor & Transactor )
{
2024-05-20 17:08:47 -04:00
const FMetaSoundFrontendDocumentBuilder & DocBuilder = GetConstBuilder ( ) ;
const FMetasoundFrontendVertex * FromNodeOutput = DocBuilder . FindNodeOutput ( NewEdge . FromNodeID , NewEdge . FromVertexID ) ;
const FMetasoundFrontendVertex * ToNodeInput = DocBuilder . FindNodeInput ( NewEdge . ToNodeID , NewEdge . ToVertexID ) ;
2023-06-16 17:48:20 -04:00
if ( FromNodeOutput & & ToNodeInput )
{
Transactor . AddDataEdge ( NewEdge . FromNodeID , FromNodeOutput - > Name , NewEdge . ToNodeID , ToNodeInput - > Name ) ;
return true ;
}
return false ;
} ) ;
}
2023-08-16 18:37:56 -04:00
TOptional < Metasound : : FAnyDataReference > UMetaSoundSourceBuilder : : CreateDataReference (
const Metasound : : FOperatorSettings & InOperatorSettings ,
FName DataType ,
const Metasound : : FLiteral & InLiteral ,
Metasound : : EDataReferenceAccessType AccessType )
2023-06-16 17:48:20 -04:00
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
return IDataTypeRegistry : : Get ( ) . CreateDataReference ( DataType , AccessType , InLiteral , InOperatorSettings ) ;
} ;
2023-12-01 12:57:59 -05:00
void UMetaSoundSourceBuilder : : OnInputAdded ( int32 InputIndex )
2023-06-16 17:48:20 -04:00
{
using namespace Metasound : : DynamicGraph ;
ExecuteAuditionableTransaction ( [ this , InputIndex ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Doc = Builder . GetConstDocumentChecked ( ) ;
2023-06-16 17:48:20 -04:00
const FMetasoundFrontendGraphClass & GraphClass = Doc . RootGraph ;
const FMetasoundFrontendClassInput & NewInput = GraphClass . Interface . Inputs [ InputIndex ] ;
2023-12-01 12:57:59 -05:00
constexpr bool bCreateUObjectProxies = true ;
UMetaSoundSource & Source = GetMetaSoundSource ( ) ;
Source . RuntimeInputData . InputMap . Add ( NewInput . Name , UMetaSoundSource : : CreateRuntimeInput ( IDataTypeRegistry : : Get ( ) , NewInput , bCreateUObjectProxies ) ) ;
for ( uint64 AudioComponentID : LiveComponentIDs )
{
if ( UAudioComponent * AudioComponent = UAudioComponent : : GetAudioComponentFromID ( AudioComponentID ) )
{
if ( FAudioDevice * AudioDevice = AudioComponent - > GetAudioDevice ( ) )
{
AudioDevice - > SendCommandToActiveSounds ( AudioComponentID , [ NewInputName = NewInput . Name ] ( FActiveSound & ActiveSound )
{
static_cast < FMetaSoundParameterTransmitter * > ( ActiveSound . GetTransmitter ( ) ) - > AddAvailableParameter ( NewInputName ) ;
} ) ;
}
}
}
2024-07-26 14:23:35 -04:00
const FLiteral NewInputLiteral = NewInput . FindConstDefaultChecked ( Frontend : : DefaultPageID ) . ToLiteral ( NewInput . TypeName ) ;
2023-08-17 17:25:00 -04:00
Transactor . AddInputDataDestination ( NewInput . NodeID , NewInput . Name , NewInputLiteral , & UMetaSoundSourceBuilder : : CreateDataReference ) ;
2023-06-16 17:48:20 -04:00
return true ;
} ) ;
}
void UMetaSoundSourceBuilder : : OnNodeAdded ( int32 NodeIndex ) const
{
using namespace Metasound : : DynamicGraph ;
ExecuteAuditionableTransaction ( [ this , NodeIndex ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendNode & AddedNode = GetConstTargetPageGraphChecked ( ) . Nodes [ NodeIndex ] ;
2023-06-16 17:48:20 -04:00
const FMetasoundFrontendClass * NodeClass = Builder . FindDependency ( AddedNode . ClassID ) ;
checkf ( NodeClass , TEXT ( " Node successfully added to graph but document is missing associated dependency " ) ) ;
2023-10-12 16:37:45 -04:00
const FNodeRegistryKey & ClassKey = FNodeRegistryKey ( NodeClass - > Metadata ) ;
2023-08-15 16:06:58 -04:00
FMetasoundFrontendRegistryContainer & NodeRegistry = * FMetasoundFrontendRegistryContainer : : Get ( ) ;
IDataTypeRegistry & DataTypeRegistry = IDataTypeRegistry : : Get ( ) ;
TUniquePtr < INode > NewNode ;
2023-06-16 17:48:20 -04:00
switch ( NodeClass - > Metadata . GetType ( ) )
{
2023-08-15 16:06:58 -04:00
case EMetasoundFrontendClassType : : VariableDeferredAccessor :
case EMetasoundFrontendClassType : : VariableAccessor :
case EMetasoundFrontendClassType : : VariableMutator :
2023-06-16 17:48:20 -04:00
case EMetasoundFrontendClassType : : External :
2023-08-15 16:06:58 -04:00
case EMetasoundFrontendClassType : : Graph :
2023-06-16 17:48:20 -04:00
{
2023-08-15 16:06:58 -04:00
const Metasound : : FNodeInitData InitData { AddedNode . Name , AddedNode . GetID ( ) } ;
NewNode = NodeRegistry . CreateNode ( ClassKey , InitData ) ;
2023-06-16 17:48:20 -04:00
}
break ;
2023-08-15 16:06:58 -04:00
case EMetasoundFrontendClassType : : Input :
2023-06-16 17:48:20 -04:00
{
2023-08-15 16:06:58 -04:00
const FName & DataTypeName = NodeClass - > Metadata . GetClassName ( ) . Name ;
const FMetasoundFrontendVertex & InputVertex = AddedNode . Interface . Inputs . Last ( ) ;
2023-09-15 11:47:57 -04:00
const FMetasoundFrontendLiteral * DefaultLiteral = nullptr ;
auto HasEqualVertexID = [ & VertexID = InputVertex . VertexID ] ( const FMetasoundFrontendVertexLiteral & InVertexLiteral )
{
return InVertexLiteral . VertexID = = VertexID ;
} ;
// Check for default literal on Node
if ( const FMetasoundFrontendVertexLiteral * VertexLiteralOnNode = AddedNode . InputLiterals . FindByPredicate ( HasEqualVertexID ) )
{
DefaultLiteral = & ( VertexLiteralOnNode - > Value ) ;
}
// Check for default literal on class input
else if ( const FMetasoundFrontendClassInput * GraphInput = Builder . FindGraphInput ( InputVertex . Name ) )
{
2024-07-26 14:23:35 -04:00
DefaultLiteral = & ( GraphInput - > FindConstDefaultChecked ( Frontend : : DefaultPageID ) ) ;
2023-09-15 11:47:57 -04:00
}
else
{
// As a last resort, get default literal on node class
2024-07-26 14:23:35 -04:00
DefaultLiteral = & ( NodeClass - > Interface . Inputs . Last ( ) . FindConstDefaultChecked ( Frontend : : DefaultPageID ) ) ;
2023-09-15 11:47:57 -04:00
}
2023-08-15 16:06:58 -04:00
FInputNodeConstructorParams InitData
{
AddedNode . Name ,
AddedNode . GetID ( ) ,
InputVertex . Name ,
2023-09-15 11:47:57 -04:00
DefaultLiteral - > ToLiteral ( DataTypeName )
2023-08-15 16:06:58 -04:00
} ;
NewNode = DataTypeRegistry . CreateInputNode ( DataTypeName , MoveTemp ( InitData ) ) ;
2023-06-16 17:48:20 -04:00
}
2023-08-15 16:06:58 -04:00
break ;
case EMetasoundFrontendClassType : : Variable :
{
const FName & DataTypeName = NodeClass - > Metadata . GetClassName ( ) . Name ;
FDefaultLiteralNodeConstructorParams InitData { AddedNode . Name , AddedNode . GetID ( ) , DataTypeRegistry . CreateDefaultLiteral ( DataTypeName ) } ;
NewNode = DataTypeRegistry . CreateVariableNode ( DataTypeName , MoveTemp ( InitData ) ) ;
}
break ;
case EMetasoundFrontendClassType : : Literal :
{
const FName & DataTypeName = NodeClass - > Metadata . GetClassName ( ) . Name ;
FDefaultLiteralNodeConstructorParams InitData { AddedNode . Name , AddedNode . GetID ( ) , DataTypeRegistry . CreateDefaultLiteral ( DataTypeName ) } ;
NewNode = DataTypeRegistry . CreateLiteralNode ( DataTypeName , MoveTemp ( InitData ) ) ;
}
break ;
case EMetasoundFrontendClassType : : Output :
{
const FName & DataTypeName = NodeClass - > Metadata . GetClassName ( ) . Name ;
const FMetasoundFrontendVertex & OutputVertex = AddedNode . Interface . Outputs . Last ( ) ;
FDefaultNamedVertexNodeConstructorParams InitData { AddedNode . Name , AddedNode . GetID ( ) , OutputVertex . Name } ;
NewNode = DataTypeRegistry . CreateOutputNode ( DataTypeName , MoveTemp ( InitData ) ) ;
}
break ;
case EMetasoundFrontendClassType : : Template :
default :
static_assert ( static_cast < int32 > ( EMetasoundFrontendClassType : : Invalid ) = = 10 , " Possible missed EMetasoundFrontendClassType case coverage " ) ;
} ;
if ( ! NewNode . IsValid ( ) )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' failed to create and forward added node '%s' to live update transactor. " ) , * GetName ( ) , * AddedNode . Name . ToString ( ) ) ;
return false ;
2023-06-16 17:48:20 -04:00
}
2023-08-15 16:06:58 -04:00
Transactor . AddNode ( AddedNode . GetID ( ) , MoveTemp ( NewNode ) ) ;
return true ;
2023-06-16 17:48:20 -04:00
} ) ;
}
void UMetaSoundSourceBuilder : : OnNodeInputLiteralSet ( int32 NodeIndex , int32 VertexIndex , int32 LiteralIndex ) const
{
using namespace Metasound : : DynamicGraph ;
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendNode & Node = GetConstTargetPageGraphChecked ( ) . Nodes [ NodeIndex ] ;
2023-07-28 16:23:27 -04:00
const FMetasoundFrontendVertex & Input = Node . Interface . Inputs [ VertexIndex ] ;
2023-08-07 13:38:36 -04:00
// Only send the literal down if not connected, as the graph core layer
// will disconnect if a new literal is sent and edge already exists.
2023-07-28 16:23:27 -04:00
if ( ! Builder . IsNodeInputConnected ( Node . GetID ( ) , Input . VertexID ) )
2023-06-16 17:48:20 -04:00
{
2023-07-28 16:23:27 -04:00
ExecuteAuditionableTransaction ( [ this , & Node , & Input , & LiteralIndex ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound ;
using namespace Metasound : : Engine ;
2023-06-16 17:48:20 -04:00
2023-07-28 16:23:27 -04:00
const FMetasoundFrontendLiteral & InputDefault = Node . InputLiterals [ LiteralIndex ] . Value ;
TUniquePtr < INode > LiteralNode = BuilderSubsystemPrivate : : CreateDynamicNodeFromFrontendLiteral ( Input . TypeName , InputDefault ) ;
Transactor . SetValue ( Node . GetID ( ) , Input . Name , MoveTemp ( LiteralNode ) ) ;
return true ;
} ) ;
}
2023-06-16 17:48:20 -04:00
}
void UMetaSoundSourceBuilder : : OnOutputAdded ( int32 OutputIndex ) const
{
using namespace Metasound : : DynamicGraph ;
ExecuteAuditionableTransaction ( [ this , OutputIndex ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound : : Frontend ;
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Doc = Builder . GetConstDocumentChecked ( ) ;
2023-06-16 17:48:20 -04:00
const FMetasoundFrontendGraphClass & GraphClass = Doc . RootGraph ;
const FMetasoundFrontendClassOutput & NewOutput = GraphClass . Interface . Outputs [ OutputIndex ] ;
Transactor . AddOutputDataSource ( NewOutput . NodeID , NewOutput . Name ) ;
return true ;
} ) ;
}
2024-06-18 16:47:21 -04:00
void UMetaSoundSourceBuilder : : OnPageAdded ( const Metasound : : Frontend : : FDocumentMutatePageArgs & Args )
{
using namespace Metasound : : Frontend ;
FDocumentModifyDelegates & DocDelegates = Builder . GetDocumentDelegates ( ) ;
2024-06-27 23:26:57 -04:00
InitTargetPageDelegates ( DocDelegates ) ;
2024-06-18 16:47:21 -04:00
}
void UMetaSoundSourceBuilder : : OnRemovingPage ( const Metasound : : Frontend : : FDocumentMutatePageArgs & Args )
{
using namespace Metasound : : Frontend ;
FDocumentModifyDelegates & DocDelegates = Builder . GetDocumentDelegates ( ) ;
2024-06-27 23:26:57 -04:00
InitTargetPageDelegates ( DocDelegates ) ;
2024-06-18 16:47:21 -04:00
}
2023-08-07 13:38:36 -04:00
void UMetaSoundSourceBuilder : : OnRemoveSwappingEdge ( int32 SwapIndex , int32 LastIndex ) const
2023-06-16 17:48:20 -04:00
{
using namespace Metasound : : DynamicGraph ;
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendEdge & EdgeBeingRemoved = GetConstTargetPageGraphChecked ( ) . Edges [ SwapIndex ] ;
2023-06-16 17:48:20 -04:00
ExecuteAuditionableTransaction ( [ this , EdgeBeingRemoved ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound ;
using namespace Metasound : : Engine ;
const FMetaSoundFrontendDocumentBuilder & Builder = GetConstBuilder ( ) ;
const FMetasoundFrontendVertex * FromNodeOutput = Builder . FindNodeOutput ( EdgeBeingRemoved . FromNodeID , EdgeBeingRemoved . FromVertexID ) ;
const FMetasoundFrontendVertex * ToNodeInput = Builder . FindNodeInput ( EdgeBeingRemoved . ToNodeID , EdgeBeingRemoved . ToVertexID ) ;
if ( FromNodeOutput & & ToNodeInput )
{
2024-08-13 14:58:36 -04:00
TOptional < FMetasoundFrontendLiteral > InputDefault = BuilderSubsystemPrivate : : TryResolveNodeInputDefault ( Builder , EdgeBeingRemoved . ToNodeID , ToNodeInput - > Name ) ;
2023-06-16 17:48:20 -04:00
2024-08-13 14:58:36 -04:00
if ( ensureAlwaysMsgf ( InputDefault . IsSet ( ) , TEXT ( " Could not dynamically assign default literal upon removing edge: literal should be assigned by either the frontend document's input or the class definition " ) ) )
2023-06-16 17:48:20 -04:00
{
TUniquePtr < INode > LiteralNode = BuilderSubsystemPrivate : : CreateDynamicNodeFromFrontendLiteral ( ToNodeInput - > TypeName , * InputDefault ) ;
Transactor . RemoveDataEdge ( EdgeBeingRemoved . FromNodeID , FromNodeOutput - > Name , EdgeBeingRemoved . ToNodeID , ToNodeInput - > Name , MoveTemp ( LiteralNode ) ) ;
return true ;
}
}
return false ;
} ) ;
}
2024-05-08 14:53:53 -04:00
void UMetaSoundSourceBuilder : : OnRemovingAssetReference ( TScriptInterface < IMetaSoundDocumentInterface > DocInterface )
{
2024-05-10 12:40:21 -04:00
using namespace Metasound : : Frontend ;
2024-05-08 14:53:53 -04:00
check ( DocInterface . GetObject ( ) ) ;
2024-05-10 12:40:21 -04:00
UMetaSoundSource & Source = GetMetaSoundSource ( ) ;
Source . ReferencedAssetClassObjects . Remove ( DocInterface . GetObject ( ) ) ;
2024-05-20 17:08:47 -04:00
const FNodeRegistryKey RegistryKey ( DocInterface - > GetConstDocument ( ) . RootGraph ) ;
2024-05-10 12:40:21 -04:00
Source . ReferencedAssetClassKeys . Remove ( RegistryKey . ToString ( ) ) ;
2024-05-08 14:53:53 -04:00
}
2023-12-01 12:57:59 -05:00
void UMetaSoundSourceBuilder : : OnRemovingInput ( int32 InputIndex )
2023-06-16 17:48:20 -04:00
{
using namespace Metasound : : DynamicGraph ;
ExecuteAuditionableTransaction ( [ this , InputIndex ] ( FDynamicOperatorTransactor & Transactor )
{
2023-12-01 12:57:59 -05:00
using namespace Metasound ;
2023-06-16 17:48:20 -04:00
using namespace Metasound : : Frontend ;
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Doc = Builder . GetConstDocumentChecked ( ) ;
2023-06-16 17:48:20 -04:00
const FMetasoundFrontendGraphClass & GraphClass = Doc . RootGraph ;
const FMetasoundFrontendClassInput & InputBeingRemoved = GraphClass . Interface . Inputs [ InputIndex ] ;
2023-12-01 12:57:59 -05:00
UMetaSoundSource & Source = GetMetaSoundSource ( ) ;
Source . RuntimeInputData . InputMap . Remove ( InputBeingRemoved . Name ) ;
2023-06-16 17:48:20 -04:00
Transactor . RemoveInputDataDestination ( InputBeingRemoved . Name ) ;
2023-12-01 12:57:59 -05:00
for ( uint64 AudioComponentID : LiveComponentIDs )
{
if ( UAudioComponent * AudioComponent = UAudioComponent : : GetAudioComponentFromID ( AudioComponentID ) )
{
if ( FAudioDevice * AudioDevice = AudioComponent - > GetAudioDevice ( ) )
{
AudioDevice - > SendCommandToActiveSounds ( AudioComponentID , [ InputRemoved = InputBeingRemoved . Name ] ( FActiveSound & ActiveSound )
{
static_cast < FMetaSoundParameterTransmitter * > ( ActiveSound . GetTransmitter ( ) ) - > RemoveAvailableParameter ( InputRemoved ) ;
} ) ;
}
}
}
2023-06-16 17:48:20 -04:00
return true ;
} ) ;
}
2023-08-07 13:38:36 -04:00
void UMetaSoundSourceBuilder : : OnRemoveSwappingNode ( int32 SwapIndex , int32 LastIndex ) const
2023-06-16 17:48:20 -04:00
{
using namespace Metasound : : DynamicGraph ;
2023-08-07 13:38:36 -04:00
// Last index will just be re-added, so this aspect of the swap is ignored by transactor
// (i.e. no sense removing and re-adding the node that is swapped from the end as this
// would potentially disconnect that node in the runtime graph model).
ExecuteAuditionableTransaction ( [ this , SwapIndex ] ( FDynamicOperatorTransactor & Transactor )
2023-06-16 17:48:20 -04:00
{
using namespace Metasound : : Frontend ;
2024-08-23 21:59:54 -04:00
const FMetasoundFrontendNode & NodeBeingRemoved = GetConstTargetPageGraphChecked ( ) . Nodes [ SwapIndex ] ;
2023-06-16 17:48:20 -04:00
const FGuid & NodeID = NodeBeingRemoved . GetID ( ) ;
Transactor . RemoveNode ( NodeID ) ;
return true ;
} ) ;
}
void UMetaSoundSourceBuilder : : OnRemovingNodeInputLiteral ( int32 NodeIndex , int32 VertexIndex , int32 LiteralIndex ) const
{
using namespace Metasound : : DynamicGraph ;
2024-08-23 21:59:54 -04:00
const TArray < FMetasoundFrontendNode > & Nodes = GetConstTargetPageGraphChecked ( ) . Nodes ;
const FMetasoundFrontendNode & Node = Nodes [ NodeIndex ] ;
2023-08-07 13:38:36 -04:00
const FMetasoundFrontendVertex & Input = Node . Interface . Inputs [ VertexIndex ] ;
// Only send the literal down if not connected, as the graph core layer will disconnect.
if ( ! Builder . IsNodeInputConnected ( Node . GetID ( ) , Input . VertexID ) )
2023-06-16 17:48:20 -04:00
{
2024-08-23 21:59:54 -04:00
ExecuteAuditionableTransaction ( [ this , & Node , & Input , & NodeIndex , & VertexIndex , & LiteralIndex ] ( FDynamicOperatorTransactor & Transactor )
2023-06-16 17:48:20 -04:00
{
2023-08-07 13:38:36 -04:00
using namespace Metasound ;
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
2023-06-16 17:48:20 -04:00
2024-08-13 14:58:36 -04:00
TOptional < FMetasoundFrontendLiteral > InputDefault = BuilderSubsystemPrivate : : TryResolveNodeInputDefault ( Builder , Node . GetID ( ) , Input . Name ) ;
if ( ensureAlwaysMsgf ( InputDefault . IsSet ( ) , TEXT ( " Could not dynamically assign default literal from class definition upon removing input '%s' literal: document's dependency entry invalid and has no default assigned " ) , * Input . Name . ToString ( ) ) )
2023-08-07 13:38:36 -04:00
{
TUniquePtr < INode > LiteralNode = BuilderSubsystemPrivate : : CreateDynamicNodeFromFrontendLiteral ( Input . TypeName , * InputDefault ) ;
Transactor . SetValue ( Node . GetID ( ) , Input . Name , MoveTemp ( LiteralNode ) ) ;
return true ;
}
return false ;
} ) ;
}
2023-06-16 17:48:20 -04:00
}
void UMetaSoundSourceBuilder : : OnRemovingOutput ( int32 OutputIndex ) const
{
using namespace Metasound : : DynamicGraph ;
ExecuteAuditionableTransaction ( [ this , OutputIndex ] ( FDynamicOperatorTransactor & Transactor )
{
using namespace Metasound : : Frontend ;
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Doc = Builder . GetConstDocumentChecked ( ) ;
2023-06-16 17:48:20 -04:00
const FMetasoundFrontendGraphClass & GraphClass = Doc . RootGraph ;
const FMetasoundFrontendClassOutput & OutputBeingRemoved = GraphClass . Interface . Outputs [ OutputIndex ] ;
Transactor . RemoveOutputDataSource ( OutputBeingRemoved . Name ) ;
return true ;
} ) ;
}
2023-11-08 16:53:27 -05:00
void UMetaSoundSourceBuilder : : SetBlockRateOverride ( float BlockRate )
{
2024-03-20 12:42:32 -04:00
# if WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
GetMetaSoundSource ( ) . BlockRateOverride . Default = BlockRate ;
2024-03-20 12:42:32 -04:00
# endif //WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
}
2023-03-07 17:01:52 -05:00
void UMetaSoundSourceBuilder : : SetFormat ( EMetaSoundOutputAudioFormat OutputFormat , EMetaSoundBuilderResult & OutResult )
{
using namespace Metasound : : Engine ;
using namespace Metasound : : Frontend ;
// Convert to non-preset MetaSoundSource since interface data is being altered
Builder . ConvertFromPreset ( ) ;
const FOutputAudioFormatInfoMap & FormatMap = GetOutputAudioFormatInfo ( ) ;
// Determine which interfaces to add and remove from the document due to the
// output format being changed.
TArray < FMetasoundFrontendVersion > OutputFormatsToAdd ;
if ( const FOutputAudioFormatInfo * FormatInfo = FormatMap . Find ( OutputFormat ) )
{
OutputFormatsToAdd . Add ( FormatInfo - > InterfaceVersion ) ;
}
TArray < FMetasoundFrontendVersion > OutputFormatsToRemove ;
2024-05-29 15:33:29 -04:00
const FMetasoundFrontendDocument & Document = GetConstBuilder ( ) . GetConstDocumentChecked ( ) ;
2023-03-07 17:01:52 -05:00
for ( const FOutputAudioFormatInfoPair & Pair : FormatMap )
{
const FMetasoundFrontendVersion & FormatVersion = Pair . Value . InterfaceVersion ;
if ( Document . Interfaces . Contains ( FormatVersion ) )
{
if ( ! OutputFormatsToAdd . Contains ( FormatVersion ) )
{
OutputFormatsToRemove . Add ( FormatVersion ) ;
}
}
}
2023-05-10 20:28:39 -04:00
FModifyInterfaceOptions Options ( OutputFormatsToRemove , OutputFormatsToAdd ) ;
# if WITH_EDITORONLY_DATA
Options . bSetDefaultNodeLocations = true ;
# endif // WITH_EDITORONLY_DATA
const bool bSuccess = Builder . ModifyInterfaces ( MoveTemp ( Options ) ) ;
2023-03-07 17:01:52 -05:00
OutResult = bSuccess ? EMetaSoundBuilderResult : : Succeeded : EMetaSoundBuilderResult : : Failed ;
}
2023-11-08 16:53:27 -05:00
# if WITH_EDITORONLY_DATA
void UMetaSoundSourceBuilder : : SetPlatformBlockRateOverride ( const FPerPlatformFloat & PlatformBlockRate )
{
GetMetaSoundSource ( ) . BlockRateOverride = PlatformBlockRate ;
}
void UMetaSoundSourceBuilder : : SetPlatformSampleRateOverride ( const FPerPlatformInt & PlatformSampleRate )
{
GetMetaSoundSource ( ) . SampleRateOverride = PlatformSampleRate ;
}
# endif // WITH_EDITORONLY_DATA
void UMetaSoundSourceBuilder : : SetQuality ( FName Quality )
{
2024-03-20 12:42:32 -04:00
# if WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
GetMetaSoundSource ( ) . QualitySetting = Quality ;
2024-03-20 12:42:32 -04:00
# endif //WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
}
void UMetaSoundSourceBuilder : : SetSampleRateOverride ( int32 SampleRate )
{
2024-03-20 12:42:32 -04:00
# if WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
GetMetaSoundSource ( ) . SampleRateOverride . Default = SampleRate ;
2024-03-20 12:42:32 -04:00
# endif //WITH_EDITORONLY_DATA
2023-11-08 16:53:27 -05:00
}
2023-03-07 17:01:52 -05:00
UMetaSoundPatchBuilder * UMetaSoundBuilderSubsystem : : CreatePatchBuilder ( FName BuilderName , EMetaSoundBuilderResult & OutResult )
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2023-06-22 14:51:42 -04:00
OutResult = EMetaSoundBuilderResult : : Succeeded ;
2024-05-08 14:53:53 -04:00
UMetaSoundPatchBuilder & NewBuilder = FDocumentBuilderRegistry : : GetChecked ( ) . CreateTransientBuilder < UMetaSoundPatchBuilder > ( BuilderName ) ;
return & NewBuilder ;
2023-03-07 17:01:52 -05:00
}
UMetaSoundSourceBuilder * UMetaSoundBuilderSubsystem : : CreateSourceBuilder (
FName BuilderName ,
FMetaSoundBuilderNodeOutputHandle & OnPlayNodeOutput ,
FMetaSoundBuilderNodeInputHandle & OnFinishedNodeInput ,
TArray < FMetaSoundBuilderNodeInputHandle > & AudioOutNodeInputs ,
EMetaSoundBuilderResult & OutResult ,
EMetaSoundOutputAudioFormat OutputFormat ,
bool bIsOneShot )
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2023-03-07 17:01:52 -05:00
using namespace Metasound : : Engine : : BuilderSubsystemPrivate ;
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Frontend ;
2023-03-07 17:01:52 -05:00
OnPlayNodeOutput = { } ;
OnFinishedNodeInput = { } ;
AudioOutNodeInputs . Reset ( ) ;
2024-05-08 14:53:53 -04:00
UMetaSoundSourceBuilder & NewBuilder = FDocumentBuilderRegistry : : GetChecked ( ) . CreateTransientBuilder < UMetaSoundSourceBuilder > ( BuilderName ) ;
2023-04-06 16:51:46 -04:00
OutResult = EMetaSoundBuilderResult : : Succeeded ;
if ( OutputFormat ! = EMetaSoundOutputAudioFormat : : Mono )
2023-04-05 17:01:55 -04:00
{
2023-04-06 16:51:46 -04:00
NewBuilder . SetFormat ( OutputFormat , OutResult ) ;
2023-03-07 17:01:52 -05:00
}
2023-04-05 17:01:55 -04:00
2023-04-06 16:51:46 -04:00
if ( OutResult = = EMetaSoundBuilderResult : : Succeeded )
2023-03-07 17:01:52 -05:00
{
TArray < FMetaSoundNodeHandle > AudioOutputNodes ;
2023-04-06 16:51:46 -04:00
if ( const Metasound : : Engine : : FOutputAudioFormatInfoPair * FormatInfo = NewBuilder . FindOutputAudioFormatInfo ( ) )
2023-03-07 17:01:52 -05:00
{
2023-03-09 17:56:53 -05:00
AudioOutputNodes = NewBuilder . FindInterfaceOutputNodes ( FormatInfo - > Value . InterfaceVersion . Name , OutResult ) ;
2023-03-07 17:01:52 -05:00
}
2023-04-06 16:51:46 -04:00
else
{
OutResult = EMetaSoundBuilderResult : : Failed ;
}
2023-03-07 17:01:52 -05:00
2023-04-06 16:51:46 -04:00
if ( OutResult = = EMetaSoundBuilderResult : : Succeeded )
2023-03-07 17:01:52 -05:00
{
Algo : : Transform ( AudioOutputNodes , AudioOutNodeInputs , [ & NewBuilder , & BuilderName ] ( const FMetaSoundNodeHandle & AudioOutputNode ) - > FMetaSoundBuilderNodeInputHandle
{
EMetaSoundBuilderResult Result ;
2023-03-09 17:56:53 -05:00
TArray < FMetaSoundBuilderNodeInputHandle > Inputs = NewBuilder . FindNodeInputs ( AudioOutputNode , Result ) ;
2023-03-07 17:01:52 -05:00
if ( ! Inputs . IsEmpty ( ) )
{
return Inputs . Last ( ) ;
}
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to find expected audio output node input vertex. Returned vertices set may be incomplete. " ) , * BuilderName . ToString ( ) ) ;
return { } ;
} ) ;
}
else
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to find expected audio output format and/or associated output nodes. " ) , * BuilderName . ToString ( ) ) ;
return nullptr ;
}
}
else
{
2023-04-06 16:51:46 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to set output format when initializing. " ) , * BuilderName . ToString ( ) ) ;
2023-03-07 17:01:52 -05:00
return nullptr ;
}
{
2023-03-09 17:56:53 -05:00
FMetaSoundNodeHandle OnPlayNode = NewBuilder . FindGraphInputNode ( SourceInterface : : Inputs : : OnPlay , OutResult ) ;
2023-03-07 17:01:52 -05:00
if ( OutResult = = EMetaSoundBuilderResult : : Failed )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to add required interface '%s' when attempting to create MetaSound Source Builder " ) , * BuilderName . ToString ( ) , * SourceInterface : : GetVersion ( ) . ToString ( ) ) ;
return nullptr ;
}
2023-03-09 17:56:53 -05:00
TArray < FMetaSoundBuilderNodeOutputHandle > Outputs = NewBuilder . FindNodeOutputs ( OnPlayNode , OutResult ) ;
2023-03-07 17:01:52 -05:00
if ( OutResult = = EMetaSoundBuilderResult : : Failed )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to find output vertex for 'OnPlay' input node when attempting to create MetaSound Source Builder " ) , * BuilderName . ToString ( ) ) ;
return nullptr ;
}
check ( ! Outputs . IsEmpty ( ) ) ;
OnPlayNodeOutput = Outputs . Last ( ) ;
}
2023-04-06 16:51:46 -04:00
if ( bIsOneShot )
2023-03-07 17:01:52 -05:00
{
2023-04-06 16:51:46 -04:00
FMetaSoundNodeHandle OnFinishedNode = NewBuilder . FindGraphOutputNode ( SourceOneShotInterface : : Outputs : : OnFinished , OutResult ) ;
if ( OutResult = = EMetaSoundBuilderResult : : Failed )
2023-03-07 17:01:52 -05:00
{
2023-04-06 16:51:46 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to add '%s' interface; interface definition may not be registered. " ) , * BuilderName . ToString ( ) , * SourceOneShotInterface : : GetVersion ( ) . ToString ( ) ) ;
2023-03-07 17:01:52 -05:00
}
2023-04-06 16:51:46 -04:00
TArray < FMetaSoundBuilderNodeInputHandle > Inputs = NewBuilder . FindNodeInputs ( OnFinishedNode , OutResult ) ;
if ( OutResult = = EMetaSoundBuilderResult : : Failed )
2023-03-07 17:01:52 -05:00
{
2023-04-06 16:51:46 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Builder '%s' Creation Error: Failed to find input vertex for 'OnFinished' output node when attempting to create MetaSound Source Builder " ) , * BuilderName . ToString ( ) ) ;
return nullptr ;
2023-03-07 17:01:52 -05:00
}
2023-04-06 16:51:46 -04:00
check ( ! Inputs . IsEmpty ( ) ) ;
OnFinishedNodeInput = Inputs . Last ( ) ;
}
else
{
NewBuilder . RemoveInterface ( SourceOneShotInterface : : GetVersion ( ) . Name , OutResult ) ;
2023-03-07 17:01:52 -05:00
}
2023-03-09 17:56:53 -05:00
return & NewBuilder ;
2023-03-07 17:01:52 -05:00
}
2023-05-30 14:39:48 -04:00
UMetaSoundPatchBuilder * UMetaSoundBuilderSubsystem : : CreatePatchPresetBuilder ( FName BuilderName , const TScriptInterface < IMetaSoundDocumentInterface > & ReferencedNodeClass , EMetaSoundBuilderResult & OutResult )
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2023-08-02 14:35:48 -04:00
if ( ReferencedNodeClass )
{
2024-05-08 14:53:53 -04:00
UMetaSoundPatchBuilder & Builder = FDocumentBuilderRegistry : : GetChecked ( ) . CreateTransientBuilder < UMetaSoundPatchBuilder > ( BuilderName ) ;
2023-08-02 14:35:48 -04:00
Builder . ConvertToPreset ( ReferencedNodeClass , OutResult ) ;
return & Builder ;
}
OutResult = EMetaSoundBuilderResult : : Failed ;
return nullptr ;
2023-05-30 14:39:48 -04:00
}
2023-06-15 13:50:27 -04:00
UMetaSoundBuilderBase & UMetaSoundBuilderSubsystem : : CreatePresetBuilder ( FName BuilderName , const TScriptInterface < IMetaSoundDocumentInterface > & ReferencedPatchClass , EMetaSoundBuilderResult & OutResult )
{
const UClass & Class = ReferencedPatchClass - > GetBaseMetaSoundUClass ( ) ;
if ( & Class = = UMetaSoundSource : : StaticClass ( ) )
{
return * CreateSourcePresetBuilder ( BuilderName , ReferencedPatchClass , OutResult ) ;
}
else if ( & Class = = UMetaSoundPatch : : StaticClass ( ) )
{
return * CreatePatchPresetBuilder ( BuilderName , ReferencedPatchClass , OutResult ) ;
}
else
{
checkf ( false , TEXT ( " UClass '%s' cannot be built to a MetaSound preset " ) , * Class . GetFullName ( ) ) ;
2023-09-13 20:11:49 -04:00
return * NewObject < UMetaSoundPatchBuilder > ( ) ;
2023-06-15 13:50:27 -04:00
}
}
2023-05-30 14:39:48 -04:00
UMetaSoundSourceBuilder * UMetaSoundBuilderSubsystem : : CreateSourcePresetBuilder ( FName BuilderName , const TScriptInterface < IMetaSoundDocumentInterface > & ReferencedNodeClass , EMetaSoundBuilderResult & OutResult )
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2023-08-02 14:35:48 -04:00
if ( ReferencedNodeClass )
{
2024-05-08 14:53:53 -04:00
UMetaSoundSourceBuilder & Builder = FDocumentBuilderRegistry : : GetChecked ( ) . CreateTransientBuilder < UMetaSoundSourceBuilder > ( ) ;
2023-08-02 14:35:48 -04:00
Builder . ConvertToPreset ( ReferencedNodeClass , OutResult ) ;
return & Builder ;
}
OutResult = EMetaSoundBuilderResult : : Failed ;
return nullptr ;
2023-05-30 14:39:48 -04:00
}
2023-09-18 14:32:59 -04:00
UMetaSoundBuilderSubsystem * UMetaSoundBuilderSubsystem : : Get ( )
{
if ( GEngine )
{
if ( UMetaSoundBuilderSubsystem * BuilderSubsystem = GEngine - > GetEngineSubsystem < UMetaSoundBuilderSubsystem > ( ) )
{
return BuilderSubsystem ;
}
}
return nullptr ;
}
2023-05-10 20:28:39 -04:00
UMetaSoundBuilderSubsystem & UMetaSoundBuilderSubsystem : : GetChecked ( )
{
checkf ( GEngine , TEXT ( " Cannot access UMetaSoundBuilderSubsystem without engine loaded " ) ) ;
UMetaSoundBuilderSubsystem * BuilderSubsystem = GEngine - > GetEngineSubsystem < UMetaSoundBuilderSubsystem > ( ) ;
checkf ( BuilderSubsystem , TEXT ( " Failed to find initialized 'UMetaSoundBuilderSubsystem " ) ) ;
return * BuilderSubsystem ;
}
2023-09-18 14:32:59 -04:00
const UMetaSoundBuilderSubsystem * UMetaSoundBuilderSubsystem : : GetConst ( )
{
if ( GEngine )
{
if ( const UMetaSoundBuilderSubsystem * BuilderSubsystem = GEngine - > GetEngineSubsystem < const UMetaSoundBuilderSubsystem > ( ) )
{
return BuilderSubsystem ;
}
}
return nullptr ;
}
2023-05-10 20:28:39 -04:00
const UMetaSoundBuilderSubsystem & UMetaSoundBuilderSubsystem : : GetConstChecked ( )
{
checkf ( GEngine , TEXT ( " Cannot access UMetaSoundBuilderSubsystem without engine loaded " ) ) ;
UMetaSoundBuilderSubsystem * BuilderSubsystem = GEngine - > GetEngineSubsystem < UMetaSoundBuilderSubsystem > ( ) ;
checkf ( BuilderSubsystem , TEXT ( " Failed to find initialized 'UMetaSoundBuilderSubsystem " ) ) ;
return * BuilderSubsystem ;
}
2023-03-07 17:01:52 -05:00
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateBoolMetaSoundLiteral ( bool Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateBoolArrayMetaSoundLiteral ( const TArray < bool > & Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateFloatMetaSoundLiteral ( float Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateFloatArrayMetaSoundLiteral ( const TArray < float > & Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateIntMetaSoundLiteral ( int32 Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateIntArrayMetaSoundLiteral ( const TArray < int32 > & Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateStringMetaSoundLiteral ( const FString & Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateStringArrayMetaSoundLiteral ( const TArray < FString > & Value , FName & OutDataType )
{
return Metasound : : Engine : : BuilderSubsystemPrivate : : CreatePODMetaSoundLiteral ( Value , OutDataType ) ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateObjectMetaSoundLiteral ( UObject * Value )
{
FMetasoundFrontendLiteral Literal ;
Literal . Set ( Value ) ;
return Literal ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateObjectArrayMetaSoundLiteral ( const TArray < UObject * > & Value )
{
FMetasoundFrontendLiteral Literal ;
Literal . Set ( Value ) ;
return Literal ;
}
FMetasoundFrontendLiteral UMetaSoundBuilderSubsystem : : CreateMetaSoundLiteralFromParam ( const FAudioParameter & Param )
{
return FMetasoundFrontendLiteral { Param } ;
}
2023-08-02 14:35:48 -04:00
bool UMetaSoundBuilderSubsystem : : DetachBuilderFromAsset ( const FMetasoundFrontendClassName & InClassName ) const
2023-06-16 17:48:20 -04:00
{
2023-10-31 17:16:11 -04:00
using namespace Metasound : : Frontend ;
2024-05-08 14:53:53 -04:00
return IDocumentBuilderRegistry : : GetChecked ( ) . FinishBuilding ( InClassName ) ;
2023-06-16 17:48:20 -04:00
}
2023-06-22 14:51:42 -04:00
UMetaSoundBuilderBase * UMetaSoundBuilderSubsystem : : FindBuilder ( FName BuilderName )
{
return NamedBuilders . FindRef ( BuilderName ) ;
}
2023-10-31 17:16:11 -04:00
UMetaSoundBuilderBase * UMetaSoundBuilderSubsystem : : FindBuilderOfDocument ( TScriptInterface < const IMetaSoundDocumentInterface > InMetaSound ) const
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2024-06-05 11:00:21 -04:00
return FDocumentBuilderRegistry : : GetChecked ( ) . FindBuilderObject ( InMetaSound ) ;
2023-10-31 17:16:11 -04:00
}
2023-03-07 17:01:52 -05:00
UMetaSoundPatchBuilder * UMetaSoundBuilderSubsystem : : FindPatchBuilder ( FName BuilderName )
{
2023-06-22 14:51:42 -04:00
if ( UMetaSoundBuilderBase * Builder = FindBuilder ( BuilderName ) )
{
return Cast < UMetaSoundPatchBuilder > ( Builder ) ;
}
return nullptr ;
2023-03-07 17:01:52 -05:00
}
UMetaSoundSourceBuilder * UMetaSoundBuilderSubsystem : : FindSourceBuilder ( FName BuilderName )
{
2023-06-22 14:51:42 -04:00
if ( UMetaSoundBuilderBase * Builder = FindBuilder ( BuilderName ) )
{
return Cast < UMetaSoundSourceBuilder > ( Builder ) ;
}
return nullptr ;
2023-06-16 17:48:20 -04:00
}
2024-05-08 14:53:53 -04:00
void UMetaSoundBuilderSubsystem : : InvalidateDocumentCache ( const FMetasoundFrontendClassName & InClassName ) const
2023-06-16 17:48:20 -04:00
{
2024-05-08 14:53:53 -04:00
using namespace Metasound : : Engine ;
2024-05-29 15:33:29 -04:00
FDocumentBuilderRegistry : : GetChecked ( ) . ReloadBuilder ( InClassName ) ;
2023-03-07 17:01:52 -05:00
}
bool UMetaSoundBuilderSubsystem : : IsInterfaceRegistered ( FName InInterfaceName ) const
{
using namespace Metasound : : Frontend ;
FMetasoundFrontendInterface Interface ;
return ISearchEngine : : Get ( ) . FindInterfaceWithHighestVersion ( InInterfaceName , Interface ) ;
}
2023-06-22 14:51:42 -04:00
void UMetaSoundBuilderSubsystem : : RegisterBuilder ( FName BuilderName , UMetaSoundBuilderBase * Builder )
{
if ( Builder )
{
NamedBuilders . FindOrAdd ( BuilderName ) = Builder ;
}
}
2023-03-07 17:01:52 -05:00
void UMetaSoundBuilderSubsystem : : RegisterPatchBuilder ( FName BuilderName , UMetaSoundPatchBuilder * Builder )
{
2023-06-22 14:51:42 -04:00
if ( Builder )
{
NamedBuilders . FindOrAdd ( BuilderName ) = Builder ;
}
2023-03-07 17:01:52 -05:00
}
void UMetaSoundBuilderSubsystem : : RegisterSourceBuilder ( FName BuilderName , UMetaSoundSourceBuilder * Builder )
{
2023-06-22 14:51:42 -04:00
if ( Builder )
{
NamedBuilders . FindOrAdd ( BuilderName ) = Builder ;
}
}
2024-06-27 23:26:57 -04:00
bool UMetaSoundBuilderSubsystem : : SetTargetPage ( FName PageName )
{
2024-08-23 21:59:54 -04:00
using namespace Metasound : : Frontend ;
2024-06-27 23:26:57 -04:00
if ( UMetaSoundSettings * Settings = GetMutableDefault < UMetaSoundSettings > ( ) )
{
2024-08-23 21:59:54 -04:00
const bool bTargetChanged = Settings - > SetTargetPage ( PageName ) ;
if ( bTargetChanged )
{
IMetaSoundAssetManager : : GetChecked ( ) . ReloadMetaSoundAssets ( ) ;
}
return bTargetChanged ;
2024-06-27 23:26:57 -04:00
}
return false ;
}
2023-06-22 14:51:42 -04:00
bool UMetaSoundBuilderSubsystem : : UnregisterBuilder ( FName BuilderName )
{
return NamedBuilders . Remove ( BuilderName ) > 0 ;
2023-03-07 17:01:52 -05:00
}
bool UMetaSoundBuilderSubsystem : : UnregisterPatchBuilder ( FName BuilderName )
{
2023-06-22 14:51:42 -04:00
return NamedBuilders . Remove ( BuilderName ) > 0 ;
2023-03-07 17:01:52 -05:00
}
bool UMetaSoundBuilderSubsystem : : UnregisterSourceBuilder ( FName BuilderName )
{
2023-06-22 14:51:42 -04:00
return NamedBuilders . Remove ( BuilderName ) > 0 ;
2023-03-07 17:01:52 -05:00
}