Files
UnrealEngineUWP/Engine/Source/Runtime/NavigationSystem/Private/NavRelevantComponent.cpp
yoan stamant b918f902d3 [UNavRelevantComponent] Fixed some calls to GetNavigationParent made before the cache initialization since this might result in improper registration in the NavOctree. Also added error reporting to detect those cases in the future.
[at]aris.theophanidis
#rb aris.theophanidis


#ROBOMERGE-SOURCE: CL 12368552 via CL 12368554
#ROBOMERGE-BOT: (v671-12333473)

[CL 12370944 by yoan stamant in Main branch]
2020-03-23 11:01:34 -04:00

135 lines
3.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "NavRelevantComponent.h"
#include "NavigationSystem.h"
UNavRelevantComponent::UNavRelevantComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
, bAttachToOwnersRoot(true)
, bBoundsInitialized(false)
, bNavParentCacheInitialized(false)
{
bCanEverAffectNavigation = true;
bNavigationRelevant = true;
}
void UNavRelevantComponent::OnRegister()
{
Super::OnRegister();
if (bAttachToOwnersRoot)
{
bool bUpdateCachedParent = true;
#if WITH_EDITOR
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
if (NavSys && NavSys->IsNavigationRegisterLocked())
{
bUpdateCachedParent = false;
}
#endif
AActor* OwnerActor = GetOwner();
if (OwnerActor && bUpdateCachedParent)
{
// attach to root component if it's relevant for navigation
UActorComponent* ActorComp = OwnerActor->GetRootComponent();
INavRelevantInterface* NavInterface = ActorComp ? Cast<INavRelevantInterface>(ActorComp) : nullptr;
if (NavInterface && NavInterface->IsNavigationRelevant() &&
OwnerActor->IsComponentRelevantForNavigation(ActorComp))
{
CachedNavParent = ActorComp;
}
// otherwise try actor itself under the same condition
if (CachedNavParent == nullptr)
{
NavInterface = Cast<INavRelevantInterface>(OwnerActor);
if (NavInterface && NavInterface->IsNavigationRelevant())
{
CachedNavParent = OwnerActor;
}
}
}
}
// Mark cache as initialized (even if null) from this point so calls to GetNavigationParent can be validated.
bNavParentCacheInitialized = true;
FNavigationSystem::OnComponentRegistered(*this);
}
void UNavRelevantComponent::OnUnregister()
{
Super::OnUnregister();
FNavigationSystem::OnComponentUnregistered(*this);
}
FBox UNavRelevantComponent::GetNavigationBounds() const
{
if (!bBoundsInitialized)
{
CalcAndCacheBounds();
bBoundsInitialized = true;
}
return Bounds;
}
bool UNavRelevantComponent::IsNavigationRelevant() const
{
return bNavigationRelevant;
}
void UNavRelevantComponent::UpdateNavigationBounds()
{
CalcAndCacheBounds();
bBoundsInitialized = true;
}
UObject* UNavRelevantComponent::GetNavigationParent() const
{
UE_CLOG(!bNavParentCacheInitialized, LogNavigation, Error,
TEXT("%s called before initialization of the navigation parent cache for [%s]. This might cause improper registration in the NavOctree and must be fixed."),
ANSI_TO_TCHAR(__FUNCTION__),
*GetFullName());
return CachedNavParent;
}
void UNavRelevantComponent::CalcAndCacheBounds() const
{
const AActor* OwnerActor = GetOwner();
const FVector MyLocation = OwnerActor ? OwnerActor->GetActorLocation() : FVector::ZeroVector;
Bounds = FBox::BuildAABB(MyLocation, FVector(100.0f, 100.0f, 100.0f));
}
void UNavRelevantComponent::ForceNavigationRelevancy(bool bForce)
{
bAttachToOwnersRoot = !bForce;
if (bForce)
{
bNavigationRelevant = true;
}
RefreshNavigationModifiers();
}
void UNavRelevantComponent::SetNavigationRelevancy(bool bRelevant)
{
if (bNavigationRelevant != bRelevant)
{
bNavigationRelevant = bRelevant;
RefreshNavigationModifiers();
}
}
void UNavRelevantComponent::RefreshNavigationModifiers()
{
// Only update after component registration since some required informations are initialized at that time (i.e. Cached Navigation Parent)
if (bRegistered)
{
FNavigationSystem::UpdateComponentData(*this);
}
}