2021-01-11 14:18:46 -04:00
|
|
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
|
|
#include "MetasoundPeriodicTriggerNode.h"
|
|
|
|
|
|
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
|
|
|
|
|
|
#include "MetasoundBuilderInterface.h"
|
|
|
|
|
#include "MetasoundDataReferenceCollection.h"
|
|
|
|
|
#include "MetasoundExecutableOperator.h"
|
|
|
|
|
#include "MetasoundFacade.h"
|
|
|
|
|
#include "MetasoundNode.h"
|
|
|
|
|
#include "MetasoundNodeInterface.h"
|
|
|
|
|
#include "MetasoundNodeRegistrationMacro.h"
|
|
|
|
|
#include "MetasoundOperatorInterface.h"
|
|
|
|
|
#include "MetasoundPrimitives.h"
|
2021-01-28 19:02:51 -04:00
|
|
|
#include "MetasoundStandardNodesNames.h"
|
2021-01-11 14:18:46 -04:00
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MetasoundStandardNodes"
|
|
|
|
|
|
|
|
|
|
namespace Metasound
|
|
|
|
|
{
|
|
|
|
|
METASOUND_REGISTER_NODE(FPeriodicTriggerNode)
|
|
|
|
|
|
|
|
|
|
class FPeriodicTriggerOperator : public TExecutableOperator<FPeriodicTriggerOperator>
|
|
|
|
|
{
|
|
|
|
|
public:
|
2021-01-28 19:02:51 -04:00
|
|
|
static const FNodeClassMetadata& GetNodeInfo();
|
2021-02-03 16:05:09 -04:00
|
|
|
static const FVertexInterface& GetVertexInterface();
|
2021-01-11 14:18:46 -04:00
|
|
|
static TUniquePtr<IOperator> CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors);
|
|
|
|
|
|
|
|
|
|
static constexpr float MinimumPeriodSeconds = 0.001f;
|
|
|
|
|
static constexpr float MinimumPeriodSamples = 20.f;
|
|
|
|
|
|
|
|
|
|
FPeriodicTriggerOperator(const FOperatorSettings& InSettings, const FTriggerReadRef& InTriggerEnable, const FTriggerReadRef& InTriggerDisable, const FFloatTimeReadRef& InPeriod);
|
|
|
|
|
|
|
|
|
|
virtual FDataReferenceCollection GetInputs() const override;
|
|
|
|
|
|
|
|
|
|
virtual FDataReferenceCollection GetOutputs() const override;
|
|
|
|
|
|
|
|
|
|
void Execute();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool bEnabled;
|
|
|
|
|
|
|
|
|
|
FTriggerWriteRef TriggerOut;
|
|
|
|
|
|
|
|
|
|
FTriggerReadRef TriggerEnable;
|
|
|
|
|
FTriggerReadRef TriggerDisable;
|
|
|
|
|
|
|
|
|
|
FFloatTimeReadRef Period;
|
|
|
|
|
|
|
|
|
|
float ExecuteDurationInSamples;
|
|
|
|
|
float SampleRate;
|
|
|
|
|
float SampleCountdown;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
FPeriodicTriggerOperator::FPeriodicTriggerOperator(const FOperatorSettings& InSettings, const FTriggerReadRef& InTriggerEnable, const FTriggerReadRef& InTriggerDisable, const FFloatTimeReadRef& InPeriod)
|
|
|
|
|
: bEnabled(false)
|
|
|
|
|
, TriggerOut(FTriggerWriteRef::CreateNew(InSettings))
|
|
|
|
|
, TriggerEnable(InTriggerEnable)
|
|
|
|
|
, TriggerDisable(InTriggerDisable)
|
|
|
|
|
, Period(InPeriod)
|
|
|
|
|
, ExecuteDurationInSamples(InSettings.GetNumFramesPerBlock())
|
|
|
|
|
, SampleRate(InSettings.GetSampleRate())
|
|
|
|
|
, SampleCountdown(0.f)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDataReferenceCollection FPeriodicTriggerOperator::GetInputs() const
|
|
|
|
|
{
|
|
|
|
|
FDataReferenceCollection InputDataReferences;
|
|
|
|
|
InputDataReferences.AddDataReadReference(TEXT("Period"), FFloatTimeReadRef(Period));
|
|
|
|
|
InputDataReferences.AddDataReadReference(TEXT("Activate"), FTriggerReadRef(TriggerEnable));
|
|
|
|
|
InputDataReferences.AddDataReadReference(TEXT("Deactivate"), FTriggerReadRef(TriggerDisable));
|
|
|
|
|
return InputDataReferences;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FDataReferenceCollection FPeriodicTriggerOperator::GetOutputs() const
|
|
|
|
|
{
|
|
|
|
|
FDataReferenceCollection OutputDataReferences;
|
|
|
|
|
OutputDataReferences.AddDataReadReference(TEXT("Out"), FTriggerReadRef(TriggerOut));
|
|
|
|
|
|
|
|
|
|
return OutputDataReferences;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FPeriodicTriggerOperator::Execute()
|
|
|
|
|
{
|
|
|
|
|
TriggerEnable->ExecuteBlock([](int32, int32) { },
|
|
|
|
|
[this](int32 StartFrame, int32 EndFrame)
|
|
|
|
|
{
|
|
|
|
|
bEnabled = true;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
TriggerDisable->ExecuteBlock([](int32, int32) { },
|
|
|
|
|
[this](int32 StartFrame, int32 EndFrame)
|
|
|
|
|
{
|
|
|
|
|
bEnabled = false;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2021-01-22 01:24:58 -04:00
|
|
|
// Advance internal counter to get rid of old triggers.
|
2021-01-11 14:18:46 -04:00
|
|
|
TriggerOut->AdvanceBlock();
|
|
|
|
|
|
|
|
|
|
if (bEnabled)
|
|
|
|
|
{
|
|
|
|
|
float PeriodInSamples = FMath::Max(Period->GetSeconds(), MinimumPeriodSeconds) * SampleRate;
|
|
|
|
|
|
|
|
|
|
PeriodInSamples = FMath::Max(PeriodInSamples, MinimumPeriodSamples);
|
|
|
|
|
|
|
|
|
|
while ((SampleCountdown - ExecuteDurationInSamples) <= 0.f)
|
|
|
|
|
{
|
|
|
|
|
uint32 Frame = FMath::RoundToInt(SampleCountdown);
|
2021-01-27 15:54:01 -04:00
|
|
|
TriggerOut->TriggerFrame(Frame);
|
2021-01-11 14:18:46 -04:00
|
|
|
SampleCountdown += PeriodInSamples;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SampleCountdown -= ExecuteDurationInSamples;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TUniquePtr<IOperator> FPeriodicTriggerOperator::CreateOperator(const FCreateOperatorParams& InParams, FBuildErrorArray& OutErrors)
|
|
|
|
|
{
|
2021-01-22 01:24:58 -04:00
|
|
|
const FPeriodicTriggerNode& PeriodicTriggerNode = static_cast<const FPeriodicTriggerNode&>(InParams.Node);
|
2021-02-03 16:05:09 -04:00
|
|
|
const FInputVertexInterface& InputInterface = GetVertexInterface().GetInputInterface();
|
2021-01-11 14:18:46 -04:00
|
|
|
|
2021-02-03 16:05:09 -04:00
|
|
|
FFloatTimeReadRef Period = InParams.InputDataReferences.GetDataReadReferenceOrConstructWithVertexDefault<FFloatTime, float>(InputInterface, TEXT("Period"));
|
2021-01-22 01:24:58 -04:00
|
|
|
FTriggerReadRef TriggerEnable = InParams.InputDataReferences.GetDataReadReferenceOrConstruct<FTrigger>(TEXT("Activate"), InParams.OperatorSettings);
|
|
|
|
|
FTriggerReadRef TriggerDisable = InParams.InputDataReferences.GetDataReadReferenceOrConstruct<FTrigger>(TEXT("Deactivate"), InParams.OperatorSettings);
|
2021-01-11 14:18:46 -04:00
|
|
|
|
|
|
|
|
return MakeUnique<FPeriodicTriggerOperator>(InParams.OperatorSettings, TriggerEnable, TriggerDisable, Period);
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-03 16:05:09 -04:00
|
|
|
const FVertexInterface& FPeriodicTriggerOperator::GetVertexInterface()
|
2021-01-11 14:18:46 -04:00
|
|
|
{
|
|
|
|
|
static const FVertexInterface Interface(
|
|
|
|
|
FInputVertexInterface(
|
2021-02-03 16:05:09 -04:00
|
|
|
TInputDataVertexModel<FFloatTime>(TEXT("Period"), LOCTEXT("PeriodTooltip", "The period to trigger in seconds."), 1.0f),
|
2021-01-22 01:24:58 -04:00
|
|
|
TInputDataVertexModel<FTrigger>(TEXT("Activate"), LOCTEXT("TriggerEnableTooltip", "Enables executing periodic output triggers.")),
|
|
|
|
|
TInputDataVertexModel<FTrigger>(TEXT("Deactivate"), LOCTEXT("TriggerDisableTooltip", "Disables executing periodic output triggers."))
|
2021-01-11 14:18:46 -04:00
|
|
|
),
|
|
|
|
|
FOutputVertexInterface(
|
2021-01-22 01:24:58 -04:00
|
|
|
TOutputDataVertexModel<FTrigger>(TEXT("Out"), LOCTEXT("TriggerOutTooltip", "The periodically generated output trigger"))
|
2021-01-11 14:18:46 -04:00
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return Interface;
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-28 19:02:51 -04:00
|
|
|
const FNodeClassMetadata& FPeriodicTriggerOperator::GetNodeInfo()
|
2021-01-11 14:18:46 -04:00
|
|
|
{
|
2021-01-28 19:02:51 -04:00
|
|
|
auto InitNodeInfo = []() -> FNodeClassMetadata
|
2021-01-11 14:18:46 -04:00
|
|
|
{
|
2021-01-28 19:02:51 -04:00
|
|
|
FNodeClassMetadata Info;
|
2021-02-03 16:05:09 -04:00
|
|
|
Info.ClassName = { Metasound::StandardNodes::Namespace, TEXT("PeriodicTrigger"), TEXT("") };
|
2021-01-11 14:18:46 -04:00
|
|
|
Info.MajorVersion = 1;
|
|
|
|
|
Info.MinorVersion = 0;
|
2021-01-28 19:02:51 -04:00
|
|
|
Info.DisplayName = LOCTEXT("Metasound_PeriodicTriggerNodeDisplayName", "Periodic Trigger");
|
2021-01-22 01:24:58 -04:00
|
|
|
Info.Description = LOCTEXT("Metasound_PeriodicTriggerNodeDescription", "Emits a trigger periodically based on the period duration given.");
|
2021-01-11 14:18:46 -04:00
|
|
|
Info.Author = PluginAuthor;
|
|
|
|
|
Info.PromptIfMissing = PluginNodeMissingPrompt;
|
2021-02-03 16:05:09 -04:00
|
|
|
Info.DefaultInterface = GetVertexInterface();
|
2021-01-11 14:18:46 -04:00
|
|
|
|
|
|
|
|
return Info;
|
|
|
|
|
};
|
|
|
|
|
|
2021-01-28 19:02:51 -04:00
|
|
|
static const FNodeClassMetadata Info = InitNodeInfo();
|
2021-01-11 14:18:46 -04:00
|
|
|
|
|
|
|
|
return Info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FPeriodicTriggerNode::FPeriodicTriggerNode(const FNodeInitData& InInitData)
|
2021-02-03 14:36:36 -04:00
|
|
|
: FNodeFacade(InInitData.InstanceName, InInitData.InstanceID, TFacadeOperatorClass<FPeriodicTriggerOperator>())
|
2021-01-11 14:18:46 -04:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 01:24:58 -04:00
|
|
|
#undef LOCTEXT_NAMESPACE //MetasoundPeriodicTriggerNode
|