You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Add a way to register a Navigation Invoker based on UObject with a INavigationInvokerInterface instead of an AActor.
#rb Aris.Theophanidis [CL 29887626 by frederic doll in ue5-main branch]
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "GameFramework/Controller.h"
|
||||
#include "AI/Navigation/NavRelevantInterface.h"
|
||||
#include "AI/Navigation/NavigationDirtyElement.h"
|
||||
#include "AI/Navigation/NavigationInvokerInterface.h"
|
||||
#include "AI/Navigation/NavigationInvokerPriority.h"
|
||||
#include "UObject/UObjectIterator.h"
|
||||
#include "EngineUtils.h"
|
||||
@@ -233,6 +234,7 @@ FNavigationInvokerRaw::FNavigationInvokerRaw(const FVector& InLocation, float Mi
|
||||
//----------------------------------------------------------------------//
|
||||
FNavigationInvoker::FNavigationInvoker()
|
||||
: Actor(nullptr)
|
||||
, Object(nullptr)
|
||||
, GenerationRadius(0)
|
||||
, RemovalRadius(0)
|
||||
, Priority(ENavigationInvokerPriority::Default)
|
||||
@@ -242,6 +244,7 @@ FNavigationInvoker::FNavigationInvoker()
|
||||
|
||||
FNavigationInvoker::FNavigationInvoker(AActor& InActor, float InGenerationRadius, float InRemovalRadius, const FNavAgentSelector& InSupportedAgents, ENavigationInvokerPriority InPriority)
|
||||
: Actor(&InActor)
|
||||
, Object(nullptr)
|
||||
, GenerationRadius(InGenerationRadius)
|
||||
, RemovalRadius(InRemovalRadius)
|
||||
, SupportedAgents(InSupportedAgents)
|
||||
@@ -250,6 +253,52 @@ FNavigationInvoker::FNavigationInvoker(AActor& InActor, float InGenerationRadius
|
||||
SupportedAgents.MarkInitialized();
|
||||
}
|
||||
|
||||
FNavigationInvoker::FNavigationInvoker(INavigationInvokerInterface& InObject, float InGenerationRadius, float InRemovalRadius, const FNavAgentSelector& InSupportedAgents, ENavigationInvokerPriority InPriority)
|
||||
: Actor(nullptr)
|
||||
, Object(&InObject)
|
||||
, GenerationRadius(InGenerationRadius)
|
||||
, RemovalRadius(InRemovalRadius)
|
||||
, SupportedAgents(InSupportedAgents)
|
||||
, Priority(InPriority)
|
||||
{
|
||||
}
|
||||
|
||||
FString FNavigationInvoker::GetName() const
|
||||
{
|
||||
/** We are using IsExplicitlyNull to know which one of the Actor or the Object was set at construction */
|
||||
if (!Actor.IsExplicitlyNull())
|
||||
{
|
||||
return GetNameSafe(Actor.Get());
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetNameSafe(Object.GetObject());
|
||||
}
|
||||
}
|
||||
|
||||
bool FNavigationInvoker::GetLocation(FVector& OutLocation) const
|
||||
{
|
||||
/** We are using IsExplicitlyNull to know which one of the Actor or the Object was set at construction */
|
||||
if (!Actor.IsExplicitlyNull())
|
||||
{
|
||||
if (const AActor* ActorPtr = Actor.Get())
|
||||
{
|
||||
OutLocation = ActorPtr->GetActorLocation();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (const INavigationInvokerInterface* InvokerInterface = Object.Get())
|
||||
{
|
||||
OutLocation = InvokerInterface->GetNavigationInvokerLocation();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------//
|
||||
// helpers
|
||||
//----------------------------------------------------------------------//
|
||||
@@ -5043,6 +5092,38 @@ void UNavigationSystemV1::SetGeometryGatheringMode(ENavDataGatheringModeConfig N
|
||||
}
|
||||
}
|
||||
|
||||
namespace UE::Navigation::Private
|
||||
{
|
||||
void LogNavInvokerRegistration(const UNavigationSystemV1& NavSystem, const FNavigationInvoker& Data)
|
||||
{
|
||||
UE_SUPPRESS(LogNavInvokers, Log,
|
||||
{
|
||||
TStringBuilder<128> InvokerNavData;
|
||||
for (int32 NavDataIndex = 0; NavDataIndex < NavSystem.NavDataSet.Num(); NavDataIndex++)
|
||||
{
|
||||
const ANavigationData* NavData = NavSystem.NavDataSet[NavDataIndex].Get();
|
||||
if (NavData)
|
||||
{
|
||||
const int32 NavDataSupportedAgentIndex = NavSystem.GetSupportedAgentIndex(NavData);
|
||||
if (Data.SupportedAgents.Contains(NavDataSupportedAgentIndex))
|
||||
{
|
||||
InvokerNavData.Append(FString::Printf(TEXT("%s "), *NavData->GetName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const FString RegisterText = FString::Printf(TEXT("Register invoker r: %.0f, r area: %.0f m2, removal r: %.0f, priority: %s, (%s %s) "),
|
||||
Data.GenerationRadius, UE_PI*FMath::Square(Data.GenerationRadius/100.f), Data.RemovalRadius, *UEnum::GetDisplayValueAsText(Data.Priority).ToString(), *Data.GetName(), *InvokerNavData);
|
||||
UE_LOG(LogNavInvokers, Log, TEXT("%s"), *RegisterText);
|
||||
|
||||
FVector InvokerLocation = FVector::ZeroVector;
|
||||
Data.GetLocation(InvokerLocation);
|
||||
UE_VLOG_CYLINDER(&NavSystem, LogNavInvokers, Log, InvokerLocation, InvokerLocation + FVector(0, 0, 20), Data.GenerationRadius, FColorList::LimeGreen, TEXT("%s"), *RegisterText);
|
||||
UE_VLOG_CYLINDER(&NavSystem, LogNavInvokers, Log, InvokerLocation, InvokerLocation + FVector(0, 0, 20), Data.RemovalRadius, FColorList::IndianRed, TEXT(""));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
void UNavigationSystemV1::RegisterInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius)
|
||||
{
|
||||
@@ -5074,32 +5155,44 @@ void UNavigationSystemV1::RegisterInvoker(AActor& Invoker, float TileGenerationR
|
||||
Data.SupportedAgents.MarkInitialized();
|
||||
Data.Priority = InPriority;
|
||||
|
||||
UE_SUPPRESS(LogNavInvokers, Log,
|
||||
UE::Navigation::Private::LogNavInvokerRegistration(*this, Data);
|
||||
}
|
||||
|
||||
void UNavigationSystemV1::RegisterInvoker(const TWeakInterfacePtr<INavigationInvokerInterface>& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents, ENavigationInvokerPriority InPriority)
|
||||
{
|
||||
UE_CVLOG(bGenerateNavigationOnlyAroundNavigationInvokers == false, this, LogNavInvokers, Warning
|
||||
, TEXT("Trying to register %s as invoker, but NavigationSystem is not set up for invoker-centric generation. See GenerateNavigationOnlyAroundNavigationInvokers in NavigationSystem's properties")
|
||||
, *GetNameSafe(Invoker.GetObject()));
|
||||
|
||||
UObject* InvokerObject = Invoker.GetObject();
|
||||
if (ensure(InvokerObject != nullptr))
|
||||
{
|
||||
TStringBuilder<128> InvokerNavData;
|
||||
for (int32 NavDataIndex = 0; NavDataIndex < NavDataSet.Num(); NavDataIndex++)
|
||||
{
|
||||
const ANavigationData* NavData = NavDataSet[NavDataIndex].Get();
|
||||
if (NavData)
|
||||
{
|
||||
const int32 NavDataSupportedAgentIndex = GetSupportedAgentIndex(NavData);
|
||||
if (Data.SupportedAgents.Contains(NavDataSupportedAgentIndex))
|
||||
{
|
||||
InvokerNavData.Append(FString::Printf(TEXT("%s "), *NavData->GetName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
FNavigationInvoker& Data = Invokers.FindOrAdd(InvokerObject);
|
||||
Data.Object = Invoker;
|
||||
Data.GenerationRadius = TileGenerationRadius;
|
||||
Data.RemovalRadius = TileRemovalRadius;
|
||||
Data.SupportedAgents = Agents;
|
||||
Data.SupportedAgents.MarkInitialized();
|
||||
Data.Priority = InPriority;
|
||||
|
||||
const FString RegisterText = FString::Printf(TEXT("Register invoker r: %.0f, r area: %.0f m2, removal r: %.0f, priority: %s, (%s %s) "),
|
||||
TileGenerationRadius, UE_PI*FMath::Square(TileGenerationRadius/100.f), TileRemovalRadius, *UEnum::GetDisplayValueAsText(InPriority).ToString(), *Invoker.GetName(), *InvokerNavData);
|
||||
UE_LOG(LogNavInvokers, Log, TEXT("%s"), *RegisterText);
|
||||
|
||||
UE_VLOG_CYLINDER(this, LogNavInvokers, Log, Invoker.GetActorLocation(), Invoker.GetActorLocation() + FVector(0, 0, 20), TileGenerationRadius, FColorList::LimeGreen, TEXT("%s"), *RegisterText);
|
||||
UE_VLOG_CYLINDER(this, LogNavInvokers, Log, Invoker.GetActorLocation(), Invoker.GetActorLocation() + FVector(0, 0, 20), TileRemovalRadius, FColorList::IndianRed, TEXT(""));
|
||||
});
|
||||
UE::Navigation::Private::LogNavInvokerRegistration(*this, Data);
|
||||
}
|
||||
}
|
||||
|
||||
void UNavigationSystemV1::UnregisterInvoker(AActor& Invoker)
|
||||
{
|
||||
UnregisterInvoker_Internal(Invoker);
|
||||
}
|
||||
|
||||
void UNavigationSystemV1::UnregisterInvoker(const TWeakInterfacePtr<INavigationInvokerInterface>& Invoker)
|
||||
{
|
||||
if (const UObject* InvokerObject = Invoker.GetObject())
|
||||
{
|
||||
UnregisterInvoker_Internal(*InvokerObject);
|
||||
}
|
||||
}
|
||||
|
||||
void UNavigationSystemV1::UnregisterInvoker_Internal(const UObject& Invoker)
|
||||
{
|
||||
UE_VLOG(this, LogNavInvokers, Log, TEXT("Removing %s from invokers list"), *Invoker.GetName());
|
||||
Invokers.Remove(&Invoker);
|
||||
@@ -5134,60 +5227,55 @@ void UNavigationSystemV1::UpdateInvokers()
|
||||
FVector(SeedLocation.X+InvokersMaximumDistanceFromSeed, SeedLocation.Y+InvokersMaximumDistanceFromSeed, SeedLocation.Z+InvokersMaximumDistanceFromSeed));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if ENABLE_VISUAL_LOG
|
||||
const double StartTime = FPlatformTime::Seconds();
|
||||
#endif // ENABLE_VISUAL_LOG
|
||||
|
||||
InvokerLocations.Reserve(Invokers.Num());
|
||||
|
||||
for (auto ItemIterator = Invokers.CreateIterator(); ItemIterator; ++ItemIterator)
|
||||
{
|
||||
const AActor* Actor = ItemIterator->Value.Actor.Get();
|
||||
if (Actor != nullptr
|
||||
#if WITH_EDITOR
|
||||
// Would like to ignore objects in transactional buffer here, but there's no flag for it
|
||||
//&& (GIsEditor == false || Item.Actor->HasAnyFlags(RF_Transactional | RF_PendingKill) == false)
|
||||
#endif //WITH_EDITOR
|
||||
)
|
||||
FVector InvokerLocation;
|
||||
if (!ItemIterator->Value.GetLocation(InvokerLocation))
|
||||
{
|
||||
const FVector ActorLocation = Actor->GetActorLocation();
|
||||
const float GenerationRadius = ItemIterator->Value.GenerationRadius;
|
||||
bool bKeep = !bCheckMaximumDistanceFromSeeds;
|
||||
ItemIterator.RemoveCurrent();
|
||||
continue;
|
||||
}
|
||||
|
||||
double ClosestDistanceSq = DBL_MAX;
|
||||
if (bCheckMaximumDistanceFromSeeds)
|
||||
const float GenerationRadius = ItemIterator->Value.GenerationRadius;
|
||||
bool bKeep = !bCheckMaximumDistanceFromSeeds;
|
||||
|
||||
double ClosestDistanceSq = DBL_MAX;
|
||||
if (bCheckMaximumDistanceFromSeeds)
|
||||
{
|
||||
const double CheckDistanceSq = FMath::Square(InvokersMaximumDistanceFromSeed + GenerationRadius);
|
||||
|
||||
// Check if the invoker is close enough
|
||||
for (const FVector SeedLocation : SeedLocations)
|
||||
{
|
||||
const double CheckDistanceSq = FMath::Square(InvokersMaximumDistanceFromSeed + GenerationRadius);
|
||||
|
||||
// Check if the invoker is close enough
|
||||
for (const FVector SeedLocation : SeedLocations)
|
||||
const double InvokerDistanceToSeedSq = FVector::DistSquared(SeedLocation, InvokerLocation);
|
||||
if (InvokerDistanceToSeedSq <= CheckDistanceSq)
|
||||
{
|
||||
const double InvokerDistanceToSeedSq = FVector::DistSquared(SeedLocation, ActorLocation);
|
||||
if (InvokerDistanceToSeedSq <= CheckDistanceSq)
|
||||
{
|
||||
bKeep = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClosestDistanceSq = FMath::Min(InvokerDistanceToSeedSq, ClosestDistanceSq);
|
||||
}
|
||||
}
|
||||
bKeep = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClosestDistanceSq = FMath::Min(InvokerDistanceToSeedSq, ClosestDistanceSq);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bKeep)
|
||||
{
|
||||
InvokerLocations.Add(FNavigationInvokerRaw(ActorLocation, GenerationRadius, ItemIterator->Value.RemovalRadius,
|
||||
ItemIterator->Value.SupportedAgents, ItemIterator->Value.Priority));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogNavInvokers, Verbose, TEXT("Invoker %s ignored because it's too far from any seed location. Closest seed at %.0f."),
|
||||
*Actor->GetName(), FMath::Sqrt(ClosestDistanceSq));
|
||||
}
|
||||
if (bKeep)
|
||||
{
|
||||
InvokerLocations.Add(FNavigationInvokerRaw(InvokerLocation, GenerationRadius, ItemIterator->Value.RemovalRadius,
|
||||
ItemIterator->Value.SupportedAgents, ItemIterator->Value.Priority));
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemIterator.RemoveCurrent();
|
||||
UE_LOG(LogNavInvokers, Verbose, TEXT("Invoker %s ignored because it's too far from any seed location. Closest seed at %.0f."),
|
||||
*ItemIterator->Value.GetName(), FMath::Sqrt(ClosestDistanceSq));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5205,7 +5293,7 @@ void UNavigationSystemV1::UpdateInvokers()
|
||||
|
||||
#if WITH_RECAST
|
||||
const double UpdateStartTime = FPlatformTime::Seconds();
|
||||
for (TActorIterator<ARecastNavMesh> It(GetWorld()); It; ++It)
|
||||
for (TActorIterator<ARecastNavMesh> It(World); It; ++It)
|
||||
{
|
||||
It->UpdateActiveTiles(InvokerLocations);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class ANavMeshBoundsVolume;
|
||||
class AWorldSettings;
|
||||
class FEdMode;
|
||||
class FNavDataGenerator;
|
||||
class INavigationInvokerInterface;
|
||||
class INavLinkCustomInterface;
|
||||
class INavRelevantInterface;
|
||||
class UCrowdManagerBase;
|
||||
@@ -453,10 +454,10 @@ protected:
|
||||
TSet<FNavigationBounds> RegisteredNavBounds;
|
||||
|
||||
private:
|
||||
TMap<AActor*, FNavigationInvoker> Invokers;
|
||||
TMap<UObject*, FNavigationInvoker> Invokers;
|
||||
/** Contains pre-digested and cached invokers' info. Generated by UpdateInvokers */
|
||||
TArray<FNavigationInvokerRaw> InvokerLocations;
|
||||
|
||||
|
||||
TArray<FBox> InvokersSeedBounds;
|
||||
|
||||
double NextInvokersUpdateTime;
|
||||
@@ -464,6 +465,8 @@ private:
|
||||
|
||||
NAVIGATIONSYSTEM_API void DirtyTilesInBuildBounds();
|
||||
|
||||
void UnregisterInvoker_Internal(const UObject& Invoker);
|
||||
|
||||
public:
|
||||
//----------------------------------------------------------------------//
|
||||
// Blueprint functions
|
||||
@@ -814,8 +817,12 @@ public:
|
||||
NAVIGATIONSYSTEM_API virtual void RegisterInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents);
|
||||
|
||||
NAVIGATIONSYSTEM_API virtual void RegisterInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents, ENavigationInvokerPriority InPriority);
|
||||
|
||||
|
||||
NAVIGATIONSYSTEM_API virtual void RegisterInvoker(const TWeakInterfacePtr<INavigationInvokerInterface>& Invoker, float TileGenerationRadius, float TileRemovalRadius, const FNavAgentSelector& Agents, ENavigationInvokerPriority InPriority);
|
||||
|
||||
NAVIGATIONSYSTEM_API virtual void UnregisterInvoker(AActor& Invoker);
|
||||
|
||||
NAVIGATIONSYSTEM_API virtual void UnregisterInvoker(const TWeakInterfacePtr<INavigationInvokerInterface>& Invoker);
|
||||
|
||||
static NAVIGATIONSYSTEM_API void RegisterNavigationInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius,
|
||||
const FNavAgentSelector& Agents = FNavAgentSelector(), ENavigationInvokerPriority Priority = ENavigationInvokerPriority::Default);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "AI/Navigation/NavLinkDefinition.h"
|
||||
#include "Math/GenericOctreePublic.h"
|
||||
#include "AI/NavigationModifier.h"
|
||||
#include "UObject/WeakInterfacePtr.h"
|
||||
|
||||
#define NAVSYS_DEBUG (0 && UE_BUILD_DEBUG)
|
||||
|
||||
@@ -20,6 +21,7 @@ struct FKAggregateGeom;
|
||||
class FNavigationOctree;
|
||||
class UNavigationPath;
|
||||
class ANavigationData;
|
||||
class INavigationInvokerInterface;
|
||||
|
||||
struct FPathFindingQueryData
|
||||
{
|
||||
@@ -105,7 +107,9 @@ struct FNavigationInvokerRaw
|
||||
|
||||
struct FNavigationInvoker
|
||||
{
|
||||
/** The Invoker source should be either an Actor or an Object. Thus only 1 of those member should be set. We'll use IsExplicitlyNull to know which one to use */
|
||||
TWeakObjectPtr<AActor> Actor;
|
||||
TWeakInterfacePtr<INavigationInvokerInterface> Object;
|
||||
|
||||
/** tiles GenerationRadius away or close will be generated if they're not already present */
|
||||
float GenerationRadius;
|
||||
@@ -119,9 +123,13 @@ struct FNavigationInvoker
|
||||
|
||||
/** invoker Priority used when dirtying tiles */
|
||||
ENavigationInvokerPriority Priority;
|
||||
|
||||
|
||||
FNavigationInvoker();
|
||||
FNavigationInvoker(AActor& InActor, float InGenerationRadius, float InRemovalRadius, const FNavAgentSelector& InSupportedAgents, ENavigationInvokerPriority InPriority);
|
||||
FNavigationInvoker(INavigationInvokerInterface& InObject, float InGenerationRadius, float InRemovalRadius, const FNavAgentSelector& InSupportedAgents, ENavigationInvokerPriority InPriority);
|
||||
|
||||
FString GetName() const;
|
||||
bool GetLocation(FVector& OutLocation) const;
|
||||
};
|
||||
|
||||
namespace NavigationHelper
|
||||
|
||||
Reference in New Issue
Block a user