5#include "WorldCollision.h"
6#include "PhysicsPublic.h"
7#include "DrawDebugHelpers.h"
8#include "IHeadMountedDisplay.h"
12#if PHYSICS_INTERFACE_PHYSX
17#include "Components/PrimitiveComponent.h"
20#define LOCTEXT_NAMESPACE "VRRootComponent"
23DECLARE_CYCLE_STAT(TEXT(
"PerformOverlapQueryVR Time"), STAT_PerformOverlapQueryVR, STATGROUP_VRRootComponent);
24DECLARE_CYCLE_STAT(TEXT(
"UpdateOverlapsVRRoot Time"), STAT_UpdateOverlapsVRRoot, STATGROUP_VRRootComponent);
32 && OtherComp->GetGenerateOverlapEvents()
34 && MyComponent->GetGenerateOverlapEvents()
35 && MyComponent->GetCollisionResponseToComponent(OtherComp) == ECR_Overlap;
73template <
class ElementType,
class AllocatorType1,
class AllocatorType2>
74FORCEINLINE_DEBUGGABLE
static void GetPointersToArrayData(TArray<const ElementType*, AllocatorType1>& Pointers,
const TArray<ElementType, AllocatorType2>& DataArray)
76 const int32 NumItems = DataArray.Num();
77 Pointers.SetNumUninitialized(NumItems);
78 for (int32 i = 0; i < NumItems; i++)
80 Pointers[i] = &(DataArray[i]);
84template <
class ElementType,
class AllocatorType1>
85FORCEINLINE_DEBUGGABLE
static void GetPointersToArrayData(TArray<const ElementType*, AllocatorType1>& Pointers,
const TArrayView<const ElementType>& DataArray)
87 const int32 NumItems = DataArray.Num();
88 Pointers.SetNumUninitialized(NumItems);
89 for (int32 i = 0; i < NumItems; i++)
91 Pointers[i] = &(DataArray[i]);
96template <
class ElementType,
class AllocatorType1,
class AllocatorType2,
typename PredicateT>
97FORCEINLINE_DEBUGGABLE
static void GetPointersToArrayDataByPredicate(TArray<const ElementType*, AllocatorType1>& Pointers,
const TArray<ElementType, AllocatorType2>& DataArray, PredicateT Predicate)
99 Pointers.Reserve(Pointers.Num() + DataArray.Num());
100 for (
const ElementType& Item : DataArray)
102 if (Invoke(Predicate, Item))
109template <
class ElementType,
class AllocatorType1,
typename PredicateT>
110FORCEINLINE_DEBUGGABLE
static void GetPointersToArrayDataByPredicate(TArray<const ElementType*, AllocatorType1>& Pointers,
const TArrayView<const ElementType>& DataArray, PredicateT Predicate)
112 Pointers.Reserve(Pointers.Num() + DataArray.Num());
113 for (
const ElementType& Item : DataArray)
115 if (Invoke(Predicate, Item))
130 return CurrentUpdate->RequiresOverlapsEventFlag();
137#define PERF_MOVECOMPONENT_STATS 0
157 return MyOwnerPtr.HasSameIndexAndSerialNumber(
Info.OverlapInfo.Actor);
175 return !
MyOwnerPtr.HasSameIndexAndSerialNumber(
Info.OverlapInfo.Actor);
195 return MyBaseInfo.OverlapInfo.Component.HasSameIndexAndSerialNumber(
Info.OverlapInfo.Component)
201 return MyBaseInfo.OverlapInfo.Component.HasSameIndexAndSerialNumber(
Info->OverlapInfo.Component)
212template<
class AllocatorType>
213FORCEINLINE_DEBUGGABLE int32
IndexOfOverlapFast(
const TArray<FOverlapInfo, AllocatorType>& OverlapArray,
const FOverlapInfo& SearchItem)
219template<
class AllocatorType>
220FORCEINLINE_DEBUGGABLE int32
IndexOfOverlapFast(
const TArray<const FOverlapInfo*, AllocatorType>& OverlapPtrArray,
const FOverlapInfo* SearchItem)
226template<
class AllocatorType>
227FORCEINLINE_DEBUGGABLE
void AddUniqueOverlapFast(TArray<FOverlapInfo, AllocatorType>& OverlapArray, FOverlapInfo& NewOverlap)
231 OverlapArray.Add(NewOverlap);
235template<
class AllocatorType>
236FORCEINLINE_DEBUGGABLE
void AddUniqueOverlapFast(TArray<FOverlapInfo, AllocatorType>& OverlapArray, FOverlapInfo&& NewOverlap)
240 OverlapArray.Add(NewOverlap);
244static void PullBackHit(FHitResult& Hit,
const FVector& Start,
const FVector& End,
const float Dist)
246 const float DesiredTimeBack = FMath::Clamp(0.1f, 0.1f / Dist, 1.f / Dist) + 0.001f;
247 Hit.Time = FMath::Clamp(Hit.Time - DesiredTimeBack, 0.f, 1.f);
250static bool ShouldIgnoreHitResult(
const UWorld* InWorld,
bool bAllowSimulatingCollision, FHitResult
const& TestHit, FVector
const& MovementDirDenormalized,
const AActor* MovingActor, EMoveComponentFlags MoveFlags)
252 if (TestHit.bBlockingHit)
255 if (!bAllowSimulatingCollision && TestHit.Component.IsValid() && TestHit.Component->IsSimulatingPhysics())
259 if ((MoveFlags & MOVECOMP_IgnoreBases) && MovingActor)
262 AActor const*
const HitActor = TestHit.GetActor();
265 if (MovingActor->IsBasedOnActor(HitActor) || HitActor->IsBasedOnActor(MovingActor))
274 static const auto CVarHitDistanceTolerance = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.HitDistanceTolerance"));
275 if ((TestHit.Distance < CVarHitDistanceTolerance->GetFloat() || TestHit.bStartPenetrating) && !(MoveFlags & MOVECOMP_NeverIgnoreBlockingOverlaps))
277 static const auto CVarInitialOverlapTolerance = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.InitialOverlapTolerance"));
278 const float DotTolerance = CVarInitialOverlapTolerance->GetFloat();
281 const FVector MovementDir = MovementDirDenormalized.GetSafeNormal();
282 const float MoveDot = (TestHit.ImpactNormal | MovementDir);
284 const bool bMovingOut = MoveDot > DotTolerance;
286#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
288 static const auto CVarShowInitialOverlaps = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.ShowInitialOverlaps"));
289 if (CVarShowInitialOverlaps->GetInt() != 0)
291 UE_LOG(LogVRRootComponent, Log, TEXT(
"Overlapping %s Dir %s Dot %f Normal %s Depth %f"), *GetNameSafe(TestHit.Component.Get()), *MovementDir.ToString(), MoveDot, *TestHit.ImpactNormal.ToString(), TestHit.PenetrationDepth);
292 DrawDebugDirectionalArrow(InWorld, TestHit.TraceStart, TestHit.TraceStart + 30.f * TestHit.ImpactNormal, 5.f, bMovingOut ? FColor(64, 128, 255) : FColor(255, 64, 64),
true, 4.f);
293 if (TestHit.PenetrationDepth > KINDA_SMALL_NUMBER)
295 DrawDebugDirectionalArrow(InWorld, TestHit.TraceStart, TestHit.TraceStart + TestHit.PenetrationDepth * TestHit.Normal, 5.f, FColor(64, 255, 64),
true, 4.f);
311static FORCEINLINE_DEBUGGABLE
bool ShouldIgnoreOverlapResult(
const UWorld* World,
const AActor* ThisActor,
const UPrimitiveComponent& ThisComponent,
const AActor* OtherActor,
const UPrimitiveComponent& OtherComponent,
bool bCheckOverlapFlags)
314 if (&ThisComponent == &OtherComponent)
319 if (bCheckOverlapFlags)
322 if (!ThisComponent.GetGenerateOverlapEvents() || !OtherComponent.GetGenerateOverlapEvents())
328 if (!ThisActor || !OtherActor)
333 if (!World || OtherActor == (
AActor*)World->GetWorldSettings() || !OtherActor->IsActorInitialized())
343 : Super(ObjectInitializer)
345 PrimaryComponentTick.bCanEverTick =
true;
346 PrimaryComponentTick.bStartWithTickEnabled =
true;
347 PrimaryComponentTick.TickGroup = TG_PrePhysics;
349 bWantsInitializeComponent =
true;
351 this->SetRelativeScale3D(FVector(1.f));
352 this->SetRelativeLocation(FVector::ZeroVector);
362 ShapeColor = FColor(223, 149, 157, 255);
364 CapsuleRadius = 20.0f;
365 CapsuleHalfHeight = 96.0f;
366 bUseEditorCompositing =
true;
385 CanCharacterStepUpOn = ECB_No;
388 SetCanEverAffectNavigation(
false);
389 bDynamicObstacle =
true;
400 static size_t UniquePointer;
401 return reinterpret_cast<size_t>(&UniquePointer);
413 ,
LocalToWorld(InComponent->OffsetComponentToWorld.ToMatrixWithScale())
415 bWillEverBeLit =
false;
418 virtual void GetDynamicMeshElements(
const TArray<const FSceneView*>& Views,
const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector)
const override
420 QUICK_SCOPE_CYCLE_COUNTER(STAT_GetDynamicMeshElements_DrawDynamicElements);
423 const int32 CapsuleSides = FMath::Clamp<int32>(
CapsuleRadius / 4.f, 16, 64);
425 for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
428 if (VisibilityMap & (1 << ViewIndex))
430 const FSceneView* View = Views[ViewIndex];
431 const FLinearColor DrawCapsuleColor = GetViewSelectionColor(
ShapeColor, *View, IsSelected(), IsHovered(),
false, IsIndividuallySelected());
433 FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
439 DrawWireCapsule(PDI,
LocalToWorld.GetOrigin() - FVector(0.f, 0.f,
CapsuleHalfHeight),
LocalToWorld.GetScaledAxis(EAxis::X),
LocalToWorld.GetScaledAxis(EAxis::Y),
LocalToWorld.GetScaledAxis(EAxis::Z), DrawCapsuleColor,
CapsuleRadius,
CapsuleHalfHeight, CapsuleSides, SDPG_World);
441 else if (UseEditorCompositing(View))
443 DrawWireCapsule(PDI,
LocalToWorld.GetOrigin() ,
LocalToWorld.GetScaledAxis(EAxis::X),
LocalToWorld.GetScaledAxis(EAxis::Y),
LocalToWorld.GetScaledAxis(EAxis::Z), DrawCapsuleColor,
CapsuleRadius,
CapsuleHalfHeight, CapsuleSides, SDPG_World, 1.25f);
446 DrawWireCapsule(PDI,
LocalToWorld.GetOrigin(),
LocalToWorld.GetScaledAxis(EAxis::X),
LocalToWorld.GetScaledAxis(EAxis::Y),
LocalToWorld.GetScaledAxis(EAxis::Z), DrawCapsuleColor,
CapsuleRadius,
CapsuleHalfHeight, CapsuleSides, SDPG_World, 1.25f);
454 check(IsInRenderingThread());
466 const bool bShowForCollision = View->Family->EngineShowFlags.Collision && IsCollisionEnabled();
468 FPrimitiveViewRelevance Result;
469 Result.bDrawRelevance = (IsShown(View) && bProxyVisible) || bShowForCollision;
470 Result.bDynamicRelevance =
true;
471 Result.bShadowRelevance = IsShadowCast(View);
472 Result.bEditorPrimitiveRelevance = UseEditorCompositing(View);
497 Super::InitializeComponent();
514 TArray<USceneComponent*> children = this->GetAttachChildren();
516 for (
int i = 0; i < children.Num(); i++)
518 if (children[i]->IsA(UCameraComponent::StaticClass()))
540 if (this->IsSimulatingPhysics())
542 return Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
556 if (
ACharacter * OwningCharacter = Cast<ACharacter>(GetOwner()))
558 CharMove = Cast<UVRBaseCharacterMovementComponent>(OwningCharacter->GetCharacterMovement());
574 else if (GEngine->XRSystem.IsValid() && GEngine->XRSystem->IsHeadTrackingAllowedForWorld(*GetWorld()))
577 if (!GEngine->XRSystem->GetCurrentPose(IXRTrackingSystem::HMDDeviceId, curRot,
curCameraLoc))
619 if (!CharMove || !CharMove->IsComponentTickEnabled() || !CharMove->IsActive())
626 OnUpdateTransform(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
640 FCollisionQueryParams Params(
"RelativeMovementSweep",
false, GetOwner());
641 FCollisionResponseParams ResponseParam;
643 InitSweepCollisionParams(Params, ResponseParam);
644 Params.bFindInitialOverlaps =
true;
645 bool bBlockingHit =
false;
650 bool bAllowWalkingCollision =
false;
651 if (CharMove !=
nullptr)
653 if (CharMove->MovementMode == EMovementMode::MOVE_Walking || CharMove->MovementMode == EMovementMode::MOVE_NavWalking)
654 bAllowWalkingCollision =
true;
657 if (bAllowWalkingCollision)
660 if (bBlockingHit && OutHit.Component.IsValid())
720 if (!CharMove || !CharMove->IsActive())
723 if (bNavigationRelevant && bRegistered)
725 UpdateNavigationData();
726 PostUpdateNavigationData();
732 OnUpdateTransform(EUpdateTransformFlags::SkipPhysicsUpdate, ETeleportType::None);
735 if (this->GetOwner()->GetLocalRole() == ENetRole::ROLE_SimulatedProxy)
737 if (bNavigationRelevant && bRegistered)
739 UpdateNavigationData();
740 PostUpdateNavigationData();
751 Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
763 Super::SetSimulatePhysics(bSimulate);
767 if (
AVRCharacter* OwningCharacter = Cast<AVRCharacter>(GetOwner()))
769 OwningCharacter->NetSmoother->SetRelativeLocation(FVector(0.f,0.f, -this->GetUnscaledCapsuleHalfHeight()));
771 this->AddWorldOffset(this->GetComponentRotation().RotateVector(FVector(0.f, 0.f, this->GetScaledCapsuleHalfHeight())),
false,
nullptr, ETeleportType::TeleportPhysics);
775 if (
AVRCharacter* OwningCharacter = Cast<AVRCharacter>(GetOwner()))
777 OwningCharacter->NetSmoother->SetRelativeLocation(FVector(0.f, 0.f, 0));
779 this->AddWorldOffset(this->GetComponentRotation().RotateVector(FVector(0.f, 0.f, -this->GetScaledCapsuleHalfHeight())),
false,
nullptr, ETeleportType::TeleportPhysics);
786 if (this->IsSimulatingPhysics())
788 if (this->ShouldRender() && this->SceneProxy)
791 float lCapsuleHalfHeight = CapsuleHalfHeight;
792 bool bIsSimulating = this->IsSimulatingPhysics();
794 ENQUEUE_RENDER_COMMAND(VRRootComponent_SendNewDebugTransform)(
795 [CylinderSceneProxy, lOffsetComponentToWorld, lCapsuleHalfHeight, bIsSimulating](FRHICommandList& RHICmdList)
801 return Super::OnUpdateTransform(UpdateTransformFlags, Teleport);
806 if (!(UpdateTransformFlags & EUpdateTransformFlags::SkipPhysicsUpdate))
811 if (this->ShouldRender() && this->SceneProxy)
823 float lCapsuleHalfHeight = CapsuleHalfHeight;
824 bool bIsSimulating = this->IsSimulatingPhysics();
826 ENQUEUE_RENDER_COMMAND(VRRootComponent_SendNewDebugTransform)(
827 [CylinderSceneProxy, lOffsetComponentToWorld, lCapsuleHalfHeight, bIsSimulating](FRHICommandList& RHICmdList)
838 if (bPhysicsStateCreated)
843 const bool bTransformSetDirectly = !(UpdateTransformFlags & EUpdateTransformFlags::PropagateFromParent);
844 if (bTransformSetDirectly || !IsWelded())
854 FVector BoxPoint = FVector(CapsuleRadius, CapsuleRadius, CapsuleHalfHeight);
867 if (bDynamicObstacle)
870 UBodySetup* BodySetup = ((UPrimitiveComponent*)
this)->GetBodySetup();
871 if (BodySetup ==
nullptr)
876 for (int32 Idx = 0; Idx < BodySetup->AggGeom.BoxElems.Num(); Idx++)
878 const FKBoxElem& BoxElem = BodySetup->AggGeom.BoxElems[Idx];
879 const FBox BoxSize = BoxElem.CalcAABB(FTransform::Identity, 1.0f);
882 Data.Modifiers.Add(AreaMod);
885 for (int32 Idx = 0; Idx < BodySetup->AggGeom.SphylElems.Num(); Idx++)
887 const FKSphylElem& SphylElem = BodySetup->AggGeom.SphylElems[Idx];
888 const FTransform AreaOffset(FVector(0, 0, -SphylElem.Length));
890 FAreaNavModifier AreaMod(SphylElem.Radius, SphylElem.Length * 2.0f, AreaOffset *
OffsetComponentToWorld, AreaClass);
891 Data.Modifiers.Add(AreaMod);
894 for (int32 Idx = 0; Idx < BodySetup->AggGeom.ConvexElems.Num(); Idx++)
896 const FKConvexElem& ConvexElem = BodySetup->AggGeom.ConvexElems[Idx];
898 FAreaNavModifier AreaMod(ConvexElem.VertexData, 0, ConvexElem.VertexData.Num(), ENavigationCoordSystem::Unreal,
OffsetComponentToWorld, AreaClass);
899 Data.Modifiers.Add(AreaMod);
902 for (int32 Idx = 0; Idx < BodySetup->AggGeom.SphereElems.Num(); Idx++)
904 const FKSphereElem& SphereElem = BodySetup->AggGeom.SphereElems[Idx];
905 const FTransform AreaOffset(FVector(0, 0, -SphereElem.Radius));
907 FAreaNavModifier AreaMod(SphereElem.Radius, SphereElem.Radius * 2.0f, AreaOffset *
OffsetComponentToWorld, AreaClass);
908 Data.Modifiers.Add(AreaMod);
914void UVRRootComponent::PreEditChange(FProperty* PropertyThatWillChange)
918 if (this->GetOwner()->IsA(AVRCharacter::StaticClass()))
921 Super::PreEditChange(PropertyThatWillChange);
924void UVRRootComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
926 const FName PropertyName = PropertyChangedEvent.Property ? PropertyChangedEvent.Property->GetFName() : NAME_None;
930 if (PropertyName == GET_MEMBER_NAME_CHECKED(
UVRRootComponent, CapsuleHalfHeight))
932 CapsuleHalfHeight = FMath::Max3(0.f, CapsuleHalfHeight, CapsuleRadius);
934 else if (PropertyName == GET_MEMBER_NAME_CHECKED(
UVRRootComponent, CapsuleRadius))
936 CapsuleRadius = FMath::Clamp(CapsuleRadius, 0.f, CapsuleHalfHeight);
958 SCOPE_CYCLE_COUNTER(STAT_VRRootMovement);
962 if (IsPendingKill() || (this->Mobility == EComponentMobility::Static && IsRegistered()))
971 const bool bSkipPhysicsMove = ((MoveFlags & MOVECOMP_SkipPhysicsMove) != MOVECOMP_NoFlags);
973 if (!this->IsSimulatingPhysics() && bSkipPhysicsMove)
979 ConditionalUpdateComponentToWorld();
984 const FVector TraceEnd = TraceStart + Delta;
987 float DeltaSizeSq = (TraceEnd - TraceStart).SizeSquared();
991 const FQuat InitialRotationQuat = GetComponentTransform().GetRotation();
994 const float MinMovementDistSq = (bSweep ? FMath::Square(4.f*KINDA_SMALL_NUMBER) : 0.f);
995 if (DeltaSizeSq <= MinMovementDistSq)
998 if (NewRotationQuat.Equals(InitialRotationQuat, SCENECOMPONENT_QUAT_TOLERANCE))
1003 OutHit->Init(TraceStart, TraceEnd);
1013 FHitResult BlockingHit(NoInit);
1014 BlockingHit.bBlockingHit =
false;
1015 BlockingHit.Time = 1.f;
1016 bool bFilledHitResult =
false;
1017 bool bMoved =
false;
1018 bool bIncludesOverlapsAtEnd =
false;
1019 bool bRotationOnly =
false;
1020 TInlineOverlapInfoArray PendingOverlaps;
1022 FVector OrigLocation = GetComponentLocation();
1027 bMoved = InternalSetWorldLocationAndRotation(OrigLocation + Delta, NewRotationQuat, bSkipPhysicsMove, Teleport);
1029 bRotationOnly = (DeltaSizeSq == 0);
1030 bIncludesOverlapsAtEnd = bRotationOnly && (AreSymmetricRotations(InitialRotationQuat, NewRotationQuat, GetComponentScale())) && IsCollisionEnabled();
1034 TArray<FHitResult> Hits;
1035 FVector NewLocation = OrigLocation;
1037 const bool bCollisionEnabled = IsQueryCollisionEnabled();
1038 if (bCollisionEnabled && (DeltaSizeSq > 0.f))
1040#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
1041 if (!IsRegistered())
1045 ensureMsgf(IsRegistered(), TEXT(
"%s MovedComponent %s not initialized deleteme %d"),*
Actor->GetName(), *GetName(),
Actor->IsPendingKill());
1049 ensureMsgf(IsRegistered(), TEXT(
"MovedComponent %s not initialized"), *GetFullName());
1053#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && PERF_MOVECOMPONENT_STATS
1054 MoveTimer.bDidLineCheck =
true;
1056 UWorld*
const MyWorld = GetWorld();
1058 static const FName TraceTagName = TEXT(
"MoveComponent");
1060 FComponentQueryParams Params(SCENE_QUERY_STAT(MoveComponent),
Actor);
1061 FCollisionResponseParams ResponseParam;
1062 InitSweepCollisionParams(Params, ResponseParam);
1063 Params.bIgnoreTouches |= !(GetGenerateOverlapEvents() || bForceGatherOverlaps);
1064 Params.TraceTag = TraceTagName;
1065 bool const bHadBlockingHit = MyWorld->ComponentSweepMulti(Hits,
this, TraceStart, TraceEnd, InitialRotationQuat, Params);
1070 const float DeltaSize = FMath::Sqrt(DeltaSizeSq);
1071 for (int32 HitIdx = 0; HitIdx < Hits.Num(); HitIdx++)
1073 PullBackHit(Hits[HitIdx], TraceStart, TraceEnd, DeltaSize);
1079 int32 FirstNonInitialOverlapIdx = INDEX_NONE;
1080 if (bHadBlockingHit || (GetGenerateOverlapEvents() || bForceGatherOverlaps))
1082 int32 BlockingHitIndex = INDEX_NONE;
1083 float BlockingHitNormalDotDelta = BIG_NUMBER;
1084 for (int32 HitIdx = 0; HitIdx < Hits.Num(); HitIdx++)
1086 const FHitResult& TestHit = Hits[HitIdx];
1088 if (TestHit.bBlockingHit)
1092 if (TestHit.bStartPenetrating)
1095 const float NormalDotDelta = (TestHit.ImpactNormal | Delta);
1096 if (NormalDotDelta < BlockingHitNormalDotDelta)
1098 BlockingHitNormalDotDelta = NormalDotDelta;
1099 BlockingHitIndex = HitIdx;
1102 else if (BlockingHitIndex == INDEX_NONE)
1106 BlockingHitIndex = HitIdx;
1111 else if (GetGenerateOverlapEvents() || bForceGatherOverlaps)
1113 UPrimitiveComponent* OverlapComponent = TestHit.Component.Get();
1114 if (OverlapComponent && (OverlapComponent->GetGenerateOverlapEvents() || bForceGatherOverlaps))
1119 if (BlockingHitIndex >= 0 && TestHit.Time > Hits[BlockingHitIndex].Time)
1124 if (FirstNonInitialOverlapIdx == INDEX_NONE && TestHit.Time > 0.f)
1127 FirstNonInitialOverlapIdx = PendingOverlaps.Num();
1138 if (BlockingHitIndex >= 0)
1140 BlockingHit = Hits[BlockingHitIndex];
1141 bFilledHitResult =
true;
1146 if (!BlockingHit.bBlockingHit)
1148 NewLocation += (TraceEnd - TraceStart);
1152 check(bFilledHitResult);
1153 NewLocation += (BlockingHit.Time * (TraceEnd - TraceStart));
1156 const FVector ToNewLocation = (NewLocation - OrigLocation);
1157 if (ToNewLocation.SizeSquared() <= MinMovementDistSq)
1160 NewLocation = OrigLocation;
1161 BlockingHit.Time = 0.f;
1164 if (FirstNonInitialOverlapIdx != INDEX_NONE)
1166 const bool bAllowShrinking =
false;
1167 PendingOverlaps.SetNum(FirstNonInitialOverlapIdx, bAllowShrinking);
1172 bIncludesOverlapsAtEnd = AreSymmetricRotations(InitialRotationQuat, NewRotationQuat, GetComponentScale());
1174 else if (DeltaSizeSq > 0.f)
1177 NewLocation += Delta;
1178 bIncludesOverlapsAtEnd =
false;
1180 else if (DeltaSizeSq == 0.f && bCollisionEnabled)
1182 bIncludesOverlapsAtEnd = AreSymmetricRotations(InitialRotationQuat, NewRotationQuat, GetComponentScale());
1183 bRotationOnly =
true;
1187 bMoved = InternalSetWorldLocationAndRotation(NewLocation, NewRotationQuat, bSkipPhysicsMove, Teleport);
1194 if (IsDeferringMovementUpdates())
1198 if (bRotationOnly && bIncludesOverlapsAtEnd)
1200 ScopedUpdate->KeepCurrentOverlapsAfterRotation(bSweep);
1204 ScopedUpdate->AppendOverlapsAfterMove(PendingOverlaps, bSweep, bIncludesOverlapsAtEnd);
1209 if (bIncludesOverlapsAtEnd)
1211 TInlineOverlapInfoArray OverlapsAtEndLocation;
1212 bool bHasEndOverlaps =
false;
1221 TOverlapArrayView PendingOverlapsView(PendingOverlaps);
1222 TOverlapArrayView OverlapsAtEndView(OverlapsAtEndLocation);
1223 UpdateOverlaps(&PendingOverlapsView,
true, bHasEndOverlaps ? &OverlapsAtEndView :
nullptr);
1227 TOverlapArrayView PendingOverlapsView(PendingOverlaps);
1228 UpdateOverlaps(&PendingOverlapsView,
true,
nullptr);
1234 const bool bAllowHitDispatch = !BlockingHit.bStartPenetrating || !(MoveFlags & MOVECOMP_DisableBlockingOverlapDispatch);
1235 if (BlockingHit.bBlockingHit && bAllowHitDispatch && !IsPendingKill())
1237 check(bFilledHitResult);
1238 if (IsDeferringMovementUpdates())
1241 ScopedUpdate->AppendBlockingHitAfterMove(BlockingHit);
1245 DispatchBlockingHit(*
Actor, BlockingHit);
1252 if (bFilledHitResult)
1254 *OutHit = BlockingHit;
1258 OutHit->Init(TraceStart, TraceEnd);
1269 SCOPE_CYCLE_COUNTER(STAT_UpdateOverlapsVRRoot);
1270 SCOPE_CYCLE_UOBJECT(ComponentScope,
this);
1274 const AActor*
const MyActor = GetOwner();
1275 if (MyActor && !MyActor->HasActorBegunPlay() && !MyActor->IsActorBeginningPlay())
1280 bool bCanSkipUpdateOverlaps =
true;
1283 if (GetGenerateOverlapEvents() && IsQueryCollisionEnabled())
1285 bCanSkipUpdateOverlaps =
false;
1289 const FTransform PrevTransform = GetComponentTransform();
1292 const bool bIgnoreChildren = (MyActor->GetRootComponent() ==
this);
1294 if (NewPendingOverlaps)
1297 const int32 NumNewPendingOverlaps = NewPendingOverlaps->Num();
1298 for (int32 Idx = 0; Idx < NumNewPendingOverlaps; ++Idx)
1300 BeginComponentOverlap((*NewPendingOverlaps)[Idx], bDoNotifies);
1304 const TOverlapArrayView* OverlapsAtEndLocationPtr = OverlapsAtEndLocation;
1311 TArray<FOverlapInfo> OverlapsAtEnd;
1312 TOverlapArrayView OverlapsAtEndLoc;
1313 if ( NewPendingOverlaps && NewPendingOverlaps->Num() > 0)
1316 OverlapsAtEndLoc = TOverlapArrayView(OverlapsAtEnd);
1317 OverlapsAtEndLocationPtr = &OverlapsAtEndLoc;
1322 TInlineOverlapInfoArray OverlapMultiResult;
1326 if (!IsPendingKill() && GetGenerateOverlapEvents())
1329 static const auto CVarAllowCachedOverlaps = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.AllowCachedOverlaps"));
1331 if (OverlapsAtEndLocationPtr !=
nullptr && CVarAllowCachedOverlaps->GetInt() > 0 && PrevTransform.Equals(GetComponentTransform()))
1333 UE_LOG(LogVRRootComponent, VeryVerbose, TEXT(
"%s->%s Skipping overlap test!"), *GetNameSafe(GetOwner()), *GetName());
1334 const bool bCheckForInvalid = (NewPendingOverlaps && NewPendingOverlaps->Num() > 0);
1335 if (bCheckForInvalid)
1347 SCOPE_CYCLE_COUNTER(STAT_PerformOverlapQueryVR);
1348 UE_LOG(LogVRRootComponent, VeryVerbose, TEXT(
"%s->%s Performing overlaps!"), *GetNameSafe(GetOwner()), *GetName());
1349 UWorld*
const MyWorld = GetWorld();
1350 TArray<FOverlapResult> Overlaps;
1353 FComponentQueryParams Params(SCENE_QUERY_STAT(UpdateOverlaps), bIgnoreChildren ? MyActor :
nullptr);
1355 Params.bIgnoreBlocks =
true;
1356 FCollisionResponseParams ResponseParam;
1357 InitSweepCollisionParams(Params, ResponseParam);
1358 ComponentOverlapMulti(Overlaps, MyWorld,
OffsetComponentToWorld.GetTranslation(), GetComponentQuat(), GetCollisionObjectType(), Params);
1360 for (int32 ResultIdx = 0; ResultIdx < Overlaps.Num(); ResultIdx++)
1362 const FOverlapResult& Result = Overlaps[ResultIdx];
1364 UPrimitiveComponent*
const HitComp = Result.Component.Get();
1365 if (HitComp && (HitComp !=
this) && HitComp->GetGenerateOverlapEvents())
1367 const bool bCheckOverlapFlags =
false;
1370 OverlapMultiResult.Emplace(HitComp, Result.ItemIndex);
1381 if (OverlappingComponents.Num() > 0)
1384 if (bIgnoreChildren)
1398 for (int32 CompIdx = 0; CompIdx < OldOverlappingComponentPtrs.Num() && NewOverlappingComponentPtrs.Num() > 0; ++CompIdx)
1401 const bool bAllowShrinking =
false;
1403 const FOverlapInfo* SearchItem = OldOverlappingComponentPtrs[CompIdx];
1404 const int32 NewElementIdx =
IndexOfOverlapFast(NewOverlappingComponentPtrs, SearchItem);
1405 if (NewElementIdx != INDEX_NONE)
1407 NewOverlappingComponentPtrs.RemoveAtSwap(NewElementIdx, 1, bAllowShrinking);
1408 OldOverlappingComponentPtrs.RemoveAtSwap(CompIdx, 1, bAllowShrinking);
1413 const int32 NumOldOverlaps = OldOverlappingComponentPtrs.Num();
1414 if (NumOldOverlaps > 0)
1417 TInlineOverlapInfoArray OldOverlappingComponents;
1418 OldOverlappingComponents.SetNumUninitialized(NumOldOverlaps);
1419 for (int32 i = 0; i < NumOldOverlaps; i++)
1421 OldOverlappingComponents[i] = *(OldOverlappingComponentPtrs[i]);
1425 for (
const FOverlapInfo& OtherOverlap : OldOverlappingComponents)
1427 if (OtherOverlap.OverlapInfo.Component.IsValid())
1429 EndComponentOverlap(OtherOverlap, bDoNotifies,
false);
1434 const bool bAllowShrinking = (OverlappingComponents.Max() >= 24);
1435 const int32 StaleElementIndex =
IndexOfOverlapFast(OverlappingComponents, OtherOverlap);
1436 if (StaleElementIndex != INDEX_NONE)
1438 OverlappingComponents.RemoveAtSwap(StaleElementIndex, 1, bAllowShrinking);
1446 static_assert(
sizeof(OverlapMultiResult) != 0,
"Variable must be in this scope");
1447 static_assert(
sizeof(OverlapsAtEndLocationPtr) != 0,
"Variable must be in this scope");
1450 for (
const FOverlapInfo* NewOverlap : NewOverlappingComponentPtrs)
1452 BeginComponentOverlap(*NewOverlap, bDoNotifies);
1460 if (OverlappingComponents.Num() > 0)
1462 const bool bSkipNotifySelf =
false;
1463 ClearComponentOverlaps(bDoNotifies, bSkipNotifySelf);
1470 TInlineComponentArray<USceneComponent*> AttachedChildren;
1471 AttachedChildren.Append(GetAttachChildren());
1478 bCanSkipUpdateOverlaps &= ChildComp->UpdateOverlaps(
nullptr, bDoNotifies,
nullptr);
1483 if (GetShouldUpdatePhysicsVolume())
1486 bCanSkipUpdateOverlaps =
false;
1489 return bCanSkipUpdateOverlaps;
1493template<
typename AllocatorType>
1495 TArray<FOverlapInfo, AllocatorType>& OverlapsAtEndLocation,
const TOverlapArrayView& SweptOverlaps, int32 SweptOverlapsIndex,
1496 const FVector& EndLocation,
const FQuat& EndRotationQuat)
1498 if (SweptOverlapsIndex == -1)
1500 SweptOverlapsIndex = 0;
1507 checkSlow(SweptOverlapsIndex >= 0);
1514 bool bResult =
false;
1517 static const auto CVarAllowCachedOverlaps = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.AllowCachedOverlaps"));
1518 if ((GetGenerateOverlapEvents() || bForceGatherOverlaps) && CVarAllowCachedOverlaps->GetInt())
1521 if (
Actor &&
Actor->GetRootComponent() ==
this)
1529 const FCollisionQueryParams UnusedQueryParams(NAME_None, FCollisionQueryParams::GetUnknownStatId());
1530 const int32 NumSweptOverlaps = SweptOverlaps.Num();
1531 OverlapsAtEndLocation.Reserve(OverlapsAtEndLocation.Num() + NumSweptOverlaps);
1532 for (int32 Index = SweptOverlapsIndex; Index < NumSweptOverlaps; ++Index)
1534 const FOverlapInfo& OtherOverlap = SweptOverlaps[Index];
1535 UPrimitiveComponent* OtherPrimitive = OtherOverlap.OverlapInfo.GetComponent();
1536 if (OtherPrimitive && (OtherPrimitive->GetGenerateOverlapEvents() || bForceGatherOverlaps))
1538 if (OtherPrimitive->bMultiBodyOverlap)
1543 else if (Cast<USkeletalMeshComponent>(OtherPrimitive) || Cast<USkeletalMeshComponent>(
this))
1548 else if (OtherPrimitive->ComponentOverlapComponent(
this, EndLocationVR, EndRotationQuat, UnusedQueryParams))
1550 OverlapsAtEndLocation.Add(OtherOverlap);
1558 TEXT(
"Child overlaps should not be included in the SweptOverlaps() array in UPrimitiveComponent::ConvertSweptOverlapsToCurrentOverlaps()."));
1564 if (SweptOverlaps.Num() == 0 && AreAllCollideableDescendantsRelative())
1578template<
typename AllocatorType>
1581 const int32 InitialCount = OutOverlaps.Num();
1584 for (int32 OverlapIdx = 0; OverlapIdx < OverlappingComponents.Num(); ++OverlapIdx)
1586 UPrimitiveComponent
const*
const PrimComp = OverlappingComponents[OverlapIdx].OverlapInfo.Component.Get();
1587 if (PrimComp && (PrimComp->GetOwner() ==
Actor))
1589 OutOverlaps.Add(OverlappingComponents[OverlapIdx]);
1594 return InitialCount != OutOverlaps.Num();
1597template<
typename AllocatorType>
1600 bool bResult =
false;
1603 static const auto CVarAllowCachedOverlaps = IConsoleManager::Get().FindConsoleVariable(TEXT(
"p.AllowCachedOverlaps"));
1605 if ((GetGenerateOverlapEvents() || bForceGatherOverlaps) && CVarAllowCachedOverlaps->GetInt())
1608 if (
Actor &&
Actor->GetRootComponent() ==
this)
1613 OutOverlapsAtEndLocation.Reserve(OutOverlapsAtEndLocation.Num() + CurrentOverlaps.Num());
1626 const AActor* MyOwner = GetOwner();
1627 return MyOwner->HasLocalNetOwner();
1634 if (GetShouldUpdatePhysicsVolume() && !IsPendingKill())
1637 if (UWorld * MyWorld = GetWorld())
1639 if (MyWorld->GetNonDefaultPhysicsVolumeCount() == 0)
1641 SetPhysicsVolume(MyWorld->GetDefaultPhysicsVolume(), bTriggerNotifiers);
1643 else if (GetGenerateOverlapEvents() && IsQueryCollisionEnabled())
1645 APhysicsVolume* BestVolume = MyWorld->GetDefaultPhysicsVolume();
1646 int32 BestPriority = BestVolume->Priority;
1648 for (
auto CompIt = OverlappingComponents.CreateIterator(); CompIt; ++CompIt)
1650 const FOverlapInfo& Overlap = *CompIt;
1651 UPrimitiveComponent* OtherComponent = Overlap.OverlapInfo.Component.Get();
1652 if (OtherComponent && OtherComponent->GetGenerateOverlapEvents())
1654 APhysicsVolume* V = Cast<APhysicsVolume>(OtherComponent->GetOwner());
1655 if (V && V->Priority > BestPriority)
1660 BestPriority = V->Priority;
1667 SetPhysicsVolume(BestVolume, bTriggerNotifiers);
1671 Super::UpdatePhysicsVolume(bTriggerNotifiers);
1677#undef LOCTEXT_NAMESPACE
static FORCEINLINE_DEBUGGABLE bool ShouldIgnoreOverlapResult(const UWorld *World, const AActor *ThisActor, const UPrimitiveComponent &ThisComponent, const AActor *OtherActor, const UPrimitiveComponent &OtherComponent, bool bCheckOverlapFlags)
DEFINE_LOG_CATEGORY(LogVRRootComponent)
static FORCEINLINE_DEBUGGABLE bool CanComponentsGenerateOverlap(const UPrimitiveComponent *MyComponent, UPrimitiveComponent *OtherComp)
static bool ShouldIgnoreHitResult(const UWorld *InWorld, bool bAllowSimulatingCollision, FHitResult const &TestHit, FVector const &MovementDirDenormalized, const AActor *MovingActor, EMoveComponentFlags MoveFlags)
static FORCEINLINE_DEBUGGABLE void GetPointersToArrayDataByPredicate(TArray< const ElementType *, AllocatorType1 > &Pointers, const TArray< ElementType, AllocatorType2 > &DataArray, PredicateT Predicate)
FORCEINLINE_DEBUGGABLE int32 IndexOfOverlapFast(const TArray< FOverlapInfo, AllocatorType > &OverlapArray, const FOverlapInfo &SearchItem)
static FORCEINLINE_DEBUGGABLE void GetPointersToArrayData(TArray< const ElementType *, AllocatorType1 > &Pointers, const TArray< ElementType, AllocatorType2 > &DataArray)
FORCEINLINE_DEBUGGABLE void AddUniqueOverlapFast(TArray< FOverlapInfo, AllocatorType > &OverlapArray, FOverlapInfo &NewOverlap)
static void PullBackHit(FHitResult &Hit, const FVector &Start, const FVector &End, const float Dist)
TArray< const FOverlapInfo *, TInlineAllocator< 8 > > TInlineOverlapPointerArray
static int32 bEnableFastOverlapCheck
DECLARE_CYCLE_STAT(TEXT("VRRootMovement"), STAT_VRRootMovement, STATGROUP_VRRootComponent)
static bool ShouldCheckOverlapFlagToQueueOverlaps(const UPrimitiveComponent &ThisComponent)
FVector PausedTrackingLoc
UReplicatedVRCameraComponent * VRReplicatedCamera
UPROPERTY(Category = VRBaseCharacter, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess ...
const uint32 bDrawOnlyIfSelected
SIZE_T GetTypeHash() const override
virtual uint32 GetMemoryFootprint(void) const override
uint32 GetAllocatedSize(void) const
FDrawVRCylinderSceneProxy(const UVRRootComponent *InComponent)
const float CapsuleRadius
const FVector VRCapsuleOffset
virtual void GetDynamicMeshElements(const TArray< const FSceneView * > &Views, const FSceneViewFamily &ViewFamily, uint32 VisibilityMap, FMeshElementCollector &Collector) const override
void UpdateTransform_RenderThread(const FTransform &NewTransform, float NewHalfHeight, bool bIsSimulating)
virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView *View) const override
static FTransform Default_GetWaistOrientationAndPosition(FBPVRWaistTracking_Info &WaistTrackingInfo)
void ApplyTrackingParameters(FVector &OriginalPosition)
bool bIgnoreSimulatingComponentsInFloorCheck
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRMovement")
static FRotator GetHMDPureYaw_I(FRotator HMDRotation)
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = VRExpansionLibrary)
UVRRootComponent(const FObjectInitializer &ObjectInitializer)
FBPVRWaistTracking_Info OptionalWaistTrackingParent
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRTrackedParentInterface")
FRotator StoredCameraRotOffset
FORCEINLINE void GenerateOffsetToWorld(bool bUpdateBounds=true, bool bGetPureYaw=true)
FVector DifferenceFromLastFrame
void SetTrackingPaused(bool bPaused)
UFUNCTION(BlueprintCallable, Category = "VRExpansionLibrary")
void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override
FPrimitiveSceneProxy * CreateSceneProxy() override
virtual bool MoveComponentImpl(const FVector &Delta, const FQuat &NewRotation, bool bSweep, FHitResult *OutHit=NULL, EMoveComponentFlags MoveFlags=MOVECOMP_NoFlags, ETeleportType Teleport=ETeleportType::None) override
bool AreWeOverlappingVolume(APhysicsVolume *V)
FTransform OffsetComponentToWorld
FVector VRCapsuleOffset
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
bool bAllowSimulatingCollision
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
USceneComponent * TargetPrimitiveComponent
UPROPERTY(BlueprintReadWrite, Transient, Category = "VRExpansionLibrary")
bool GetOverlapsWithActor_Template(const AActor *Actor, TArray< FOverlapInfo, AllocatorType > &OutOverlaps) const
bool bUseWalkingCollisionOverride
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
bool IsLocallyControlled() const
virtual void GetNavigationData(FNavigationRelevantData &Data) const override
void SendPhysicsTransform(ETeleportType Teleport)
bool bCalledUpdateTransform
bool bCenterCapsuleOnHMD
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
bool ConvertSweptOverlapsToCurrentOverlaps(TArray< FOverlapInfo, AllocatorType > &OutOverlapsAtEndLocation, const TOverlapArrayView &SweptOverlaps, int32 SweptOverlapsIndex, const FVector &EndLocation, const FQuat &EndRotationQuat)
virtual void SetSimulatePhysics(bool bSimulate) override
virtual void OnUpdateTransform(EUpdateTransformFlags UpdateTransformFlags, ETeleportType Teleport=ETeleportType::None) override
AVRBaseCharacter * owningVRChar
TEnumAsByte< ECollisionChannel > WalkingCollisionOverride
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
virtual void InitializeComponent() override
bool bPauseTracking
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "VRExpansionLibrary")
bool bHadRelativeMovement
UPROPERTY(BlueprintReadOnly, Category = "VRExpansionLibrary")
void BeginPlay() override
virtual bool UpdateOverlapsImpl(const TOverlapArrayView *NewPendingOverlaps=nullptr, bool bDoNotifies=true, const TOverlapArrayView *OverlapsAtEndLocation=nullptr) override
bool ConvertRotationOverlapsToCurrentOverlaps(TArray< FOverlapInfo, AllocatorType > &OutOverlapsAtEndLocation, const TOverlapArrayView &CurrentOverlaps)
virtual FBoxSphereBounds CalcBounds(const FTransform &LocalToWorld) const override
virtual void UpdatePhysicsVolume(bool bTriggerNotifiers) override
static const FName MoveComponentName(TEXT("MoveComponent"))
static const FName UpdateOverlapsName(TEXT("UpdateOverlaps"))
bool operator()(const FOverlapInfo &Info)
FFastOverlapInfoCompare(const FOverlapInfo &BaseInfo)
const FOverlapInfo & MyBaseInfo
const UPrimitiveComponent & MyComponent
FPredicateFilterCanOverlap(const UPrimitiveComponent &OwningComponent)
bool operator()(const FOverlapInfo &Info) const
const UPrimitiveComponent & MyComponent
FPredicateFilterCannotOverlap(const UPrimitiveComponent &OwningComponent)
bool operator()(const FOverlapInfo &Info) const
bool operator()(const FOverlapInfo &Info)
const TWeakObjectPtr< const AActor > MyOwnerPtr
FPredicateOverlapHasDifferentActor(const AActor &Owner)
bool operator()(const FOverlapInfo &Info)
FPredicateOverlapHasSameActor(const AActor &Owner)
const TWeakObjectPtr< const AActor > MyOwnerPtr