2021-01-11 22:57:56 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# 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 22:57:56 -04:00
# include "MetasoundTime.h"
2021-01-27 15:54:01 -04:00
# include "MetasoundTrigger.h"
2021-03-05 23:03:16 -04:00
# include "MetasoundSampleCounter.h"
# include "MetasoundStandardNodesCategories.h"
2021-03-24 03:22:53 -04:00
# include "MetasoundParamHelper.h"
2021-01-11 22:57:56 -04:00
2021-04-07 02:57:54 -04:00
# define LOCTEXT_NAMESPACE "MetasoundStandardNodes_TriggerPipe"
2021-01-11 22:57:56 -04:00
namespace Metasound
{
2021-03-24 03:22:53 -04:00
namespace TriggerPipeVertexNames
{
METASOUND_PARAM ( InputInTrigger , " In " , " Trigger to execute at a future time by the given delay amount. " ) ;
METASOUND_PARAM ( InputReset , " Reset " , " Resets the trigger delay, clearing any pending execution tasks. " ) ;
METASOUND_PARAM ( InputDelayTime , " Delay Time " , " Time to delay and execute deferred input trigger execution(s) in seconds. " ) ;
METASOUND_PARAM ( OutputOutTrigger , " Out " , " The delayed output trigger(s). " ) ;
}
2021-01-11 22:57:56 -04:00
class FTriggerPipeOperator : public TExecutableOperator < FTriggerPipeOperator >
{
2021-02-03 14:36:36 -04:00
public :
static const FNodeClassMetadata & GetNodeInfo ( ) ;
static const FVertexInterface & GetVertexInterface ( ) ;
static TUniquePtr < IOperator > CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors ) ;
2021-01-11 22:57:56 -04:00
2021-02-16 01:26:50 -04:00
FTriggerPipeOperator ( const FOperatorSettings & InSettings , const FTriggerReadRef & InTriggerReset , const FTriggerReadRef & InTriggerIn , const FTimeReadRef & InDelay ) ;
2021-01-11 22:57:56 -04:00
2023-05-22 13:28:27 -04:00
virtual void BindInputs ( FInputVertexInterfaceData & InOutVertexData ) override ;
virtual void BindOutputs ( FOutputVertexInterfaceData & InOutVertexData ) override ;
2021-02-03 14:36:36 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override ;
virtual FDataReferenceCollection GetOutputs ( ) const override ;
void Execute ( ) ;
2023-03-02 14:40:35 -05:00
void Reset ( const IOperator : : FResetParams & InParams ) ;
2021-01-11 22:57:56 -04:00
2021-02-03 14:36:36 -04:00
private :
2021-02-16 01:26:50 -04:00
TArray < FSampleCount > SamplesUntilTrigger ;
2021-01-11 22:57:56 -04:00
2021-02-03 14:36:36 -04:00
FTriggerReadRef TriggerIn ;
FTriggerReadRef TriggerReset ;
FTriggerWriteRef TriggerOut ;
2021-01-11 22:57:56 -04:00
2021-03-24 03:22:53 -04:00
FTimeReadRef DelayTime ;
2021-01-11 22:57:56 -04:00
2021-02-16 01:26:50 -04:00
FSampleCount FramesPerBlock ;
FSampleRate SampleRate ;
2021-01-11 22:57:56 -04:00
} ;
2021-03-24 03:22:53 -04:00
FTriggerPipeOperator : : FTriggerPipeOperator ( const FOperatorSettings & InSettings , const FTriggerReadRef & InTriggerReset , const FTriggerReadRef & InTriggerIn , const FTimeReadRef & InDelayTime )
: TriggerIn ( InTriggerIn )
, TriggerReset ( InTriggerReset )
, TriggerOut ( FTriggerWriteRef : : CreateNew ( InSettings ) )
, DelayTime ( InDelayTime )
, FramesPerBlock ( InSettings . GetNumFramesPerBlock ( ) )
, SampleRate ( InSettings . GetSampleRate ( ) )
2021-01-11 22:57:56 -04:00
{
}
2023-05-22 13:28:27 -04:00
void FTriggerPipeOperator : : BindInputs ( FInputVertexInterfaceData & InOutVertexData )
2021-01-11 22:57:56 -04:00
{
2021-03-24 03:22:53 -04:00
using namespace TriggerPipeVertexNames ;
2023-05-22 13:28:27 -04:00
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputInTrigger ) , TriggerIn ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputReset ) , TriggerReset ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputDelayTime ) , DelayTime ) ;
}
2021-03-24 03:22:53 -04:00
2023-05-22 13:28:27 -04:00
void FTriggerPipeOperator : : BindOutputs ( FOutputVertexInterfaceData & InOutVertexData )
{
using namespace TriggerPipeVertexNames ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( OutputOutTrigger ) , TriggerOut ) ;
}
FDataReferenceCollection FTriggerPipeOperator : : GetInputs ( ) const
{
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
2021-01-11 22:57:56 -04:00
}
FDataReferenceCollection FTriggerPipeOperator : : GetOutputs ( ) const
{
2023-05-22 13:28:27 -04:00
// This should never be called. Bind(...) is called instead. This method
// exists as a stop-gap until the API can be deprecated and removed.
checkNoEntry ( ) ;
return { } ;
2021-01-11 22:57:56 -04:00
}
void FTriggerPipeOperator : : Execute ( )
{
// Advance internal counter to get rid of old triggers.
TriggerOut - > AdvanceBlock ( ) ;
TriggerIn - > ExecuteBlock (
[ ] ( int32 StartFrame , int32 EndFrame )
{
} ,
[ this ] ( int32 StartFrame , int32 EndFrame )
{
2021-03-25 10:52:30 -04:00
SamplesUntilTrigger . AddUnique ( StartFrame + FMath : : Max ( DelayTime - > GetSeconds ( ) , 0.0 ) * SampleRate ) ;
2021-01-11 22:57:56 -04:00
}
) ;
TriggerReset - > ExecuteBlock (
[ ] ( int32 StartFrame , int32 EndFrame )
{
} ,
[ this ] ( int32 StartFrame , int32 EndFrame )
{
2021-02-03 14:36:36 -04:00
// Iterate backward and only remove delayed triggers that occur
// after the reset trigger's start frame.
2021-02-16 01:26:50 -04:00
for ( FSampleCount i = SamplesUntilTrigger . Num ( ) - 1 ; i > = 0 ; - - i )
2021-02-03 14:36:36 -04:00
{
2021-02-16 01:26:50 -04:00
const FSampleCount SamplesRemaining = SamplesUntilTrigger [ i ] - FramesPerBlock ;
2021-02-03 14:36:36 -04:00
if ( SamplesRemaining > = StartFrame )
{
SamplesUntilTrigger . RemoveAtSwap ( i ) ;
}
}
2021-01-11 22:57:56 -04:00
}
) ;
2021-02-03 14:36:36 -04:00
2021-02-16 01:26:50 -04:00
for ( FSampleCount i = SamplesUntilTrigger . Num ( ) - 1 ; i > = 0 ; - - i )
2021-02-03 14:36:36 -04:00
{
2021-02-16 01:26:50 -04:00
const FSampleCount SamplesRemaining = SamplesUntilTrigger [ i ] - FramesPerBlock ;
2021-02-03 14:36:36 -04:00
if ( SamplesRemaining > = 0 )
{
SamplesUntilTrigger [ i ] - = FramesPerBlock ;
}
else
{
2021-02-16 01:26:50 -04:00
TriggerOut - > TriggerFrame ( SamplesRemaining + static_cast < FSampleCount > ( FramesPerBlock ) ) ;
2021-02-03 14:36:36 -04:00
SamplesUntilTrigger . RemoveAtSwap ( i ) ;
}
}
2021-01-11 22:57:56 -04:00
}
2023-03-02 14:40:35 -05:00
void FTriggerPipeOperator : : Reset ( const IOperator : : FResetParams & InParams )
{
SamplesUntilTrigger . Reset ( ) ;
TriggerOut - > Reset ( ) ;
}
2021-01-11 22:57:56 -04:00
TUniquePtr < IOperator > FTriggerPipeOperator : : CreateOperator ( const FCreateOperatorParams & InParams , FBuildErrorArray & OutErrors )
{
2021-03-24 03:22:53 -04:00
using namespace TriggerPipeVertexNames ;
2021-02-03 14:36:36 -04:00
const FDataReferenceCollection & InputCollection = InParams . InputDataReferences ;
const FInputVertexInterface & InputInterface = GetVertexInterface ( ) . GetInputInterface ( ) ;
2021-02-16 01:26:50 -04:00
2021-03-25 10:52:30 -04:00
FTriggerReadRef TriggerIn = InParams . InputDataReferences . GetDataReadReferenceOrConstruct < FTrigger > ( METASOUND_GET_PARAM_NAME ( InputInTrigger ) , InParams . OperatorSettings ) ;
2021-03-24 03:22:53 -04:00
FTriggerReadRef TriggerReset = InParams . InputDataReferences . GetDataReadReferenceOrConstruct < FTrigger > ( METASOUND_GET_PARAM_NAME ( InputReset ) , InParams . OperatorSettings ) ;
2021-03-25 10:52:30 -04:00
FTimeReadRef DelayTime = InputCollection . GetDataReadReferenceOrConstructWithVertexDefault < FTime > ( InputInterface , METASOUND_GET_PARAM_NAME ( InputDelayTime ) , InParams . OperatorSettings ) ;
2021-01-11 22:57:56 -04:00
2021-03-24 03:22:53 -04:00
return MakeUnique < FTriggerPipeOperator > ( InParams . OperatorSettings , TriggerReset , TriggerIn , DelayTime ) ;
2021-01-11 22:57:56 -04:00
}
2021-02-03 14:36:36 -04:00
const FVertexInterface & FTriggerPipeOperator : : GetVertexInterface ( )
2021-01-11 22:57:56 -04:00
{
2021-03-24 03:22:53 -04:00
using namespace TriggerPipeVertexNames ;
2021-01-11 22:57:56 -04:00
static const FVertexInterface Interface (
FInputVertexInterface (
2022-03-31 16:49:59 -04:00
TInputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputInTrigger ) ) ,
TInputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputReset ) ) ,
TInputDataVertex < FTime > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputDelayTime ) , 1.0f )
2021-03-24 03:22:53 -04:00
) ,
2021-01-11 22:57:56 -04:00
FOutputVertexInterface (
2022-03-31 16:49:59 -04:00
TOutputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( OutputOutTrigger ) )
2021-01-11 22:57:56 -04:00
)
) ;
return Interface ;
}
2021-01-28 19:02:51 -04:00
const FNodeClassMetadata & FTriggerPipeOperator : : GetNodeInfo ( )
2021-01-11 22:57:56 -04:00
{
2021-01-28 19:02:51 -04:00
auto InitNodeInfo = [ ] ( ) - > FNodeClassMetadata
2021-01-11 22:57:56 -04:00
{
2021-01-28 19:02:51 -04:00
FNodeClassMetadata Info ;
2021-03-24 03:22:53 -04:00
Info . ClassName = FNodeClassName ( StandardNodes : : Namespace , " Pipe " , " " ) ;
2021-01-11 22:57:56 -04:00
Info . MajorVersion = 1 ;
Info . MinorVersion = 0 ;
2022-02-10 18:36:47 -05:00
Info . DisplayName = METASOUND_LOCTEXT ( " PipeTriggerNode_NodeDisplayName " , " Trigger Pipe " ) ;
Info . Description = METASOUND_LOCTEXT ( " Metasound_DelayNodeDescription " , " Delays execution of the input trigger(s) by the given delay for all input trigger executions. " ) ;
2021-01-11 22:57:56 -04:00
Info . Author = PluginAuthor ;
Info . PromptIfMissing = PluginNodeMissingPrompt ;
2021-02-03 14:36:36 -04:00
Info . DefaultInterface = GetVertexInterface ( ) ;
2021-08-09 15:08:37 -04:00
Info . CategoryHierarchy . Emplace ( NodeCategories : : Trigger ) ;
2021-01-11 22:57:56 -04:00
return Info ;
} ;
2021-01-28 19:02:51 -04:00
static const FNodeClassMetadata Info = InitNodeInfo ( ) ;
2021-01-11 22:57:56 -04:00
return Info ;
}
2021-03-25 10:52:30 -04:00
class METASOUNDSTANDARDNODES_API FTriggerPipeNode : public FNodeFacade
2021-01-11 22:57:56 -04:00
{
2021-03-25 10:52:30 -04:00
public :
FTriggerPipeNode ( const FNodeInitData & InInitData )
: FNodeFacade ( InInitData . InstanceName , InInitData . InstanceID , TFacadeOperatorClass < FTriggerPipeOperator > ( ) )
{
}
virtual ~ FTriggerPipeNode ( ) = default ;
} ;
METASOUND_REGISTER_NODE ( FTriggerPipeNode )
2021-01-11 22:57:56 -04:00
}
# undef LOCTEXT_NAMESPACE // MetasoundTriggerPipeNode