You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
When initializing a new world, reset navlinks id counter to make sure each map has its own set of unique ids (else, when cooking map by map, ids may change depending on order of cooking). [REVIEW] [at]Yoan.StAmant [at]Mieszko.Zielinski #rb Yoan.StAmant #ROBOMERGE-SOURCE: CL 11116144 via CL 11116146 via CL 11116148 #ROBOMERGE-BOT: (v640-11091645) [CL 11116177 by aris theophanidis in Main branch]
386 lines
10 KiB
C++
386 lines
10 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "NavLinkCustomComponent.h"
|
|
#include "TimerManager.h"
|
|
#include "GameFramework/Pawn.h"
|
|
#include "CollisionQueryParams.h"
|
|
#include "WorldCollision.h"
|
|
#include "Engine/World.h"
|
|
#include "GameFramework/Controller.h"
|
|
#include "NavigationSystem.h"
|
|
#include "NavAreas/NavArea_Null.h"
|
|
#include "NavAreas/NavArea_Default.h"
|
|
#include "AI/NavigationModifier.h"
|
|
#include "NavigationOctree.h"
|
|
#include "AI/NavigationSystemHelpers.h"
|
|
#include "AI/Navigation/PathFollowingAgentInterface.h"
|
|
|
|
|
|
UNavLinkCustomComponent::UNavLinkCustomComponent(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
|
|
{
|
|
NavLinkUserId = 0;
|
|
LinkRelativeStart = FVector(70, 0, 0);
|
|
LinkRelativeEnd = FVector(-70, 0, 0);
|
|
LinkDirection = ENavLinkDirection::BothWays;
|
|
EnabledAreaClass = UNavArea_Default::StaticClass();
|
|
DisabledAreaClass = UNavArea_Null::StaticClass();
|
|
ObstacleAreaClass = UNavArea_Null::StaticClass();
|
|
ObstacleExtent = FVector(50, 50, 50);
|
|
bLinkEnabled = true;
|
|
bNotifyWhenEnabled = false;
|
|
bNotifyWhenDisabled = false;
|
|
bCreateBoxObstacle = false;
|
|
BroadcastRadius = 0.0f;
|
|
BroadcastChannel = ECC_Pawn;
|
|
BroadcastInterval = 0.0f;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::PostLoad()
|
|
{
|
|
Super::PostLoad();
|
|
|
|
INavLinkCustomInterface::UpdateUniqueId(NavLinkUserId);
|
|
}
|
|
|
|
TStructOnScope<FActorComponentInstanceData> UNavLinkCustomComponent::GetComponentInstanceData() const
|
|
{
|
|
TStructOnScope<FActorComponentInstanceData> InstanceData = MakeStructOnScope<FActorComponentInstanceData, FNavLinkCustomInstanceData>(this);
|
|
FNavLinkCustomInstanceData* NavLinkCustomInstanceData = InstanceData.Cast<FNavLinkCustomInstanceData>();
|
|
NavLinkCustomInstanceData->NavLinkUserId = NavLinkUserId;
|
|
|
|
return InstanceData;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::ApplyComponentInstanceData(FNavLinkCustomInstanceData* NavLinkData)
|
|
{
|
|
check(NavLinkData);
|
|
|
|
if (NavLinkUserId != NavLinkData->NavLinkUserId)
|
|
{
|
|
// Registered component has its link registered in the navigation system.
|
|
// In such case, we need to unregister current Id and register with the Id from the instance data.
|
|
const bool bIsLinkRegistrationUpdateRequired = IsRegistered();
|
|
|
|
if (bIsLinkRegistrationUpdateRequired)
|
|
{
|
|
UNavigationSystemV1::RequestCustomLinkUnregistering(*this, this);
|
|
}
|
|
|
|
NavLinkUserId = NavLinkData->NavLinkUserId;
|
|
|
|
if (bIsLinkRegistrationUpdateRequired)
|
|
{
|
|
UNavigationSystemV1::RequestCustomLinkRegistering(*this, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if WITH_EDITOR
|
|
void UNavLinkCustomComponent::PostEditImport()
|
|
{
|
|
Super::PostEditImport();
|
|
|
|
NavLinkUserId = INavLinkCustomInterface::GetUniqueId();
|
|
UE_LOG(LogNavLink, VeryVerbose, TEXT("%s new navlink id %u."), ANSI_TO_TCHAR(__FUNCTION__), NavLinkUserId);
|
|
}
|
|
#endif
|
|
|
|
void UNavLinkCustomComponent::GetLinkData(FVector& LeftPt, FVector& RightPt, ENavLinkDirection::Type& Direction) const
|
|
{
|
|
LeftPt = LinkRelativeStart;
|
|
RightPt = LinkRelativeEnd;
|
|
Direction = LinkDirection;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::GetSupportedAgents(FNavAgentSelector& OutSupportedAgents) const
|
|
{
|
|
OutSupportedAgents = SupportedAgents;
|
|
}
|
|
|
|
TSubclassOf<UNavArea> UNavLinkCustomComponent::GetLinkAreaClass() const
|
|
{
|
|
return bLinkEnabled ? EnabledAreaClass : DisabledAreaClass;
|
|
}
|
|
|
|
uint32 UNavLinkCustomComponent::GetLinkId() const
|
|
{
|
|
return NavLinkUserId;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::UpdateLinkId(uint32 NewUniqueId)
|
|
{
|
|
NavLinkUserId = NewUniqueId;
|
|
}
|
|
|
|
bool UNavLinkCustomComponent::IsLinkPathfindingAllowed(const UObject* Querier) const
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool UNavLinkCustomComponent::OnLinkMoveStarted(UObject* PathComp, const FVector& DestPoint)
|
|
{
|
|
MovingAgents.Add(MakeWeakObjectPtr(PathComp));
|
|
|
|
if (OnMoveReachedLink.IsBound())
|
|
{
|
|
OnMoveReachedLink.Execute(this, PathComp, DestPoint);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::OnLinkMoveFinished(UObject* PathComp)
|
|
{
|
|
MovingAgents.Remove(MakeWeakObjectPtr(PathComp));
|
|
}
|
|
|
|
void UNavLinkCustomComponent::GetNavigationData(FNavigationRelevantData& Data) const
|
|
{
|
|
TArray<FNavigationLink> NavLinks;
|
|
FNavigationLink LinkMod = GetLinkModifier();
|
|
LinkMod.MaxFallDownLength = 0.f;
|
|
LinkMod.LeftProjectHeight = 0.f;
|
|
NavLinks.Add(LinkMod);
|
|
NavigationHelper::ProcessNavLinkAndAppend(&Data.Modifiers, GetOwner(), NavLinks);
|
|
|
|
if (bCreateBoxObstacle)
|
|
{
|
|
Data.Modifiers.Add(FAreaNavModifier(FBox::BuildAABB(ObstacleOffset, ObstacleExtent), GetOwner()->GetTransform(), ObstacleAreaClass));
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::CalcAndCacheBounds() const
|
|
{
|
|
Bounds = FBox(ForceInit);
|
|
Bounds += GetStartPoint();
|
|
Bounds += GetEndPoint();
|
|
|
|
if (bCreateBoxObstacle)
|
|
{
|
|
FBox ObstacleBounds = FBox::BuildAABB(ObstacleOffset, ObstacleExtent);
|
|
Bounds += ObstacleBounds.TransformBy(GetOwner()->GetTransform());
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::OnRegister()
|
|
{
|
|
Super::OnRegister();
|
|
|
|
if (NavLinkUserId == 0)
|
|
{
|
|
NavLinkUserId = INavLinkCustomInterface::GetUniqueId();
|
|
UE_LOG(LogNavLink, VeryVerbose, TEXT("%s new navlink id %u [%s]."), ANSI_TO_TCHAR(__FUNCTION__), NavLinkUserId, *GetFullName());
|
|
}
|
|
|
|
UNavigationSystemV1::RequestCustomLinkRegistering(*this, this);
|
|
}
|
|
|
|
void UNavLinkCustomComponent::OnUnregister()
|
|
{
|
|
Super::OnUnregister();
|
|
|
|
UNavigationSystemV1::RequestCustomLinkUnregistering(*this, this);
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetLinkData(const FVector& RelativeStart, const FVector& RelativeEnd, ENavLinkDirection::Type Direction)
|
|
{
|
|
LinkRelativeStart = RelativeStart;
|
|
LinkRelativeEnd = RelativeEnd;
|
|
LinkDirection = Direction;
|
|
|
|
RefreshNavigationModifiers();
|
|
MarkRenderStateDirty();
|
|
}
|
|
|
|
FNavigationLink UNavLinkCustomComponent::GetLinkModifier() const
|
|
{
|
|
return INavLinkCustomInterface::GetModifier(this);
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetEnabledArea(TSubclassOf<UNavArea> AreaClass)
|
|
{
|
|
EnabledAreaClass = AreaClass;
|
|
if (IsNavigationRelevant() && bLinkEnabled)
|
|
{
|
|
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
|
|
if (NavSys)
|
|
{
|
|
NavSys->UpdateCustomLink(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetDisabledArea(TSubclassOf<UNavArea> AreaClass)
|
|
{
|
|
DisabledAreaClass = AreaClass;
|
|
if (IsNavigationRelevant() && !bLinkEnabled)
|
|
{
|
|
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
|
|
if (NavSys)
|
|
{
|
|
NavSys->UpdateCustomLink(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::AddNavigationObstacle(TSubclassOf<UNavArea> AreaClass, const FVector& BoxExtent, const FVector& BoxOffset)
|
|
{
|
|
ObstacleOffset = BoxOffset;
|
|
ObstacleExtent = BoxExtent;
|
|
ObstacleAreaClass = AreaClass;
|
|
bCreateBoxObstacle = true;
|
|
|
|
RefreshNavigationModifiers();
|
|
}
|
|
|
|
void UNavLinkCustomComponent::ClearNavigationObstacle()
|
|
{
|
|
ObstacleAreaClass = NULL;
|
|
bCreateBoxObstacle = false;
|
|
|
|
RefreshNavigationModifiers();
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetEnabled(bool bNewEnabled)
|
|
{
|
|
if (bLinkEnabled != bNewEnabled)
|
|
{
|
|
bLinkEnabled = bNewEnabled;
|
|
|
|
UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
|
|
if (NavSys)
|
|
{
|
|
NavSys->UpdateCustomLink(this);
|
|
}
|
|
|
|
if (GetWorld())
|
|
{
|
|
GetWorld()->GetTimerManager().ClearTimer(TimerHandle_BroadcastStateChange);
|
|
|
|
if ((bLinkEnabled && bNotifyWhenEnabled) || (!bLinkEnabled && bNotifyWhenDisabled))
|
|
{
|
|
BroadcastStateChange();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetMoveReachedLink(FOnMoveReachedLink const& InDelegate)
|
|
{
|
|
OnMoveReachedLink = InDelegate;
|
|
}
|
|
|
|
bool UNavLinkCustomComponent::HasMovingAgents() const
|
|
{
|
|
for (int32 i = 0; i < MovingAgents.Num(); i++)
|
|
{
|
|
if (MovingAgents[i].IsValid())
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SetBroadcastData(float Radius, ECollisionChannel TraceChannel, float Interval)
|
|
{
|
|
BroadcastRadius = Radius;
|
|
BroadcastChannel = TraceChannel;
|
|
BroadcastInterval = Interval;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SendBroadcastWhenEnabled(bool bEnabled)
|
|
{
|
|
bNotifyWhenEnabled = bEnabled;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::SendBroadcastWhenDisabled(bool bEnabled)
|
|
{
|
|
bNotifyWhenDisabled = bEnabled;
|
|
}
|
|
|
|
void UNavLinkCustomComponent::CollectNearbyAgents(TArray<UObject*>& NotifyList)
|
|
{
|
|
AActor* MyOwner = GetOwner();
|
|
if (BroadcastRadius < KINDA_SMALL_NUMBER || MyOwner == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
FCollisionQueryParams Params(SCENE_QUERY_STAT(SmartLinkBroadcastTrace), false, MyOwner);
|
|
TArray<FOverlapResult> OverlapsL, OverlapsR;
|
|
|
|
const FVector LocationL = GetStartPoint();
|
|
const FVector LocationR = GetEndPoint();
|
|
const float LinkDistSq = (LocationL - LocationR).SizeSquared();
|
|
const float DistThresholdSq = FMath::Square(BroadcastRadius * 0.25f);
|
|
if (LinkDistSq > DistThresholdSq)
|
|
{
|
|
GetWorld()->OverlapMultiByChannel(OverlapsL, LocationL, FQuat::Identity, BroadcastChannel, FCollisionShape::MakeSphere(BroadcastRadius), Params);
|
|
GetWorld()->OverlapMultiByChannel(OverlapsR, LocationR, FQuat::Identity, BroadcastChannel, FCollisionShape::MakeSphere(BroadcastRadius), Params);
|
|
}
|
|
else
|
|
{
|
|
const FVector MidPoint = (LocationL + LocationR) * 0.5f;
|
|
GetWorld()->OverlapMultiByChannel(OverlapsL, MidPoint, FQuat::Identity, BroadcastChannel, FCollisionShape::MakeSphere(BroadcastRadius), Params);
|
|
}
|
|
|
|
TArray<AController*> ControllerList;
|
|
for (int32 i = 0; i < OverlapsL.Num(); i++)
|
|
{
|
|
APawn* MovingPawn = Cast<APawn>(OverlapsL[i].GetActor());
|
|
if (MovingPawn && MovingPawn->GetController())
|
|
{
|
|
ControllerList.Add(MovingPawn->GetController());
|
|
}
|
|
}
|
|
for (int32 i = 0; i < OverlapsR.Num(); i++)
|
|
{
|
|
APawn* MovingPawn = Cast<APawn>(OverlapsR[i].GetActor());
|
|
if (MovingPawn && MovingPawn->GetController())
|
|
{
|
|
ControllerList.Add(MovingPawn->GetController());
|
|
}
|
|
}
|
|
|
|
for (AController* Controller : ControllerList)
|
|
{
|
|
IPathFollowingAgentInterface* PFAgent = Controller->GetPathFollowingAgent();
|
|
UObject* PFAgentObject = Cast<UObject>(PFAgent);
|
|
if (PFAgentObject)
|
|
{
|
|
NotifyList.Add(PFAgentObject);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UNavLinkCustomComponent::BroadcastStateChange()
|
|
{
|
|
TArray<UObject*> NearbyAgents;
|
|
|
|
CollectNearbyAgents(NearbyAgents);
|
|
OnBroadcastFilter.ExecuteIfBound(this, NearbyAgents);
|
|
|
|
for (int32 i = 0; i < NearbyAgents.Num(); i++)
|
|
{
|
|
// NearbyAgents[i]->OnCustomLinkBroadcast(this);
|
|
}
|
|
|
|
if (BroadcastInterval > 0.0f)
|
|
{
|
|
GetWorld()->GetTimerManager().SetTimer(TimerHandle_BroadcastStateChange, this, &UNavLinkCustomComponent::BroadcastStateChange, BroadcastInterval);
|
|
}
|
|
}
|
|
|
|
FVector UNavLinkCustomComponent::GetStartPoint() const
|
|
{
|
|
return GetOwner()->GetTransform().TransformPosition(LinkRelativeStart);
|
|
}
|
|
|
|
FVector UNavLinkCustomComponent::GetEndPoint() const
|
|
{
|
|
return GetOwner()->GetTransform().TransformPosition(LinkRelativeEnd);
|
|
}
|