// Copyright Epic Games, Inc. All Rights Reserved. #include "MetasoundNodeRegistrationMacro.h" #include "CoreMinimal.h" #include "MetasoundFacade.h" #include "MetasoundExecutableOperator.h" #include "MetasoundPrimitives.h" #include "MetasoundStandardNodesCategories.h" #include "MetasoundStandardNodesNames.h" #include "MetasoundAudioBuffer.h" #include "Internationalization/Text.h" #include "MetasoundParamHelper.h" #define LOCTEXT_NAMESPACE "MetasoundStandardNodes_MaxNode" namespace Metasound { namespace MaxVertexNames { METASOUND_PARAM(InputAValue, "A", "Input value A."); METASOUND_PARAM(InputBValue, "B", "Input value B."); METASOUND_PARAM(OutputValue, "Value", "The max of A and B."); } namespace MetasoundMaxNodePrivate { FNodeClassMetadata CreateNodeClassMetadata(const FName& InDataTypeName, const FName& InOperatorName, const FText& InDisplayName, const FText& InDescription, const FVertexInterface& InDefaultInterface) { FNodeClassMetadata Metadata { FNodeClassName { "Max", InOperatorName, InDataTypeName }, 1, // Major Version 0, // Minor Version InDisplayName, InDescription, PluginAuthor, PluginNodeMissingPrompt, InDefaultInterface, { NodeCategories::Math }, { }, FNodeDisplayStyle{} }; return Metadata; } template struct TMax { bool bSupported = false; }; template<> struct TMax { static void GetMax(int32 InA, int32 InB, int32& OutMax) { OutMax = FMath::Max(InA, InB); } static TDataReadReference CreateInRefA(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputAValue), InParams.OperatorSettings); } static TDataReadReference CreateInRefB(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputBValue), InParams.OperatorSettings); } }; template<> struct TMax { static void GetMax(float InA, float InB, float& OutMax) { OutMax = FMath::Max(InA, InB); } static TDataReadReference CreateInRefA(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputAValue), InParams.OperatorSettings); } static TDataReadReference CreateInRefB(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputBValue), InParams.OperatorSettings); } static bool IsAudioBuffer() { return false; } }; template<> struct TMax { static void GetMax(const FAudioBuffer& InA, const FAudioBuffer& InB, FAudioBuffer& OutMax) { float* OutMaxBufferPtr = OutMax.GetData(); const float* APtr = InA.GetData(); const float* BPtr = InB.GetData(); int32 NumSamples = InA.Num(); for (int32 i = 0; i < NumSamples; ++i) { OutMaxBufferPtr[i] = FMath::Max(APtr[i], BPtr[i]); } } static TDataReadReference CreateInRefA(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputAValue), InParams.OperatorSettings); } static TDataReadReference CreateInRefB(const FBuildOperatorParams& InParams) { using namespace MaxVertexNames; const FInputVertexInterfaceData& InputData = InParams.InputData; return InputData.GetOrCreateDefaultDataReadReference(METASOUND_GET_PARAM_NAME(InputBValue), InParams.OperatorSettings); } }; } template class TMaxNodeOperator : public TExecutableOperator> { public: static const FVertexInterface& GetDefaultInterface() { using namespace MaxVertexNames; using namespace MetasoundMaxNodePrivate; static const FVertexInterface DefaultInterface( FInputVertexInterface( TInputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(InputAValue)), TInputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(InputBValue)) ), FOutputVertexInterface( TOutputDataVertex(METASOUND_GET_PARAM_NAME_AND_METADATA(OutputValue)) ) ); return DefaultInterface; } static const FNodeClassMetadata& GetNodeInfo() { auto CreateNodeClassMetadata = []() -> FNodeClassMetadata { const FName DataTypeName = GetMetasoundDataTypeName(); const FName OperatorName = TEXT("Max"); const FText NodeDisplayName = METASOUND_LOCTEXT_FORMAT("MaxDisplayNamePattern", "Max ({0})", GetMetasoundDataTypeDisplayText()); const FText NodeDescription = METASOUND_LOCTEXT("MaxDesc", "Returns the max of A and B."); const FVertexInterface NodeInterface = GetDefaultInterface(); return MetasoundMaxNodePrivate::CreateNodeClassMetadata(DataTypeName, OperatorName, NodeDisplayName, NodeDescription, NodeInterface); }; static const FNodeClassMetadata Metadata = CreateNodeClassMetadata(); return Metadata; } static TUniquePtr CreateOperator(const FBuildOperatorParams& InParams, FBuildResults& OutResults) { using namespace MaxVertexNames; using namespace MetasoundMaxNodePrivate; TDataReadReference InputA = TMax::CreateInRefA(InParams); TDataReadReference InputB = TMax::CreateInRefB(InParams); return MakeUnique>(InParams.OperatorSettings, InputA, InputB); } TMaxNodeOperator(const FOperatorSettings& InSettings, const TDataReadReference& InInputA, const TDataReadReference& InInputB) : InputA(InInputA) , InputB(InInputB) , OutputValue(TDataWriteReferenceFactory::CreateAny(InSettings)) { GetMax(); } virtual ~TMaxNodeOperator() = default; virtual void BindInputs(FInputVertexInterfaceData& InOutVertexData) override { using namespace MaxVertexNames; InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputAValue), InputA); InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(InputBValue), InputB); } virtual void BindOutputs(FOutputVertexInterfaceData& InOutVertexData) override { using namespace MaxVertexNames; InOutVertexData.BindReadVertex(METASOUND_GET_PARAM_NAME(OutputValue), OutputValue); } void GetMax() { using namespace MetasoundMaxNodePrivate; TMax::GetMax(*InputA, *InputB, *OutputValue); } void Reset(const IOperator::FResetParams& InParams) { GetMax(); } void Execute() { GetMax(); } private: TDataReadReference InputA; TDataReadReference InputB; TDataWriteReference OutputValue; }; /** TMaxNode * * Returns the min of both inputs */ template using TMaxNode = TNodeFacade>; using FMaxNodeInt32 = TMaxNode; METASOUND_REGISTER_NODE(FMaxNodeInt32) using FMaxNodeFloat = TMaxNode; METASOUND_REGISTER_NODE(FMaxNodeFloat) using FMaxNodeAudioBuffer = TMaxNode; METASOUND_REGISTER_NODE(FMaxNodeAudioBuffer) } #undef LOCTEXT_NAMESPACE