You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
ARecastNavMesh::ReplaceAreaInTileBounds replaces occurences of given area directly on navmesh polys (checking and setting areaID) in tiles overlapped by given bounding box.
UNavigationSystemV1::ReplaceAreaInOctreeData replaces occurences of given area in object's nav representation in the NavOctree.
Also extended navmesh drawing to be able to optionally mark polys excluded by navmesh's default query filter (via dtQueryFilter.data.m_excludeFlags).
review-5764395
#rb Stephen.Holmes
#ROBOMERGE-OWNER: ryan.vance
#ROBOMERGE-AUTHOR: mieszko.zielinski
#ROBOMERGE-SOURCE: CL 5809064 via CL 5810331 via CL 5813303 via CL 5813372
#ROBOMERGE-BOT: DEVVR (Main -> Dev-VR)
[CL 5844457 by mieszko zielinski in Dev-VR branch]
1050 lines
51 KiB
C++
1050 lines
51 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "Templates/SubclassOf.h"
|
|
#include "UObject/WeakObjectPtr.h"
|
|
#include "Misc/CoreMisc.h"
|
|
#include "Misc/CoreDelegates.h"
|
|
#include "NavFilters/NavigationQueryFilter.h"
|
|
#include "AI/Navigation/NavigationTypes.h"
|
|
#include "NavigationSystemTypes.h"
|
|
#include "NavigationData.h"
|
|
#include "AI/NavigationSystemBase.h"
|
|
#include "Kismet/BlueprintFunctionLibrary.h"
|
|
#include "NavigationOctree.h"
|
|
#include "AI/NavigationSystemConfig.h"
|
|
#include "NavigationSystem.generated.h"
|
|
|
|
|
|
class AController;
|
|
class ANavMeshBoundsVolume;
|
|
class AWorldSettings;
|
|
class FEdMode;
|
|
class FNavDataGenerator;
|
|
class FNavigationOctree;
|
|
class INavLinkCustomInterface;
|
|
class INavRelevantInterface;
|
|
class UCrowdManagerBase;
|
|
class UNavArea;
|
|
class UNavigationPath;
|
|
class UNavigationSystemModuleConfig;
|
|
struct FNavigationRelevantData;
|
|
struct FNavigationOctreeElement;
|
|
|
|
#if WITH_EDITOR
|
|
class FEdMode;
|
|
#endif // WITH_EDITOR
|
|
|
|
/** delegate to let interested parties know that new nav area class has been registered */
|
|
DECLARE_MULTICAST_DELEGATE_OneParam(FOnNavAreaChanged, const UClass* /*AreaClass*/);
|
|
|
|
/** Delegate to let interested parties know that Nav Data has been registered */
|
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnNavDataGenericEvent, ANavigationData*, NavData);
|
|
|
|
DECLARE_MULTICAST_DELEGATE(FOnNavigationInitDone);
|
|
|
|
namespace NavigationDebugDrawing
|
|
{
|
|
extern const NAVIGATIONSYSTEM_API float PathLineThickness;
|
|
extern const NAVIGATIONSYSTEM_API FVector PathOffset;
|
|
extern const NAVIGATIONSYSTEM_API FVector PathNodeBoxExtent;
|
|
}
|
|
|
|
namespace FNavigationSystem
|
|
{
|
|
/**
|
|
* Used to construct an ANavigationData instance for specified navigation data agent
|
|
*/
|
|
typedef ANavigationData* (*FNavigationDataInstanceCreator)(UWorld*, const FNavDataConfig&);
|
|
|
|
struct NAVIGATIONSYSTEM_API FCustomLinkOwnerInfo
|
|
{
|
|
FWeakObjectPtr LinkOwner;
|
|
INavLinkCustomInterface* LinkInterface;
|
|
|
|
FCustomLinkOwnerInfo() : LinkInterface(nullptr) {}
|
|
FCustomLinkOwnerInfo(INavLinkCustomInterface* Link);
|
|
|
|
bool IsValid() const { return LinkOwner.IsValid(); }
|
|
};
|
|
|
|
bool NAVIGATIONSYSTEM_API ShouldLoadNavigationOnClient(ANavigationData& NavData);
|
|
bool NAVIGATIONSYSTEM_API ShouldDiscardSubLevelNavData(ANavigationData& NavData);
|
|
|
|
void NAVIGATIONSYSTEM_API MakeAllComponentsNeverAffectNav(AActor& Actor);
|
|
}
|
|
|
|
struct FNavigationSystemExec: public FSelfRegisteringExec
|
|
{
|
|
//~ Begin FExec Interface
|
|
virtual bool Exec(UWorld* Inworld, const TCHAR* Cmd, FOutputDevice& Ar) override;
|
|
//~ End FExec Interface
|
|
};
|
|
|
|
namespace ENavigationBuildLock
|
|
{
|
|
enum Type
|
|
{
|
|
NoUpdateInEditor = 1 << 1, // editor doesn't allow automatic updates
|
|
InitialLock = 1 << 2, // initial lock, release manually after levels are ready for rebuild (e.g. streaming)
|
|
Custom = 1 << 3,
|
|
};
|
|
}
|
|
|
|
UCLASS(Within=World, config=Engine, defaultconfig)
|
|
class NAVIGATIONSYSTEM_API UNavigationSystemV1 : public UNavigationSystemBase
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
friend UNavigationSystemModuleConfig;
|
|
|
|
public:
|
|
UNavigationSystemV1(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
|
virtual ~UNavigationSystemV1();
|
|
|
|
UPROPERTY()
|
|
ANavigationData* MainNavData;
|
|
|
|
/** special navigation data for managing direct paths, not part of NavDataSet! */
|
|
UPROPERTY(Transient)
|
|
ANavigationData* AbstractNavData;
|
|
|
|
protected:
|
|
UPROPERTY(config, EditAnywhere, BlueprintReadOnly, Category = Navigation)
|
|
TSoftClassPtr<UCrowdManagerBase> CrowdManagerClass;
|
|
|
|
/** Should navigation system spawn default Navigation Data when there's none and there are navigation bounds present? */
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bAutoCreateNavigationData:1;
|
|
|
|
UPROPERTY(config, EditAnywhere, Category = NavigationSystem)
|
|
uint32 bSpawnNavDataInNavBoundsLevel:1;
|
|
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bAllowClientSideNavigation:1;
|
|
|
|
UPROPERTY(config, EditAnywhere, Category = NavigationSystem)
|
|
uint32 bShouldDiscardSubLevelNavData:1;
|
|
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bTickWhilePaused:1;
|
|
|
|
/** gets set to true if gathering navigation data (like in navoctree) is required due to the need of navigation generation
|
|
* Is always true in Editor Mode. In other modes it depends on bRebuildAtRuntime of every required NavigationData class' CDO
|
|
*/
|
|
UPROPERTY()
|
|
uint32 bSupportRebuilding : 1;
|
|
|
|
public:
|
|
/** if set to true will result navigation system not rebuild navigation until
|
|
* a call to ReleaseInitialBuildingLock() is called. Does not influence
|
|
* editor-time generation (i.e. does influence PIE and Game).
|
|
* Defaults to false.*/
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bInitialBuildingLocked:1;
|
|
|
|
/** If set to true (default) navigation will be generated only within special navigation
|
|
* bounds volumes (like ANavMeshBoundsVolume). Set to false means navigation should be generated
|
|
* everywhere.
|
|
*/
|
|
// @todo removing it from edition since it's currently broken and I'm not sure we want that at all
|
|
// since I'm not sure we can make it efficient in a generic case
|
|
//UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bWholeWorldNavigable:1;
|
|
|
|
/** false by default, if set to true will result in not caring about nav agent height
|
|
* when trying to match navigation data to passed in nav agent */
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
uint32 bSkipAgentHeightCheckWhenPickingNavData:1;
|
|
|
|
protected:
|
|
|
|
UPROPERTY(EditDefaultsOnly, Category = "NavigationSystem", config)
|
|
ENavDataGatheringModeConfig DataGatheringMode;
|
|
|
|
/** If set to true navigation will be generated only around registered "navigation enforcers"
|
|
* This has a range of consequences (including how navigation octree operates) so it needs to
|
|
* be a conscious decision.
|
|
* Once enabled results in whole world being navigable.
|
|
* @see RegisterNavigationInvoker
|
|
*/
|
|
UPROPERTY(EditDefaultsOnly, Category = "Navigation Enforcing", config)
|
|
uint32 bGenerateNavigationOnlyAroundNavigationInvokers : 1;
|
|
|
|
/** Minimal time, in seconds, between active tiles set update */
|
|
UPROPERTY(EditAnywhere, Category = "Navigation Enforcing", meta = (ClampMin = "0.1", UIMin = "0.1", EditCondition = "bGenerateNavigationOnlyAroundNavigationInvokers"), config)
|
|
float ActiveTilesUpdateInterval;
|
|
|
|
UPROPERTY(config, EditAnywhere, Category = Agents)
|
|
TArray<FNavDataConfig> SupportedAgents;
|
|
|
|
public:
|
|
/** update frequency for dirty areas on navmesh */
|
|
UPROPERTY(config, EditAnywhere, Category=NavigationSystem)
|
|
float DirtyAreasUpdateFreq;
|
|
|
|
UPROPERTY()
|
|
TArray<ANavigationData*> NavDataSet;
|
|
|
|
UPROPERTY(transient)
|
|
TArray<ANavigationData*> NavDataRegistrationQueue;
|
|
|
|
TSet<FNavigationDirtyElement> PendingOctreeUpdates;
|
|
|
|
// List of pending navigation bounds update requests (add, remove, update size)
|
|
TArray<FNavigationBoundsUpdateRequest> PendingNavBoundsUpdates;
|
|
|
|
UPROPERTY(/*BlueprintAssignable, */Transient)
|
|
FOnNavDataGenericEvent OnNavDataRegisteredEvent;
|
|
|
|
UPROPERTY(BlueprintAssignable, Transient, meta = (displayname = OnNavigationGenerationFinished))
|
|
FOnNavDataGenericEvent OnNavigationGenerationFinishedDelegate;
|
|
|
|
FOnNavigationInitDone OnNavigationInitDone;
|
|
|
|
private:
|
|
TWeakObjectPtr<UCrowdManagerBase> CrowdManager;
|
|
|
|
/** set to true when navigation processing was blocked due to missing nav bounds */
|
|
uint32 bNavDataRemovedDueToMissingNavBounds : 1;
|
|
|
|
protected:
|
|
/** All areas where we build/have navigation */
|
|
TSet<FNavigationBounds> RegisteredNavBounds;
|
|
|
|
private:
|
|
TMap<AActor*, FNavigationInvoker> Invokers;
|
|
/** Contains pre-digested and cached invokers' info. Generated by UpdateInvokers */
|
|
TArray<FNavigationInvokerRaw> InvokerLocations;
|
|
|
|
float NextInvokersUpdateTime;
|
|
void UpdateInvokers();
|
|
|
|
public:
|
|
//----------------------------------------------------------------------//
|
|
// Blueprint functions
|
|
//----------------------------------------------------------------------//
|
|
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject"))
|
|
static UNavigationSystemV1* GetNavigationSystem(UObject* WorldContextObject);
|
|
|
|
/** Project a point onto the NavigationData */
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "ProjectPointToNavigation", ScriptName = "ProjectPointToNavigation"))
|
|
static bool K2_ProjectPointToNavigation(UObject* WorldContextObject, const FVector& Point, FVector& ProjectedLocation, ANavigationData* NavData, TSubclassOf<UNavigationQueryFilter> FilterClass, const FVector QueryExtent = FVector::ZeroVector);
|
|
|
|
/** Generates a random location reachable from given Origin location.
|
|
* @return Return Value represents if the call was successful */
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomReachablePointInRadius", ScriptName = "GetRandomReachablePointInRadius"))
|
|
static bool K2_GetRandomReachablePointInRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
/** Generates a random location in navigable space within given radius of Origin.
|
|
* @return Return Value represents if the call was successful */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomLocationInNavigableRadius", ScriptName = "GetRandomLocationInNavigableRadius"))
|
|
static bool K2_GetRandomLocationInNavigableRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
/** Potentially expensive. Use with caution. Consider using UPathFollowingComponent::GetRemainingPathCost instead */
|
|
UFUNCTION(BlueprintPure, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" ) )
|
|
static ENavigationQueryResult::Type GetPathCost(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, float& PathCost, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
/** Potentially expensive. Use with caution */
|
|
UFUNCTION(BlueprintPure, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" ) )
|
|
static ENavigationQueryResult::Type GetPathLength(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, float& PathLength, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
UFUNCTION(BlueprintPure, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" ) )
|
|
static bool IsNavigationBeingBuilt(UObject* WorldContextObject);
|
|
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject"))
|
|
static bool IsNavigationBeingBuiltOrLocked(UObject* WorldContextObject);
|
|
|
|
/** Finds path instantly, in a FindPath Synchronously.
|
|
* @param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext="WorldContextObject"))
|
|
static UNavigationPath* FindPathToLocationSynchronously(UObject* WorldContextObject, const FVector& PathStart, const FVector& PathEnd, AActor* PathfindingContext = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
/** Finds path instantly, in a FindPath Synchronously. Main advantage over FindPathToLocationSynchronously is that
|
|
* the resulting path will automatically get updated if goal actor moves more than TetherDistance away from last path node
|
|
* @param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (WorldContext="WorldContextObject"))
|
|
static UNavigationPath* FindPathToActorSynchronously(UObject* WorldContextObject, const FVector& PathStart, AActor* GoalActor, float TetherDistance = 50.f, AActor* PathfindingContext = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
|
|
/** Performs navigation raycast on NavigationData appropriate for given Querier.
|
|
* @param Querier if not passed default navigation data will be used
|
|
* @param HitLocation if line was obstructed this will be set to hit location. Otherwise it contains SegmentEnd
|
|
* @return true if line from RayStart to RayEnd was obstructed. Also, true when no navigation data present */
|
|
UFUNCTION(BlueprintCallable, Category="AI|Navigation", meta=(WorldContext="WorldContextObject" ))
|
|
static bool NavigationRaycast(UObject* WorldContextObject, const FVector& RayStart, const FVector& RayEnd, FVector& HitLocation, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL, AController* Querier = NULL);
|
|
|
|
/** will limit the number of simultaneously running navmesh tile generation jobs to specified number.
|
|
* @param MaxNumberOfJobs gets trimmed to be at least 1. You cannot use this function to pause navmesh generation */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation")
|
|
void SetMaxSimultaneousTileGenerationJobsCount(int32 MaxNumberOfJobs);
|
|
|
|
/** Brings limit of simultaneous navmesh tile generation jobs back to Project Setting's default value */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation")
|
|
void ResetMaxSimultaneousTileGenerationJobsCount();
|
|
|
|
/** Registers given actor as a "navigation enforcer" which means navigation system will
|
|
* make sure navigation is being generated in specified radius around it.
|
|
* @note: you need NavigationSystem's GenerateNavigationOnlyAroundNavigationInvokers to be set to true
|
|
* to take advantage of this feature
|
|
*/
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation")
|
|
void RegisterNavigationInvoker(AActor* Invoker, float TileGenerationRadius = 3000, float TileRemovalRadius = 5000);
|
|
|
|
/** Removes given actor from the list of active navigation enforcers.
|
|
* @see RegisterNavigationInvoker for more details */
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation")
|
|
void UnregisterNavigationInvoker(AActor* Invoker);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation|Generation")
|
|
void SetGeometryGatheringMode(ENavDataGatheringModeConfig NewMode);
|
|
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta=(DisplayName="ReplaceAreaInOctreeData"))
|
|
bool K2_ReplaceAreaInOctreeData(const UObject* Object, TSubclassOf<UNavArea> OldArea, TSubclassOf<UNavArea> NewArea);
|
|
|
|
FORCEINLINE bool IsActiveTilesGenerationEnabled() const{ return bGenerateNavigationOnlyAroundNavigationInvokers; }
|
|
|
|
/** delegate type for events that dirty the navigation data ( Params: const FBox& DirtyBounds ) */
|
|
DECLARE_MULTICAST_DELEGATE_OneParam(FOnNavigationDirty, const FBox&);
|
|
/** called after navigation influencing event takes place*/
|
|
static FOnNavigationDirty NavigationDirtyEvent;
|
|
|
|
enum ERegistrationResult
|
|
{
|
|
RegistrationError,
|
|
RegistrationFailed_DataPendingKill, // means navigation data being registered is marked as pending kill
|
|
RegistrationFailed_AgentAlreadySupported, // this means that navigation agent supported by given nav data is already handled by some other, previously registered instance
|
|
RegistrationFailed_AgentNotValid, // given instance contains navmesh that doesn't support any of expected agent types, or instance doesn't specify any agent
|
|
RegistrationFailed_NotSuitable, // given instance had been considered unsuitable by current navigation system instance itself
|
|
RegistrationSuccessful,
|
|
};
|
|
|
|
enum EOctreeUpdateMode
|
|
{
|
|
OctreeUpdate_Default = 0, // regular update, mark dirty areas depending on exported content
|
|
OctreeUpdate_Geometry = 1, // full update, mark dirty areas for geometry rebuild
|
|
OctreeUpdate_Modifiers = 2, // quick update, mark dirty areas for modifier rebuild
|
|
OctreeUpdate_Refresh = 4, // update is used for refresh, don't invalidate pending queue
|
|
OctreeUpdate_ParentChain = 8, // update child nodes, don't remove anything
|
|
};
|
|
|
|
//~ Begin UObject Interface
|
|
virtual void PostInitProperties() override;
|
|
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
|
|
#if WITH_EDITOR
|
|
virtual void PostEditChangeChainProperty(FPropertyChangedChainEvent& PropertyChangedEvent) override;
|
|
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& PropertyChangedEvent) override;
|
|
#endif // WITH_EDITOR
|
|
//~ End UObject Interface
|
|
|
|
virtual void Tick(float DeltaSeconds) override;
|
|
|
|
UWorld* GetWorld() const override { return GetOuterUWorld(); }
|
|
|
|
UCrowdManagerBase* GetCrowdManager() const { return CrowdManager.Get(); }
|
|
|
|
protected:
|
|
/** spawn new crowd manager */
|
|
virtual void CreateCrowdManager();
|
|
|
|
/** Used to properly set navigation class for indicated agent and propagate information to other places
|
|
* (like project settings) that may need this information
|
|
*/
|
|
void SetSupportedAgentsNavigationClass(int32 AgentIndex, TSubclassOf<ANavigationData> NavigationDataClass);
|
|
|
|
public:
|
|
//----------------------------------------------------------------------//
|
|
//~ Begin Public querying Interface
|
|
//----------------------------------------------------------------------//
|
|
/**
|
|
* Synchronously looks for a path from @fLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified
|
|
* FNavAgentProperties will be found automatically
|
|
* @param ResultPath results are put here
|
|
* @param NavData optional navigation data that will be used instead of the one that would be deducted from AgentProperties
|
|
* @param Mode switch between normal and hierarchical path finding algorithms
|
|
*/
|
|
FPathFindingResult FindPathSync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular);
|
|
|
|
/**
|
|
* Does a simple path finding from @StartLocation to @EndLocation on specified NavData. If none passed MainNavData will be used
|
|
* Result gets placed in ResultPath
|
|
* @param NavData optional navigation data that will be used instead main navigation data
|
|
* @param Mode switch between normal and hierarchical path finding algorithms
|
|
*/
|
|
FPathFindingResult FindPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular);
|
|
|
|
/**
|
|
* Asynchronously looks for a path from @StartLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified
|
|
* FNavAgentProperties will be found automatically
|
|
* @param ResultDelegate delegate that will be called once query has been processed and finished. Will be called even if query fails - in such case see comments for delegate's params
|
|
* @param NavData optional navigation data that will be used instead of the one that would be deducted from AgentProperties
|
|
* @param PathToFill if points to an actual navigation path instance than this instance will be filled with resulting path. Otherwise a new instance will be created and
|
|
* used in call to ResultDelegate
|
|
* @param Mode switch between normal and hierarchical path finding algorithms
|
|
* @return request ID
|
|
*/
|
|
uint32 FindPathAsync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, const FNavPathQueryDelegate& ResultDelegate, EPathFindingMode::Type Mode = EPathFindingMode::Regular);
|
|
|
|
/** Removes query indicated by given ID from queue of path finding requests to process. */
|
|
void AbortAsyncFindPathRequest(uint32 AsynPathQueryID);
|
|
|
|
/**
|
|
* Synchronously check if path between two points exists
|
|
* Does not return path object, but will run faster (especially in hierarchical mode)
|
|
* @param Mode switch between normal and hierarchical path finding algorithms. @note Hierarchical mode ignores QueryFilter
|
|
* @return true if path exists
|
|
*/
|
|
bool TestPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular, int32* NumVisitedNodes = NULL) const;
|
|
|
|
/** Finds random point in navigable space
|
|
* @param ResultLocation Found point is put here
|
|
* @param NavData If NavData == NULL then MainNavData is used.
|
|
* @return true if any location found, false otherwise */
|
|
bool GetRandomPoint(FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL);
|
|
|
|
/** Finds random, reachable point in navigable space restricted to Radius around Origin
|
|
* @param ResultLocation Found point is put here
|
|
* @param NavData If NavData == NULL then MainNavData is used.
|
|
* @return true if any location found, false otherwise */
|
|
bool GetRandomReachablePointInRadius(const FVector& Origin, float Radius, FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
/** Finds random, point in navigable space restricted to Radius around Origin. Resulting location is not tested for reachability from the Origin
|
|
* @param ResultLocation Found point is put here
|
|
* @param NavData If NavData == NULL then MainNavData is used.
|
|
* @return true if any location found, false otherwise */
|
|
bool GetRandomPointInNavigableRadius(const FVector& Origin, float Radius, FNavLocation& ResultLocation, ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
/** Calculates a path from PathStart to PathEnd and retrieves its cost.
|
|
* @NOTE potentially expensive, so use it with caution */
|
|
ENavigationQueryResult::Type GetPathCost(const FVector& PathStart, const FVector& PathEnd, float& PathCost, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
/** Calculates a path from PathStart to PathEnd and retrieves its overestimated length.
|
|
* @NOTE potentially expensive, so use it with caution */
|
|
ENavigationQueryResult::Type GetPathLength(const FVector& PathStart, const FVector& PathEnd, float& PathLength, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
/** Calculates a path from PathStart to PathEnd and retrieves its overestimated length and cost.
|
|
* @NOTE potentially expensive, so use it with caution */
|
|
ENavigationQueryResult::Type GetPathLengthAndCost(const FVector& PathStart, const FVector& PathEnd, float& PathLength, float& PathCost, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
// @todo document
|
|
bool ProjectPointToNavigation(const FVector& Point, FNavLocation& OutLocation, const FVector& Extent = INVALID_NAVEXTENT, const FNavAgentProperties* AgentProperties = NULL, FSharedConstNavQueryFilter QueryFilter = NULL)
|
|
{
|
|
return ProjectPointToNavigation(Point, OutLocation, Extent, AgentProperties != NULL ? GetNavDataForProps(*AgentProperties) : GetDefaultNavDataInstance(FNavigationSystem::DontCreate), QueryFilter);
|
|
}
|
|
|
|
// @todo document
|
|
bool ProjectPointToNavigation(const FVector& Point, FNavLocation& OutLocation, const FVector& Extent = INVALID_NAVEXTENT, const ANavigationData* NavData = NULL, FSharedConstNavQueryFilter QueryFilter = NULL) const;
|
|
|
|
/**
|
|
* Looks for NavData generated for specified movement properties and returns it. NULL if not found;
|
|
*/
|
|
ANavigationData* GetNavDataForProps(const FNavAgentProperties& AgentProperties);
|
|
|
|
/**
|
|
* Looks for NavData generated for specified movement properties and returns it. NULL if not found; Const version.
|
|
*/
|
|
const ANavigationData* GetNavDataForProps(const FNavAgentProperties& AgentProperties) const;
|
|
|
|
/** Returns the world default navigation data instance. Creates one if it doesn't exist. */
|
|
ANavigationData* GetDefaultNavDataInstance(FNavigationSystem::ECreateIfMissing CreateNewIfNoneFound);
|
|
/** Returns the world default navigation data instance. */
|
|
virtual INavigationDataInterface* GetMainNavData() const override { return Cast<INavigationDataInterface>(GetDefaultNavDataInstance()); }
|
|
ANavigationData& GetMainNavDataChecked() const { check(MainNavData); return *MainNavData; }
|
|
|
|
ANavigationData* GetDefaultNavDataInstance() const { return MainNavData; }
|
|
|
|
ANavigationData* GetAbstractNavData() const { return AbstractNavData; }
|
|
|
|
/** constructs a navigation data instance of specified NavDataClass, in passed World
|
|
* for supplied NavConfig */
|
|
virtual ANavigationData* CreateNavigationDataInstance(const FNavDataConfig& NavConfig);
|
|
|
|
FSharedNavQueryFilter CreateDefaultQueryFilterCopy() const;
|
|
|
|
/** Super-hacky safety feature for threaded navmesh building. Will be gone once figure out why keeping TSharedPointer to Navigation Generator doesn't
|
|
* guarantee its existence */
|
|
bool ShouldGeneratorRun(const FNavDataGenerator* Generator) const;
|
|
|
|
virtual bool IsNavigationBuilt(const AWorldSettings* Settings) const override;
|
|
|
|
virtual bool IsThereAnywhereToBuildNavigation() const;
|
|
|
|
bool ShouldGenerateNavigationEverywhere() const { return bWholeWorldNavigable; }
|
|
|
|
bool ShouldAllowClientSideNavigation() const { return bAllowClientSideNavigation; }
|
|
virtual bool ShouldLoadNavigationOnClient(ANavigationData* NavData = nullptr) const { return bAllowClientSideNavigation; }
|
|
virtual bool ShouldDiscardSubLevelNavData(ANavigationData* NavData = nullptr) const { return bShouldDiscardSubLevelNavData; }
|
|
|
|
FBox GetWorldBounds() const;
|
|
|
|
FBox GetLevelBounds(ULevel* InLevel) const;
|
|
|
|
bool IsNavigationRelevant(const AActor* TestActor) const;
|
|
|
|
const TSet<FNavigationBounds>& GetNavigationBounds() const;
|
|
|
|
static const FNavDataConfig& GetDefaultSupportedAgent();
|
|
FORCEINLINE const FNavDataConfig& GetDefaultSupportedAgentConfig() const { check(SupportedAgents.Num() > 0); return SupportedAgents[0]; }
|
|
FORCEINLINE const TArray<FNavDataConfig>& GetSupportedAgents() const { return SupportedAgents; }
|
|
void OverrideSupportedAgents(const TArray<FNavDataConfig>& NewSupportedAgents);
|
|
|
|
virtual void ApplyWorldOffset(const FVector& InOffset, bool bWorldShift) override;
|
|
|
|
/** checks if navigation/navmesh is dirty and needs to be rebuilt */
|
|
bool IsNavigationDirty() const;
|
|
|
|
/** checks if dirty navigation data can rebuild itself */
|
|
bool CanRebuildDirtyNavigation() const;
|
|
|
|
FORCEINLINE bool SupportsNavigationGeneration() const { return bSupportRebuilding; }
|
|
|
|
static bool DoesPathIntersectBox(const FNavigationPath* Path, const FBox& Box, uint32 StartingIndex = 0, FVector* AgentExtent = NULL);
|
|
static bool DoesPathIntersectBox(const FNavigationPath* Path, const FBox& Box, const FVector& AgentLocation, uint32 StartingIndex = 0, FVector* AgentExtent = NULL);
|
|
|
|
//----------------------------------------------------------------------//
|
|
// Active tiles
|
|
//----------------------------------------------------------------------//
|
|
virtual void RegisterInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius);
|
|
virtual void UnregisterInvoker(AActor& Invoker);
|
|
|
|
static void RegisterNavigationInvoker(AActor& Invoker, float TileGenerationRadius, float TileRemovalRadius);
|
|
static void UnregisterNavigationInvoker(AActor& Invoker);
|
|
|
|
const TArray<FNavigationInvokerRaw>& GetInvokerLocations() const { return InvokerLocations; }
|
|
|
|
//----------------------------------------------------------------------//
|
|
// Bookkeeping
|
|
//----------------------------------------------------------------------//
|
|
|
|
// @todo document
|
|
virtual void UnregisterNavData(ANavigationData* NavData);
|
|
|
|
/** adds NavData to registration candidates queue - NavDataRegistrationQueue
|
|
* @return true if registration request was successful, false if given NavData
|
|
* was deemed unsuitable for registration consideration */
|
|
virtual void RequestRegistration(ANavigationData* NavData, bool bTriggerRegistrationProcessing = true);
|
|
|
|
protected:
|
|
|
|
/** Processes all NavigationData instances in UWorld owning navigation system instance, and registers
|
|
* all previously unregistered */
|
|
void RegisterNavigationDataInstances();
|
|
|
|
/** called in places where we need to spawn the NavOctree, but is checking additional conditions if we really want to do that
|
|
* depending on navigation data setup among others
|
|
* @return true if NavOctree instance has been created, or if one is already present */
|
|
bool ConditionalPopulateNavOctree();
|
|
|
|
/** Processes registration of candidates queues via RequestRegistration and stored in NavDataRegistrationQueue */
|
|
virtual void ProcessRegistrationCandidates();
|
|
|
|
/** registers CustomLinks awaiting registration in PendingCustomLinkRegistration */
|
|
void ProcessCustomLinkPendingRegistration();
|
|
|
|
/** used to apply updates of nav volumes in navigation system's tick */
|
|
void PerformNavigationBoundsUpdate(const TArray<FNavigationBoundsUpdateRequest>& UpdateRequests);
|
|
|
|
/** adds data to RegisteredNavBounds */
|
|
void AddNavigationBounds(const FNavigationBounds& NewBounds);
|
|
|
|
/** Searches for all valid navigation bounds in the world and stores them */
|
|
virtual void GatherNavigationBounds();
|
|
|
|
/** @return pointer to ANavigationData instance of given ID, or NULL if it was not found. Note it looks only through registered navigation data */
|
|
ANavigationData* GetNavDataWithID(const uint16 NavDataID) const;
|
|
|
|
public:
|
|
virtual void ReleaseInitialBuildingLock();
|
|
|
|
//----------------------------------------------------------------------//
|
|
// navigation octree related functions
|
|
//----------------------------------------------------------------------//
|
|
static void OnComponentRegistered(UActorComponent* Comp);
|
|
static void OnComponentUnregistered(UActorComponent* Comp);
|
|
static void OnActorRegistered(AActor* Actor);
|
|
static void OnActorUnregistered(AActor* Actor);
|
|
|
|
/** update navoctree entry for specified actor/component */
|
|
static void UpdateActorInNavOctree(AActor& Actor);
|
|
static void UpdateComponentInNavOctree(UActorComponent& Comp);
|
|
/** update all navoctree entries for actor and its components */
|
|
static void UpdateActorAndComponentsInNavOctree(AActor& Actor, bool bUpdateAttachedActors = true);
|
|
/** update all navoctree entries for actor and its non scene components after root movement */
|
|
static void UpdateNavOctreeAfterMove(USceneComponent* Comp);
|
|
|
|
protected:
|
|
/** updates navoctree information on actors attached to RootActor */
|
|
static void UpdateAttachedActorsInNavOctree(AActor& RootActor);
|
|
|
|
public:
|
|
/** removes all navoctree entries for actor and its components */
|
|
static void ClearNavOctreeAll(AActor* Actor);
|
|
/** updates bounds of all components implementing INavRelevantInterface */
|
|
static void UpdateNavOctreeBounds(AActor* Actor);
|
|
|
|
virtual void AddDirtyArea(const FBox& NewArea, int32 Flags);
|
|
void AddDirtyAreas(const TArray<FBox>& NewAreas, int32 Flags);
|
|
bool HasDirtyAreasQueued() const;
|
|
|
|
const FNavigationOctree* GetNavOctree() const { return NavOctree.Get(); }
|
|
FNavigationOctree* GetMutableNavOctree() { return NavOctree.Get(); }
|
|
|
|
FORCEINLINE static uint32 HashObject(const UObject& Object)
|
|
{
|
|
return Object.GetUniqueID();
|
|
}
|
|
FORCEINLINE void SetObjectsNavOctreeId(const UObject& Object, FOctreeElementId Id) { ObjectToOctreeId.Add(HashObject(Object), Id); }
|
|
FORCEINLINE const FOctreeElementId* GetObjectsNavOctreeId(const UObject& Object) const { return ObjectToOctreeId.Find(HashObject(Object)); }
|
|
FORCEINLINE bool HasPendingObjectNavOctreeId(UObject* Object) const { return PendingOctreeUpdates.Contains(FNavigationDirtyElement(Object)); }
|
|
FORCEINLINE void RemoveObjectsNavOctreeId(const UObject& Object) { ObjectToOctreeId.Remove(HashObject(Object)); }
|
|
|
|
void RemoveNavOctreeElementId(const FOctreeElementId& ElementId, int32 UpdateFlags);
|
|
|
|
const FNavigationRelevantData* GetDataForObject(const UObject& Object) const;
|
|
FNavigationRelevantData* GetMutableDataForObject(const UObject& Object);
|
|
|
|
/** find all elements in navigation octree within given box (intersection) */
|
|
void FindElementsInNavOctree(const FBox& QueryBox, const FNavigationOctreeFilter& Filter, TArray<FNavigationOctreeElement>& Elements);
|
|
|
|
/** update single element in navoctree */
|
|
void UpdateNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags);
|
|
|
|
/** force updating parent node and all its children */
|
|
void UpdateNavOctreeParentChain(UObject* ElementOwner, bool bSkipElementOwnerUpdate = false);
|
|
|
|
/** update component bounds in navigation octree and mark only specified area as dirty, doesn't re-export component geometry */
|
|
bool UpdateNavOctreeElementBounds(UActorComponent* Comp, const FBox& NewBounds, const FBox& DirtyArea);
|
|
|
|
/** fetched Object's data from the octree and replaces occurences of OldArea with NewArea */
|
|
bool ReplaceAreaInOctreeData(const UObject& Object, TSubclassOf<UNavArea> OldArea, TSubclassOf<UNavArea> NewArea, bool bReplaceChildClasses = false);
|
|
|
|
//----------------------------------------------------------------------//
|
|
// Custom navigation links
|
|
//----------------------------------------------------------------------//
|
|
void RegisterCustomLink(INavLinkCustomInterface& CustomLink);
|
|
void UnregisterCustomLink(INavLinkCustomInterface& CustomLink);
|
|
|
|
static void RequestCustomLinkRegistering(INavLinkCustomInterface& CustomLink, UObject* OwnerOb);
|
|
static void RequestCustomLinkUnregistering(INavLinkCustomInterface& CustomLink, UObject* ObjectOb);
|
|
|
|
/** find custom link by unique ID */
|
|
INavLinkCustomInterface* GetCustomLink(uint32 UniqueLinkId) const;
|
|
|
|
/** updates custom link for all active navigation data instances */
|
|
void UpdateCustomLink(const INavLinkCustomInterface* CustomLink);
|
|
|
|
//----------------------------------------------------------------------//
|
|
// Areas
|
|
//----------------------------------------------------------------------//
|
|
static void RequestAreaRegistering(UClass* NavAreaClass);
|
|
static void RequestAreaUnregistering(UClass* NavAreaClass);
|
|
|
|
/** find index in SupportedAgents array for given navigation data */
|
|
int32 GetSupportedAgentIndex(const ANavigationData* NavData) const;
|
|
|
|
/** find index in SupportedAgents array for agent type */
|
|
int32 GetSupportedAgentIndex(const FNavAgentProperties& NavAgent) const;
|
|
|
|
//----------------------------------------------------------------------//
|
|
// Filters
|
|
//----------------------------------------------------------------------//
|
|
|
|
/** prepare descriptions of navigation flags in UNavigationQueryFilter class: using enum */
|
|
void DescribeFilterFlags(UEnum* FlagsEnum) const;
|
|
|
|
/** prepare descriptions of navigation flags in UNavigationQueryFilter class: using array */
|
|
void DescribeFilterFlags(const TArray<FString>& FlagsDesc) const;
|
|
|
|
/** removes cached filters from currently registered navigation data */
|
|
void ResetCachedFilter(TSubclassOf<UNavigationQueryFilter> FilterClass);
|
|
|
|
//----------------------------------------------------------------------//
|
|
// building
|
|
//----------------------------------------------------------------------//
|
|
|
|
/** Triggers navigation building on all eligible navigation data. */
|
|
virtual void Build();
|
|
|
|
/** Cancels all currently running navigation builds */
|
|
virtual void CancelBuild();
|
|
|
|
// @todo document
|
|
void OnPIEStart();
|
|
// @todo document
|
|
void OnPIEEnd();
|
|
|
|
// @todo document
|
|
FORCEINLINE bool IsNavigationBuildingLocked() const { return NavBuildingLockFlags != 0; }
|
|
|
|
/** check if building is permanently locked to avoid showing navmesh building notify (due to queued dirty areas) */
|
|
FORCEINLINE bool IsNavigationBuildingPermanentlyLocked() const
|
|
{
|
|
return (NavBuildingLockFlags & ~ENavigationBuildLock::InitialLock) != 0;
|
|
}
|
|
|
|
/** check if navigation octree updates are currently ignored */
|
|
FORCEINLINE bool IsNavigationOctreeLocked() const { return bNavOctreeLock; }
|
|
|
|
// @todo document
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation")
|
|
void OnNavigationBoundsUpdated(ANavMeshBoundsVolume* NavVolume);
|
|
virtual void OnNavigationBoundsAdded(ANavMeshBoundsVolume* NavVolume);
|
|
void OnNavigationBoundsRemoved(ANavMeshBoundsVolume* NavVolume);
|
|
|
|
/** Used to display "navigation building in progress" notify */
|
|
bool IsNavigationBuildInProgress(bool bCheckDirtyToo = true);
|
|
|
|
virtual void OnNavigationGenerationFinished(ANavigationData& NavData);
|
|
|
|
/** Used to display "navigation building in progress" counter */
|
|
int32 GetNumRemainingBuildTasks() const;
|
|
|
|
/** Number of currently running tasks */
|
|
int32 GetNumRunningBuildTasks() const;
|
|
|
|
protected:
|
|
/** Sets up SuportedAgents and NavigationDataCreators. Override it to add additional setup, but make sure to call Super implementation */
|
|
virtual void DoInitialSetup();
|
|
|
|
/** spawn new crowd manager */
|
|
virtual void UpdateAbstractNavData();
|
|
|
|
/** Called when ConditionalPopulateNavOctree processes each Actor */
|
|
virtual void ConditionalPopulateNavOctreeActor(AActor& Actor);
|
|
|
|
public:
|
|
/** Called upon UWorld destruction to release what needs to be released */
|
|
virtual void CleanUp(const FNavigationSystem::ECleanupMode Mode = FNavigationSystem::ECleanupMode::CleanupUnsafe) override;
|
|
|
|
/**
|
|
* Called when owner-UWorld initializes actors
|
|
*/
|
|
virtual void OnInitializeActors() override;
|
|
|
|
/** */
|
|
virtual void OnWorldInitDone(FNavigationSystemRunMode Mode);
|
|
|
|
FORCEINLINE bool IsInitialized() const { return bWorldInitDone; }
|
|
|
|
/** adds BSP collisions of currently streamed in levels to octree */
|
|
void InitializeLevelCollisions();
|
|
|
|
FORCEINLINE void AddNavigationBuildLock(uint8 Flags) { NavBuildingLockFlags |= Flags; }
|
|
void RemoveNavigationBuildLock(uint8 Flags, bool bSkipRebuildInEditor = false);
|
|
|
|
void SetNavigationOctreeLock(bool bLock) { bNavOctreeLock = bLock; }
|
|
|
|
/** checks if auto-rebuilding navigation data is enabled. Defaults to bNavigationAutoUpdateEnabled
|
|
* value, but can be overridden per nav sys instance */
|
|
virtual bool GetIsAutoUpdateEnabled() const { return bNavigationAutoUpdateEnabled; }
|
|
|
|
#if WITH_EDITOR
|
|
/** allow editor to toggle whether seamless navigation building is enabled */
|
|
static void SetNavigationAutoUpdateEnabled(bool bNewEnable, UNavigationSystemBase* InNavigationSystem);
|
|
|
|
FORCEINLINE bool IsNavigationRegisterLocked() const { return NavUpdateLockFlags != 0; }
|
|
FORCEINLINE bool IsNavigationUnregisterLocked() const { return NavUpdateLockFlags && !(NavUpdateLockFlags & ENavigationLockReason::AllowUnregister); }
|
|
FORCEINLINE bool IsNavigationUpdateLocked() const { return IsNavigationRegisterLocked(); }
|
|
FORCEINLINE void AddNavigationUpdateLock(uint8 Flags) { NavUpdateLockFlags |= Flags; }
|
|
FORCEINLINE void RemoveNavigationUpdateLock(uint8 Flags) { NavUpdateLockFlags &= ~Flags; }
|
|
|
|
void UpdateLevelCollision(ULevel* InLevel);
|
|
|
|
virtual void OnEditorModeChanged(FEdMode* Mode, bool IsEntering);
|
|
#endif // WITH_EDITOR
|
|
|
|
FORCEINLINE bool IsSetUpForLazyGeometryExporting() const { return bGenerateNavigationOnlyAroundNavigationInvokers; }
|
|
|
|
static UNavigationSystemV1* CreateNavigationSystem(UWorld* WorldOwner);
|
|
|
|
static UNavigationSystemV1* GetCurrent(UWorld* World);
|
|
static UNavigationSystemV1* GetCurrent(UObject* WorldContextObject);
|
|
|
|
virtual void InitializeForWorld(UWorld& World, FNavigationSystemRunMode Mode) override;
|
|
|
|
// Fetch the array of all nav-agent properties.
|
|
void GetNavAgentPropertiesArray(TArray<FNavAgentProperties>& OutNavAgentProperties) const;
|
|
|
|
static FORCEINLINE bool ShouldUpdateNavOctreeOnComponentChange()
|
|
{
|
|
return (bUpdateNavOctreeOnComponentChange && !bStaticRuntimeNavigation)
|
|
#if WITH_EDITOR
|
|
|| (GIsEditor && !GIsPlayInEditorWorld)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
static FORCEINLINE bool IsNavigationSystemStatic()
|
|
{
|
|
return bStaticRuntimeNavigation
|
|
#if WITH_EDITOR
|
|
&& !(GIsEditor && !GIsPlayInEditorWorld)
|
|
#endif
|
|
;
|
|
}
|
|
|
|
/** Use this function to signal the NavigationSystem it doesn't need to store
|
|
* any navigation-generation-related data at game runtime, because
|
|
* nothing is going to use it anyway. This will short-circuit all code related
|
|
* to navmesh rebuilding, so use it only if you have fully static navigation in
|
|
* your game.
|
|
* Note: this is not a runtime switch. Call it before any actual game starts. */
|
|
static void ConfigureAsStatic();
|
|
|
|
static void SetUpdateNavOctreeOnComponentChange(bool bNewUpdateOnComponentChange);
|
|
|
|
/**
|
|
* Exec command handlers
|
|
*/
|
|
bool HandleCycleNavDrawnCommand( const TCHAR* Cmd, FOutputDevice& Ar );
|
|
bool HandleCountNavMemCommand();
|
|
|
|
//----------------------------------------------------------------------//
|
|
// debug
|
|
//----------------------------------------------------------------------//
|
|
void CycleNavigationDataDrawn();
|
|
|
|
protected:
|
|
|
|
UPROPERTY()
|
|
FNavigationSystemRunMode OperationMode;
|
|
|
|
TSharedPtr<FNavigationOctree, ESPMode::ThreadSafe> NavOctree;
|
|
|
|
TArray<FAsyncPathFindingQuery> AsyncPathFindingQueries;
|
|
|
|
FCriticalSection NavDataRegistration;
|
|
|
|
TMap<FNavAgentProperties, TWeakObjectPtr<ANavigationData> > AgentToNavDataMap;
|
|
|
|
TMap<uint32, FOctreeElementId> ObjectToOctreeId;
|
|
|
|
/** Map of all objects that are tied to indexed navigation parent */
|
|
TMultiMap<UObject*, FWeakObjectPtr> OctreeChildNodesMap;
|
|
|
|
/** Map of all custom navigation links, that are relevant for path following */
|
|
TMap<uint32, FNavigationSystem::FCustomLinkOwnerInfo> CustomLinksMap;
|
|
|
|
/** stores areas marked as dirty throughout the frame, processes them
|
|
* once a frame in Tick function */
|
|
TArray<FNavigationDirtyArea> DirtyAreas;
|
|
|
|
// async queries
|
|
FCriticalSection NavDataRegistrationSection;
|
|
static FCriticalSection CustomLinkRegistrationSection;
|
|
|
|
#if WITH_EDITOR
|
|
uint8 NavUpdateLockFlags;
|
|
#endif
|
|
uint8 NavBuildingLockFlags;
|
|
|
|
/** set of locking flags applied on startup of navigation system */
|
|
uint8 InitialNavBuildingLockFlags;
|
|
|
|
/** if set, navoctree updates are ignored, use with caution! */
|
|
uint8 bNavOctreeLock : 1;
|
|
|
|
uint8 bInitialSetupHasBeenPerformed : 1;
|
|
uint8 bInitialLevelsAdded : 1;
|
|
uint8 bWorldInitDone : 1;
|
|
uint8 bAsyncBuildPaused : 1; // mz@todo remove, replaced by bIsPIEActive and IsGameWorld
|
|
uint8 bCanAccumulateDirtyAreas : 1;
|
|
#if !UE_BUILD_SHIPPING
|
|
uint8 bDirtyAreasReportedWhileAccumulationLocked : 1;
|
|
#endif // !UE_BUILD_SHIPPING
|
|
|
|
/** cached navigable world bounding box*/
|
|
mutable FBox NavigableWorldBounds;
|
|
|
|
/** indicates which of multiple navigation data instances to draw*/
|
|
int32 CurrentlyDrawnNavDataIndex;
|
|
|
|
/** temporary cumulative time to calculate when we need to update dirty areas */
|
|
float DirtyAreasUpdateTime;
|
|
|
|
#if !UE_BUILD_SHIPPING
|
|
/** self-registering exec command to handle nav sys console commands */
|
|
static FNavigationSystemExec ExecHandler;
|
|
#endif // !UE_BUILD_SHIPPING
|
|
|
|
/** whether seamless navigation building is enabled */
|
|
static bool bNavigationAutoUpdateEnabled;
|
|
static bool bUpdateNavOctreeOnComponentChange;
|
|
static bool bStaticRuntimeNavigation;
|
|
static bool bIsPIEActive;
|
|
|
|
static TMap<INavLinkCustomInterface*, FWeakObjectPtr> PendingCustomLinkRegistration;
|
|
TSet<const UClass*> NavAreaClasses;
|
|
|
|
/** delegate handler for PostLoadMap event */
|
|
void OnPostLoadMap(UWorld* LoadedWorld);
|
|
#if WITH_EDITOR
|
|
/** delegate handler for ActorMoved events */
|
|
void OnActorMoved(AActor* Actor);
|
|
#endif
|
|
/** delegate handler called when navigation is dirtied*/
|
|
void OnNavigationDirtied(const FBox& Bounds);
|
|
|
|
#if WITH_HOT_RELOAD
|
|
FDelegateHandle HotReloadDelegateHandle;
|
|
|
|
/** called to notify NavigaitonSystem about finished hot reload */
|
|
virtual void OnHotReload(bool bWasTriggeredAutomatically);
|
|
#endif // WITH_HOT_RELOAD
|
|
|
|
/** Registers given navigation data with this Navigation System.
|
|
* @return RegistrationSuccessful if registration was successful, other results mean it failed
|
|
* @see ERegistrationResult
|
|
*/
|
|
virtual ERegistrationResult RegisterNavData(ANavigationData* NavData);
|
|
|
|
/** tries to register navigation area */
|
|
void RegisterNavAreaClass(UClass* NavAreaClass);
|
|
|
|
/** tries to unregister navigation area */
|
|
void UnregisterNavAreaClass(UClass* NavAreaClass);
|
|
|
|
void OnNavigationAreaEvent(UClass* AreaClass, ENavAreaEvent::Type Event);
|
|
|
|
FSetElementId RegisterNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags);
|
|
void UnregisterNavOctreeElement(UObject* ElementOwner, INavRelevantInterface* ElementInterface, int32 UpdateFlags);
|
|
|
|
/** read element data from navigation octree */
|
|
bool GetNavOctreeElementData(const UObject& NodeOwner, int32& DirtyFlags, FBox& DirtyBounds);
|
|
//bool GetNavOctreeElementData(UObject* NodeOwner, int32& DirtyFlags, FBox& DirtyBounds);
|
|
|
|
/** Adds given element to NavOctree. No check for owner's validity are performed,
|
|
* nor its presence in NavOctree - function assumes callee responsibility
|
|
* in this regard **/
|
|
void AddElementToNavOctree(const FNavigationDirtyElement& DirtyElement);
|
|
|
|
void SetCrowdManager(UCrowdManagerBase* NewCrowdManager);
|
|
|
|
/** Add BSP collision data to navigation octree */
|
|
void AddLevelCollisionToOctree(ULevel* Level);
|
|
|
|
/** Remove BSP collision data from navigation octree */
|
|
void RemoveLevelCollisionFromOctree(ULevel* Level);
|
|
|
|
virtual void SpawnMissingNavigationData();
|
|
|
|
private:
|
|
// adds navigation bounds update request to a pending list
|
|
void AddNavigationBoundsUpdateRequest(const FNavigationBoundsUpdateRequest& UpdateRequest);
|
|
|
|
/** Triggers navigation building on all eligible navigation data. */
|
|
void RebuildAll(bool bIsLoadTime = false);
|
|
|
|
/** Handler for FWorldDelegates::LevelAddedToWorld event */
|
|
void OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld);
|
|
|
|
/** Handler for FWorldDelegates::LevelRemovedFromWorld event */
|
|
void OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld);
|
|
|
|
/** Adds given request to requests queue. Note it's to be called only on game thread only */
|
|
void AddAsyncQuery(const FAsyncPathFindingQuery& Query);
|
|
|
|
/** spawns a non-game-thread task to process requests given in PathFindingQueries.
|
|
* In the process PathFindingQueries gets copied. */
|
|
void TriggerAsyncQueries(TArray<FAsyncPathFindingQuery>& PathFindingQueries);
|
|
|
|
/** Processes pathfinding requests given in PathFindingQueries.*/
|
|
void PerformAsyncQueries(TArray<FAsyncPathFindingQuery> PathFindingQueries);
|
|
|
|
/** */
|
|
void DestroyNavOctree();
|
|
|
|
/** Whether Navigation system needs to populate nav octree.
|
|
* Depends on runtime generation settings of each navigation data, always true in the editor
|
|
*/
|
|
bool RequiresNavOctree() const;
|
|
|
|
/** Return "Strongest" runtime generation type required by registered navigation data objects
|
|
* Depends on runtime generation settings of each navigation data, always ERuntimeGenerationType::Dynamic in the editor world
|
|
*/
|
|
ERuntimeGenerationType GetRuntimeGenerationType() const;
|
|
|
|
//----------------------------------------------------------------------//
|
|
// new stuff
|
|
//----------------------------------------------------------------------//
|
|
public:
|
|
void VerifyNavigationRenderingComponents(const bool bShow);
|
|
virtual int GetNavigationBoundsForNavData(const ANavigationData& NavData, TArray<FBox>& OutBounds) const;
|
|
static INavigationDataInterface* GetNavDataForActor(const AActor& Actor);
|
|
virtual void Configure(const UNavigationSystemConfig& Config);
|
|
|
|
#if !UE_BUILD_SHIPPING
|
|
void GetOnScreenMessages(TMultiMap<FCoreDelegates::EOnScreenMessageSeverity, FText>& OutMessages);
|
|
#endif // !UE_BUILD_SHIPPING
|
|
|
|
//----------------------------------------------------------------------//
|
|
// DEPRECATED
|
|
//----------------------------------------------------------------------//
|
|
public:
|
|
UE_DEPRECATED(4.16, "This version of ProjectPointToNavigation is deprecated. Please use the new version")
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "ProjectPointToNavigation_DEPRECATED", ScriptNoExport, DeprecatedFunction, DeprecationMessage = "This version of ProjectPointToNavigation is deprecated. Please use the new version"))
|
|
static FVector ProjectPointToNavigation(UObject* WorldContextObject, const FVector& Point, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL, const FVector QueryExtent = FVector::ZeroVector);
|
|
UE_DEPRECATED(4.16, "This version of GetRandomReachablePointInRadius is deprecated. Please use the new version")
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomReachablePointInRadius_DEPRECATED", ScriptNoExport, DeprecatedFunction, DeprecationMessage = "This version of GetRandomReachablePointInRadius is deprecated. Please use the new version"))
|
|
static FVector GetRandomReachablePointInRadius(UObject* WorldContextObject, const FVector& Origin, float Radius, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
UE_DEPRECATED(4.16, "This version of GetRandomPointInNavigableRadius is deprecated. Please use the new version")
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomPointInNavigableRadius_DEPRECATED", ScriptNoExport, DeprecatedFunction, DeprecationMessage = "This version of GetRandomPointInNavigableRadius is deprecated. Please use the new version"))
|
|
static FVector GetRandomPointInNavigableRadius(UObject* WorldContextObject, const FVector& Origin, float Radius, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
UE_DEPRECATED(4.20, "SimpleMoveToActor is deprecated. Use UAIBlueprintHelperLibrary::SimpleMoveToActor instead")
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (DisplayName = "SimpleMoveToActor_DEPRECATED", ScriptNoExport, DeprecatedFunction, DeprecationMessage = "SimpleMoveToActor is deprecated. Use AIBlueprintHelperLibrary::SimpleMoveToActor instead"))
|
|
static void SimpleMoveToActor(AController* Controller, const AActor* Goal);
|
|
UE_DEPRECATED(4.20, "SimpleMoveToLocation is deprecated. Use UAIBlueprintHelperLibrary::SimpleMoveToLocation instead")
|
|
UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (DisplayName = "SimpleMoveToLocation_DEPRECATED", ScriptNoExport, DeprecatedFunction, DeprecationMessage = "SimpleMoveToLocation is deprecated. Use AIBlueprintHelperLibrary::SimpleMoveToLocation instead"))
|
|
static void SimpleMoveToLocation(AController* Controller, const FVector& Goal);
|
|
UE_DEPRECATED(4.20, "UNavigationSystem::GetDefaultWalkableArea is deprecated. Use FNavigationSystem::GetDefaultWalkableArea instead")
|
|
static TSubclassOf<UNavAreaBase> GetDefaultWalkableArea() { return FNavigationSystem::GetDefaultWalkableArea(); }
|
|
UE_DEPRECATED(4.20, "UNavigationSystem::GetDefaultObstacleArea is deprecated. Use FNavigationSystem::GetDefaultObstacleArea instead")
|
|
static TSubclassOf<UNavAreaBase> GetDefaultObstacleArea() { return FNavigationSystem::GetDefaultObstacleArea(); }
|
|
UE_DEPRECATED(4.22, "This version is deprecated. Please use GetRandomLocationInNavigableRadius instead")
|
|
UFUNCTION(BlueprintPure, Category = "AI|Navigation", meta = (WorldContext = "WorldContextObject", DisplayName = "GetRandomPointInNavigableRadius", ScriptName = "GetRandomPointInNavigableRadius"))
|
|
static bool K2_GetRandomPointInNavigableRadius(UObject* WorldContextObject, const FVector& Origin, FVector& RandomLocation, float Radius, ANavigationData* NavData = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);
|
|
};
|
|
|
|
//----------------------------------------------------------------------//
|
|
// UNavigationSystemModuleConfig
|
|
//----------------------------------------------------------------------//
|
|
UCLASS()
|
|
class NAVIGATIONSYSTEM_API UNavigationSystemModuleConfig : public UNavigationSystemConfig
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
protected:
|
|
/** Whether at game runtime we expect any kind of dynamic navigation generation */
|
|
UPROPERTY(EditAnywhere, Category = Navigation)
|
|
uint32 bStrictlyStatic : 1;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Navigation)
|
|
uint32 bCreateOnClient : 1;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Navigation)
|
|
uint32 bAutoSpawnMissingNavData : 1;
|
|
|
|
UPROPERTY(EditAnywhere, Category = Navigation)
|
|
uint32 bSpawnNavDataInNavBoundsLevel : 1;
|
|
|
|
public:
|
|
UNavigationSystemModuleConfig(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
|
|
|
virtual void PostInitProperties() override;
|
|
|
|
virtual UNavigationSystemBase* CreateAndConfigureNavigationSystem(UWorld& World) const override;
|
|
|
|
#if WITH_EDITOR
|
|
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
|
#endif // WITH_EDITOR
|
|
|
|
protected:
|
|
#if WITH_EDITOR
|
|
friend UNavigationSystemV1;
|
|
#endif // WITH_EDITOR
|
|
void UpdateWithNavSysCDO(const UNavigationSystemV1& NavSysCDO);
|
|
};
|