// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "HAL/Platform.h" #include "MetasoundDocumentInterface.h" #include "MetasoundFrontendDocument.h" #include "MetasoundFrontendDocumentCacheInterface.h" #include "Containers/SortedMap.h" // Forward Declarations struct FMetaSoundFrontendDocumentBuilder; namespace Metasound::Frontend { // Forward Declarations class FDocumentCache; class FDocumentGraphEdgeCache : public IDocumentGraphEdgeCache { template friend class SharedPointerInternals::TIntrusiveReferenceController; // Only exists to make TSharedFromThis happy, but should never be called FDocumentGraphEdgeCache(); FDocumentGraphEdgeCache(TSharedRef ParentCache, const FGuid& InPageID); public: static TSharedRef Create(TSharedRef ParentCache, const FGuid& InPageID, FDocumentModifyDelegates& OutDelegates); virtual ~FDocumentGraphEdgeCache() = default; // IDocumentGraphEdgeCache implementation virtual bool ContainsEdge(const FMetasoundFrontendEdge& InEdge) const override; virtual bool IsNodeInputConnected(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual bool IsNodeOutputConnected(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual TArray FindEdges(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual const int32* FindEdgeIndexToNodeInput(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual const TArrayView FindEdgeIndicesFromNodeOutput(const FGuid& InNodeID, const FGuid& InVertexID) const override; int32 GetTransactionCount() const; private: void Init(FEdgeModifyDelegates& OutDelegates); void OnEdgeAdded(int32 InNewIndex); void OnRemoveSwappingEdge(int32 SwapIndex, int32 LastIndex); // Cache of outputs NodeId/VertexId pairs to associated edge indices TMap> OutputToEdgeIndices; // Cache of Input NodeId/VertexId pairs to associated edge indices TMap InputToEdgeIndex; TSharedRef Parent; FGuid PageID; int32 TransactionCount = 0; }; class FDocumentGraphNodeCache : public IDocumentGraphNodeCache { template friend class SharedPointerInternals::TIntrusiveReferenceController; // Only exists to make TSharedFromThis happy, but should never be called FDocumentGraphNodeCache(); FDocumentGraphNodeCache(TSharedRef ParentCache, const FGuid& InPageID); public: static TSharedRef Create(TSharedRef ParentCache, const FGuid& InPageID, FDocumentModifyDelegates& OutDelegates); virtual ~FDocumentGraphNodeCache() = default; // IDocumentGraphNodeCache implementation virtual bool ContainsNode(const FGuid& InNodeID) const override; virtual bool ContainsNodesOfClassID(const FGuid& InClassID) const override; virtual const int32* FindNodeIndex(const FGuid& InNodeID) const override; virtual TArray FindNodesOfClassID(const FGuid& InClassID) const override; virtual const FMetasoundFrontendNode* FindNode(const FGuid& InNodeID) const override; virtual TArray FindNodeInputs(const FGuid& InNodeID, FName TypeName = FName()) const override; virtual TArray FindNodeOutputs(const FGuid& InNodeID, FName TypeName = FName()) const override; virtual const FMetasoundFrontendVertex* FindInputVertex(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual const FMetasoundFrontendVertex* FindInputVertex(const FGuid& InNodeID, FName InVertexName) const override; virtual const FMetasoundFrontendVertex* FindOutputVertex(const FGuid& InNodeID, const FGuid& InVertexID) const override; virtual const FMetasoundFrontendVertex* FindOutputVertex(const FGuid& InNodeID, FName InVertexName) const override; virtual TArray FindReroutedInputVertices(const FGuid& InNodeID, const FGuid& InVertexID, TArray* ConnectedNodes = nullptr, bool* bOutIsRerouted = nullptr) const override; virtual TArray FindReroutedInputVertices(const FGuid& InNodeID, FName InVertexName, TArray* ConnectedNodes = nullptr, bool* bOutIsRerouted = nullptr) const override; virtual const FMetasoundFrontendVertex* FindReroutedOutputVertex(const FGuid& InNodeID, const FGuid& InVertexID, const FMetasoundFrontendNode** ConnectedNodes = nullptr, bool* bOutIsRerouted = nullptr) const override; virtual const FMetasoundFrontendVertex* FindReroutedOutputVertex(const FGuid& InNodeID, FName InVertexName, const FMetasoundFrontendNode** ConnectedNodes = nullptr, bool* bOutIsRerouted = nullptr) const override; int32 GetTransactionCount() const; private: void Init(FNodeModifyDelegates& OutDelegates); void OnNodeAdded(int32 NewIndex); void OnNodeInputLiteralSet(int32 NodeIndex, int32 VertexIndex, int32 LiteralIndex); void OnRemoveSwappingNode(int32 IndexBeingRemoved, int32 LastIndex); void OnRemovingNodeInputLiteral(int32 NodeIndex, int32 VertexIndex, int32 LiteralIndex); // Cache of NodeId to array index of node TSortedMap IDToIndex; // Cache of ClassID to referencing node indices TSortedMap> ClassIDToNodeIndices; TSharedRef Parent; FGuid PageID; int32 TransactionCount = 0; }; class FDocumentGraphInterfaceCache : public IDocumentGraphInterfaceCache { template friend class SharedPointerInternals::TIntrusiveReferenceController; FDocumentGraphInterfaceCache(TSharedRef ParentCache); public: static TSharedRef Create(TSharedRef ParentCache, FInterfaceModifyDelegates& OutDelegates); virtual ~FDocumentGraphInterfaceCache() = default; // IDocumentGraphInterfaceCache implementation virtual const FMetasoundFrontendClassInput* FindInput(FName InputName) const override; virtual const int32* FindInputIndex(FName InputName) const override; virtual const FMetasoundFrontendClassOutput* FindOutput(FName OutputName) const override; virtual const int32* FindOutputIndex(FName OutputName) const override; int32 GetTransactionCount() const; private: void Init(FInterfaceModifyDelegates& OutDelegates); void OnInputAdded(int32 NewIndex); void OnInputDefaultChanged(int32 NewIndex); void OnInputNameChanged(FName OldName, FName NewName); void OnOutputAdded(int32 NewIndex); void OnOutputNameChanged(FName OldName, FName NewName); void OnRemovingInput(int32 IndexBeingRemoved); void OnRemovingOutput(int32 IndexBeingRemoved); #if WITH_EDITOR void OnInputDataTypeChanged(int32 Index); void OnOutputDataTypeChanged(int32 Index); #endif // WITH_EDITOR // Cache of Input name to array index of input TMap InputNameToIndex; // Cache of Output name to array index of output TMap OutputNameToIndex; TSharedRef Parent; int32 TransactionCount = 0; }; class FDocumentCache : public IDocumentCache { template friend class SharedPointerInternals::TIntrusiveReferenceController; // Only exists to make TSharedFromThis happy, but should never be called FDocumentCache(); FDocumentCache(const FMetasoundFrontendDocument& InDocument, TSharedRef Delegates); public: static TSharedRef Create(const FMetasoundFrontendDocument& InDocument, TSharedRef Delegates, const FGuid& InBuildPageID, bool bPrimeCache); virtual ~FDocumentCache() = default; virtual bool ContainsDependency(const FNodeRegistryKey& InClassKey) const override; virtual bool ContainsDependencyOfType(EMetasoundFrontendClassType ClassType) const override; virtual const FMetasoundFrontendClass* FindDependency(const FNodeRegistryKey& InClassKey) const override; virtual const FMetasoundFrontendClass* FindDependency(const FGuid& InClassID) const override; virtual const int32* FindDependencyIndex(const Metasound::Frontend::FNodeRegistryKey& InClassKey) const override; virtual const int32* FindDependencyIndex(const FGuid& InClassID) const override; virtual const FMetasoundFrontendDocument& GetDocument() const override; virtual const IDocumentGraphEdgeCache& GetEdgeCache(const FGuid& InPageID) const override; virtual const IDocumentGraphNodeCache& GetNodeCache(const FGuid& InPageID) const override; virtual const IDocumentGraphInterfaceCache& GetInterfaceCache() const override; #if WITH_EDITORONLY_DATA virtual void SetBuildPageID(const FGuid& InPageID) override; #endif // WITH_EDITORONLY_DATA int32 GetTransactionCount() const; int32 GetTransactionCount(const FGuid& InPageID) const; private: void Init(const FGuid& InBuildPageID, bool bPrimeCache); void OnDependencyAdded(int32 InNewIndex); void OnRemoveSwappingDependency(int32 SwapIndex, int32 LastIndex); void OnRenamingDependencyClass(const int32 IndexBeingRenamed, const FMetasoundFrontendClassName& NewName); struct FDocumentDependencyCache : public TSharedFromThis { FDocumentDependencyCache(const FMetasoundFrontendDocument& InDocument); ~FDocumentDependencyCache() = default; // Cache of dependency (Class) ID to corresponding class dependency index TSortedMap IDToIndex; // Cache of version data to corresponding class dependency index TSortedMap KeyToIndex; }; // Private as cached queried data for fast access at document layer is minimal (i.e. dependencies by class id), // so API is just passed through document cache interface. Opaque create getter API kept similar to calls above // to separately implemented caches for parity. FDocumentDependencyCache& GetDependencyCache(); const FDocumentDependencyCache& GetDependencyCache() const; // Caches are mutable to be able to be loaded on demand if cache does not exist at the time of an initial query mutable TSharedPtr DependencyCache; // Sorted map of PageID to EdgeCache mutable TSortedMap> EdgeCacheMap; // Sorted map of PageID to NodeCache mutable TSortedMap> NodeCacheMap; mutable TSharedPtr InterfaceCache; const FMetasoundFrontendDocument* Document = nullptr; TSharedRef ModifyDelegates; // Number of transactions processed since builder was instantiated int32 TransactionCount = 0; // Currently set build PageID, which is the default PageID for API calls that do not specify a targeted PageID. FGuid BuildPageID; }; } // namespace Metasound::Frontend