A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
VRSliderComponent.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
5#include "Net/UnrealNetwork.h"
6
7 //=============================================================================
8UVRSliderComponent::UVRSliderComponent(const FObjectInitializer& ObjectInitializer)
9 : Super(ObjectInitializer)
10{
11 this->SetGenerateOverlapEvents(true);
12 this->PrimaryComponentTick.bStartWithTickEnabled = false;
13 PrimaryComponentTick.bCanEverTick = true;
14
15 bRepGameplayTags = false;
16
17 // Defaulting these true so that they work by default in networked environments
18 bReplicateMovement = true;
19
21 BreakDistance = 100.0f;
22
23 InitialRelativeTransform = FTransform::Identity;
24 bDenyGripping = false;
25
26 bUpdateInTick = false;
27 bPassThrough = false;
28
29 MinSlideDistance = FVector::ZeroVector;
30 MaxSlideDistance = FVector(10.0f, 0.f, 0.f);
31 SliderRestitution = 0.0f;
33 LastSliderProgress = FVector::ZeroVector;//0.0f;
35
36 MomentumAtDrop = FVector::ZeroVector;// 0.0f;
39 MaxSliderMomentum = 1.0f;
41
42 InitialInteractorLocation = FVector::ZeroVector;
43 InitialGripLoc = FVector::ZeroVector;
44
46 bUseLegacyLogic = false;
47 bIsLocked = false;
49
51
54 SplineLerpValue = 8.f;
55
56 PrimarySlotRange = 100.f;
57 SecondarySlotRange = 100.f;
58 GripPriority = 1;
60 LastInputKey = 0.0f;
61
63 SnapIncrement = 0.1f;
64 SnapThreshold = 0.1f;
67 bHitEventThreshold = false;
68
69 // Set to only overlap with things so that its not ruined by touching over actors
70 this->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Overlap);
71}
72
73//=============================================================================
77
78
79void UVRSliderComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
80{
81 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
82
85 //DOREPLIFETIME_CONDITION(UVRSliderComponent, bIsLerping, COND_InitialOnly);
86
89 DOREPLIFETIME_CONDITION(UVRSliderComponent, GameplayTags, COND_Custom);
90}
91
92void UVRSliderComponent::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
93{
94 Super::PreReplication(ChangedPropertyTracker);
95
96 // Replicate the levers initial transform if we are replicating movement
97 //DOREPLIFETIME_ACTIVE_OVERRIDE(UVRSliderComponent, InitialRelativeTransform, bReplicateMovement);
98 //DOREPLIFETIME_ACTIVE_OVERRIDE(UVRSliderComponent, SplineComponentToFollow, bReplicateMovement);
99
100 // Don't replicate if set to not do it
101 DOREPLIFETIME_ACTIVE_OVERRIDE(UVRSliderComponent, GameplayTags, bRepGameplayTags);
102
103 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeLocation, bReplicateMovement);
104 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeRotation, bReplicateMovement);
105 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeScale3D, bReplicateMovement);
106}
107
109{
110 Super::OnRegister();
111
112 // Init the slider settings
113 if (USplineComponent * ParentSpline = Cast<USplineComponent>(GetAttachParent()))
114 {
115 SetSplineComponentToFollow(ParentSpline);
116 }
117 else
118 {
120 }
121}
122
124{
125 // Call the base class
126 Super::BeginPlay();
127
129
131}
132
133void UVRSliderComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
134{
135 // Call supers tick (though I don't think any of the base classes to this actually implement it)
136 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
137
139 {
141 EBPVRResultSwitch Result;
143
144 if (Result == EBPVRResultSwitch::OnSucceeded)
145 {
146 bPassThrough = true;
148 bPassThrough = false;
149 }
150 return;
151 }
152
153 // If we are locked then end the lerp, no point
154 if (bIsLocked)
155 {
156 // Notify the end user
159
160 this->SetComponentTickEnabled(false);
162
163 return;
164 }
165
166 if (bIsLerping)
167 {
168 if ((SplineComponentToFollow && FMath::IsNearlyZero((SplineMomentumAtDrop * DeltaTime), 0.00001f)) || (!SplineComponentToFollow && (MomentumAtDrop * DeltaTime).IsNearlyZero(0.00001f)))
169 {
170 bIsLerping = false;
171 }
172 else
173 {
174 if (this->SplineComponentToFollow)
175 {
176 SplineMomentumAtDrop = FMath::FInterpTo(SplineMomentumAtDrop, 0.0f, DeltaTime, SliderMomentumFriction);
177 float newProgress = CurrentSliderProgress + (SplineMomentumAtDrop * DeltaTime);
178
179 if (newProgress < 0.0f || FMath::IsNearlyEqual(newProgress, 0.0f, 0.00001f))
180 {
181 if (SliderRestitution > 0.0f)
182 {
183 // Reverse the momentum
185 this->SetSliderProgress(0.0f);
186 }
187 else
188 {
189 bIsLerping = false;
190 this->SetSliderProgress(0.0f);
191 }
192 }
193 else if (newProgress > 1.0f || FMath::IsNearlyEqual(newProgress, 1.0f, 0.00001f))
194 {
195 if (SliderRestitution > 0.0f)
196 {
197 // Reverse the momentum
199 this->SetSliderProgress(1.0f);
200 }
201 else
202 {
203 bIsLerping = false;
204 this->SetSliderProgress(1.0f);
205 }
206 }
207 else
208 {
209 this->SetSliderProgress(newProgress);
210 }
211 }
212 else
213 {
214 MomentumAtDrop = FMath::VInterpTo(MomentumAtDrop, FVector::ZeroVector, DeltaTime, SliderMomentumFriction);
215
216 FVector ClampedLocation = ClampSlideVector(InitialRelativeTransform.InverseTransformPosition(this->GetRelativeLocation()) + (MomentumAtDrop * DeltaTime));
217 this->SetRelativeLocation(InitialRelativeTransform.TransformPosition(ClampedLocation));
219 float newProgress = CurrentSliderProgress;
220 if (SliderRestitution > 0.0f)
221 {
222 // Implement bounce
223 FVector CurLoc = ClampedLocation;
224
225 if (
226 (FMath::Abs(MinSlideDistance.X) > 0.0f && CurLoc.X <= -FMath::Abs(this->MinSlideDistance.X)) ||
227 (FMath::Abs(MinSlideDistance.Y) > 0.0f && CurLoc.Y <= -FMath::Abs(this->MinSlideDistance.Y)) ||
228 (FMath::Abs(MinSlideDistance.Z) > 0.0f && CurLoc.Z <= -FMath::Abs(this->MinSlideDistance.Z)) ||
229 (FMath::Abs(MaxSlideDistance.X) > 0.0f && CurLoc.X >= FMath::Abs(this->MaxSlideDistance.X)) ||
230 (FMath::Abs(MaxSlideDistance.Y) > 0.0f && CurLoc.Y >= FMath::Abs(this->MaxSlideDistance.Y)) ||
231 (FMath::Abs(MaxSlideDistance.Z) > 0.0f && CurLoc.Z >= FMath::Abs(this->MaxSlideDistance.Z))
232 )
233 {
235 }
236 }
237 else
238 {
239 if (newProgress < 0.0f || FMath::IsNearlyEqual(newProgress, 0.0f, 0.00001f))
240 {
241 bIsLerping = false;
242 this->SetSliderProgress(0.0f);
243 }
244 else if (newProgress > 1.0f || FMath::IsNearlyEqual(newProgress, 1.0f, 0.00001f))
245 {
246 bIsLerping = false;
247 this->SetSliderProgress(1.0f);
248 }
249 }
250 }
251 }
252
253 if (!bIsLerping)
254 {
255 // Notify the end user
258
259 this->SetComponentTickEnabled(false);
261 }
262
263 // Check for the hit point always
265 }
266}
267
268void UVRSliderComponent::TickGrip_Implementation(UGripMotionControllerComponent * GrippingController, const FBPActorGripInformation & GripInformation, float DeltaTime)
269{
270
271 // Skip this tick if its not triggered from the pass through
273 return;
274
275 // If the sliders progress is locked then just exit early
276 if (bIsLocked)
277 {
279 {
280 // Check if we should auto drop
281 CheckAutoDrop(GrippingController, GripInformation);
282 }
283
284 return;
285 }
286
287 // Handle manual tracking here
289 FTransform CurrentRelativeTransform = InitialRelativeTransform * ParentTransform;
290 FVector CurInteractorLocation = CurrentRelativeTransform.InverseTransformPosition(GrippingController->GetPivotLocation());
291
292 FVector CalculatedLocation = InitialGripLoc + (CurInteractorLocation - InitialInteractorLocation);
293
294 float SplineProgress = CurrentSliderProgress;
295 if (SplineComponentToFollow != nullptr)
296 {
297 FVector WorldCalculatedLocation = CurrentRelativeTransform.TransformPosition(CalculatedLocation);
298 float ClosestKey = SplineComponentToFollow->FindInputKeyClosestToWorldLocation(WorldCalculatedLocation);
299
301 {
302 float SplineLength = SplineComponentToFollow->GetSplineLength();
303 SplineProgress = GetCurrentSliderProgress(WorldCalculatedLocation, true, ClosestKey);
304
306
307 const int32 NumPoints = SplineComponentToFollow->SplineCurves.Position.Points.Num();
308
309 if (SplineComponentToFollow->SplineCurves.Position.Points.Num() > 1)
310 {
311 ClosestKey = SplineComponentToFollow->SplineCurves.ReparamTable.Eval(SplineProgress * SplineLength, 0.0f);
312 }
313
314 WorldCalculatedLocation = SplineComponentToFollow->GetLocationAtSplineInputKey(ClosestKey, ESplineCoordinateSpace::World);
315 }
316
317 bool bLerpToNewKey = true;
318 bool bChangedLocation = false;
319
320 if (bEnforceSplineLinearity && LastInputKey >= 0.0f &&
321 FMath::Abs((FMath::TruncToFloat(ClosestKey) - FMath::TruncToFloat(LastInputKey))) > 1.0f &&
323 )
324 {
325 bLerpToNewKey = false;
326 }
327 else
328 {
329 LerpedKey = ClosestKey;
330 }
331
333 {
334 FTransform trans;
336 {
337 GetLerpedKey(LerpedKey, DeltaTime);
338 trans = SplineComponentToFollow->GetTransformAtSplineInputKey(LerpedKey, ESplineCoordinateSpace::World, true);
339 bChangedLocation = true;
340 }
341 else if (bLerpToNewKey)
342 {
343 trans = SplineComponentToFollow->FindTransformClosestToWorldLocation(WorldCalculatedLocation, ESplineCoordinateSpace::World, true);
344 bChangedLocation = true;
345 }
346
347 if (bChangedLocation)
348 {
349 trans.MultiplyScale3D(InitialRelativeTransform.GetScale3D());
350 trans = trans * ParentTransform.Inverse();
351 this->SetRelativeTransform(trans);
352 }
353 }
354 else
355 {
356 FVector WorldLocation;
358 {
359 GetLerpedKey(LerpedKey, DeltaTime);
360 WorldLocation = SplineComponentToFollow->GetLocationAtSplineInputKey(LerpedKey, ESplineCoordinateSpace::World);
361 bChangedLocation = true;
362 }
363 else if (bLerpToNewKey)
364 {
365 WorldLocation = SplineComponentToFollow->FindLocationClosestToWorldLocation(WorldCalculatedLocation, ESplineCoordinateSpace::World);
366 bChangedLocation = true;
367 }
368
369 if (bChangedLocation)
370 this->SetRelativeLocation(ParentTransform.InverseTransformPosition(WorldLocation));
371 }
372
373 CurrentSliderProgress = GetCurrentSliderProgress(WorldCalculatedLocation, true, bLerpToNewKey ? LerpedKey : ClosestKey);
374 if (bLerpToNewKey)
375 {
377 }
378 }
379 else
380 {
381 FVector ClampedLocation = ClampSlideVector(CalculatedLocation);
382 this->SetRelativeLocation(InitialRelativeTransform.TransformPosition(ClampedLocation));
384 }
385
387 {
389 {
390 // Rolling average across num samples
393
394 float momentumSign = FMath::Sign(SplineMomentumAtDrop);
395 SplineMomentumAtDrop = momentumSign * FMath::Min(MaxSliderMomentum, FMath::Abs(SplineMomentumAtDrop));
396
398 }
399 else
400 {
401 // Rolling average across num samples
403 FVector CurProgress = InitialRelativeTransform.InverseTransformPosition(this->GetRelativeLocation());
405 CurProgress *= FVector(1.0f) / InitialRelativeTransform.GetScale3D();
406
407 MomentumAtDrop += ((/*CurrentSliderProgress*/CurProgress - LastSliderProgress) / DeltaTime) / FramesToAverage;
408
409 //MomentumAtDrop = FMath::Min(MaxSliderMomentum, MomentumAtDrop);
410
411 LastSliderProgress = CurProgress;//CurrentSliderProgress;
412 }
413 }
414
416
417 // Check if we should auto drop
418 CheckAutoDrop(GrippingController, GripInformation);
419}
420
422{
423 // Converted to a relative value now so it should be correct
424 if (BreakDistance > 0.f && GrippingController->HasGripAuthority(GripInformation) && FVector::DistSquared(InitialDropLocation, this->GetComponentTransform().InverseTransformPosition(GrippingController->GetPivotLocation())) >= FMath::Square(BreakDistance))
425 {
426 if (GrippingController->OnGripOutOfRange.IsBound())
427 {
428 uint8 GripID = GripInformation.GripID;
429 GrippingController->OnGripOutOfRange.Broadcast(GripInformation, GripInformation.GripDistance);
430 }
431 else
432 {
433 GrippingController->DropObjectByInterface(this, HoldingGrip.GripID);
434 }
435 return true;
436 }
437
438 return false;
439}
440
442{
443 // Skip first check, this will skip an event throw on rounded
444 if (LastSliderProgressState < 0.0f)
445 {
446 // Skip first tick, this is our resting position
448 LastSliderProgressState = FMath::RoundToFloat(CurrentSliderProgress); // Ensure it is rounded to 0 or 1
449 else
451 }
453 {
455 (bSliderUsesSnapPoints && SnapIncrement > 0.f && FMath::IsNearlyEqual(FMath::Fmod(CurrentSliderProgress, SnapIncrement), 0.0f, 0.001f))
456 )
457 {
458 // I am working with exacts here because of the clamping, it should actually work with no precision issues
459 // I wanted to ABS(Last-Cur) == 1.0 but it would cause an initial miss on whatever one last was inited to.
460
462 LastSliderProgressState = FMath::RoundToFloat(CurrentSliderProgress); // Ensure it is rounded to 0 or 1
463 else
465
468 bHitEventThreshold = false;
469 }
470 }
471
473 {
474 bHitEventThreshold = true;
475 }
476}
477
479{
481
482 // This lets me use the correct original location over the network without changes
483 FTransform ReversedRelativeTransform = FTransform(GripInformation.RelativeTransform.ToInverseMatrixWithScale());
484 FTransform RelativeToGripTransform = ReversedRelativeTransform * this->GetComponentTransform();
485
486 InitialInteractorLocation = CurrentRelativeTransform.InverseTransformPosition(RelativeToGripTransform.GetTranslation());
487 InitialGripLoc = InitialRelativeTransform.InverseTransformPosition(this->GetRelativeLocation());
488 InitialDropLocation = ReversedRelativeTransform.GetTranslation();
489 LastInputKey = -1.0f;
490 LerpedKey = 0.0f;
491 bHitEventThreshold = false;
492 //LastSliderProgressState = -1.0f;
493 LastSliderProgress = InitialGripLoc;//CurrentSliderProgress;
495
496 bIsLerping = false;
497 MomentumAtDrop = FVector::ZeroVector;//0.0f;
499
501 {
502 bReplicateMovement = false;
503 }
504
505 if (bUpdateInTick)
506 SetComponentTickEnabled(true);
507
508 //OnGripped.Broadcast(GrippingController, GripInformation);
509
510}
511
512void UVRSliderComponent::OnGripRelease_Implementation(UGripMotionControllerComponent * ReleasingController, const FBPActorGripInformation & GripInformation, bool bWasSocketed)
513{
514 //this->SetComponentTickEnabled(false);
515 // #TODO: Handle letting go and how lerping works, specifically with the snap points it may be an issue
517 {
518 bIsLerping = true;
519 this->SetComponentTickEnabled(true);
520
521 FVector Len = (MinSlideDistance.GetAbs() + MaxSlideDistance.GetAbs());
523 Len *= (FVector(1.0f) / InitialRelativeTransform.GetScale3D());
524
525 float TotalDistance = Len.Size();
526
528 {
529 if (MaxSliderMomentum * TotalDistance < MomentumAtDrop.Size())
530 {
531 MomentumAtDrop = MomentumAtDrop.GetSafeNormal() * (TotalDistance * MaxSliderMomentum);
532 }
533 }
534
536 bReplicateMovement = false;
537 }
538 else
539 {
540 this->SetComponentTickEnabled(false);
542 }
543
544 //OnDropped.Broadcast(ReleasingController, GripInformation, bWasSocketed);
545}
546
547void UVRSliderComponent::SetIsLocked(bool bNewLockedState)
548{
549 bIsLocked = bNewLockedState;
550}
551
552void UVRSliderComponent::SetGripPriority(int NewGripPriority)
553{
554 GripPriority = NewGripPriority;
555}
556
558void UVRSliderComponent::OnChildGripRelease_Implementation(UGripMotionControllerComponent * ReleasingController, const FBPActorGripInformation & GripInformation, bool bWasSocketed) {}
559void UVRSliderComponent::OnSecondaryGrip_Implementation(UGripMotionControllerComponent * GripOwningController, USceneComponent * SecondaryGripComponent, const FBPActorGripInformation & GripInformation) {}
560void UVRSliderComponent::OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent * GripOwningController, USceneComponent * ReleasingSecondaryGripComponent, const FBPActorGripInformation & GripInformation) {}
565void UVRSliderComponent::OnInput_Implementation(FKey Key, EInputEvent KeyEvent) {}
566bool UVRSliderComponent::RequestsSocketing_Implementation(USceneComponent *& ParentToSocketTo, FName & OptionalSocketName, FTransform_NetQuantize & RelativeTransform) { return false; }
567
572
577
579{
580 return false;
581}
582
583/*EGripCollisionType UVRSliderComponent::SlotGripType_Implementation()
584{
585 return EGripCollisionType::CustomGrip;
586}
587
588EGripCollisionType UVRSliderComponent::FreeGripType_Implementation()
589{
590 return EGripCollisionType::CustomGrip;
591}*/
592
597
602
603
608
613
614/*float UVRSliderComponent::GripStiffness_Implementation()
615{
616 return 0.0f;
617}
618
619float UVRSliderComponent::GripDamping_Implementation()
620{
621 return 0.0f;
622}*/
623void UVRSliderComponent::GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut)
624{
625 GripStiffnessOut = 0.0f;
626 GripDampingOut = 0.0f;
627}
628
633
638
639/*void UVRSliderComponent::ClosestSecondarySlotInRange_Implementation(FVector WorldLocation, bool & bHadSlotInRange, FTransform & SlotWorldTransform, UGripMotionControllerComponent * CallingController, FName OverridePrefix)
640{
641 bHadSlotInRange = false;
642}
643
644void UVRSliderComponent::ClosestPrimarySlotInRange_Implementation(FVector WorldLocation, bool & bHadSlotInRange, FTransform & SlotWorldTransform, UGripMotionControllerComponent * CallingController, FName OverridePrefix)
645{
646 bHadSlotInRange = false;
647}*/
648
649void UVRSliderComponent::ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool & bHadSlotInRange, FTransform & SlotWorldTransform, FName & SlotName, UGripMotionControllerComponent * CallingController, FName OverridePrefix)
650{
651 if (OverridePrefix.IsNone())
652 bSecondarySlot ? OverridePrefix = "VRGripS" : OverridePrefix = "VRGripP";
653
654 UVRExpansionFunctionLibrary::GetGripSlotInRangeByTypeName_Component(OverridePrefix, this, WorldLocation, bSecondarySlot ? SecondarySlotRange : PrimarySlotRange, bHadSlotInRange, SlotWorldTransform, SlotName, CallingController);
655}
656
661
662void UVRSliderComponent::IsHeld_Implementation(TArray<FBPGripPair> & CurHoldingControllers, bool & bCurIsHeld)
663{
664 CurHoldingControllers.Empty();
665 if (HoldingGrip.IsValid())
666 {
667 CurHoldingControllers.Add(HoldingGrip);
668 bCurIsHeld = bIsHeld;
669 }
670 else
671 {
672 bCurIsHeld = false;
673 }
674}
675
677{
678 if (bGripped)
679 {
680 OnGripped.Broadcast(Controller, GripInformation);
681 }
682 else
683 {
684 OnDropped.Broadcast(Controller, GripInformation, bWasSocketed);
685 }
686}
687
688void UVRSliderComponent::SetHeld_Implementation(UGripMotionControllerComponent * NewHoldingController, uint8 GripID, bool bNewIsHeld)
689{
690 if (bNewIsHeld)
691 {
692 HoldingGrip = FBPGripPair(NewHoldingController, GripID);
694 {
695 if (!bIsHeld && !bIsLerping)
697 bReplicateMovement = false;
698 }
699 }
700 else
701 {
704 {
706 }
707 }
708
709 bIsHeld = bNewIsHeld;
710}
711
712/*FBPInteractionSettings UVRSliderComponent::GetInteractionSettings_Implementation()
713{
714 return FBPInteractionSettings();
715}*/
716
717bool UVRSliderComponent::GetGripScripts_Implementation(TArray<UVRGripScriptBase*> & ArrayReference)
718{
719 return false;
720}
721
722FVector UVRSliderComponent::ClampSlideVector(FVector ValueToClamp)
723{
724 FVector fScaleFactor = FVector(1.0f);
725
727 fScaleFactor = fScaleFactor / InitialRelativeTransform.GetScale3D();
728
729 FVector MinScale = (bUseLegacyLogic ? MinSlideDistance : MinSlideDistance.GetAbs()) * fScaleFactor;
730
731 FVector Dist = (bUseLegacyLogic ? (MinSlideDistance + MaxSlideDistance) : (MinSlideDistance.GetAbs() + MaxSlideDistance.GetAbs())) * fScaleFactor;
732 FVector Progress = (ValueToClamp - (-MinScale)) / Dist;
733
735 {
739 }
740 else
741 {
742 Progress.X = FMath::Clamp(Progress.X, 0.f, 1.f);
743 Progress.Y = FMath::Clamp(Progress.Y, 0.f, 1.f);
744 Progress.Z = FMath::Clamp(Progress.Z, 0.f, 1.f);
745 }
746
747 return (Progress * Dist) - (MinScale);
748}
749
751{
752
753 const int32 NumPoints = SplineComponentToFollow->SplineCurves.Position.Points.Num();
754 const int32 NumSegments = SplineComponentToFollow->IsClosedLoop() ? NumPoints : NumPoints - 1;
755
756 if ((InKey >= 0) && (InKey < NumSegments))
757 {
758 const int32 ReparamPrevIndex = static_cast<int32>(InKey * SplineComponentToFollow->ReparamStepsPerSegment);
759 const int32 ReparamNextIndex = ReparamPrevIndex + 1;
760
761 const float Alpha = (InKey * SplineComponentToFollow->ReparamStepsPerSegment) - static_cast<float>(ReparamPrevIndex);
762
763 const float PrevDistance = SplineComponentToFollow->SplineCurves.ReparamTable.Points[ReparamPrevIndex].InVal;
764 const float NextDistance = SplineComponentToFollow->SplineCurves.ReparamTable.Points[ReparamNextIndex].InVal;
765
766 // ReparamTable assumes that distance and input keys have a linear relationship in-between entries.
767 return FMath::Lerp(PrevDistance, NextDistance, Alpha);
768 }
769 else if (InKey >= NumSegments)
770 {
771 return SplineComponentToFollow->SplineCurves.GetSplineLength();
772 }
773
774 return 0.0f;
775}
776
777float UVRSliderComponent::GetCurrentSliderProgress(FVector CurLocation, bool bUseKeyInstead, float CurKey)
778{
779 if (SplineComponentToFollow != nullptr)
780 {
781 // In this case it is a world location
782 float ClosestKey = CurKey;
783
784 if (!bUseKeyInstead)
785 ClosestKey = SplineComponentToFollow->FindInputKeyClosestToWorldLocation(CurLocation);
786
787 /*int32 primaryKey = FMath::TruncToInt(ClosestKey);
788
789 float distance1 = SplineComponentToFollow->GetDistanceAlongSplineAtSplinePoint(primaryKey);
790 float distance2 = SplineComponentToFollow->GetDistanceAlongSplineAtSplinePoint(primaryKey + 1);
791
792 float FinalDistance = ((distance2 - distance1) * (ClosestKey - (float)primaryKey)) + distance1;
793 return FMath::Clamp(FinalDistance / SplineComponentToFollow->GetSplineLength(), 0.0f, 1.0f);*/
794 float SplineLength = SplineComponentToFollow->GetSplineLength();
795 return GetDistanceAlongSplineAtSplineInputKey(ClosestKey) / SplineLength;
796 }
797
798 // Should need the clamp normally, but if someone is manually setting locations it could go out of bounds
799 float Progress = 0.f;
800
801 if (bUseLegacyLogic)
802 {
803 Progress = FMath::Clamp(FVector::Dist(-MinSlideDistance, CurLocation) / FVector::Dist(-MinSlideDistance, MaxSlideDistance), 0.0f, 1.0f);
804 }
805 else
806 {
807 Progress = FMath::Clamp(FVector::Dist(-MinSlideDistance.GetAbs(), CurLocation) / FVector::Dist(-MinSlideDistance.GetAbs(), MaxSlideDistance.GetAbs()), 0.0f, 1.0f);
808 }
809
811 {
812 if (FMath::Fmod(Progress, SnapIncrement) < SnapThreshold)
813 {
814 Progress = FMath::GridSnap(Progress, SnapIncrement);
815 }
817 {
818 Progress = CurrentSliderProgress;
819 }
820 }
821
822 return Progress;
823}
824
825void UVRSliderComponent::GetLerpedKey(float &ClosestKey, float DeltaTime)
826{
827 switch (SplineLerpType)
828 {
830 {
831 ClosestKey = FMath::FInterpTo(LastInputKey, ClosestKey, DeltaTime, SplineLerpValue);
832 }break;
834 {
835 ClosestKey = FMath::FInterpConstantTo(LastInputKey, ClosestKey, DeltaTime, SplineLerpValue);
836 }break;
837
838 default: break;
839 }
840}
841
842void UVRSliderComponent::SetSplineComponentToFollow(USplineComponent * SplineToFollow)
843{
844 SplineComponentToFollow = SplineToFollow;
845
846 if (SplineToFollow != nullptr)
848 else
850}
851
853{
854 // Get our initial relative transform to our parent (or not if un-parented).
855 InitialRelativeTransform = this->GetRelativeTransform();
857
858 if (SplineComponentToFollow == nullptr)
860}
861
863{
864 if (SplineComponentToFollow != nullptr)
865 {
867 FTransform WorldTransform = SplineComponentToFollow->FindTransformClosestToWorldLocation(this->GetComponentLocation(), ESplineCoordinateSpace::World, true);
869 {
870 WorldTransform.MultiplyScale3D(InitialRelativeTransform.GetScale3D());
871 WorldTransform = WorldTransform * ParentTransform.Inverse();
872 this->SetRelativeTransform(WorldTransform);
873 }
874 else
875 {
876 this->SetWorldLocation(WorldTransform.GetLocation());
877 }
878
879 CurrentSliderProgress = GetCurrentSliderProgress(WorldTransform.GetLocation());
880 }
881}
882
883void UVRSliderComponent::SetSliderProgress(float NewSliderProgress)
884{
885 NewSliderProgress = FMath::Clamp(NewSliderProgress, 0.0f, 1.0f);
886
887 if (SplineComponentToFollow != nullptr)
888 {
890 float splineProgress = SplineComponentToFollow->GetSplineLength() * NewSliderProgress;
891
893 {
894 FTransform trans = SplineComponentToFollow->GetTransformAtDistanceAlongSpline(splineProgress, ESplineCoordinateSpace::World, true);
895 trans.MultiplyScale3D(InitialRelativeTransform.GetScale3D());
896 trans = trans * ParentTransform.Inverse();
897 this->SetRelativeTransform(trans);
898 }
899 else
900 {
901 this->SetRelativeLocation(ParentTransform.InverseTransformPosition(SplineComponentToFollow->GetLocationAtDistanceAlongSpline(splineProgress, ESplineCoordinateSpace::World)));
902 }
903 }
904 else // Not a spline follow
905 {
906 // Doing it min+max because the clamp value subtracts the min value
907 FVector CalculatedLocation = bUseLegacyLogic ? FMath::Lerp(-MinSlideDistance, MaxSlideDistance, NewSliderProgress) : FMath::Lerp(-MinSlideDistance.GetAbs(), MaxSlideDistance.GetAbs(), NewSliderProgress);
908
910 CalculatedLocation *= FVector(1.0f) / InitialRelativeTransform.GetScale3D();
911
912 FVector ClampedLocation = ClampSlideVector(CalculatedLocation);
913
914 //if (bSlideDistanceIsInParentSpace)
915 // this->SetRelativeLocation(InitialRelativeTransform.TransformPositionNoScale(ClampedLocation));
916 //else
917 this->SetRelativeLocation(InitialRelativeTransform.TransformPosition(ClampedLocation));
918 }
919
920 CurrentSliderProgress = NewSliderProgress;
921}
922
924{
925 if (this->SplineComponentToFollow != nullptr)
926 {
927 CurrentSliderProgress = GetCurrentSliderProgress(this->GetComponentLocation());
928 }
929 else
930 {
932 FTransform CurrentRelativeTransform = InitialRelativeTransform * ParentTransform;
933 FVector CalculatedLocation = CurrentRelativeTransform.InverseTransformPosition(this->GetComponentLocation());
934
935 CurrentSliderProgress = GetCurrentSliderProgress(bSlideDistanceIsInParentSpace ? CalculatedLocation * InitialRelativeTransform.GetScale3D() : CalculatedLocation);
936 }
937
939}
EGripMovementReplicationSettings
UENUM(Blueprintable)
ESecondaryGripType
UENUM(Blueprintable)
EBPVRResultSwitch
UENUM()
EGripCollisionType
UENUM(Blueprintable)
EGripLateUpdateSettings
UENUM(Blueprintable)
EGripInterfaceTeleportBehavior
UENUM(Blueprintable)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
bool HasGripAuthority(const FBPActorGripInformation &Grip)
void GetGripByID(FBPActorGripInformation &Grip, uint8 IDToLookForGrip, EBPVRResultSwitch &Result)
UFUNCTION(BlueprintCallable, Category = "GripMotionController", meta = (ExpandEnumAsExecs = "Result")...
FVRGripControllerOnGripOutOfRange OnGripOutOfRange
UPROPERTY(BlueprintAssignable, Category = "GripMotionController")
bool DropObjectByInterface(UObject *ObjectToDrop=nullptr, uint8 GripIDToDrop=0, FVector OptionalAngularVelocity=FVector::ZeroVector, FVector OptionalLinearVelocity=FVector::ZeroVector)
UFUNCTION(BlueprintCallable, Category = "GripMotionController")
static void GetGripSlotInRangeByTypeName_Component(FName SlotType, USceneComponent *Component, FVector WorldLocation, float MaxRange, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *QueryController=nullptr)
UFUNCTION(BlueprintPure, Category = "VRGrip", meta = (bIgnoreSelf = "true", DisplayName = "GetGripSlo...
static float Interactible_GetThresholdSnappedValue(float ValueToSnap, float SnapIncrement, float SnapThreshold)
UFUNCTION(BlueprintPure, Category = "VRInteractibleFunctions", meta = (bIgnoreSelf = "true"))
static FTransform Interactible_GetCurrentParentTransform(USceneComponent *SceneComponentToCheck)
UFUNCTION(BlueprintPure, Category = "VRInteractibleFunctions", meta = (bIgnoreSelf = "true"))
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = (VRExpansionPlugin))
float SnapThreshold
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent", meta = (editcondition = "...
void OnGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
FBPGripPair HoldingGrip
UPROPERTY(BlueprintReadOnly, Category = "VRGripInterface")
void ClosestGripSlotInRange_Implementation(FVector WorldLocation, bool bSecondarySlot, bool &bHadSlotInRange, FTransform &SlotWorldTransform, FName &SlotName, UGripMotionControllerComponent *CallingController=nullptr, FName OverridePrefix=NAME_None) override
FVRSliderFinishedLerpingSignature OnSliderFinishedLerping
UPROPERTY(BlueprintAssignable, Category = "VRSliderComponent")
FGameplayTagContainer GameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "GameplayTags")
EGripMovementReplicationSettings GripMovementReplicationType_Implementation() override
UVRSliderComponent(const FObjectInitializer &ObjectInitializer)
EGripLateUpdateSettings GripLateUpdateSetting_Implementation() override
float PrimarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripSettings")
float BreakDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
virtual void Native_NotifyThrowGripDelegates(UGripMotionControllerComponent *Controller, bool bGripped, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
void OnSecondaryUsed_Implementation() override
int FramesToAverage
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent|Momentum Settings",...
float SnapIncrement
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent", meta = (editcondition = "...
void SetHeld_Implementation(UGripMotionControllerComponent *NewHoldingController, uint8 GripID, bool bNewIsHeld) override
EVRInteractibleSliderLerpType SplineLerpType
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
void OnEndUsed_Implementation() override
float GetCurrentSliderProgress(FVector CurLocation, bool bUseKeyInstead=false, float CurKey=0.f)
int GripPriority
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripSettings")
float MaxSliderMomentum
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent|Momentum Settings",...
bool CheckAutoDrop(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation)
float SecondarySlotRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripSettings")
USplineComponent * SplineComponentToFollow
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Replicated, Category = "VRSliderComponent")
EGripInterfaceTeleportBehavior TeleportBehavior_Implementation() override
virtual void PreReplication(IRepChangedPropertyTracker &ChangedPropertyTracker) override
bool bIsLocked
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
bool bEnforceSplineLinearity
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
float EventThrowThreshold
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent", meta = (ClampMin = "0....
bool bRepGameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface")
void GetGripStiffnessAndDamping_Implementation(float &GripStiffnessOut, float &GripDampingOut) override
bool bIsHeld
UPROPERTY(BlueprintReadOnly, Category = "VRGripInterface", meta = (ScriptName = "IsCurrentlyHeld"))
void ReceiveSliderHitPoint(float SliderProgressPoint)
UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Slider State Changed"))
FVector MinSlideDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
float CurrentSliderProgress
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "VRSliderComponent")
EGripMovementReplicationSettings MovementReplicationSetting
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface")
virtual void OnRegister() override
bool SimulateOnDrop_Implementation() override
void OnSecondaryGrip_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *SecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
float SliderMomentumFriction
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent|Momentum Settings",...
bool bDenyGripping
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRGripInterface", meta = (ScriptName = "IsDen...
void OnChildGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
bool RequestsSocketing_Implementation(USceneComponent *&ParentToSocketTo, FName &OptionalSocketName, FTransform_NetQuantize &RelativeTransform) override
bool bUpdateInTick
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
void OnEndSecondaryUsed_Implementation() override
void GetLerpedKey(float &ClosestKey, float DeltaTime)
bool GetGripScripts_Implementation(TArray< UVRGripScriptBase * > &ArrayReference) override
void IsHeld_Implementation(TArray< FBPGripPair > &CurHoldingControllers, bool &bCurIsHeld) override
void OnGripRelease_Implementation(UGripMotionControllerComponent *ReleasingController, const FBPActorGripInformation &GripInformation, bool bWasSocketed=false) override
EVRInteractibleSliderDropBehavior SliderBehaviorWhenReleased
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
void SetIsLocked(bool bNewLockedState)
UFUNCTION(BlueprintCallable, Category = "GripSettings")
FVROnGripSignature OnGripped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
bool bIsLerping
UPROPERTY(BlueprintReadOnly, Category = "VRSliderComponent")
void SetSplineComponentToFollow(USplineComponent *SplineToFollow)
UFUNCTION(BlueprintCallable, Category = "VRSliderComponent")
bool bSliderUsesSnapPoints
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
ESecondaryGripType SecondaryGripType_Implementation() override
FTransform_NetQuantize InitialRelativeTransform
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_InitialRelativeTransform, Category = "VRSliderCo...
bool bUseLegacyLogic
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
FVRSliderHitPointSignature OnSliderHitPoint
UPROPERTY(BlueprintAssignable, Category = "VRSliderComponent")
void SetSliderProgress(float NewSliderProgress)
UFUNCTION(BlueprintCallable, Category = "VRSliderComponent")
void OnUsed_Implementation() override
void TickGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation, float DeltaTime) override
bool bIncrementProgressBetweenSnapPoints
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent", meta = (editcondition = "...
float CalculateSliderProgress()
UFUNCTION(BlueprintCallable, Category = "VRSliderComponent")
bool bSlideDistanceIsInParentSpace
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
FVector MaxSlideDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
void SetGripPriority(int NewGripPriority)
UFUNCTION(BlueprintCallable, Category = "GripSettings")
bool bReplicateMovement
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface|Replication")
void OnSecondaryGripRelease_Implementation(UGripMotionControllerComponent *GripOwningController, USceneComponent *ReleasingSecondaryGripComponent, const FBPActorGripInformation &GripInformation) override
void ReceiveSliderFinishedLerping(float FinalProgress)
UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "Slider Finished Lerping"))
float GetDistanceAlongSplineAtSplineInputKey(float InKey) const
float GripBreakDistance_Implementation() override
virtual void BeginPlay() override
FVROnDropSignature OnDropped
UPROPERTY(BlueprintAssignable, Category = "Grip Events")
float SplineLerpValue
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent", meta = (ClampMin = "0",...
float SliderRestitution
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent|Momentum Settings",...
bool bAutoDropWhenLocked
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
EGripCollisionType GetPrimaryGripType_Implementation(bool bIsSlot) override
void ResetInitialSliderLocation()
UFUNCTION(BlueprintCallable, Category = "VRSliderComponent")
bool bFollowSplineRotationAndScale
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRSliderComponent")
void OnChildGrip_Implementation(UGripMotionControllerComponent *GrippingController, const FBPActorGripInformation &GripInformation) override
FVector ClampSlideVector(FVector ValueToClamp)
virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override
bool AllowsMultipleGrips_Implementation() override
bool DenyGripping_Implementation(UGripMotionControllerComponent *GripInitiator=nullptr) override
void OnInput_Implementation(FKey Key, EInputEvent KeyEvent) override
FBPAdvGripSettings AdvancedGripSettings_Implementation() override
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
FTransform_NetQuantize RelativeTransform
UPROPERTY(BlueprintReadWrite, Category = "Settings")
uint8 GripID
UPROPERTY(BlueprintReadOnly, Category = "Settings")
EGripMovementReplicationSettings GripMovementReplicationSetting
UPROPERTY(BlueprintReadOnly, Category = "Settings")
float GripDistance
UPROPERTY(BlueprintReadOnly, NotReplicated, Category = "Settings")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
UGripMotionControllerComponent * HoldingController
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripPair")
uint8 GripID
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripPair")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary|TransformNetQuantize", meta = (HasNativeMake = ...