Lovense Integration: LovenseIntegration/Source/LovenseIntegration/Public/Components/LovenseToyAnimationControlComponent.h Source File

Lovense Integration

LovenseToyAnimationControlComponent.h
1 // (CVN) - Candy Valley Network GmbH
2
3 #pragma once
4
5 #include <CoreMinimal.h>
6
7 // EXTERNAL INCLUDES
8 #include <Components/ActorComponent.h>
9
10 // INTERNAL INCLUDES
11 #include "LovenseTypes.h"
12
13 #include "LovenseToyAnimationControlComponent.generated.h"
14
15
16 // Example of how a FLovenseGetAnimationData event function could be implemented. This is dummy code to get the general idea across.
17 #if false
18 class Class {
19 void LovenseGetAnimationData(TArray<class UAnimSequence*>& outAnimations, TArray<float>& outTimes);
20 void CalculatePlayRate(float deltaTime, FRandomStream& random, float& playRate);
21 void Tick(float deltaTime);
22
23 TArray<class USkeletalMeshComponent> skeletalMeshComponents;
24 TArray<class UAnimSequence*> animations;
25 float currentAnimationTime;
26 // It's important to use FRandomStream instead of the FMath functions as it is deterministic, allowing us to "look into the future".
27 FRandomStream randomStream;
28 float currentPlayRate;
29 float currentTime;
30 float currentPlayRateTarget;
31 };
32
33 void Class::LovenseGetAnimationData(TArray<class UAnimSequence*>& outAnimations, TArray<float>& outTimes) {
34 outAnimations.Empty(this->skeletalMeshComponents.Num());
35 outTimes.Empty(50);
36
37 for (int32 i = 0; i < this->skeletalMeshComponents.Num(); ++i) {
38 // Need one animation for every skeletal mesh component.
39 outAnimations.Add(this->animations[i]);
40 }
41
42 // Filling outTimes is optional. If it's empty, the component will use a fixed time step of 0.1 seconds.
43
44 // Cache any play rate values as we want to "look into the future" and not affect the current play rate.
45 FRandomStream random = this->randomStream;
46 float playRate = this->currentPlayRate;
47
48 int32 toyDelay = FLovenseManager::Get()->GetToyDelay();
49 float toyDelaySeconds = static_cast<float>(toyDelay) / 1000.0f;
50 // Start at the current animation time + the toy delay to account for the communication delay.
51 float animationTime = this->currentAnimationTime + toyDelaySeconds;
52 float time = this->currentTime;
53 float playRateTarget = this->currentPlayRateTarget;
54
55 // Iterate animationTime until we have 51 time values as we can only have 50 pattern values and the first time value will be swallowed.
56 while (outTimes.Num() < 51) {
57 // Add current animation time to times array.
58 outTimes.Add(animationTime);
59 // Step the animation time forwards with the cached play rate.
60 animationTime += 0.1f * playRate;
61 // Tick the cached play rate with the cached random stream.
62 this->CalculatePlayRate(0.1f, random, time, playRateTarget, playRate);
63 }
64 }
65
66 void Class::CalculatePlayRate(float deltaTime, FRandomStream& random, float& time, float& playRateTarget, float& playRate) {
67 // This part is important; we need to make sure to not get a value from the random stream faster than the pattern interval.
68 // Otherwise we would get a different result as we'd get fewer values from the random stream when looking into the future
69 // compared to the actual play rate update, which runs every tick.
70 // Alternatively, you could update the actual play rate every >0.1 seconds instead of every tick.
71 time += deltaTime;
72 if (time > 0.1f) {
73 // This can be as simple or as complex as you want.
74 playRateTarget = random.FRand();
75 }
76
77 playRate = FMath::FInterpTo(playRate, playRateTarget, deltaTime, 1.0f);
78 }
79
80 void Class::Tick(float deltaTime) {
81 // Actually update the play rate.
82 this->CalculatePlayRate(deltaTime, this->randomStream, this->currentTime, this->currentPlayRateTarget, this->currentPlayRate);
83 }
84 #endif
85
97 DECLARE_DYNAMIC_DELEGATE_TwoParams(FLovenseGetAnimationData, TArray<class UAnimSequence*>&, outAnimations, TArray<float>&, outTimes);
98
99
161 UCLASS(ClassGroup = "Lovense", Meta = (BlueprintSpawnableComponent))
162 class LOVENSEINTEGRATION_API ULovenseToyAnimationControlComponent : public UActorComponent {
163 GENERATED_BODY()
164
165 public:
174 UFUNCTION(BlueprintCallable, Category = "Lovense")
175 virtual void Initialize(
176 const TArray<USkeletalMeshComponent*>& inSkeletalMeshComponents,
177 const TArray<FName>& inBoneNames,
178 const FLovenseGetAnimationData& inGetAnimationDataDelegate
179 );
180
185 UFUNCTION(BlueprintCallable, Category = "Lovense")
186 virtual void StartBehaviour();
187
195 UFUNCTION(BlueprintCallable, Category = "Lovense")
196 virtual void StartTransition();
197
203 UFUNCTION(BlueprintCallable, Category = "Lovense")
204 virtual void SetEnabled(bool value);
205
207 UFUNCTION(BlueprintPure, Category = "Lovense")
208 FORCEINLINE bool IsEnabled() { return this->bIsEnabled; }
209
214 UFUNCTION(BlueprintCallable, Category = "Lovense")
215 virtual void OnGamePaused();
216
221 UFUNCTION(BlueprintCallable, Category = "Lovense")
222 virtual void OnGameUnpaused();
223
224 public:
225 ULovenseToyAnimationControlComponent();
226
227 // UActorComponent Interface
228 virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
229 virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
230 // End UActorComponent Interface
231
236 FORCEINLINE float GetMaxRecordedVelocityDecaySpeed() { return this->maxRecordedVelocityDecaySpeed; }
241 FORCEINLINE void SetMaxRecordedVelocityDecaySpeed(float newDecaySpeed) { this->maxRecordedVelocityDecaySpeed = newDecaySpeed; }
246 FORCEINLINE float GetMaxRecordedVelocityDecayMinimum() { return this->maxRecordedVelocityDecayMinimum; }
251 FORCEINLINE void SetMaxRecordedVelocityDecayMinimum(float newDecayMinimum) { this->maxRecordedVelocityDecayMinimum = newDecayMinimum; }
256 FORCEINLINE float GetMaxToySpeedInterpolationSpeed() { return this->maxToySpeedInterpolationSpeed; }
261 FORCEINLINE void SetMaxToySpeedInterpolationSpeed(float newInterpolationSpeed) { this->maxToySpeedInterpolationSpeed = newInterpolationSpeed; }
267 FORCEINLINE float GetMaxToySpeedTargetDuringTransition() { return this->maxToySpeedTargetDuringTransition; }
273 FORCEINLINE void SetMaxToySpeedTargetDuringTransition(float newSpeedTargetDuringTransition) { this->maxToySpeedTargetDuringTransition = newSpeedTargetDuringTransition; }
280 FORCEINLINE FVector2D GetPatternToySpeedInputRange() { return this->patternToySpeedInputRange; }
287 FORCEINLINE void SetPatternToySpeedInputRange(FVector2D newInputRange) { this->patternToySpeedInputRange = newInputRange; }
292 FORCEINLINE const TArray<USkeletalMeshComponent*>& GetSkeletalMeshComponents() { return this->skeletalMeshComponents; }
298 FORCEINLINE const TArray<FName>& GetBoneNames() { return this->boneNames; }
304 FORCEINLINE float GeMaxRecordedVelocity() { return this->maxRecordedVelocity; }
310 FORCEINLINE float GeCurrentMaxToySpeed() { return this->currentMaxToySpeed; }
316 FORCEINLINE float GeMaxToySpeedTarget() { return this->maxToySpeedTarget; }
322 FORCEINLINE bool GeRotateClockwise() { return this->bRotateClockwise; }
323
324 protected:
329 UFUNCTION()
330 virtual void OnPatternGenerationTimerFinished();
331
332 protected:
337 virtual void RealtimeEvaluationUpdate(float deltaTime);
343 virtual bool GeneratePattern(const TArray<class UAnimSequence*>& animations, const TArray<float>& times, FLovensePattern& outPattern);
344
345 protected:
351 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Realtime Evaluation")
352 double maxAverageVelocity;
353
358 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Realtime Evaluation")
359 float maxRecordedVelocityDecaySpeed;
360
365 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Realtime Evaluation")
366 float maxRecordedVelocityDecayMinimum;
367
372 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Realtime Evaluation")
373 float maxToySpeedInterpolationSpeed;
374
380 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Realtime Evaluation", Meta = (ClampMin = "1", ClampMax = "20", UIMin = "1", UIMax = "20"))
381 float maxToySpeedTargetDuringTransition;
382
389 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Lovense|Pattern Generation")
390 FVector2D patternToySpeedInputRange;
391
396 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense")
397 TArray<TObjectPtr<USkeletalMeshComponent>> skeletalMeshComponents;
398
404 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense")
405 TArray<FName> boneNames;
406
412 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense|Realtime Evaluation")
413 double maxRecordedVelocity;
414
420 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense|Realtime Evaluation")
421 float currentMaxToySpeed;
422
428 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense|Realtime Evaluation")
429 float maxToySpeedTarget;
430
436 UPROPERTY(Transient, VisibleAnywhere, BlueprintReadOnly, Category = "Lovense|Realtime Evaluation")
437 bool bRotateClockwise;
438
439 protected:
441 bool bIsEnabled;
448 FTimerHandle patternGenerationTimerHandle;
455 FLovenseGetAnimationData getAnimationDataDelegate;
456 };
ULovenseToyAnimationControlComponent
This component calculates Lovense command speeds based on the average bone movement of N bones on N s...
Definition: LovenseToyAnimationControlComponent.h:162
ULovenseToyAnimationControlComponent::GetMaxToySpeedTargetDuringTransition
FORCEINLINE float GetMaxToySpeedTargetDuringTransition()
Get maximum toy command speed that maxToySpeedTarget will be set to during transitions (See StartTran...
Definition: LovenseToyAnimationControlComponent.h:267
ULovenseToyAnimationControlComponent::SetMaxRecordedVelocityDecayMinimum
FORCEINLINE void SetMaxRecordedVelocityDecayMinimum(float newDecayMinimum)
Naming is a bit confusing, this is the minimum value that maxRecordedVelocity can decay to....
Definition: LovenseToyAnimationControlComponent.h:251
FLovenseManager::GetToyDelay
FORCEINLINE int32 GetToyDelay()
Get the cached "ToyDelay" config value. Toy delay is in milliseconds. Value range is 0-2000ms and d...
Definition: LovenseManager.h:671
ULovenseToyAnimationControlComponent::GetSkeletalMeshComponents
const FORCEINLINE TArray< USkeletalMeshComponent * > & GetSkeletalMeshComponents()
Get the skeletal meshes that will be evaluated. All of these components have to use the same skeleton...
Definition: LovenseToyAnimationControlComponent.h:292
ULovenseToyAnimationControlComponent::SetPatternToySpeedInputRange
FORCEINLINE void SetPatternToySpeedInputRange(FVector2D newInputRange)
Set input value range for the average velocity to toy command speed conversion. E....
Definition: LovenseToyAnimationControlComponent.h:287
ULovenseToyAnimationControlComponent::GeMaxToySpeedTarget
FORCEINLINE float GeMaxToySpeedTarget()
Get the target value that currentMaxToySpeed gets interpolated to. Is usually 20,...
Definition: LovenseToyAnimationControlComponent.h:316
FLovenseManager::Get
static FLovenseManager * Get()
Get the instance of the lovense manager. Always valid.
Definition: LovenseManager.cpp:49
ULovenseToyAnimationControlComponent::GeMaxRecordedVelocity
FORCEINLINE float GeMaxRecordedVelocity()
Get the current maximum velocity that has been calculated. Used to remap the current velocity to a to...
Definition: LovenseToyAnimationControlComponent.h:304
ULovenseToyAnimationControlComponent::GeCurrentMaxToySpeed
FORCEINLINE float GeCurrentMaxToySpeed()
Get the current maximum toy command speed. Is interpolated towards maxToySpeedTarget with maxToySpe...
Definition: LovenseToyAnimationControlComponent.h:310
ULovenseToyAnimationControlComponent::GetMaxRecordedVelocityDecayMinimum
FORCEINLINE float GetMaxRecordedVelocityDecayMinimum()
Naming is a bit confusing, this is the minimum value that maxRecordedVelocity can decay to....
Definition: LovenseToyAnimationControlComponent.h:246
ULovenseToyAnimationControlComponent::SetMaxToySpeedInterpolationSpeed
FORCEINLINE void SetMaxToySpeedInterpolationSpeed(float newInterpolationSpeed)
Set interpolation speed at which currentMaxToySpeed will be interpolated towards maxToySpeedTarget....
Definition: LovenseToyAnimationControlComponent.h:261
ULovenseToyAnimationControlComponent::GetMaxToySpeedInterpolationSpeed
FORCEINLINE float GetMaxToySpeedInterpolationSpeed()
Get interpolation speed at which currentMaxToySpeed will be interpolated towards maxToySpeedTarget....
Definition: LovenseToyAnimationControlComponent.h:256
FLovensePattern
Structure holding all necessary information for a pattern command.
Definition: LovenseTypes.h:403
ULovenseToyAnimationControlComponent::GeRotateClockwise
FORCEINLINE bool GeRotateClockwise()
Whether the toys should rotate clockwise or anticlockwise. Gets toggled in StartTransition()....
Definition: LovenseToyAnimationControlComponent.h:322
ULovenseToyAnimationControlComponent::SetMaxToySpeedTargetDuringTransition
FORCEINLINE void SetMaxToySpeedTargetDuringTransition(float newSpeedTargetDuringTransition)
Set maximum toy command speed that maxToySpeedTarget will be set to during transitions (See StartTran...
Definition: LovenseToyAnimationControlComponent.h:273
ULovenseToyAnimationControlComponent::GetBoneNames
const FORCEINLINE TArray< FName > & GetBoneNames()
Get the names of the bones of the skeletal meshes that will be evaluated. This component calculates...
Definition: LovenseToyAnimationControlComponent.h:298
ULovenseToyAnimationControlComponent::GetPatternToySpeedInputRange
FORCEINLINE FVector2D GetPatternToySpeedInputRange()
Get input value range for the average velocity to toy command speed conversion. E....
Definition: LovenseToyAnimationControlComponent.h:280
ULovenseToyAnimationControlComponent::SetMaxRecordedVelocityDecaySpeed
FORCEINLINE void SetMaxRecordedVelocityDecaySpeed(float newDecaySpeed)
Set the speed (per second) at which maxRecordedVelocity will decay at. Only relevant for realtime e...
Definition: LovenseToyAnimationControlComponent.h:241