Files
UnrealEngineUWP/Engine/Source/Runtime/NavigationSystem/Private/NavSystemConfigOverride.cpp
mieszko zielinski c9c9e0790d Reorganized how we configure SupportedAgents. From now on every NavigationSystem instance has data on the full set of SupportedAgents (as configured via ProjectSettings) but also has a SupportedAgentsMask, that marks agents supported by the instance. It has been done this way to keep filtered per-agent NavMeshBoundVolumes work regardless of which supported agents a nav sys instance wants to support.
This approach allowed for easy NavigationSystem's config update with NavSystemConfigOverride's properties. NavSystemConfigOverride can now specify if it wants to fully override the pre-existing nav sys instance or if it just wants to append new information (like supported agents) to the existing navigation system instance. There's also an option to do nothing if there's already a navigation system present.

This CL rolls-back a bunch of temp fixes done in past couple of days.

#rb Yoan.StAmant
Yoan.StAmant


#ROBOMERGE-OWNER: mieszko.zielinski
#ROBOMERGE-AUTHOR: mieszko.zielinski
#ROBOMERGE-SOURCE: CL 8187661 via CL 8193395 via CL 8207613
#ROBOMERGE-BOT: (v401-8057353)

[CL 8207758 by mieszko zielinski in Main branch]
2019-08-21 23:59:12 -04:00

190 lines
5.1 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
#include "NavSystemConfigOverride.h"
#include "Engine/World.h"
#include "GameFramework/WorldSettings.h"
#include "AI/NavigationSystemBase.h"
#include "NavigationSystem.h"
#include "TimerManager.h"
#if WITH_EDITORONLY_DATA
#include "UObject/ConstructorHelpers.h"
#include "Components/BillboardComponent.h"
#include "Engine/Texture2D.h"
#include "Editor.h"
#endif // WITH_EDITORONLY_DATA
ANavSystemConfigOverride::ANavSystemConfigOverride(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
USceneComponent* SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
RootComponent = SceneComponent;
RootComponent->Mobility = EComponentMobility::Static;
#if WITH_EDITORONLY_DATA
SpriteComponent = CreateEditorOnlyDefaultSubobject<UBillboardComponent>(TEXT("Sprite"));
if (!IsRunningCommandlet())
{
// Structure to hold one-time initialization
struct FConstructorStatics
{
ConstructorHelpers::FObjectFinderOptional<UTexture2D> NoteTextureObject;
FName ID_Notes;
FText NAME_Notes;
FConstructorStatics()
: NoteTextureObject(TEXT("/Engine/EditorResources/S_Note"))
, ID_Notes(TEXT("Notes"))
, NAME_Notes(NSLOCTEXT("SpriteCategory", "Notes", "Notes"))
{
}
};
static FConstructorStatics ConstructorStatics;
if (SpriteComponent)
{
SpriteComponent->Sprite = ConstructorStatics.NoteTextureObject.Get();
SpriteComponent->RelativeScale3D = FVector(0.5f, 0.5f, 0.5f);
SpriteComponent->SpriteInfo.Category = ConstructorStatics.ID_Notes;
SpriteComponent->SpriteInfo.DisplayName = ConstructorStatics.NAME_Notes;
SpriteComponent->SetupAttachment(RootComponent);
SpriteComponent->Mobility = EComponentMobility::Static;
}
}
#endif // WITH_EDITORONLY_DATA
bHidden = true;
bCanBeDamaged = false;
bNetLoadOnClient = false;
}
void ANavSystemConfigOverride::PostLoad()
{
Super::PostLoad();
UWorld* World = GetWorld();
if (World != nullptr)
{
if (World->bInTick)
{
World->GetTimerManager().SetTimerForNextTick(this, &ANavSystemConfigOverride::ApplyConfig);
}
else
{
ApplyConfig();
}
}
}
void ANavSystemConfigOverride::ApplyConfig()
{
UWorld* World = GetWorld();
if (World)
{
UNavigationSystemBase* PrevNavSys = World->GetNavigationSystem();
if (PrevNavSys == nullptr || OverridePolicy == ENavSystemOverridePolicy::Override)
{
OverrideNavSystem();
}
// PrevNavSys != null at this point
else if (OverridePolicy == ENavSystemOverridePolicy::Append)
{
// take the prev nav system and append data to it
AppendToNavSystem(*PrevNavSys);
}
// else PrevNavSys != null AND OverridePolicy == ENavSystemOverridePolicy::Skip, so ignoring the override
}
}
void ANavSystemConfigOverride::PostInitProperties()
{
Super::PostInitProperties();
}
void ANavSystemConfigOverride::AppendToNavSystem(UNavigationSystemBase& PrevNavSys)
{
if (NavigationSystemConfig)
{
PrevNavSys.AppendConfig(*NavigationSystemConfig);
}
}
void ANavSystemConfigOverride::OverrideNavSystem()
{
UWorld* World = GetWorld();
if (World == nullptr)
{
return;
}
AWorldSettings* WorldSetting = World->GetWorldSettings();
if (WorldSetting)
{
WorldSetting->SetNavigationSystemConfigOverride(NavigationSystemConfig);
}
if (World->bIsWorldInitialized
&& NavigationSystemConfig)
{
const FNavigationSystemRunMode RunMode = World->WorldType == EWorldType::Editor
? FNavigationSystemRunMode::EditorMode
: (World->WorldType == EWorldType::PIE
? FNavigationSystemRunMode::PIEMode
: FNavigationSystemRunMode::GameMode)
;
if (RunMode == FNavigationSystemRunMode::EditorMode)
{
FNavigationSystem::AddNavigationSystemToWorld(*World, RunMode, NavigationSystemConfig, /*bInitializeForWorld=*/false, /*bOverridePreviousNavSys=*/true);
#if WITH_EDITOR
UNavigationSystemBase* NewNavSys = World->GetNavigationSystem();
if (NewNavSys)
{
GEditor->GetTimerManager()->SetTimerForNextTick(FTimerDelegate::CreateUObject(this
, &ANavSystemConfigOverride::InitializeForWorld, NewNavSys, World, RunMode));
}
#endif // WITH_EDITOR
}
else
{
FNavigationSystem::AddNavigationSystemToWorld(*World, RunMode, NavigationSystemConfig, /*bInitializeForWorld=*/true, /*bOverridePreviousNavSys=*/true);
}
}
}
#if WITH_EDITOR
void ANavSystemConfigOverride::InitializeForWorld(UNavigationSystemBase* NewNavSys, UWorld* World, const FNavigationSystemRunMode RunMode)
{
if (NewNavSys && World)
{
NewNavSys->InitializeForWorld(*World, RunMode);
}
}
void ANavSystemConfigOverride::ApplyChanges()
{
UWorld* World = GetWorld();
if (World)
{
AWorldSettings* WorldSetting = World->GetWorldSettings();
if (WorldSetting)
{
WorldSetting->SetNavigationSystemConfigOverride(NavigationSystemConfig);
}
// recreate nav sys
World->SetNavigationSystem(nullptr);
FNavigationSystem::AddNavigationSystemToWorld(*World, FNavigationSystemRunMode::EditorMode, NavigationSystemConfig, /*bInitializeForWorld=*/true);
}
}
void ANavSystemConfigOverride::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
bNetLoadOnClient = bLoadOnClient;
}
#endif // WITH_EDITOR