2019-12-26 15:33:43 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2019-06-06 15:34:43 -04:00
# include "LandscapeProxyUIDetails.h"
2022-01-20 17:23:55 -05:00
2023-04-10 10:30:39 -04:00
# include "Algo/AnyOf.h"
2022-11-22 19:52:28 -05:00
# include "Algo/Count.h"
# include "Algo/Find.h"
# include "Algo/Transform.h"
2022-01-20 17:23:55 -05:00
# include "Components/RuntimeVirtualTextureComponent.h"
2022-08-30 23:03:03 -04:00
# include "Containers/Array.h"
# include "Containers/Map.h"
2022-01-20 17:23:55 -05:00
# include "DetailCategoryBuilder.h"
2019-06-06 15:34:43 -04:00
# include "DetailLayoutBuilder.h"
2022-01-20 17:23:55 -05:00
# include "DetailWidgetRow.h"
2022-08-30 23:03:03 -04:00
# include "Engine/World.h"
# include "Fonts/SlateFontInfo.h"
# include "HAL/PlatformCrt.h"
# include "IDetailPropertyRow.h"
# include "Internationalization/Internationalization.h"
# include "Internationalization/Text.h"
# include "Landscape.h"
2022-09-11 18:33:06 -04:00
# include "LandscapeInfo.h"
2022-08-30 23:03:03 -04:00
# include "LandscapeProxy.h"
2022-11-22 19:52:28 -05:00
# include "LandscapeStreamingProxy.h"
# include "LandscapeSubsystem.h"
2022-08-30 23:03:03 -04:00
# include "Layout/Margin.h"
# include "Math/IntPoint.h"
# include "Math/IntRect.h"
# include "Math/UnrealMathSSE.h"
# include "Misc/Attribute.h"
2022-01-20 17:23:55 -05:00
# include "RuntimeVirtualTextureSetBounds.h"
# include "ScopedTransaction.h"
2022-08-30 23:03:03 -04:00
# include "Templates/Casts.h"
# include "Types/SlateEnums.h"
# include "UObject/LazyObjectPtr.h"
# include "UObject/ObjectMacros.h"
# include "UObject/ObjectPtr.h"
# include "UObject/UObjectIterator.h"
# include "UObject/WeakObjectPtr.h"
# include "UObject/WeakObjectPtrTemplates.h"
2022-01-20 17:23:55 -05:00
# include "VT/RuntimeVirtualTextureVolume.h"
# include "Widgets/DeclarativeSyntaxSupport.h"
2019-06-06 15:34:43 -04:00
# include "Widgets/Input/SButton.h"
2023-06-14 16:03:16 -04:00
# include "Widgets/Input/SCheckBox.h"
# include "Widgets/IToolTip.h"
# include "Widgets/Layout/SBox.h"
2022-01-20 17:23:55 -05:00
# include "Widgets/Text/STextBlock.h"
2023-11-27 13:00:29 -05:00
# include "Widgets/Input/STextComboBox.h"
2019-06-06 15:34:43 -04:00
2022-08-30 23:03:03 -04:00
class IPropertyHandle ;
class SWidget ;
class UObject ;
class URuntimeVirtualTexture ;
2019-06-06 15:34:43 -04:00
# define LOCTEXT_NAMESPACE "FLandscapeProxyUIDetails"
FLandscapeProxyUIDetails : : FLandscapeProxyUIDetails ( )
{
2023-11-27 13:00:29 -05:00
// Position Precision options are copied from StaticMeshEditorTools.cpp
auto PositionPrecisionValueToDisplayString = [ ] ( int32 Value )
{
if ( Value < = 0 )
{
return FString : : Printf ( TEXT ( " %dcm " ) , 1 < < ( - Value ) ) ;
}
else
{
const float fValue = static_cast < float > ( FMath : : Exp2 ( ( double ) - Value ) ) ;
return FString : : Printf ( TEXT ( " 1/%dcm (%.3gcm) " ) , 1 < < Value , fValue ) ;
}
} ;
for ( int32 i = MinNanitePrecision ; i < = MaxNanitePrecision ; i + + )
{
TSharedPtr < FString > Option = MakeShared < FString > ( PositionPrecisionValueToDisplayString ( i ) ) ;
PositionPrecisionOptions . Add ( Option ) ;
}
2019-06-06 15:34:43 -04:00
}
TSharedRef < IDetailCustomization > FLandscapeProxyUIDetails : : MakeInstance ( )
{
return MakeShareable ( new FLandscapeProxyUIDetails ) ;
}
void FLandscapeProxyUIDetails : : CustomizeDetails ( IDetailLayoutBuilder & DetailBuilder )
{
TArray < TWeakObjectPtr < UObject > > EditingObjects ;
DetailBuilder . GetObjectsBeingCustomized ( EditingObjects ) ;
auto GenerateTextWidget = [ ] ( const FText & InText , bool bInBold = false ) - > TSharedRef < SWidget >
{
return SNew ( STextBlock )
. Font ( bInBold ? IDetailLayoutBuilder : : GetDetailFontBold ( ) : IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( InText ) ;
} ;
2022-11-22 19:52:28 -05:00
TArray < TWeakObjectPtr < ALandscapeProxy > > EditingProxies ;
Algo : : Transform ( EditingObjects , EditingProxies , [ ] ( TWeakObjectPtr < UObject > InObject ) { return TWeakObjectPtr < ALandscapeProxy > ( Cast < ALandscapeProxy > ( InObject . Get ( ) ) ) ; } ) ;
TArray < TWeakObjectPtr < ALandscape > > LandscapeActors ;
2023-06-21 13:48:18 -04:00
TArray < TWeakObjectPtr < ALandscapeStreamingProxy > > EditingStreamingProxies ;
2022-11-22 19:52:28 -05:00
for ( TWeakObjectPtr < ALandscapeProxy > EditingProxy : EditingProxies )
2019-06-06 15:34:43 -04:00
{
2022-11-22 19:52:28 -05:00
if ( EditingProxy . IsValid ( ) )
2019-06-06 15:34:43 -04:00
{
2023-01-13 13:48:07 -05:00
if ( ALandscape * LandscapeActor = EditingProxy - > GetLandscapeActor ( ) )
{
LandscapeActors . AddUnique ( LandscapeActor ) ;
}
2023-06-21 13:48:18 -04:00
if ( ALandscapeStreamingProxy * LandscapeStreamingProxy = Cast < ALandscapeStreamingProxy > ( EditingProxy . Get ( ) ) )
{
EditingStreamingProxies . Add ( LandscapeStreamingProxy ) ;
}
2022-11-22 19:52:28 -05:00
}
}
2023-11-27 13:00:29 -05:00
ALandscapeStreamingProxy * LandscapeStreamingProxy = EditingStreamingProxies . IsEmpty ( ) ? nullptr : EditingStreamingProxies [ 0 ] . Get ( ) ;
2023-04-10 10:30:39 -04:00
// Hide World Partition specific properties in non WP levels
const bool bShouldDisplayWorldPartitionProperties = Algo : : AnyOf ( EditingProxies , [ ] ( const TWeakObjectPtr < ALandscapeProxy > InProxy )
{
UWorld * World = InProxy . IsValid ( ) ? InProxy - > GetTypedOuter < UWorld > ( ) : nullptr ;
return UWorld : : IsPartitionedWorld ( World ) ;
} ) ;
if ( ! bShouldDisplayWorldPartitionProperties )
{
DetailBuilder . HideProperty ( DetailBuilder . GetProperty ( GET_MEMBER_NAME_CHECKED ( ALandscape , bAreNewLandscapeActorsSpatiallyLoaded ) , ALandscape : : StaticClass ( ) ) ) ;
}
2022-11-22 19:52:28 -05:00
if ( LandscapeActors . Num ( ) = = 1 )
{
TWeakObjectPtr < ALandscape > LandscapeActor = LandscapeActors [ 0 ] ;
if ( ULandscapeInfo * LandscapeInfo = LandscapeActor - > GetLandscapeInfo ( ) )
{
IDetailCategoryBuilder & CategoryBuilder = DetailBuilder . EditCategory ( " Information " , FText : : GetEmpty ( ) , ECategoryPriority : : Important ) ;
FText CreateRVTVolumesTooltip = LOCTEXT ( " Button_CreateVolumes_Tooltip " , " Create volumes for the selected Runtime Virtual Textures. " ) ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
FText RowDisplayText = LOCTEXT ( " LandscapeComponentResolution " , " Component Resolution (Verts) " ) ;
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeComponentResolution " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " LandscapeComponentResolutionValue " , " {0} x {0} " ) , LandscapeActor - > ComponentSizeQuads + 1 ) , true ) // Verts
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
RowDisplayText = LOCTEXT ( " LandscapeComponentCount " , " Component Count " ) ;
2023-06-21 13:48:18 -04:00
int32 NumComponents = LandscapeActor - > LandscapeComponents . Num ( ) ;
// If displaying streaming proxies, don't show the main landscape actor's component count, which is always 0 :
if ( ! EditingStreamingProxies . IsEmpty ( ) )
{
NumComponents = EditingStreamingProxies [ 0 ] - > LandscapeComponents . Num ( ) ;
if ( Algo : : AnyOf ( EditingStreamingProxies , [ NumComponents ] ( const TWeakObjectPtr < ALandscapeStreamingProxy > InStreamingProxy ) { return InStreamingProxy . Get ( ) - > LandscapeComponents . Num ( ) ! = NumComponents ; } ) )
{
NumComponents = - 1 ;
}
}
2022-11-22 19:52:28 -05:00
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeComponentCount " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
2023-06-21 13:48:18 -04:00
GenerateTextWidget ( ( NumComponents = = - 1 ) ? LOCTEXT ( " MultipleValues " , " Multiple Values " ) : FText : : Format ( LOCTEXT ( " LandscapeComponentCountValue " , " {0} " ) , NumComponents ) , true )
2022-11-22 19:52:28 -05:00
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
RowDisplayText = LOCTEXT ( " LandscapeComponentSubsections " , " Component Subsections " ) ;
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeComponentSubsections " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " LandscapeComponentSubSectionsValue " , " {0} x {0} " ) , LandscapeActor - > NumSubsections ) , true )
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
FIntRect Rect = LandscapeActor - > GetBoundingRect ( ) ;
FIntPoint Size = Rect . Size ( ) ;
RowDisplayText = LOCTEXT ( " LandscapeResolution " , " Resolution (Verts) " ) ;
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeResolution " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " LandscapeResolutionValue " , " {0} x {1} " ) , Size . X + 1 , Size . Y + 1 ) , true )
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
int32 LandscapeCount = LandscapeInfo - > StreamingProxies . Num ( ) + ( LandscapeInfo - > LandscapeActor . Get ( ) ? 1 : 0 ) ;
2023-06-06 15:05:13 -04:00
RowDisplayText = LOCTEXT ( " LandscapeCount " , " Landscape Proxy Count " ) ;
2022-11-22 19:52:28 -05:00
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeCount " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
2023-06-06 15:05:13 -04:00
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " LandscapeProxyCountValue " , " {0} " ) , LandscapeCount ) , true )
2022-11-22 19:52:28 -05:00
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
int32 TotalComponentCount = LandscapeInfo - > XYtoComponentMap . Num ( ) ;
RowDisplayText = LOCTEXT ( " TotalLandscapeComponentCount " , " Total Component Count " ) ;
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " TotalLandscapeComponentCount " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " TotalLandscapeComponentCountValue " , " {0} " ) , TotalComponentCount ) , true )
] ;
2019-06-06 15:34:43 -04:00
2022-11-22 19:52:28 -05:00
LandscapeInfo - > GetLandscapeExtent ( Rect . Min . X , Rect . Min . Y , Rect . Max . X , Rect . Max . Y ) ;
Size = Rect . Size ( ) ;
RowDisplayText = LOCTEXT ( " LandscapeOverallResolution " , " Overall Resolution (Verts) " ) ;
CategoryBuilder . AddCustomRow ( RowDisplayText )
. RowTag ( TEXT ( " LandscapeOverallResolution " ) )
. NameContent ( )
[
GenerateTextWidget ( RowDisplayText )
]
. ValueContent ( )
[
GenerateTextWidget ( FText : : Format ( LOCTEXT ( " LandscapeOverallResolutionValue " , " {0} x {1} " ) , Size . X + 1 , Size . Y + 1 ) , true )
] ;
2022-01-20 17:23:55 -05:00
// Apply custom widget for CreateVolume.
TSharedRef < IPropertyHandle > CreateVolumePropertyHandle = DetailBuilder . GetProperty ( TEXT ( " bSetCreateRuntimeVirtualTextureVolumes " ) ) ;
DetailBuilder . EditDefaultProperty ( CreateVolumePropertyHandle ) - > CustomWidget ( )
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " Button_CreateVolumes " , " Create Volumes " ) )
2022-11-22 19:52:28 -05:00
. ToolTipText ( CreateRVTVolumesTooltip )
2022-01-20 17:23:55 -05:00
]
. ValueContent ( )
. MinDesiredWidth ( 125.f )
[
SNew ( SButton )
. VAlign ( VAlign_Center )
. HAlign ( HAlign_Center )
. ContentPadding ( 2 )
. Text ( LOCTEXT ( " Button_CreateVolumes " , " Create Volumes " ) )
2022-11-22 19:52:28 -05:00
. OnClicked_Lambda ( [ LandscapeActor , this ] ( ) { return CreateRuntimeVirtualTextureVolume ( LandscapeActor . Get ( ) ) ; } )
. IsEnabled_Lambda ( [ LandscapeActor , this ] ( ) { return IsCreateRuntimeVirtualTextureVolumeEnabled ( LandscapeActor . Get ( ) ) ; } )
. ToolTipText_Lambda ( [ LandscapeActor , this , CreateRVTVolumesTooltip ] ( )
{
return IsCreateRuntimeVirtualTextureVolumeEnabled ( LandscapeActor . Get ( ) )
? CreateRVTVolumesTooltip
: LOCTEXT ( " Button_CreateVolumes_Tooltip_Invalid " , " No Runtime Virtual Textures found in the world. " ) ;
} )
2022-01-20 17:23:55 -05:00
] ;
2019-06-06 15:34:43 -04:00
}
2023-11-27 13:00:29 -05:00
TSharedRef < IPropertyHandle > NanitePositionPrecisionHandle = DetailBuilder . GetProperty ( TEXT ( " NanitePositionPrecision " ) ) ;
IDetailPropertyRow * DetailRow = DetailBuilder . EditDefaultProperty ( NanitePositionPrecisionHandle ) ;
// todo don.boogert : this is the handling of disabling of inherited properties on Landscape Proxies.
// todo don.boogert : be able to handle override & inherited properties which also have custom UI.
if ( LandscapeStreamingProxy - > IsPropertyInherited ( NanitePositionPrecisionHandle - > GetProperty ( ) ) )
{
if ( LandscapeStreamingProxy ! = nullptr )
{
if ( DetailRow ! = nullptr )
{
// Extend the tool tip to indicate this property is inherited
FText ToolTipText = NanitePositionPrecisionHandle - > GetToolTipText ( ) ;
2024-05-14 08:08:57 -04:00
DetailRow - > ToolTip ( FText : : Format ( LOCTEXT ( " InheritedProperty " , " {0} This property is inherited from the parent Landscape proxy. " ) , ToolTipText ) ) ;
2023-11-27 13:00:29 -05:00
// Disable the property editing
DetailRow - > IsEnabled ( false ) ;
}
}
}
auto GetPositionPrecision = [ MinNanitePrecision = this - > MinNanitePrecision , & PositionOptions = this - > PositionPrecisionOptions , LandscapeActor ] ( )
{
return PositionOptions [ LandscapeActor - > GetNanitePositionPrecision ( ) - MinNanitePrecision ] ;
} ;
auto SetPositionPrecision = [ NanitePositionPrecisionHandle , MinNanitePrecision = this - > MinNanitePrecision , & PositionOptions = this - > PositionPrecisionOptions , LandscapeActor ] ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
if ( ! LandscapeActor . IsValid ( ) )
{
return ;
}
if ( const int32 Index = PositionOptions . Find ( NewValue ) ; Index ! = INDEX_NONE )
{
NanitePositionPrecisionHandle - > SetValue ( Index + MinNanitePrecision ) ;
}
} ;
DetailRow - > CustomWidget ( )
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " LandscapeNanitePositionPrecision " , " Nanite Position Precision " ) )
. ToolTipText ( LOCTEXT ( " LandscapeNanitePositionPrecisionTooltip " , " Precision of Nanite vertex positions in World Space. " ) )
]
. ValueContent ( )
. VAlign ( VAlign_Center )
[
SNew ( STextComboBox )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. OptionsSource ( & PositionPrecisionOptions )
. InitiallySelectedItem ( GetPositionPrecision ( ) )
. OnSelectionChanged_Lambda ( SetPositionPrecision )
] ;
2019-06-06 15:34:43 -04:00
}
2022-11-22 19:52:28 -05:00
// Add Nanite buttons :
if ( ! EditingProxies . IsEmpty ( ) )
{
auto BuildNaniteData = [ EditingProxies ] ( bool bInForceRebuild ) - > FReply
{
TArray < ALandscapeProxy * > ProxiesToBuild ;
Algo : : TransformIf ( EditingProxies , ProxiesToBuild , [ ] ( const TWeakObjectPtr < ALandscapeProxy > & InProxy ) { return InProxy . IsValid ( ) ; } , [ ] ( const TWeakObjectPtr < ALandscapeProxy > & InProxy ) { return InProxy . Get ( ) ; } ) ;
if ( ProxiesToBuild . IsEmpty ( ) )
{
return FReply : : Unhandled ( ) ;
}
if ( UWorld * World = ProxiesToBuild [ 0 ] - > GetWorld ( ) )
{
if ( ULandscapeSubsystem * LandscapeSubsystem = World - > GetSubsystem < ULandscapeSubsystem > ( ) )
{
LandscapeSubsystem - > BuildNanite ( MakeArrayView ( ProxiesToBuild ) , bInForceRebuild ) ;
}
}
return FReply : : Handled ( ) ;
} ;
auto GetNumProxiesNeedingRebuild = [ EditingProxies ] ( bool bInForceRebuild ) - > int32
{
TSet < TWeakObjectPtr < ALandscapeProxy > > ProxiesToBuild ;
for ( TWeakObjectPtr < ALandscapeProxy > EditingProxy : EditingProxies )
{
if ( EditingProxy . IsValid ( ) )
{
ProxiesToBuild . Add ( EditingProxy ) ;
// Build all streaming proxies in the case of a ALandscape :
if ( ALandscape * Landscape = Cast < ALandscape > ( EditingProxy . Get ( ) ) )
{
ULandscapeInfo * LandscapeInfo = Landscape - > GetLandscapeInfo ( ) ;
if ( LandscapeInfo ! = nullptr )
{
Algo : : Transform ( LandscapeInfo - > StreamingProxies , ProxiesToBuild , [ ] ( const TWeakObjectPtr < ALandscapeStreamingProxy > & InStreamingProxy ) { return InStreamingProxy ; } ) ;
}
}
}
}
return Algo : : CountIf ( ProxiesToBuild , [ bInForceRebuild ] ( TWeakObjectPtr < ALandscapeProxy > InProxy ) { return ( InProxy . IsValid ( ) & & ( bInForceRebuild | | ! InProxy - > IsNaniteMeshUpToDate ( ) ) ) ; } ) ;
} ;
auto HasAtLeastOneNaniteLandscape = [ LandscapeActors ] ( ) - > bool
{
return Algo : : FindByPredicate ( LandscapeActors , [ ] ( TWeakObjectPtr < ALandscape > InLandscape ) { return ( InLandscape . IsValid ( ) & & InLandscape - > IsNaniteEnabled ( ) ) ; } ) ! = nullptr ;
} ;
IDetailCategoryBuilder & CategoryBuilder = DetailBuilder . EditCategory ( " Nanite " , FText : : GetEmpty ( ) , ECategoryPriority : : Default ) ;
2022-11-23 05:56:52 -05:00
CategoryBuilder . AddCustomRow ( FText : : FromString ( TEXT ( " Rebuild Nanite Data " ) ) )
2023-02-21 06:00:28 -05:00
. RowTag ( " RebuildNaniteData " )
2022-11-22 19:52:28 -05:00
[
SNew ( SHorizontalBox )
. IsEnabled_Lambda ( [ HasAtLeastOneNaniteLandscape ] { return HasAtLeastOneNaniteLandscape ( ) ; } )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1 )
[
SNew ( SButton )
. Text ( LOCTEXT ( " BuildNaniteData " , " Build Data " ) )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. ToolTipText_Lambda ( [ GetNumProxiesNeedingRebuild ] ( )
{
return FText : : Format ( LOCTEXT ( " BuildNaniteDataTooltip " , " Builds the Nanite mesh representation from the Landscape data if it's not up to date ({0} {0}|plural(one=actors, other=actors) to build) " ) , GetNumProxiesNeedingRebuild ( /*bInForceRebuild = */ false ) ) ;
} )
. OnClicked_Lambda ( [ BuildNaniteData ] ( ) { return BuildNaniteData ( /*bInForceRebuild = */ false ) ; } )
. IsEnabled_Lambda ( [ GetNumProxiesNeedingRebuild ] ( ) { return ( GetNumProxiesNeedingRebuild ( /*bInForceRebuild = */ false ) > 0 ) ; } )
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1 )
[
SNew ( SButton )
. Text ( LOCTEXT ( " RebuildNaniteData " , " Rebuild Data " ) )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. ToolTipText_Lambda ( [ GetNumProxiesNeedingRebuild ] ( )
{
return FText : : Format ( LOCTEXT ( " RebuildNaniteDataTooltip " , " Rebuilds the Nanite mesh representation from the Landscape data ({0} {0}|plural(one=actors, other=actors) to build) " ) , GetNumProxiesNeedingRebuild ( /*bInForceRebuild = */ true ) ) ;
} )
. OnClicked_Lambda ( [ BuildNaniteData ] ( ) { return BuildNaniteData ( /*bInForceRebuild = */ true ) ; } )
]
] ;
}
2023-06-14 16:03:16 -04:00
if ( LandscapeStreamingProxy ! = nullptr )
{
for ( TFieldIterator < FProperty > PropertyIterator ( LandscapeStreamingProxy - > GetClass ( ) ) ; PropertyIterator ; + + PropertyIterator )
{
FProperty * Property = * PropertyIterator ;
if ( Property = = nullptr )
{
continue ;
}
if ( LandscapeStreamingProxy - > IsPropertyInherited ( Property ) )
{
TSharedPtr < IPropertyHandle > PropertyHandle = DetailBuilder . GetProperty ( Property - > GetFName ( ) ) ;
if ( PropertyHandle - > IsValidHandle ( ) )
{
IDetailPropertyRow * DetailRow = DetailBuilder . EditDefaultProperty ( PropertyHandle ) ;
if ( DetailRow ! = nullptr )
{
// Extend the tool tip to indicate this property is inherited
FText ToolTipText = PropertyHandle - > GetToolTipText ( ) ;
2024-05-14 08:08:57 -04:00
DetailRow - > ToolTip ( FText : : Format ( LOCTEXT ( " InheritedProperty " , " {0} This property is inherited from the parent Landscape proxy. " ) , ToolTipText ) ) ;
2023-06-14 16:03:16 -04:00
// Disable the property editing
DetailRow - > IsEnabled ( false ) ;
}
}
}
else if ( LandscapeStreamingProxy - > IsPropertyOverridable ( Property ) )
{
TSharedPtr < IPropertyHandle > PropertyHandle = DetailBuilder . GetProperty ( Property - > GetFName ( ) ) ;
if ( PropertyHandle - > IsValidHandle ( ) )
{
2024-05-14 08:08:57 -04:00
const FText TooltipText = LOCTEXT ( " OverriddenProperty " , " Check this box to override the parent landscape's property. " ) ;
2023-12-13 12:58:59 -05:00
FName PropertyName = Property - > GetFName ( ) ;
2023-06-14 16:03:16 -04:00
IDetailPropertyRow * DetailRow = DetailBuilder . EditDefaultProperty ( PropertyHandle ) ;
TSharedPtr < SWidget > NameWidget = nullptr ;
TSharedPtr < SWidget > ValueWidget = nullptr ;
DetailRow - > GetDefaultWidgets ( NameWidget , ValueWidget ) ;
2023-12-13 12:58:59 -05:00
TAttribute < bool > EnabledAttribute = TAttribute < bool > : : Create ( [ LandscapeStreamingProxy , PropertyName ] ( ) - > bool
{
return LandscapeStreamingProxy - > IsSharedPropertyOverridden ( PropertyName ) ;
} ) ;
2023-10-24 12:40:23 -04:00
DetailRow - > CustomWidget ( /*bShowChildren = */ true )
2023-06-14 16:03:16 -04:00
. NameContent ( )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
SNew ( SCheckBox )
. ToolTipText ( TooltipText )
. IsChecked_Lambda ( [ EditingStreamingProxies , PropertyName ] ( ) - > ECheckBoxState
{
bool bContainsOverriddenProperty = false ;
bool bContainsDefaultProperty = false ;
for ( const TWeakObjectPtr < ALandscapeStreamingProxy > StreamingProxy : EditingStreamingProxies )
{
if ( ! StreamingProxy . IsValid ( ) )
{
continue ;
}
const bool bIsPropertyOverridden = StreamingProxy - > IsSharedPropertyOverridden ( PropertyName ) ;
bContainsOverriddenProperty | = bIsPropertyOverridden ;
bContainsDefaultProperty | = ! bIsPropertyOverridden ;
}
if ( bContainsOverriddenProperty & & bContainsDefaultProperty )
{
return ECheckBoxState : : Undetermined ;
}
return bContainsOverriddenProperty ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
} )
. OnCheckStateChanged_Lambda ( [ EditingStreamingProxies , PropertyName ] ( ECheckBoxState NewState )
{
if ( NewState = = ECheckBoxState : : Undetermined )
{
return ;
}
const bool bChecked = NewState = = ECheckBoxState : : Checked ;
2024-05-14 08:08:57 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " SetSharedPropertyOverride " , " Change Property Override " ) ) ;
2023-06-14 16:03:16 -04:00
for ( const TWeakObjectPtr < ALandscapeStreamingProxy > StreamingProxy : EditingStreamingProxies )
{
if ( ! StreamingProxy . IsValid ( ) )
{
continue ;
}
StreamingProxy - > SetSharedPropertyOverride ( PropertyName , bChecked ) ;
}
} )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
[
2023-12-13 12:58:59 -05:00
SNew ( SBox )
. IsEnabled ( EnabledAttribute )
[
NameWidget - > AsShared ( )
]
2023-06-14 16:03:16 -04:00
]
]
. ValueContent ( )
[
SNew ( SBox )
2023-12-13 12:58:59 -05:00
. IsEnabled ( EnabledAttribute )
2023-06-14 16:03:16 -04:00
[
ValueWidget - > AsShared ( )
]
2023-12-13 12:58:59 -05:00
]
. IsValueEnabled ( EnabledAttribute ) ;
2023-06-14 16:03:16 -04:00
}
}
}
}
2019-06-06 15:34:43 -04:00
}
2022-11-22 19:52:28 -05:00
static void GetMissingRuntimeVirtualTextureVolumes ( ALandscape * InLandscapeActor , TArray < URuntimeVirtualTexture * > & OutVirtualTextures )
2022-01-20 17:23:55 -05:00
{
2022-11-22 19:52:28 -05:00
UWorld * World = InLandscapeActor ! = nullptr ? InLandscapeActor - > GetWorld ( ) : nullptr ;
2022-01-20 17:23:55 -05:00
if ( World = = nullptr )
{
return ;
}
TArray < URuntimeVirtualTexture * > FoundVolumes ;
2022-02-02 02:21:12 -05:00
for ( TObjectIterator < URuntimeVirtualTextureComponent > It ( RF_ClassDefaultObject , false , EInternalObjectFlags : : Garbage ) ; It ; + + It )
2022-01-20 17:23:55 -05:00
{
if ( It - > GetWorld ( ) = = World )
{
if ( URuntimeVirtualTexture * VirtualTexture = It - > GetVirtualTexture ( ) )
{
FoundVolumes . Add ( VirtualTexture ) ;
}
}
}
2022-11-22 19:52:28 -05:00
for ( URuntimeVirtualTexture * VirtualTexture : InLandscapeActor - > RuntimeVirtualTextures )
2022-01-20 17:23:55 -05:00
{
if ( VirtualTexture ! = nullptr & & FoundVolumes . Find ( VirtualTexture ) = = INDEX_NONE )
{
OutVirtualTextures . Add ( VirtualTexture ) ;
}
}
}
2022-11-22 19:52:28 -05:00
bool FLandscapeProxyUIDetails : : IsCreateRuntimeVirtualTextureVolumeEnabled ( ALandscape * InLandscapeActor ) const
2022-01-20 17:23:55 -05:00
{
2022-11-22 19:52:28 -05:00
if ( InLandscapeActor = = nullptr )
{
return false ;
}
2022-01-20 17:23:55 -05:00
TArray < URuntimeVirtualTexture * > VirtualTextureVolumesToCreate ;
2022-11-22 19:52:28 -05:00
GetMissingRuntimeVirtualTextureVolumes ( InLandscapeActor , VirtualTextureVolumesToCreate ) ;
2022-01-20 17:23:55 -05:00
return VirtualTextureVolumesToCreate . Num ( ) > 0 ;
}
2022-11-22 19:52:28 -05:00
FReply FLandscapeProxyUIDetails : : CreateRuntimeVirtualTextureVolume ( ALandscape * InLandscapeActor )
2022-01-20 17:23:55 -05:00
{
2022-11-22 19:52:28 -05:00
if ( InLandscapeActor = = nullptr )
{
return FReply : : Unhandled ( ) ;
}
2022-01-20 17:23:55 -05:00
TArray < URuntimeVirtualTexture * > VirtualTextureVolumesToCreate ;
2022-11-22 19:52:28 -05:00
GetMissingRuntimeVirtualTextureVolumes ( InLandscapeActor , VirtualTextureVolumesToCreate ) ;
2022-01-20 17:23:55 -05:00
if ( VirtualTextureVolumesToCreate . Num ( ) = = 0 )
{
return FReply : : Unhandled ( ) ;
}
const FScopedTransaction Transaction ( LOCTEXT ( " Transaction_CreateVolumes " , " Create Runtime Virtual Texture Volumes " ) ) ;
for ( URuntimeVirtualTexture * VirtualTexture : VirtualTextureVolumesToCreate )
{
2022-11-22 19:52:28 -05:00
ARuntimeVirtualTextureVolume * NewVolume = InLandscapeActor - > GetWorld ( ) - > SpawnActor < ARuntimeVirtualTextureVolume > ( ) ;
2022-01-20 17:23:55 -05:00
NewVolume - > VirtualTextureComponent - > SetVirtualTexture ( VirtualTexture ) ;
2022-11-22 19:52:28 -05:00
NewVolume - > VirtualTextureComponent - > SetBoundsAlignActor ( InLandscapeActor ) ;
2022-01-20 17:23:55 -05:00
RuntimeVirtualTexture : : SetBounds ( NewVolume - > VirtualTextureComponent ) ;
}
return FReply : : Handled ( ) ;
}
2019-06-06 15:34:43 -04:00
# undef LOCTEXT_NAMESPACE