You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- FGuid IDs are used to identify unique verticies within an entire graph (currently may be duplicated if graph is duplicated). - FNames are used to be readible vertex identifiers that are only unique within a node's API. - FText is only for ***OPTIONAL*** DisplayNames that can be provided as a more descriptive, readible descriptor of a given vertex (But are not necessarily unique). Currently disabled until loc tool on FText property in MetaSoundDetailsCustomization is properly displayed. #rb phil.popp #jira UE-123982 #preflight 613f6ff892b32b00016cf188 #ROBOMERGE-AUTHOR: rob.gay #ROBOMERGE-SOURCE: CL 17494445 in //UE5/Main/... #ROBOMERGE-BOT: STARSHIP (Main -> Release-Engine-Test) (v870-17433530) [CL 17494469 by rob gay in ue5-release-engine-test branch]
1520 lines
53 KiB
C++
1520 lines
53 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "DSP/BufferVectorOperations.h"
|
|
#include "MetasoundAudioBuffer.h"
|
|
#include "MetasoundBuilderInterface.h"
|
|
#include "MetasoundDataReference.h"
|
|
#include "MetasoundDataReferenceCollection.h"
|
|
#include "MetasoundExecutableOperator.h"
|
|
#include "MetasoundFacade.h"
|
|
#include "MetasoundNode.h"
|
|
#include "MetasoundNodeRegistrationMacro.h"
|
|
#include "MetasoundNodeInterface.h"
|
|
#include "MetasoundOperatorInterface.h"
|
|
#include "MetasoundPrimitives.h"
|
|
#include "MetasoundStandardNodesCategories.h"
|
|
#include "MetasoundStandardNodesNames.h"
|
|
#include "MetasoundTime.h"
|
|
#include "MetasoundTrigger.h"
|
|
#include "MetasoundVertex.h"
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MetasoundMathOpNode"
|
|
|
|
#define DEFINE_METASOUND_MATHOP(OpName, DataTypeName, DataClass, Description, Keywords) \
|
|
class F##OpName##DataTypeName##Node \
|
|
: public ::Metasound::TMathOpNode<F##OpName##DataTypeName##Node, ::Metasound::TMathOp##OpName<DataClass, DataClass>, DataClass, DataClass> \
|
|
{ \
|
|
public: \
|
|
static FNodeClassName GetClassName() { return { ::Metasound::StandardNodes::Namespace, TEXT(#OpName), TEXT(#DataTypeName)}; } \
|
|
static FText GetDisplayName() { return MathOpNames::Get##OpName##DisplayName<DataClass>(); } \
|
|
static FText GetDescription() { return Description; } \
|
|
static FName GetImageName() { return "MetasoundEditor.Graph.Node.Math." #OpName; } \
|
|
static TArray<FText> GetKeywords() { return Keywords; } \
|
|
F##OpName##DataTypeName##Node(const FNodeInitData& InInitData) : TMathOpNode(InInitData) { } \
|
|
};
|
|
|
|
#define DEFINE_METASOUND_OPERAND_TYPED_MATHOP(OpName, DataTypeName, DataClass, OperandTypeName, OperandDataClass, Description, Keywords) \
|
|
class F##OpName##DataTypeName##OperandTypeName##Node \
|
|
: public ::Metasound::TMathOpNode<F##OpName##DataTypeName##OperandTypeName##Node, ::Metasound::TMathOp##OpName<DataClass, OperandDataClass>, DataClass, OperandDataClass> \
|
|
{ \
|
|
public: \
|
|
static FNodeClassName GetClassName() { return {::Metasound::StandardNodes::Namespace, TEXT(#OpName), TEXT(#DataTypeName " by " #OperandTypeName)}; } \
|
|
static FText GetDisplayName() { return MathOpNames::Get##OpName##DisplayName<DataClass, OperandDataClass>(); } \
|
|
static FText GetDescription() { return Description; } \
|
|
static FName GetImageName() { return "MetasoundEditor.Graph.Node.Math." #OpName; } \
|
|
static TArray<FText> GetKeywords() { return Keywords; } \
|
|
F##OpName##DataTypeName##OperandTypeName##Node(const FNodeInitData& InInitData) : TMathOpNode(InInitData) { } \
|
|
};
|
|
|
|
namespace Metasound
|
|
{
|
|
namespace MathOpNames
|
|
{
|
|
static const FVertexName PrimaryOperandName = TEXT("PrimaryOperand");
|
|
|
|
static const FVertexName AdditionalOperandsName = TEXT("AdditionalOperands");
|
|
|
|
static const TArray<FText> AddKeywords = { LOCTEXT("AddMathKeyword", "+") };
|
|
static const TArray<FText> SubtractKeywords = { LOCTEXT("SubtractMathKeyword", "-") };
|
|
static const TArray<FText> MultiplyKeywords = { LOCTEXT("MultiplyMathKeyword", "*") };
|
|
static const TArray<FText> DivideKeywords = { LOCTEXT("DivideMathKeyword", "/") };
|
|
static const TArray<FText> PowerKeywords = { LOCTEXT("PowerMathKeyword", "^") };
|
|
static const TArray<FText> ModuloKeywords = { LOCTEXT("ModuloMathKeyword", "%") };
|
|
|
|
template<typename DataType>
|
|
const FText GetAddDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("AddNodeDisplayNamePattern", "Add ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetAddDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("AddNodeDisplayNamePattern", "Add ({0} to {1})"),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>(),
|
|
GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetSubtractDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("SubtractNodeDisplayNamePattern", "Subtract ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetSubtractDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("SubtractNodeOperandTypedDisplayNamePattern", "Subtract ({0} from {1})"),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>(),
|
|
GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetMultiplyDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("MultiplyNodeDisplayNamePattern", "Multiply ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetMultiplyDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("MultiplyNodeOperandTypedDisplayNamePattern", "Multiply ({0} by {1})"),
|
|
GetMetasoundDataTypeDisplayText<DataType>(),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetDivideDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("DivideNodeDisplayNamePattern", "Divide ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetDivideDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("DivideNodeOperandTypedDisplayNamePattern", "Divide ({0} by {1})"),
|
|
GetMetasoundDataTypeDisplayText<DataType>(),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetModuloDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("ModuloNodeDisplayNamePattern", "Modulo ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetModuloDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("ModuloNodeOperandTypedDisplayNamePattern", "Modulo ({0} by {1})"),
|
|
GetMetasoundDataTypeDisplayText<DataType>(),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetPowerDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("PowerNodeDisplayNamePattern", "Power ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetPowerDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("PowerNodeOperandTypedDisplayNamePattern", "Power ({0} to the power of {1})"),
|
|
GetMetasoundDataTypeDisplayText<DataType>(),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType>
|
|
const FText GetLogarithmDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(LOCTEXT("LogNodeDisplayNamePattern", "Log ({0})"), GetMetasoundDataTypeDisplayText<DataType>());
|
|
return DisplayName;
|
|
}
|
|
|
|
template<typename DataType, typename OperandDataType>
|
|
const FText GetLogarithmDisplayName()
|
|
{
|
|
static const FText DisplayName = FText::Format(
|
|
LOCTEXT("LogarithmNodeOperandTypedDisplayNamePattern", "Log ({0}-Base logarithm of {1})"),
|
|
GetMetasoundDataTypeDisplayText<DataType>(),
|
|
GetMetasoundDataTypeDisplayText<OperandDataType>());
|
|
return DisplayName;
|
|
}
|
|
}
|
|
|
|
template <typename TDerivedClass, typename TMathOpClass, typename TDataClass, typename TOperandDataClass>
|
|
class TMathOpNode : public FNodeFacade
|
|
{
|
|
private:
|
|
class TMathOperator : public TExecutableOperator<TMathOperator>
|
|
{
|
|
private:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
TMathOpClass InstanceData;
|
|
|
|
TDataClassReadRef PrimaryOperandRef;
|
|
TArray<TOperandDataClassReadRef> AdditionalOperandRefs;
|
|
TDataClassWriteRef ValueRef;
|
|
|
|
public:
|
|
static const FNodeClassMetadata& GetNodeInfo()
|
|
{
|
|
auto InitNodeInfo = []() -> FNodeClassMetadata
|
|
{
|
|
FNodeDisplayStyle DisplayStyle;
|
|
DisplayStyle.ImageName = TDerivedClass::GetImageName();
|
|
DisplayStyle.bShowName = false;
|
|
DisplayStyle.bShowInputNames = false;
|
|
DisplayStyle.bShowOutputNames = false;
|
|
|
|
FNodeClassMetadata Info;
|
|
Info.ClassName = TDerivedClass::GetClassName();
|
|
Info.MajorVersion = 1;
|
|
Info.MinorVersion = 0;
|
|
Info.DisplayName = TDerivedClass::GetDisplayName();
|
|
Info.Description = TDerivedClass::GetDescription();
|
|
Info.Author = PluginAuthor;
|
|
Info.PromptIfMissing = PluginNodeMissingPrompt;
|
|
Info.DefaultInterface = TMathOpClass::GetVertexInterface();
|
|
Info.DisplayStyle = DisplayStyle;
|
|
Info.CategoryHierarchy = { NodeCategories::Math };
|
|
Info.Keywords = TDerivedClass::GetKeywords();
|
|
|
|
return Info;
|
|
};
|
|
|
|
static const FNodeClassMetadata Info = InitNodeInfo();
|
|
return Info;
|
|
}
|
|
|
|
void Execute()
|
|
{
|
|
TMathOpClass::Calculate(InstanceData, PrimaryOperandRef, AdditionalOperandRefs, ValueRef);
|
|
}
|
|
|
|
static TUniquePtr<IOperator> CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors)
|
|
{
|
|
const TMathOpNode& MathOpNode = static_cast<const TMathOpNode&>(InParams.Node);
|
|
|
|
const FInputVertexInterface& InputInterface = MathOpNode.GetVertexInterface().GetInputInterface();
|
|
|
|
FLiteral DefaultValue = FLiteral::CreateInvalid();
|
|
const FVertexName& PrimaryOperandName = MathOpNames::PrimaryOperandName;
|
|
if (InputInterface.Contains(PrimaryOperandName))
|
|
{
|
|
DefaultValue = InputInterface[PrimaryOperandName].GetDefaultLiteral();
|
|
}
|
|
TDataClassReadRef PrimaryOperand = InParams.InputDataReferences.GetDataReadReferenceOrConstruct<TDataClass>(MathOpNames::PrimaryOperandName, TMathOpClass::GetDefault(InParams.OperatorSettings, DefaultValue));
|
|
|
|
// TODO: Support dynamic number of inputs
|
|
const FVertexName& OpName = MathOpNames::AdditionalOperandsName;
|
|
if (InputInterface.Contains(OpName))
|
|
{
|
|
DefaultValue = InputInterface[OpName].GetDefaultLiteral();
|
|
}
|
|
TOperandDataClassReadRef Op1 = InParams.InputDataReferences.GetDataReadReferenceOrConstruct<TOperandDataClass>(OpName, TMathOpClass::GetDefaultOp(InParams.OperatorSettings, DefaultValue));
|
|
TArray<TOperandDataClassReadRef> AdditionalOperandRefs = { Op1 };
|
|
|
|
return MakeUnique<TMathOperator>(InParams.OperatorSettings, PrimaryOperand, AdditionalOperandRefs);
|
|
}
|
|
|
|
TMathOperator(const FOperatorSettings& InSettings, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands)
|
|
: PrimaryOperandRef(InPrimaryOperand)
|
|
, AdditionalOperandRefs(InAdditionalOperands)
|
|
, ValueRef(TDataWriteReferenceFactory<TDataClass>::CreateAny(InSettings))
|
|
{
|
|
}
|
|
|
|
virtual FDataReferenceCollection GetInputs() const override
|
|
{
|
|
FDataReferenceCollection InputDataReferences;
|
|
InputDataReferences.AddDataReadReference(MathOpNames::PrimaryOperandName, PrimaryOperandRef);
|
|
InputDataReferences.AddDataReadReference(MathOpNames::AdditionalOperandsName, AdditionalOperandRefs[0]);
|
|
return InputDataReferences;
|
|
}
|
|
|
|
virtual FDataReferenceCollection GetOutputs() const override
|
|
{
|
|
FDataReferenceCollection OutputDataReferences;
|
|
OutputDataReferences.AddDataReadReference(TEXT("Out"), TDataClassReadRef(ValueRef));
|
|
|
|
return OutputDataReferences;
|
|
}
|
|
};
|
|
|
|
public:
|
|
TMathOpNode(const FNodeInitData& InInitData)
|
|
: FNodeFacade(InInitData.InstanceName, InInitData.InstanceID, TFacadeOperatorClass<TMathOperator>())
|
|
{
|
|
}
|
|
};
|
|
|
|
// Standard Math Operations
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpAdd
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<TDataClass>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAddendInitialTooltip", "Initial addend."), static_cast<TDataClass>(0)),
|
|
TInputDataVertexModel<TOperandDataClass>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendsTooltip", "Additional addend(s)."), static_cast<TOperandDataClass>(0))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<TDataClass>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Math operation result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(0);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(0);
|
|
}
|
|
|
|
static void Calculate(TMathOpAdd<TDataClass, TOperandDataClass>& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
*OutResult += *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpSubtract
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<TDataClass>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpMinuendTooltip", "Minuend."), static_cast<TDataClass>(0)),
|
|
TInputDataVertexModel<TOperandDataClass>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpSubtrahendsTooltip", "Subtrahend(s)."), static_cast<TOperandDataClass>(0))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<TDataClass>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Subtraction result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(0);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(0);
|
|
}
|
|
|
|
static void Calculate(TMathOpSubtract<TDataClass, TOperandDataClass>& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
*OutResult -= *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpMultiply
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<TDataClass>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpInitMultiplicandTooltip", "Initial multiplicand."), static_cast<TDataClass>(1)),
|
|
TInputDataVertexModel<TOperandDataClass>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpMultiplicandsTooltip", "Additional multiplicand(s)."), static_cast<TOperandDataClass>(1))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<TDataClass>(TEXT("Out"), LOCTEXT("MultiplicationResultTooltip", "Multiplication result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(1);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(1);
|
|
}
|
|
|
|
static void Calculate(TMathOpMultiply<TDataClass, TOperandDataClass>& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
*OutResult *= *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpDivide
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<TDataClass>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpDividendTooltip", "Dividend."), static_cast<TDataClass>(1)),
|
|
TInputDataVertexModel<TOperandDataClass>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpDivisorsTooltip", "Divisor(s)."), static_cast<TOperandDataClass>(1))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<TDataClass>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Math operation result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(1);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(1);
|
|
}
|
|
|
|
static void Calculate(TMathOpDivide& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const TDataClass& OperandValue = *InAdditionalOperands[i];
|
|
if (OperandValue == static_cast<TDataClass>(0))
|
|
{
|
|
// TODO: Error here
|
|
return;
|
|
}
|
|
|
|
*OutResult /= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpModulo
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<TDataClass>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpModuloDividendTooltip", "Dividend."), static_cast<TDataClass>(1)),
|
|
TInputDataVertexModel<TOperandDataClass>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpModuloDivisorsTooltip", "Divisor(s)."), static_cast<TOperandDataClass>(1))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<TDataClass>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Resulting value"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(1);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(1);
|
|
}
|
|
|
|
static void Calculate(TMathOpModulo& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
// TODO: chaining modulo operations doesn't make too much sense... how do we forbid additional operands in some math ops?
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const TDataClass& OperandValue = *InAdditionalOperands[i];
|
|
if (OperandValue == static_cast<TDataClass>(0))
|
|
{
|
|
// TODO: Error here
|
|
return;
|
|
}
|
|
|
|
*OutResult %= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpPower
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface DefaultInterface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<float>(MathOpNames::PrimaryOperandName, LOCTEXT("Base", "The base of the power")),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("Exponent", "The exponent to take the base to the power of"))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<float>(TEXT("Out"), LOCTEXT("Result", "Returns Base to the Exponent power"))
|
|
)
|
|
);
|
|
|
|
return DefaultInterface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(1);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(1);
|
|
}
|
|
|
|
static void Calculate(TMathOpPower& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const TDataClass& OperandValue = *InAdditionalOperands[i];
|
|
|
|
*OutResult = FMath::Pow(*OutResult, OperandValue);
|
|
}
|
|
}
|
|
};
|
|
|
|
template <typename TDataClass, typename TOperandDataClass = TDataClass>
|
|
class TMathOpLogarithm
|
|
{
|
|
public:
|
|
using TDataClassReadRef = TDataReadReference<TDataClass>;
|
|
using TDataClassWriteRef = TDataWriteReference<TDataClass>;
|
|
|
|
using TOperandDataClassReadRef = TDataReadReference<TOperandDataClass>;
|
|
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface DefaultInterface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<float>(MathOpNames::PrimaryOperandName, LOCTEXT("Base", "The base of the logarithm")),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("Value", "The value to find the logarithm of"))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<float>(TEXT("Out"), LOCTEXT("Result", "The logarithm of the inputted value"))
|
|
)
|
|
);
|
|
|
|
return DefaultInterface;
|
|
}
|
|
|
|
static TDataClass GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TDataClass>(1);
|
|
}
|
|
|
|
static TOperandDataClass GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<TOperandDataClass>(1);
|
|
}
|
|
|
|
static void Calculate(TMathOpLogarithm& InInstanceData, const TDataClassReadRef& InPrimaryOperand, const TArray<TOperandDataClassReadRef>& InAdditionalOperands, TDataClassWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
//TODO: Find out how to disallow it from additional inputs, it doesn't really make sense in the context of logarithms
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const TDataClass& OperandValue = *InAdditionalOperands[i];
|
|
|
|
*OutResult = FMath::LogX(FMath::Max(SMALL_NUMBER, *OutResult), FMath::Max(SMALL_NUMBER, OperandValue));
|
|
}
|
|
}
|
|
};
|
|
|
|
// Specialized Math Operations
|
|
template <>
|
|
class TMathOpAdd<FAudioBuffer>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAddendTooltip", "First attend.")),
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Additional attends."))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FAudioBuffer>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Math operation result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FAudioBuffer GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FAudioBuffer(InSettings.GetNumFramesPerBlock());
|
|
}
|
|
|
|
static FAudioBuffer GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return GetDefault(InSettings, InVertexDefault);
|
|
}
|
|
|
|
static void Calculate(TMathOpAdd<FAudioBuffer>& InInstanceData, FAudioBufferReadRef& InPrimaryOperand, const TArray<FAudioBufferReadRef>& InAdditionalOperands, FAudioBufferWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const int32 NumSamples = InAdditionalOperands[0]->Num();
|
|
if (!ensure(NumSamples == OutResult->Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
FMemory::Memcpy(OutResult->GetData(), InPrimaryOperand->GetData(), sizeof(float) * NumSamples);
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const FAudioBuffer& Operand = *InAdditionalOperands[i];
|
|
if (!ensure(NumSamples == Operand.Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const float* OperandData = InAdditionalOperands[i]->GetData();
|
|
float* OutData = OutResult->GetData();
|
|
|
|
if (NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER)
|
|
{
|
|
for (int32 SampleIndex = 0; SampleIndex < NumSamples; ++SampleIndex)
|
|
{
|
|
OutData[SampleIndex] += OperandData[SampleIndex];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
const float StartGain = 1.0f;
|
|
const float EndGain = 1.0f;
|
|
Audio::MixInBufferFast(OperandData, OutData, NumSamples, StartGain, EndGain);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TMathOpAdd<FTime>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FTime>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAddendTooltip", "First attend."), 0.0f),
|
|
TInputDataVertexModel<FTime>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Additional attends."), 0.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FTime>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Math operation result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FTime GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FTime(InVertexDefault.Value.Get<float>());
|
|
}
|
|
|
|
static FTime GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return GetDefault(InSettings, InVertexDefault);
|
|
}
|
|
|
|
static void Calculate(TMathOpAdd& InInstanceData, const FTimeReadRef& InPrimaryOperand, const TArray<FTimeReadRef>& InAdditionalOperands, FTimeWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
*OutResult += *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TMathOpAdd<FAudioBuffer, float>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAddendAudioTooltip", "Audio Buffer to add offset(s) to.")),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Float attends of which to offset buffer samples."), 0.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FAudioBuffer>(TEXT("Out"), LOCTEXT("MathOpAudioFloatAddOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FAudioBuffer GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FAudioBuffer(InSettings.GetNumFramesPerBlock());
|
|
}
|
|
|
|
static float GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return InVertexDefault.Value.Get<float>();
|
|
}
|
|
|
|
static void Calculate(TMathOpAdd& InInstanceData, const FAudioBufferReadRef& InPrimaryOperand, const TArray<FFloatReadRef>& InAdditionalOperands, FAudioBufferWriteRef& OutResult)
|
|
{
|
|
FMemory::Memcpy(OutResult->GetData(), InPrimaryOperand->GetData(), sizeof(float) * OutResult->Num());
|
|
|
|
const int32 SIMDRemainder = OutResult->Num() % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER;
|
|
const int32 SIMDCount = OutResult->Num() - SIMDRemainder;
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
Audio::AddConstantToBufferInplace(OutResult->GetData(), SIMDCount, *InAdditionalOperands[i]);
|
|
|
|
for (int32 j = SIMDCount; j < OutResult->Num(); ++j)
|
|
{
|
|
OutResult->GetData()[j] += *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
#if 0
|
|
// int64 has to be explicitly implemented as they are PODs that are not implemented as a literal base type.
|
|
template <>
|
|
class TMathOpAdd<int64>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<int64>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpInt64InitialAddendMinuendTooltip", "Initial Addend."), 0),
|
|
TInputDataVertexModel<int64>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpInt64AddendsTooltip", "Additional Addend(s)."), 0)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<int64>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Addition result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static int32 GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static int32 GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static void Calculate(TMathOpAdd& InInstanceData, const FInt64ReadRef& InPrimaryOperand, const TArray<FInt64ReadRef>& InAdditionalOperands, FInt64WriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int64 OperandValue = *InAdditionalOperands[i];
|
|
*OutResult += OperandValue;
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
|
|
template <>
|
|
class TMathOpSubtract<FAudioBuffer>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpBuffersMinuendTooltip", "Initial buffer to act as minuend.")),
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpSubtractBuffersSubtrahendsTooltip", "Additional buffers to act as subtrahend(s)."))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FAudioBuffer>(TEXT("Out"), LOCTEXT("MathOpSubtractBuffersOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FAudioBuffer GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FAudioBuffer(InSettings.GetNumFramesPerBlock());
|
|
}
|
|
|
|
static FAudioBuffer GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return GetDefault(InSettings, InVertexDefault);
|
|
}
|
|
|
|
static void Calculate(TMathOpSubtract& InInstanceData, FAudioBufferReadRef& InPrimaryOperand, const TArray<FAudioBufferReadRef>& InAdditionalOperands, FAudioBufferWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const int32 NumSamples = InAdditionalOperands[0]->Num();
|
|
if (!ensure(NumSamples == OutResult->Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
FMemory::Memcpy(OutResult->GetData(), InPrimaryOperand->GetData(), sizeof(float) * NumSamples);
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const FAudioBuffer& Operand = *InAdditionalOperands[i];
|
|
if (!ensure(NumSamples == Operand.Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const float* OperandData = InAdditionalOperands[i]->GetData();
|
|
float* OutData = OutResult->GetData();
|
|
|
|
if (NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER)
|
|
{
|
|
for (int32 SampleIndex = 0; SampleIndex < NumSamples; ++SampleIndex)
|
|
{
|
|
OutData[i] -= OperandData[i];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Audio::BufferSubtractInPlace2Fast(OutData, OperandData, NumSamples);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TMathOpSubtract<FTime>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FTime>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpTimeMinuendTooltip", "Time minuend."), 0.0f),
|
|
TInputDataVertexModel<FTime>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpTimeSubtrahendsTooltip", "Time subtrahends."), 0.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FTime>(TEXT("Out"), LOCTEXT("MathOpTimeSubtractOutTooltip", "Resulting time value"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FTime GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FTime(InVertexDefault.Value.Get<float>());
|
|
}
|
|
|
|
static FTime GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return GetDefault(InSettings, InVertexDefault);
|
|
}
|
|
|
|
static void Calculate(TMathOpSubtract& InInstanceData, const FTimeReadRef& InPrimaryOperand, const TArray<FTimeReadRef>& InAdditionalOperands, FTimeWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
*OutResult = *InPrimaryOperand;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
*OutResult -= *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
};
|
|
|
|
#if 0
|
|
// int64 has to be explicitly implemented as they are PODs that are not implemented as a literal base type.
|
|
template <>
|
|
class TMathOpSubtract<int64>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<int64>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpMinuendTooltip", "Minuend."), 0),
|
|
TInputDataVertexModel<int64>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpSubtrahendsTooltip", "Subtrahend(s)."), 0)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<int64>(TEXT("Out"), LOCTEXT("MathOpOutTooltip", "Subtraction result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static int32 GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static int32 GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static void Calculate(TMathOpSubtract& InInstanceData, const FInt64ReadRef& InPrimaryOperand, const TArray<FInt64ReadRef>& InAdditionalOperands, FInt64WriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int64 OperandValue = *InAdditionalOperands[i];
|
|
*OutResult -= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
|
|
template <>
|
|
class TMathOpMultiply<FAudioBuffer>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAudioInitMultiplicandTooltip", "Initial audio to multiply.")),
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpMultiplyAudioSubtrahendsTooltip", "Additional audio to multiply sample-by-sample."))
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FAudioBuffer>(TEXT("Out"), LOCTEXT("MathOpMultiplyAudioOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FAudioBuffer GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FAudioBuffer(InSettings.GetNumFramesPerBlock());
|
|
}
|
|
|
|
static FAudioBuffer GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return GetDefault(InSettings, InVertexDefault);
|
|
}
|
|
|
|
static void Calculate(TMathOpMultiply& InInstanceData, const FAudioBufferReadRef& InPrimaryOperand, const TArray<FAudioBufferReadRef>& InAdditionalOperands, FAudioBufferWriteRef& OutResult)
|
|
{
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const int32 NumSamples = InPrimaryOperand->Num();
|
|
if (!ensure(NumSamples == OutResult->Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
FMemory::Memcpy(OutResult->GetData(), InPrimaryOperand->GetData(), sizeof(float) * NumSamples);
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const FAudioBuffer& Operand = *InAdditionalOperands[i];
|
|
if (!ensure(NumSamples == Operand.Num()))
|
|
{
|
|
// TODO: Error
|
|
OutResult->Zero();
|
|
return;
|
|
}
|
|
|
|
const float* OperandData = InAdditionalOperands[i]->GetData();
|
|
float* OutData = OutResult->GetData();
|
|
|
|
if (NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER)
|
|
{
|
|
for (int32 SampleIndex = 0; SampleIndex < NumSamples; ++SampleIndex)
|
|
{
|
|
OutData[SampleIndex] += OperandData[SampleIndex];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Audio::MultiplyBuffersInPlace(OperandData, OutData, NumSamples);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TMathOpMultiply<FAudioBuffer, float>
|
|
{
|
|
bool bInit = false;
|
|
float LastGain = 0.0f;
|
|
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FAudioBuffer>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpAudioMultiplyFloatTooltip", "Audio multiplicand.")),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Float multiplicand to apply sample-by-sample to audio. Interpolates over buffer size on value change."), 1.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FAudioBuffer>(TEXT("Out"), LOCTEXT("MathOpAudioFloatMultiplyOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FAudioBuffer GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FAudioBuffer(InSettings.GetNumFramesPerBlock());
|
|
}
|
|
|
|
static float GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return InVertexDefault.Value.Get<float>();
|
|
}
|
|
|
|
static void Calculate(TMathOpMultiply& InInstanceData, const FAudioBufferReadRef& InPrimaryOperand, const TArray<FFloatReadRef>& InAdditionalOperands, FAudioBufferWriteRef& OutResult)
|
|
{
|
|
if (!InInstanceData.bInit)
|
|
{
|
|
InInstanceData.bInit = true;
|
|
InInstanceData.LastGain = 1.0f;
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
InInstanceData.LastGain *= *InAdditionalOperands[i];
|
|
}
|
|
}
|
|
|
|
FMemory::Memcpy(OutResult->GetData(), InPrimaryOperand->GetData(), sizeof(float) * InPrimaryOperand->Num());
|
|
|
|
float NewGain = 1.0f;
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int32 SIMDRemainder = OutResult->Num() % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER;
|
|
const int32 SIMDCount = OutResult->Num() - SIMDRemainder;
|
|
|
|
Audio::FadeBufferFast(OutResult->GetData(), SIMDCount, InInstanceData.LastGain, *InAdditionalOperands[i]);
|
|
|
|
for (int32 j = SIMDCount; j < OutResult->Num(); ++j)
|
|
{
|
|
OutResult->GetData()[j] *= *InAdditionalOperands[j];
|
|
}
|
|
|
|
NewGain *= *InAdditionalOperands[i];
|
|
}
|
|
|
|
InInstanceData.LastGain = NewGain;
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TMathOpMultiply<FTime, float>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FTime>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpTimeMultiplyFloatTooltip", "Time multiplicand."), 1.0f),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Float multiplicand(s)."), 1.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FTime>(TEXT("Out"), LOCTEXT("MathOpTimeMultiplyOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FTime GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FTime(InVertexDefault.Value.Get<float>());
|
|
}
|
|
|
|
static float GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return 1.0f;
|
|
}
|
|
|
|
static void Calculate(TMathOpMultiply& InInstanceData, const FTimeReadRef& InPrimaryOperand, const TArray<FFloatReadRef>& InAdditionalOperands, FTimeWriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const float OperandValue = *InAdditionalOperands[i];
|
|
*OutResult *= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
|
|
#if 0
|
|
// int64 has to be explicitly implemented as they are PODs that are not implemented as a literal base type.
|
|
template <>
|
|
class TMathOpMultiply<int64>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<int64>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpInitMultiplicandTooltip", "Initial multiplicand."), 1),
|
|
TInputDataVertexModel<int64>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpMultiplicandsTooltip", "Additional multiplicand(s)."), 1)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<int64>(TEXT("Out"), LOCTEXT("MultiplicationResultTooltip", "Multiplication result"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static int32 GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static int32 GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static void Calculate(TMathOpMultiply& InInstanceData, const FInt64ReadRef& InPrimaryOperand, const TArray<FInt64ReadRef>& InAdditionalOperands, FInt64WriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int64 OperandValue = *InAdditionalOperands[i];
|
|
*OutResult *= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
|
|
template <>
|
|
class TMathOpDivide<FTime, float>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<FTime>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpTimeMultiplyFloatTooltip", "Time multiplicand."), 1.0f),
|
|
TInputDataVertexModel<float>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpAddendAdditionalTooltip", "Float multiplicand(s)."), 1.0f)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<FTime>(TEXT("Out"), LOCTEXT("MathOpTimeMultiplyOutTooltip", "Resulting buffer"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static FTime GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return FTime(InVertexDefault.Value.Get<float>());
|
|
}
|
|
|
|
static float GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return 1.0f;
|
|
}
|
|
|
|
static void Calculate(TMathOpDivide& InInstanceData, const FTimeReadRef& InPrimaryOperand, const TArray<FFloatReadRef>& InAdditionalOperands, FTimeWriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const float OperandValue = *InAdditionalOperands[i];
|
|
if (OperandValue == 0.0f)
|
|
{
|
|
// TODO: Error here
|
|
continue;
|
|
}
|
|
|
|
*OutResult /= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
|
|
#if 0
|
|
// int64 has to be explicitly implemented as they are PODs that are not implemented as a literal base type.
|
|
template <>
|
|
class TMathOpDivide<int64>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<int64>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpDivideDividendTooltip", "Dividend of operation."), 1),
|
|
TInputDataVertexModel<int64>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpDivideDivisorTooltip", "Divisor of operation."), 1)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<int64>(TEXT("Out"), LOCTEXT("MathOpDivideOutTooltip", "Resulting value"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static int64 GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
// TODO: we are truncating to int32, why do we need int64?
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static int64 GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
// TODO: we are truncating to int32, why do we need in64?
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static void Calculate(TMathOpDivide& InInstanceData, const FInt64ReadRef& InPrimaryOperand, const TArray<FInt64ReadRef>& InAdditionalOperands, FInt64WriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int64 OperandValue = *InAdditionalOperands[i];
|
|
if (OperandValue == 0)
|
|
{
|
|
// TODO: Error here
|
|
continue;
|
|
}
|
|
|
|
*OutResult /= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// int64 has to be explicitly implemented as they are PODs that are not implemented as a literal base type.
|
|
template <>
|
|
class TMathOpModulo<int64>
|
|
{
|
|
public:
|
|
static const FVertexInterface& GetVertexInterface()
|
|
{
|
|
static const FVertexInterface Interface(
|
|
FInputVertexInterface(
|
|
TInputDataVertexModel<int64>(MathOpNames::PrimaryOperandName, LOCTEXT("MathOpModuloDividendTooltip", "Dividend"), 1),
|
|
TInputDataVertexModel<int64>(MathOpNames::AdditionalOperandsName, LOCTEXT("MathOpModuluDivisorTooltip", "Divisor(s)"), 1)
|
|
),
|
|
FOutputVertexInterface(
|
|
TOutputDataVertexModel<int64>(TEXT("Out"), LOCTEXT("MathOpModuloOutTooltip", "Resulting value"))
|
|
)
|
|
);
|
|
|
|
return Interface;
|
|
}
|
|
|
|
static int64 GetDefault(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static int64 GetDefaultOp(const FOperatorSettings& InSettings, const FLiteral& InVertexDefault)
|
|
{
|
|
return static_cast<int64>(InVertexDefault.Value.Get<int32>());
|
|
}
|
|
|
|
static void Calculate(TMathOpModulo& InInstanceData, const FInt64ReadRef& InPrimaryOperand, const TArray<FInt64ReadRef>& InAdditionalOperands, FInt64WriteRef& OutResult)
|
|
{
|
|
*OutResult = *InPrimaryOperand;
|
|
|
|
if (!ensure(!InAdditionalOperands.IsEmpty()))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int32 i = 0; i < InAdditionalOperands.Num(); ++i)
|
|
{
|
|
const int64 OperandValue = *InAdditionalOperands[i];
|
|
if (OperandValue == 0)
|
|
{
|
|
// TODO: Error here
|
|
continue;
|
|
}
|
|
|
|
*OutResult %= OperandValue;
|
|
}
|
|
}
|
|
};
|
|
#endif
|
|
|
|
// Definitions
|
|
DEFINE_METASOUND_MATHOP(Add, Float, float, LOCTEXT("Metasound_MathAddFloatNodeDescription", "Adds floats."), MathOpNames::AddKeywords)
|
|
DEFINE_METASOUND_MATHOP(Add, Int32, int32, LOCTEXT("Metasound_MathAddInt32NodeDescription", "Adds int32s."), MathOpNames::AddKeywords)
|
|
//DEFINE_METASOUND_MATHOP(Add, Int64, int64, LOCTEXT("Metasound_MathAddInt64NodeDescription", "Adds int64s."), MathOpNames::AddKeywords)
|
|
DEFINE_METASOUND_MATHOP(Add, Audio, FAudioBuffer, LOCTEXT("Metasound_MathAddBufferNodeDescription", "Adds buffers together by sample."), MathOpNames::AddKeywords)
|
|
DEFINE_METASOUND_MATHOP(Add, Time, FTime, LOCTEXT("Metasound_MathAddTimeNodeDescription", "Adds time values."), MathOpNames::AddKeywords)
|
|
|
|
DEFINE_METASOUND_OPERAND_TYPED_MATHOP(Add, Audio, FAudioBuffer, Float, float, LOCTEXT("Metasound_MathAddAudioFloatNodeDescription", "Add floats to buffer sample-by-sample."), MathOpNames::AddKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Subtract, Float, float, LOCTEXT("Metasound_MathSubractFloatNodeDescription", "Subtracts floats."), MathOpNames::SubtractKeywords)
|
|
DEFINE_METASOUND_MATHOP(Subtract, Int32, int32, LOCTEXT("Metasound_MathSubractInt32NodeDescription", "Subtracts int32s."), MathOpNames::SubtractKeywords)
|
|
//DEFINE_METASOUND_MATHOP(Subtract, Int64, int64, LOCTEXT("Metasound_MathSubractInt64NodeDescription", "Subtracts int64s."), MathOpNames::SubtractKeywords)
|
|
DEFINE_METASOUND_MATHOP(Subtract, Audio, FAudioBuffer, LOCTEXT("Metasound_MathSubtractBufferNodeDescription", "Subtracts buffers sample-by-sample."), MathOpNames::SubtractKeywords)
|
|
DEFINE_METASOUND_MATHOP(Subtract, Time, FTime, LOCTEXT("Metasound_MathSubractTimeNodeDescription", "Subtracts time values."), MathOpNames::SubtractKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Multiply, Float, float, LOCTEXT("Metasound_MathMultiplyFloatNodeDescription", "Multiplies floats."), MathOpNames::MultiplyKeywords)
|
|
DEFINE_METASOUND_MATHOP(Multiply, Int32, int32, LOCTEXT("Metasound_MathMultiplyInt32NodeDescription", "Multiplies int32s."), MathOpNames::MultiplyKeywords)
|
|
//DEFINE_METASOUND_MATHOP(Multiply, Int64, int64, LOCTEXT("Metasound_MathMultiplyInt64NodeDescription", "Multiplies int64s."), MathOpNames::MultiplyKeywords)
|
|
DEFINE_METASOUND_MATHOP(Multiply, Audio, FAudioBuffer, LOCTEXT("Metasound_MathMultiplyBufferNodeDescription", "Multiplies buffers together sample-by-sample."), MathOpNames::MultiplyKeywords)
|
|
|
|
DEFINE_METASOUND_OPERAND_TYPED_MATHOP(Multiply, Audio, FAudioBuffer, Float, float, LOCTEXT("Metasound_MathMultiplyAudioByFloatDescription", "Multiplies buffer by float scalars."), MathOpNames::MultiplyKeywords)
|
|
DEFINE_METASOUND_OPERAND_TYPED_MATHOP(Multiply, Time, FTime, Float, float, LOCTEXT("Metasound_MathMultiplyTimeNodeDescription", "Scales time by floats."), MathOpNames::MultiplyKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Divide, Float, float, LOCTEXT("Metasound_MathDivideFloatNodeDescription", "Divide float by another float."), MathOpNames::DivideKeywords)
|
|
DEFINE_METASOUND_MATHOP(Divide, Int32, int32, LOCTEXT("Metasound_MathDivideInt32NodeDescription", "Divide int32 by another int32."), MathOpNames::DivideKeywords)
|
|
//DEFINE_METASOUND_MATHOP(Divide, Int64, int64, LOCTEXT("Metasound_MathDivideInt64NodeDescription", "Divide int64 by another int64."), MathOpNames::DivideKeywords)
|
|
|
|
DEFINE_METASOUND_OPERAND_TYPED_MATHOP(Divide, Time, FTime, Float, float, LOCTEXT("Metasound_MathDivideTimeNodeDescription", "Divides time by floats."), MathOpNames::DivideKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Modulo, Int32, int32, LOCTEXT("Metasound_MathModulusInt32NodeDescription", "Modulo int32 by another int32."), MathOpNames::ModuloKeywords)
|
|
//DEFINE_METASOUND_MATHOP(Modulo, Int64, int64, LOCTEXT("Metasound_MathModulusInt64NodeDescription", "Modulo int64 by another int64."), MathOpNames::ModuloKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Power, Float, float, LOCTEXT("Metasound_MathPowerFloatNodeDescription", "Raise float to the power of another float."), MathOpNames::PowerKeywords)
|
|
|
|
DEFINE_METASOUND_MATHOP(Logarithm, Float, float, LOCTEXT("Metasound_MathLogarithmFloatNodeDescription", "Calculate float-base logarithm of another float."), TArray<FText>())
|
|
|
|
METASOUND_REGISTER_NODE(FAddFloatNode)
|
|
METASOUND_REGISTER_NODE(FAddInt32Node)
|
|
//METASOUND_REGISTER_NODE(FAddInt64Node)
|
|
METASOUND_REGISTER_NODE(FAddTimeNode)
|
|
METASOUND_REGISTER_NODE(FAddAudioNode)
|
|
METASOUND_REGISTER_NODE(FAddAudioFloatNode)
|
|
|
|
METASOUND_REGISTER_NODE(FSubtractFloatNode)
|
|
METASOUND_REGISTER_NODE(FSubtractInt32Node)
|
|
//METASOUND_REGISTER_NODE(FSubtractInt64Node)
|
|
METASOUND_REGISTER_NODE(FSubtractTimeNode)
|
|
METASOUND_REGISTER_NODE(FSubtractAudioNode)
|
|
|
|
METASOUND_REGISTER_NODE(FMultiplyAudioNode)
|
|
METASOUND_REGISTER_NODE(FMultiplyAudioFloatNode)
|
|
METASOUND_REGISTER_NODE(FMultiplyFloatNode)
|
|
METASOUND_REGISTER_NODE(FMultiplyInt32Node)
|
|
//METASOUND_REGISTER_NODE(FMultiplyInt64Node)
|
|
METASOUND_REGISTER_NODE(FMultiplyTimeFloatNode)
|
|
|
|
METASOUND_REGISTER_NODE(FDivideFloatNode)
|
|
METASOUND_REGISTER_NODE(FDivideInt32Node)
|
|
//METASOUND_REGISTER_NODE(FDivideInt64Node)
|
|
METASOUND_REGISTER_NODE(FDivideTimeFloatNode)
|
|
|
|
METASOUND_REGISTER_NODE(FModuloInt32Node)
|
|
//METASOUND_REGISTER_NODE(FModuloInt64Node)
|
|
|
|
METASOUND_REGISTER_NODE(FPowerFloatNode)
|
|
|
|
METASOUND_REGISTER_NODE(FLogarithmFloatNode)
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE // MetasoundMathOpNode
|