2024-05-08 14:53:53 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundDocumentBuilderRegistry.h"
2024-06-27 23:26:57 -04:00
# include "HAL/PlatformProperties.h"
2024-06-14 13:05:35 -04:00
# include "MetasoundAssetManager.h"
2024-06-17 12:51:18 -04:00
# include "MetasoundGlobals.h"
2024-06-18 16:47:21 -04:00
# include "MetasoundSettings.h"
2024-05-08 14:53:53 -04:00
# include "MetasoundTrace.h"
# include "MetasoundUObjectRegistry.h"
namespace Metasound : : Engine
{
FDocumentBuilderRegistry : : ~ FDocumentBuilderRegistry ( )
{
2024-06-03 14:44:36 -04:00
TMultiMap < FMetasoundFrontendClassName , TWeakObjectPtr < UMetaSoundBuilderBase > > BuildersToFinish ;
2024-05-29 15:33:29 -04:00
FScopeLock Lock ( & BuildersCriticalSection ) ;
2024-06-03 14:44:36 -04:00
{
BuildersToFinish = MoveTemp ( Builders ) ;
Builders . Reset ( ) ;
}
UE_CLOG ( ! BuildersToFinish . IsEmpty ( ) , LogMetaSound , Display , TEXT ( " BuilderRegistry is shutting down with the following %i active builder entries. Forcefully shutting down: " ) , BuildersToFinish . Num ( ) ) ;
2024-05-29 15:33:29 -04:00
int32 NumStale = 0 ;
2024-06-03 14:44:36 -04:00
for ( const TPair < FMetasoundFrontendClassName , TWeakObjectPtr < UMetaSoundBuilderBase > > & Pair : BuildersToFinish )
2024-05-08 14:53:53 -04:00
{
2024-05-29 15:33:29 -04:00
const bool bIsValid = Pair . Value . IsValid ( ) ;
if ( bIsValid )
2024-05-14 20:20:01 -04:00
{
2024-05-29 15:33:29 -04:00
UE_CLOG ( bIsValid , LogMetaSound , Display , TEXT ( " - %s " ) , * Pair . Value - > GetFullName ( ) ) ;
2024-05-14 20:20:01 -04:00
constexpr bool bForceUnregister = true ;
2024-06-05 11:00:21 -04:00
FinishBuildingInternal ( * Pair . Value . Get ( ) , bForceUnregister ) ;
2024-05-29 15:33:29 -04:00
}
else
{
+ + NumStale ;
2024-05-14 20:20:01 -04:00
}
2024-05-08 14:53:53 -04:00
}
2024-05-29 15:33:29 -04:00
UE_CLOG ( NumStale > 0 , LogMetaSound , Display , TEXT ( " BuilderRegistry is shutting down with %i stale entries " ) , NumStale ) ;
2024-06-03 14:44:36 -04:00
}
void FDocumentBuilderRegistry : : AddBuilderInternal ( const FMetasoundFrontendClassName & InClassName , UMetaSoundBuilderBase * NewBuilder ) const
{
FScopeLock Lock ( & BuildersCriticalSection ) ;
2024-06-05 12:06:07 -04:00
// #if !NO_LOGGING
2024-06-10 13:52:48 -04:00
// bool bLogDuplicateEntries = CanPostEventLog(ELogEvent::DuplicateEntries, ELogVerbosity::Error);
// if (bLogDuplicateEntries)
// {
// bLogDuplicateEntries = Builders.Contains(InClassName);
// }
2024-06-05 12:06:07 -04:00
// #endif // !NO_LOGGING
2024-06-03 14:44:36 -04:00
Builders . Add ( InClassName , NewBuilder ) ;
2024-06-05 12:06:07 -04:00
// #if !NO_LOGGING
2024-06-10 13:52:48 -04:00
// if (bLogDuplicateEntries)
2024-06-05 12:06:07 -04:00
// {
// TArray<TWeakObjectPtr<UMetaSoundBuilderBase>> Entries;
// Builders.MultiFind(InClassName, Entries);
2024-06-10 13:52:48 -04:00
//
// // Don't print stale entries as during cook and some editor asset actions,
// // these may be removed after a new valid builder is created. If stale
// // entries leak, they will show up on registry logging upon destruction.
// Entries.RemoveAllSwap([](const TWeakObjectPtr<UMetaSoundBuilderBase>& Builder) { return !Builder.IsValid(); });
//
// if (!Entries.IsEmpty())
2024-06-05 12:06:07 -04:00
// {
2024-06-10 13:52:48 -04:00
// UE_LOG(LogMetaSound, Error, TEXT("More than one asset registered with class name '%s'. "
// "Look-up may return builder that is not associated with desired object! \n"
// "This can happen if asset was moved using revision control and original location was revived. \n"
// "Remove all but one of the following assets and relink a duplicate or copied replacement asset:"),
// *InClassName.ToString());
// for (const TWeakObjectPtr<UMetaSoundBuilderBase>& BuilderPtr : Entries)
2024-06-05 12:06:07 -04:00
// {
// UE_LOG(LogMetaSound, Error, TEXT("- %s"), *BuilderPtr->GetConstBuilder().CastDocumentObjectChecked<UObject>().GetPathName());
// }
// }
// }
// #endif // !NO_LOGGING
2024-05-08 14:53:53 -04:00
}
2024-06-10 13:52:48 -04:00
bool FDocumentBuilderRegistry : : CanPostEventLog ( ELogEvent Event , ELogVerbosity : : Type Verbosity ) const
{
# if NO_LOGGING
return false ;
# else // !NO_LOGGING
if ( const ELogVerbosity : : Type * SetVerbosity = EventLogVerbosity . Find ( Event ) )
{
return * SetVerbosity > = Verbosity ;
}
return true ;
# endif // !NO_LOGGING
}
2024-05-08 14:53:53 -04:00
# if WITH_EDITORONLY_DATA
2024-08-23 21:59:54 -04:00
bool FDocumentBuilderRegistry : : CookPages ( FName PlatformName , FMetaSoundFrontendDocumentBuilder & Builder ) const
{
2024-08-28 10:50:41 -04:00
METASOUND_LLM_SCOPE ;
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( FDocumentBuilderRegistry : : CookPages ) ;
2024-08-23 21:59:54 -04:00
bool bModified = false ;
const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) ;
check ( Settings ) ;
2024-08-28 10:50:41 -04:00
const TArray < FGuid > PlatformTargetPageIDs = Settings - > GetCookedTargetPageIDs ( PlatformName ) ;
2024-08-23 21:59:54 -04:00
checkf ( ! PlatformTargetPageIDs . IsEmpty ( ) , TEXT ( " Must have at least one targeted page ID to cook MetaSound. " ) ) ;
2024-10-08 18:08:08 -04:00
const FString DebugName = Builder . GetDebugName ( ) ;
auto StripPageEntries = [ & ] (
TArray < FGuid > & PageIdsToResolve ,
TSet < FGuid > & ResolveTargetScratch ,
TFunctionRef < bool ( const FGuid & ) > RemovePageItem ,
const FName & ItemName ,
const FString & ItemType )
2024-08-23 21:59:54 -04:00
{
2024-08-28 10:50:41 -04:00
ResolveTargetScratch . Reset ( ) ;
2024-08-23 21:59:54 -04:00
for ( const FGuid & TargetPage : PlatformTargetPageIDs )
{
2024-08-24 11:36:20 -04:00
const FGuid PageID = ResolveTargetPageIDInternal ( * Settings , PageIdsToResolve , TargetPage , PlatformName ) ;
2024-08-28 10:50:41 -04:00
ResolveTargetScratch . Add ( PageID ) ;
2024-08-23 21:59:54 -04:00
}
2024-08-28 10:50:41 -04:00
auto IsResolvedTarget = [ & ResolveTargetScratch ] ( const FGuid & PageID ) { return ResolveTargetScratch . Contains ( PageID ) ; } ;
checkf ( ! ResolveTargetScratch . IsEmpty ( ) , TEXT ( " Failed to resolve any valid target IDs, which will leave serialized page array in invalid state. " ) ) ;
2024-08-24 11:36:20 -04:00
PageIdsToResolve . RemoveAllSwap ( IsResolvedTarget , EAllowShrinking : : No ) ;
2024-08-23 21:59:54 -04:00
2024-08-24 11:36:20 -04:00
for ( const FGuid & PageID : PageIdsToResolve )
2024-08-23 21:59:54 -04:00
{
2024-10-08 18:08:08 -04:00
const bool bRemovedPageItem = RemovePageItem ( PageID ) ;
if ( bRemovedPageItem )
{
UE_LOG ( LogMetaSound , Display , TEXT ( " %s: Removed %s %s w/PageID '%s' " ) ,
* DebugName ,
ItemName . IsNone ( ) ? TEXT ( " paged " ) : * ItemName . ToString ( ) ,
* ItemType ,
* PageID . ToString ( ) ) ;
}
bModified | = bRemovedPageItem ;
2024-08-23 21:59:54 -04:00
}
} ;
const FMetasoundFrontendDocument & Document = Builder . GetConstDocumentChecked ( ) ;
2024-08-24 11:36:20 -04:00
TArray < FGuid > ResolvePageIDs ;
2024-08-28 10:50:41 -04:00
TSet < FGuid > ResolvedTargetScratchIDs ;
2024-08-23 21:59:54 -04:00
{ // Strip graphs
2024-08-24 11:36:20 -04:00
auto AddPageID = [ & ResolvePageIDs ] ( const FMetasoundFrontendGraph & Graph ) { ResolvePageIDs . Add ( Graph . PageID ) ; } ;
2024-08-23 21:59:54 -04:00
Document . RootGraph . IterateGraphPages ( AddPageID ) ;
auto RemoveGraphPage = [ & Builder ] ( const FGuid & InPageID )
{
return Builder . RemoveGraphPage ( InPageID ) ;
} ;
2024-10-01 17:46:57 -04:00
const int32 NumInitGraphs = Document . RootGraph . GetConstGraphPages ( ) . Num ( ) ;
2024-10-08 18:08:08 -04:00
StripPageEntries ( ResolvePageIDs , ResolvedTargetScratchIDs , RemoveGraphPage , FName ( ) , TEXT ( " graph " ) ) ;
2024-10-01 17:46:57 -04:00
const int32 NumRemainingGraphs = Document . RootGraph . GetConstGraphPages ( ) . Num ( ) ;
2024-08-23 21:59:54 -04:00
2024-10-01 17:46:57 -04:00
checkf ( NumRemainingGraphs > 0 ,
2024-08-23 21:59:54 -04:00
TEXT ( " Document in MetaSound asset '%s' had all default values "
" cooked away leaving it in an invalid state. "
" Graph must always have at least one implementation. " ) ,
* Builder . GetDebugName ( ) ) ;
2024-10-01 17:46:57 -04:00
if ( NumInitGraphs > NumRemainingGraphs )
{
UE_LOG ( LogMetaSound , Display , TEXT ( " Cook removed %i graph page(s) from '%s' " ) , NumInitGraphs - NumRemainingGraphs , * Builder . GetDebugName ( ) ) ;
}
2024-08-23 21:59:54 -04:00
}
{ // Strip default input values
for ( const FMetasoundFrontendClassInput & GraphInput : Document . RootGraph . Interface . Inputs )
{
2024-08-24 11:36:20 -04:00
ResolvePageIDs . Reset ( ) ;
auto AddPageID = [ & ResolvePageIDs ] ( const FGuid & PageID , const FMetasoundFrontendLiteral & ) { ResolvePageIDs . Add ( PageID ) ; } ;
2024-08-23 21:59:54 -04:00
GraphInput . IterateDefaults ( AddPageID ) ;
auto RemoveDefault = [ & Builder , & GraphInput ] ( const FGuid & InPageID )
{
2024-10-08 18:08:08 -04:00
const bool bClearInheritsDefault = false ;
return Builder . RemoveGraphInputDefault ( GraphInput . Name , InPageID , bClearInheritsDefault ) ;
2024-08-23 21:59:54 -04:00
} ;
2024-10-01 17:46:57 -04:00
const int32 NumInitDefaults = GraphInput . GetDefaults ( ) . Num ( ) ;
2024-10-08 18:08:08 -04:00
StripPageEntries ( ResolvePageIDs , ResolvedTargetScratchIDs , RemoveDefault , GraphInput . Name , TEXT ( " input default " ) ) ;
2024-10-01 17:46:57 -04:00
const int32 NumRemainingDefaults = GraphInput . GetDefaults ( ) . Num ( ) ;
checkf ( NumRemainingDefaults > 0 ,
2024-08-23 21:59:54 -04:00
TEXT ( " Input '%s' had all default values stripped leaving it in an invalid state. "
" Input must always have at least one default value " ) ,
* GraphInput . Name . ToString ( ) ) ;
2024-10-01 17:46:57 -04:00
if ( NumInitDefaults > NumRemainingDefaults )
{
UE_LOG ( LogMetaSound , Display , TEXT ( " Cook removed %i default input page value(s) from input '%s' " ) , NumInitDefaults - NumRemainingDefaults , * GraphInput . Name . ToString ( ) ) ;
}
2024-08-23 21:59:54 -04:00
}
}
return bModified ;
}
2024-05-08 14:53:53 -04:00
FMetaSoundFrontendDocumentBuilder & FDocumentBuilderRegistry : : FindOrBeginBuilding ( TScriptInterface < IMetaSoundDocumentInterface > MetaSound )
{
UObject * Object = MetaSound . GetObject ( ) ;
check ( Object ) ;
return FindOrBeginBuilding ( * Object ) . GetBuilder ( ) ;
}
# endif // WITH_EDITORONLY_DATA
FMetaSoundFrontendDocumentBuilder * FDocumentBuilderRegistry : : FindBuilder ( TScriptInterface < IMetaSoundDocumentInterface > MetaSound ) const
{
2024-05-29 15:33:29 -04:00
if ( UMetaSoundBuilderBase * Builder = FindBuilderObject ( MetaSound ) )
2024-05-08 14:53:53 -04:00
{
2024-05-29 15:33:29 -04:00
return & Builder - > GetBuilder ( ) ;
2024-05-08 14:53:53 -04:00
}
return nullptr ;
}
2024-06-05 11:00:21 -04:00
FMetaSoundFrontendDocumentBuilder * FDocumentBuilderRegistry : : FindBuilder ( const FMetasoundFrontendClassName & InClassName , const FTopLevelAssetPath & AssetPath ) const
2024-05-08 14:53:53 -04:00
{
2024-06-05 11:00:21 -04:00
if ( UMetaSoundBuilderBase * Builder = FindBuilderObject ( InClassName , AssetPath ) )
2024-05-08 14:53:53 -04:00
{
return & Builder - > GetBuilder ( ) ;
}
return nullptr ;
}
UMetaSoundBuilderBase * FDocumentBuilderRegistry : : FindBuilderObject ( TScriptInterface < const IMetaSoundDocumentInterface > MetaSound ) const
{
2024-06-05 11:00:21 -04:00
UMetaSoundBuilderBase * FoundEntry = nullptr ;
2024-05-08 14:53:53 -04:00
if ( const UObject * MetaSoundObject = MetaSound . GetObject ( ) )
{
const FMetasoundFrontendDocument & Document = MetaSound - > GetConstDocument ( ) ;
const FMetasoundFrontendClassName & ClassName = Document . RootGraph . Metadata . GetClassName ( ) ;
2024-05-29 15:33:29 -04:00
TArray < TWeakObjectPtr < UMetaSoundBuilderBase > > Entries ;
{
FScopeLock Lock ( & BuildersCriticalSection ) ;
Builders . MultiFind ( ClassName , Entries ) ;
}
2024-06-05 11:00:21 -04:00
for ( const TWeakObjectPtr < UMetaSoundBuilderBase > & BuilderPtr : Entries )
2024-05-29 15:33:29 -04:00
{
2024-06-05 11:00:21 -04:00
if ( UMetaSoundBuilderBase * Builder = BuilderPtr . Get ( ) )
2024-05-29 15:33:29 -04:00
{
2024-06-05 11:00:21 -04:00
// Can be invalid if look-up is called during asset removal/destruction or the entry was
// prematurely "finished". Only return invalid entry if builder asset path cannot be
// matched as this is likely the destroyed entry associated with the provided AssetPath.
const FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetConstBuilder ( ) ;
if ( DocBuilder . IsValid ( ) )
2024-05-29 15:33:29 -04:00
{
UObject & TestMetaSound = BuilderPtr - > GetConstBuilder ( ) . CastDocumentObjectChecked < UObject > ( ) ;
2024-06-05 11:00:21 -04:00
if ( & TestMetaSound = = MetaSoundObject )
{
FoundEntry = Builder ;
break ;
}
}
else
{
FoundEntry = Builder ;
2024-05-29 15:33:29 -04:00
}
}
}
2024-05-08 14:53:53 -04:00
}
2024-06-05 11:00:21 -04:00
return FoundEntry ;
2024-05-08 14:53:53 -04:00
}
2024-06-05 11:00:21 -04:00
UMetaSoundBuilderBase * FDocumentBuilderRegistry : : FindBuilderObject ( const FMetasoundFrontendClassName & InClassName , const FTopLevelAssetPath & AssetPath ) const
2024-05-08 14:53:53 -04:00
{
2024-05-29 15:33:29 -04:00
TArray < TWeakObjectPtr < UMetaSoundBuilderBase > > Entries ;
{
FScopeLock Lock ( & BuildersCriticalSection ) ;
2024-06-03 14:44:36 -04:00
Builders . MultiFind ( InClassName , Entries ) ;
2024-05-29 15:33:29 -04:00
}
2024-06-05 11:00:21 -04:00
UMetaSoundBuilderBase * FoundEntry = nullptr ;
for ( const TWeakObjectPtr < UMetaSoundBuilderBase > & BuilderPtr : Entries )
2024-05-29 15:33:29 -04:00
{
2024-06-05 11:00:21 -04:00
if ( UMetaSoundBuilderBase * Builder = BuilderPtr . Get ( ) )
{
const FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder - > GetConstBuilder ( ) ;
// Can be invalid if look-up is called during asset removal/destruction or the entry was
// prematurely "finished". Only return invalid entry if builder asset path cannot be
// matched as this is likely the destroyed entry associated with the provided AssetPath.
if ( DocBuilder . IsValid ( ) )
{
const UObject & DocObject = DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
FTopLevelAssetPath ObjectPath ;
if ( ObjectPath . TrySetPath ( & DocObject ) )
{
2024-06-21 14:37:29 -04:00
if ( AssetPath . IsNull ( ) | | AssetPath = = ObjectPath )
2024-06-05 11:00:21 -04:00
{
FoundEntry = Builder ;
break ;
}
}
else
{
FoundEntry = Builder ;
}
}
else
{
FoundEntry = Builder ;
}
}
2024-05-29 15:33:29 -04:00
}
2024-06-05 11:00:21 -04:00
return FoundEntry ;
2024-05-29 15:33:29 -04:00
}
2024-06-03 14:44:36 -04:00
TArray < UMetaSoundBuilderBase * > FDocumentBuilderRegistry : : FindBuilderObjects ( const FMetasoundFrontendClassName & InClassName ) const
2024-05-29 15:33:29 -04:00
{
TArray < UMetaSoundBuilderBase * > FoundBuilders ;
TArray < TWeakObjectPtr < UMetaSoundBuilderBase > > Entries ;
{
FScopeLock Lock ( & BuildersCriticalSection ) ;
2024-06-03 14:44:36 -04:00
Builders . MultiFind ( InClassName , Entries ) ;
2024-05-29 15:33:29 -04:00
}
if ( ! Entries . IsEmpty ( ) )
{
Algo : : TransformIf ( Entries , FoundBuilders ,
[ ] ( const TWeakObjectPtr < UMetaSoundBuilderBase > & BuilderPtr ) { return BuilderPtr . IsValid ( ) ; } ,
[ ] ( const TWeakObjectPtr < UMetaSoundBuilderBase > & BuilderPtr ) { return BuilderPtr . Get ( ) ; }
) ;
}
return FoundBuilders ;
}
FMetaSoundFrontendDocumentBuilder * FDocumentBuilderRegistry : : FindOutermostBuilder ( const UObject & InSubObject ) const
{
using namespace Metasound : : Frontend ;
TScriptInterface < IMetaSoundDocumentInterface > DocumentInterface = InSubObject . GetOutermostObject ( ) ;
check ( DocumentInterface . GetObject ( ) ) ;
return FindBuilder ( DocumentInterface ) ;
2024-05-08 14:53:53 -04:00
}
2024-05-30 18:56:24 -04:00
bool FDocumentBuilderRegistry : : FinishBuilding ( const FMetasoundFrontendClassName & InClassName , bool bForceUnregisterNodeClass ) const
2024-05-08 14:53:53 -04:00
{
using namespace Metasound ;
using namespace Metasound : : Engine ;
2024-05-29 15:33:29 -04:00
TArray < UMetaSoundBuilderBase * > FoundBuilders = FindBuilderObjects ( InClassName ) ;
for ( UMetaSoundBuilderBase * Builder : FoundBuilders )
2024-05-08 14:53:53 -04:00
{
2024-06-05 11:00:21 -04:00
FinishBuildingInternal ( * Builder , bForceUnregisterNodeClass ) ;
}
2024-06-06 14:50:30 -04:00
FScopeLock Lock ( & BuildersCriticalSection ) ;
return Builders . Remove ( InClassName ) > 0 ;
2024-06-05 11:00:21 -04:00
}
bool FDocumentBuilderRegistry : : FinishBuilding ( const FMetasoundFrontendClassName & InClassName , const FTopLevelAssetPath & AssetPath , bool bForceUnregisterNodeClass ) const
{
using namespace Metasound ;
using namespace Metasound : : Engine ;
TWeakObjectPtr < UMetaSoundBuilderBase > BuilderPtr ;
if ( UMetaSoundBuilderBase * Builder = FindBuilderObject ( InClassName , AssetPath ) )
{
FinishBuildingInternal ( * Builder , bForceUnregisterNodeClass ) ;
BuilderPtr = TWeakObjectPtr < UMetaSoundBuilderBase > ( Builder ) ;
}
FScopeLock Lock ( & BuildersCriticalSection ) ;
return Builders . RemoveSingle ( InClassName , BuilderPtr ) > 0 ;
}
void FDocumentBuilderRegistry : : FinishBuildingInternal ( UMetaSoundBuilderBase & Builder , bool bForceUnregisterNodeClass ) const
{
2024-06-14 13:05:35 -04:00
using namespace Metasound ;
using namespace Metasound : : Frontend ;
2024-06-05 11:00:21 -04:00
// If the builder has applied transactions to its document object that are not mirrored in the frontend registry,
// unregister version in registry. This will ensure that future requests for the builder's associated asset will
// register a fresh version from the object as the transaction history is intrinsically lost once this builder
// is destroyed. It is also possible that the DocBuilder's underlying object can be invalid if object was force
// deleted, so validity check is necessary.
FMetaSoundFrontendDocumentBuilder & DocBuilder = Builder . GetBuilder ( ) ;
if ( DocBuilder . IsValid ( ) )
{
2024-06-17 12:51:18 -04:00
if ( Metasound : : CanEverExecuteGraph ( ) )
2024-05-08 14:53:53 -04:00
{
2024-06-05 11:00:21 -04:00
const int32 TransactionCount = DocBuilder . GetTransactionCount ( ) ;
const int32 LastTransactionRegistered = Builder . GetLastTransactionRegistered ( ) ;
if ( bForceUnregisterNodeClass | | LastTransactionRegistered ! = TransactionCount )
2024-05-08 14:53:53 -04:00
{
2024-06-05 11:00:21 -04:00
UObject & MetaSound = DocBuilder . CastDocumentObjectChecked < UObject > ( ) ;
if ( FMetasoundAssetBase * MetaSoundAsset = IMetasoundUObjectRegistry : : Get ( ) . GetObjectAsAssetBase ( & MetaSound ) )
2024-05-10 12:40:21 -04:00
{
2024-06-05 11:00:21 -04:00
MetaSoundAsset - > UnregisterGraphWithFrontend ( ) ;
2024-05-10 12:40:21 -04:00
}
2024-05-08 14:53:53 -04:00
}
2024-05-29 15:33:29 -04:00
}
2024-06-05 11:00:21 -04:00
DocBuilder . FinishBuilding ( ) ;
2024-05-29 15:33:29 -04:00
}
}
2024-06-27 23:26:57 -04:00
# if WITH_EDITOR
2024-08-23 21:59:54 -04:00
FOnResolveEditorPage & FDocumentBuilderRegistry : : GetOnResolveAuditionPageDelegate ( )
2024-06-27 23:26:57 -04:00
{
2024-08-23 21:59:54 -04:00
return OnResolveAuditionPage ;
2024-06-27 23:26:57 -04:00
}
# endif // WITH_EDITOR
2024-08-23 21:59:54 -04:00
FOnResolvePage & FDocumentBuilderRegistry : : GetOnResolveProjectPageOverrideDelegate ( )
{
return OnResolveProjectPage ;
}
2024-05-29 15:33:29 -04:00
bool FDocumentBuilderRegistry : : ReloadBuilder ( const FMetasoundFrontendClassName & InClassName ) const
{
2024-06-05 11:00:21 -04:00
bool bReloaded = false ;
TArray < UMetaSoundBuilderBase * > ClassBuilders = FindBuilderObjects ( InClassName ) ;
for ( UMetaSoundBuilderBase * Builder : ClassBuilders )
2024-05-29 15:33:29 -04:00
{
Builder - > Reload ( ) ;
2024-06-05 11:00:21 -04:00
bReloaded = true ;
2024-05-08 14:53:53 -04:00
}
2024-06-05 11:00:21 -04:00
return bReloaded ;
2024-05-08 14:53:53 -04:00
}
2024-06-10 13:52:48 -04:00
2024-08-23 21:59:54 -04:00
FGuid FDocumentBuilderRegistry : : ResolveTargetPageID ( const FMetasoundFrontendGraphClass & InGraphClass ) const
2024-08-13 14:58:36 -04:00
{
2024-08-24 11:36:20 -04:00
FScopeLock Lock ( & TargetPageResolveScratchCritSec ) ;
2024-08-23 21:59:54 -04:00
TargetPageResolveScratch . Reset ( ) ;
InGraphClass . IterateGraphPages ( [ this ] ( const FMetasoundFrontendGraph & PageGraph )
2024-08-13 14:58:36 -04:00
{
2024-08-23 21:59:54 -04:00
TargetPageResolveScratch . Add ( PageGraph . PageID ) ;
2024-08-13 14:58:36 -04:00
} ) ;
2024-08-24 11:36:20 -04:00
return ResolveTargetPageIDInternal ( TargetPageResolveScratch ) ;
2024-08-13 14:58:36 -04:00
}
2024-08-23 21:59:54 -04:00
FGuid FDocumentBuilderRegistry : : ResolveTargetPageID ( const FMetasoundFrontendClassInput & InClassInput ) const
2024-08-13 14:58:36 -04:00
{
2024-08-24 11:36:20 -04:00
FScopeLock Lock ( & TargetPageResolveScratchCritSec ) ;
2024-08-23 21:59:54 -04:00
TargetPageResolveScratch . Reset ( ) ;
InClassInput . IterateDefaults ( [ this ] ( const FGuid & PageID , const FMetasoundFrontendLiteral & )
2024-08-13 14:58:36 -04:00
{
2024-08-23 21:59:54 -04:00
TargetPageResolveScratch . Add ( PageID ) ;
2024-08-13 14:58:36 -04:00
} ) ;
2024-08-24 11:36:20 -04:00
return ResolveTargetPageIDInternal ( TargetPageResolveScratch ) ;
2024-08-13 14:58:36 -04:00
}
2024-08-23 21:59:54 -04:00
FGuid FDocumentBuilderRegistry : : ResolveTargetPageID ( const TArray < FMetasoundFrontendClassInputDefault > & InClassDefaults ) const
2024-08-13 14:58:36 -04:00
{
2024-08-24 11:36:20 -04:00
FScopeLock Lock ( & TargetPageResolveScratchCritSec ) ;
2024-08-23 21:59:54 -04:00
TargetPageResolveScratch . Reset ( ) ;
Algo : : Transform ( InClassDefaults , TargetPageResolveScratch , [ ] ( const FMetasoundFrontendClassInputDefault & ClassDefault ) { return ClassDefault . PageID ; } ) ;
2024-08-24 11:36:20 -04:00
return ResolveTargetPageIDInternal ( TargetPageResolveScratch ) ;
2024-08-13 14:58:36 -04:00
}
2024-08-24 11:36:20 -04:00
FGuid FDocumentBuilderRegistry : : ResolveTargetPageIDInternal ( const TArray < FGuid > & InPageIDsToResolve ) const
2024-06-27 23:26:57 -04:00
{
2024-08-23 21:59:54 -04:00
METASOUND_LLM_SCOPE ;
METASOUND_TRACE_CPUPROFILER_EVENT_SCOPE ( FDocumentBuilderRegistry : : ResolveTargetPageID ) ;
2024-06-27 23:26:57 -04:00
FName PlatformName = FPlatformProperties : : IniPlatformName ( ) ;
# if WITH_EDITOR
2024-08-23 21:59:54 -04:00
if ( OnResolveAuditionPage . IsBound ( ) )
2024-06-27 23:26:57 -04:00
{
2024-08-24 11:36:20 -04:00
FPageResolutionEditorResults PreviewInfo = OnResolveAuditionPage . Execute ( InPageIDsToResolve ) ;
2024-06-27 23:26:57 -04:00
if ( PreviewInfo . PageID . IsSet ( ) )
{
2024-08-23 21:59:54 -04:00
return PreviewInfo . PageID . GetValue ( ) ;
2024-06-27 23:26:57 -04:00
}
PlatformName = PreviewInfo . PlatformName ;
}
# endif // WITH_EDITOR
2024-08-23 21:59:54 -04:00
if ( OnResolveProjectPage . IsBound ( ) )
2024-06-27 23:26:57 -04:00
{
2024-08-24 11:36:20 -04:00
const FGuid ResolvedPageID = OnResolveProjectPage . Execute ( InPageIDsToResolve ) ;
check ( InPageIDsToResolve . Contains ( ResolvedPageID ) ) ;
2024-08-23 21:59:54 -04:00
return ResolvedPageID ;
}
2024-06-27 23:26:57 -04:00
2024-08-23 21:59:54 -04:00
if ( const UMetaSoundSettings * Settings = GetDefault < UMetaSoundSettings > ( ) )
{
const FGuid & TargetPageID = Settings - > GetTargetPageSettings ( ) . UniqueId ;
2024-08-24 11:36:20 -04:00
return ResolveTargetPageIDInternal ( * Settings , InPageIDsToResolve , TargetPageID , PlatformName ) ;
2024-08-23 21:59:54 -04:00
}
return Frontend : : DefaultPageID ;
}
2024-08-24 11:36:20 -04:00
FGuid FDocumentBuilderRegistry : : ResolveTargetPageIDInternal ( const UMetaSoundSettings & Settings , const TArray < FGuid > & InPageIDsToResolve , const FGuid & TargetPageID , FName PlatformName ) const
2024-08-23 21:59:54 -04:00
{
bool bResolved = false ;
FGuid ResolvedPageID = Frontend : : DefaultPageID ;
constexpr bool bReverse = true ;
2024-08-23 23:03:23 -04:00
bool bFoundTarget = false ;
2024-08-23 21:59:54 -04:00
Settings . IteratePageSettings ( [ & ] ( const FMetaSoundPageSettings & PageSettings )
{
2024-08-23 23:03:23 -04:00
bFoundTarget | = PageSettings . UniqueId = = TargetPageID ;
if ( bFoundTarget & & ! bResolved )
2024-06-27 23:26:57 -04:00
{
2024-08-24 11:36:20 -04:00
const bool bAssetImplementsPage = InPageIDsToResolve . Contains ( PageSettings . UniqueId ) ;
2024-08-23 21:59:54 -04:00
if ( bAssetImplementsPage )
2024-06-27 23:26:57 -04:00
{
# if WITH_EDITOR
2024-08-23 23:03:23 -04:00
const bool bIsCooked = ! PageSettings . GetExcludeFromCook ( PlatformName ) ;
2024-06-27 23:26:57 -04:00
if ( bIsCooked )
{
2024-08-23 21:59:54 -04:00
bResolved = true ;
ResolvedPageID = PageSettings . UniqueId ;
2024-06-27 23:26:57 -04:00
}
# else // !WITH_EDITOR
2024-08-23 21:59:54 -04:00
bResolved = true ;
ResolvedPageID = PageSettings . UniqueId ;
2024-06-27 23:26:57 -04:00
# endif // !WITH_EDITOR
}
}
2024-08-23 21:59:54 -04:00
} , bReverse ) ;
2024-06-27 23:26:57 -04:00
2024-10-01 19:22:54 -04:00
if ( ! bResolved )
{
const FGuid & AnyPageID = InPageIDsToResolve . Last ( ) ;
# if !NO_LOGGING
auto GetDisplayPageString = [ & Settings ] ( const FGuid & InPageID )
{
if ( const FMetaSoundPageSettings * DisplayPage = Settings . FindPageSettings ( InPageID ) )
{
return DisplayPage - > Name . ToString ( ) ;
}
return InPageID . ToString ( ) ;
} ;
UE_LOG ( LogMetaSound , Error ,
TEXT ( " Failed to resolve PageID for Target '%s': Setting to arbitrary Page '%s' (Target likely overridden by page not set as 'CanTarget/Targetable' for the current platform) " ) ,
* GetDisplayPageString ( TargetPageID ) ,
* GetDisplayPageString ( AnyPageID ) ) ;
# endif // !NO_LOGGING
ResolvedPageID = AnyPageID ;
}
2024-08-23 21:59:54 -04:00
return ResolvedPageID ;
2024-06-27 23:26:57 -04:00
}
2024-06-10 13:52:48 -04:00
void FDocumentBuilderRegistry : : SetEventLogVerbosity ( ELogEvent Event , ELogVerbosity : : Type Verbosity )
{
EventLogVerbosity . FindOrAdd ( Event ) = Verbosity ;
}
2024-05-08 14:53:53 -04:00
} // namespace Metasound::Engine