2020-07-17 16:43:42 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundAssetBase.h"
2020-12-14 15:48:27 -04:00
# include "Algo/AnyOf.h"
2022-08-18 13:55:13 -04:00
# include "Algo/Copy.h"
2022-03-01 16:31:55 -05:00
# include "Algo/ForEach.h"
2021-06-16 11:21:13 -04:00
# include "Algo/Transform.h"
2021-09-16 14:46:43 -04:00
# include "Containers/Set.h"
2020-07-21 14:34:07 -04:00
# include "HAL/FileManager.h"
2022-11-03 14:18:47 -04:00
# include "HAL/IConsoleManager.h"
2021-11-22 15:55:50 -05:00
# include "IAudioParameterTransmitter.h"
2022-08-19 12:14:31 -04:00
# include "Interfaces/MetasoundFrontendInterface.h"
2023-03-13 17:23:05 -04:00
# include "Interfaces/MetasoundFrontendInterfaceRegistry.h"
2021-06-08 10:52:31 -04:00
# include "Internationalization/Text.h"
2020-07-17 16:43:42 -04:00
# include "IStructSerializerBackend.h"
2021-07-27 15:36:03 -04:00
# include "Logging/LogMacros.h"
2021-11-07 23:43:01 -05:00
# include "MetasoundAssetManager.h"
2023-09-05 17:54:02 -04:00
# include "MetasoundDocumentInterface.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundFrontendController.h"
2021-07-12 16:13:03 -04:00
# include "MetasoundFrontendDocument.h"
2023-03-07 17:01:52 -05:00
# include "MetasoundFrontendDocumentBuilder.h"
2023-06-20 13:12:39 -04:00
# include "MetasoundFrontendDocumentIdGenerator.h"
2022-08-19 12:14:31 -04:00
# include "MetasoundFrontendDocumentVersioning.h"
2021-06-08 10:52:31 -04:00
# include "MetasoundFrontendGraph.h"
2022-08-10 14:18:10 -04:00
# include "MetasoundFrontendNodeTemplateRegistry.h"
2023-09-13 14:21:35 -04:00
# include "MetasoundFrontendProxyDataCache.h"
2021-08-18 15:16:57 -04:00
# include "MetasoundFrontendRegistries.h"
2023-12-15 13:21:12 -05:00
# include "MetasoundFrontendRegistryContainerImpl.h"
2021-06-08 10:52:31 -04:00
# include "MetasoundFrontendSearchEngine.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundFrontendTransform.h"
2023-10-10 11:32:28 -04:00
# include "MetasoundGraph.h"
2020-12-14 15:48:27 -04:00
# include "MetasoundJsonBackend.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundLog.h"
2023-03-07 17:01:52 -05:00
# include "MetasoundParameterPack.h"
2021-08-30 14:08:45 -04:00
# include "MetasoundParameterTransmitter.h"
2021-08-11 15:22:01 -04:00
# include "MetasoundTrace.h"
2021-09-13 14:14:37 -04:00
# include "MetasoundVertex.h"
2020-07-17 16:43:42 -04:00
# include "StructSerializer.h"
2022-08-10 14:18:10 -04:00
# include "Templates/SharedPointer.h"
2021-06-16 11:21:13 -04:00
# include "UObject/MetaData.h"
2020-07-17 16:43:42 -04:00
2021-06-08 10:52:31 -04:00
# define LOCTEXT_NAMESPACE "MetaSound"
2021-06-16 11:21:13 -04:00
namespace Metasound
{
2022-05-10 16:51:39 -04:00
namespace Frontend
2021-07-27 15:36:03 -04:00
{
2022-05-10 16:51:39 -04:00
namespace AssetBasePrivate
2021-07-27 15:36:03 -04:00
{
2023-10-10 13:37:20 -04:00
// Zero values means, that these don't do anything.
static float BlockRateOverride = 0 ;
static int32 SampleRateOverride = 0 ;
2023-09-19 18:30:29 -04:00
2022-05-10 16:51:39 -04:00
void DepthFirstTraversal ( const FMetasoundAssetBase & InInitAsset , TFunctionRef < TSet < const FMetasoundAssetBase * > ( const FMetasoundAssetBase & ) > InVisitFunction )
2021-07-27 15:36:03 -04:00
{
2022-05-10 16:51:39 -04:00
// Non recursive depth first traversal.
TArray < const FMetasoundAssetBase * > Stack ( { & InInitAsset } ) ;
TSet < const FMetasoundAssetBase * > Visited ;
2021-07-27 15:36:03 -04:00
2022-05-10 16:51:39 -04:00
while ( ! Stack . IsEmpty ( ) )
{
const FMetasoundAssetBase * CurrentNode = Stack . Pop ( ) ;
if ( ! Visited . Contains ( CurrentNode ) )
{
TArray < const FMetasoundAssetBase * > Children = InVisitFunction ( * CurrentNode ) . Array ( ) ;
Stack . Append ( Children ) ;
Visited . Add ( CurrentNode ) ;
}
2021-07-27 15:36:03 -04:00
}
}
2022-10-10 15:44:28 -04:00
2022-10-13 17:38:11 -04:00
// Registers node by copying document. Updates to document require re-registration.
2023-09-22 15:01:07 -04:00
// This registry entry does not support node creation as it is only intended to be
// used when cooking MetaSounds.
class FDocumentNodeRegistryEntryForCook : public INodeRegistryEntry
2022-10-13 17:38:11 -04:00
{
public :
2023-12-15 13:21:12 -05:00
FDocumentNodeRegistryEntryForCook ( const FMetasoundFrontendDocument & InDocument , const FTopLevelAssetPath & InAssetPath )
2023-09-22 15:01:07 -04:00
: Interfaces ( InDocument . Interfaces )
, FrontendClass ( InDocument . RootGraph )
, ClassInfo ( InDocument . RootGraph , InAssetPath )
2022-10-13 17:38:11 -04:00
{
// Copy FrontendClass to preserve original document.
FrontendClass . Metadata . SetType ( EMetasoundFrontendClassType : : External ) ;
2023-09-13 20:11:49 -04:00
}
2022-10-13 17:38:11 -04:00
2023-09-22 15:01:07 -04:00
FDocumentNodeRegistryEntryForCook ( const FDocumentNodeRegistryEntryForCook & InOther ) = default ;
2022-10-13 17:38:11 -04:00
2023-09-22 15:01:07 -04:00
virtual ~ FDocumentNodeRegistryEntryForCook ( ) = default ;
2022-10-13 17:38:11 -04:00
virtual const FNodeClassInfo & GetClassInfo ( ) const override
{
return ClassInfo ;
}
2023-09-22 15:01:07 -04:00
virtual TUniquePtr < INode > CreateNode ( const FNodeInitData & ) const override { return nullptr ; }
2022-10-13 17:38:11 -04:00
virtual TUniquePtr < INode > CreateNode ( FDefaultLiteralNodeConstructorParams & & ) const override { return nullptr ; }
virtual TUniquePtr < INode > CreateNode ( FDefaultNamedVertexNodeConstructorParams & & ) const override { return nullptr ; }
virtual TUniquePtr < INode > CreateNode ( FDefaultNamedVertexWithLiteralNodeConstructorParams & & ) const override { return nullptr ; }
virtual const FMetasoundFrontendClass & GetFrontendClass ( ) const override
{
return FrontendClass ;
}
virtual TUniquePtr < INodeRegistryEntry > Clone ( ) const override
{
2023-09-22 15:01:07 -04:00
return MakeUnique < FDocumentNodeRegistryEntryForCook > ( * this ) ;
2022-10-13 17:38:11 -04:00
}
2023-09-13 20:11:49 -04:00
virtual const TSet < FMetasoundFrontendVersion > * GetImplementedInterfaces ( ) const override
2023-06-22 14:51:42 -04:00
{
2023-09-22 15:01:07 -04:00
return & Interfaces ;
2023-06-22 14:51:42 -04:00
}
2022-10-13 17:38:11 -04:00
virtual bool IsNative ( ) const override
{
return false ;
}
private :
2023-09-22 15:01:07 -04:00
TSet < FMetasoundFrontendVersion > Interfaces ;
2022-10-13 17:38:11 -04:00
FMetasoundFrontendClass FrontendClass ;
FNodeClassInfo ClassInfo ;
} ;
2022-05-10 16:51:39 -04:00
} // namespace AssetBasePrivate
2023-10-03 12:17:13 -04:00
namespace ConsoleVariables
{
2023-10-10 11:32:28 -04:00
static bool bDisableAsyncGraphRegistration = false ;
2023-10-03 12:17:13 -04:00
}
FAutoConsoleVariableRef CVarMetaSoundDisableAsyncGraphRegistration (
2024-02-05 12:33:10 -05:00
TEXT ( " au.MetaSound.DisableAsyncGraphRegistration " ) ,
2023-10-03 12:17:13 -04:00
Metasound : : Frontend : : ConsoleVariables : : bDisableAsyncGraphRegistration ,
TEXT ( " Disables async registration of MetaSound graphs \n " )
2023-10-10 11:32:28 -04:00
TEXT ( " Default: false " ) ,
2023-10-03 12:17:13 -04:00
ECVF_Default ) ;
2023-10-10 13:37:20 -04:00
FConsoleVariableMulticastDelegate CVarMetaSoundBlockRateChanged ;
2023-10-03 12:17:13 -04:00
2022-05-10 16:51:39 -04:00
FAutoConsoleVariableRef CVarMetaSoundBlockRate (
TEXT ( " au.MetaSound.BlockRate " ) ,
2023-10-10 13:37:20 -04:00
AssetBasePrivate : : BlockRateOverride ,
2022-05-10 16:51:39 -04:00
TEXT ( " Sets block rate (blocks per second) of MetaSounds. \n " )
TEXT ( " Default: 100.0f, Min: 1.0f, Max: 1000.0f " ) ,
2023-10-10 13:37:20 -04:00
FConsoleVariableDelegate : : CreateLambda ( [ ] ( IConsoleVariable * Var ) { CVarMetaSoundBlockRateChanged . Broadcast ( Var ) ; } ) ,
2022-05-10 16:51:39 -04:00
ECVF_Default ) ;
2023-10-10 13:37:20 -04:00
FConsoleVariableMulticastDelegate CVarMetaSoundSampleRateChanged ;
2023-09-19 18:30:29 -04:00
FAutoConsoleVariableRef CVarMetaSoundSampleRate (
TEXT ( " au.MetaSound.SampleRate " ) ,
2023-10-10 13:37:20 -04:00
AssetBasePrivate : : SampleRateOverride ,
2023-09-19 18:30:29 -04:00
TEXT ( " Overrides the sample rate of metasounds. Negative values default to audio mixer sample rate. \n " )
2023-10-10 13:37:20 -04:00
TEXT ( " Default: 0, Min: 8000, Max: 48000 " ) ,
FConsoleVariableDelegate : : CreateLambda ( [ ] ( IConsoleVariable * Var ) { CVarMetaSoundSampleRateChanged . Broadcast ( Var ) ; } ) ,
2023-09-19 18:30:29 -04:00
ECVF_Default ) ;
2023-10-10 13:37:20 -04:00
float GetBlockRateOverride ( )
2022-05-10 16:51:39 -04:00
{
2023-10-10 13:37:20 -04:00
if ( AssetBasePrivate : : BlockRateOverride > 0 )
{
return FMath : : Clamp ( AssetBasePrivate : : BlockRateOverride ,
GetBlockRateClampRange ( ) . GetLowerBoundValue ( ) ,
GetBlockRateClampRange ( ) . GetUpperBoundValue ( )
) ;
}
return AssetBasePrivate : : BlockRateOverride ;
2023-10-06 19:42:56 -04:00
}
2023-10-10 13:37:20 -04:00
FConsoleVariableMulticastDelegate & GetBlockRateOverrideChangedDelegate ( )
2023-10-06 19:42:56 -04:00
{
2023-10-10 13:37:20 -04:00
return CVarMetaSoundBlockRateChanged ;
}
int32 GetSampleRateOverride ( )
{
if ( AssetBasePrivate : : SampleRateOverride > 0 )
2023-10-06 18:51:06 -04:00
{
2023-10-10 13:37:20 -04:00
return FMath : : Clamp ( AssetBasePrivate : : SampleRateOverride ,
GetSampleRateClampRange ( ) . GetLowerBoundValue ( ) ,
GetSampleRateClampRange ( ) . GetUpperBoundValue ( )
) ;
2023-10-06 18:51:06 -04:00
}
2023-10-10 13:37:20 -04:00
return AssetBasePrivate : : SampleRateOverride ;
}
FConsoleVariableMulticastDelegate & GetSampleRateOverrideChangedDelegate ( )
{
return CVarMetaSoundSampleRateChanged ;
}
TRange < float > GetBlockRateClampRange ( )
{
2024-03-04 15:11:39 -05:00
return TRange < float > ( 1.f , 1000.f ) ;
2023-10-10 13:37:20 -04:00
}
TRange < int32 > GetSampleRateClampRange ( )
{
return TRange < int32 > ( 8000 , 96000 ) ;
2023-09-19 18:30:29 -04:00
}
2022-05-10 16:51:39 -04:00
} // namespace Frontend
2021-06-16 11:21:13 -04:00
} // namespace Metasound
2020-07-23 16:39:56 -04:00
const FString FMetasoundAssetBase : : FileExtension ( TEXT ( " .metasound " ) ) ;
2021-11-07 23:43:01 -05:00
void FMetasoundAssetBase : : RegisterGraphWithFrontend ( Metasound : : Frontend : : FMetaSoundAssetRegistrationOptions InRegistrationOptions )
2020-07-23 16:39:56 -04:00
{
2021-06-08 10:52:31 -04:00
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2020-07-23 16:39:56 -04:00
2023-10-03 12:17:13 -04:00
// Graph registration must only happen on one thread to avoid race conditions on graph registration.
checkf ( IsInGameThread ( ) , TEXT ( " MetaSound %s graph can only be registered on the GameThread " ) , * GetOwningAssetName ( ) ) ;
2023-12-19 15:55:04 -05:00
checkf ( ! IsRunningCookCommandlet ( ) , TEXT ( " Cook of asset must call RegisterNode directly providing FDocumentNodeRegistryEntryForCook to avoid proxy/runtime graph generation. " ) ) ;
2023-10-03 12:17:13 -04:00
2021-08-11 15:22:01 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : RegisterGraphWithFrontend ) ;
2023-10-17 20:13:54 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE_TEXT ( * FString : : Printf ( TEXT ( " MetaSoundAssetBase::RegisterGraphWithFrontend asset %s " ) , * this - > GetOwningAssetName ( ) ) ) ;
2021-08-18 15:16:57 -04:00
if ( ! InRegistrationOptions . bForceReregister )
2021-06-08 10:52:31 -04:00
{
2021-08-18 15:16:57 -04:00
if ( IsRegistered ( ) )
{
return ;
}
}
2021-11-07 23:43:01 -05:00
2022-10-13 17:38:11 -04:00
# if WITH_EDITOR
if ( InRegistrationOptions . bRebuildReferencedAssetClasses )
2021-08-18 15:16:57 -04:00
{
2022-10-13 17:38:11 -04:00
RebuildReferencedAssetClasses ( ) ;
2021-08-18 15:16:57 -04:00
}
2022-10-13 17:38:11 -04:00
# endif
2021-08-18 15:16:57 -04:00
if ( InRegistrationOptions . bRegisterDependencies )
{
2022-10-13 17:38:11 -04:00
RegisterAssetDependencies ( InRegistrationOptions ) ;
2021-08-18 15:16:57 -04:00
}
2022-10-13 17:38:11 -04:00
IMetaSoundAssetManager : : GetChecked ( ) . AddOrUpdateAsset ( * GetOwningAsset ( ) ) ;
2021-08-18 15:16:57 -04:00
// Auto update must be done after all referenced asset classes are registered
if ( InRegistrationOptions . bAutoUpdate )
{
2022-10-13 17:38:11 -04:00
const bool bDidUpdate = AutoUpdate ( InRegistrationOptions . bAutoUpdateLogWarningOnDroppedConnection ) ;
2022-02-10 18:36:26 -05:00
# if WITH_EDITOR
2022-10-13 17:38:11 -04:00
if ( bDidUpdate | | InRegistrationOptions . bForceViewSynchronization )
2022-02-02 02:19:16 -05:00
{
2022-09-22 15:02:24 -04:00
GetModifyContext ( ) . SetForceRefreshViews ( ) ;
2022-02-02 02:19:16 -05:00
}
2022-02-10 18:36:26 -05:00
# endif // WITH_EDITOR
2022-02-02 02:19:16 -05:00
}
else
{
2022-02-10 18:36:26 -05:00
# if WITH_EDITOR
2022-02-02 02:19:16 -05:00
if ( InRegistrationOptions . bForceViewSynchronization )
2022-01-18 18:06:06 -05:00
{
2022-09-22 15:02:24 -04:00
GetModifyContext ( ) . SetForceRefreshViews ( ) ;
2021-11-18 14:37:34 -05:00
}
2022-02-10 18:36:26 -05:00
# endif // WITH_EDITOR
2021-06-08 10:52:31 -04:00
}
2022-02-10 18:36:26 -05:00
# if WITH_EDITOR
2022-01-20 19:19:55 -05:00
// Must be completed after auto-update to ensure all non-transient referenced dependency data is up-to-date (ex.
// class version), which is required for most accurately caching current registry metadata.
2022-01-26 18:11:52 -05:00
CacheRegistryMetadata ( ) ;
2022-02-10 18:36:26 -05:00
# endif // WITH_EDITOR
2022-01-20 19:19:55 -05:00
2023-09-13 20:11:49 -04:00
UObject * Owner = GetOwningAsset ( ) ;
check ( Owner ) ;
const FString AssetName = Owner - > GetName ( ) ;
2023-09-05 17:54:02 -04:00
2024-02-06 11:37:36 -05:00
// Register graphs async by default;
const bool bAsync = ! ConsoleVariables : : bDisableAsyncGraphRegistration ;
// Force a copy if async registration is enabled and we need to protect against
// race conditions from external modifications.
bool bForceCopy = ( IsBuilderActive ( ) & & bAsync ) ;
# if WITH_EDITOR
bForceCopy | = InRegistrationOptions . bRegisterCopyIfAsync ;
# endif // WITH_EDITOR
GraphRegistryKey = FRegistryContainerImpl : : Get ( ) . RegisterGraph ( Owner , bAsync , bForceCopy ) ;
2021-06-16 11:21:13 -04:00
2023-12-15 13:21:12 -05:00
if ( GraphRegistryKey . IsValid ( ) )
2021-06-16 11:21:13 -04:00
{
# if WITH_EDITORONLY_DATA
2022-10-13 17:38:11 -04:00
UpdateAssetRegistry ( ) ;
2021-06-16 11:21:13 -04:00
# endif // WITH_EDITORONLY_DATA
}
else
2021-06-08 10:52:31 -04:00
{
2023-09-13 20:11:49 -04:00
UClass * Class = Owner - > GetClass ( ) ;
2023-09-05 17:54:02 -04:00
check ( Class ) ;
const FString ClassName = Class - > GetName ( ) ;
2021-08-18 15:16:57 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Registration failed for MetaSound node class '%s' of UObject class '%s' " ) , * AssetName , * ClassName ) ;
2021-06-08 10:52:31 -04:00
}
2020-07-23 16:39:56 -04:00
}
2023-09-05 17:54:02 -04:00
void FMetasoundAssetBase : : CookMetaSound ( )
2023-08-21 12:25:01 -04:00
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2023-09-05 17:54:02 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : CookMetaSound ) ;
2023-08-21 12:25:01 -04:00
if ( IsRegistered ( ) )
{
return ;
}
2023-09-05 17:54:02 -04:00
CookReferencedMetaSounds ( ) ;
2023-08-21 12:25:01 -04:00
IMetaSoundAssetManager : : GetChecked ( ) . AddOrUpdateAsset ( * GetOwningAsset ( ) ) ;
// Auto update must be done after all referenced asset classes are registered
const bool bDidUpdate = AutoUpdate ( /*bAutoUpdateLogWarningOnDroppedConnection=*/ true ) ;
# if WITH_EDITOR
if ( bDidUpdate )
{
GetModifyContext ( ) . SetForceRefreshViews ( ) ;
}
# endif // WITH_EDITOR
# if WITH_EDITOR
// Must be completed after auto-update to ensure all non-transient referenced dependency data is up-to-date (ex.
// class version), which is required for most accurately caching current registry metadata.
CacheRegistryMetadata ( ) ;
# endif // WITH_EDITOR
2023-09-13 20:11:49 -04:00
UObject * Owner = GetOwningAsset ( ) ;
check ( Owner ) ;
2023-09-05 17:54:02 -04:00
2023-09-13 20:11:49 -04:00
{
2023-09-15 00:40:42 -04:00
// Performs document transforms on local copy, which reduces document footprint & renders transforming unnecessary unless altered at runtime when registering
2023-09-13 20:11:49 -04:00
FMetaSoundFrontendDocumentBuilder DocBuilder ( Owner ) ;
const bool bContainsTemplateDependency = DocBuilder . ContainsDependencyOfType ( EMetasoundFrontendClassType : : Template ) ;
if ( bContainsTemplateDependency )
{
DocBuilder . TransformTemplateNodes ( ) ;
}
2023-08-21 12:25:01 -04:00
2023-12-19 15:55:04 -05:00
if ( GraphRegistryKey . IsValid ( ) )
{
FRegistryContainerImpl : : Get ( ) . UnregisterNode ( GraphRegistryKey . NodeKey ) ;
GraphRegistryKey = { } ;
}
2023-09-22 15:01:07 -04:00
// During cook, we need to register the node so that it is available for other graphs, but we need to avoid
// creating proxies. To do so, we use a special node registration object which reflects the necessary information
// for the node registry, but does not create INodes.
2023-12-15 13:21:12 -05:00
TScriptInterface < IMetaSoundDocumentInterface > DocInterface ( Owner ) ;
const FMetasoundFrontendDocument & Document = DocInterface - > GetConstDocument ( ) ;
const FTopLevelAssetPath AssetPath = DocInterface - > GetAssetPathChecked ( ) ;
TUniquePtr < INodeRegistryEntry > RegistryEntry = MakeUnique < AssetBasePrivate : : FDocumentNodeRegistryEntryForCook > ( Document , AssetPath ) ;
2023-12-19 15:55:04 -05:00
const FNodeRegistryKey NodeKey = FRegistryContainerImpl : : Get ( ) . RegisterNode ( MoveTemp ( RegistryEntry ) ) ;
2023-12-15 13:21:12 -05:00
GraphRegistryKey = FGraphRegistryKey { NodeKey , AssetPath } ;
2023-09-13 20:11:49 -04:00
}
2023-08-21 12:25:01 -04:00
2023-12-15 13:21:12 -05:00
if ( GraphRegistryKey . IsValid ( ) )
2023-08-21 12:25:01 -04:00
{
# if WITH_EDITORONLY_DATA
UpdateAssetRegistry ( ) ;
# endif // WITH_EDITORONLY_DATA
}
else
{
2023-09-13 20:11:49 -04:00
const UClass * Class = Owner - > GetClass ( ) ;
2023-09-05 17:54:02 -04:00
check ( Class ) ;
const FString ClassName = Class - > GetName ( ) ;
2023-09-22 15:01:07 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Registration failed during cook for MetaSound node class '%s' of UObject class '%s' " ) , * GetOwningAssetName ( ) , * ClassName ) ;
2023-08-21 12:25:01 -04:00
}
}
2023-12-19 15:55:04 -05:00
void FMetasoundAssetBase : : OnNotifyBeginDestroy ( )
{
using namespace Metasound : : Frontend ;
// Unregistration of graph is not necessary when cooking as deserialized objects are not mutable and, should they be reloaded,
// omitting unregistration avoids potentially kicking off an invalid asynchronous task to unregister a non-existent runtime graph.
if ( IsRunningCookCommandlet ( ) )
{
if ( GraphRegistryKey . IsValid ( ) )
{
FRegistryContainerImpl : : Get ( ) . UnregisterNode ( GraphRegistryKey . NodeKey ) ;
GraphRegistryKey = { } ;
}
}
else
{
UnregisterGraphWithFrontend ( ) ;
}
}
2021-07-27 15:36:03 -04:00
void FMetasoundAssetBase : : UnregisterGraphWithFrontend ( )
{
using namespace Metasound : : Frontend ;
2021-08-11 15:22:01 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : UnregisterGraphWithFrontend ) ;
2021-07-27 15:36:03 -04:00
2023-10-09 11:42:49 -04:00
check ( IsInGameThread ( ) ) ;
2023-12-19 15:55:04 -05:00
checkf ( ! IsRunningCookCommandlet ( ) , TEXT ( " Cook of asset must call UnregisterNode directly providing FDocumentNodeRegistryEntryForCook to avoid proxy/runtime graph generation. " ) ) ;
2023-12-15 13:21:12 -05:00
if ( GraphRegistryKey . IsValid ( ) )
2021-07-27 15:36:03 -04:00
{
2023-12-15 13:21:12 -05:00
UObject * OwningAsset = GetOwningAsset ( ) ;
if ( ensureAlways ( OwningAsset ) )
{
2023-12-19 15:55:04 -05:00
// Async registration is only available if:
// 1. The IMetaSoundDocumentInterface is not actively modified by a builder
// (built graph must be released synchronously to avoid a race condition on
// reading/writing the IMetaSoundDocumentInterface on the Game Thread)
// 2. Async registration is globally disabled via console variable.
2023-12-15 13:21:12 -05:00
const bool bAsync = ! ( IsBuilderActive ( ) | | ConsoleVariables : : bDisableAsyncGraphRegistration ) ;
const bool bSuccess = FRegistryContainerImpl : : Get ( ) . UnregisterGraph ( GraphRegistryKey , OwningAsset , bAsync ) ;
if ( ! bSuccess )
{
UE_LOG ( LogMetaSound , Verbose , TEXT ( " Failed to unregister node with key %s for asset %s. No registry entry exists with that key. " ) , * GraphRegistryKey . ToString ( ) , * GetOwningAssetName ( ) ) ;
}
}
2023-12-11 20:36:24 -05:00
2023-12-15 13:21:12 -05:00
GraphRegistryKey = { } ;
2023-12-11 20:36:24 -05:00
}
2021-07-27 15:36:03 -04:00
}
2021-01-13 10:48:59 -04:00
void FMetasoundAssetBase : : SetMetadata ( FMetasoundFrontendClassMetadata & InMetadata )
2020-07-17 16:43:42 -04:00
{
2021-01-13 10:48:59 -04:00
FMetasoundFrontendDocument & Doc = GetDocumentChecked ( ) ;
Doc . RootGraph . Metadata = InMetadata ;
2021-07-27 15:36:03 -04:00
if ( Doc . RootGraph . Metadata . GetType ( ) ! = EMetasoundFrontendClassType : : Graph )
2021-01-13 10:48:59 -04:00
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Forcing class type to EMetasoundFrontendClassType::Graph on root graph metadata " ) ) ;
2021-07-27 15:36:03 -04:00
Doc . RootGraph . Metadata . SetType ( EMetasoundFrontendClassType : : Graph ) ;
2021-01-13 10:48:59 -04:00
}
2020-07-17 16:43:42 -04:00
}
2021-11-22 15:55:50 -05:00
bool FMetasoundAssetBase : : GetDeclaredInterfaces ( TArray < const Metasound : : Frontend : : IInterfaceRegistryEntry * > & OutInterfaces ) const
2021-07-28 17:12:57 -04:00
{
2023-03-07 17:01:52 -05:00
return FMetaSoundFrontendDocumentBuilder : : FindDeclaredInterfaces ( GetDocumentChecked ( ) , OutInterfaces ) ;
2021-11-22 15:55:50 -05:00
}
2021-12-10 20:37:31 -05:00
bool FMetasoundAssetBase : : IsInterfaceDeclared ( const FMetasoundFrontendVersion & InVersion ) const
2021-11-22 15:55:50 -05:00
{
2021-12-10 20:37:31 -05:00
return GetDocumentChecked ( ) . Interfaces . Contains ( InVersion ) ;
2021-07-28 17:12:57 -04:00
}
2023-09-13 20:11:49 -04:00
Metasound : : Frontend : : FNodeClassInfo FMetasoundAssetBase : : GetAssetClassInfo ( ) const
{
using namespace Metasound : : Frontend ;
const UObject * Owner = GetOwningAsset ( ) ;
check ( Owner ) ;
2023-12-15 13:21:12 -05:00
TScriptInterface < const IMetaSoundDocumentInterface > DocInterface ( ( UObject * ) Owner ) ;
return FNodeClassInfo { GetDocumentChecked ( ) . RootGraph , DocInterface - > GetAssetPathChecked ( ) } ;
2023-09-13 20:11:49 -04:00
}
2023-08-21 12:25:01 -04:00
void FMetasoundAssetBase : : SetDocument ( const FMetasoundFrontendDocument & InDocument , bool bMarkDirty )
2020-12-14 15:48:27 -04:00
{
2021-01-13 10:48:59 -04:00
FMetasoundFrontendDocument & Document = GetDocumentChecked ( ) ;
2020-07-23 20:32:26 -04:00
Document = InDocument ;
2023-08-21 12:25:01 -04:00
if ( bMarkDirty )
{
MarkMetasoundDocumentDirty ( ) ;
}
2020-07-23 20:32:26 -04:00
}
2021-11-22 15:55:50 -05:00
void FMetasoundAssetBase : : AddDefaultInterfaces ( )
2020-07-23 20:32:26 -04:00
{
2021-11-22 15:55:50 -05:00
using namespace Metasound : : Frontend ;
2021-02-01 15:59:27 -04:00
2021-11-22 15:55:50 -05:00
UObject * OwningAsset = GetOwningAsset ( ) ;
check ( OwningAsset ) ;
2021-06-23 20:08:21 -04:00
2021-11-22 15:55:50 -05:00
UClass * AssetClass = OwningAsset - > GetClass ( ) ;
check ( AssetClass ) ;
2023-04-04 19:14:26 -04:00
const FTopLevelAssetPath & ClassPath = AssetClass - > GetClassPathName ( ) ;
2021-11-22 15:55:50 -05:00
2023-04-04 19:14:26 -04:00
TArray < FMetasoundFrontendVersion > InitVersions = ISearchEngine : : Get ( ) . FindUClassDefaultInterfaceVersions ( ClassPath ) ;
FModifyRootGraphInterfaces ( { } , InitVersions ) . Transform ( GetDocumentChecked ( ) ) ;
2021-06-23 20:08:21 -04:00
}
2023-08-21 12:25:01 -04:00
void FMetasoundAssetBase : : SetDocument ( FMetasoundFrontendDocument & & InDocument , bool bMarkDirty )
2023-03-07 17:01:52 -05:00
{
FMetasoundFrontendDocument & Document = GetDocumentChecked ( ) ;
Document = MoveTemp ( InDocument ) ;
2023-08-21 12:25:01 -04:00
if ( bMarkDirty )
{
MarkMetasoundDocumentDirty ( ) ;
}
2023-03-07 17:01:52 -05:00
}
2021-08-18 15:16:57 -04:00
bool FMetasoundAssetBase : : VersionAsset ( )
2021-06-23 20:08:21 -04:00
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2023-08-21 12:25:01 -04:00
2021-08-11 15:22:01 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : VersionAsset ) ;
2023-08-21 12:25:01 -04:00
constexpr bool bIsDeterministic = true ;
2023-06-20 13:12:39 -04:00
FDocumentIDGenerator : : FScopeDeterminism DeterminismScope ( bIsDeterministic ) ;
2021-06-23 20:08:21 -04:00
FName AssetName ;
FString AssetPath ;
if ( const UObject * OwningAsset = GetOwningAsset ( ) )
{
AssetName = FName ( OwningAsset - > GetName ( ) ) ;
AssetPath = OwningAsset - > GetPathName ( ) ;
}
2023-03-07 17:01:52 -05:00
FMetasoundFrontendDocument * Doc = GetDocumentAccessPtr ( ) . Get ( ) ;
2021-11-22 15:55:50 -05:00
if ( ! ensure ( Doc ) )
2021-06-23 20:08:21 -04:00
{
2021-11-22 15:55:50 -05:00
return false ;
}
2021-12-10 20:37:31 -05:00
bool bDidEdit = Doc - > VersionInterfaces ( ) ;
2021-11-22 15:55:50 -05:00
// Version Document Model
2021-12-10 20:37:31 -05:00
FDocumentHandle DocHandle = GetDocumentHandle ( ) ;
2021-11-22 15:55:50 -05:00
{
bDidEdit | = FVersionDocument ( AssetName , AssetPath ) . Transform ( DocHandle ) ;
}
2021-12-16 19:59:03 -05:00
// Version Interfaces. Has to be re-run until no pass reports an update in case
// versions fork (ex. an interface splits into two newly named interfaces).
2021-11-22 15:55:50 -05:00
{
bool bInterfaceUpdated = false ;
2021-12-16 19:59:03 -05:00
bool bPassUpdated = true ;
while ( bPassUpdated )
2021-08-18 15:16:57 -04:00
{
2021-12-16 19:59:03 -05:00
bPassUpdated = false ;
const TArray < FMetasoundFrontendVersion > Versions = Doc - > Interfaces . Array ( ) ;
for ( const FMetasoundFrontendVersion & Version : Versions )
{
2023-04-28 16:43:19 -04:00
bPassUpdated | = FUpdateRootGraphInterface ( Version , GetOwningAssetName ( ) ) . Transform ( DocHandle ) ;
2021-12-16 19:59:03 -05:00
}
bInterfaceUpdated | = bPassUpdated ;
2021-08-18 15:16:57 -04:00
}
2021-12-16 19:59:03 -05:00
2021-11-22 15:55:50 -05:00
if ( bInterfaceUpdated )
{
ConformObjectDataToInterfaces ( ) ;
}
bDidEdit | = bInterfaceUpdated ;
2021-06-23 20:08:21 -04:00
}
2021-07-27 15:36:03 -04:00
return bDidEdit ;
2021-02-01 15:59:27 -04:00
}
2022-02-10 18:36:26 -05:00
# if WITH_EDITOR
2022-01-26 18:11:52 -05:00
void FMetasoundAssetBase : : CacheRegistryMetadata ( )
{
using namespace Metasound : : Frontend ;
2023-03-07 17:01:52 -05:00
FMetasoundFrontendDocument * Document = GetDocumentAccessPtr ( ) . Get ( ) ;
2022-01-26 18:11:52 -05:00
if ( ! ensure ( Document ) )
{
return ;
}
using FNameDataTypePair = TPair < FName , FName > ;
const TSet < FMetasoundFrontendVersion > & InterfaceVersions = Document - > Interfaces ;
FMetasoundFrontendClassInterface & RootGraphClassInterface = Document - > RootGraph . Interface ;
// 1. Gather inputs/outputs managed by interfaces
TMap < FNameDataTypePair , FMetasoundFrontendClassInput * > Inputs ;
for ( FMetasoundFrontendClassInput & Input : RootGraphClassInterface . Inputs )
{
FNameDataTypePair NameDataTypePair = FNameDataTypePair ( Input . Name , Input . TypeName ) ;
Inputs . Add ( MoveTemp ( NameDataTypePair ) , & Input ) ;
}
TMap < FNameDataTypePair , FMetasoundFrontendClassOutput * > Outputs ;
for ( FMetasoundFrontendClassOutput & Output : RootGraphClassInterface . Outputs )
{
FNameDataTypePair NameDataTypePair = FNameDataTypePair ( Output . Name , Output . TypeName ) ;
Outputs . Add ( MoveTemp ( NameDataTypePair ) , & Output ) ;
}
// 2. Copy metadata for inputs/outputs managed by interfaces, removing them from maps generated
2022-03-01 16:31:55 -05:00
auto CacheInterfaceMetadata = [ ] ( const FMetasoundFrontendVertexMetadata & InRegistryMetadata , FMetasoundFrontendVertexMetadata & OutMetadata )
{
const int32 CachedSortOrderIndex = OutMetadata . SortOrderIndex ;
OutMetadata = InRegistryMetadata ;
OutMetadata . SortOrderIndex = CachedSortOrderIndex ;
} ;
2022-01-26 18:11:52 -05:00
for ( const FMetasoundFrontendVersion & Version : InterfaceVersions )
{
const FInterfaceRegistryKey InterfaceKey = GetInterfaceRegistryKey ( Version ) ;
const IInterfaceRegistryEntry * Entry = IInterfaceRegistry : : Get ( ) . FindInterfaceRegistryEntry ( InterfaceKey ) ;
if ( ensure ( Entry ) )
{
for ( const FMetasoundFrontendClassInput & InterfaceInput : Entry - > GetInterface ( ) . Inputs )
{
const FNameDataTypePair NameDataTypePair = FNameDataTypePair ( InterfaceInput . Name , InterfaceInput . TypeName ) ;
if ( FMetasoundFrontendClassInput * Input = Inputs . FindRef ( NameDataTypePair ) )
{
2022-03-01 16:31:55 -05:00
CacheInterfaceMetadata ( InterfaceInput . Metadata , Input - > Metadata ) ;
2022-01-26 18:11:52 -05:00
Inputs . Remove ( NameDataTypePair ) ;
}
}
for ( const FMetasoundFrontendClassOutput & InterfaceOutput : Entry - > GetInterface ( ) . Outputs )
{
const FNameDataTypePair NameDataTypePair = FNameDataTypePair ( InterfaceOutput . Name , InterfaceOutput . TypeName ) ;
if ( FMetasoundFrontendClassOutput * Output = Outputs . FindRef ( NameDataTypePair ) )
{
2022-03-01 16:31:55 -05:00
CacheInterfaceMetadata ( InterfaceOutput . Metadata , Output - > Metadata ) ;
2022-01-26 18:11:52 -05:00
Outputs . Remove ( NameDataTypePair ) ;
}
}
}
}
// 3. Iterate remaining inputs/outputs not managed by interfaces and set to serialize text
// (in case they were orphaned by an interface no longer being implemented).
for ( TPair < FNameDataTypePair , FMetasoundFrontendClassInput * > & Pair : Inputs )
{
Pair . Value - > Metadata . SetSerializeText ( true ) ;
}
for ( TPair < FNameDataTypePair , FMetasoundFrontendClassOutput * > & Pair : Outputs )
{
Pair . Value - > Metadata . SetSerializeText ( true ) ;
}
2022-03-01 16:31:55 -05:00
// 4. Refresh style as order of members could've changed
{
FMetasoundFrontendInterfaceStyle InputStyle ;
Algo : : ForEach ( RootGraphClassInterface . Inputs , [ & InputStyle ] ( const FMetasoundFrontendClassInput & Input )
{
InputStyle . DefaultSortOrder . Add ( Input . Metadata . SortOrderIndex ) ;
} ) ;
RootGraphClassInterface . SetInputStyle ( InputStyle ) ;
}
{
FMetasoundFrontendInterfaceStyle OutputStyle ;
Algo : : ForEach ( RootGraphClassInterface . Outputs , [ & OutputStyle ] ( const FMetasoundFrontendClassOutput & Output )
{
OutputStyle . DefaultSortOrder . Add ( Output . Metadata . SortOrderIndex ) ;
} ) ;
RootGraphClassInterface . SetOutputStyle ( OutputStyle ) ;
}
// 5. Cache registry data on document dependencies
2022-01-27 01:31:46 -05:00
for ( FMetasoundFrontendClass & Dependency : Document - > Dependencies )
2022-01-26 18:11:52 -05:00
{
2022-01-27 01:31:46 -05:00
if ( ! FMetasoundFrontendClass : : CacheGraphDependencyMetadataFromRegistry ( Dependency ) )
2022-01-26 18:11:52 -05:00
{
UE_LOG ( LogMetaSound , Warning ,
TEXT ( " '%s' failed to cache dependency registry data: Registry missing class with key '%s' " ) ,
* GetOwningAssetName ( ) ,
2022-01-27 01:31:46 -05:00
* Dependency . Metadata . GetClassName ( ) . ToString ( ) ) ;
2022-01-26 18:11:52 -05:00
UE_LOG ( LogMetaSound , Warning ,
TEXT ( " Asset '%s' may fail to build runtime graph unless re-registered after dependency with given key is loaded. " ) ,
* GetOwningAssetName ( ) ) ;
}
}
}
2022-09-22 15:02:24 -04:00
FMetasoundFrontendDocumentModifyContext & FMetasoundAssetBase : : GetModifyContext ( )
2021-11-18 14:37:34 -05:00
{
2022-09-22 15:02:24 -04:00
return GetDocumentChecked ( ) . Metadata . ModifyContext ;
2021-11-18 14:37:34 -05:00
}
2022-09-22 15:02:24 -04:00
const FMetasoundFrontendDocumentModifyContext & FMetasoundAssetBase : : GetModifyContext ( ) const
2021-11-22 15:55:50 -05:00
{
2022-09-22 15:02:24 -04:00
return GetDocumentChecked ( ) . Metadata . ModifyContext ;
2021-11-18 14:37:34 -05:00
}
2022-02-10 18:36:26 -05:00
# endif // WITH_EDITOR
2021-11-18 14:37:34 -05:00
2021-06-08 10:52:31 -04:00
2021-08-18 15:16:57 -04:00
bool FMetasoundAssetBase : : IsRegistered ( ) const
2021-07-27 15:36:03 -04:00
{
2021-08-18 15:16:57 -04:00
using namespace Metasound : : Frontend ;
2023-12-15 13:21:12 -05:00
return GraphRegistryKey . IsValid ( ) ;
2021-07-27 15:36:03 -04:00
}
2021-11-18 14:37:34 -05:00
bool FMetasoundAssetBase : : IsReferencedAsset ( const FMetasoundAssetBase & InAsset ) const
{
using namespace Metasound : : Frontend ;
bool bIsReferenced = false ;
2022-05-10 16:51:39 -04:00
AssetBasePrivate : : DepthFirstTraversal ( * this , [ & ] ( const FMetasoundAssetBase & ChildAsset )
2021-11-18 14:37:34 -05:00
{
TSet < const FMetasoundAssetBase * > Children ;
if ( & ChildAsset = = & InAsset )
{
bIsReferenced = true ;
return Children ;
}
TArray < FMetasoundAssetBase * > ChildRefs ;
ensureAlways ( IMetaSoundAssetManager : : GetChecked ( ) . TryLoadReferencedAssets ( ChildAsset , ChildRefs ) ) ;
Algo : : Transform ( ChildRefs , Children , [ ] ( FMetasoundAssetBase * Child ) { return Child ; } ) ;
return Children ;
} ) ;
return bIsReferenced ;
}
2021-08-18 15:16:57 -04:00
bool FMetasoundAssetBase : : AddingReferenceCausesLoop ( const FSoftObjectPath & InReferencePath ) const
2021-07-27 15:36:03 -04:00
{
2021-11-07 23:43:01 -05:00
using namespace Metasound : : Frontend ;
2021-08-18 15:16:57 -04:00
const FMetasoundAssetBase * ReferenceAsset = IMetaSoundAssetManager : : GetChecked ( ) . TryLoadAsset ( InReferencePath ) ;
2021-07-27 15:36:03 -04:00
if ( ! ensureAlways ( ReferenceAsset ) )
{
return false ;
}
bool bCausesLoop = false ;
const FMetasoundAssetBase * Parent = this ;
2022-05-10 16:51:39 -04:00
AssetBasePrivate : : DepthFirstTraversal ( * ReferenceAsset , [ & ] ( const FMetasoundAssetBase & ChildAsset )
2021-07-27 15:36:03 -04:00
{
TSet < const FMetasoundAssetBase * > Children ;
if ( Parent = = & ChildAsset )
{
bCausesLoop = true ;
return Children ;
}
2021-11-07 23:43:01 -05:00
TArray < FMetasoundAssetBase * > ChildRefs ;
2021-11-18 14:37:34 -05:00
ensureAlways ( IMetaSoundAssetManager : : GetChecked ( ) . TryLoadReferencedAssets ( ChildAsset , ChildRefs ) ) ;
Algo : : Transform ( ChildRefs , Children , [ ] ( FMetasoundAssetBase * Child ) { return Child ; } ) ;
2021-07-27 15:36:03 -04:00
return Children ;
} ) ;
return bCausesLoop ;
}
2021-06-16 11:21:13 -04:00
void FMetasoundAssetBase : : ConvertFromPreset ( )
{
using namespace Metasound : : Frontend ;
FGraphHandle GraphHandle = GetRootGraphHandle ( ) ;
2022-02-10 15:07:39 -05:00
# if WITH_EDITOR
2021-06-16 11:21:13 -04:00
FMetasoundFrontendGraphStyle Style = GraphHandle - > GetGraphStyle ( ) ;
Style . bIsGraphEditable = true ;
GraphHandle - > SetGraphStyle ( Style ) ;
2022-02-10 15:07:39 -05:00
# endif // WITH_EDITOR
2021-07-27 15:36:03 -04:00
2022-02-09 12:52:07 -05:00
FMetasoundFrontendGraphClassPresetOptions PresetOptions = GraphHandle - > GetGraphPresetOptions ( ) ;
PresetOptions . bIsPreset = false ;
GraphHandle - > SetGraphPresetOptions ( PresetOptions ) ;
2021-06-16 11:21:13 -04:00
}
2021-06-08 10:52:31 -04:00
TArray < FMetasoundAssetBase : : FSendInfoAndVertexName > FMetasoundAssetBase : : GetSendInfos ( uint64 InInstanceID ) const
{
2023-10-03 12:17:13 -04:00
return TArray < FSendInfoAndVertexName > ( ) ;
2021-06-08 10:52:31 -04:00
}
2022-02-10 18:36:26 -05:00
# if WITH_EDITOR
2021-06-08 10:52:31 -04:00
FText FMetasoundAssetBase : : GetDisplayName ( FString & & InTypeName ) const
{
using namespace Metasound : : Frontend ;
FConstGraphHandle GraphHandle = GetRootGraphHandle ( ) ;
const bool bIsPreset = ! GraphHandle - > GetGraphStyle ( ) . bIsGraphEditable ;
if ( ! bIsPreset )
{
return FText : : FromString ( MoveTemp ( InTypeName ) ) ;
}
return FText : : Format ( LOCTEXT ( " PresetDisplayNameFormat " , " {0} (Preset) " ) , FText : : FromString ( MoveTemp ( InTypeName ) ) ) ;
}
2022-02-10 18:36:26 -05:00
# endif // WITH_EDITOR
2021-06-08 10:52:31 -04:00
2021-02-01 15:59:27 -04:00
bool FMetasoundAssetBase : : MarkMetasoundDocumentDirty ( ) const
{
if ( const UObject * OwningAsset = GetOwningAsset ( ) )
{
return ensure ( OwningAsset - > MarkPackageDirty ( ) ) ;
}
return false ;
2020-07-23 20:32:26 -04:00
}
2021-01-13 10:48:59 -04:00
Metasound : : Frontend : : FDocumentHandle FMetasoundAssetBase : : GetDocumentHandle ( )
{
2023-03-07 17:01:52 -05:00
return Metasound : : Frontend : : IDocumentController : : CreateDocumentHandle ( GetDocumentAccessPtr ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2020-07-17 16:43:42 -04:00
2021-01-13 19:18:22 -04:00
Metasound : : Frontend : : FConstDocumentHandle FMetasoundAssetBase : : GetDocumentHandle ( ) const
{
2023-03-07 17:01:52 -05:00
return Metasound : : Frontend : : IDocumentController : : CreateDocumentHandle ( GetDocumentConstAccessPtr ( ) ) ;
2021-01-13 19:18:22 -04:00
}
2020-12-14 15:48:27 -04:00
Metasound : : Frontend : : FGraphHandle FMetasoundAssetBase : : GetRootGraphHandle ( )
2020-07-17 16:43:42 -04:00
{
2021-01-13 10:48:59 -04:00
return GetDocumentHandle ( ) - > GetRootGraph ( ) ;
2020-07-17 16:43:42 -04:00
}
2021-01-13 19:18:22 -04:00
Metasound : : Frontend : : FConstGraphHandle FMetasoundAssetBase : : GetRootGraphHandle ( ) const
{
return GetDocumentHandle ( ) - > GetRootGraph ( ) ;
}
2020-08-05 12:47:19 -04:00
bool FMetasoundAssetBase : : ImportFromJSON ( const FString & InJSON )
2020-07-23 16:39:56 -04:00
{
2021-08-11 15:22:01 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : ImportFromJSON ) ;
2023-03-07 17:01:52 -05:00
FMetasoundFrontendDocument * Document = GetDocumentAccessPtr ( ) . Get ( ) ;
2021-07-12 16:13:03 -04:00
if ( ensure ( nullptr ! = Document ) )
2020-12-14 15:48:27 -04:00
{
2021-02-01 15:59:27 -04:00
bool bSuccess = Metasound : : Frontend : : ImportJSONToMetasound ( InJSON , * Document ) ;
if ( bSuccess )
{
ensure ( MarkMetasoundDocumentDirty ( ) ) ;
}
return bSuccess ;
2020-12-14 15:48:27 -04:00
}
return false ;
2020-07-23 16:39:56 -04:00
}
2020-08-05 12:47:19 -04:00
bool FMetasoundAssetBase : : ImportFromJSONAsset ( const FString & InAbsolutePath )
2020-07-17 16:43:42 -04:00
{
2021-08-11 15:22:01 -04:00
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( MetaSoundAssetBase : : ImportFromJSONAsset ) ;
2023-03-07 17:01:52 -05:00
Metasound : : Frontend : : FDocumentAccessPtr DocumentPtr = GetDocumentAccessPtr ( ) ;
2021-07-12 16:13:03 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2020-12-14 15:48:27 -04:00
{
2021-02-01 15:59:27 -04:00
bool bSuccess = Metasound : : Frontend : : ImportJSONAssetToMetasound ( InAbsolutePath , * Document ) ;
if ( bSuccess )
{
ensure ( MarkMetasoundDocumentDirty ( ) ) ;
}
return bSuccess ;
2020-12-14 15:48:27 -04:00
}
return false ;
}
2021-01-13 10:48:59 -04:00
FMetasoundFrontendDocument & FMetasoundAssetBase : : GetDocumentChecked ( )
2020-12-14 15:48:27 -04:00
{
2023-03-07 17:01:52 -05:00
FMetasoundFrontendDocument * Document = GetDocumentAccessPtr ( ) . Get ( ) ;
2021-07-12 16:13:03 -04:00
check ( nullptr ! = Document ) ;
return * Document ;
2020-12-14 15:48:27 -04:00
}
2021-01-13 10:48:59 -04:00
const FMetasoundFrontendDocument & FMetasoundAssetBase : : GetDocumentChecked ( ) const
2020-12-14 15:48:27 -04:00
{
2023-03-07 17:01:52 -05:00
const FMetasoundFrontendDocument * Document = GetDocumentConstAccessPtr ( ) . Get ( ) ;
2020-12-14 15:48:27 -04:00
2021-07-12 16:13:03 -04:00
check ( nullptr ! = Document ) ;
return * Document ;
2020-08-05 12:47:19 -04:00
}
2021-07-28 17:12:57 -04:00
2023-12-15 13:21:12 -05:00
const Metasound : : Frontend : : FGraphRegistryKey & FMetasoundAssetBase : : GetGraphRegistryKey ( ) const
{
return GraphRegistryKey ;
}
2023-03-23 14:04:36 -04:00
const Metasound : : Frontend : : FNodeRegistryKey & FMetasoundAssetBase : : GetRegistryKey ( ) const
{
2023-12-15 13:21:12 -05:00
return GraphRegistryKey . NodeKey ;
2023-03-23 14:04:36 -04:00
}
2021-07-28 17:12:57 -04:00
FString FMetasoundAssetBase : : GetOwningAssetName ( ) const
{
if ( const UObject * OwningAsset = GetOwningAsset ( ) )
{
2022-01-27 00:45:28 -05:00
return OwningAsset - > GetPathName ( ) ;
2021-07-28 17:12:57 -04:00
}
return FString ( ) ;
}
2022-10-13 17:38:11 -04:00
# if WITH_EDITOR
void FMetasoundAssetBase : : RebuildReferencedAssetClasses ( )
2022-01-21 15:40:14 -05:00
{
using namespace Metasound : : Frontend ;
2022-10-13 17:38:11 -04:00
IMetaSoundAssetManager & AssetManager = IMetaSoundAssetManager : : GetChecked ( ) ;
AssetManager . AddAssetReferences ( * this ) ;
TSet < IMetaSoundAssetManager : : FAssetInfo > ReferencedAssetClasses = AssetManager . GetReferencedAssetClasses ( * this ) ;
SetReferencedAssetClasses ( MoveTemp ( ReferencedAssetClasses ) ) ;
}
# endif // WITH_EDITOR
void FMetasoundAssetBase : : RegisterAssetDependencies ( const Metasound : : Frontend : : FMetaSoundAssetRegistrationOptions & InRegistrationOptions )
{
using namespace Metasound : : Frontend ;
IMetaSoundAssetManager & AssetManager = IMetaSoundAssetManager : : GetChecked ( ) ;
TArray < FMetasoundAssetBase * > References = GetReferencedAssets ( ) ;
for ( FMetasoundAssetBase * Reference : References )
{
if ( InRegistrationOptions . bForceReregister | | ! Reference - > IsRegistered ( ) )
{
// TODO: Check for infinite recursion and error if so
AssetManager . AddOrUpdateAsset ( * ( Reference - > GetOwningAsset ( ) ) ) ;
Reference - > RegisterGraphWithFrontend ( InRegistrationOptions ) ;
}
}
}
2023-09-05 17:54:02 -04:00
void FMetasoundAssetBase : : CookReferencedMetaSounds ( )
2023-08-21 12:25:01 -04:00
{
using namespace Metasound : : Frontend ;
IMetaSoundAssetManager & AssetManager = IMetaSoundAssetManager : : GetChecked ( ) ;
TArray < FMetasoundAssetBase * > References = GetReferencedAssets ( ) ;
for ( FMetasoundAssetBase * Reference : References )
{
if ( ! Reference - > IsRegistered ( ) )
{
// TODO: Check for infinite recursion and error if so
AssetManager . AddOrUpdateAsset ( * ( Reference - > GetOwningAsset ( ) ) ) ;
2023-09-05 17:54:02 -04:00
Reference - > CookMetaSound ( ) ;
2023-08-21 12:25:01 -04:00
}
}
}
2022-10-13 17:38:11 -04:00
bool FMetasoundAssetBase : : AutoUpdate ( bool bInLogWarningsOnDroppedConnection )
{
using namespace Metasound : : Frontend ;
FString OwningAssetName = GetOwningAssetName ( ) ;
const bool bAutoUpdated = FAutoUpdateRootGraph ( MoveTemp ( OwningAssetName ) , bInLogWarningsOnDroppedConnection ) . Transform ( GetDocumentHandle ( ) ) ;
return bAutoUpdated ;
}
# if WITH_EDITORONLY_DATA
void FMetasoundAssetBase : : UpdateAssetRegistry ( )
{
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2023-12-15 13:21:12 -05:00
UObject * Owner = GetOwningAsset ( ) ;
2023-09-13 20:11:49 -04:00
check ( Owner ) ;
2023-12-15 13:21:12 -05:00
TScriptInterface < IMetaSoundDocumentInterface > DocInterface ( Owner ) ;
FNodeClassInfo AssetClassInfo ( GetDocumentChecked ( ) . RootGraph , DocInterface - > GetAssetPathChecked ( ) ) ;
2023-09-13 20:11:49 -04:00
2022-10-13 17:38:11 -04:00
// Refresh Asset Registry Info if successfully registered with Frontend
const FMetasoundFrontendGraphClass & DocumentClassGraph = GetDocumentHandle ( ) - > GetRootGraphClass ( ) ;
const FMetasoundFrontendClassMetadata & DocumentClassMetadata = DocumentClassGraph . Metadata ;
AssetClassInfo . AssetClassID = FGuid ( DocumentClassMetadata . GetClassName ( ) . Name . ToString ( ) ) ;
FNodeClassName ClassName = DocumentClassMetadata . GetClassName ( ) . ToNodeClassName ( ) ;
FMetasoundFrontendClass GraphClass ;
2023-09-12 13:54:05 -04:00
AssetClassInfo . bIsPreset = DocumentClassGraph . PresetOptions . bIsPreset ;
2022-10-13 17:38:11 -04:00
AssetClassInfo . Version = DocumentClassMetadata . GetVersion ( ) ;
AssetClassInfo . InputTypes . Reset ( ) ;
Algo : : Transform ( GraphClass . Interface . Inputs , AssetClassInfo . InputTypes , [ ] ( const FMetasoundFrontendClassInput & Input ) { return Input . TypeName ; } ) ;
AssetClassInfo . OutputTypes . Reset ( ) ;
Algo : : Transform ( GraphClass . Interface . Outputs , AssetClassInfo . OutputTypes , [ ] ( const FMetasoundFrontendClassOutput & Output ) { return Output . TypeName ; } ) ;
SetRegistryAssetClassInfo ( MoveTemp ( AssetClassInfo ) ) ;
}
# endif
TSharedPtr < FMetasoundFrontendDocument > FMetasoundAssetBase : : PreprocessDocument ( )
{
2023-09-05 17:54:02 -04:00
return nullptr ;
2022-01-21 15:40:14 -05:00
}
2023-10-03 12:17:13 -04:00
PRAGMA_DISABLE_DEPRECATION_WARNINGS
2022-03-10 22:07:08 -05:00
const FMetasoundAssetBase : : FRuntimeData & FMetasoundAssetBase : : GetRuntimeData ( ) const
{
2023-10-03 12:17:13 -04:00
static const FRuntimeData PlaceholderForDeprecatedMethod ;
return PlaceholderForDeprecatedMethod ;
2022-03-10 22:07:08 -05:00
}
2023-10-03 12:17:13 -04:00
PRAGMA_ENABLE_DEPRECATION_WARNINGS
2022-03-10 22:07:08 -05:00
2021-06-08 10:52:31 -04:00
# undef LOCTEXT_NAMESPACE // "MetaSound"