2020-01-17 08:59:21 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "LandscapeSubsystem.h"
# include "UObject/UObjectGlobals.h"
# include "Engine/EngineBaseTypes.h"
2020-01-17 10:17:06 -05:00
# include "Engine/World.h"
2020-01-22 14:16:42 -05:00
# include "ContentStreaming.h"
# include "Landscape.h"
2020-04-27 16:16:09 -04:00
# include "LandscapeProxy.h"
2020-09-24 10:42:45 -04:00
# include "LandscapeStreamingProxy.h"
# include "LandscapeInfo.h"
2020-01-20 19:32:56 -05:00
# include "ProfilingDebugging/CsvProfiler.h"
2020-09-24 10:42:45 -04:00
# include "WorldPartition/WorldPartitionSubsystem.h"
# include "ActorPartition/ActorPartitionSubsystem.h"
# include "Engine/World.h"
# include "Math/IntRect.h"
2020-10-14 08:06:05 -04:00
# include "LandscapeConfigHelper.h"
2020-11-26 14:22:44 -04:00
# include "Engine/Canvas.h"
2020-01-17 08:59:21 -05:00
2020-01-22 14:16:42 -05:00
static int32 GUseStreamingManagerForCameras = 1 ;
static FAutoConsoleVariableRef CVarUseStreamingManagerForCameras (
TEXT ( " grass.UseStreamingManagerForCameras " ) ,
GUseStreamingManagerForCameras ,
TEXT ( " 1: Use Streaming Manager; 0: Use ViewLocationsRenderedLastFrame " ) ) ;
2020-01-17 08:59:21 -05:00
DECLARE_CYCLE_STAT ( TEXT ( " LandscapeSubsystem Tick " ) , STAT_LandscapeSubsystemTick , STATGROUP_Landscape ) ;
2020-11-26 14:22:44 -04:00
# define LOCTEXT_NAMESPACE "LandscapeSubsystem"
2020-09-25 14:17:42 -04:00
ULandscapeSubsystem : : ULandscapeSubsystem ( )
2020-02-19 14:27:51 -05:00
{
}
2020-01-17 08:59:21 -05:00
ULandscapeSubsystem : : ~ ULandscapeSubsystem ( )
{
2020-01-22 14:16:42 -05:00
}
void ULandscapeSubsystem : : RegisterActor ( ALandscapeProxy * Proxy )
{
Proxies . AddUnique ( Proxy ) ;
}
void ULandscapeSubsystem : : UnregisterActor ( ALandscapeProxy * Proxy )
{
Proxies . Remove ( Proxy ) ;
2020-01-17 08:59:21 -05:00
}
2020-02-19 14:27:51 -05:00
void ULandscapeSubsystem : : Initialize ( FSubsystemCollectionBase & Collection )
{
Super : : Initialize ( Collection ) ;
2020-04-27 16:16:09 -04:00
# if WITH_EDITOR
2020-04-27 21:14:20 -04:00
GrassMapsBuilder = new FLandscapeGrassMapsBuilder ( GetWorld ( ) ) ;
2020-12-08 15:05:44 -04:00
GIBakedTextureBuilder = new FLandscapeGIBakedTextureBuilder ( GetWorld ( ) ) ;
2020-12-09 16:49:05 -04:00
PhysicalMaterialBuilder = new FLandscapePhysicalMaterialBuilder ( GetWorld ( ) ) ;
2020-04-27 16:16:09 -04:00
# endif
2020-02-19 14:27:51 -05:00
}
void ULandscapeSubsystem : : Deinitialize ( )
{
2020-04-27 21:14:20 -04:00
# if WITH_EDITOR
if ( GrassMapsBuilder )
{
delete GrassMapsBuilder ;
}
2020-12-08 15:05:44 -04:00
if ( GIBakedTextureBuilder )
{
delete GIBakedTextureBuilder ;
}
2020-12-09 16:49:05 -04:00
if ( PhysicalMaterialBuilder )
{
delete PhysicalMaterialBuilder ;
}
2020-04-27 21:14:20 -04:00
# endif
2020-02-19 14:27:51 -05:00
Proxies . Empty ( ) ;
Super : : Deinitialize ( ) ;
}
2020-09-24 00:43:27 -04:00
TStatId ULandscapeSubsystem : : GetStatId ( ) const
{
RETURN_QUICK_DECLARE_CYCLE_STAT ( ULandscapeSubsystem , STATGROUP_Tickables ) ;
}
ETickableTickType ULandscapeSubsystem : : GetTickableTickType ( ) const
{
return HasAnyFlags ( RF_ClassDefaultObject ) | | ! GetWorld ( ) | | GetWorld ( ) - > IsNetMode ( NM_DedicatedServer ) ? ETickableTickType : : Never : ETickableTickType : : Always ;
}
void ULandscapeSubsystem : : Tick ( float DeltaTime )
2020-01-17 08:59:21 -05:00
{
SCOPE_CYCLE_COUNTER ( STAT_LandscapeSubsystemTick ) ;
TRACE_CPUPROFILER_EVENT_SCOPE ( ULandscapeSubsystem : : Tick ) ;
2020-01-20 16:19:27 -05:00
CSV_SCOPED_TIMING_STAT_EXCLUSIVE ( Landscape ) ;
LLM_SCOPE ( ELLMTag : : Landscape ) ;
2021-02-24 06:56:06 -04:00
Super : : Tick ( DeltaTime ) ;
2020-01-17 08:59:21 -05:00
UWorld * World = GetWorld ( ) ;
2020-01-22 14:16:42 -05:00
static TArray < FVector > OldCameras ;
TArray < FVector > * Cameras = nullptr ;
if ( GUseStreamingManagerForCameras = = 0 )
2020-01-17 08:59:21 -05:00
{
2020-01-22 14:16:42 -05:00
if ( OldCameras . Num ( ) | | World - > ViewLocationsRenderedLastFrame . Num ( ) )
{
Cameras = & OldCameras ;
// there is a bug here, which often leaves us with no cameras in the editor
if ( World - > ViewLocationsRenderedLastFrame . Num ( ) )
{
check ( IsInGameThread ( ) ) ;
Cameras = & World - > ViewLocationsRenderedLastFrame ;
OldCameras = * Cameras ;
}
}
2020-01-17 08:59:21 -05:00
}
2020-01-22 14:16:42 -05:00
else
2020-01-17 08:59:21 -05:00
{
2020-01-22 14:16:42 -05:00
int32 Num = IStreamingManager : : Get ( ) . GetNumViews ( ) ;
if ( Num )
{
OldCameras . Reset ( Num ) ;
for ( int32 Index = 0 ; Index < Num ; Index + + )
{
auto & ViewInfo = IStreamingManager : : Get ( ) . GetViewInformation ( Index ) ;
OldCameras . Add ( ViewInfo . ViewOrigin ) ;
}
Cameras = & OldCameras ;
}
}
int32 InOutNumComponentsCreated = 0 ;
2020-02-19 14:27:51 -05:00
for ( ALandscapeProxy * Proxy : Proxies )
2020-01-22 14:16:42 -05:00
{
# if WITH_EDITOR
if ( GIsEditor )
{
if ( ALandscape * Landscape = Cast < ALandscape > ( Proxy ) )
{
Landscape - > TickLayers ( DeltaTime ) ;
}
// editor-only
if ( ! World - > IsPlayInEditor ( ) )
{
2020-12-08 15:05:44 -04:00
Proxy - > UpdateGIBakedTextures ( ) ;
2020-03-11 12:18:16 -04:00
Proxy - > UpdatePhysicalMaterialTasks ( ) ;
2020-01-22 14:16:42 -05:00
}
}
# endif
if ( Cameras & & Proxy - > ShouldTickGrass ( ) )
{
Proxy - > TickGrass ( * Cameras , InOutNumComponentsCreated ) ;
}
2020-01-17 08:59:21 -05:00
}
2020-03-11 12:18:16 -04:00
# if WITH_EDITOR
if ( GIsEditor & & ! World - > IsPlayInEditor ( ) )
{
LandscapePhysicalMaterial : : GarbageCollectTasks ( ) ;
}
# endif
2020-01-17 08:59:21 -05:00
}
2020-04-27 16:16:09 -04:00
# if WITH_EDITOR
2020-11-26 14:22:44 -04:00
void ULandscapeSubsystem : : BuildAll ( )
{
BuildGrassMaps ( ) ;
2020-12-08 15:05:44 -04:00
BuildGIBakedTextures ( ) ;
2020-12-09 16:49:05 -04:00
BuildPhysicalMaterial ( ) ;
2020-11-26 14:22:44 -04:00
}
2020-04-27 16:16:09 -04:00
void ULandscapeSubsystem : : BuildGrassMaps ( )
{
GrassMapsBuilder - > Build ( ) ;
}
int32 ULandscapeSubsystem : : GetOutdatedGrassMapCount ( )
{
return GrassMapsBuilder - > GetOutdatedGrassMapCount ( /*bInForceUpdate*/ false ) ;
}
2020-09-24 10:42:45 -04:00
2020-12-08 15:05:44 -04:00
void ULandscapeSubsystem : : BuildGIBakedTextures ( )
2020-11-26 14:22:44 -04:00
{
2020-12-08 15:05:44 -04:00
GIBakedTextureBuilder - > Build ( ) ;
2020-11-26 14:22:44 -04:00
}
2020-12-08 15:05:44 -04:00
int32 ULandscapeSubsystem : : GetOutdatedGIBakedTextureComponentsCount ( )
2020-11-26 14:22:44 -04:00
{
2020-12-08 15:05:44 -04:00
return GIBakedTextureBuilder - > GetOutdatedGIBakedTextureComponentsCount ( /*bInForceUpdate*/ false ) ;
2020-11-26 14:22:44 -04:00
}
2020-12-09 16:49:05 -04:00
void ULandscapeSubsystem : : BuildPhysicalMaterial ( )
{
PhysicalMaterialBuilder - > Build ( ) ;
}
int32 ULandscapeSubsystem : : GetOudatedPhysicalMaterialComponentsCount ( )
{
return PhysicalMaterialBuilder - > GetOudatedPhysicalMaterialComponentsCount ( ) ;
}
2020-09-24 10:42:45 -04:00
bool ULandscapeSubsystem : : IsGridBased ( ) const
{
2022-02-22 08:54:19 -05:00
return UWorld : : IsPartitionedWorld ( GetWorld ( ) ) ;
2020-09-24 10:42:45 -04:00
}
2020-10-14 08:06:05 -04:00
void ULandscapeSubsystem : : ChangeGridSize ( ULandscapeInfo * LandscapeInfo , uint32 GridSizeInComponents )
2020-09-24 10:42:45 -04:00
{
if ( ! IsGridBased ( ) )
{
return ;
}
2020-10-14 08:06:05 -04:00
TSet < AActor * > ActorsToDelete ;
FLandscapeConfigHelper : : ChangeGridSize ( LandscapeInfo , GridSizeInComponents , ActorsToDelete ) ;
// This code path is used for converting a non grid based Landscape to a gridbased so it shouldn't delete any actors
check ( ! ActorsToDelete . Num ( ) ) ;
2020-09-24 10:42:45 -04:00
}
ALandscapeProxy * ULandscapeSubsystem : : FindOrAddLandscapeProxy ( ULandscapeInfo * LandscapeInfo , const FIntPoint & SectionBase )
{
if ( ! IsGridBased ( ) )
{
return LandscapeInfo - > GetCurrentLevelLandscapeProxy ( true ) ;
}
2020-10-14 08:06:05 -04:00
return FLandscapeConfigHelper : : FindOrAddLandscapeStreamingProxy ( LandscapeInfo , SectionBase ) ;
2020-09-24 10:42:45 -04:00
}
2020-11-26 14:22:44 -04:00
void ULandscapeSubsystem : : DisplayBuildMessages ( FCanvas * Canvas , float & XPos , float & YPos )
{
const int32 FontSizeY = 20 ;
FCanvasTextItem SmallTextItem ( FVector2D ( 0 , 0 ) , FText : : GetEmpty ( ) , GEngine - > GetSmallFont ( ) , FLinearColor : : White ) ;
SmallTextItem . EnableShadow ( FLinearColor : : Black ) ;
if ( int32 OutdatedGrassMapCount = GetOutdatedGrassMapCount ( ) )
{
SmallTextItem . SetColor ( FLinearColor : : Red ) ;
2020-12-09 16:49:05 -04:00
SmallTextItem . Text = FText : : Format ( LOCTEXT ( " GRASS_MAPS_NEED_TO_BE_REBUILT_FMT " , " GRASS MAPS NEEDS TO BE REBUILT ({0} {0}|plural(one=object,other=objects)) " ) , OutdatedGrassMapCount ) ;
2020-11-26 14:22:44 -04:00
Canvas - > DrawItem ( SmallTextItem , FVector2D ( XPos , YPos ) ) ;
YPos + = FontSizeY ;
}
2020-12-08 15:05:44 -04:00
if ( int32 ComponentsNeedingGITextureBaking = GetOutdatedGIBakedTextureComponentsCount ( ) )
2020-11-26 14:22:44 -04:00
{
SmallTextItem . SetColor ( FLinearColor : : Red ) ;
2020-12-09 16:49:05 -04:00
SmallTextItem . Text = FText : : Format ( LOCTEXT ( " LANDSCAPE_TEXTURES_NEED_TO_BE_REBUILT_FMT " , " LANDSCAPE BAKED TEXTURES NEEDS TO BE REBUILT ({0} {0}|plural(one=object,other=objects)) " ) , ComponentsNeedingGITextureBaking ) ;
Canvas - > DrawItem ( SmallTextItem , FVector2D ( XPos , YPos ) ) ;
YPos + = FontSizeY ;
}
if ( int32 ComponentsWithOudatedPhysicalMaterial = GetOudatedPhysicalMaterialComponentsCount ( ) )
{
SmallTextItem . SetColor ( FLinearColor : : Red ) ;
SmallTextItem . Text = FText : : Format ( LOCTEXT ( " LANDSCAPE_PHYSICALMATERIAL_NEED_TO_BE_REBUILT_FMT " , " LANDSCAPE PHYSICAL MATERIAL NEEDS TO BE REBUILT ({0} {0}|plural(one=object,other=objects)) " ) , ComponentsWithOudatedPhysicalMaterial ) ;
2020-11-26 14:22:44 -04:00
Canvas - > DrawItem ( SmallTextItem , FVector2D ( XPos , YPos ) ) ;
YPos + = FontSizeY ;
}
}
# endif
# undef LOCTEXT_NAMESPACE