2021-01-13 10:48:59 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "MetasoundFrontendStandardController.h"
# include "Algo/ForEach.h"
# include "Algo/NoneOf.h"
# include "CoreMinimal.h"
# include "HAL/FileManager.h"
# include "MetasoundAccessPtr.h"
# include "MetasoundFrontendController.h"
# include "MetasoundFrontendDocument.h"
# include "MetasoundFrontendGraph.h"
2021-02-03 14:36:36 -04:00
# include "MetasoundFrontendRegistries.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundJsonBackend.h"
# include "MetasoundOperatorBuilder.h"
# include "StructDeserializer.h"
# include "StructSerializer.h"
# include "Serialization/MemoryReader.h"
2021-02-03 14:36:36 -04:00
2021-01-13 10:48:59 -04:00
namespace Metasound
{
namespace Frontend
{
namespace FrontendControllerIntrinsics
{
// utility function for returning invalid values. If an invalid value type
// needs special construction, this template can be specialized.
template < typename ValueType >
ValueType GetInvalidValue ( )
{
ValueType InvalidValue ;
return InvalidValue ;
}
// Utility function to get a value for an existing description pointer
// or return an invalid value const ref if the TAccessPtr is invalid.
template < typename ValueType , typename PtrType >
const ValueType & GetValueOrReturnInvalid ( const TAccessPtr < PtrType > & InPointer , ValueType ( PtrType : : * InMember ) )
{
static const ValueType InvalidValue = GetInvalidValue < ValueType > ( ) ;
if ( InPointer . IsValid ( ) )
{
return ( * InPointer ) . * InMember ;
}
return InvalidValue ;
}
// Invalid value specialization for int32
template < >
int32 GetInvalidValue < int32 > ( ) { return INDEX_NONE ; }
// Invalid value specialization for EMetasoundFrontendClassType
template < >
EMetasoundFrontendClassType GetInvalidValue < EMetasoundFrontendClassType > ( ) { return EMetasoundFrontendClassType : : Invalid ; }
// Invalid value specialization for FText
template < >
FText GetInvalidValue < FText > ( ) { return FText : : GetEmpty ( ) ; }
template < typename ValueType >
const ValueType & GetInvalidValueConstRef ( )
{
static const ValueType Value = GetInvalidValue < ValueType > ( ) ;
return Value ;
}
template < typename Type >
TAccessPtr < Type > MakeAutoAccessPtr ( Type & InObj )
{
return MakeAccessPtr ( InObj . AccessPoint , InObj ) ;
//return MakeAccessPtr(InObj);
}
// TODO: All these access ptr helper routines should be merged into
// the TAccessPtr<> interface. The TAccessPtr<> class should be specialized
// for the types used here, with the specialized TAccessPtr<> interface
// adding support for getting specific member access ptrs and doing
// specific queries.
struct FGetSubgraphFromDocumentByID
{
2021-01-20 17:26:40 -04:00
FGetSubgraphFromDocumentByID ( FGuid InID )
2021-01-13 10:48:59 -04:00
: ID ( InID )
{
}
FMetasoundFrontendGraphClass * operator ( ) ( FMetasoundFrontendDocument & InDoc ) const
{
return InDoc . Subgraphs . FindByPredicate ( [ & ] ( const FMetasoundFrontendGraphClass & GraphClass ) { return GraphClass . ID = = ID ; } ) ;
}
const FMetasoundFrontendGraphClass * operator ( ) ( const FMetasoundFrontendDocument & InDoc ) const
{
return InDoc . Subgraphs . FindByPredicate ( [ & ] ( const FMetasoundFrontendGraphClass & GraphClass ) { return GraphClass . ID = = ID ; } ) ;
}
private :
2021-01-20 17:26:40 -04:00
FGuid ID ;
2021-01-13 10:48:59 -04:00
} ;
struct FGetClassInputFromClassWithName
{
FGetClassInputFromClassWithName ( const FString & InName )
: Name ( InName )
{
}
FMetasoundFrontendClassInput * operator ( ) ( FMetasoundFrontendClass & InClass )
{
auto IsClassInputWithName = [ & ] ( const FMetasoundFrontendClassInput & ClassInput ) { return ClassInput . Name = = Name ; } ;
return InClass . Interface . Inputs . FindByPredicate ( IsClassInputWithName ) ;
}
const FMetasoundFrontendClassInput * operator ( ) ( const FMetasoundFrontendClass & InClass )
{
auto IsClassInputWithName = [ & ] ( const FMetasoundFrontendClassInput & ClassInput ) { return ClassInput . Name = = Name ; } ;
return InClass . Interface . Inputs . FindByPredicate ( IsClassInputWithName ) ;
}
private :
FString Name ;
} ;
struct FGetClassOutputFromClassWithName
{
FGetClassOutputFromClassWithName ( const FString & InName )
: Name ( InName )
{
}
FMetasoundFrontendClassOutput * operator ( ) ( FMetasoundFrontendClass & InClass )
{
auto IsClassOutputWithName = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput ) { return ClassOutput . Name = = Name ; } ;
return InClass . Interface . Outputs . FindByPredicate ( IsClassOutputWithName ) ;
}
const FMetasoundFrontendClassOutput * operator ( ) ( const FMetasoundFrontendClass & InClass )
{
auto IsClassOutputWithName = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput ) { return ClassOutput . Name = = Name ; } ;
return InClass . Interface . Outputs . FindByPredicate ( IsClassOutputWithName ) ;
}
private :
FString Name ;
} ;
auto FGetNodeInputFromNodeWithName ( const FString & InName )
{
return [ = ] ( FMetasoundFrontendNode & InNode ) - > FMetasoundFrontendVertex *
{
auto IsVertexWithName = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . Name = = InName ; } ;
return InNode . Interface . Inputs . FindByPredicate ( IsVertexWithName ) ;
} ;
}
auto FGetConstNodeInputFromNodeWithName ( const FString & InName )
{
return [ = ] ( const FMetasoundFrontendNode & InNode ) - > const FMetasoundFrontendVertex *
{
auto IsVertexWithName = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . Name = = InName ; } ;
return InNode . Interface . Inputs . FindByPredicate ( IsVertexWithName ) ;
} ;
}
auto FGetNodeOutputFromNodeWithName ( const FString & InName )
{
return [ = ] ( FMetasoundFrontendNode & InNode ) - > FMetasoundFrontendVertex *
{
auto IsVertexWithName = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . Name = = InName ; } ;
return InNode . Interface . Outputs . FindByPredicate ( IsVertexWithName ) ;
} ;
}
auto FGetConstNodeOutputFromNodeWithName ( const FString & InName )
{
return [ = ] ( const FMetasoundFrontendNode & InNode ) - > const FMetasoundFrontendVertex *
{
auto IsVertexWithName = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . Name = = InName ; } ;
return InNode . Interface . Outputs . FindByPredicate ( IsVertexWithName ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetNodeInputFromNodeWithPoint ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( FMetasoundFrontendNode & InNode ) - > FMetasoundFrontendVertex *
{
auto IsVertexWithPoint = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . PointIDs . Contains ( InPointID ) ; } ;
return InNode . Interface . Inputs . FindByPredicate ( IsVertexWithPoint ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstNodeInputFromNodeWithPoint ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendNode & InNode ) - > const FMetasoundFrontendVertex *
{
auto IsVertexWithPoint = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . PointIDs . Contains ( InPointID ) ; } ;
return InNode . Interface . Inputs . FindByPredicate ( IsVertexWithPoint ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetNodeOutputFromNodeWithPoint ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( FMetasoundFrontendNode & InNode ) - > FMetasoundFrontendVertex *
{
auto IsVertexWithPoint = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . PointIDs . Contains ( InPointID ) ; } ;
return InNode . Interface . Outputs . FindByPredicate ( IsVertexWithPoint ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstNodeOutputFromNodeWithPoint ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendNode & InNode ) - > const FMetasoundFrontendVertex *
{
auto IsVertexWithPoint = [ = ] ( const FMetasoundFrontendVertex & Vertex ) { return Vertex . PointIDs . Contains ( InPointID ) ; } ;
return InNode . Interface . Outputs . FindByPredicate ( IsVertexWithPoint ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstClassFromDocumentDependenciesWithID ( FGuid InClassID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendDocument & InDocument ) - > const FMetasoundFrontendClass *
{
auto IsClassWithID = [ = ] ( const FMetasoundFrontendClass & InClass ) { return InClass . ID = = InClassID ; } ;
return InDocument . Dependencies . FindByPredicate ( IsClassWithID ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstGraphClassFromDocumentWithID ( FGuid InClassID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendDocument & InDocument ) - > const FMetasoundFrontendGraphClass *
{
auto IsClassWithID = [ = ] ( const FMetasoundFrontendGraphClass & InClass ) { return InClass . ID = = InClassID ; } ;
return InDocument . Subgraphs . FindByPredicate ( IsClassWithID ) ;
} ;
}
auto FGetConstClassFromDocumentWithClassInfo ( const FNodeClassInfo & InInfo )
{
return [ = ] ( const FMetasoundFrontendDocument & InDocument ) - > const FMetasoundFrontendClass *
{
auto IsClassWithClassInfo = [ = ] ( const FMetasoundFrontendClass & InClass )
{
return FDocumentController : : IsMatchingMetasoundClass ( InInfo , InClass . Metadata ) ;
} ;
const FMetasoundFrontendClass * MetasoundClass = InDocument . Dependencies . FindByPredicate ( IsClassWithClassInfo ) ;
if ( nullptr = = MetasoundClass )
{
MetasoundClass = InDocument . Subgraphs . FindByPredicate ( IsClassWithClassInfo ) ;
}
return MetasoundClass ;
} ;
}
auto FGetConstClassFromDocumentWithMetadata ( const FMetasoundFrontendClassMetadata & InMetadata )
{
return [ = ] ( const FMetasoundFrontendDocument & InDocument ) - > const FMetasoundFrontendClass *
{
auto IsClassWithMetadata = [ = ] ( const FMetasoundFrontendClass & InClass )
{
return FDocumentController : : IsMatchingMetasoundClass ( InMetadata , InClass . Metadata ) ;
} ;
const FMetasoundFrontendClass * MetasoundClass = InDocument . Dependencies . FindByPredicate ( IsClassWithMetadata ) ;
if ( nullptr = = MetasoundClass )
{
MetasoundClass = InDocument . Subgraphs . FindByPredicate ( IsClassWithMetadata ) ;
}
return MetasoundClass ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetNodeFromGraphClassByNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( FMetasoundFrontendGraphClass & InGraphClass ) - > FMetasoundFrontendNode *
{
auto IsNodeWithID = [ & ] ( const FMetasoundFrontendNode & InNode ) { return InNode . ID = = InNodeID ; } ;
return InGraphClass . Graph . Nodes . FindByPredicate ( IsNodeWithID ) ;
} ;
}
auto FGetConstGraphFromGraphClass ( )
{
return [ ] ( const FMetasoundFrontendGraphClass & InGraphClass ) - > const FMetasoundFrontendGraph * { return & InGraphClass . Graph ; } ;
}
auto FGetGraphFromGraphClass ( )
{
return [ ] ( FMetasoundFrontendGraphClass & InGraphClass ) - > FMetasoundFrontendGraph * { return & InGraphClass . Graph ; } ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstNodeFromGraphClassByNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendGraphClass & InGraphClass ) - > const FMetasoundFrontendNode *
{
auto IsNodeWithID = [ & ] ( const FMetasoundFrontendNode & InNode ) { return InNode . ID = = InNodeID ; } ;
return InGraphClass . Graph . Nodes . FindByPredicate ( IsNodeWithID ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstClassInputFromGraphClassWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendGraphClass & InGraphClass ) - > const FMetasoundFrontendClassInput *
{
return InGraphClass . Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . NodeID = = InNodeID ; } ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetClassInputFromGraphClassWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( FMetasoundFrontendGraphClass & InGraphClass ) - > FMetasoundFrontendClassInput *
{
return InGraphClass . Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . NodeID = = InNodeID ; } ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetConstClassOutputFromGraphClassWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( const FMetasoundFrontendGraphClass & InGraphClass ) - > const FMetasoundFrontendClassOutput *
{
return InGraphClass . Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . NodeID = = InNodeID ; } ) ;
} ;
}
2021-01-20 17:26:40 -04:00
auto FGetClassOutputFromGraphClassWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
return [ = ] ( FMetasoundFrontendGraphClass & InGraphClass ) - > FMetasoundFrontendClassOutput *
{
return InGraphClass . Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . NodeID = = InNodeID ; } ) ;
} ;
}
2021-01-20 17:26:40 -04:00
}
2021-01-13 10:48:59 -04:00
2021-01-20 17:26:40 -04:00
FDocumentAccess IDocumentAccessor : : GetSharedAccess ( IDocumentAccessor & InDocumentAccessor )
{
return InDocumentAccessor . ShareAccess ( ) ;
}
2021-01-13 10:48:59 -04:00
2021-01-20 17:26:40 -04:00
FConstDocumentAccess IDocumentAccessor : : GetSharedAccess ( const IDocumentAccessor & InDocumentAccessor )
{
return InDocumentAccessor . ShareAccess ( ) ;
2021-01-13 10:48:59 -04:00
}
//
// FBaseOutputController
//
FBaseOutputController : : FBaseOutputController ( const FBaseOutputController : : FInitParams & InParams )
: ID ( InParams . ID )
, NodeVertexPtr ( InParams . NodeVertexPtr )
2021-01-22 03:05:22 -04:00
, GraphPtr ( InParams . GraphPtr )
2021-01-13 10:48:59 -04:00
, OwningNode ( InParams . OwningNode )
{
}
bool FBaseOutputController : : IsValid ( ) const
{
2021-01-22 03:05:22 -04:00
return OwningNode - > IsValid ( ) & & NodeVertexPtr . IsValid ( ) & & GraphPtr . IsValid ( ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FGuid FBaseOutputController : : GetID ( ) const
2021-01-13 10:48:59 -04:00
{
return ID ;
}
const FName & FBaseOutputController : : GetDataType ( ) const
{
if ( NodeVertexPtr . IsValid ( ) )
{
return NodeVertexPtr - > TypeName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FName > ( ) ;
}
const FString & FBaseOutputController : : GetName ( ) const
{
if ( NodeVertexPtr . IsValid ( ) )
{
return NodeVertexPtr - > Name ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FString > ( ) ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseOutputController : : GetOwningNodeID ( ) const
2021-01-13 10:48:59 -04:00
{
return OwningNode - > GetID ( ) ;
}
FNodeHandle FBaseOutputController : : GetOwningNode ( )
{
return OwningNode ;
}
FConstNodeHandle FBaseOutputController : : GetOwningNode ( ) const
{
return OwningNode ;
}
2021-01-22 03:05:22 -04:00
TArray < FInputHandle > FBaseOutputController : : GetCurrentlyConnectedInputs ( )
{
TArray < FInputHandle > Inputs ;
// Create output handle from output node.
FGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
for ( const FMetasoundFrontendEdge & Edge : FindEdges ( ) )
{
FNodeHandle InputNode = Graph - > GetNodeWithID ( Edge . ToNodeID ) ;
FInputHandle Input = InputNode - > GetInputWithID ( Edge . ToPointID ) ;
if ( Input - > IsValid ( ) )
{
Inputs . Add ( Input ) ;
}
}
return Inputs ;
}
TArray < FConstInputHandle > FBaseOutputController : : GetCurrentlyConnectedInputs ( ) const
{
TArray < FConstInputHandle > Inputs ;
// Create output handle from output node.
FConstGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
for ( const FMetasoundFrontendEdge & Edge : FindEdges ( ) )
{
FConstNodeHandle InputNode = Graph - > GetNodeWithID ( Edge . ToNodeID ) ;
FConstInputHandle Input = InputNode - > GetInputWithID ( Edge . ToPointID ) ;
if ( Input - > IsValid ( ) )
{
Inputs . Add ( Input ) ;
}
}
return Inputs ;
}
bool FBaseOutputController : : Disconnect ( )
{
bool bSuccess = true ;
for ( FInputHandle Input : GetCurrentlyConnectedInputs ( ) )
{
if ( Input - > IsValid ( ) )
{
bSuccess & = Disconnect ( * Input ) ;
}
}
return bSuccess ;
}
2021-01-13 10:48:59 -04:00
FConnectability FBaseOutputController : : CanConnectTo ( const IInputController & InController ) const
{
return InController . CanConnectTo ( * this ) ;
}
bool FBaseOutputController : : Connect ( IInputController & InController )
{
return InController . Connect ( * this ) ;
}
bool FBaseOutputController : : ConnectWithConverterNode ( IInputController & InController , const FConverterNodeInfo & InNodeClassName )
{
return InController . ConnectWithConverterNode ( * this , InNodeClassName ) ;
}
bool FBaseOutputController : : Disconnect ( IInputController & InController )
{
return InController . Disconnect ( * this ) ;
}
2021-01-22 03:05:22 -04:00
TArray < FMetasoundFrontendEdge > FBaseOutputController : : FindEdges ( ) const
{
if ( GraphPtr . IsValid ( ) )
{
const FGuid NodeID = GetOwningNodeID ( ) ;
FGuid PointID = GetID ( ) ;
auto EdgeHasMatchingSource = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
return ( Edge . FromNodeID = = NodeID ) & & ( Edge . FromPointID = = PointID ) ;
} ;
return GraphPtr - > Edges . FilterByPredicate ( EdgeHasMatchingSource ) ;
}
return TArray < FMetasoundFrontendEdge > ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FBaseOutputController : : ShareAccess ( )
{
FDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
2021-01-22 03:05:22 -04:00
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
2021-01-20 17:26:40 -04:00
return Access ;
}
FConstDocumentAccess FBaseOutputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
2021-01-22 03:05:22 -04:00
Access . ConstGraph = GraphPtr ;
2021-01-20 17:26:40 -04:00
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FNodeOutputController
//
FNodeOutputController : : FNodeOutputController ( const FNodeOutputController : : FInitParams & InParams )
2021-01-22 03:05:22 -04:00
: FBaseOutputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . GraphPtr , InParams . OwningNode } )
2021-01-13 10:48:59 -04:00
, ClassOutputPtr ( InParams . ClassOutputPtr )
{
}
bool FNodeOutputController : : IsValid ( ) const
{
return FBaseOutputController : : IsValid ( ) & & ClassOutputPtr . IsValid ( ) ;
}
const FText & FNodeOutputController : : GetDisplayName ( ) const
{
if ( ClassOutputPtr . IsValid ( ) )
{
return ClassOutputPtr - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FNodeOutputController : : GetTooltip ( ) const
{
if ( ClassOutputPtr . IsValid ( ) )
{
return ClassOutputPtr - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FNodeOutputController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseOutputController : : ShareAccess ( ) ;
Access . ConstClassOutput = ClassOutputPtr ;
return Access ;
}
FConstDocumentAccess FNodeOutputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseOutputController : : ShareAccess ( ) ;
Access . ConstClassOutput = ClassOutputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FInputNodeOutputController
//
FInputNodeOutputController : : FInputNodeOutputController ( const FInputNodeOutputController : : FInitParams & InParams )
2021-01-22 03:05:22 -04:00
: FBaseOutputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . GraphPtr , InParams . OwningNode } )
2021-01-13 10:48:59 -04:00
, OwningGraphClassInputPtr ( InParams . OwningGraphClassInputPtr )
{
}
bool FInputNodeOutputController : : IsValid ( ) const
{
return FBaseOutputController : : IsValid ( ) & & OwningGraphClassInputPtr . IsValid ( ) ;
}
const FText & FInputNodeOutputController : : GetDisplayName ( ) const
{
if ( OwningGraphClassInputPtr . IsValid ( ) )
{
return OwningGraphClassInputPtr - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FInputNodeOutputController : : GetTooltip ( ) const
{
if ( OwningGraphClassInputPtr . IsValid ( ) )
{
return OwningGraphClassInputPtr - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FInputNodeOutputController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseOutputController : : ShareAccess ( ) ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
FConstDocumentAccess FInputNodeOutputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseOutputController : : ShareAccess ( ) ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FBaseInputController
//
FBaseInputController : : FBaseInputController ( const FBaseInputController : : FInitParams & InParams )
: ID ( InParams . ID )
, NodeVertexPtr ( InParams . NodeVertexPtr )
, GraphPtr ( InParams . GraphPtr )
, OwningNode ( InParams . OwningNode )
{
}
bool FBaseInputController : : IsValid ( ) const
{
return OwningNode - > IsValid ( ) & & NodeVertexPtr . IsValid ( ) & & GraphPtr . IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseInputController : : GetID ( ) const
2021-01-13 10:48:59 -04:00
{
return ID ;
}
const FName & FBaseInputController : : GetDataType ( ) const
{
if ( NodeVertexPtr . IsValid ( ) )
{
return NodeVertexPtr - > TypeName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FName > ( ) ;
}
const FString & FBaseInputController : : GetName ( ) const
{
if ( NodeVertexPtr . IsValid ( ) )
{
return NodeVertexPtr - > Name ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FString > ( ) ;
}
bool FBaseInputController : : IsConnected ( ) const
{
return ( nullptr ! = FindEdge ( ) ) ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseInputController : : GetOwningNodeID ( ) const
2021-01-13 10:48:59 -04:00
{
return OwningNode - > GetID ( ) ;
}
FNodeHandle FBaseInputController : : GetOwningNode ( )
{
return OwningNode ;
}
FConstNodeHandle FBaseInputController : : GetOwningNode ( ) const
{
return OwningNode ;
}
FOutputHandle FBaseInputController : : GetCurrentlyConnectedOutput ( )
{
if ( const FMetasoundFrontendEdge * Edge = FindEdge ( ) )
{
// Create output handle from output node.
FGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
FNodeHandle OutputNode = Graph - > GetNodeWithID ( Edge - > FromNodeID ) ;
return OutputNode - > GetOutputWithID ( Edge - > FromPointID ) ;
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
FConstOutputHandle FBaseInputController : : GetCurrentlyConnectedOutput ( ) const
{
if ( const FMetasoundFrontendEdge * Edge = FindEdge ( ) )
{
// Create output handle from output node.
FConstGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
FConstNodeHandle OutputNode = Graph - > GetNodeWithID ( Edge - > FromNodeID ) ;
return OutputNode - > GetOutputWithID ( Edge - > FromPointID ) ;
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
FConnectability FBaseInputController : : CanConnectTo ( const IOutputController & InController ) const
{
FConnectability OutConnectability ;
OutConnectability . Connectable = FConnectability : : EConnectable : : No ;
if ( ! ( InController . IsValid ( ) & & IsValid ( ) ) )
{
return OutConnectability ;
}
if ( InController . GetDataType ( ) = = GetDataType ( ) )
{
// If data types are equal, connection can happen.
OutConnectability . Connectable = FConnectability : : EConnectable : : Yes ;
return OutConnectability ;
}
// If data types are not equal, check for converter nodes which could
// convert data type.
OutConnectability . PossibleConverterNodeClasses = FMetasoundFrontendRegistryContainer : : Get ( ) - > GetPossibleConverterNodes ( InController . GetDataType ( ) , GetDataType ( ) ) ;
if ( OutConnectability . PossibleConverterNodeClasses . Num ( ) > 0 )
{
OutConnectability . Connectable = FConnectability : : EConnectable : : YesWithConverterNode ;
return OutConnectability ;
}
return OutConnectability ;
}
bool FBaseInputController : : Connect ( IOutputController & InController )
{
if ( ! IsValid ( ) | | ! InController . IsValid ( ) )
{
return false ;
}
if ( ensureAlwaysMsgf ( InController . GetDataType ( ) = = GetDataType ( ) , TEXT ( " Cannot connect incompatible types. " ) ) )
{
// Overwrite an existing connection if it exists.
FMetasoundFrontendEdge * Edge = FindEdge ( ) ;
if ( ! Edge )
{
Edge = & GraphPtr - > Edges . AddDefaulted_GetRef ( ) ;
Edge - > ToNodeID = GetOwningNodeID ( ) ;
Edge - > ToPointID = GetID ( ) ;
}
Edge - > FromNodeID = InController . GetOwningNodeID ( ) ;
Edge - > FromPointID = InController . GetID ( ) ;
return true ;
}
return false ;
}
bool FBaseInputController : : ConnectWithConverterNode ( IOutputController & InController , const FConverterNodeInfo & InConverterInfo )
{
FGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
// Generate the converter node.
FNodeHandle ConverterNode = Graph - > AddNode ( InConverterInfo . NodeKey ) ;
// TODO: may want to rename Point -> Pin.
// TODO: fix naming confusion between "Pin" and "VertexKey". ConverterInfo should use vertexkey.
TArray < FInputHandle > ConverterInputs = ConverterNode - > GetInputsWithVertexName ( InConverterInfo . PreferredConverterInputPin ) ;
TArray < FOutputHandle > ConverterOutputs = ConverterNode - > GetOutputsWithVertexName ( InConverterInfo . PreferredConverterOutputPin ) ;
if ( ConverterInputs . Num ( ) < 1 )
{
2021-01-28 19:02:51 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Converter node [Name: %s] does not support preferred input vertex [Vertex: %s] " ) , * InConverterInfo . NodeKey . NodeClassFullName . ToString ( ) , * InConverterInfo . PreferredConverterInputPin ) ;
2021-01-13 10:48:59 -04:00
return false ;
}
if ( ConverterOutputs . Num ( ) < 1 )
{
2021-01-28 19:02:51 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Converter node [Name: %s] does not support preferred output vertex [Vertex: %s] " ) , * InConverterInfo . NodeKey . NodeClassFullName . ToString ( ) , * InConverterInfo . PreferredConverterOutputPin ) ;
2021-01-13 10:48:59 -04:00
return false ;
}
FInputHandle ConverterInput = ConverterInputs [ 0 ] ;
FOutputHandle ConverterOutput = ConverterOutputs [ 0 ] ;
// Connect the output InController to the converter, than connect the converter to this input.
if ( ConverterInput - > Connect ( InController ) & & Connect ( * ConverterOutput ) )
{
return true ;
}
return false ;
}
bool FBaseInputController : : Disconnect ( IOutputController & InController )
{
if ( GraphPtr . IsValid ( ) )
{
2021-01-20 17:26:40 -04:00
FGuid FromNodeID = InController . GetOwningNodeID ( ) ;
FGuid FromPointID = InController . GetID ( ) ;
FGuid ToNodeID = GetOwningNodeID ( ) ;
FGuid ToPointID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto IsMatchingEdge = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
return ( Edge . FromNodeID = = FromNodeID ) & & ( Edge . FromPointID = = FromPointID ) & & ( Edge . ToNodeID = = ToNodeID ) & & ( Edge . ToPointID = = ToPointID ) ;
} ;
int32 NumRemoved = GraphPtr - > Edges . RemoveAllSwap ( IsMatchingEdge ) ;
return NumRemoved > 0 ;
}
return false ;
}
bool FBaseInputController : : Disconnect ( )
{
if ( GraphPtr . IsValid ( ) )
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
FGuid PointID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToPointID = = PointID ) ;
} ;
int32 NumRemoved = GraphPtr - > Edges . RemoveAllSwap ( EdgeHasMatchingDestination ) ;
return NumRemoved > 0 ;
}
return false ;
}
const FMetasoundFrontendEdge * FBaseInputController : : FindEdge ( ) const
{
if ( GraphPtr . IsValid ( ) )
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
FGuid PointID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToPointID = = PointID ) ;
} ;
return GraphPtr - > Edges . FindByPredicate ( EdgeHasMatchingDestination ) ;
}
return nullptr ;
}
FMetasoundFrontendEdge * FBaseInputController : : FindEdge ( )
{
if ( GraphPtr . IsValid ( ) )
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
FGuid PointID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToPointID = = PointID ) ;
} ;
return GraphPtr - > Edges . FindByPredicate ( EdgeHasMatchingDestination ) ;
}
return nullptr ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FBaseInputController : : ShareAccess ( )
{
FDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
return Access ;
}
FConstDocumentAccess FBaseInputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
Access . ConstGraph = GraphPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FNodeInputController
//
FNodeInputController : : FNodeInputController ( const FNodeInputController : : FInitParams & InParams )
: FBaseInputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . GraphPtr , InParams . OwningNode } )
, OwningGraphClassInputPtr ( InParams . OwningGraphClassInputPtr )
{
}
bool FNodeInputController : : IsValid ( ) const
{
return FBaseInputController : : IsValid ( ) & & OwningGraphClassInputPtr . IsValid ( ) ;
}
const FText & FNodeInputController : : GetDisplayName ( ) const
{
if ( OwningGraphClassInputPtr . IsValid ( ) )
{
return OwningGraphClassInputPtr - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-02-03 14:36:36 -04:00
const TArray < FMetasoundFrontendVertexLiteral > & FNodeInputController : : GetDefaults ( ) const
{
if ( OwningGraphClassInputPtr . IsValid ( ) )
{
return OwningGraphClassInputPtr - > Defaults ;
}
static const TArray < FMetasoundFrontendVertexLiteral > InvalidDefaults ;
return InvalidDefaults ;
}
2021-01-13 10:48:59 -04:00
const FText & FNodeInputController : : GetTooltip ( ) const
{
if ( OwningGraphClassInputPtr . IsValid ( ) )
{
return OwningGraphClassInputPtr - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FNodeInputController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseInputController : : ShareAccess ( ) ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
FConstDocumentAccess FNodeInputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseInputController : : ShareAccess ( ) ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FOutputNodeInputController
//
FOutputNodeInputController : : FOutputNodeInputController ( const FOutputNodeInputController : : FInitParams & InParams )
: FBaseInputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . GraphPtr , InParams . OwningNode } )
, OwningGraphClassOutputPtr ( InParams . OwningGraphClassOutputPtr )
{
}
bool FOutputNodeInputController : : IsValid ( ) const
{
return FBaseInputController : : IsValid ( ) & & OwningGraphClassOutputPtr . IsValid ( ) ;
}
const FText & FOutputNodeInputController : : GetDisplayName ( ) const
{
if ( OwningGraphClassOutputPtr . IsValid ( ) )
{
return OwningGraphClassOutputPtr - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FOutputNodeInputController : : GetTooltip ( ) const
{
if ( OwningGraphClassOutputPtr . IsValid ( ) )
{
return OwningGraphClassOutputPtr - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FOutputNodeInputController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseInputController : : ShareAccess ( ) ;
Access . ConstClassOutput = OwningGraphClassOutputPtr ;
return Access ;
}
FConstDocumentAccess FOutputNodeInputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseInputController : : ShareAccess ( ) ;
Access . ConstClassOutput = OwningGraphClassOutputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FBaseNodeController
//
FBaseNodeController : : FBaseNodeController ( const FBaseNodeController : : FInitParams & InParams )
: NodePtr ( InParams . NodePtr )
, ClassPtr ( InParams . ClassPtr )
, OwningGraph ( InParams . OwningGraph )
{
if ( NodePtr . IsValid ( ) & & ClassPtr . IsValid ( ) )
{
if ( NodePtr - > ClassID ! = ClassPtr - > ID )
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Changing node's class id from [ClassID:%s] to [ClassID:%s] " ) , * NodePtr - > ClassID . ToString ( ) , * ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
NodePtr - > ClassID = ClassPtr - > ID ;
}
}
}
bool FBaseNodeController : : IsValid ( ) const
{
return OwningGraph - > IsValid ( ) & & NodePtr . IsValid ( ) & & ClassPtr . IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseNodeController : : GetOwningGraphClassID ( ) const
2021-01-13 10:48:59 -04:00
{
return OwningGraph - > GetClassID ( ) ;
}
FGraphHandle FBaseNodeController : : GetOwningGraph ( )
{
return OwningGraph ;
}
FConstGraphHandle FBaseNodeController : : GetOwningGraph ( ) const
{
return OwningGraph ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseNodeController : : GetID ( ) const
2021-01-13 10:48:59 -04:00
{
if ( NodePtr . IsValid ( ) )
{
return NodePtr - > ID ;
}
return Metasound : : FrontendInvalidID ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseNodeController : : GetClassID ( ) const
2021-01-13 10:48:59 -04:00
{
if ( ClassPtr . IsValid ( ) )
{
return ClassPtr - > ID ;
}
return Metasound : : FrontendInvalidID ;
}
2021-01-28 19:02:51 -04:00
const FText & FBaseNodeController : : GetClassDisplayName ( ) const
{
if ( const FMetasoundFrontendClass * NodeClass = ClassPtr . Get ( ) )
{
return NodeClass - > Metadata . DisplayName ;
}
return FText : : GetEmpty ( ) ;
}
2021-01-13 10:48:59 -04:00
FMetasoundFrontendVersionNumber FBaseNodeController : : GetClassVersionNumber ( ) const
{
if ( ClassPtr . IsValid ( ) )
{
return ClassPtr - > Metadata . Version ;
}
return FMetasoundFrontendVersionNumber ( ) ;
}
2021-01-23 12:59:01 -04:00
const FMetasoundFrontendClassStyle & FBaseNodeController : : GetClassStyle ( ) const
2021-01-20 00:42:47 -04:00
{
if ( ClassPtr . IsValid ( ) )
{
2021-01-23 12:59:01 -04:00
return ClassPtr - > Style ;
2021-01-20 00:42:47 -04:00
}
2021-01-23 12:59:01 -04:00
static const FMetasoundFrontendClassStyle Invalid ;
return Invalid ;
}
const FMetasoundFrontendNodeStyle & FBaseNodeController : : GetNodeStyle ( ) const
{
if ( NodePtr . IsValid ( ) )
{
return NodePtr - > Style ;
}
static const FMetasoundFrontendNodeStyle Invalid ;
return Invalid ;
}
void FBaseNodeController : : SetNodeStyle ( const FMetasoundFrontendNodeStyle & InStyle )
{
if ( ClassPtr . IsValid ( ) )
{
NodePtr - > Style = InStyle ;
}
2021-01-20 00:42:47 -04:00
}
2021-01-13 10:48:59 -04:00
const FText & FBaseNodeController : : GetClassDescription ( ) const
{
if ( ClassPtr . IsValid ( ) )
{
return ClassPtr - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FString & FBaseNodeController : : GetNodeName ( ) const
{
if ( NodePtr . IsValid ( ) )
{
return NodePtr - > Name ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FString > ( ) ;
}
EMetasoundFrontendClassType FBaseNodeController : : GetClassType ( ) const
{
if ( ClassPtr . IsValid ( ) )
{
return ClassPtr - > Metadata . Type ;
}
return EMetasoundFrontendClassType : : Invalid ;
}
2021-01-28 19:02:51 -04:00
const FMetasoundFrontendClassName & FBaseNodeController : : GetClassName ( ) const
2021-01-13 10:48:59 -04:00
{
if ( ClassPtr . IsValid ( ) )
{
2021-01-28 19:02:51 -04:00
return ClassPtr - > Metadata . ClassName ;
2021-01-13 10:48:59 -04:00
}
2021-01-28 19:02:51 -04:00
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendClassName > ( ) ;
2021-01-13 10:48:59 -04:00
}
bool FBaseNodeController : : CanAddInput ( const FString & InVertexName ) const
{
// TODO: not yet supported
return false ;
}
FInputHandle FBaseNodeController : : AddInput ( const FString & InVertexName , const FMetasoundFrontendLiteral * InDefault )
{
checkNoEntry ( ) ;
// TODO: not yet supported
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
bool FBaseNodeController : : RemoveInput ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
checkNoEntry ( ) ;
// TODO: not yet supported
return false ;
}
bool FBaseNodeController : : CanAddOutput ( const FString & InVertexName ) const
{
// TODO: not yet supported
return false ;
}
FInputHandle FBaseNodeController : : AddOutput ( const FString & InVertexName , const FMetasoundFrontendLiteral * InDefault )
{
checkNoEntry ( ) ;
// TODO: not yet supported
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
bool FBaseNodeController : : RemoveOutput ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
checkNoEntry ( ) ;
// TODO: not yet supported
return false ;
}
TArray < FInputHandle > FBaseNodeController : : GetInputs ( )
{
TArray < FInputHandle > Inputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FInputControllerParams & Params : GetInputControllerParams ( ) )
{
FInputHandle InputHandle = CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
TArray < FOutputHandle > FBaseNodeController : : GetOutputs ( )
{
TArray < FOutputHandle > Outputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FOutputControllerParams & Params : GetOutputControllerParams ( ) )
{
FOutputHandle OutputHandle = CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
TArray < FConstInputHandle > FBaseNodeController : : GetConstInputs ( ) const
{
TArray < FConstInputHandle > Inputs ;
// If I had a nickle for every time C++ backed me into a corner, I would be sitting
// on a tropical beach next to my mansion sipping strawberry daiquiris instead of
// trying to code using this guileful language. The const cast is generally safe here
// because the FConstInputHandle only allows const access to the internal node controller.
// Ostensibly, there could have been a INodeController and IConstNodeController
// which take different types in their constructor, but it starts to become
// difficult to maintain. So instead of adding 500 lines of nearly duplicate
// code, a ConstCastSharedRef is used here.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
for ( const FInputControllerParams & Params : GetInputControllerParams ( ) )
{
FConstInputHandle InputHandle = CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
TArray < FConstOutputHandle > FBaseNodeController : : GetConstOutputs ( ) const
{
TArray < FConstOutputHandle > Outputs ;
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
for ( const FOutputControllerParams & Params : GetOutputControllerParams ( ) )
{
FConstOutputHandle OutputHandle = CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
TArray < FInputHandle > FBaseNodeController : : GetInputsWithVertexName ( const FString & InName )
{
TArray < FInputHandle > Inputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FInputControllerParams & Params : GetInputControllerParamsWithVertexName ( InName ) )
{
FInputHandle InputHandle = CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
TArray < FConstInputHandle > FBaseNodeController : : GetInputsWithVertexName ( const FString & InName ) const
{
TArray < FConstInputHandle > Inputs ;
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
for ( const FInputControllerParams & Params : GetInputControllerParamsWithVertexName ( InName ) )
{
FInputHandle InputHandle = CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
TArray < FOutputHandle > FBaseNodeController : : GetOutputsWithVertexName ( const FString & InName )
{
TArray < FOutputHandle > Outputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FOutputControllerParams & Params : GetOutputControllerParamsWithVertexName ( InName ) )
{
FOutputHandle OutputHandle = CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
TArray < FConstOutputHandle > FBaseNodeController : : GetOutputsWithVertexName ( const FString & InName ) const
{
TArray < FConstOutputHandle > Outputs ;
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
for ( const FOutputControllerParams & Params : GetOutputControllerParamsWithVertexName ( InName ) )
{
FConstOutputHandle OutputHandle = CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
2021-01-20 17:26:40 -04:00
FInputHandle FBaseNodeController : : GetInputWithID ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
FInputControllerParams Params ;
if ( FindInputControllerParamsWithID ( InPointID , Params ) )
{
FNodeHandle ThisNode = this - > AsShared ( ) ;
return CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
}
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FConstInputHandle FBaseNodeController : : GetInputWithID ( FGuid InPointID ) const
2021-01-13 10:48:59 -04:00
{
FInputControllerParams Params ;
if ( FindInputControllerParamsWithID ( InPointID , Params ) )
{
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
return CreateInputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
}
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FOutputHandle FBaseNodeController : : GetOutputWithID ( FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
FOutputControllerParams Params ;
if ( FindOutputControllerParamsWithID ( InPointID , Params ) )
{
FNodeHandle ThisNode = this - > AsShared ( ) ;
return CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FConstOutputHandle FBaseNodeController : : GetOutputWithID ( FGuid InPointID ) const
2021-01-13 10:48:59 -04:00
{
FOutputControllerParams Params ;
if ( FindOutputControllerParamsWithID ( InPointID , Params ) )
{
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
return CreateOutputController ( Params . PointID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
TArray < FBaseNodeController : : FInputControllerParams > FBaseNodeController : : GetInputControllerParams ( ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FBaseNodeController : : FInputControllerParams > Inputs ;
if ( NodePtr . IsValid ( ) )
{
for ( const FMetasoundFrontendVertex & NodeInputVertex : NodePtr - > Interface . Inputs )
{
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetNodeInputFromNodeWithName ( NodeInputVertex . Name ) ) ;
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassInput > ( FGetClassInputFromClassWithName ( NodeInputVertex . Name ) ) ;
2021-01-20 17:26:40 -04:00
for ( const FGuid & PointID : NodeInputVertex . PointIDs )
2021-01-13 10:48:59 -04:00
{
Inputs . Add ( { PointID , NodeVertexPtr , ClassInputPtr } ) ;
}
}
}
return Inputs ;
}
TArray < FBaseNodeController : : FOutputControllerParams > FBaseNodeController : : GetOutputControllerParams ( ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FBaseNodeController : : FOutputControllerParams > Outputs ;
for ( const FMetasoundFrontendVertex & NodeOutputVertex : NodePtr - > Interface . Outputs )
{
const FString & VertexName = NodeOutputVertex . Name ;
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetConstNodeOutputFromNodeWithName ( VertexName ) ) ;
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassOutput > ( FGetClassOutputFromClassWithName ( VertexName ) ) ;
2021-01-20 17:26:40 -04:00
for ( const FGuid & PointID : NodeOutputVertex . PointIDs )
2021-01-13 10:48:59 -04:00
{
Outputs . Add ( { PointID , NodeVertexPtr , ClassOutputPtr } ) ;
}
}
return Outputs ;
}
TArray < FBaseNodeController : : FInputControllerParams > FBaseNodeController : : GetInputControllerParamsWithVertexName ( const FString & InName ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FBaseNodeController : : FInputControllerParams > Inputs ;
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetConstNodeInputFromNodeWithName ( InName ) ) ;
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassInput > ( FGetClassInputFromClassWithName ( InName ) ) ;
2021-01-20 17:26:40 -04:00
for ( const FGuid & PointID : Vertex - > PointIDs )
2021-01-13 10:48:59 -04:00
{
Inputs . Add ( { PointID , NodeVertexPtr , ClassInputPtr } ) ;
}
}
return Inputs ;
}
TArray < FBaseNodeController : : FOutputControllerParams > FBaseNodeController : : GetOutputControllerParamsWithVertexName ( const FString & InName ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FBaseNodeController : : FOutputControllerParams > Outputs ;
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetConstNodeOutputFromNodeWithName ( InName ) ) ;
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassOutput > ( FGetClassOutputFromClassWithName ( InName ) ) ;
2021-01-20 17:26:40 -04:00
for ( const FGuid & PointID : Vertex - > PointIDs )
2021-01-13 10:48:59 -04:00
{
Outputs . Add ( { PointID , NodeVertexPtr , ClassOutputPtr } ) ;
}
}
return Outputs ;
}
2021-01-20 17:26:40 -04:00
bool FBaseNodeController : : FindInputControllerParamsWithID ( FGuid InPointID , FInputControllerParams & OutParams ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetConstNodeInputFromNodeWithPoint ( InPointID ) ) ;
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassInput > ( FGetClassInputFromClassWithName ( Vertex - > Name ) ) ;
OutParams = FInputControllerParams { InPointID , NodeVertexPtr , ClassInputPtr } ;
return true ;
}
return false ;
}
2021-01-20 17:26:40 -04:00
bool FBaseNodeController : : FindOutputControllerParamsWithID ( FGuid InPointID , FOutputControllerParams & OutParams ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetMemberAccessPtr < const FMetasoundFrontendVertex > ( FGetConstNodeOutputFromNodeWithPoint ( InPointID ) ) ;
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassOutput > ( FGetClassOutputFromClassWithName ( Vertex - > Name ) ) ;
OutParams = FOutputControllerParams { InPointID , NodeVertexPtr , ClassOutputPtr } ;
return true ;
}
return false ;
}
const FMetasoundFrontendClassInput * FBaseNodeController : : FindClassInputWithName ( const FString & InName ) const
{
if ( ClassPtr . IsValid ( ) )
{
auto IsClassInputWithName = [ & ] ( const FMetasoundFrontendClassInput & ClassInput ) { return ClassInput . Name = = InName ; } ;
return ClassPtr - > Interface . Inputs . FindByPredicate ( IsClassInputWithName ) ;
}
return nullptr ;
}
const FMetasoundFrontendClassOutput * FBaseNodeController : : FindClassOutputWithName ( const FString & InName ) const
{
if ( ClassPtr . IsValid ( ) )
{
auto IsClassOutputWithName = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput ) { return ClassOutput . Name = = InName ; } ;
return ClassPtr - > Interface . Outputs . FindByPredicate ( IsClassOutputWithName ) ;
}
return nullptr ;
}
const FMetasoundFrontendVertex * FBaseNodeController : : FindNodeInputWithName ( const FString & InName ) const
{
if ( NodePtr . IsValid ( ) )
{
auto IsNodeInputWithName = [ & ] ( const FMetasoundFrontendVertex & NodeInput ) { return NodeInput . Name = = InName ; } ;
return NodePtr - > Interface . Inputs . FindByPredicate ( IsNodeInputWithName ) ;
}
return nullptr ;
}
const FMetasoundFrontendVertex * FBaseNodeController : : FindNodeOutputWithName ( const FString & InName ) const
{
if ( NodePtr . IsValid ( ) )
{
auto IsNodeOutputWithName = [ & ] ( const FMetasoundFrontendVertex & NodeOutput ) { return NodeOutput . Name = = InName ; } ;
return NodePtr - > Interface . Outputs . FindByPredicate ( IsNodeOutputWithName ) ;
}
return nullptr ;
}
FGraphHandle FBaseNodeController : : AsGraph ( )
{
// TODO: consider adding support for external graph owned in another document.
// Will require lookup support for external subgraphs..
if ( ClassPtr . IsValid ( ) )
{
return GetOwningGraph ( ) - > GetOwningDocument ( ) - > GetSubgraphWithClassID ( ClassPtr - > ID ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FBaseNodeController : : AsGraph ( ) const
{
// TODO: add support for graph owned in another asset.
// Will require lookup support for external subgraphs..
if ( ClassPtr . IsValid ( ) )
{
return GetOwningGraph ( ) - > GetOwningDocument ( ) - > GetSubgraphWithClassID ( ClassPtr - > ID ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FBaseNodeController : : ShareAccess ( )
{
FDocumentAccess Access ;
Access . Node = NodePtr ;
Access . ConstNode = NodePtr ;
Access . ConstClass = ClassPtr ;
return Access ;
}
FConstDocumentAccess FBaseNodeController : : ShareAccess ( ) const
{
FConstDocumentAccess Access ;
Access . ConstNode = NodePtr ;
Access . ConstClass = ClassPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FNodeController
//
FNodeController : : FNodeController ( EPrivateToken InToken , const FNodeController : : FInitParams & InParams )
: FBaseNodeController ( { InParams . NodePtr , InParams . ClassPtr , InParams . OwningGraph } )
, GraphPtr ( InParams . GraphPtr )
{
}
FNodeHandle FNodeController : : CreateNodeHandle ( const FNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
// Cannot make a valid node handle if the node description and class description differ
if ( InParams . NodePtr - > ClassID = = InParams . ClassPtr - > ID )
{
return MakeShared < FNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FNodeController : : CreateConstNodeHandle ( const FNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
// Cannot make a valid node handle if the node description and class description differ
if ( InParams . NodePtr - > ClassID = = InParams . ClassPtr - > ID )
{
return MakeShared < const FNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FNodeController : : IsValid ( ) const
{
return FBaseNodeController : : IsValid ( ) & & GraphPtr . IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FInputHandle FNodeController : : CreateInputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
return MakeShared < FNodeInputController > ( FNodeInputController : : FInitParams { InPointID , InNodeVertexPtr , InClassInputPtr , GraphPtr , InOwningNode } ) ;
}
2021-01-20 17:26:40 -04:00
FOutputHandle FNodeController : : CreateOutputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-01-22 03:05:22 -04:00
return MakeShared < FNodeOutputController > ( FNodeOutputController : : FInitParams { InPointID , InNodeVertexPtr , InClassOutputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FNodeController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
return Access ;
}
FConstDocumentAccess FNodeController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . ConstGraph = GraphPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FOutputNodeController
//
FOutputNodeController : : FOutputNodeController ( FOutputNodeController : : EPrivateToken InToken , const FOutputNodeController : : FInitParams & InParams )
: FBaseNodeController ( { InParams . NodePtr , InParams . ClassPtr , InParams . OwningGraph } )
, GraphPtr ( InParams . GraphPtr )
, OwningGraphClassOutputPtr ( InParams . OwningGraphClassOutputPtr )
{
}
FNodeHandle FOutputNodeController : : CreateOutputNodeHandle ( const FOutputNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
if ( EMetasoundFrontendClassType : : Output = = InParams . ClassPtr - > Metadata . Type )
{
if ( InParams . ClassPtr - > ID = = InParams . NodePtr - > ClassID )
{
return MakeShared < FOutputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating output node.. Must be EMetasoundFrontendClassType::Output. " ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FOutputNodeController : : CreateConstOutputNodeHandle ( const FOutputNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
if ( EMetasoundFrontendClassType : : Output = = InParams . ClassPtr - > Metadata . Type )
{
if ( InParams . ClassPtr - > ID = = InParams . NodePtr - > ClassID )
{
return MakeShared < const FOutputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating output node. Must be EMetasoundFrontendClassType::Output. " ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FOutputNodeController : : IsValid ( ) const
{
return OwningGraph - > IsValid ( ) & & OwningGraphClassOutputPtr . IsValid ( ) & & GraphPtr . IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FInputHandle FOutputNodeController : : CreateInputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
return MakeShared < FOutputNodeInputController > ( FOutputNodeInputController : : FInitParams { InPointID , InNodeVertexPtr , OwningGraphClassOutputPtr , GraphPtr , InOwningNode } ) ;
}
2021-01-20 17:26:40 -04:00
FOutputHandle FOutputNodeController : : CreateOutputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
return FInvalidOutputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FOutputNodeController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
Access . ConstClassOutput = OwningGraphClassOutputPtr ;
return Access ;
}
FConstDocumentAccess FOutputNodeController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . ConstGraph = GraphPtr ;
Access . ConstClassOutput = OwningGraphClassOutputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FInputNodeController
//
FInputNodeController : : FInputNodeController ( EPrivateToken InToken , const FInputNodeController : : FInitParams & InParams )
: FBaseNodeController ( { InParams . NodePtr , InParams . ClassPtr , InParams . OwningGraph } )
, OwningGraphClassInputPtr ( InParams . OwningGraphClassInputPtr )
, GraphPtr ( InParams . GraphPtr )
{
}
FNodeHandle FInputNodeController : : CreateInputNodeHandle ( const FInputNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
if ( EMetasoundFrontendClassType : : Input = = InParams . ClassPtr - > Metadata . Type )
{
if ( InParams . ClassPtr - > ID = = InParams . NodePtr - > ClassID )
{
return MakeShared < FInputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating input node. Must be EMetasoundFrontendClassType::Input. " ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FInputNodeController : : CreateConstInputNodeHandle ( const FInputNodeController : : FInitParams & InParams )
{
if ( InParams . NodePtr . IsValid ( ) & & InParams . ClassPtr . IsValid ( ) )
{
if ( EMetasoundFrontendClassType : : Input = = InParams . ClassPtr - > Metadata . Type )
{
if ( InParams . ClassPtr - > ID = = InParams . NodePtr - > ClassID )
{
return MakeShared < const FInputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * InParams . NodePtr - > ID . ToString ( ) , * InParams . NodePtr - > ClassID . ToString ( ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating input node. Must be EMetasoundFrontendClassType::Input. " ) , * InParams . ClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FInputNodeController : : IsValid ( ) const
{
return OwningGraph - > IsValid ( ) & & OwningGraphClassInputPtr . IsValid ( ) & & GraphPtr . IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FInputHandle FInputNodeController : : CreateInputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-01-20 17:26:40 -04:00
FOutputHandle FInputNodeController : : CreateOutputController ( FGuid InPointID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-01-22 03:05:22 -04:00
return MakeShared < FInputNodeOutputController > ( FInputNodeOutputController : : FInitParams { InPointID , InNodeVertexPtr , OwningGraphClassInputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FInputNodeController : : ShareAccess ( )
{
FDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
FConstDocumentAccess FInputNodeController : : ShareAccess ( ) const
{
FConstDocumentAccess Access = FBaseNodeController : : ShareAccess ( ) ;
Access . ConstGraph = GraphPtr ;
Access . ConstClassInput = OwningGraphClassInputPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FGraphController
//
FGraphController : : FGraphController ( EPrivateToken InToken , const FGraphController : : FInitParams & InParams )
: GraphClassPtr ( InParams . GraphClassPtr )
, OwningDocument ( InParams . OwningDocument )
{
}
FGraphHandle FGraphController : : CreateGraphHandle ( const FGraphController : : FInitParams & InParams )
{
if ( InParams . GraphClassPtr . IsValid ( ) )
{
if ( InParams . GraphClassPtr - > Metadata . Type = = EMetasoundFrontendClassType : : Graph )
{
return MakeShared < FGraphController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to make graph controller [ClassID:%s]. Class must be EMeatsoundFrontendClassType::Graph. " ) , * InParams . GraphClassPtr - > ID . ToString ( ) )
2021-01-13 10:48:59 -04:00
}
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FGraphController : : CreateConstGraphHandle ( const FGraphController : : FInitParams & InParams )
{
if ( InParams . GraphClassPtr . IsValid ( ) )
{
if ( InParams . GraphClassPtr - > Metadata . Type = = EMetasoundFrontendClassType : : Graph )
{
return MakeShared < FGraphController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to make graph controller [ClassID:%s]. Class must be EMeatsoundFrontendClassType::Graph. " ) , * InParams . GraphClassPtr - > ID . ToString ( ) )
2021-01-13 10:48:59 -04:00
}
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
bool FGraphController : : IsValid ( ) const
{
return GraphClassPtr . IsValid ( ) & & OwningDocument - > IsValid ( ) ;
}
2021-01-20 17:26:40 -04:00
FGuid FGraphController : : GetClassID ( ) const
2021-01-13 10:48:59 -04:00
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > ID ;
}
return Metasound : : FrontendInvalidID ;
}
2021-01-20 17:26:40 -04:00
FGuid FGraphController : : GetNewPointID ( ) const
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
return FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
}
TArray < FString > FGraphController : : GetInputVertexNames ( ) const
{
TArray < FString > Names ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( const FMetasoundFrontendClassInput & Input : GraphClassPtr - > Interface . Inputs )
{
Names . Add ( Input . Name ) ;
}
}
return Names ;
}
TArray < FString > FGraphController : : GetOutputVertexNames ( ) const
{
TArray < FString > Names ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( const FMetasoundFrontendClassOutput & Output : GraphClassPtr - > Interface . Outputs )
{
Names . Add ( Output . Name ) ;
}
}
return Names ;
}
FConstClassInputAccessPtr FGraphController : : FindClassInputWithName ( const FString & InName ) const
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendClassInput > ( FGetClassInputFromClassWithName ( InName ) ) ;
}
FConstClassOutputAccessPtr FGraphController : : FindClassOutputWithName ( const FString & InName ) const
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendClassOutput > ( FGetClassOutputFromClassWithName ( InName ) ) ;
}
2021-01-20 17:26:40 -04:00
TArray < FGuid > FGraphController : : GetDefaultIDsForInputVertex ( const FString & InInputName ) const
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendClassInput * Input = FindClassInputWithName ( InInputName ) . Get ( ) )
{
return Input - > PointIDs ;
}
2021-01-20 17:26:40 -04:00
return TArray < FGuid > ( ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
TArray < FGuid > FGraphController : : GetDefaultIDsForOutputVertex ( const FString & InOutputName ) const
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendClassOutput * Output = FindClassOutputWithName ( InOutputName ) . Get ( ) )
{
return Output - > PointIDs ;
}
2021-01-20 17:26:40 -04:00
return TArray < FGuid > ( ) ;
2021-01-13 10:48:59 -04:00
}
TArray < FNodeHandle > FGraphController : : GetNodes ( )
{
return GetNodeHandles ( GetNodesAndClasses ( ) ) ;
}
TArray < FConstNodeHandle > FGraphController : : GetConstNodes ( ) const
{
return GetNodeHandles ( GetNodesAndClasses ( ) ) ;
}
2021-01-20 17:26:40 -04:00
FConstNodeHandle FGraphController : : GetNodeWithID ( FGuid InNodeID ) const
2021-01-13 10:48:59 -04:00
{
auto IsNodeWithSameID = [ & ] ( const FMetasoundFrontendClass & NodeClas , const FMetasoundFrontendNode & Node )
{
return Node . ID = = InNodeID ;
} ;
return GetNodeByPredicate ( IsNodeWithSameID ) ;
}
2021-01-20 17:26:40 -04:00
FNodeHandle FGraphController : : GetNodeWithID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
auto IsNodeWithSameID = [ & ] ( const FMetasoundFrontendClass & NodeClas , const FMetasoundFrontendNode & Node )
{
return Node . ID = = InNodeID ;
} ;
return GetNodeByPredicate ( IsNodeWithSameID ) ;
}
TArray < FNodeHandle > FGraphController : : GetOutputNodes ( )
{
auto IsOutputNode = [ ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ;
} ;
return GetNodesByPredicate ( IsOutputNode ) ;
}
TArray < FNodeHandle > FGraphController : : GetInputNodes ( )
{
auto IsInputNode = [ ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ;
} ;
return GetNodesByPredicate ( IsInputNode ) ;
}
TArray < FConstNodeHandle > FGraphController : : GetConstOutputNodes ( ) const
{
auto IsOutputNode = [ ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ;
} ;
return GetNodesByPredicate ( IsOutputNode ) ;
}
TArray < FConstNodeHandle > FGraphController : : GetConstInputNodes ( ) const
{
auto IsInputNode = [ ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ;
} ;
return GetNodesByPredicate ( IsInputNode ) ;
}
2021-01-13 19:18:22 -04:00
bool FGraphController : : ContainsOutputVertexWithName ( const FString & InName ) const
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
auto IsOutputVertexWithSameName = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput )
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
return ClassOutput . Name = = InName ;
2021-01-13 10:48:59 -04:00
} ;
2021-01-13 19:18:22 -04:00
return GraphClass - > Interface . Outputs . ContainsByPredicate ( IsOutputVertexWithSameName ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-01-13 19:18:22 -04:00
bool FGraphController : : ContainsInputVertexWithName ( const FString & InName ) const
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
auto IsInputVertexWithSameName = [ & ] ( const FMetasoundFrontendClassInput & ClassInput )
2021-01-13 10:48:59 -04:00
{
2021-01-13 19:18:22 -04:00
return ClassInput . Name = = InName ;
2021-01-13 10:48:59 -04:00
} ;
2021-01-13 19:18:22 -04:00
return GraphClass - > Interface . Inputs . ContainsByPredicate ( IsInputVertexWithSameName ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
FConstNodeHandle FGraphController : : GetOutputNodeWithName ( const FString & InName ) const
{
auto IsOutputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return ( NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ) & & ( Node . Name = = InName ) ;
} ;
return GetNodeByPredicate ( IsOutputNodeWithSameName ) ;
}
FConstNodeHandle FGraphController : : GetInputNodeWithName ( const FString & InName ) const
{
auto IsInputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return ( NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ) & & ( Node . Name = = InName ) ;
} ;
return GetNodeByPredicate ( IsInputNodeWithSameName ) ;
}
FNodeHandle FGraphController : : GetOutputNodeWithName ( const FString & InName )
{
auto IsOutputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return ( NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ) & & ( Node . Name = = InName ) ;
} ;
return GetNodeByPredicate ( IsOutputNodeWithSameName ) ;
}
FNodeHandle FGraphController : : GetInputNodeWithName ( const FString & InName )
{
auto IsInputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & NodeClass , const FMetasoundFrontendNode & Node )
{
return ( NodeClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ) & & ( Node . Name = = InName ) ;
} ;
return GetNodeByPredicate ( IsInputNodeWithSameName ) ;
}
FNodeHandle FGraphController : : AddInputVertex ( const FMetasoundFrontendClassInput & InClassInput )
{
using namespace FrontendControllerIntrinsics ;
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
auto IsInputWithSameName = [ & ] ( const FMetasoundFrontendClassInput & ExistingDesc ) { return ExistingDesc . Name = = InClassInput . Name ; } ;
if ( Algo : : NoneOf ( GraphClass - > Interface . Inputs , IsInputWithSameName ) )
{
FMetasoundFrontendClassMetadata ClassMetadata ;
if ( FMetasoundFrontendRegistryContainer : : GetInputNodeClassMetadataForDataType ( InClassInput . TypeName , ClassMetadata ) )
{
if ( FConstClassAccessPtr InputClass = OwningDocument - > FindOrAddClass ( ClassMetadata ) )
{
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * InputClass ) ;
2021-01-13 19:18:22 -04:00
Node . Name = InClassInput . Name ;
2021-01-13 10:48:59 -04:00
Node . ID = NewNodeID ( ) ;
// TODO: have something that checks if input node has valid interface.
auto IsVertexWithTypeName = [ & ] ( FMetasoundFrontendVertex & Vertex ) { return Vertex . TypeName = = InClassInput . TypeName ; } ;
if ( FMetasoundFrontendVertex * InputVertex = Node . Interface . Inputs . FindByPredicate ( IsVertexWithTypeName ) )
{
InputVertex - > Name = InClassInput . Name ;
}
else
{
UE_LOG ( LogMetasound , Error , TEXT ( " Input node [TypeName:%s] does not contain input vertex with type [TypeName:%s] " ) , * InClassInput . TypeName . ToString ( ) , * InClassInput . TypeName . ToString ( ) ) ;
}
if ( FMetasoundFrontendVertex * OutputVertex = Node . Interface . Outputs . FindByPredicate ( IsVertexWithTypeName ) )
{
OutputVertex - > Name = InClassInput . Name ;
}
else
{
UE_LOG ( LogMetasound , Error , TEXT ( " Input node [TypeName:%s] does not contain input vertex with type [TypeName:%s] " ) , * InClassInput . TypeName . ToString ( ) , * InClassInput . TypeName . ToString ( ) ) ;
}
FMetasoundFrontendClassInput & NewInput = GraphClassPtr - > Interface . Inputs . Add_GetRef ( InClassInput ) ;
NewInput . NodeID = Node . ID ;
FNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendNode > ( FGetNodeFromGraphClassByNodeID ( Node . ID ) ) ;
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , InputClass } ) ;
}
}
else
{
UE_LOG ( LogMetasound , Display , TEXT ( " Failed to add input. No input node registered for data type [TypeName:%s] " ) , * InClassInput . TypeName . ToString ( ) ) ;
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Display , TEXT ( " Failed to add input. Input with same name \" %s \" exists in class [ClassID:%s] " ) , * InClassInput . Name , * GraphClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveInputVertex ( const FString & InName )
{
if ( GraphClassPtr . IsValid ( ) )
{
auto IsInputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & InClass , const FMetasoundFrontendNode & InNode )
{
return ( InClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ) & & ( InNode . Name = = InName ) ;
} ;
for ( const FNodeAndClass & NodeAndClass : GetNodesAndClassesByPredicate ( IsInputNodeWithSameName ) )
{
return RemoveInput ( * NodeAndClass . Node ) ;
}
}
return false ;
}
FNodeHandle FGraphController : : AddOutputVertex ( const FMetasoundFrontendClassOutput & InClassOutput )
{
using namespace FrontendControllerIntrinsics ;
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
auto IsOutputWithSameName = [ & ] ( const FMetasoundFrontendClassOutput & ExistingDesc ) { return ExistingDesc . Name = = InClassOutput . Name ; } ;
if ( Algo : : NoneOf ( GraphClass - > Interface . Outputs , IsOutputWithSameName ) )
{
FMetasoundFrontendClassMetadata ClassMetadata ;
if ( FMetasoundFrontendRegistryContainer : : GetOutputNodeClassMetadataForDataType ( InClassOutput . TypeName , ClassMetadata ) )
{
if ( FConstClassAccessPtr OutputClass = OwningDocument - > FindOrAddClass ( ClassMetadata ) )
{
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * OutputClass ) ;
2021-01-13 19:18:22 -04:00
Node . Name = InClassOutput . Name ;
2021-01-13 10:48:59 -04:00
Node . ID = NewNodeID ( ) ;
// TODO: have something that checks if input node has valid interface.
auto IsVertexWithTypeName = [ & ] ( FMetasoundFrontendVertex & Vertex ) { return Vertex . TypeName = = InClassOutput . TypeName ; } ;
if ( FMetasoundFrontendVertex * InputVertex = Node . Interface . Inputs . FindByPredicate ( IsVertexWithTypeName ) )
{
InputVertex - > Name = InClassOutput . Name ;
}
else
{
UE_LOG ( LogMetasound , Error , TEXT ( " Output node [TypeName:%s] does not contain input vertex with type [TypeName:%s] " ) , * InClassOutput . TypeName . ToString ( ) , * InClassOutput . TypeName . ToString ( ) ) ;
}
if ( FMetasoundFrontendVertex * OutputVertex = Node . Interface . Outputs . FindByPredicate ( IsVertexWithTypeName ) )
{
OutputVertex - > Name = InClassOutput . Name ;
}
else
{
UE_LOG ( LogMetasound , Error , TEXT ( " Output node [TypeName:%s] does not contain input vertex with type [TypeName:%s] " ) , * InClassOutput . TypeName . ToString ( ) , * InClassOutput . TypeName . ToString ( ) ) ;
}
FMetasoundFrontendClassOutput & NewOutput = GraphClassPtr - > Interface . Outputs . Add_GetRef ( InClassOutput ) ;
NewOutput . NodeID = Node . ID ;
FNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendNode > ( FGetNodeFromGraphClassByNodeID ( Node . ID ) ) ;
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , OutputClass } ) ;
}
}
else
{
UE_LOG ( LogMetasound , Display , TEXT ( " Failed to add output. No output node registered for data type [TypeName:%s] " ) , * InClassOutput . TypeName . ToString ( ) ) ;
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Display , TEXT ( " Failed to add output. Output with same name \" %s \" exists in class [ClassID:%s] " ) , * InClassOutput . Name , * GraphClassPtr - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveOutputVertex ( const FString & InName )
{
if ( GraphClassPtr . IsValid ( ) )
{
auto IsOutputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & InClass , const FMetasoundFrontendNode & InNode )
{
return ( InClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ) & & ( InNode . Name = = InName ) ;
} ;
for ( const FNodeAndClass & NodeAndClass : GetNodesAndClassesByPredicate ( IsOutputNodeWithSameName ) )
{
return RemoveOutput ( * NodeAndClass . Node ) ;
}
}
return false ;
}
// This can be used to determine what kind of property editor we should use for the data type of a given input.
// Will return Invalid if the input couldn't be found, or if the input doesn't support any kind of literals.
ELiteralType FGraphController : : GetPreferredLiteralTypeForInputVertex ( const FString & InInputName ) const
{
if ( const FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InInputName ) )
{
return FMetasoundFrontendRegistryContainer : : Get ( ) - > GetDesiredLiteralTypeForDataType ( Desc - > TypeName ) ;
}
return ELiteralType : : Invalid ;
}
// For inputs whose preferred literal type is UObject or UObjectArray, this can be used to determine the UObject corresponding to that input's datatype.
UClass * FGraphController : : GetSupportedClassForInputVertex ( const FString & InInputName )
{
if ( const FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InInputName ) )
{
return FMetasoundFrontendRegistryContainer : : Get ( ) - > GetLiteralUClassForDataType ( Desc - > TypeName ) ;
}
return nullptr ;
}
2021-02-03 14:36:36 -04:00
bool FGraphController : : SetDefaultInputToFrontendLiteral ( const FString & InInputName , FGuid InPointID , FName InDataTypeName , const FMetasoundFrontendLiteral & InLiteral )
2021-01-13 10:48:59 -04:00
{
2021-02-03 14:36:36 -04:00
switch ( InLiteral . Type )
{
case EMetasoundFrontendLiteralType : : Bool :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , InLiteral . AsBool ) ;
}
break ;
case EMetasoundFrontendLiteralType : : Float :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , InLiteral . AsFloat ) ;
}
break ;
case EMetasoundFrontendLiteralType : : Integer :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , InLiteral . AsInteger ) ;
}
break ;
case EMetasoundFrontendLiteralType : : String :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , InLiteral . AsString ) ;
}
break ;
case EMetasoundFrontendLiteralType : : UObject :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , InLiteral . AsUObject ) ;
}
break ;
// TODO: Remove as array support will not be specialized to object type
case EMetasoundFrontendLiteralType : : UObjectArray :
{
return false ;
}
break ;
case EMetasoundFrontendLiteralType : : Invalid :
case EMetasoundFrontendLiteralType : : None :
default :
{
2021-02-04 16:31:46 -04:00
static_assert ( static_cast < int32 > ( EMetasoundFrontendLiteralType : : Invalid ) = = 7 , " Possible missing ELiteralType case coverage " ) ;
2021-02-03 14:36:36 -04:00
return false ;
}
break ;
}
2021-01-13 10:48:59 -04:00
}
2021-02-03 14:36:36 -04:00
bool FGraphController : : SetDefaultInputToTypeDefaultLiteral ( const FString & InInputName , FGuid InPointID , FName InDataTypeName )
2021-01-13 10:48:59 -04:00
{
2021-02-03 14:36:36 -04:00
Metasound : : FLiteral LiteralParam = Frontend : : GetDefaultParamForDataType ( InDataTypeName ) ;
switch ( LiteralParam . GetType ( ) )
{
case ELiteralType : : Boolean :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , LiteralParam . Value . Get < bool > ( ) ) ;
}
break ;
2021-01-13 10:48:59 -04:00
2021-02-03 14:36:36 -04:00
case ELiteralType : : Float :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , LiteralParam . Value . Get < float > ( ) ) ;
}
break ;
2021-01-13 10:48:59 -04:00
2021-02-03 14:36:36 -04:00
case ELiteralType : : Integer :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , LiteralParam . Value . Get < int32 > ( ) ) ;
}
break ;
2021-01-13 10:48:59 -04:00
2021-02-03 14:36:36 -04:00
case ELiteralType : : String :
{
return SetDefaultInputToLiteralInternal ( InInputName , InPointID , LiteralParam . Value . Get < FString > ( ) ) ;
}
break ;
2021-01-13 10:48:59 -04:00
2021-02-03 14:36:36 -04:00
case ELiteralType : : None :
2021-02-04 16:31:46 -04:00
case ELiteralType : : UObjectProxy : // UObject literals do not currently support default data type references
case ELiteralType : : NoneArray :
case ELiteralType : : BooleanArray :
case ELiteralType : : IntegerArray :
case ELiteralType : : FloatArray :
case ELiteralType : : StringArray :
case ELiteralType : : UObjectProxyArray :
case ELiteralType : : Invalid :
2021-02-03 14:36:36 -04:00
default :
{
2021-02-04 16:31:46 -04:00
static_assert ( static_cast < int32 > ( ELiteralType : : Invalid ) = = 12 , " Possible missing ELiteralType case coverage " ) ;
2021-02-03 14:36:36 -04:00
return false ;
}
break ;
}
2021-01-13 10:48:59 -04:00
}
// Set the display name for the input with the given name
void FGraphController : : SetInputDisplayName ( FString InName , const FText & InDisplayName )
{
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InName ) )
{
Desc - > Metadata . DisplayName = InDisplayName ;
}
}
// Set the display name for the output with the given name
void FGraphController : : SetOutputDisplayName ( FString InName , const FText & InDisplayName )
{
if ( FMetasoundFrontendClassOutput * Desc = FindOutputDescriptionWithName ( InName ) )
{
Desc - > Metadata . DisplayName = InDisplayName ;
}
}
FMetasoundFrontendClassMetadata FGraphController : : CreateInputClassMetadata ( const FMetasoundFrontendClassInput & InClassInput )
{
FMetasoundFrontendClassMetadata ClassMetadata ;
FMetasoundFrontendRegistryContainer : : GetInputNodeClassMetadataForDataType ( InClassInput . TypeName , ClassMetadata ) ;
return ClassMetadata ;
}
FMetasoundFrontendClassMetadata FGraphController : : CreateOutputClassMetadata ( const FMetasoundFrontendClassOutput & InClassOutput )
{
FMetasoundFrontendClassMetadata ClassMetadata ;
FMetasoundFrontendRegistryContainer : : GetOutputNodeClassMetadataForDataType ( InClassOutput . TypeName , ClassMetadata ) ;
return ClassMetadata ;
}
// This can be used to clear the current literal for a given input.
// @returns false if the input name couldn't be found.
2021-01-20 17:26:40 -04:00
bool FGraphController : : ClearLiteralForInput ( const FString & InInputName , FGuid InPointID )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InInputName ) )
{
auto IsLiteralWithSamePointID = [ & ] ( const FMetasoundFrontendVertexLiteral & InVertexLiteral )
{
return InVertexLiteral . PointID = = InPointID ;
} ;
if ( FMetasoundFrontendVertexLiteral * VertexLiteral = Desc - > Defaults . FindByPredicate ( IsLiteralWithSamePointID ) )
{
VertexLiteral - > Value . Clear ( ) ;
return true ;
}
}
return false ;
}
FNodeHandle FGraphController : : AddNode ( const FNodeClassInfo & InNodeClass )
{
if ( IsValid ( ) )
{
if ( FConstClassAccessPtr DependencyDescription = OwningDocument - > FindOrAddClass ( InNodeClass ) )
{
return AddNode ( DependencyDescription ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FNodeHandle FGraphController : : AddNode ( const FNodeRegistryKey & InNodeClass )
{
// Construct a FNodeClassInfo from this lookup key.
FNodeClassInfo ClassInfo ;
ClassInfo . LookupKey = InNodeClass ;
ClassInfo . NodeType = EMetasoundFrontendClassType : : External ;
return AddNode ( ClassInfo ) ;
}
2021-01-22 03:05:22 -04:00
FNodeHandle FGraphController : : AddNode ( const FMetasoundFrontendClassMetadata & InClassMetadata )
{
return AddNode ( FMetasoundFrontendRegistryContainer
: : GetRegistryKey ( InClassMetadata ) ) ;
}
2021-01-13 10:48:59 -04:00
// Remove the node corresponding to this node handle.
// On success, invalidates the received node handle.
bool FGraphController : : RemoveNode ( INodeController & InNode )
{
2021-01-20 17:26:40 -04:00
FGuid NodeID = InNode . GetID ( ) ;
2021-01-13 10:48:59 -04:00
const EMetasoundFrontendClassType NodeType = InNode . GetClassType ( ) ;
auto IsNodeWithSameID = [ & ] ( const FMetasoundFrontendNode & InDesc ) { return InDesc . ID = = NodeID ; } ;
if ( const FMetasoundFrontendNode * Desc = GraphClassPtr - > Graph . Nodes . FindByPredicate ( IsNodeWithSameID ) )
{
if ( EMetasoundFrontendClassType : : Input = = NodeType )
{
return RemoveInput ( * Desc ) ;
}
else if ( EMetasoundFrontendClassType : : Output = = NodeType )
{
return RemoveOutput ( * Desc ) ;
}
else
{
return RemoveNode ( * Desc ) ;
}
}
return false ;
}
// Returns the metadata for the current graph, including the name, description and author.
const FMetasoundFrontendClassMetadata & FGraphController : : GetGraphMetadata ( ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > Metadata ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendClassMetadata > ( ) ;
}
bool FGraphController : : InflateNodeDirectlyIntoGraph ( const INodeController & InNode )
{
// TODO: implement
checkNoEntry ( ) ;
return false ;
}
FNodeHandle FGraphController : : CreateEmptySubgraph ( const FMetasoundFrontendClassMetadata & InInfo )
{
if ( IsValid ( ) )
{
if ( InInfo . Type = = EMetasoundFrontendClassType : : Graph )
{
if ( const FMetasoundFrontendClass * ExistingDependency = OwningDocument - > FindClass ( InInfo ) . Get ( ) )
{
2021-01-28 19:02:51 -04:00
UE_LOG ( LogMetasound , Error , TEXT ( " Cannot add new subgraph. Metasound class already exists with matching metadata Name: \" %s \" , Version %d.%d " ) , * ( ExistingDependency - > Metadata . ClassName . GetFullName ( ) . ToString ( ) ) , ExistingDependency - > Metadata . Version . Major , ExistingDependency - > Metadata . Version . Minor ) ;
2021-01-13 10:48:59 -04:00
}
//else if (const FMetasoundFrontendClass* DependencyDescription = OwningDocument->FindOrAddClass(InInfo))
else if ( FConstClassAccessPtr DependencyDescription = OwningDocument - > FindOrAddClass ( InInfo ) )
{
return AddNode ( DependencyDescription ) ;
}
}
else
{
UE_LOG ( LogMetasound , Warning , TEXT ( " Incompatible Metasound NodeType encountered when attempting to create an empty subgraph. NodeType must equal EMetasoundFrontendClassType::Graph " ) ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
TUniquePtr < IOperator > FGraphController : : BuildOperator ( const FOperatorSettings & InSettings , const FMetasoundEnvironment & InEnvironment , TArray < IOperatorBuilder : : FBuildErrorPtr > & OutBuildErrors ) const
{
if ( ! IsValid ( ) )
{
return TUniquePtr < IOperator > ( nullptr ) ;
}
// TODO: Implement inflation step here.
// TODO: bubble up errors.
TArray < FMetasoundFrontendGraphClass > Subgraphs = OwningDocument - > GetSubgraphs ( ) ;
TArray < FMetasoundFrontendClass > Dependencies = OwningDocument - > GetDependencies ( ) ;
FFrontendGraphBuilder GraphBuilder ;
TUniquePtr < FFrontendGraph > Graph = GraphBuilder . CreateGraph ( * GraphClassPtr , Subgraphs , Dependencies ) ;
if ( ! Graph . IsValid ( ) )
{
return TUniquePtr < IOperator > ( nullptr ) ;
}
// Step 5: Invoke Operator Builder
FOperatorBuilder OperatorBuilder ( FOperatorBuilderSettings : : GetDefaultSettings ( ) ) ;
return OperatorBuilder . BuildGraphOperator ( * Graph , InSettings , InEnvironment , OutBuildErrors ) ;
}
FDocumentHandle FGraphController : : GetOwningDocument ( )
{
return OwningDocument ;
}
FConstDocumentHandle FGraphController : : GetOwningDocument ( ) const
{
return OwningDocument ;
}
FNodeHandle FGraphController : : AddNode ( FConstClassAccessPtr InExistingDependency )
{
using namespace FrontendControllerIntrinsics ;
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
if ( const FMetasoundFrontendClass * NodeClass = InExistingDependency . Get ( ) )
{
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * InExistingDependency ) ;
Node . ID = NewNodeID ( ) ;
FNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendNode > ( FGetNodeFromGraphClassByNodeID ( Node . ID ) ) ;
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , InExistingDependency } ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveNode ( const FMetasoundFrontendNode & InDesc )
{
if ( GraphClassPtr . IsValid ( ) )
{
2021-02-04 16:31:46 -04:00
auto IsEdgeForThisNode = [ & ] ( const FMetasoundFrontendEdge & ConDesc ) { return ( ConDesc . FromNodeID = = InDesc . ID ) | | ( ConDesc . ToNodeID = = InDesc . ID ) ; } ;
2021-01-13 10:48:59 -04:00
// Remove any reference connections
2021-02-04 16:31:46 -04:00
int32 NumRemoved = GraphClassPtr - > Graph . Edges . RemoveAll ( IsEdgeForThisNode ) ;
2021-01-13 10:48:59 -04:00
auto IsNodeWithID = [ & ] ( const FMetasoundFrontendNode & Desc ) { return InDesc . ID = = Desc . ID ; } ;
2021-02-04 16:31:46 -04:00
NumRemoved + = GraphClassPtr - > Graph . Nodes . RemoveAll ( IsNodeWithID ) ;
2021-01-13 10:48:59 -04:00
OwningDocument - > RemoveUnreferencedDependencies ( ) ;
return ( NumRemoved > 0 ) ;
}
return false ;
}
bool FGraphController : : RemoveInput ( const FMetasoundFrontendNode & InNode )
{
if ( GraphClassPtr . IsValid ( ) )
{
auto IsInputWithSameNodeID = [ & ] ( const FMetasoundFrontendClassInput & ClassInput ) { return ClassInput . NodeID = = InNode . ID ; } ;
int32 NumInputsRemoved = GraphClassPtr - > Interface . Inputs . RemoveAll ( IsInputWithSameNodeID ) ;
bool bDidRemoveNode = RemoveNode ( InNode ) ;
return ( NumInputsRemoved > 0 ) | | bDidRemoveNode ;
}
return false ;
}
bool FGraphController : : RemoveOutput ( const FMetasoundFrontendNode & InNode )
{
if ( GraphClassPtr . IsValid ( ) )
{
auto IsOutputWithSameNodeID = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput ) { return ClassOutput . NodeID = = InNode . ID ; } ;
int32 NumOutputsRemoved = GraphClassPtr - > Interface . Outputs . RemoveAll ( IsOutputWithSameNodeID ) ;
bool bDidRemoveNode = RemoveNode ( InNode ) ;
return ( NumOutputsRemoved > 0 ) | | bDidRemoveNode ;
}
return false ;
}
2021-01-20 17:26:40 -04:00
FGuid FGraphController : : NewNodeID ( ) const
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
return FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
}
bool FGraphController : : ContainsNodesAndClassesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
for ( FMetasoundFrontendNode & Node : GraphClassPtr - > Graph . Nodes )
{
const FMetasoundFrontendClass * NodeClass = OwningDocument - > FindClassWithID ( Node . ClassID ) . Get ( ) ;
if ( nullptr ! = NodeClass )
{
if ( InPredicate ( * NodeClass , Node ) )
{
return true ;
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return false ;
}
TArray < FGraphController : : FNodeAndClass > FGraphController : : GetNodesAndClasses ( )
{
using namespace FrontendControllerIntrinsics ;
TArray < FNodeAndClass > NodesAndClasses ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( FMetasoundFrontendNode & Node : GraphClassPtr - > Graph . Nodes )
{
FNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendNode > ( FGetNodeFromGraphClassByNodeID ( Node . ID ) ) ;
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
2021-01-20 17:26:40 -04:00
2021-01-13 10:48:59 -04:00
if ( NodeClassPtr & & NodePtr )
{
NodesAndClasses . Add ( FGraphController : : FNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return NodesAndClasses ;
}
TArray < FGraphController : : FConstNodeAndClass > FGraphController : : GetNodesAndClasses ( ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FConstNodeAndClass > NodesAndClasses ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( const FMetasoundFrontendNode & Node : GraphClassPtr - > Graph . Nodes )
{
FConstNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < const FMetasoundFrontendNode > ( FGetConstNodeFromGraphClassByNodeID ( Node . ID ) ) ;
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
2021-01-20 17:26:40 -04:00
2021-01-13 10:48:59 -04:00
if ( NodeClassPtr & & NodePtr )
{
NodesAndClasses . Add ( FGraphController : : FConstNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return NodesAndClasses ;
}
TArray < FGraphController : : FNodeAndClass > FGraphController : : GetNodesAndClassesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate )
{
using namespace FrontendControllerIntrinsics ;
TArray < FNodeAndClass > NodesAndClasses ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( FMetasoundFrontendNode & Node : GraphClassPtr - > Graph . Nodes )
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InPredicate ( * NodeClass , Node ) )
{
FNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendNode > ( FGetNodeFromGraphClassByNodeID ( Node . ID ) ) ;
NodesAndClasses . Add ( FGraphController : : FNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return NodesAndClasses ;
}
TArray < FGraphController : : FConstNodeAndClass > FGraphController : : GetNodesAndClassesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate ) const
{
using namespace FrontendControllerIntrinsics ;
TArray < FConstNodeAndClass > NodesAndClasses ;
if ( GraphClassPtr . IsValid ( ) )
{
for ( const FMetasoundFrontendNode & Node : GraphClassPtr - > Graph . Nodes )
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InPredicate ( * NodeClass , Node ) )
{
FConstNodeAccessPtr NodePtr = GraphClassPtr . GetMemberAccessPtr < const FMetasoundFrontendNode > ( FGetConstNodeFromGraphClassByNodeID ( Node . ID ) ) ;
NodesAndClasses . Add ( FGraphController : : FConstNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
}
else
{
2021-01-20 17:26:40 -04:00
UE_LOG ( LogMetasound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return NodesAndClasses ;
}
FNodeHandle FGraphController : : GetNodeByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate )
{
if ( GraphClassPtr . IsValid ( ) )
{
TArray < FNodeAndClass > NodeAndClass = GetNodesAndClassesByPredicate ( InPredicate ) ;
if ( NodeAndClass . Num ( ) > 0 )
{
return GetNodeHandle ( NodeAndClass [ 0 ] ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FGraphController : : GetNodeByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
TArray < FConstNodeAndClass > NodeAndClass = GetNodesAndClassesByPredicate ( InPredicate ) ;
if ( NodeAndClass . Num ( ) > 0 )
{
return GetNodeHandle ( NodeAndClass [ 0 ] ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
TArray < FNodeHandle > FGraphController : : GetNodesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InFilterFunc )
{
if ( GraphClassPtr . IsValid ( ) )
{
return GetNodeHandles ( GetNodesAndClassesByPredicate ( InFilterFunc ) ) ;
}
return TArray < FNodeHandle > ( ) ;
}
TArray < FConstNodeHandle > FGraphController : : GetNodesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InFilterFunc ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
return GetNodeHandles ( GetNodesAndClassesByPredicate ( InFilterFunc ) ) ;
}
return TArray < FConstNodeHandle > ( ) ;
}
TArray < FNodeHandle > FGraphController : : GetNodeHandles ( TArrayView < const FGraphController : : FNodeAndClass > InNodesAndClasses )
{
TArray < FNodeHandle > Nodes ;
for ( const FNodeAndClass & NodeAndClass : InNodesAndClasses )
{
FNodeHandle NodeController = GetNodeHandle ( NodeAndClass ) ;
if ( NodeController - > IsValid ( ) )
{
Nodes . Add ( NodeController ) ;
}
}
return Nodes ;
}
TArray < FConstNodeHandle > FGraphController : : GetNodeHandles ( TArrayView < const FGraphController : : FConstNodeAndClass > InNodesAndClasses ) const
{
TArray < FConstNodeHandle > Nodes ;
for ( const FConstNodeAndClass & NodeAndClass : InNodesAndClasses )
{
FConstNodeHandle NodeController = GetNodeHandle ( NodeAndClass ) ;
if ( NodeController - > IsValid ( ) )
{
Nodes . Add ( NodeController ) ;
}
}
return Nodes ;
}
FNodeHandle FGraphController : : GetNodeHandle ( const FGraphController : : FNodeAndClass & InNodeAndClass )
{
using namespace FrontendControllerIntrinsics ;
if ( InNodeAndClass . IsValid ( ) & & GraphClassPtr . IsValid ( ) )
{
FGraphHandle OwningGraph = this - > AsShared ( ) ;
FGraphAccessPtr GraphPtr = GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendGraph > ( FGetGraphFromGraphClass ( ) ) ;
switch ( InNodeAndClass . Class - > Metadata . Type )
{
case EMetasoundFrontendClassType : : Input :
if ( FClassInputAccessPtr OwningGraphClassInputPtr = FindInputDescriptionWithNodeID ( InNodeAndClass . Node - > ID ) )
{
FInputNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
OwningGraphClassInputPtr ,
GraphPtr ,
OwningGraph
} ;
return FInputNodeController : : CreateInputNodeHandle ( InitParams ) ;
}
break ;
case EMetasoundFrontendClassType : : Output :
if ( FClassOutputAccessPtr OwningGraphClassOutputPtr = FindOutputDescriptionWithNodeID ( InNodeAndClass . Node - > ID ) )
{
FOutputNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
OwningGraphClassOutputPtr ,
GraphPtr ,
OwningGraph
} ;
return FOutputNodeController : : CreateOutputNodeHandle ( InitParams ) ;
}
break ;
case EMetasoundFrontendClassType : : External :
case EMetasoundFrontendClassType : : Graph :
{
FNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
GraphPtr ,
OwningGraph
} ;
return FNodeController : : CreateNodeHandle ( InitParams ) ;
}
break ;
default :
checkNoEntry ( ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FGraphController : : GetNodeHandle ( const FGraphController : : FConstNodeAndClass & InNodeAndClass ) const
{
using namespace FrontendControllerIntrinsics ;
if ( InNodeAndClass . IsValid ( ) & & GraphClassPtr . IsValid ( ) )
{
FConstGraphHandle OwningGraph = this - > AsShared ( ) ;
FConstGraphAccessPtr GraphPtr = GraphClassPtr . GetMemberAccessPtr < const FMetasoundFrontendGraph > ( FGetConstGraphFromGraphClass ( ) ) ;
2021-01-20 17:26:40 -04:00
2021-01-13 10:48:59 -04:00
switch ( InNodeAndClass . Class - > Metadata . Type )
{
case EMetasoundFrontendClassType : : Input :
if ( FConstClassInputAccessPtr OwningGraphClassInputPtr = FindInputDescriptionWithNodeID ( InNodeAndClass . Node - > ID ) )
{
FInputNodeController : : FInitParams InitParams
{
ConstCastAccessPtr < FMetasoundFrontendNode > ( InNodeAndClass . Node ) ,
InNodeAndClass . Class ,
ConstCastAccessPtr < FMetasoundFrontendClassInput > ( OwningGraphClassInputPtr ) ,
ConstCastAccessPtr < FMetasoundFrontendGraph > ( GraphPtr ) ,
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FInputNodeController : : CreateConstInputNodeHandle ( InitParams ) ;
}
break ;
case EMetasoundFrontendClassType : : Output :
if ( FConstClassOutputAccessPtr OwningGraphClassOutputPtr = FindOutputDescriptionWithNodeID ( InNodeAndClass . Node - > ID ) )
{
FOutputNodeController : : FInitParams InitParams
{
ConstCastAccessPtr < FMetasoundFrontendNode > ( InNodeAndClass . Node ) ,
InNodeAndClass . Class ,
ConstCastAccessPtr < FMetasoundFrontendClassOutput > ( OwningGraphClassOutputPtr ) ,
ConstCastAccessPtr < FMetasoundFrontendGraph > ( GraphPtr ) ,
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FOutputNodeController : : CreateConstOutputNodeHandle ( InitParams ) ;
}
break ;
case EMetasoundFrontendClassType : : External :
case EMetasoundFrontendClassType : : Graph :
{
FNodeController : : FInitParams InitParams
{
ConstCastAccessPtr < FMetasoundFrontendNode > ( InNodeAndClass . Node ) ,
InNodeAndClass . Class ,
ConstCastAccessPtr < FMetasoundFrontendGraph > ( GraphPtr ) ,
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FNodeController : : CreateConstNodeHandle ( InitParams ) ;
}
break ;
default :
checkNoEntry ( ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithName ( const FString & InName )
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . Name = = InName ; } ) ;
}
return nullptr ;
}
const FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithName ( const FString & InName ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . Name = = InName ; } ) ;
}
return nullptr ;
}
FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithName ( const FString & InName )
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . Name = = InName ; } ) ;
}
return nullptr ;
}
const FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithName ( const FString & InName ) const
{
if ( GraphClassPtr . IsValid ( ) )
{
return GraphClassPtr - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . Name = = InName ; } ) ;
}
return nullptr ;
}
2021-01-20 17:26:40 -04:00
FClassInputAccessPtr FGraphController : : FindInputDescriptionWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendClassInput > ( FGetClassInputFromGraphClassWithNodeID ( InNodeID ) ) ;
}
2021-01-20 17:26:40 -04:00
FConstClassInputAccessPtr FGraphController : : FindInputDescriptionWithNodeID ( FGuid InNodeID ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassInput > ( FGetConstClassInputFromGraphClassWithNodeID ( InNodeID ) ) ;
}
2021-01-20 17:26:40 -04:00
FClassOutputAccessPtr FGraphController : : FindOutputDescriptionWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < FMetasoundFrontendClassOutput > ( FGetClassOutputFromGraphClassWithNodeID ( InNodeID ) ) ;
}
2021-01-20 17:26:40 -04:00
FConstClassOutputAccessPtr FGraphController : : FindOutputDescriptionWithNodeID ( FGuid InNodeID ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return GraphClassPtr . GetMemberAccessPtr < const FMetasoundFrontendClassOutput > ( FGetConstClassOutputFromGraphClassWithNodeID ( InNodeID ) ) ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FGraphController : : ShareAccess ( )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
FDocumentAccess Access ;
Access . GraphClass = GraphClassPtr ;
Access . ConstGraphClass = GraphClassPtr ;
return Access ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FConstDocumentAccess FGraphController : : ShareAccess ( ) const
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
FConstDocumentAccess Access ;
Access . ConstGraphClass = GraphClassPtr ;
return Access ;
2021-01-13 10:48:59 -04:00
}
//
// FDocumentController
//
FDocumentController : : FDocumentController ( FDocumentAccessPtr InDocumentPtr )
: DocumentPtr ( InDocumentPtr )
{
}
bool FDocumentController : : IsValid ( ) const
{
return DocumentPtr . IsValid ( ) ;
}
bool FDocumentController : : IsRequiredInput ( const FString & InInputName ) const
{
if ( DocumentPtr . IsValid ( ) )
{
auto IsInputWithSameName = [ & ] ( const FMetasoundFrontendClassVertex & Desc ) { return Desc . Name = = InInputName ; } ;
return DocumentPtr - > Archetype . Interface . Inputs . ContainsByPredicate ( IsInputWithSameName ) ;
}
return false ;
}
bool FDocumentController : : IsRequiredOutput ( const FString & InOutputName ) const
{
if ( DocumentPtr . IsValid ( ) )
{
auto IsOutputWithSameName = [ & ] ( const FMetasoundFrontendClassVertex & Desc ) { return Desc . Name = = InOutputName ; } ;
return DocumentPtr - > Archetype . Interface . Outputs . ContainsByPredicate ( IsOutputWithSameName ) ;
}
return false ;
}
TArray < FMetasoundFrontendClassVertex > FDocumentController : : GetRequiredInputs ( ) const
{
if ( DocumentPtr . IsValid ( ) )
{
return DocumentPtr - > Archetype . Interface . Inputs ;
}
return TArray < FMetasoundFrontendClassVertex > ( ) ;
}
TArray < FMetasoundFrontendClassVertex > FDocumentController : : GetRequiredOutputs ( ) const
{
if ( DocumentPtr . IsValid ( ) )
{
return DocumentPtr - > Archetype . Interface . Outputs ;
}
return TArray < FMetasoundFrontendClassVertex > ( ) ;
}
TArray < FMetasoundFrontendClass > FDocumentController : : GetDependencies ( ) const
{
if ( DocumentPtr . IsValid ( ) )
{
return DocumentPtr - > Dependencies ;
}
return TArray < FMetasoundFrontendClass > ( ) ;
}
TArray < FMetasoundFrontendGraphClass > FDocumentController : : GetSubgraphs ( ) const
{
if ( DocumentPtr . IsValid ( ) )
{
return DocumentPtr - > Subgraphs ;
}
return TArray < FMetasoundFrontendGraphClass > ( ) ;
}
TArray < FMetasoundFrontendClass > FDocumentController : : GetClasses ( ) const
{
TArray < FMetasoundFrontendClass > Classes = GetDependencies ( ) ;
Classes . Append ( GetSubgraphs ( ) ) ;
return Classes ;
}
2021-01-20 17:26:40 -04:00
FConstClassAccessPtr FDocumentController : : FindDependencyWithID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendClass > ( FGetConstClassFromDocumentDependenciesWithID ( InClassID ) ) ;
}
2021-01-20 17:26:40 -04:00
FConstGraphClassAccessPtr FDocumentController : : FindSubgraphWithID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
using namespace FrontendControllerIntrinsics ;
return DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendGraphClass > ( FGetConstGraphClassFromDocumentWithID ( InClassID ) ) ;
}
2021-01-20 17:26:40 -04:00
FConstClassAccessPtr FDocumentController : : FindClassWithID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
FConstClassAccessPtr MetasoundClass = FindDependencyWithID ( InClassID ) ;
if ( ! MetasoundClass . IsValid ( ) )
{
MetasoundClass = FindSubgraphWithID ( InClassID ) ;
}
return MetasoundClass ;
}
FConstClassAccessPtr FDocumentController : : FindClass ( const FNodeClassInfo & InNodeClass ) const
{
using namespace FrontendControllerIntrinsics ;
return DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendClass > ( FGetConstClassFromDocumentWithClassInfo ( InNodeClass ) ) ;
}
FConstClassAccessPtr FDocumentController : : FindOrAddClass ( const FNodeClassInfo & InNodeClass )
{
using namespace FrontendControllerIntrinsics ;
FConstClassAccessPtr ClassPtr = FindClass ( InNodeClass ) ;
if ( ( ! ClassPtr . IsValid ( ) ) & & DocumentPtr . IsValid ( ) )
{
// FNodeClassInfo does not contain enough info add a subgraph.
check ( EMetasoundFrontendClassType : : Graph ! = InNodeClass . NodeType ) ;
FMetasoundFrontendClass NewClass = GenerateClassDescription ( InNodeClass ) ;
NewClass . ID = NewClassID ( ) ;
DocumentPtr - > Dependencies . Add ( NewClass ) ;
ClassPtr = FindClass ( InNodeClass ) ;
}
return ClassPtr ;
}
FConstClassAccessPtr FDocumentController : : FindClass ( const FMetasoundFrontendClassMetadata & InMetadata ) const
{
using namespace FrontendControllerIntrinsics ;
return DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendClass > ( FGetConstClassFromDocumentWithMetadata ( InMetadata ) ) ;
}
FConstClassAccessPtr FDocumentController : : FindOrAddClass ( const FMetasoundFrontendClassMetadata & InMetadata )
{
FConstClassAccessPtr ClassPtr = FindClass ( InMetadata ) ;
if ( ( ! ClassPtr . IsValid ( ) ) & & DocumentPtr . IsValid ( ) )
{
if ( ( EMetasoundFrontendClassType : : External = = InMetadata . Type ) | | ( EMetasoundFrontendClassType : : Input = = InMetadata . Type ) | | ( EMetasoundFrontendClassType : : Output = = InMetadata . Type ) )
{
FMetasoundFrontendClass NewClass ;
if ( FMetasoundFrontendRegistryContainer : : GetFrontendClassFromRegistered ( InMetadata , NewClass ) )
{
NewClass . ID = NewClassID ( ) ;
DocumentPtr - > Dependencies . Add ( NewClass ) ;
}
else
{
2021-01-28 19:02:51 -04:00
UE_LOG ( LogMetasound , Error , TEXT ( " Cannot add external dependency. No Metasound class found with matching metadata Name: \" %s \" , Version %d.%d. Suggested solution \" %s \" by %s. " ) , * InMetadata . ClassName . GetFullName ( ) . ToString ( ) , InMetadata . Version . Major , InMetadata . Version . Minor , * InMetadata . PromptIfMissing . ToString ( ) , * InMetadata . Author . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else if ( EMetasoundFrontendClassType : : Graph = = InMetadata . Type )
{
FMetasoundFrontendGraphClass NewClass ;
NewClass . ID = NewClassID ( ) ;
NewClass . Metadata = InMetadata ;
DocumentPtr - > Subgraphs . Add ( NewClass ) ;
}
else
{
2021-01-28 19:02:51 -04:00
UE_LOG ( LogMetasound , Error , TEXT ( " Unsupported metasound class type for node: \" %s \" , Version %d.%d. " ) , * InMetadata . ClassName . GetFullName ( ) . ToString ( ) , InMetadata . Version . Major , InMetadata . Version . Minor ) ;
2021-01-13 10:48:59 -04:00
checkNoEntry ( ) ;
}
ClassPtr = FindClass ( InMetadata ) ;
}
return ClassPtr ;
}
void FDocumentController : : RemoveUnreferencedDependencies ( )
{
if ( DocumentPtr . IsValid ( ) )
{
int32 NumDependenciesRemovedThisItr = 0 ;
// Repeatedly remove unreferenced dependencies until there are
// no unreferenced dependencies left.
do
{
2021-01-20 17:26:40 -04:00
TSet < FGuid > ReferencedDependencyIDs ;
2021-01-13 10:48:59 -04:00
auto AddNodeClassIDToSet = [ & ] ( const FMetasoundFrontendNode & Node )
{
ReferencedDependencyIDs . Add ( Node . ClassID ) ;
} ;
auto AddGraphNodeClassIDsToSet = [ & ] ( const FMetasoundFrontendGraphClass & GraphClass )
{
Algo : : ForEach ( GraphClass . Graph . Nodes , AddNodeClassIDToSet ) ;
} ;
// Referenced dependencies in root class
Algo : : ForEach ( DocumentPtr - > RootGraph . Graph . Nodes , AddNodeClassIDToSet ) ;
// Referenced dependencies in
Algo : : ForEach ( DocumentPtr - > Subgraphs , AddGraphNodeClassIDsToSet ) ;
auto IsDependencyUnreferenced = [ & ] ( const FMetasoundFrontendClass & ClassDependency )
{
return ! ReferencedDependencyIDs . Contains ( ClassDependency . ID ) ;
} ;
NumDependenciesRemovedThisItr = DocumentPtr - > Dependencies . RemoveAllSwap ( IsDependencyUnreferenced ) ;
}
while ( NumDependenciesRemovedThisItr > 0 ) ;
}
}
FGraphHandle FDocumentController : : GetRootGraph ( )
{
if ( DocumentPtr . IsValid ( ) )
{
FGraphClassAccessPtr GraphClass = DocumentPtr . GetMemberAccessPtr < FMetasoundFrontendGraphClass > ( [ ] ( FMetasoundFrontendDocument & Doc ) { return & Doc . RootGraph ; } ) ;
return FGraphController : : CreateGraphHandle ( FGraphController : : FInitParams { GraphClass , this - > AsShared ( ) } ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FDocumentController : : GetRootGraph ( ) const
{
if ( DocumentPtr . IsValid ( ) )
{
FConstGraphClassAccessPtr GraphClass = DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendGraphClass > ( [ ] ( const FMetasoundFrontendDocument & Doc ) { return & Doc . RootGraph ; } ) ;
return FGraphController : : CreateConstGraphHandle ( FGraphController : : FInitParams
{
ConstCastAccessPtr < FMetasoundFrontendGraphClass > ( GraphClass ) ,
ConstCastSharedRef < IDocumentController > ( this - > AsShared ( ) )
} ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
TArray < FGraphHandle > FDocumentController : : GetSubgraphHandles ( )
{
TArray < FGraphHandle > Subgraphs ;
if ( DocumentPtr . IsValid ( ) )
{
for ( FMetasoundFrontendGraphClass & GraphClass : DocumentPtr - > Subgraphs )
{
Subgraphs . Add ( GetSubgraphWithClassID ( GraphClass . ID ) ) ;
}
}
return Subgraphs ;
}
TArray < FConstGraphHandle > FDocumentController : : GetSubgraphHandles ( ) const
{
TArray < FConstGraphHandle > Subgraphs ;
if ( DocumentPtr . IsValid ( ) )
{
for ( const FMetasoundFrontendGraphClass & GraphClass : DocumentPtr - > Subgraphs )
{
Subgraphs . Add ( GetSubgraphWithClassID ( GraphClass . ID ) ) ;
}
}
return Subgraphs ;
}
2021-01-20 17:26:40 -04:00
FGraphHandle FDocumentController : : GetSubgraphWithClassID ( FGuid InClassID )
2021-01-13 10:48:59 -04:00
{
FGraphClassAccessPtr GraphClassPtr = DocumentPtr . GetMemberAccessPtr < FMetasoundFrontendGraphClass > ( FrontendControllerIntrinsics : : FGetSubgraphFromDocumentByID ( InClassID ) ) ;
return FGraphController : : CreateGraphHandle ( FGraphController : : FInitParams { GraphClassPtr , this - > AsShared ( ) } ) ;
}
2021-01-20 17:26:40 -04:00
FConstGraphHandle FDocumentController : : GetSubgraphWithClassID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
FConstGraphClassAccessPtr GraphClassPtr = DocumentPtr . GetMemberAccessPtr < const FMetasoundFrontendGraphClass > ( FrontendControllerIntrinsics : : FGetSubgraphFromDocumentByID ( InClassID ) ) ;
return FGraphController : : CreateConstGraphHandle ( FGraphController : : FInitParams { ConstCastAccessPtr < FMetasoundFrontendGraphClass > ( GraphClassPtr ) , ConstCastSharedRef < IDocumentController > ( this - > AsShared ( ) ) } ) ;
}
bool FDocumentController : : ExportToJSONAsset ( const FString & InAbsolutePath ) const
{
if ( DocumentPtr . IsValid ( ) )
{
if ( TUniquePtr < FArchive > FileWriter = TUniquePtr < FArchive > ( IFileManager : : Get ( ) . CreateFileWriter ( * InAbsolutePath ) ) )
{
TJsonStructSerializerBackend < DefaultCharType > Backend ( * FileWriter , EStructSerializerBackendFlags : : Default ) ;
FStructSerializer : : Serialize < FMetasoundFrontendDocument > ( * DocumentPtr , Backend ) ;
FileWriter - > Close ( ) ;
return true ;
}
else
{
UE_LOG ( LogMetasound , Error , TEXT ( " Failed to export Metasound json asset. Could not write to path \" %s \" . " ) , * InAbsolutePath ) ;
}
}
return false ;
}
FString FDocumentController : : ExportToJSON ( ) const
{
TArray < uint8 > WriterBuffer ;
FMemoryWriter MemWriter ( WriterBuffer ) ;
Metasound : : TJsonStructSerializerBackend < Metasound : : DefaultCharType > Backend ( MemWriter , EStructSerializerBackendFlags : : Default ) ;
FStructSerializer : : Serialize < FMetasoundFrontendDocument > ( * DocumentPtr , Backend ) ;
MemWriter . Close ( ) ;
// null terminator
WriterBuffer . AddZeroed ( sizeof ( ANSICHAR ) ) ;
FString Output ;
Output . AppendChars ( reinterpret_cast < ANSICHAR * > ( WriterBuffer . GetData ( ) ) , WriterBuffer . Num ( ) / sizeof ( ANSICHAR ) ) ;
return Output ;
}
bool FDocumentController : : IsMatchingMetasoundClass ( const FMetasoundFrontendClassMetadata & InMetadataA , const FMetasoundFrontendClassMetadata & InMetadataB )
{
if ( InMetadataA . Type = = InMetadataB . Type )
{
2021-01-28 19:02:51 -04:00
if ( InMetadataA . ClassName = = InMetadataB . ClassName )
2021-01-13 10:48:59 -04:00
{
return FRegistry : : GetRegistryKey ( InMetadataA ) = = FRegistry : : GetRegistryKey ( InMetadataB ) ;
}
}
return false ;
}
bool FDocumentController : : IsMatchingMetasoundClass ( const FNodeClassInfo & InNodeClass , const FMetasoundFrontendClassMetadata & InMetadata )
{
if ( InNodeClass . NodeType = = InMetadata . Type )
{
2021-01-28 19:02:51 -04:00
return InNodeClass . LookupKey = = FRegistry : : GetRegistryKey ( InMetadata ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FDocumentController : : ShareAccess ( )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
FDocumentAccess Access ;
2021-01-13 10:48:59 -04:00
2021-01-20 17:26:40 -04:00
Access . Document = DocumentPtr ;
Access . ConstDocument = DocumentPtr ;
2021-01-13 10:48:59 -04:00
2021-01-20 17:26:40 -04:00
return Access ;
}
FConstDocumentAccess FDocumentController : : ShareAccess ( ) const
{
FConstDocumentAccess Access ;
Access . ConstDocument = DocumentPtr ;
return Access ;
}
FGuid FDocumentController : : NewClassID ( ) const
{
return FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
}
}
}