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"
2021-06-23 20:07:53 -04:00
# include "MetasoundFrontendArchetypeRegistry.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundFrontendController.h"
# include "MetasoundFrontendDocument.h"
2021-05-10 19:52:56 -04:00
# include "MetasoundFrontendDocumentAccessPtr.h"
2021-01-13 10:48:59 -04:00
# include "MetasoundFrontendGraph.h"
2021-02-03 14:36:36 -04:00
# include "MetasoundFrontendRegistries.h"
2021-05-20 19:33:21 -04:00
# include "MetasoundFrontendSubgraphNodeController.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-03-03 15:00:53 -04:00
# define LOCTEXT_NAMESPACE "MetasoundFrontendStandardController"
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 ;
}
// 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 ;
}
2021-05-20 19:33:21 -04:00
2021-01-20 17:26:40 -04:00
}
2021-01-13 10:48:59 -04:00
2021-05-03 17:52:04 -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
}
2021-05-03 17:52:04 -04:00
2021-01-13 10:48:59 -04:00
//
// FBaseOutputController
//
FBaseOutputController : : FBaseOutputController ( const FBaseOutputController : : FInitParams & InParams )
: ID ( InParams . ID )
, NodeVertexPtr ( InParams . NodeVertexPtr )
2021-03-03 15:00:53 -04:00
, ClassOutputPtr ( InParams . ClassOutputPtr )
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-07-12 16:12:36 -04:00
return OwningNode - > IsValid ( ) & & ( nullptr ! = NodeVertexPtr . Get ( ) ) & & ( nullptr ! = GraphPtr . Get ( ) ) ;
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
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Vertex - > TypeName ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FName > ( ) ;
}
const FString & FBaseOutputController : : GetName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Vertex - > Name ;
2021-01-13 10:48:59 -04:00
}
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-05-20 19:33:21 -04:00
bool FBaseOutputController : : IsConnected ( ) const
{
return ( FindEdges ( ) . Num ( ) > 0 ) ;
}
TArray < FInputHandle > FBaseOutputController : : GetConnectedInputs ( )
2021-01-22 03:05:22 -04:00
{
TArray < FInputHandle > Inputs ;
// Create output handle from output node.
FGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
for ( const FMetasoundFrontendEdge & Edge : FindEdges ( ) )
{
FNodeHandle InputNode = Graph - > GetNodeWithID ( Edge . ToNodeID ) ;
2021-02-24 18:37:19 -04:00
FInputHandle Input = InputNode - > GetInputWithID ( Edge . ToVertexID ) ;
2021-01-22 03:05:22 -04:00
if ( Input - > IsValid ( ) )
{
Inputs . Add ( Input ) ;
}
}
return Inputs ;
}
2021-05-20 19:33:21 -04:00
TArray < FConstInputHandle > FBaseOutputController : : GetConstConnectedInputs ( ) const
2021-01-22 03:05:22 -04:00
{
TArray < FConstInputHandle > Inputs ;
// Create output handle from output node.
FConstGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
for ( const FMetasoundFrontendEdge & Edge : FindEdges ( ) )
{
FConstNodeHandle InputNode = Graph - > GetNodeWithID ( Edge . ToNodeID ) ;
2021-02-24 18:37:19 -04:00
FConstInputHandle Input = InputNode - > GetInputWithID ( Edge . ToVertexID ) ;
2021-01-22 03:05:22 -04:00
if ( Input - > IsValid ( ) )
{
Inputs . Add ( Input ) ;
}
}
return Inputs ;
}
bool FBaseOutputController : : Disconnect ( )
{
bool bSuccess = true ;
2021-05-20 19:33:21 -04:00
for ( FInputHandle Input : GetConnectedInputs ( ) )
2021-01-22 03:05:22 -04:00
{
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
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-22 03:05:22 -04:00
{
const FGuid NodeID = GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid VertexID = GetID ( ) ;
2021-01-22 03:05:22 -04:00
auto EdgeHasMatchingSource = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
2021-02-24 18:37:19 -04:00
return ( Edge . FromNodeID = = NodeID ) & & ( Edge . FromVertexID = = VertexID ) ;
2021-01-22 03:05:22 -04:00
} ;
2021-07-12 16:12:36 -04:00
return Graph - > Edges . FilterByPredicate ( EdgeHasMatchingSource ) ;
2021-01-22 03:05:22 -04:00
}
return TArray < FMetasoundFrontendEdge > ( ) ;
}
2021-03-03 15:00:53 -04:00
const FText & FBaseOutputController : : GetDisplayName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * Output = ClassOutputPtr . Get ( ) )
2021-03-03 15:00:53 -04:00
{
2021-07-12 16:12:36 -04:00
return Output - > Metadata . DisplayName ;
2021-03-03 15:00:53 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FBaseOutputController : : GetTooltip ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * Output = ClassOutputPtr . Get ( ) )
2021-03-03 15:00:53 -04:00
{
2021-07-12 16:12:36 -04:00
return Output - > Metadata . Description ;
2021-03-03 15:00:53 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FBaseOutputController : : GetMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * Output = ClassOutputPtr . Get ( ) )
2021-03-31 15:34:29 -04:00
{
2021-07-12 16:12:36 -04:00
return Output - > Metadata ;
2021-03-31 15:34:29 -04:00
}
2021-03-03 15:00:53 -04:00
2021-03-31 15:34:29 -04:00
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
FDocumentAccess FBaseOutputController : : ShareAccess ( )
2021-01-20 17:26:40 -04:00
{
FDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
2021-03-03 15:00:53 -04:00
Access . ConstClassOutput = ClassOutputPtr ;
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-03-03 15:00:53 -04:00
Access . ConstClassOutput = ClassOutputPtr ;
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
//
// FInputNodeOutputController
//
FInputNodeOutputController : : FInputNodeOutputController ( const FInputNodeOutputController : : FInitParams & InParams )
2021-03-03 15:00:53 -04:00
: FBaseOutputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . ClassOutputPtr , InParams . GraphPtr , InParams . OwningNode } )
2021-01-13 10:48:59 -04:00
, OwningGraphClassInputPtr ( InParams . OwningGraphClassInputPtr )
{
}
bool FInputNodeOutputController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return FBaseOutputController : : IsValid ( ) & & ( nullptr ! = OwningGraphClassInputPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
const FText & FInputNodeOutputController : : GetDisplayName ( ) const
{
2021-03-03 15:00:53 -04:00
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
if ( const FMetasoundFrontendClassOutput * ClassOutput = ClassOutputPtr . Get ( ) )
{
// If there is a valid ClassOutput, combine the names.
CachedDisplayName = FText : : Format ( LOCTEXT ( " InputNodeOutputControllerFormat " , " {1} {0} " ) , OwningInput - > Metadata . DisplayName , ClassOutput - > Metadata . DisplayName ) ;
}
else
{
// If there is no valid ClassOutput, use the owning value display name.
CachedDisplayName = OwningInput - > Metadata . DisplayName ;
}
2021-01-13 10:48:59 -04:00
}
2021-03-03 15:00:53 -04:00
return CachedDisplayName ;
2021-01-13 10:48:59 -04:00
}
const FText & FInputNodeOutputController : : GetTooltip ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassInput * Input = OwningGraphClassInputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Input - > Metadata . Description ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FInputNodeOutputController : : GetMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassInput * Input = OwningGraphClassInputPtr . Get ( ) )
2021-03-31 15:34:29 -04:00
{
2021-07-12 16:12:36 -04:00
return Input - > Metadata ;
2021-03-31 15:34:29 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
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-03-11 21:12:31 -04:00
//
// FOutputNodeOutputController
//
FOutputNodeOutputController : : FOutputNodeOutputController ( const FOutputNodeOutputController : : FInitParams & InParams )
: FBaseOutputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . ClassOutputPtr , InParams . GraphPtr , InParams . OwningNode } )
, OwningGraphClassOutputPtr ( InParams . OwningGraphClassOutputPtr )
{
}
bool FOutputNodeOutputController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return FBaseOutputController : : IsValid ( ) & & ( nullptr ! = OwningGraphClassOutputPtr . Get ( ) ) ;
2021-03-11 21:12:31 -04:00
}
const FText & FOutputNodeOutputController : : GetDisplayName ( ) const
{
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
{
return OwningOutput - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FOutputNodeOutputController : : GetTooltip ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-03-11 21:12:31 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata . Description ;
2021-03-11 21:12:31 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FOutputNodeOutputController : : GetMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-03-31 15:34:29 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata ;
2021-03-31 15:34:29 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
2021-03-11 21:12:31 -04:00
FConnectability FOutputNodeOutputController : : CanConnectTo ( const IInputController & InController ) const
{
// Cannot connect to a graph's output.
static const FConnectability Connectability = { FConnectability : : EConnectable : : No } ;
return Connectability ;
}
bool FOutputNodeOutputController : : Connect ( IInputController & InController )
{
return false ;
}
bool FOutputNodeOutputController : : ConnectWithConverterNode ( IInputController & InController , const FConverterNodeInfo & InNodeClassName )
{
return false ;
}
2021-01-13 10:48:59 -04:00
//
// FBaseInputController
//
FBaseInputController : : FBaseInputController ( const FBaseInputController : : FInitParams & InParams )
: ID ( InParams . ID )
, NodeVertexPtr ( InParams . NodeVertexPtr )
2021-03-03 15:00:53 -04:00
, ClassInputPtr ( InParams . ClassInputPtr )
2021-01-13 10:48:59 -04:00
, GraphPtr ( InParams . GraphPtr )
, OwningNode ( InParams . OwningNode )
{
}
bool FBaseInputController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return OwningNode - > IsValid ( ) & & ( nullptr ! = NodeVertexPtr . Get ( ) ) & & ( nullptr ! = GraphPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
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
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Vertex - > TypeName ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FName > ( ) ;
}
const FString & FBaseInputController : : GetName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Vertex - > Name ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FString > ( ) ;
}
2021-03-03 15:00:53 -04:00
const FText & FBaseInputController : : GetDisplayName ( ) const
{
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
return ClassInput - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-05-28 14:09:45 -04:00
const FMetasoundFrontendLiteral * FBaseInputController : : GetLiteral ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningNode - > GetInputLiteral ( Vertex - > VertexID ) ;
2021-05-28 14:09:45 -04:00
}
return nullptr ;
}
void FBaseInputController : : SetLiteral ( const FMetasoundFrontendLiteral & InLiteral )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
if ( const FMetasoundFrontendLiteral * ClassLiteral = GetClassDefaultLiteral ( ) )
{
// Clear if equivalent to class default as fallback is the class default
if ( ClassLiteral - > IsEquivalent ( InLiteral ) )
{
2021-07-12 16:12:36 -04:00
OwningNode - > ClearInputLiteral ( Vertex - > VertexID ) ;
2021-05-28 14:09:45 -04:00
return ;
}
}
2021-07-12 16:12:36 -04:00
OwningNode - > SetInputLiteral ( FMetasoundFrontendVertexLiteral { Vertex - > VertexID , InLiteral } ) ;
2021-05-28 14:09:45 -04:00
}
}
const FMetasoundFrontendLiteral * FBaseInputController : : GetClassDefaultLiteral ( ) const
2021-03-03 15:00:53 -04:00
{
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
return & ( ClassInput - > DefaultLiteral ) ;
}
return nullptr ;
}
const FText & FBaseInputController : : GetTooltip ( ) const
{
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
return ClassInput - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FBaseInputController : : GetMetadata ( ) const
{
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
return ClassInput - > Metadata ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
2021-03-03 15:00:53 -04:00
2021-01-13 10:48:59 -04:00
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 ;
}
2021-05-20 19:33:21 -04:00
FOutputHandle FBaseInputController : : GetConnectedOutput ( )
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendEdge * Edge = FindEdge ( ) )
{
// Create output handle from output node.
FGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
FNodeHandle OutputNode = Graph - > GetNodeWithID ( Edge - > FromNodeID ) ;
2021-02-24 18:37:19 -04:00
return OutputNode - > GetOutputWithID ( Edge - > FromVertexID ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
2021-05-20 19:33:21 -04:00
FConstOutputHandle FBaseInputController : : GetConnectedOutput ( ) const
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendEdge * Edge = FindEdge ( ) )
{
// Create output handle from output node.
FConstGraphHandle Graph = OwningNode - > GetOwningGraph ( ) ;
FConstNodeHandle OutputNode = Graph - > GetNodeWithID ( Edge - > FromNodeID ) ;
2021-02-24 18:37:19 -04:00
return OutputNode - > GetOutputWithID ( Edge - > FromVertexID ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
FConnectability FBaseInputController : : CanConnectTo ( const IOutputController & InController ) const
{
FConnectability OutConnectability ;
OutConnectability . Connectable = FConnectability : : EConnectable : : No ;
2021-07-12 16:12:36 -04:00
const FName & DataType = GetDataType ( ) ;
const FName & OtherDataType = InController . GetDataType ( ) ;
if ( ! DataType . IsValid ( ) )
2021-01-13 10:48:59 -04:00
{
return OutConnectability ;
}
2021-07-12 16:12:36 -04:00
if ( OtherDataType = = DataType )
2021-01-13 10:48:59 -04:00
{
// 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.
2021-07-12 16:12:36 -04:00
OutConnectability . PossibleConverterNodeClasses = FRegistry : : Get ( ) - > GetPossibleConverterNodes ( OtherDataType , DataType ) ;
2021-01-13 10:48:59 -04:00
if ( OutConnectability . PossibleConverterNodeClasses . Num ( ) > 0 )
{
OutConnectability . Connectable = FConnectability : : EConnectable : : YesWithConverterNode ;
return OutConnectability ;
}
return OutConnectability ;
}
bool FBaseInputController : : Connect ( IOutputController & InController )
{
2021-07-12 16:12:36 -04:00
const FName & DataType = GetDataType ( ) ;
const FName & OtherDataType = InController . GetDataType ( ) ;
if ( ! DataType . IsValid ( ) )
2021-01-13 10:48:59 -04:00
{
return false ;
}
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( ensureAlwaysMsgf ( OtherDataType = = DataType , TEXT ( " Cannot connect incompatible types. " ) ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
// Overwrite an existing connection if it exists.
FMetasoundFrontendEdge * Edge = FindEdge ( ) ;
if ( ! Edge )
{
Edge = & Graph - > Edges . AddDefaulted_GetRef ( ) ;
Edge - > ToNodeID = GetOwningNodeID ( ) ;
Edge - > ToVertexID = GetID ( ) ;
}
Edge - > FromNodeID = InController . GetOwningNodeID ( ) ;
Edge - > FromVertexID = InController . GetID ( ) ;
return true ;
2021-01-13 10:48:59 -04:00
}
}
return false ;
}
bool FBaseInputController : : ConnectWithConverterNode ( IOutputController & InController , const FConverterNodeInfo & InConverterInfo )
{
2021-07-12 16:12:36 -04:00
FGraphHandle OwningGraph = OwningNode - > GetOwningGraph ( ) ;
2021-01-13 10:48:59 -04:00
// Generate the converter node.
2021-07-12 16:12:36 -04:00
FNodeHandle ConverterNode = OwningGraph - > AddNode ( InConverterInfo . NodeKey ) ;
2021-01-13 10:48:59 -04:00
TArray < FInputHandle > ConverterInputs = ConverterNode - > GetInputsWithVertexName ( InConverterInfo . PreferredConverterInputPin ) ;
TArray < FOutputHandle > ConverterOutputs = ConverterNode - > GetOutputsWithVertexName ( InConverterInfo . PreferredConverterOutputPin ) ;
if ( ConverterInputs . Num ( ) < 1 )
{
2021-06-08 10:52:31 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Converter node [Name: %s] does not support preferred input vertex [Vertex: %s] " ) , * ConverterNode - > GetNodeName ( ) , * InConverterInfo . PreferredConverterInputPin ) ;
2021-01-13 10:48:59 -04:00
return false ;
}
if ( ConverterOutputs . Num ( ) < 1 )
{
2021-06-08 10:52:31 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Converter node [Name: %s] does not support preferred output vertex [Vertex: %s] " ) , * ConverterNode - > GetNodeName ( ) , * 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 )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
FGuid FromNodeID = InController . GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid FromVertexID = InController . GetID ( ) ;
2021-01-20 17:26:40 -04:00
FGuid ToNodeID = GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid ToVertexID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto IsMatchingEdge = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
2021-02-24 18:37:19 -04:00
return ( Edge . FromNodeID = = FromNodeID ) & & ( Edge . FromVertexID = = FromVertexID ) & & ( Edge . ToNodeID = = ToNodeID ) & & ( Edge . ToVertexID = = ToVertexID ) ;
2021-01-13 10:48:59 -04:00
} ;
2021-07-12 16:12:36 -04:00
int32 NumRemoved = Graph - > Edges . RemoveAllSwap ( IsMatchingEdge ) ;
2021-01-13 10:48:59 -04:00
return NumRemoved > 0 ;
}
return false ;
}
bool FBaseInputController : : Disconnect ( )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid VertexID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
2021-02-24 18:37:19 -04:00
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToVertexID = = VertexID ) ;
2021-01-13 10:48:59 -04:00
} ;
2021-07-12 16:12:36 -04:00
int32 NumRemoved = Graph - > Edges . RemoveAllSwap ( EdgeHasMatchingDestination ) ;
2021-01-13 10:48:59 -04:00
return NumRemoved > 0 ;
}
return false ;
}
const FMetasoundFrontendEdge * FBaseInputController : : FindEdge ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid VertexID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
2021-02-24 18:37:19 -04:00
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToVertexID = = VertexID ) ;
2021-01-13 10:48:59 -04:00
} ;
2021-07-12 16:12:36 -04:00
return Graph - > Edges . FindByPredicate ( EdgeHasMatchingDestination ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
FMetasoundFrontendEdge * FBaseInputController : : FindEdge ( )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraph * Graph = GraphPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-01-20 17:26:40 -04:00
const FGuid NodeID = GetOwningNodeID ( ) ;
2021-02-24 18:37:19 -04:00
FGuid VertexID = GetID ( ) ;
2021-01-13 10:48:59 -04:00
auto EdgeHasMatchingDestination = [ & ] ( const FMetasoundFrontendEdge & Edge )
{
2021-02-24 18:37:19 -04:00
return ( Edge . ToNodeID = = NodeID ) & & ( Edge . ToVertexID = = VertexID ) ;
2021-01-13 10:48:59 -04:00
} ;
2021-07-12 16:12:36 -04:00
return Graph - > Edges . FindByPredicate ( EdgeHasMatchingDestination ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
2021-01-20 17:26:40 -04:00
FDocumentAccess FBaseInputController : : ShareAccess ( )
{
FDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
2021-03-03 15:00:53 -04:00
Access . ConstClassInput = ClassInputPtr ;
2021-01-20 17:26:40 -04:00
Access . Graph = GraphPtr ;
Access . ConstGraph = GraphPtr ;
return Access ;
}
FConstDocumentAccess FBaseInputController : : ShareAccess ( ) const
{
FConstDocumentAccess Access ;
Access . ConstVertex = NodeVertexPtr ;
2021-03-03 15:00:53 -04:00
Access . ConstClassInput = ClassInputPtr ;
2021-01-20 17:26:40 -04:00
Access . ConstGraph = GraphPtr ;
return Access ;
}
2021-01-13 10:48:59 -04:00
//
// FOutputNodeInputController
//
FOutputNodeInputController : : FOutputNodeInputController ( const FOutputNodeInputController : : FInitParams & InParams )
2021-03-03 15:00:53 -04:00
: FBaseInputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . ClassInputPtr , InParams . GraphPtr , InParams . OwningNode } )
2021-01-13 10:48:59 -04:00
, OwningGraphClassOutputPtr ( InParams . OwningGraphClassOutputPtr )
{
}
bool FOutputNodeInputController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return FBaseInputController : : IsValid ( ) & & ( nullptr ! = OwningGraphClassOutputPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
const FText & FOutputNodeInputController : : GetDisplayName ( ) const
{
2021-03-03 15:00:53 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
if ( const FMetasoundFrontendClassInput * ClassInput = ClassInputPtr . Get ( ) )
{
// If there the ClassInput exists, combine the variable name and class input name.
// of the variable should be added to the names of the vertices.
CachedDisplayName = FText : : Format ( LOCTEXT ( " OutputNodeInputControllerFormat " , " {1} {0} " ) , OwningOutput - > Metadata . DisplayName , ClassInput - > Metadata . DisplayName ) ;
}
else
{
// If there is not ClassInput, then use the variable name.
CachedDisplayName = OwningOutput - > Metadata . DisplayName ;
}
2021-01-13 10:48:59 -04:00
}
2021-03-03 15:00:53 -04:00
return CachedDisplayName ;
2021-01-13 10:48:59 -04:00
}
const FText & FOutputNodeInputController : : GetTooltip ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata . Description ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FOutputNodeInputController : : GetMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-03-31 15:34:29 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata ;
2021-03-31 15:34:29 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
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-05-03 17:52:04 -04:00
2021-03-11 21:12:31 -04:00
//
// FInputNodeInputController
//
FInputNodeInputController : : FInputNodeInputController ( const FInputNodeInputController : : FInitParams & InParams )
: FBaseInputController ( { InParams . ID , InParams . NodeVertexPtr , InParams . ClassInputPtr , InParams . GraphPtr , InParams . OwningNode } )
, OwningGraphClassInputPtr ( InParams . OwningGraphClassInputPtr )
{
}
bool FInputNodeInputController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return FBaseInputController : : IsValid ( ) & & ( nullptr ! = OwningGraphClassInputPtr . Get ( ) ) ;
2021-03-11 21:12:31 -04:00
}
const FText & FInputNodeInputController : : GetDisplayName ( ) const
{
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
{
return OwningInput - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FInputNodeInputController : : GetTooltip ( ) const
{
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
{
return OwningInput - > Metadata . Description ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
2021-03-31 15:34:29 -04:00
const FMetasoundFrontendVertexMetadata & FInputNodeInputController : : GetMetadata ( ) const
{
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
{
return OwningInput - > Metadata ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendVertexMetadata > ( ) ;
}
2021-03-11 21:12:31 -04:00
FConnectability FInputNodeInputController : : CanConnectTo ( const IOutputController & InController ) const
{
static const FConnectability Connectability = { FConnectability : : EConnectable : : No } ;
return Connectability ;
}
bool FInputNodeInputController : : Connect ( IOutputController & InController )
{
return false ;
}
bool FInputNodeInputController : : ConnectWithConverterNode ( IOutputController & InController , const FConverterNodeInfo & InNodeClassName )
{
return false ;
}
2021-01-13 10:48:59 -04:00
//
// FBaseNodeController
//
FBaseNodeController : : FBaseNodeController ( const FBaseNodeController : : FInitParams & InParams )
: NodePtr ( InParams . NodePtr )
, ClassPtr ( InParams . ClassPtr )
, OwningGraph ( InParams . OwningGraph )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( Node - > ClassID ! = Class - > ID )
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Changing node's class id from [ClassID:%s] to [ClassID:%s] " ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
Node - > ClassID = Class - > ID ;
}
2021-01-13 10:48:59 -04:00
}
}
}
bool FBaseNodeController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return OwningGraph - > IsValid ( ) & & ( nullptr ! = NodePtr . Get ( ) ) & & ( nullptr ! = ClassPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
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
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Node - > ID ;
2021-01-13 10:48:59 -04:00
}
return Metasound : : FrontendInvalidID ;
}
2021-01-20 17:26:40 -04:00
FGuid FBaseNodeController : : GetClassID ( ) const
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > ID ;
2021-01-13 10:48:59 -04:00
}
return Metasound : : FrontendInvalidID ;
}
2021-05-28 14:09:45 -04:00
const FMetasoundFrontendLiteral * FBaseNodeController : : GetInputLiteral ( const FGuid & InVertexID ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendVertexLiteral & VertexLiteral : Node - > InputLiterals )
2021-05-28 14:09:45 -04:00
{
if ( VertexLiteral . VertexID = = InVertexID )
{
return & VertexLiteral . Value ;
}
}
}
return nullptr ;
}
void FBaseNodeController : : SetInputLiteral ( const FMetasoundFrontendVertexLiteral & InVertexLiteral )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
auto IsInputVertex = [ InVertexLiteral ] ( const FMetasoundFrontendVertex & Vertex )
{
return InVertexLiteral . VertexID = = Vertex . VertexID ;
} ;
2021-07-12 16:12:36 -04:00
FMetasoundFrontendNodeInterface & NodeInterface = Node - > Interface ;
2021-05-28 14:09:45 -04:00
if ( ! ensure ( NodeInterface . Inputs . ContainsByPredicate ( IsInputVertex ) ) )
{
return ;
}
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendVertexLiteral & VertexLiteral : Node - > InputLiterals )
2021-05-28 14:09:45 -04:00
{
if ( VertexLiteral . VertexID = = InVertexLiteral . VertexID )
{
if ( ensure ( VertexLiteral . Value . GetType ( ) = = InVertexLiteral . Value . GetType ( ) ) )
{
VertexLiteral = InVertexLiteral ;
}
return ;
}
}
2021-07-12 16:12:36 -04:00
Node - > InputLiterals . Add ( InVertexLiteral ) ;
2021-05-28 14:09:45 -04:00
}
}
bool FBaseNodeController : : ClearInputLiteral ( FGuid InVertexID )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
auto IsInputVertex = [ InVertexID ] ( const FMetasoundFrontendVertexLiteral & VertexLiteral )
{
return InVertexID = = VertexLiteral . VertexID ;
} ;
2021-07-12 16:12:36 -04:00
return Node - > InputLiterals . RemoveAllSwap ( IsInputVertex , false ) > 0 ;
2021-05-28 14:09:45 -04:00
}
return false ;
}
2021-05-03 17:52:04 -04:00
const FMetasoundFrontendClassInterface & FBaseNodeController : : GetClassInterface ( ) const
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Interface ;
2021-01-13 10:48:59 -04:00
}
2021-05-03 17:52:04 -04:00
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendClassInterface > ( ) ;
}
const FMetasoundFrontendClassMetadata & FBaseNodeController : : GetClassMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Metadata ;
2021-05-03 17:52:04 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendClassMetadata > ( ) ;
2021-01-13 10:48:59 -04:00
}
2021-03-02 21:39:09 -04:00
const FMetasoundFrontendInterfaceStyle & FBaseNodeController : : GetInputStyle ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-03-02 21:39:09 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Interface . InputStyle ;
2021-03-02 21:39:09 -04:00
}
static const FMetasoundFrontendInterfaceStyle Invalid ;
return Invalid ;
}
const FMetasoundFrontendInterfaceStyle & FBaseNodeController : : GetOutputStyle ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-03-02 21:39:09 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Interface . OutputStyle ;
2021-03-02 21:39:09 -04:00
}
static const FMetasoundFrontendInterfaceStyle Invalid ;
return Invalid ;
}
2021-01-23 12:59:01 -04:00
const FMetasoundFrontendClassStyle & FBaseNodeController : : GetClassStyle ( ) const
2021-01-20 00:42:47 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-20 00:42:47 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > 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
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-23 12:59:01 -04:00
{
2021-07-12 16:12:36 -04:00
return Node - > Style ;
2021-01-23 12:59:01 -04:00
}
static const FMetasoundFrontendNodeStyle Invalid ;
return Invalid ;
}
void FBaseNodeController : : SetNodeStyle ( const FMetasoundFrontendNodeStyle & InStyle )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-23 12:59:01 -04:00
{
2021-07-12 16:12:36 -04:00
Node - > Style = InStyle ;
2021-01-23 12:59:01 -04:00
}
2021-01-20 00:42:47 -04:00
}
2021-03-19 15:10:57 -04:00
const FText & FBaseNodeController : : GetDescription ( ) const
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Metadata . Description ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FString & FBaseNodeController : : GetNodeName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Node - > Name ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FString > ( ) ;
}
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-02-24 18:37:19 -04:00
bool FBaseNodeController : : RemoveInput ( FGuid InVertexID )
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-02-24 18:37:19 -04:00
bool FBaseNodeController : : RemoveOutput ( FGuid InVertexID )
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 ( ) )
{
2021-02-24 18:37:19 -04:00
FInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
2021-03-19 15:10:57 -04:00
int32 FBaseNodeController : : GetNumInputs ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return Node - > Interface . Inputs . Num ( ) ;
2021-03-19 15:10:57 -04:00
}
return 0 ;
}
void FBaseNodeController : : IterateInputs ( TUniqueFunction < void ( FInputHandle ) > InFunction )
{
for ( const FInputControllerParams & Params : GetInputControllerParams ( ) )
{
FInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , AsShared ( ) ) ;
if ( InputHandle - > IsValid ( ) )
{
InFunction ( InputHandle ) ;
}
}
}
2021-01-13 10:48:59 -04:00
TArray < FOutputHandle > FBaseNodeController : : GetOutputs ( )
{
TArray < FOutputHandle > Outputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FOutputControllerParams & Params : GetOutputControllerParams ( ) )
{
2021-02-24 18:37:19 -04:00
FOutputHandle OutputHandle = CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
2021-03-19 15:10:57 -04:00
int32 FBaseNodeController : : GetNumOutputs ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return Node - > Interface . Outputs . Num ( ) ;
2021-03-19 15:10:57 -04:00
}
return 0 ;
}
2021-01-13 10:48:59 -04:00
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 ( ) )
{
2021-02-24 18:37:19 -04:00
FConstInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
2021-03-19 15:10:57 -04:00
void FBaseNodeController : : IterateOutputs ( TUniqueFunction < void ( FOutputHandle ) > InFunction )
{
for ( const FOutputControllerParams & Params : GetOutputControllerParams ( ) )
{
FOutputHandle OutputHandle = CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , AsShared ( ) ) ;
if ( OutputHandle - > IsValid ( ) )
{
InFunction ( OutputHandle ) ;
}
}
}
const FText & FBaseNodeController : : GetDisplayTitle ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Metadata . DisplayName ;
2021-03-19 15:10:57 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FBaseNodeController : : GetDisplayName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return Class - > Metadata . DisplayName ;
2021-03-19 15:10:57 -04:00
}
return FText : : GetEmpty ( ) ;
}
void FBaseNodeController : : IterateConstInputs ( TUniqueFunction < void ( FConstInputHandle ) > InFunction ) const
{
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
for ( const FInputControllerParams & Params : GetInputControllerParams ( ) )
{
FConstInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
if ( InputHandle - > IsValid ( ) )
{
InFunction ( InputHandle ) ;
}
}
}
2021-01-13 10:48:59 -04:00
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 ( ) )
{
2021-02-24 18:37:19 -04:00
FConstOutputHandle OutputHandle = CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
2021-03-19 15:10:57 -04:00
void FBaseNodeController : : IterateConstOutputs ( TUniqueFunction < void ( FConstOutputHandle ) > InFunction ) const
{
// 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 . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
if ( OutputHandle - > IsValid ( ) )
{
InFunction ( OutputHandle ) ;
}
}
}
2021-01-13 10:48:59 -04:00
TArray < FInputHandle > FBaseNodeController : : GetInputsWithVertexName ( const FString & InName )
{
TArray < FInputHandle > Inputs ;
FNodeHandle ThisNode = this - > AsShared ( ) ;
for ( const FInputControllerParams & Params : GetInputControllerParamsWithVertexName ( InName ) )
{
2021-02-24 18:37:19 -04:00
FInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( InputHandle - > IsValid ( ) )
{
Inputs . Add ( InputHandle ) ;
}
}
return Inputs ;
}
2021-05-20 19:33:21 -04:00
TArray < FConstInputHandle > FBaseNodeController : : GetConstInputsWithVertexName ( const FString & InName ) const
2021-01-13 10:48:59 -04:00
{
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 ) )
{
2021-02-24 18:37:19 -04:00
FInputHandle InputHandle = CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
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 ) )
{
2021-02-24 18:37:19 -04:00
FOutputHandle OutputHandle = CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
2021-05-20 19:33:21 -04:00
TArray < FConstOutputHandle > FBaseNodeController : : GetConstOutputsWithVertexName ( const FString & InName ) const
2021-01-13 10:48:59 -04:00
{
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 ) )
{
2021-02-24 18:37:19 -04:00
FConstOutputHandle OutputHandle = CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
if ( OutputHandle - > IsValid ( ) )
{
Outputs . Add ( OutputHandle ) ;
}
}
return Outputs ;
}
2021-02-24 18:37:19 -04:00
FInputHandle FBaseNodeController : : GetInputWithID ( FGuid InVertexID )
2021-01-13 10:48:59 -04:00
{
FInputControllerParams Params ;
2021-02-24 18:37:19 -04:00
if ( FindInputControllerParamsWithID ( InVertexID , Params ) )
2021-01-13 10:48:59 -04:00
{
FNodeHandle ThisNode = this - > AsShared ( ) ;
2021-02-24 18:37:19 -04:00
return CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-06-23 20:07:53 -04:00
bool FBaseNodeController : : IsRequired ( ) const
2021-03-19 15:10:57 -04:00
{
return false ;
}
2021-02-24 18:37:19 -04:00
FConstInputHandle FBaseNodeController : : GetInputWithID ( FGuid InVertexID ) const
2021-01-13 10:48:59 -04:00
{
FInputControllerParams Params ;
2021-02-24 18:37:19 -04:00
if ( FindInputControllerParamsWithID ( InVertexID , Params ) )
2021-01-13 10:48:59 -04:00
{
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
2021-02-24 18:37:19 -04:00
return CreateInputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassInputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidInputController : : GetInvalid ( ) ;
}
2021-02-24 18:37:19 -04:00
FOutputHandle FBaseNodeController : : GetOutputWithID ( FGuid InVertexID )
2021-01-13 10:48:59 -04:00
{
FOutputControllerParams Params ;
2021-02-24 18:37:19 -04:00
if ( FindOutputControllerParamsWithID ( InVertexID , Params ) )
2021-01-13 10:48:59 -04:00
{
FNodeHandle ThisNode = this - > AsShared ( ) ;
2021-02-24 18:37:19 -04:00
return CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
2021-02-24 18:37:19 -04:00
FConstOutputHandle FBaseNodeController : : GetOutputWithID ( FGuid InVertexID ) const
2021-01-13 10:48:59 -04:00
{
FOutputControllerParams Params ;
2021-02-24 18:37:19 -04:00
if ( FindOutputControllerParamsWithID ( InVertexID , Params ) )
2021-01-13 10:48:59 -04:00
{
// See early use of ConstCastSharedRef in this class for discussion.
FNodeHandle ThisNode = ConstCastSharedRef < INodeController > ( this - > AsShared ( ) ) ;
2021-02-24 18:37:19 -04:00
return CreateOutputController ( Params . VertexID , Params . NodeVertexPtr , Params . ClassOutputPtr , ThisNode ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidOutputController : : GetInvalid ( ) ;
}
TArray < FBaseNodeController : : FInputControllerParams > FBaseNodeController : : GetInputControllerParams ( ) const
{
TArray < FBaseNodeController : : FInputControllerParams > Inputs ;
2021-05-20 19:33:21 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-05-20 19:33:21 -04:00
for ( const FMetasoundFrontendVertex & NodeInputVertex : Node - > Interface . Inputs )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetInputWithName ( NodeInputVertex . Name ) ;
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetInputWithName ( NodeInputVertex . Name ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
Inputs . Add ( { NodeInputVertex . VertexID , NodeVertexPtr , ClassInputPtr } ) ;
2021-01-13 10:48:59 -04:00
}
}
return Inputs ;
}
TArray < FBaseNodeController : : FOutputControllerParams > FBaseNodeController : : GetOutputControllerParams ( ) const
{
TArray < FBaseNodeController : : FOutputControllerParams > Outputs ;
2021-05-20 19:33:21 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-05-20 19:33:21 -04:00
for ( const FMetasoundFrontendVertex & NodeOutputVertex : Node - > Interface . Outputs )
{
const FString & VertexName = NodeOutputVertex . Name ;
2021-01-13 10:48:59 -04:00
2021-05-20 19:33:21 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetOutputWithName ( VertexName ) ;
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetOutputWithName ( VertexName ) ;
2021-01-13 10:48:59 -04:00
2021-05-20 19:33:21 -04:00
Outputs . Add ( { NodeOutputVertex . VertexID , NodeVertexPtr , ClassOutputPtr } ) ;
}
2021-01-13 10:48:59 -04:00
}
return Outputs ;
}
TArray < FBaseNodeController : : FInputControllerParams > FBaseNodeController : : GetInputControllerParamsWithVertexName ( const FString & InName ) const
{
TArray < FBaseNodeController : : FInputControllerParams > Inputs ;
2021-05-10 19:52:56 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetInputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
2021-05-10 19:52:56 -04:00
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetInputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
Inputs . Add ( { Vertex - > VertexID , NodeVertexPtr , ClassInputPtr } ) ;
2021-01-13 10:48:59 -04:00
}
return Inputs ;
}
TArray < FBaseNodeController : : FOutputControllerParams > FBaseNodeController : : GetOutputControllerParamsWithVertexName ( const FString & InName ) const
{
TArray < FBaseNodeController : : FOutputControllerParams > Outputs ;
2021-05-10 19:52:56 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetOutputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
2021-05-10 19:52:56 -04:00
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetOutputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
Outputs . Add ( { Vertex - > VertexID , NodeVertexPtr , ClassOutputPtr } ) ;
2021-01-13 10:48:59 -04:00
}
return Outputs ;
}
2021-02-24 18:37:19 -04:00
bool FBaseNodeController : : FindInputControllerParamsWithID ( FGuid InVertexID , FInputControllerParams & OutParams ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetInputWithVertexID ( InVertexID ) ;
2021-01-13 10:48:59 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
2021-05-10 19:52:56 -04:00
FConstClassInputAccessPtr ClassInputPtr = ClassPtr . GetInputWithName ( Vertex - > Name ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
OutParams = FInputControllerParams { InVertexID , NodeVertexPtr , ClassInputPtr } ;
2021-01-13 10:48:59 -04:00
return true ;
}
return false ;
}
2021-02-24 18:37:19 -04:00
bool FBaseNodeController : : FindOutputControllerParamsWithID ( FGuid InVertexID , FOutputControllerParams & OutParams ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FConstVertexAccessPtr NodeVertexPtr = NodePtr . GetOutputWithVertexID ( InVertexID ) ;
2021-01-13 10:48:59 -04:00
if ( const FMetasoundFrontendVertex * Vertex = NodeVertexPtr . Get ( ) )
{
2021-05-10 19:52:56 -04:00
FConstClassOutputAccessPtr ClassOutputPtr = ClassPtr . GetOutputWithName ( Vertex - > Name ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
OutParams = FOutputControllerParams { InVertexID , NodeVertexPtr , ClassOutputPtr } ;
2021-01-13 10:48:59 -04:00
return true ;
}
return false ;
}
FGraphHandle FBaseNodeController : : AsGraph ( )
{
// TODO: consider adding support for external graph owned in another document.
// Will require lookup support for external subgraphs..
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GetOwningGraph ( ) - > GetOwningDocument ( ) - > GetSubgraphWithClassID ( Class - > ID ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FBaseNodeController : : AsGraph ( ) const
{
// TODO: add support for graph owned in another asset.
// Will require lookup support for external subgraphs..
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GetOwningGraph ( ) - > GetOwningDocument ( ) - > GetSubgraphWithClassID ( Class - > ID ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
2021-05-20 19:33:21 -04:00
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-05-03 17:52:04 -04:00
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 )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
// Cannot make a valid node handle if the node description and class description differ
if ( Node - > ClassID = = Class - > ID )
{
return MakeShared < FNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FNodeController : : CreateConstNodeHandle ( const FNodeController : : FInitParams & InParams )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
// Cannot make a valid node handle if the node description and class description differ
if ( Node - > ClassID = = Class - > ID )
{
return MakeShared < const FNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FNodeController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return FBaseNodeController : : IsValid ( ) & & ( nullptr ! = GraphPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FInputHandle FNodeController : : CreateInputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
return MakeShared < FBaseInputController > ( FBaseInputController : : FInitParams { InVertexID , InNodeVertexPtr , InClassInputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FOutputHandle FNodeController : : CreateOutputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
return MakeShared < FBaseOutputController > ( FBaseOutputController : : FInitParams { InVertexID , 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-05-03 17:52:04 -04:00
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 )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( EMetasoundFrontendClassType : : Output = = Class - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( Class - > ID = = Node - > ClassID )
{
return MakeShared < FOutputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating output node.. Must be EMetasoundFrontendClassType::Output. " ) , * Class - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
2021-03-19 15:10:57 -04:00
const FText & FOutputNodeController : : GetDescription ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata . Description ;
2021-03-19 15:10:57 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FOutputNodeController : : GetDisplayName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassOutput * OwningOutput = OwningGraphClassOutputPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningOutput - > Metadata . DisplayName ;
2021-03-19 15:10:57 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
void FOutputNodeController : : SetDescription ( const FText & InDescription )
{
2021-05-10 19:52:56 -04:00
// TODO: can we remove the const cast by constructing output nodes with a non-const access to class outputs?
if ( FMetasoundFrontendClassOutput * ClassOutput = ConstCastAccessPtr < FClassOutputAccessPtr > ( OwningGraphClassOutputPtr ) . Get ( ) )
2021-03-19 15:10:57 -04:00
{
ClassOutput - > Metadata . Description = InDescription ;
}
}
void FOutputNodeController : : SetDisplayName ( const FText & InDisplayName )
{
2021-05-10 19:52:56 -04:00
// TODO: can we remove the const cast by constructing output nodes with a non-const access to class outputs?
if ( FMetasoundFrontendClassOutput * ClassOutput = ConstCastAccessPtr < FClassOutputAccessPtr > ( OwningGraphClassOutputPtr ) . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-05-10 19:52:56 -04:00
ClassOutput - > Metadata . DisplayName = InDisplayName ;
2021-03-19 15:10:57 -04:00
}
}
2021-01-13 10:48:59 -04:00
FConstNodeHandle FOutputNodeController : : CreateConstOutputNodeHandle ( const FOutputNodeController : : FInitParams & InParams )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( EMetasoundFrontendClassType : : Output = = Class - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( Class - > ID = = Node - > ClassID )
{
return MakeShared < const FOutputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating output node.. Must be EMetasoundFrontendClassType::Output. " ) , * Class - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
2021-03-19 15:10:57 -04:00
const FText & FOutputNodeController : : GetDisplayTitle ( ) const
{
static FText OutputDisplayTitle = LOCTEXT ( " OutputNode_Title " , " Output " ) ;
return OutputDisplayTitle ;
}
2021-06-23 20:07:53 -04:00
bool FOutputNodeController : : IsRequired ( ) const
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
FConstDocumentHandle OwningDocument = OwningGraph - > GetOwningDocument ( ) ;
FConstGraphHandle RootGraph = OwningDocument - > GetRootGraph ( ) ;
// Test if this node exists on the document's root graph.
const bool bIsNodeOnRootGraph = OwningGraph - > IsValid ( ) & & ( RootGraph - > GetClassID ( ) = = OwningGraph - > GetClassID ( ) ) ;
if ( bIsNodeOnRootGraph )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
// If the node is on the root graph, test if it is in the archetypes
// required inputs or outputs.
FMetasoundFrontendArchetype Archetype ;
FArchetypeRegistryKey ArchetypeKey = GetArchetypeRegistryKey ( OwningDocument - > GetArchetypeVersion ( ) ) ;
bool bFoundArchetype = IArchetypeRegistry : : Get ( ) . FindArchetype ( ArchetypeKey , Archetype ) ;
if ( bFoundArchetype )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
const FString & Name = Node - > Name ;
auto IsVertexWithSameName = [ & Name ] ( const FMetasoundFrontendClassVertex & InVertex )
{
return InVertex . Name = = Name ;
} ;
return Archetype . Interface . Outputs . ContainsByPredicate ( IsVertexWithSameName ) ;
2021-03-19 15:10:57 -04:00
}
}
2021-06-23 20:07:53 -04:00
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Document using unregistered archetype [ArchetypeVersion:%s] " ) , * OwningDocument - > GetArchetypeVersion ( ) . ToString ( ) ) ;
}
2021-03-19 15:10:57 -04:00
}
return false ;
}
2021-01-13 10:48:59 -04:00
bool FOutputNodeController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return OwningGraph - > IsValid ( ) & & ( nullptr ! = OwningGraphClassOutputPtr . Get ( ) ) & & ( nullptr ! = GraphPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FInputHandle FOutputNodeController : : CreateInputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
return MakeShared < FOutputNodeInputController > ( FOutputNodeInputController : : FInitParams { InVertexID , InNodeVertexPtr , InClassInputPtr , OwningGraphClassOutputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FOutputHandle FOutputNodeController : : CreateOutputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-11 21:12:31 -04:00
return MakeShared < FOutputNodeOutputController > ( FOutputNodeOutputController : : FInitParams { InVertexID , InNodeVertexPtr , InClassOutputPtr , OwningGraphClassOutputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-03-19 15:10:57 -04:00
FDocumentAccess FOutputNodeController : : ShareAccess ( )
2021-01-20 17:26:40 -04:00
{
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-05-03 17:52:04 -04:00
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 )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( EMetasoundFrontendClassType : : Input = = Class - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( Class - > ID = = Node - > ClassID )
{
return MakeShared < FInputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating input node. Must be EMetasoundFrontendClassType::Input. " ) , * Class - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FInputNodeController : : CreateConstInputNodeHandle ( const FInputNodeController : : FInitParams & InParams )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendNode * Node = InParams . NodePtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = InParams . ClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( EMetasoundFrontendClassType : : Input = = Class - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( Class - > ID = = Node - > ClassID )
{
return MakeShared < const FInputNodeController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Node [NodeID:%s, ClassID:%s] is not of expected class class [ClassID:%s] " ) , * Node - > ID . ToString ( ) , * Node - > ClassID . ToString ( ) , * Class - > ID . ToString ( ) ) ;
}
2021-01-13 10:48:59 -04:00
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Frontend Class of incorrect class type [ClassID:%s] while creating input node. Must be EMetasoundFrontendClassType::Input. " ) , * Class - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FInputNodeController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return OwningGraph - > IsValid ( ) & & ( nullptr ! = OwningGraphClassInputPtr . Get ( ) ) & & ( nullptr ! = GraphPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FInputHandle FInputNodeController : : CreateInputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassInputAccessPtr InClassInputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-11 21:12:31 -04:00
return MakeShared < FInputNodeInputController > ( FInputNodeInputController : : FInitParams { InVertexID , InNodeVertexPtr , InClassInputPtr , OwningGraphClassInputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FOutputHandle FInputNodeController : : CreateOutputController ( FGuid InVertexID , FConstVertexAccessPtr InNodeVertexPtr , FConstClassOutputAccessPtr InClassOutputPtr , FNodeHandle InOwningNode ) const
2021-01-13 10:48:59 -04:00
{
2021-03-03 15:00:53 -04:00
return MakeShared < FInputNodeOutputController > ( FInputNodeOutputController : : FInitParams { InVertexID , InNodeVertexPtr , InClassOutputPtr , OwningGraphClassInputPtr , GraphPtr , InOwningNode } ) ;
2021-01-13 10:48:59 -04:00
}
2021-03-19 15:10:57 -04:00
const FText & FInputNodeController : : GetDescription ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningInput - > Metadata . Description ;
2021-03-19 15:10:57 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FInputNodeController : : GetDisplayName ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClassInput * OwningInput = OwningGraphClassInputPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
return OwningInput - > Metadata . DisplayName ;
2021-03-19 15:10:57 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
}
const FText & FInputNodeController : : GetDisplayTitle ( ) const
{
static FText InputDisplayTitle = LOCTEXT ( " InputNode_Title " , " Input " ) ;
return InputDisplayTitle ;
}
2021-06-23 20:07:53 -04:00
bool FInputNodeController : : IsRequired ( ) const
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
FConstDocumentHandle OwningDocument = OwningGraph - > GetOwningDocument ( ) ;
FConstGraphHandle RootGraph = OwningDocument - > GetRootGraph ( ) ;
// Test if this node exists on the document's root graph.
const bool bIsNodeOnRootGraph = OwningGraph - > IsValid ( ) & & ( RootGraph - > GetClassID ( ) = = OwningGraph - > GetClassID ( ) ) ;
if ( bIsNodeOnRootGraph )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
// If the node is on the root graph, test if it is in the archetypes
// required inputs or outputs.
FMetasoundFrontendArchetype Archetype ;
FArchetypeRegistryKey ArchetypeKey = GetArchetypeRegistryKey ( OwningDocument - > GetArchetypeVersion ( ) ) ;
bool bFoundArchetype = IArchetypeRegistry : : Get ( ) . FindArchetype ( ArchetypeKey , Archetype ) ;
if ( bFoundArchetype )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
if ( const FMetasoundFrontendNode * Node = NodePtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-06-23 20:07:53 -04:00
const FString & Name = Node - > Name ;
auto IsVertexWithSameName = [ & Name ] ( const FMetasoundFrontendClassVertex & InVertex )
{
return InVertex . Name = = Name ;
} ;
return Archetype . Interface . Inputs . ContainsByPredicate ( IsVertexWithSameName ) ;
2021-03-19 15:10:57 -04:00
}
}
2021-06-23 20:07:53 -04:00
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Document using unregistered archetype [ArchetypeVersion:%s] " ) , * OwningDocument - > GetArchetypeVersion ( ) . ToString ( ) ) ;
}
2021-03-19 15:10:57 -04:00
}
return false ;
}
void FInputNodeController : : SetDescription ( const FText & InDescription )
{
2021-05-10 19:52:56 -04:00
// TODO: can we remove these const casts by constructing FINputNodeController with non-const access to the class input?
if ( FMetasoundFrontendClassInput * ClassInput = ConstCastAccessPtr < FClassInputAccessPtr > ( OwningGraphClassInputPtr ) . Get ( ) )
2021-03-19 15:10:57 -04:00
{
ClassInput - > Metadata . Description = InDescription ;
}
}
void FInputNodeController : : SetDisplayName ( const FText & InDisplayName )
{
2021-05-10 19:52:56 -04:00
// TODO: can we remove these const casts by constructing FINputNodeController with non-const access to the class input?
if ( FMetasoundFrontendClassInput * ClassInput = ConstCastAccessPtr < FClassInputAccessPtr > ( OwningGraphClassInputPtr ) . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-05-10 19:52:56 -04:00
ClassInput - > Metadata . DisplayName = InDisplayName ;
2021-03-19 15:10:57 -04:00
}
}
FDocumentAccess FInputNodeController : : ShareAccess ( )
2021-01-20 17:26:40 -04:00
{
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 )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = InParams . GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( GraphClass - > Metadata . Type = = EMetasoundFrontendClassType : : Graph )
2021-01-13 10:48:59 -04:00
{
return MakeShared < FGraphController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to make graph controller [ClassID:%s]. Class must be EMeatsoundFrontendClassType::Graph. " ) , * GraphClass - > ID . ToString ( ) )
2021-01-13 10:48:59 -04:00
}
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FGraphController : : CreateConstGraphHandle ( const FGraphController : : FInitParams & InParams )
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = InParams . GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( GraphClass - > Metadata . Type = = EMetasoundFrontendClassType : : Graph )
2021-01-13 10:48:59 -04:00
{
return MakeShared < FGraphController > ( EPrivateToken : : Token , InParams ) ;
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to make graph controller [ClassID:%s]. Class must be EMeatsoundFrontendClassType::Graph. " ) , * GraphClass - > ID . ToString ( ) )
2021-01-13 10:48:59 -04:00
}
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
bool FGraphController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return ( nullptr ! = GraphClassPtr . Get ( ) ) & & OwningDocument - > IsValid ( ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FGuid FGraphController : : GetClassID ( ) const
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > ID ;
2021-01-13 10:48:59 -04:00
}
return Metasound : : FrontendInvalidID ;
}
2021-05-20 19:33:21 -04:00
const FText & FGraphController : : GetDisplayName ( ) const
2021-01-13 10:48:59 -04:00
{
2021-05-20 19:33:21 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
return GraphClass - > Metadata . DisplayName ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FText > ( ) ;
2021-01-13 10:48:59 -04:00
}
TArray < FString > FGraphController : : GetInputVertexNames ( ) const
{
TArray < FString > Names ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendClassInput & Input : GraphClass - > Interface . Inputs )
2021-01-13 10:48:59 -04:00
{
Names . Add ( Input . Name ) ;
}
}
return Names ;
}
TArray < FString > FGraphController : : GetOutputVertexNames ( ) const
{
TArray < FString > Names ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendClassOutput & Output : GraphClass - > Interface . Outputs )
2021-01-13 10:48:59 -04:00
{
Names . Add ( Output . Name ) ;
}
}
return Names ;
}
FConstClassInputAccessPtr FGraphController : : FindClassInputWithName ( const FString & InName ) const
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetInputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
}
FConstClassOutputAccessPtr FGraphController : : FindClassOutputWithName ( const FString & InName ) const
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetOutputWithName ( InName ) ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FGuid FGraphController : : GetVertexIDForInputVertex ( const FString & InInputName ) const
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendClassInput * Input = FindClassInputWithName ( InInputName ) . Get ( ) )
{
2021-02-24 18:37:19 -04:00
return Input - > VertexID ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
return Metasound : : FrontendInvalidID ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
FGuid FGraphController : : GetVertexIDForOutputVertex ( const FString & InOutputName ) const
2021-01-13 10:48:59 -04:00
{
if ( const FMetasoundFrontendClassOutput * Output = FindClassOutputWithName ( InOutputName ) . Get ( ) )
{
2021-02-24 18:37:19 -04:00
return Output - > VertexID ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
return Metasound : : FrontendInvalidID ;
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 ) ;
}
2021-06-08 10:52:31 -04:00
const FMetasoundFrontendGraphStyle & FGraphController : : GetGraphStyle ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-06-08 10:52:31 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Graph . Style ;
2021-06-08 10:52:31 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendGraphStyle > ( ) ;
}
void FGraphController : : SetGraphStyle ( const FMetasoundFrontendGraphStyle & InStyle )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-06-08 10:52:31 -04:00
{
2021-07-12 16:12:36 -04:00
GraphClass - > Graph . Style = InStyle ;
2021-06-08 10:52:31 -04:00
}
}
2021-01-13 10:48:59 -04:00
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 ) ;
}
2021-03-19 15:10:57 -04:00
void FGraphController : : IterateNodes ( TUniqueFunction < void ( FNodeHandle ) > InFunction , EMetasoundFrontendClassType InClassType )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-03-19 15:10:57 -04:00
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InClassType = = EMetasoundFrontendClassType : : Invalid | | NodeClass - > Metadata . Type = = InClassType )
{
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-03-19 15:10:57 -04:00
FNodeHandle NodeHandle = GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , NodeClassPtr } ) ;
InFunction ( NodeHandle ) ;
}
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-03-19 15:10:57 -04:00
}
}
}
}
void FGraphController : : IterateConstNodes ( TUniqueFunction < void ( FConstNodeHandle ) > InFunction , EMetasoundFrontendClassType InClassType ) const
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-03-19 15:10:57 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-03-19 15:10:57 -04:00
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InClassType = = EMetasoundFrontendClassType : : Invalid | | NodeClass - > Metadata . Type = = InClassType )
{
2021-05-10 19:52:56 -04:00
FConstNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-03-19 15:10:57 -04:00
FConstNodeHandle NodeHandle = GetNodeHandle ( FGraphController : : FConstNodeAndClass { NodePtr , NodeClassPtr } ) ;
InFunction ( NodeHandle ) ;
}
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to find class for node [NodeID:%s, ClassID:%s] " ) , * Node . ID . ToString ( ) , * Node . ClassID . ToString ( ) ) ;
2021-03-19 15:10:57 -04:00
}
}
}
}
2021-01-13 10:48:59 -04:00
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 )
{
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
auto IsInputWithSameName = [ & ] ( const FMetasoundFrontendClassInput & ExistingDesc ) { return ExistingDesc . Name = = InClassInput . Name ; } ;
if ( Algo : : NoneOf ( GraphClass - > Interface . Inputs , IsInputWithSameName ) )
{
2021-06-14 16:45:51 -04:00
FNodeRegistryKey Key ;
if ( FRegistry : : GetInputNodeRegistryKeyForDataType ( InClassInput . TypeName , Key ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FConstClassAccessPtr InputClassPtr = OwningDocument - > FindOrAddClass ( Key ) ;
if ( const FMetasoundFrontendClass * InputClass = InputClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * InputClass ) ;
2021-01-13 19:18:22 -04:00
Node . Name = InClassInput . Name ;
2021-05-20 19:33:21 -04:00
Node . ID = FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
auto IsVertexWithTypeName = [ & ] ( FMetasoundFrontendVertex & Vertex ) { return Vertex . TypeName = = InClassInput . TypeName ; } ;
if ( FMetasoundFrontendVertex * InputVertex = Node . Interface . Inputs . FindByPredicate ( IsVertexWithTypeName ) )
{
InputVertex - > Name = InClassInput . Name ;
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Input node [TypeName:%s] does not contain input vertex with type [TypeName:%s] " ) , * InClassInput . TypeName . ToString ( ) , * InClassInput . TypeName . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-03-03 15:00:53 -04:00
if ( Node . Interface . Outputs . Num ( ) = = 1 )
{
Node . Interface . Outputs [ 0 ] . Name = InClassInput . Name ;
}
else if ( FMetasoundFrontendVertex * OutputVertex = Node . Interface . Outputs . FindByPredicate ( IsVertexWithTypeName ) )
2021-01-13 10:48:59 -04:00
{
OutputVertex - > Name = InClassInput . Name ;
}
2021-07-12 16:12:36 -04:00
FMetasoundFrontendClassInput & NewInput = GraphClass - > Interface . Inputs . Add_GetRef ( InClassInput ) ;
2021-01-13 10:48:59 -04:00
NewInput . NodeID = Node . ID ;
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-07-12 16:12:36 -04:00
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , InputClassPtr } ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Failed to add input. No input node registered for data type [TypeName:%s] " ) , * InClassInput . TypeName . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Failed to add input. Input with same name \" %s \" exists in class [ClassID:%s] " ) , * InClassInput . Name , * GraphClass - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveInputVertex ( const FString & InName )
{
2021-07-12 16:12:36 -04:00
auto IsInputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & InClass , const FMetasoundFrontendNode & InNode )
{
return ( InClass . Metadata . Type = = EMetasoundFrontendClassType : : Input ) & & ( InNode . Name = = InName ) ;
} ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
for ( const FNodeAndClass & NodeAndClass : GetNodesAndClassesByPredicate ( IsInputNodeWithSameName ) )
{
if ( const FMetasoundFrontendNode * Node = NodeAndClass . Node . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return RemoveInput ( * Node ) ;
2021-01-13 10:48:59 -04:00
}
}
return false ;
}
FNodeHandle FGraphController : : AddOutputVertex ( const FMetasoundFrontendClassOutput & InClassOutput )
{
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
auto IsOutputWithSameName = [ & ] ( const FMetasoundFrontendClassOutput & ExistingDesc ) { return ExistingDesc . Name = = InClassOutput . Name ; } ;
if ( Algo : : NoneOf ( GraphClass - > Interface . Outputs , IsOutputWithSameName ) )
{
2021-06-14 16:45:51 -04:00
FNodeRegistryKey Key ;
if ( FRegistry : : GetOutputNodeRegistryKeyForDataType ( InClassOutput . TypeName , Key ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FConstClassAccessPtr OutputClassPtr = OwningDocument - > FindOrAddClass ( Key ) ;
if ( const FMetasoundFrontendClass * OutputClass = OutputClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * OutputClass ) ;
2021-01-13 19:18:22 -04:00
Node . Name = InClassOutput . Name ;
2021-05-20 19:33:21 -04:00
Node . ID = FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
// TODO: have something that checks if input node has valid interface.
auto IsVertexWithTypeName = [ & ] ( FMetasoundFrontendVertex & Vertex ) { return Vertex . TypeName = = InClassOutput . TypeName ; } ;
2021-03-03 15:00:53 -04:00
if ( Node . Interface . Inputs . Num ( ) = = 1 )
{
Node . Interface . Inputs [ 0 ] . Name = InClassOutput . Name ;
}
else if ( FMetasoundFrontendVertex * InputVertex = Node . Interface . Inputs . FindByPredicate ( IsVertexWithTypeName ) )
2021-01-13 10:48:59 -04:00
{
InputVertex - > Name = InClassOutput . Name ;
}
if ( FMetasoundFrontendVertex * OutputVertex = Node . Interface . Outputs . FindByPredicate ( IsVertexWithTypeName ) )
{
OutputVertex - > Name = InClassOutput . Name ;
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Output node [TypeName:%s] does not contain output vertex with type [TypeName:%s] " ) , * InClassOutput . TypeName . ToString ( ) , * InClassOutput . TypeName . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-07-12 16:12:36 -04:00
FMetasoundFrontendClassOutput & NewOutput = GraphClass - > Interface . Outputs . Add_GetRef ( InClassOutput ) ;
2021-01-13 10:48:59 -04:00
NewOutput . NodeID = Node . ID ;
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-07-12 16:12:36 -04:00
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , OutputClassPtr } ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Failed to add output. No output node registered for data type [TypeName:%s] " ) , * InClassOutput . TypeName . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
else
{
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Display , TEXT ( " Failed to add output. Output with same name \" %s \" exists in class [ClassID:%s] " ) , * InClassOutput . Name , * GraphClass - > ID . ToString ( ) ) ;
2021-01-13 10:48:59 -04:00
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveOutputVertex ( const FString & InName )
{
2021-07-12 16:12:36 -04:00
auto IsOutputNodeWithSameName = [ & ] ( const FMetasoundFrontendClass & InClass , const FMetasoundFrontendNode & InNode )
{
return ( InClass . Metadata . Type = = EMetasoundFrontendClassType : : Output ) & & ( InNode . Name = = InName ) ;
} ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
for ( const FNodeAndClass & NodeAndClass : GetNodesAndClassesByPredicate ( IsOutputNodeWithSameName ) )
{
if ( const FMetasoundFrontendNode * Node = NodeAndClass . Node . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return RemoveOutput ( * Node ) ;
2021-01-13 10:48:59 -04:00
}
}
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 ) )
{
2021-06-14 16:45:51 -04:00
return FRegistry : : Get ( ) - > GetDesiredLiteralTypeForDataType ( Desc - > TypeName ) ;
2021-01-13 10:48:59 -04:00
}
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 ) )
{
2021-06-14 16:45:51 -04:00
return FRegistry : : Get ( ) - > GetLiteralUClassForDataType ( Desc - > TypeName ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
2021-02-24 18:37:19 -04:00
FMetasoundFrontendLiteral FGraphController : : GetDefaultInput ( const FGuid & InVertexID ) const
2021-02-24 02:02:03 -04:00
{
2021-02-24 18:37:19 -04:00
if ( const FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithVertexID ( InVertexID ) )
2021-02-24 02:02:03 -04:00
{
2021-02-24 18:37:19 -04:00
return Desc - > DefaultLiteral ;
2021-02-24 02:02:03 -04:00
}
2021-02-24 18:37:19 -04:00
return FMetasoundFrontendLiteral { } ;
2021-02-24 02:02:03 -04:00
}
2021-02-24 18:37:19 -04:00
bool FGraphController : : SetDefaultInput ( const FGuid & InVertexID , const FMetasoundFrontendLiteral & InLiteral )
2021-01-13 10:48:59 -04:00
{
2021-02-24 18:37:19 -04:00
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithVertexID ( InVertexID ) )
2021-02-03 14:36:36 -04:00
{
2021-02-24 02:02:03 -04:00
if ( ensure ( DoesDataTypeSupportLiteralType ( Desc - > TypeName , InLiteral . GetType ( ) ) ) )
2021-02-03 14:36:36 -04:00
{
2021-02-24 18:37:19 -04:00
Desc - > DefaultLiteral = InLiteral ;
2021-02-10 21:43:31 -04:00
return true ;
2021-02-03 14:36:36 -04:00
}
2021-02-10 21:43:31 -04:00
else
2021-02-03 14:36:36 -04:00
{
2021-02-24 18:37:19 -04:00
SetDefaultInputToDefaultLiteralOfType ( InVertexID ) ;
2021-02-03 14:36:36 -04:00
}
}
2021-02-10 21:43:31 -04:00
return false ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 18:37:19 -04:00
bool FGraphController : : SetDefaultInputToDefaultLiteralOfType ( const FGuid & InVertexID )
2021-01-13 10:48:59 -04:00
{
2021-02-24 18:37:19 -04:00
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithVertexID ( InVertexID ) )
{
Metasound : : FLiteral Literal = Frontend : : GetDefaultParamForDataType ( Desc - > TypeName ) ;
Desc - > DefaultLiteral . SetFromLiteral ( Literal ) ;
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
return Desc - > DefaultLiteral . IsValid ( ) ;
}
2021-01-13 10:48:59 -04:00
2021-02-24 18:37:19 -04:00
return false ;
2021-01-13 10:48:59 -04:00
}
2021-02-24 02:02:03 -04:00
const FText & FGraphController : : GetInputDescription ( const FString & InName ) const
{
if ( const FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InName ) )
{
return Desc - > Metadata . Description ;
}
return FText : : GetEmpty ( ) ;
}
const FText & FGraphController : : GetOutputDescription ( const FString & InName ) const
{
if ( const FMetasoundFrontendClassOutput * Desc = FindOutputDescriptionWithName ( InName ) )
{
return Desc - > Metadata . Description ;
}
return FText : : GetEmpty ( ) ;
}
void FGraphController : : SetInputDisplayName ( const FString & InName , const FText & InDisplayName )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InName ) )
{
Desc - > Metadata . DisplayName = InDisplayName ;
}
}
2021-02-24 02:02:03 -04:00
void FGraphController : : SetOutputDisplayName ( const FString & InName , const FText & InDisplayName )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendClassOutput * Desc = FindOutputDescriptionWithName ( InName ) )
{
Desc - > Metadata . DisplayName = InDisplayName ;
}
}
2021-02-24 02:02:03 -04:00
void FGraphController : : SetInputDescription ( const FString & InName , const FText & InDescription )
{
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InName ) )
{
Desc - > Metadata . Description = InDescription ;
}
}
void FGraphController : : SetOutputDescription ( const FString & InName , const FText & InDescription )
{
if ( FMetasoundFrontendClassOutput * Desc = FindOutputDescriptionWithName ( InName ) )
{
Desc - > Metadata . Description = InDescription ;
}
}
2021-01-13 10:48:59 -04:00
// This can be used to clear the current literal for a given input.
// @returns false if the input name couldn't be found.
2021-02-24 18:37:19 -04:00
bool FGraphController : : ClearLiteralForInput ( const FString & InInputName , FGuid InVertexID )
2021-01-13 10:48:59 -04:00
{
if ( FMetasoundFrontendClassInput * Desc = FindInputDescriptionWithName ( InInputName ) )
{
2021-02-24 18:37:19 -04:00
Desc - > DefaultLiteral . Clear ( ) ;
2021-01-13 10:48:59 -04:00
}
return false ;
}
2021-06-14 16:45:51 -04:00
FNodeHandle FGraphController : : AddNode ( const FNodeRegistryKey & InKey )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
// Construct a FNodeClassInfo from this lookup key.
FConstClassAccessPtr Class = OwningDocument - > FindOrAddClass ( InKey ) ;
const bool bIsValidClass = ( nullptr ! = Class . Get ( ) ) ;
if ( bIsValidClass )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return AddNode ( Class ) ;
2021-01-13 10:48:59 -04:00
}
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Warning , TEXT ( " Failed to find or add node class info with registry key [Key:%s] " ) , * InKey ) ;
return INodeController : : GetInvalidHandle ( ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-22 03:05:22 -04:00
FNodeHandle FGraphController : : AddNode ( const FMetasoundFrontendClassMetadata & InClassMetadata )
{
2021-07-12 16:12:36 -04:00
return AddNode ( NodeRegistryKey : : CreateKey ( InClassMetadata ) ) ;
2021-01-22 03:05:22 -04:00
}
2021-05-20 19:33:21 -04:00
FNodeHandle FGraphController : : AddDuplicateNode ( const INodeController & InNode )
{
2021-07-12 16:12:36 -04:00
// TODO: will need to copy node interface when dynamic pins exist.
2021-05-20 19:33:21 -04:00
const FMetasoundFrontendClassMetadata & ClassMetadata = InNode . GetClassMetadata ( ) ;
2021-07-12 16:12:36 -04:00
FConstClassAccessPtr ClassPtr ;
2021-05-20 19:33:21 -04:00
if ( EMetasoundFrontendClassType : : Graph = = ClassMetadata . Type )
{
// Add subgraph and dependencies if needed
2021-07-12 16:12:36 -04:00
ClassPtr = OwningDocument - > FindClass ( ClassMetadata ) ;
const bool bIsClassMissing = ( nullptr = = ClassPtr . Get ( ) ) ;
if ( bIsClassMissing )
2021-05-20 19:33:21 -04:00
{
// Class does not exist, need to add the subgraph
OwningDocument - > AddDuplicateSubgraph ( * ( InNode . AsGraph ( ) ) ) ;
2021-07-12 16:12:36 -04:00
ClassPtr = OwningDocument - > FindClass ( ClassMetadata ) ;
2021-05-20 19:33:21 -04:00
}
}
2021-07-12 16:12:36 -04:00
else
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
ClassPtr = OwningDocument - > FindOrAddClass ( ClassMetadata ) ;
2021-05-20 19:33:21 -04:00
}
2021-07-12 16:12:36 -04:00
return AddNode ( ClassPtr ) ;
2021-05-20 19:33:21 -04:00
}
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-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FGuid NodeID = InNode . GetID ( ) ;
auto IsNodeWithSameID = [ & ] ( const FMetasoundFrontendNode & InDesc ) { return InDesc . ID = = NodeID ; } ;
if ( const FMetasoundFrontendNode * Desc = GraphClass - > Graph . Nodes . FindByPredicate ( IsNodeWithSameID ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
switch ( InNode . GetClassMetadata ( ) . Type )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
case EMetasoundFrontendClassType : : Input :
{
return RemoveInput ( * Desc ) ;
}
2021-05-03 17:52:04 -04:00
2021-07-12 16:12:36 -04:00
case EMetasoundFrontendClassType : : Output :
{
return RemoveOutput ( * Desc ) ;
}
2021-05-03 17:52:04 -04:00
2021-07-12 16:12:36 -04:00
case EMetasoundFrontendClassType : : Variable :
case EMetasoundFrontendClassType : : External :
case EMetasoundFrontendClassType : : Graph :
{
return RemoveNode ( * Desc ) ;
}
2021-05-03 17:52:04 -04:00
2021-07-12 16:12:36 -04:00
default :
case EMetasoundFrontendClassType : : Invalid :
{
static_assert ( static_cast < int32 > ( EMetasoundFrontendClassType : : Invalid ) = = 5 , " Possible missing switch case coverage for EMetasoundFrontendClassType. " ) ;
checkNoEntry ( ) ;
}
2021-05-03 17:52:04 -04:00
}
2021-01-13 10:48:59 -04:00
}
}
return false ;
}
// Returns the metadata for the current graph, including the name, description and author.
const FMetasoundFrontendClassMetadata & FGraphController : : GetGraphMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Metadata ;
2021-01-13 10:48:59 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendClassMetadata > ( ) ;
}
2021-06-08 10:52:31 -04:00
void FGraphController : : SetGraphMetadata ( const FMetasoundFrontendClassMetadata & InMetadata )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-06-08 10:52:31 -04:00
{
2021-07-12 16:12:36 -04:00
GraphClass - > Metadata = InMetadata ;
2021-06-08 10:52:31 -04:00
}
}
2021-01-13 10:48:59 -04:00
FNodeHandle FGraphController : : CreateEmptySubgraph ( const FMetasoundFrontendClassMetadata & InInfo )
{
2021-07-12 16:12:36 -04:00
if ( InInfo . Type = = EMetasoundFrontendClassType : : Graph )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * ExistingDependency = OwningDocument - > FindClass ( InInfo ) . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -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
}
2021-07-12 16:12:36 -04:00
else
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return AddNode ( OwningDocument - > FindOrAddClass ( InInfo ) ) ;
2021-01-13 10:48:59 -04:00
}
}
2021-07-12 16:12:36 -04:00
else
{
UE_LOG ( LogMetaSound , Warning , TEXT ( " Incompatible Metasound NodeType encountered when attempting to create an empty subgraph. NodeType must equal EMetasoundFrontendClassType::Graph " ) ) ;
}
2021-01-13 10:48:59 -04:00
return FInvalidNodeController : : GetInvalid ( ) ;
}
TUniquePtr < IOperator > FGraphController : : BuildOperator ( const FOperatorSettings & InSettings , const FMetasoundEnvironment & InEnvironment , TArray < IOperatorBuilder : : FBuildErrorPtr > & OutBuildErrors ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
// TODO: Implement subgraph inflation step here.
// TODO: bubble up errors.
TArray < FMetasoundFrontendGraphClass > Subgraphs = OwningDocument - > GetSubgraphs ( ) ;
TArray < FMetasoundFrontendClass > Dependencies = OwningDocument - > GetDependencies ( ) ;
TUniquePtr < FFrontendGraph > Graph = FFrontendGraphBuilder : : CreateGraph ( * GraphClass , Subgraphs , Dependencies ) ;
if ( ! Graph . IsValid ( ) )
{
return TUniquePtr < IOperator > ( nullptr ) ;
}
FOperatorBuilder OperatorBuilder ( FOperatorBuilderSettings : : GetDefaultSettings ( ) ) ;
FBuildGraphParams BuildParams { * Graph , InSettings , FDataReferenceCollection { } , InEnvironment } ;
return OperatorBuilder . BuildGraphOperator ( BuildParams , OutBuildErrors ) ;
}
else
2021-01-13 10:48:59 -04:00
{
return TUniquePtr < IOperator > ( nullptr ) ;
}
}
FDocumentHandle FGraphController : : GetOwningDocument ( )
{
return OwningDocument ;
}
FConstDocumentHandle FGraphController : : GetOwningDocument ( ) const
{
return OwningDocument ;
}
FNodeHandle FGraphController : : AddNode ( FConstClassAccessPtr InExistingDependency )
{
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
{
if ( const FMetasoundFrontendClass * NodeClass = InExistingDependency . Get ( ) )
{
2021-07-12 16:12:36 -04:00
FMetasoundFrontendNode & Node = GraphClass - > Graph . Nodes . Emplace_GetRef ( * NodeClass ) ;
2021-01-13 10:48:59 -04:00
2021-05-20 19:33:21 -04:00
Node . ID = FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-01-13 10:48:59 -04:00
return GetNodeHandle ( FGraphController : : FNodeAndClass { NodePtr , InExistingDependency } ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
bool FGraphController : : RemoveNode ( const FMetasoundFrontendNode & InDesc )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
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-07-12 16:12:36 -04:00
int32 NumRemoved = GraphClass - > Graph . Edges . RemoveAll ( IsEdgeForThisNode ) ;
2021-01-13 10:48:59 -04:00
auto IsNodeWithID = [ & ] ( const FMetasoundFrontendNode & Desc ) { return InDesc . ID = = Desc . ID ; } ;
2021-07-12 16:12:36 -04:00
NumRemoved + = GraphClass - > Graph . Nodes . RemoveAll ( IsNodeWithID ) ;
2021-01-13 10:48:59 -04:00
2021-05-03 17:52:04 -04:00
OwningDocument - > SynchronizeDependencies ( ) ;
2021-01-13 10:48:59 -04:00
return ( NumRemoved > 0 ) ;
}
return false ;
}
bool FGraphController : : RemoveInput ( const FMetasoundFrontendNode & InNode )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
auto IsInputWithSameNodeID = [ & ] ( const FMetasoundFrontendClassInput & ClassInput ) { return ClassInput . NodeID = = InNode . ID ; } ;
2021-07-12 16:12:36 -04:00
int32 NumInputsRemoved = GraphClass - > Interface . Inputs . RemoveAll ( IsInputWithSameNodeID ) ;
2021-01-13 10:48:59 -04:00
bool bDidRemoveNode = RemoveNode ( InNode ) ;
return ( NumInputsRemoved > 0 ) | | bDidRemoveNode ;
}
return false ;
}
bool FGraphController : : RemoveOutput ( const FMetasoundFrontendNode & InNode )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
auto IsOutputWithSameNodeID = [ & ] ( const FMetasoundFrontendClassOutput & ClassOutput ) { return ClassOutput . NodeID = = InNode . ID ; } ;
2021-07-12 16:12:36 -04:00
int32 NumOutputsRemoved = GraphClass - > Interface . Outputs . RemoveAll ( IsOutputWithSameNodeID ) ;
2021-01-13 10:48:59 -04:00
bool bDidRemoveNode = RemoveNode ( InNode ) ;
return ( NumOutputsRemoved > 0 ) | | bDidRemoveNode ;
}
return false ;
}
bool FGraphController : : ContainsNodesAndClassesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate ) const
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-01-13 10:48:59 -04:00
{
const FMetasoundFrontendClass * NodeClass = OwningDocument - > FindClassWithID ( Node . ClassID ) . Get ( ) ;
if ( nullptr ! = NodeClass )
{
if ( InPredicate ( * NodeClass , Node ) )
{
return true ;
}
}
else
{
2021-04-02 03:03:27 -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 ( )
{
TArray < FNodeAndClass > NodesAndClasses ;
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-01-13 10:48:59 -04:00
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
2021-01-20 17:26:40 -04:00
2021-07-12 16:12:36 -04:00
const bool bIsValidNodePtr = ( nullptr ! = NodePtr . Get ( ) ) ;
const bool bIsValidNodeClassPtr = ( nullptr ! = NodeClassPtr . Get ( ) ) ;
if ( bIsValidNodePtr & & bIsValidNodeClassPtr )
2021-01-13 10:48:59 -04:00
{
NodesAndClasses . Add ( FGraphController : : FNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
else
{
2021-04-02 03:03:27 -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
{
TArray < FConstNodeAndClass > NodesAndClasses ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FConstNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-01-13 10:48:59 -04:00
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
2021-01-20 17:26:40 -04:00
2021-07-12 16:12:36 -04:00
const bool bIsValidNodePtr = ( nullptr ! = NodePtr . Get ( ) ) ;
const bool bIsValidNodeClassPtr = ( nullptr ! = NodeClassPtr . Get ( ) ) ;
if ( bIsValidNodePtr & & bIsValidNodeClassPtr )
2021-01-13 10:48:59 -04:00
{
NodesAndClasses . Add ( FGraphController : : FConstNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
else
{
2021-04-02 03:03:27 -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 )
{
TArray < FNodeAndClass > NodesAndClasses ;
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-01-13 10:48:59 -04:00
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InPredicate ( * NodeClass , Node ) )
{
2021-05-10 19:52:56 -04:00
FNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-01-13 10:48:59 -04:00
NodesAndClasses . Add ( FGraphController : : FNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
}
else
{
2021-04-02 03:03:27 -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
{
TArray < FConstNodeAndClass > NodesAndClasses ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendNode & Node : GraphClass - > Graph . Nodes )
2021-01-13 10:48:59 -04:00
{
FConstClassAccessPtr NodeClassPtr = OwningDocument - > FindClassWithID ( Node . ClassID ) ;
if ( const FMetasoundFrontendClass * NodeClass = NodeClassPtr . Get ( ) )
{
if ( InPredicate ( * NodeClass , Node ) )
{
2021-05-10 19:52:56 -04:00
FConstNodeAccessPtr NodePtr = GraphClassPtr . GetNodeWithNodeID ( Node . ID ) ;
2021-01-13 10:48:59 -04:00
NodesAndClasses . Add ( FGraphController : : FConstNodeAndClass { NodePtr , NodeClassPtr } ) ;
}
}
else
{
2021-04-02 03:03:27 -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 )
{
2021-07-12 16:12:36 -04:00
TArray < FNodeAndClass > NodeAndClass = GetNodesAndClassesByPredicate ( InPredicate ) ;
if ( NodeAndClass . Num ( ) > 0 )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GetNodeHandle ( NodeAndClass [ 0 ] ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FGraphController : : GetNodeByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InPredicate ) const
{
2021-07-12 16:12:36 -04:00
TArray < FConstNodeAndClass > NodeAndClass = GetNodesAndClassesByPredicate ( InPredicate ) ;
if ( NodeAndClass . Num ( ) > 0 )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GetNodeHandle ( NodeAndClass [ 0 ] ) ;
2021-01-13 10:48:59 -04:00
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
TArray < FNodeHandle > FGraphController : : GetNodesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InFilterFunc )
{
2021-07-12 16:12:36 -04:00
return GetNodeHandles ( GetNodesAndClassesByPredicate ( InFilterFunc ) ) ;
2021-01-13 10:48:59 -04:00
}
TArray < FConstNodeHandle > FGraphController : : GetNodesByPredicate ( TFunctionRef < bool ( const FMetasoundFrontendClass & , const FMetasoundFrontendNode & ) > InFilterFunc ) const
{
2021-07-12 16:12:36 -04:00
return GetNodeHandles ( GetNodesAndClassesByPredicate ( InFilterFunc ) ) ;
2021-01-13 10:48:59 -04:00
}
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 )
{
2021-07-12 16:12:36 -04:00
FMetasoundFrontendNode * Node = InNodeAndClass . Node . Get ( ) ;
const FMetasoundFrontendClass * NodeClass = InNodeAndClass . Class . Get ( ) ;
if ( ( nullptr ! = Node ) & & ( nullptr ! = NodeClass ) )
2021-01-13 10:48:59 -04:00
{
FGraphHandle OwningGraph = this - > AsShared ( ) ;
2021-05-10 19:52:56 -04:00
FGraphAccessPtr GraphPtr = GraphClassPtr . GetGraph ( ) ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
switch ( NodeClass - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
case EMetasoundFrontendClassType : : Input :
{
2021-07-12 16:12:36 -04:00
FClassInputAccessPtr OwningGraphClassInputPtr = FindInputDescriptionWithNodeID ( Node - > ID ) ;
if ( nullptr ! = OwningGraphClassInputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FInputNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
OwningGraphClassInputPtr ,
GraphPtr ,
OwningGraph
} ;
return FInputNodeController : : CreateInputNodeHandle ( InitParams ) ;
}
else
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
// TODO: This supports input nodes introduced during subgraph inflation. Input nodes
// should be replaced with value nodes once they are implemented.
FNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
GraphPtr ,
OwningGraph
} ;
return FNodeController : : CreateNodeHandle ( InitParams ) ;
}
2021-05-20 19:33:21 -04:00
}
2021-01-13 10:48:59 -04:00
break ;
case EMetasoundFrontendClassType : : Output :
{
2021-07-12 16:12:36 -04:00
FClassOutputAccessPtr OwningGraphClassOutputPtr = FindOutputDescriptionWithNodeID ( Node - > ID ) ;
if ( nullptr ! = OwningGraphClassOutputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FOutputNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
OwningGraphClassOutputPtr ,
GraphPtr ,
OwningGraph
} ;
return FOutputNodeController : : CreateOutputNodeHandle ( InitParams ) ;
}
else
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
// TODO: This supports output nodes introduced during subgraph inflation. Output nodes
// should be replaced with value nodes once they are implemented.
FNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
GraphPtr ,
OwningGraph
} ;
return FNodeController : : CreateNodeHandle ( InitParams ) ;
}
2021-05-20 19:33:21 -04:00
}
2021-01-13 10:48:59 -04:00
break ;
case EMetasoundFrontendClassType : : External :
{
FNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
GraphPtr ,
OwningGraph
} ;
return FNodeController : : CreateNodeHandle ( InitParams ) ;
}
break ;
2021-05-20 19:33:21 -04:00
case EMetasoundFrontendClassType : : Graph :
{
FSubgraphNodeController : : FInitParams InitParams
{
InNodeAndClass . Node ,
InNodeAndClass . Class ,
GraphPtr ,
OwningGraph
} ;
return FSubgraphNodeController : : CreateNodeHandle ( InitParams ) ;
}
break ;
2021-01-13 10:48:59 -04:00
default :
checkNoEntry ( ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FConstNodeHandle FGraphController : : GetNodeHandle ( const FGraphController : : FConstNodeAndClass & InNodeAndClass ) const
{
2021-07-12 16:12:36 -04:00
const FMetasoundFrontendNode * Node = InNodeAndClass . Node . Get ( ) ;
const FMetasoundFrontendClass * NodeClass = InNodeAndClass . Class . Get ( ) ;
if ( ( nullptr ! = Node ) & & ( nullptr ! = NodeClass ) )
2021-01-13 10:48:59 -04:00
{
FConstGraphHandle OwningGraph = this - > AsShared ( ) ;
2021-05-10 19:52:56 -04:00
FConstGraphAccessPtr GraphPtr = GraphClassPtr . GetGraph ( ) ;
2021-01-20 17:26:40 -04:00
2021-07-12 16:12:36 -04:00
switch ( NodeClass - > Metadata . Type )
2021-01-13 10:48:59 -04:00
{
case EMetasoundFrontendClassType : : Input :
{
2021-07-12 16:12:36 -04:00
FConstClassInputAccessPtr OwningGraphClassInputPtr = FindInputDescriptionWithNodeID ( Node - > ID ) ;
if ( nullptr ! = OwningGraphClassInputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FInputNodeController : : FInitParams InitParams
{
ConstCastAccessPtr < FNodeAccessPtr > ( InNodeAndClass . Node ) ,
InNodeAndClass . Class ,
ConstCastAccessPtr < FClassInputAccessPtr > ( OwningGraphClassInputPtr ) ,
ConstCastAccessPtr < FGraphAccessPtr > ( GraphPtr ) ,
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FInputNodeController : : CreateConstInputNodeHandle ( InitParams ) ;
}
2021-01-13 10:48:59 -04:00
}
break ;
case EMetasoundFrontendClassType : : Output :
{
2021-07-12 16:12:36 -04:00
FConstClassOutputAccessPtr OwningGraphClassOutputPtr = FindOutputDescriptionWithNodeID ( Node - > ID ) ;
if ( nullptr ! = OwningGraphClassOutputPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FOutputNodeController : : FInitParams InitParams
{
ConstCastAccessPtr < FNodeAccessPtr > ( InNodeAndClass . Node ) ,
InNodeAndClass . Class ,
ConstCastAccessPtr < FClassOutputAccessPtr > ( OwningGraphClassOutputPtr ) ,
ConstCastAccessPtr < FGraphAccessPtr > ( GraphPtr ) ,
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FOutputNodeController : : CreateConstOutputNodeHandle ( InitParams ) ;
}
2021-01-13 10:48:59 -04:00
}
break ;
case EMetasoundFrontendClassType : : External :
case EMetasoundFrontendClassType : : Graph :
{
FNodeController : : FInitParams InitParams
{
2021-05-10 19:52:56 -04:00
ConstCastAccessPtr < FNodeAccessPtr > ( InNodeAndClass . Node ) ,
2021-01-13 10:48:59 -04:00
InNodeAndClass . Class ,
2021-05-10 19:52:56 -04:00
ConstCastAccessPtr < FGraphAccessPtr > ( GraphPtr ) ,
2021-01-13 10:48:59 -04:00
ConstCastSharedRef < IGraphController > ( OwningGraph )
} ;
return FNodeController : : CreateConstNodeHandle ( InitParams ) ;
}
break ;
default :
checkNoEntry ( ) ;
}
}
return FInvalidNodeController : : GetInvalid ( ) ;
}
FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithName ( const FString & InName )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . Name = = InName ; } ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
const FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithName ( const FString & InName ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . Name = = InName ; } ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithName ( const FString & InName )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . Name = = InName ; } ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
const FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithName ( const FString & InName ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . Name = = InName ; } ) ;
2021-01-13 10:48:59 -04:00
}
return nullptr ;
}
2021-02-24 18:37:19 -04:00
FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithVertexID ( const FGuid & InVertexID )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-02-24 18:37:19 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . VertexID = = InVertexID ; } ) ;
2021-02-24 18:37:19 -04:00
}
return nullptr ;
}
const FMetasoundFrontendClassInput * FGraphController : : FindInputDescriptionWithVertexID ( const FGuid & InVertexID ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-02-24 18:37:19 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Inputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassInput & Desc ) { return Desc . VertexID = = InVertexID ; } ) ;
2021-02-24 18:37:19 -04:00
}
return nullptr ;
}
FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithVertexID ( const FGuid & InVertexID )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-02-24 18:37:19 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . VertexID = = InVertexID ; } ) ;
2021-02-24 18:37:19 -04:00
}
return nullptr ;
}
const FMetasoundFrontendClassOutput * FGraphController : : FindOutputDescriptionWithVertexID ( const FGuid & InVertexID ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendGraphClass * GraphClass = GraphClassPtr . Get ( ) )
2021-02-24 18:37:19 -04:00
{
2021-07-12 16:12:36 -04:00
return GraphClass - > Interface . Outputs . FindByPredicate ( [ & ] ( const FMetasoundFrontendClassOutput & Desc ) { return Desc . VertexID = = InVertexID ; } ) ;
2021-02-24 18:37:19 -04:00
}
return nullptr ;
}
2021-01-20 17:26:40 -04:00
FClassInputAccessPtr FGraphController : : FindInputDescriptionWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetInputWithNodeID ( InNodeID ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FConstClassInputAccessPtr FGraphController : : FindInputDescriptionWithNodeID ( FGuid InNodeID ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetInputWithNodeID ( InNodeID ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FClassOutputAccessPtr FGraphController : : FindOutputDescriptionWithNodeID ( FGuid InNodeID )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetOutputWithNodeID ( InNodeID ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FConstClassOutputAccessPtr FGraphController : : FindOutputDescriptionWithNodeID ( FGuid InNodeID ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return GraphClassPtr . GetOutputWithNodeID ( InNodeID ) ;
2021-01-13 10:48:59 -04:00
}
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
}
2021-05-03 17:52:04 -04:00
2021-01-13 10:48:59 -04:00
//
// FDocumentController
//
FDocumentController : : FDocumentController ( FDocumentAccessPtr InDocumentPtr )
: DocumentPtr ( InDocumentPtr )
{
}
bool FDocumentController : : IsValid ( ) const
{
2021-07-12 16:12:36 -04:00
return ( nullptr ! = DocumentPtr . Get ( ) ) ;
2021-01-13 10:48:59 -04:00
}
TArray < FMetasoundFrontendClass > FDocumentController : : GetDependencies ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Document - > Dependencies ;
2021-01-13 10:48:59 -04:00
}
return TArray < FMetasoundFrontendClass > ( ) ;
}
TArray < FMetasoundFrontendGraphClass > FDocumentController : : GetSubgraphs ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
return Document - > Subgraphs ;
2021-01-13 10:48:59 -04:00
}
return TArray < FMetasoundFrontendGraphClass > ( ) ;
}
TArray < FMetasoundFrontendClass > FDocumentController : : GetClasses ( ) const
{
TArray < FMetasoundFrontendClass > Classes = GetDependencies ( ) ;
Classes . Append ( GetSubgraphs ( ) ) ;
return Classes ;
}
2021-06-23 20:07:53 -04:00
const FMetasoundFrontendGraphClass & FDocumentController : : GetRootGraphClass ( ) const
{
if ( const FMetasoundFrontendDocument * Doc = DocumentPtr . Get ( ) )
{
return Doc - > RootGraph ;
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendGraphClass > ( ) ;
}
2021-05-20 19:33:21 -04:00
bool FDocumentController : : AddDuplicateSubgraph ( const FMetasoundFrontendGraphClass & InGraphToCopy , const FMetasoundFrontendDocument & InOtherDocument )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
// Direct copy of subgraph
bool bSuccess = true ;
FMetasoundFrontendGraphClass SubgraphCopy ( InGraphToCopy ) ;
2021-05-20 19:33:21 -04:00
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendNode & Node : SubgraphCopy . Graph . Nodes )
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
const FGuid OriginalClassID = Node . ClassID ;
2021-05-20 19:33:21 -04:00
2021-07-12 16:12:36 -04:00
auto IsClassWithClassID = [ & ] ( const FMetasoundFrontendClass & InClass ) - > bool
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
return InClass . ID = = OriginalClassID ;
} ;
if ( const FMetasoundFrontendClass * OriginalNodeClass = InOtherDocument . Dependencies . FindByPredicate ( IsClassWithClassID ) )
{
// Should not be a graph class since it's in the dependencies list
check ( EMetasoundFrontendClassType : : Graph ! = OriginalNodeClass - > Metadata . Type ) ;
if ( const FMetasoundFrontendClass * NodeClass = FindOrAddClass ( OriginalNodeClass - > Metadata ) . Get ( ) )
{
// All this just to update this ID. Maybe having globally
// consistent class IDs would help. Or using the classname & version as
// a class ID.
Node . ClassID = NodeClass - > ID ;
}
else
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Failed to add subgraph dependency [Class:%s] " ) , * OriginalNodeClass - > Metadata . ClassName . ToString ( ) ) ;
bSuccess = false ;
}
}
else if ( const FMetasoundFrontendGraphClass * OriginalNodeGraphClass = InOtherDocument . Subgraphs . FindByPredicate ( IsClassWithClassID ) )
{
bSuccess = bSuccess & & AddDuplicateSubgraph ( * OriginalNodeGraphClass , InOtherDocument ) ;
if ( ! bSuccess )
{
break ;
}
2021-05-20 19:33:21 -04:00
}
else
{
bSuccess = false ;
2021-07-12 16:12:36 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Failed to copy subgraph. Subgraph document is missing dependency info for node [Node:%s, NodeID:%s] " ) , * Node . Name , * Node . ID . ToString ( ) ) ;
2021-05-20 19:33:21 -04:00
}
}
2021-07-12 16:12:36 -04:00
if ( bSuccess )
2021-05-20 19:33:21 -04:00
{
2021-07-12 16:12:36 -04:00
Document - > Subgraphs . Add ( SubgraphCopy ) ;
2021-05-20 19:33:21 -04:00
}
2021-07-12 16:12:36 -04:00
return bSuccess ;
2021-05-20 19:33:21 -04:00
}
2021-07-12 16:12:36 -04:00
return false ;
2021-05-20 19:33:21 -04:00
}
2021-06-23 20:07:53 -04:00
const FMetasoundFrontendVersion & FDocumentController : : GetArchetypeVersion ( ) const
{
if ( const FMetasoundFrontendDocument * Doc = DocumentPtr . Get ( ) )
{
return Doc - > ArchetypeVersion ;
}
return FMetasoundFrontendVersion : : GetInvalid ( ) ;
}
void FDocumentController : : SetArchetypeVersion ( const FMetasoundFrontendVersion & InVersion )
{
if ( FMetasoundFrontendDocument * Doc = DocumentPtr . Get ( ) )
{
Doc - > ArchetypeVersion = InVersion ;
}
}
2021-05-20 19:33:21 -04:00
FGraphHandle FDocumentController : : AddDuplicateSubgraph ( const IGraphController & InGraph )
{
2021-06-14 16:45:51 -04:00
// TODO: class IDs have issues..
// Currently ClassIDs are just used for internal linking. They need to be fixed up
// here if swapping documents. In the future, ClassIDs should be unique and consistent
// across documents and platforms.
2021-05-20 19:33:21 -04:00
FConstDocumentAccess GraphDocumentAccess = GetSharedAccess ( * InGraph . GetOwningDocument ( ) ) ;
const FMetasoundFrontendDocument * OtherDocument = GraphDocumentAccess . ConstDocument . Get ( ) ;
if ( nullptr = = OtherDocument )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Cannot add subgraph from invalid document " ) ) ;
return IGraphController : : GetInvalidHandle ( ) ;
}
FConstDocumentAccess GraphAccess = GetSharedAccess ( InGraph ) ;
const FMetasoundFrontendGraphClass * OtherGraph = GraphAccess . ConstGraphClass . Get ( ) ;
if ( nullptr = = OtherGraph )
{
UE_LOG ( LogMetaSound , Error , TEXT ( " Cannot add invalid subgraph to document " ) ) ;
return IGraphController : : GetInvalidHandle ( ) ;
}
if ( AddDuplicateSubgraph ( * OtherGraph , * OtherDocument ) )
{
if ( const FMetasoundFrontendClass * SubgraphClass = FindClass ( OtherGraph - > Metadata ) . Get ( ) )
{
return GetSubgraphWithClassID ( SubgraphClass - > ID ) ;
}
}
return IGraphController : : GetInvalidHandle ( ) ;
}
2021-01-20 17:26:40 -04:00
FConstClassAccessPtr FDocumentController : : FindDependencyWithID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return DocumentPtr . GetDependencyWithID ( InClassID ) ;
2021-01-13 10:48:59 -04:00
}
2021-01-20 17:26:40 -04:00
FConstGraphClassAccessPtr FDocumentController : : FindSubgraphWithID ( FGuid InClassID ) const
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
return DocumentPtr . GetSubgraphWithID ( InClassID ) ;
2021-01-13 10:48:59 -04:00
}
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 ) ;
2021-07-12 16:12:36 -04:00
if ( nullptr = = MetasoundClass . Get ( ) )
2021-01-13 10:48:59 -04:00
{
MetasoundClass = FindSubgraphWithID ( InClassID ) ;
}
return MetasoundClass ;
}
2021-05-28 14:09:45 -04:00
void FDocumentController : : SetMetadata ( const FMetasoundFrontendDocumentMetadata & InMetadata )
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
2021-07-12 16:12:36 -04:00
Document - > Metadata = InMetadata ;
2021-05-28 14:09:45 -04:00
}
}
const FMetasoundFrontendDocumentMetadata & FDocumentController : : GetMetadata ( ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-05-28 14:09:45 -04:00
{
2021-07-12 16:12:36 -04:00
return Document - > Metadata ;
2021-05-28 14:09:45 -04:00
}
return FrontendControllerIntrinsics : : GetInvalidValueConstRef < FMetasoundFrontendDocumentMetadata > ( ) ;
}
2021-06-14 16:45:51 -04:00
FConstClassAccessPtr FDocumentController : : FindClass ( const FNodeRegistryKey & InKey ) const
2021-01-13 10:48:59 -04:00
{
2021-06-14 16:45:51 -04:00
return DocumentPtr . GetClassWithRegistryKey ( InKey ) ;
2021-01-13 10:48:59 -04:00
}
2021-06-14 16:45:51 -04:00
FConstClassAccessPtr FDocumentController : : FindOrAddClass ( const FNodeRegistryKey & InKey )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
FConstClassAccessPtr ClassPtr = FindClass ( InKey ) ;
auto AddClass = [ = ] ( FMetasoundFrontendClass & & NewClassDescription )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
FConstClassAccessPtr NewClassPtr ;
2021-06-14 16:45:51 -04:00
// Cannot add a subgraph using this method because dependencies
// of external graph are not added in this method.
check ( EMetasoundFrontendClassType : : Graph ! = NewClassDescription . Metadata . Type ) ;
2021-05-20 19:33:21 -04:00
NewClassDescription . ID = FGuid : : NewGuid ( ) ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
Document - > Dependencies . Add ( MoveTemp ( NewClassDescription ) ) ;
2021-06-14 16:45:51 -04:00
NewClassPtr = FindClass ( InKey ) ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
return NewClassPtr ;
} ;
if ( const FMetasoundFrontendClass * MetasoundClass = ClassPtr . Get ( ) )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
// External node classes must match version to return shared definition.
if ( MetasoundClass - > Metadata . Type = = EMetasoundFrontendClassType : : External )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
// TODO: Assuming we want to recheck classes when they add another
// node, this should be replace with a call to synchronize a
// single class.
FMetasoundFrontendClass NewClass = GenerateClassDescription ( InKey ) ;
if ( NewClass . Metadata . Version . Major ! = MetasoundClass - > Metadata . Version . Major )
{
return AddClass ( MoveTemp ( NewClass ) ) ;
}
2021-05-03 17:52:04 -04:00
}
2021-07-12 16:12:36 -04:00
return ClassPtr ;
2021-05-03 17:52:04 -04:00
}
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
FMetasoundFrontendClass NewClass = GenerateClassDescription ( InKey ) ;
return AddClass ( MoveTemp ( NewClass ) ) ;
2021-01-13 10:48:59 -04:00
}
2021-07-12 16:12:36 -04:00
return FConstClassAccessPtr ( ) ;
2021-01-13 10:48:59 -04:00
}
FConstClassAccessPtr FDocumentController : : FindClass ( const FMetasoundFrontendClassMetadata & InMetadata ) const
{
2021-05-10 19:52:56 -04:00
return DocumentPtr . GetClassWithMetadata ( InMetadata ) ;
2021-01-13 10:48:59 -04:00
}
FConstClassAccessPtr FDocumentController : : FindOrAddClass ( const FMetasoundFrontendClassMetadata & InMetadata )
{
FConstClassAccessPtr ClassPtr = FindClass ( InMetadata ) ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendClass * Class = ClassPtr . Get ( ) )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
// External node classes must match major version to return shared definition.
if ( EMetasoundFrontendClassType : : External = = InMetadata . Type )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
if ( InMetadata . Version . Major ! = Class - > Metadata . Version . Major )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
// Mismatched major version. Reset class pointer to null.
2021-05-10 19:52:56 -04:00
ClassPtr = FConstClassAccessPtr ( ) ;
}
}
}
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
const bool bNoMatchingClassFoundInDocument = ( nullptr = = ClassPtr . Get ( ) ) ;
if ( bNoMatchingClassFoundInDocument )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
// If no matching class found, attempt to add a class matching the metadata.
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
switch ( InMetadata . Type )
2021-05-10 19:52:56 -04:00
{
2021-07-12 16:12:36 -04:00
case EMetasoundFrontendClassType : : External :
case EMetasoundFrontendClassType : : Input :
case EMetasoundFrontendClassType : : Output :
{
FMetasoundFrontendClass NewClass ;
FNodeRegistryKey Key = NodeRegistryKey : : CreateKey ( InMetadata ) ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
if ( FRegistry : : GetFrontendClassFromRegistered ( Key , NewClass ) )
{
NewClass . ID = FGuid : : NewGuid ( ) ;
Document - > Dependencies . Add ( NewClass ) ;
}
else
{
UE_LOG ( LogMetaSound , Error ,
TEXT ( " Cannot add external dependency. No Metasound class found with matching registry key [Key:%s, Name:%s, Version:%s]. Suggested solution \" %s \" by %s. " ) ,
* Key ,
* InMetadata . ClassName . GetFullName ( ) . ToString ( ) ,
* InMetadata . Version . ToString ( ) ,
* InMetadata . PromptIfMissing . ToString ( ) ,
* InMetadata . Author . ToString ( ) ) ;
}
}
break ;
2021-05-03 17:52:04 -04:00
2021-07-12 16:12:36 -04:00
case EMetasoundFrontendClassType : : Graph :
{
FMetasoundFrontendGraphClass NewClass ;
NewClass . ID = FGuid : : NewGuid ( ) ;
NewClass . Metadata = InMetadata ;
Document - > Subgraphs . Add ( NewClass ) ;
}
break ;
default :
{
UE_LOG ( LogMetaSound , Error , TEXT (
" Unsupported metasound class type for node: \" %s \" (%s). " ) ,
* InMetadata . ClassName . GetFullName ( ) . ToString ( ) ,
* InMetadata . Version . ToString ( ) ) ;
checkNoEntry ( ) ;
}
}
ClassPtr = FindClass ( InMetadata ) ;
}
2021-05-10 19:52:56 -04:00
}
2021-05-03 17:52:04 -04:00
2021-05-10 19:52:56 -04:00
return ClassPtr ;
2021-01-13 10:48:59 -04:00
}
2021-05-03 17:52:04 -04:00
void FDocumentController : : SynchronizeDependencies ( )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
int32 NumDependenciesRemovedThisItr = 0 ;
2021-01-13 10:48:59 -04:00
2021-07-12 16:12:36 -04:00
// Repeatedly remove unreferenced dependencies until there are
// no unreferenced dependencies left.
do
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
TSet < FGuid > ReferencedDependencyIDs ;
auto AddNodeClassIDToSet = [ & ] ( const FMetasoundFrontendNode & Node )
2021-05-03 17:52:04 -04:00
{
2021-07-12 16:12:36 -04:00
ReferencedDependencyIDs . Add ( Node . ClassID ) ;
} ;
auto AddGraphNodeClassIDsToSet = [ & ] ( const FMetasoundFrontendGraphClass & GraphClass )
{
Algo : : ForEach ( GraphClass . Graph . Nodes , AddNodeClassIDToSet ) ;
} ;
// Referenced dependencies in root class
Algo : : ForEach ( Document - > RootGraph . Graph . Nodes , AddNodeClassIDToSet ) ;
// Referenced dependencies in subgraphs
Algo : : ForEach ( Document - > Subgraphs , AddGraphNodeClassIDsToSet ) ;
auto IsDependencyUnreferenced = [ & ] ( const FMetasoundFrontendClass & ClassDependency )
{
return ! ReferencedDependencyIDs . Contains ( ClassDependency . ID ) ;
} ;
NumDependenciesRemovedThisItr = Document - > Dependencies . RemoveAllSwap ( IsDependencyUnreferenced ) ;
}
while ( NumDependenciesRemovedThisItr > 0 ) ;
/*
FRegistry * Registry = FRegistry : : Get ( ) ;
if ( ensure ( Registry ) )
{
// Make sure classes are up-to-date with registered versions of class
for ( FMetasoundFrontendClass & Class : DocumentPtr - > Dependencies )
{
FMetasoundFrontendClass RegisteredClass ;
FNodeRegistryKey Key = FRegistry : : GetRegistryKey ( Class . Metadata ) ;
if ( Registry - > FindFrontendClassFromRegistered ( Key , RegisteredClass ) )
{
Class = RegisteredClass ;
// TODO: update nodes for class.
// TODO: perform minor version updating.
}
2021-05-03 17:52:04 -04:00
}
}
2021-07-12 16:12:36 -04:00
*/
2021-01-13 10:48:59 -04:00
}
}
FGraphHandle FDocumentController : : GetRootGraph ( )
{
2021-07-12 16:12:36 -04:00
if ( IsValid ( ) )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FGraphClassAccessPtr GraphClass = DocumentPtr . GetRootGraph ( ) ;
2021-01-13 10:48:59 -04:00
return FGraphController : : CreateGraphHandle ( FGraphController : : FInitParams { GraphClass , this - > AsShared ( ) } ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
FConstGraphHandle FDocumentController : : GetRootGraph ( ) const
{
2021-07-12 16:12:36 -04:00
if ( IsValid ( ) )
2021-01-13 10:48:59 -04:00
{
2021-05-10 19:52:56 -04:00
FConstGraphClassAccessPtr GraphClass = DocumentPtr . GetRootGraph ( ) ;
2021-01-13 10:48:59 -04:00
return FGraphController : : CreateConstGraphHandle ( FGraphController : : FInitParams
{
2021-05-10 19:52:56 -04:00
ConstCastAccessPtr < FGraphClassAccessPtr > ( GraphClass ) ,
2021-01-13 10:48:59 -04:00
ConstCastSharedRef < IDocumentController > ( this - > AsShared ( ) )
} ) ;
}
return FInvalidGraphController : : GetInvalid ( ) ;
}
TArray < FGraphHandle > FDocumentController : : GetSubgraphHandles ( )
{
TArray < FGraphHandle > Subgraphs ;
2021-07-12 16:12:36 -04:00
if ( FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( FMetasoundFrontendGraphClass & GraphClass : Document - > Subgraphs )
2021-01-13 10:48:59 -04:00
{
Subgraphs . Add ( GetSubgraphWithClassID ( GraphClass . ID ) ) ;
}
}
return Subgraphs ;
}
TArray < FConstGraphHandle > FDocumentController : : GetSubgraphHandles ( ) const
{
TArray < FConstGraphHandle > Subgraphs ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
2021-07-12 16:12:36 -04:00
for ( const FMetasoundFrontendGraphClass & GraphClass : Document - > Subgraphs )
2021-01-13 10:48:59 -04:00
{
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
{
2021-05-10 19:52:56 -04:00
FGraphClassAccessPtr GraphClassPtr = DocumentPtr . GetSubgraphWithID ( InClassID ) ;
2021-01-13 10:48:59 -04:00
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
{
2021-05-10 19:52:56 -04:00
FConstGraphClassAccessPtr GraphClassPtr = DocumentPtr . GetSubgraphWithID ( InClassID ) ;
2021-01-13 10:48:59 -04:00
2021-05-10 19:52:56 -04:00
return FGraphController : : CreateConstGraphHandle ( FGraphController : : FInitParams { ConstCastAccessPtr < FGraphClassAccessPtr > ( GraphClassPtr ) , ConstCastSharedRef < IDocumentController > ( this - > AsShared ( ) ) } ) ;
2021-01-13 10:48:59 -04:00
}
bool FDocumentController : : ExportToJSONAsset ( const FString & InAbsolutePath ) const
{
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
2021-01-13 10:48:59 -04:00
{
if ( TUniquePtr < FArchive > FileWriter = TUniquePtr < FArchive > ( IFileManager : : Get ( ) . CreateFileWriter ( * InAbsolutePath ) ) )
{
TJsonStructSerializerBackend < DefaultCharType > Backend ( * FileWriter , EStructSerializerBackendFlags : : Default ) ;
2021-07-12 16:12:36 -04:00
FStructSerializer : : Serialize < FMetasoundFrontendDocument > ( * Document , Backend ) ;
2021-01-13 10:48:59 -04:00
FileWriter - > Close ( ) ;
return true ;
}
else
{
2021-04-02 03:03:27 -04:00
UE_LOG ( LogMetaSound , Error , TEXT ( " Failed to export Metasound json asset. Could not write to path \" %s \" . " ) , * InAbsolutePath ) ;
2021-01-13 10:48:59 -04:00
}
}
return false ;
}
FString FDocumentController : : ExportToJSON ( ) const
{
FString Output ;
2021-07-12 16:12:36 -04:00
if ( const FMetasoundFrontendDocument * Document = DocumentPtr . Get ( ) )
{
TArray < uint8 > WriterBuffer ;
FMemoryWriter MemWriter ( WriterBuffer ) ;
Metasound : : TJsonStructSerializerBackend < Metasound : : DefaultCharType > Backend ( MemWriter , EStructSerializerBackendFlags : : Default ) ;
FStructSerializer : : Serialize < FMetasoundFrontendDocument > ( * Document , Backend ) ;
MemWriter . Close ( ) ;
// null terminator
WriterBuffer . AddZeroed ( sizeof ( ANSICHAR ) ) ;
Output . AppendChars ( reinterpret_cast < ANSICHAR * > ( WriterBuffer . GetData ( ) ) , WriterBuffer . Num ( ) / sizeof ( ANSICHAR ) ) ;
}
2021-01-13 10:48:59 -04:00
return Output ;
}
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 ;
}
2021-01-13 10:48:59 -04:00
}
}
2021-05-03 17:52:04 -04:00
# undef LOCTEXT_NAMESPACE