Files
UnrealEngine/Engine/Plugins/Runtime/Metasound/Source/MetasoundFrontend/Private/MetasoundFrontendNodeTemplateRegistry.cpp
2025-05-18 13:04:45 +08:00

195 lines
6.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "MetasoundFrontendNodeTemplateRegistry.h"
#include "MetasoundFrontendDocument.h"
#include "MetasoundFrontendDocumentBuilder.h"
#include "MetasoundFrontendNodeClassRegistry.h"
#include "MetasoundFrontendNodeClassRegistryPrivate.h"
#include "MetasoundFrontendRegistryTransaction.h"
#include "MetasoundFrontendTransform.h"
#include "MetasoundLog.h"
#include "MetasoundTrace.h"
namespace Metasound::Frontend
{
#if WITH_EDITOR
FText INodeTemplate::ResolveMemberDisplayName(FName FullName, FText DisplayName, bool bIncludeNamespace)
{
FName Namespace;
FName ShortParamName;
Audio::FParameterPath::SplitName(FullName, Namespace, ShortParamName);
if (DisplayName.IsEmpty())
{
DisplayName = FText::FromName(ShortParamName);
}
if (bIncludeNamespace && !Namespace.IsNone())
{
return FText::Format(NSLOCTEXT("MetasoundFrontend", "DisplayNameWithNamespaceFormat", "{0} ({1})"), DisplayName, FText::FromName(Namespace));
}
return DisplayName;
}
#endif // WITH_EDITOR
class FNodeTemplateRegistry : public INodeTemplateRegistry
{
public:
FNodeTemplateRegistry() = default;
virtual ~FNodeTemplateRegistry() = default;
virtual const INodeTemplate* FindTemplate(const FNodeClassRegistryKey& InKey) const override;
virtual const INodeTemplate* FindTemplate(const FMetasoundFrontendClassName& InClassName) const override;
void Register(TUniquePtr<INodeTemplate>&& InEntry);
void Unregister(const FNodeClassRegistryKey& InKey);
private:
TMap<FNodeClassRegistryKey, TUniquePtr<const INodeTemplate>> Templates;
TMultiMap<FMetasoundFrontendClassName, const INodeTemplate*> TemplateByClassName;
};
void FNodeTemplateRegistry::Register(TUniquePtr<INodeTemplate>&& InTemplate)
{
if (ensure(InTemplate.IsValid()))
{
const FNodeClassRegistryKey Key = FNodeClassRegistryKey(InTemplate->GetFrontendClass().Metadata);
if (ensure(Key.IsValid()))
{
TUniquePtr<const INodeTemplate>& Entry = Templates.Add(Key, MoveTemp(InTemplate));
TemplateByClassName.Add(Entry->GetFrontendClass().Metadata.GetClassName(), Entry.Get());
}
}
}
void FNodeTemplateRegistry::Unregister(const FNodeClassRegistryKey& InKey)
{
TUniquePtr<const INodeTemplate> Removed;
if (ensure(Templates.RemoveAndCopyValue(InKey, Removed)))
{
ensure(TemplateByClassName.Remove(Removed->GetFrontendClass().Metadata.GetClassName()));
}
}
const INodeTemplate* FNodeTemplateRegistry::FindTemplate(const FNodeClassRegistryKey& InKey) const
{
if (const TUniquePtr<const INodeTemplate>* Template = Templates.Find(InKey))
{
return Template->Get();
}
return nullptr;
}
const INodeTemplate* FNodeTemplateRegistry::FindTemplate(const FMetasoundFrontendClassName& InClassName) const
{
if (TemplateByClassName.Contains(InClassName))
{
TArray<const INodeTemplate*> FoundTemplates;
constexpr bool bMaintainOrder = false;
TemplateByClassName.MultiFind(InClassName, FoundTemplates, bMaintainOrder);
Algo::Sort(FoundTemplates, [](const INodeTemplate* A, const INodeTemplate* B) { return A->GetVersionNumber() < B->GetVersionNumber(); });
return FoundTemplates.Last();
}
return nullptr;
}
INodeTemplateRegistry& INodeTemplateRegistry::Get()
{
static FNodeTemplateRegistry Registry;
return Registry;
}
const TArray<FMetasoundFrontendClassInputDefault>* FNodeTemplateBase::FindNodeClassInputDefaults(const FMetaSoundFrontendDocumentBuilder& InBuilder, const FGuid& InPageID, const FGuid& InNodeID, FName VertexName) const
{
if (const FMetasoundFrontendVertex* Vertex = InBuilder.FindNodeInput(InNodeID, VertexName, &InPageID))
{
const FMetasoundFrontendNode* Node = InBuilder.FindNode(InNodeID, &InPageID);
check(Node);
if (const FMetasoundFrontendClass* Class = InBuilder.FindDependency(Node->ClassID))
{
const FMetasoundFrontendClassInterface& ClassInterface = Class->GetInterfaceForNode(*Node);
const EMetasoundFrontendClassType ClassType = Class->Metadata.GetType();
auto MatchesName = [&Vertex](const FMetasoundFrontendClassInput& Input) { return Input.Name == Vertex->Name; };
if (const FMetasoundFrontendClassInput* Input = ClassInterface.Inputs.FindByPredicate(MatchesName))
{
return &Input->GetDefaults();
}
}
}
return nullptr;
}
#if WITH_EDITOR
FText FNodeTemplateBase::GetNodeDisplayName(const IMetaSoundDocumentInterface& Interface, const FGuid& InPageID, const FGuid& InNodeID) const
{
return { };
}
FText FNodeTemplateBase::GetInputVertexDisplayName(const FMetaSoundFrontendDocumentBuilder& InBuilder, const FGuid& InPageID, const FGuid& InNodeID, FName InputName) const
{
return FText::FromName(InputName);
}
FText FNodeTemplateBase::GetOutputVertexDisplayName(const FMetaSoundFrontendDocumentBuilder& InBuilder, const FGuid& InPageID, const FGuid& InNodeID, FName OutputName) const
{
return FText::FromName(OutputName);
}
bool FNodeTemplateBase::HasRequiredConnections(const FMetaSoundFrontendDocumentBuilder& InBuilder, const FGuid& InPageID, const FGuid& InNodeID, FString* OutMessage) const
{
return true;
}
#endif // WITH_EDITOR
void RegisterNodeTemplate(TUniquePtr<INodeTemplate>&& InTemplate)
{
class FTemplateRegistryEntry : public INodeTemplateRegistryEntry
{
const FNodeClassInfo ClassInfo;
const FMetasoundFrontendClass FrontendClass;
public:
FTemplateRegistryEntry(const INodeTemplate& InNodeTemplate)
: ClassInfo(InNodeTemplate.GetFrontendClass().Metadata)
, FrontendClass(InNodeTemplate.GetFrontendClass())
{
}
virtual ~FTemplateRegistryEntry() = default;
virtual const FNodeClassInfo& GetClassInfo() const override
{
return ClassInfo;
}
/** Return a FMetasoundFrontendClass which describes the node. */
virtual const FMetasoundFrontendClass& GetFrontendClass() const override
{
return FrontendClass;
}
};
TUniquePtr<INodeTemplateRegistryEntry> RegEntry = TUniquePtr<INodeTemplateRegistryEntry>(new FTemplateRegistryEntry(*InTemplate.Get()));
FNodeClassRegistry::Get().RegisterNodeTemplate(MoveTemp(RegEntry));
static_cast<FNodeTemplateRegistry&>(INodeTemplateRegistry::Get()).Register(MoveTemp(InTemplate));
}
void UnregisterNodeTemplate(const FMetasoundFrontendClassName& InClassName, const FMetasoundFrontendVersionNumber& InTemplateVersion)
{
const FNodeClassRegistryKey Key = FNodeClassRegistryKey(EMetasoundFrontendClassType::Template, InClassName, InTemplateVersion);
if (ensure(Key.IsValid()))
{
FNodeClassRegistry::Get().UnregisterNodeTemplate(Key);
static_cast<FNodeTemplateRegistry&>(INodeTemplateRegistry::Get()).Unregister(Key);
}
}
} // namespace Metasound::Frontend