2021-03-15 14:00:26 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# pragma once
2021-04-05 20:22:19 -04:00
# include "Containers/CircularQueue.h"
2022-08-19 12:14:31 -04:00
# include "Interfaces/MetasoundFrontendSourceInterface.h"
2021-04-05 20:22:19 -04:00
# include "MetasoundArrayNodes.h"
# include "MetasoundExecutableOperator.h"
2021-03-15 14:00:26 -04:00
# include "MetasoundFacade.h"
# include "MetasoundNodeInterface.h"
2022-03-17 13:14:50 -04:00
# include "MetasoundParamHelper.h"
2021-03-29 23:58:06 -04:00
# include "MetasoundTrigger.h"
2021-03-15 14:00:26 -04:00
2022-01-18 17:44:56 -05:00
# define LOCTEXT_NAMESPACE "MetasoundFrontend"
2021-03-15 14:00:26 -04:00
namespace Metasound
{
namespace ArrayNodeRandomGetVertexNames
{
2022-03-17 13:14:50 -04:00
METASOUND_PARAM ( InputTriggerNextValue , " Next " , " Trigger to get the next value in the randomized array. " )
METASOUND_PARAM ( InputTriggerResetSeed , " Reset " , " Trigger to reset the seed for the randomized array. " )
METASOUND_PARAM ( InputRandomArray , " In Array " , " Input array to randomized. " )
METASOUND_PARAM ( InputWeights , " Weights " , " Input array of weights to use for random selection. Will repeat if this array is shorter than the input array to select from. " )
METASOUND_PARAM ( InputSeed , " Seed " , " Seed to use for the random shuffle. " )
METASOUND_PARAM ( InputNoRepeatOrder , " No Repeats " , " The number of elements to track to avoid repeating in a row. " )
METASOUND_PARAM ( InputEnableSharedState , " Enable Shared State " , " Set to enabled to share state across instances of this MetaSound. " )
METASOUND_PARAM ( OutputTriggerOnNext , " On Next " , " Triggers when the \" Next \" input is triggered. " )
METASOUND_PARAM ( OutputTriggerOnReset , " On Reset " , " Triggers when the \" Shuffle \" input is triggered or if the array is auto-shuffled. " )
METASOUND_PARAM ( ShuffleOutputValue , " Value " , " Value of the current shuffled element. " )
2021-03-15 14:00:26 -04:00
}
class METASOUNDFRONTEND_API FArrayRandomGet
{
public :
FArrayRandomGet ( ) = default ;
2021-03-29 23:58:06 -04:00
FArrayRandomGet ( int32 InSeed , int32 InMaxIndex , const TArray < float > & InWeights , int32 InNoRepeatOrder ) ;
~ FArrayRandomGet ( ) = default ;
void Init ( int32 InSeed , int32 InMaxIndex , const TArray < float > & InWeights , int32 InNoRepeatOrder ) ;
2021-03-15 14:00:26 -04:00
void SetSeed ( int32 InSeed ) ;
void SetNoRepeatOrder ( int32 InNoRepeatOrder ) ;
2021-03-29 23:58:06 -04:00
void SetRandomWeights ( const TArray < float > & InRandomWeights ) ;
2021-03-15 14:00:26 -04:00
void ResetSeed ( ) ;
int32 NextValue ( ) ;
2022-03-01 21:24:51 -05:00
int32 GetNoRepeatOrder ( ) const { return NoRepeatOrder ; }
int32 GetMaxIndex ( ) const { return MaxIndex ; }
2021-03-15 14:00:26 -04:00
private :
2021-03-29 23:58:06 -04:00
float ComputeTotalWeight ( ) ;
2021-03-15 14:00:26 -04:00
// The current index into the array of indicies (wraps between 0 and ShuffleIndices.Num())
TArray < int32 > PreviousIndices ;
TUniquePtr < TCircularQueue < int32 > > PreviousIndicesQueue ;
2021-03-22 08:31:34 -04:00
int32 NoRepeatOrder = INDEX_NONE ;
2021-03-15 14:00:26 -04:00
// Array of indices (in order 0 to Num)
int32 MaxIndex = 0 ;
TArray < float > RandomWeights ;
// Random stream to use to randomize the shuffling
FRandomStream RandomStream ;
} ;
2021-04-03 18:41:39 -04:00
struct InitSharedStateArgs
{
2022-02-04 18:18:22 -05:00
FGuid SharedStateId ;
2021-04-03 18:41:39 -04:00
int32 Seed = INDEX_NONE ;
int32 NumElements = 0 ;
int32 NoRepeatOrder = 0 ;
bool bIsPreviewSound = false ;
TArray < float > Weights ;
} ;
2021-03-15 14:00:26 -04:00
class METASOUNDFRONTEND_API FSharedStateRandomGetManager
{
public :
static FSharedStateRandomGetManager & Get ( ) ;
2021-04-03 18:41:39 -04:00
void InitSharedState ( InitSharedStateArgs & InArgs ) ;
2022-02-04 18:18:22 -05:00
int32 NextValue ( const FGuid & InSharedStateId ) ;
void SetSeed ( const FGuid & InSharedStateId , int32 InSeed ) ;
void SetNoRepeatOrder ( const FGuid & InSharedStateId , int32 InNoRepeatOrder ) ;
void SetRandomWeights ( const FGuid & InSharedStateId , const TArray < float > & InRandomWeights ) ;
void ResetSeed ( const FGuid & InSharedStateId ) ;
2021-03-15 14:00:26 -04:00
private :
FSharedStateRandomGetManager ( ) = default ;
~ FSharedStateRandomGetManager ( ) = default ;
FCriticalSection CritSect ;
2022-02-04 18:18:22 -05:00
TMap < FGuid , TUniquePtr < FArrayRandomGet > > RandomGets ;
2021-03-15 14:00:26 -04:00
} ;
template < typename ArrayType >
class TArrayRandomGetOperator : public TExecutableOperator < TArrayRandomGetOperator < ArrayType > >
{
public :
using FArrayDataReadReference = TDataReadReference < ArrayType > ;
2021-03-29 23:58:06 -04:00
using FArrayWeightReadReference = TDataReadReference < TArray < float > > ;
2021-04-03 18:41:39 -04:00
using WeightsArrayType = TArray < float > ;
2021-03-15 14:00:26 -04:00
using ElementType = typename MetasoundArrayNodesPrivate : : TArrayElementType < ArrayType > : : Type ;
using FElementTypeWriteReference = TDataWriteReference < ElementType > ;
static const FVertexInterface & GetDefaultInterface ( )
{
using namespace ArrayNodeRandomGetVertexNames ;
static const FVertexInterface DefaultInterface (
FInputVertexInterface (
2022-03-31 16:49:59 -04:00
TInputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputTriggerNextValue ) ) ,
TInputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputTriggerResetSeed ) ) ,
TInputDataVertex < ArrayType > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputRandomArray ) ) ,
TInputDataVertex < WeightsArrayType > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputWeights ) ) ,
TInputDataVertex < int32 > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputSeed ) , - 1 ) ,
TInputDataVertex < int32 > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputNoRepeatOrder ) , 1 ) ,
TInputDataVertex < bool > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( InputEnableSharedState ) , false )
2021-03-15 14:00:26 -04:00
) ,
FOutputVertexInterface (
2022-03-31 16:49:59 -04:00
TOutputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( OutputTriggerOnNext ) ) ,
TOutputDataVertex < FTrigger > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( OutputTriggerOnReset ) ) ,
TOutputDataVertex < ElementType > ( METASOUND_GET_PARAM_NAME_AND_METADATA ( ShuffleOutputValue ) )
2021-03-15 14:00:26 -04:00
)
) ;
return DefaultInterface ;
}
static const FNodeClassMetadata & GetNodeInfo ( )
{
auto CreateNodeClassMetadata = [ ] ( ) - > FNodeClassMetadata
{
FName DataTypeName = GetMetasoundDataTypeName < ArrayType > ( ) ;
2021-05-10 16:56:43 -04:00
FName OperatorName = " Random Get " ;
2022-02-10 18:36:47 -05:00
FText NodeDisplayName = METASOUND_LOCTEXT_FORMAT ( " RandomArrayGetNode_OpDisplayNamePattern " , " Random Get ({0}) " , GetMetasoundDataTypeDisplayText < ArrayType > ( ) ) ;
FText NodeDescription = METASOUND_LOCTEXT ( " RandomArrayGetNode_Description " , " Randomly retrieve data from input array using the supplied weights. " ) ;
2021-03-15 14:00:26 -04:00
FVertexInterface NodeInterface = GetDefaultInterface ( ) ;
return MetasoundArrayNodesPrivate : : CreateArrayNodeClassMetadata ( DataTypeName , OperatorName , NodeDisplayName , NodeDescription , NodeInterface ) ;
} ;
static const FNodeClassMetadata Metadata = CreateNodeClassMetadata ( ) ;
return Metadata ;
}
2023-10-13 19:29:51 -04:00
static TUniquePtr < IOperator > CreateOperator ( const FBuildOperatorParams & InParams , FBuildResults & OutResults )
2021-03-15 14:00:26 -04:00
{
using namespace ArrayNodeRandomGetVertexNames ;
using namespace MetasoundArrayNodesPrivate ;
2023-10-13 19:29:51 -04:00
const FInputVertexInterfaceData & InputData = InParams . InputData ;
2021-03-15 14:00:26 -04:00
2023-10-13 19:29:51 -04:00
FTriggerReadRef InTriggerNext = InputData . GetOrCreateDefaultDataReadReference < FTrigger > ( METASOUND_GET_PARAM_NAME ( InputTriggerNextValue ) , InParams . OperatorSettings ) ;
FTriggerReadRef InTriggerReset = InputData . GetOrCreateDefaultDataReadReference < FTrigger > ( METASOUND_GET_PARAM_NAME ( InputTriggerResetSeed ) , InParams . OperatorSettings ) ;
FArrayDataReadReference InInputArray = InputData . GetOrCreateDefaultDataReadReference < ArrayType > ( METASOUND_GET_PARAM_NAME ( InputRandomArray ) , InParams . OperatorSettings ) ;
FArrayWeightReadReference InInputWeightsArray = InputData . GetOrCreateDefaultDataReadReference < WeightsArrayType > ( METASOUND_GET_PARAM_NAME ( InputWeights ) , InParams . OperatorSettings ) ;
FInt32ReadRef InSeedValue = InputData . GetOrCreateDefaultDataReadReference < int32 > ( METASOUND_GET_PARAM_NAME ( InputSeed ) , InParams . OperatorSettings ) ;
FInt32ReadRef InNoRepeatOrder = InputData . GetOrCreateDefaultDataReadReference < int32 > ( METASOUND_GET_PARAM_NAME ( InputNoRepeatOrder ) , InParams . OperatorSettings ) ;
FBoolReadRef bInEnableSharedState = InputData . GetOrCreateDefaultDataReadReference < bool > ( METASOUND_GET_PARAM_NAME ( InputEnableSharedState ) , InParams . OperatorSettings ) ;
2021-03-15 14:00:26 -04:00
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
return MakeUnique < TArrayRandomGetOperator < ArrayType > > ( InParams , InTriggerNext , InTriggerReset , InInputArray , InInputWeightsArray , InSeedValue , InNoRepeatOrder , bInEnableSharedState ) ;
2021-03-15 14:00:26 -04:00
}
TArrayRandomGetOperator (
2023-10-13 19:29:51 -04:00
const FBuildOperatorParams & InParams ,
2021-03-15 14:00:26 -04:00
const FTriggerReadRef & InTriggerNext ,
const FTriggerReadRef & InTriggerReset ,
const FArrayDataReadReference & InInputArray ,
2021-04-03 18:41:39 -04:00
const TDataReadReference < WeightsArrayType > & InInputWeightsArray ,
2021-03-15 14:00:26 -04:00
const FInt32ReadRef & InSeedValue ,
const FInt32ReadRef & InNoRepeatOrder ,
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
const FBoolReadRef & bInEnableSharedState )
2021-03-15 14:00:26 -04:00
: TriggerNext ( InTriggerNext )
, TriggerReset ( InTriggerReset )
, InputArray ( InInputArray )
, InputWeightsArray ( InInputWeightsArray )
, SeedValue ( InSeedValue )
, NoRepeatOrder ( InNoRepeatOrder )
, TriggerOnNext ( FTriggerWriteRef : : CreateNew ( InParams . OperatorSettings ) )
, TriggerOnReset ( FTriggerWriteRef : : CreateNew ( InParams . OperatorSettings ) )
, OutValue ( TDataWriteReferenceFactory < ElementType > : : CreateAny ( InParams . OperatorSettings ) )
2023-04-17 15:20:55 -04:00
, bEnableSharedState ( bInEnableSharedState )
2021-12-10 19:13:22 -05:00
{
2021-12-10 20:37:31 -05:00
using namespace Frontend ;
2023-02-22 17:54:26 -05:00
SharedStateUniqueId = InParams . Node . GetInstanceID ( ) ;
2021-08-09 15:13:40 -04:00
2023-02-22 17:54:26 -05:00
Reset ( InParams ) ;
2021-03-15 14:00:26 -04:00
}
virtual ~ TArrayRandomGetOperator ( ) = default ;
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
virtual void BindInputs ( FInputVertexInterfaceData & InOutVertexData ) override
{
using namespace ArrayNodeRandomGetVertexNames ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputTriggerNextValue ) , TriggerNext ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputTriggerResetSeed ) , TriggerReset ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputRandomArray ) , InputArray ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputWeights ) , InputWeightsArray ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputSeed ) , SeedValue ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputNoRepeatOrder ) , NoRepeatOrder ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( InputEnableSharedState ) , bEnableSharedState ) ;
}
virtual void BindOutputs ( FOutputVertexInterfaceData & InOutVertexData ) override
{
using namespace ArrayNodeRandomGetVertexNames ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( OutputTriggerOnNext ) , TriggerOnNext ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( OutputTriggerOnReset ) , TriggerOnReset ) ;
InOutVertexData . BindReadVertex ( METASOUND_GET_PARAM_NAME ( ShuffleOutputValue ) , OutValue ) ;
}
2021-03-15 14:00:26 -04:00
virtual FDataReferenceCollection GetInputs ( ) const override
{
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -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.
2023-04-17 15:20:55 -04:00
checkNoEntry ( ) ;
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
return { } ;
2021-03-15 14:00:26 -04:00
}
virtual FDataReferenceCollection GetOutputs ( ) const override
2023-04-17 15:20:55 -04:00
{
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -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.
2023-04-17 15:20:55 -04:00
checkNoEntry ( ) ;
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
return { } ;
2021-03-15 14:00:26 -04:00
}
2023-02-22 17:54:26 -05:00
void Reset ( const IOperator : : FResetParams & InParams )
{
using namespace Frontend ;
# if WITH_METASOUND_DEBUG_ENVIRONMENT
if ( InParams . Environment . Contains < FString > ( SourceInterface : : Environment : : GraphName ) )
{
GraphName = * InParams . Environment . GetValue < FString > ( SourceInterface : : Environment : : GraphName ) ;
}
# endif // WITH_METASOUND_DEBUG_ENVIRONMENT
bIsPreviewSound = InParams . Environment . GetValue < bool > ( SourceInterface : : Environment : : IsPreview ) ;
// Check to see if this is a global shuffler or a local one.
// Global shuffler will use a namespace to opt into it.
PrevSeedValue = * SeedValue ;
2023-12-20 12:45:12 -05:00
2023-02-22 17:54:26 -05:00
WeightsArray = * InputWeightsArray ;
const ArrayType & InputArrayRef = * InputArray ;
PrevArraySize = InputArrayRef . Num ( ) ;
2023-12-20 12:45:12 -05:00
PrevNoRepeatOrder = FMath : : Clamp ( * NoRepeatOrder , 0 , PrevArraySize - 1 ) ;
2023-02-22 17:54:26 -05:00
* OutValue = TDataTypeFactory < ElementType > : : CreateAny ( InParams . OperatorSettings ) ;
TriggerOnNext - > Reset ( ) ;
TriggerOnReset - > Reset ( ) ;
}
2023-02-22 18:03:42 -05:00
bool UseSharedState ( ) const
{
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
return * bEnableSharedState & & bSharedStateInitialized ;
2023-02-22 18:03:42 -05:00
}
2021-03-15 14:00:26 -04:00
void Execute ( )
{
TriggerOnNext - > AdvanceBlock ( ) ;
TriggerOnReset - > AdvanceBlock ( ) ;
2021-03-29 23:58:06 -04:00
const ArrayType & InputArrayRef = * InputArray ;
2024-02-08 19:57:31 -05:00
if ( InputArrayRef . Num ( ) = = 0 )
2021-04-07 03:05:51 -04:00
{
2023-04-17 15:20:55 -04:00
# if WITH_METASOUND_DEBUG_ENVIRONMENT
2021-04-07 03:05:51 -04:00
if ( ! bHasLoggedEmptyArrayWarning )
{
2021-08-09 15:13:40 -04:00
UE_LOG ( LogMetaSound , Verbose , TEXT ( " Array Random Get: empty array input (Graph '%s') " ) , * GraphName ) ;
2021-04-07 03:05:51 -04:00
bHasLoggedEmptyArrayWarning = true ;
}
2023-04-17 15:20:55 -04:00
# endif // WITH_METASOUND_DEBUG_ENVIRONMENT
2021-04-07 03:05:51 -04:00
return ;
}
2024-02-08 19:57:31 -05:00
2021-03-15 14:00:26 -04:00
TriggerReset - > ExecuteBlock (
[ & ] ( int32 StartFrame , int32 EndFrame )
{
} ,
[ this ] ( int32 StartFrame , int32 EndFrame )
{
2024-02-13 20:27:50 -05:00
if ( IsStateInitializationNeeded ( ) )
2024-02-08 19:57:31 -05:00
{
InitializeState ( PrevArraySize ) ;
}
2023-02-22 18:03:42 -05:00
if ( UseSharedState ( ) )
2021-03-15 14:00:26 -04:00
{
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
RGM . ResetSeed ( SharedStateUniqueId ) ;
}
else
{
check ( ArrayRandomGet . IsValid ( ) ) ;
ArrayRandomGet - > ResetSeed ( ) ;
}
TriggerOnReset - > TriggerFrame ( StartFrame ) ;
}
) ;
TriggerNext - > ExecuteBlock (
[ & ] ( int32 StartFrame , int32 EndFrame )
{
} ,
[ this ] ( int32 StartFrame , int32 EndFrame )
{
2024-02-08 19:57:31 -05:00
ExecuteTriggerNext ( StartFrame ) ;
2021-03-15 14:00:26 -04:00
}
) ;
}
private :
2024-02-08 19:57:31 -05:00
void ExecuteTriggerNext ( int32 StartFrame )
{
const ArrayType & InputArrayRef = * InputArray ;
int32 OutRandomIndex = INDEX_NONE ;
2024-02-13 20:27:50 -05:00
const bool bIsStateReinitializationNeeded = IsStateInitializationNeeded ( ) ;
const bool bIsArraySizeChanged = PrevArraySize ! = InputArrayRef . Num ( ) ;
2024-02-08 19:57:31 -05:00
const bool bSeedValueChanged = PrevSeedValue ! = * SeedValue ;
const bool bNoRepeatOrderChanged = PrevNoRepeatOrder ! = * NoRepeatOrder ;
const bool bWeightsArrayChanged = WeightsArray ! = * InputWeightsArray ;
// Update cached values if changed
if ( bIsArraySizeChanged )
{
PrevArraySize = InputArrayRef . Num ( ) ;
}
if ( bSeedValueChanged )
{
PrevSeedValue = * SeedValue ;
}
if ( bNoRepeatOrderChanged )
{
PrevNoRepeatOrder = * NoRepeatOrder ;
}
if ( bWeightsArrayChanged )
{
WeightsArray = * InputWeightsArray ;
}
// Reinitialize state (with new values) if needed
if ( bIsStateReinitializationNeeded )
{
InitializeState ( PrevArraySize ) ;
}
// Update other state (which was not necessarily changed by new state initialization)
if ( bSeedValueChanged )
{
if ( UseSharedState ( ) )
{
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
RGM . SetSeed ( SharedStateUniqueId , PrevSeedValue ) ;
}
else
{
check ( ArrayRandomGet . IsValid ( ) ) ;
ArrayRandomGet - > SetSeed ( PrevSeedValue ) ;
}
}
if ( bNoRepeatOrderChanged )
{
if ( UseSharedState ( ) )
{
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
RGM . SetNoRepeatOrder ( SharedStateUniqueId , PrevNoRepeatOrder ) ;
}
else
{
check ( ArrayRandomGet . IsValid ( ) ) ;
ArrayRandomGet - > SetNoRepeatOrder ( PrevNoRepeatOrder ) ;
}
}
if ( bWeightsArrayChanged )
{
if ( UseSharedState ( ) )
{
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
RGM . SetRandomWeights ( SharedStateUniqueId , WeightsArray ) ;
}
else
{
check ( ArrayRandomGet . IsValid ( ) ) ;
ArrayRandomGet - > SetRandomWeights ( WeightsArray ) ;
}
}
// Get next value
if ( UseSharedState ( ) )
{
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
OutRandomIndex = RGM . NextValue ( SharedStateUniqueId ) ;
}
else
{
check ( ArrayRandomGet . IsValid ( ) ) ;
OutRandomIndex = ArrayRandomGet - > NextValue ( ) ;
}
check ( OutRandomIndex ! = INDEX_NONE ) ;
# if WITH_METASOUND_DEBUG_ENVIRONMENT
UE_LOG ( LogMetaSound , Verbose , TEXT ( " Array Random Get: Index chosen: '%u' " ) , OutRandomIndex ) ;
# endif // WITH_METASOUND_DEBUG_ENVIRONMENT
// The input array size may have changed, so make sure it's wrapped into range of the input array
* OutValue = InputArrayRef [ OutRandomIndex % InputArrayRef . Num ( ) ] ;
TriggerOnNext - > TriggerFrame ( StartFrame ) ;
}
2024-02-13 20:27:50 -05:00
bool IsStateInitializationNeeded ( )
{
const ArrayType & InputArrayRef = * InputArray ;
const bool bIsArrayNonEmpty = InputArrayRef . Num ( ) ! = 0 ; // Skip reinit if the array is empty because it represents an invalid state for this node.
const bool bIsArraySizeChanged = PrevArraySize ! = InputArrayRef . Num ( ) ; // Need to reinit for array size changes.
const bool bIsSharedStateEnablementInconsistent = ( * bEnableSharedState ! = bSharedStateInitialized ) ; // Need to reinit if the shared state enablement has been updated.
const bool bIsNonSharedStateInitializationNeeded = ! * bEnableSharedState & & ! ArrayRandomGet . IsValid ( ) ; // For the first initialization of the non shared state random get (bIsSharedStateEnablementInconsistent will take care of that for shared state)
return ( bIsArrayNonEmpty & & ( bIsArraySizeChanged | | bIsSharedStateEnablementInconsistent | | bIsNonSharedStateInitializationNeeded ) ) ;
}
2023-04-17 15:20:55 -04:00
void InitializeState ( int32 InArraySize )
{
bSharedStateInitialized = false ;
if ( InArraySize > 0 )
{
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
if ( * bEnableSharedState )
2023-04-17 15:20:55 -04:00
{
// Get the environment variable for the unique ID of the sound
check ( SharedStateUniqueId . IsValid ( ) ) ;
FSharedStateRandomGetManager & RGM = FSharedStateRandomGetManager : : Get ( ) ;
InitSharedStateArgs Args ;
Args . SharedStateId = SharedStateUniqueId ;
Args . Seed = PrevSeedValue ;
Args . NumElements = PrevArraySize ;
Args . NoRepeatOrder = PrevNoRepeatOrder ;
Args . bIsPreviewSound = bIsPreviewSound ;
Args . Weights = WeightsArray ;
RGM . InitSharedState ( Args ) ;
bSharedStateInitialized = true ;
}
else
{
ArrayRandomGet = MakeUnique < FArrayRandomGet > ( PrevSeedValue , PrevArraySize , WeightsArray , PrevNoRepeatOrder ) ;
}
}
else
{
ArrayRandomGet = MakeUnique < FArrayRandomGet > ( ) ;
# if WITH_METASOUND_DEBUG_ENVIRONMENT
UE_LOG ( LogMetaSound , Verbose , TEXT ( " Array Random Get: Can't retrieve random elements from an empty array in graph '%s' " ) , * GraphName ) ;
# endif // WITH_METASOUND_DEBUG_ENVIRONMENT
}
}
2021-03-15 14:00:26 -04:00
// Inputs
FTriggerReadRef TriggerNext ;
FTriggerReadRef TriggerReset ;
FArrayDataReadReference InputArray ;
2021-04-03 18:41:39 -04:00
TDataReadReference < WeightsArrayType > InputWeightsArray ;
2021-03-15 14:00:26 -04:00
FInt32ReadRef SeedValue ;
FInt32ReadRef NoRepeatOrder ;
// Outputs
FTriggerWriteRef TriggerOnNext ;
FTriggerWriteRef TriggerOnReset ;
TDataWriteReference < ElementType > OutValue ;
2021-08-09 15:13:40 -04:00
# if WITH_METASOUND_DEBUG_ENVIRONMENT
FString GraphName ;
2023-04-17 15:20:55 -04:00
bool bHasLoggedEmptyArrayWarning = false ;
2021-08-09 15:13:40 -04:00
# endif // WITH_METASOUND_DEBUG_ENVIRONMENT
2021-03-15 14:00:26 -04:00
// Data
TUniquePtr < FArrayRandomGet > ArrayRandomGet ;
2021-04-03 18:41:39 -04:00
TArray < float > WeightsArray ;
2021-03-15 14:00:26 -04:00
int32 PrevSeedValue = INDEX_NONE ;
int32 PrevNoRepeatOrder = INDEX_NONE ;
2022-02-04 18:18:22 -05:00
FGuid SharedStateUniqueId ;
2021-04-07 03:05:51 -04:00
int32 PrevArraySize = 0 ;
2021-04-03 18:41:39 -04:00
bool bIsPreviewSound = false ;
[Metasound Bind] Fixup for bind issues caught by new automated tests.
#jira UE-187406, UE-187390, UE-187404, UE-187403, UE-187405, UE-187392, UE-187391, UE-187395, UE-187399, UE-187398, UE-187389, UE-187393, UE-187394, UE-187396, UE-187397, UE-187401
#rb phil.popp
[CL 26130674 by maxwell hayes in ue5-main branch]
2023-06-20 15:08:54 -04:00
FBoolReadRef bEnableSharedState ;
2023-02-22 18:03:42 -05:00
bool bSharedStateInitialized = false ;
2021-03-15 14:00:26 -04:00
} ;
template < typename ArrayType >
class TArrayRandomGetNode : public FNodeFacade
{
public :
TArrayRandomGetNode ( const FNodeInitData & InInitData )
: FNodeFacade ( InInitData . InstanceName , InInitData . InstanceID , TFacadeOperatorClass < TArrayRandomGetOperator < ArrayType > > ( ) )
{
}
virtual ~ TArrayRandomGetNode ( ) = default ;
} ;
}
2021-04-05 20:22:19 -04:00
# undef LOCTEXT_NAMESPACE