2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "StaticMeshEditorModule.h"
# include "StaticMeshEditorTools.h"
# include "RawMesh.h"
# include "MeshUtilities.h"
# include "TargetPlatform.h"
# include "StaticMeshResources.h"
# include "StaticMeshEditor.h"
# include "PropertyCustomizationHelpers.h"
# include "PhysicsEngine/BodySetup.h"
# include "FbxMeshUtils.h"
2014-04-23 19:03:58 -04:00
# include "SVectorInputBox.h"
2014-03-14 14:13:41 -04:00
2014-07-24 04:28:41 -04:00
# include "Runtime/Analytics/Analytics/Public/Interfaces/IAnalyticsProvider.h"
# include "EngineAnalytics.h"
2014-10-14 22:50:06 -04:00
# include "STextComboBox.h"
2014-07-24 04:28:41 -04:00
2015-03-30 07:26:43 -04:00
const float MaxHullAccuracy = 1.f ;
const float MinHullAccuracy = 0.f ;
const float DefaultHullAccuracy = 0.5f ;
const float HullAccuracyDelta = 0.01f ;
2014-03-14 14:13:41 -04:00
const int32 MaxVertsPerHullCount = 32 ;
const int32 MinVertsPerHullCount = 6 ;
2015-03-30 07:26:43 -04:00
const int32 DefaultVertsPerHull = 16 ;
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "StaticMeshEditor"
DEFINE_LOG_CATEGORY_STATIC ( LogStaticMeshEditorTools , Log , All ) ;
FStaticMeshDetails : : FStaticMeshDetails ( class FStaticMeshEditor & InStaticMeshEditor )
: StaticMeshEditor ( InStaticMeshEditor )
{ }
FStaticMeshDetails : : ~ FStaticMeshDetails ( )
{
}
void FStaticMeshDetails : : CustomizeDetails ( class IDetailLayoutBuilder & DetailBuilder )
{
2014-12-01 11:19:41 -05:00
IDetailCategoryBuilder & LODSettingsCategory = DetailBuilder . EditCategory ( " LodSettings " , LOCTEXT ( " LodSettingsCategory " , " LOD Settings " ) ) ;
IDetailCategoryBuilder & StaticMeshCategory = DetailBuilder . EditCategory ( " StaticMesh " , LOCTEXT ( " StaticMeshGeneralSettings " , " Static Mesh Settings " ) ) ;
IDetailCategoryBuilder & ImportCategory = DetailBuilder . EditCategory ( " ImportSettings " , LOCTEXT ( " ImportGeneralSettings " , " Import Settings " ) ) ;
2014-07-15 05:54:01 -04:00
2014-12-01 11:19:41 -05:00
DetailBuilder . EditCategory ( " Navigation " , FText : : GetEmpty ( ) , ECategoryPriority : : Uncommon ) ;
2014-03-14 14:13:41 -04:00
LevelOfDetailSettings = MakeShareable ( new FLevelOfDetailSettingsLayout ( StaticMeshEditor ) ) ;
LevelOfDetailSettings - > AddToDetailsPanel ( DetailBuilder ) ;
TSharedRef < IPropertyHandle > BodyProp = DetailBuilder . GetProperty ( " BodySetup " ) ;
BodyProp - > MarkHiddenByCustomization ( ) ;
static TArray < FName > HiddenBodyInstanceProps ;
if ( HiddenBodyInstanceProps . Num ( ) = = 0 )
{
HiddenBodyInstanceProps . Add ( " DefaultInstance " ) ;
HiddenBodyInstanceProps . Add ( " BoneName " ) ;
HiddenBodyInstanceProps . Add ( " PhysicsType " ) ;
HiddenBodyInstanceProps . Add ( " bConsiderForBounds " ) ;
HiddenBodyInstanceProps . Add ( " CollisionReponse " ) ;
}
uint32 NumChildren = 0 ;
BodyProp - > GetNumChildren ( NumChildren ) ;
TSharedPtr < IPropertyHandle > BodyPropObject ;
if ( NumChildren = = 1 )
{
// This is an edit inline new property so the first child is the object instance for the edit inline new. The instance contains the child we want to display
BodyPropObject = BodyProp - > GetChildHandle ( 0 ) ;
NumChildren = 0 ;
BodyPropObject - > GetNumChildren ( NumChildren ) ;
for ( uint32 ChildIndex = 0 ; ChildIndex < NumChildren ; + + ChildIndex )
{
TSharedPtr < IPropertyHandle > ChildProp = BodyPropObject - > GetChildHandle ( ChildIndex ) ;
if ( ChildProp . IsValid ( ) & & ChildProp - > GetProperty ( ) & & ! HiddenBodyInstanceProps . Contains ( ChildProp - > GetProperty ( ) - > GetFName ( ) ) )
{
StaticMeshCategory . AddProperty ( ChildProp ) ;
}
}
}
2014-07-15 05:54:01 -04:00
// Only add the reimport button if we have reimport settings we can modify
// Note: this will get rebuilt if the asset is reimported so we don't need to use .Visibility on the button
const UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
if ( StaticMesh - > AssetImportData & & StaticMesh - > AssetImportData - > GetClass ( ) ! = UAssetImportData : : StaticClass ( ) )
{
2014-12-01 11:19:41 -05:00
ImportCategory . AddCustomRow ( LOCTEXT ( " ReimportStaticMesh " , " Reimport Static Mesh " ) , true )
2014-07-15 05:54:01 -04:00
. ValueContent ( )
[
SNew ( SButton )
. OnClicked ( this , & FStaticMeshDetails : : Reimport )
. IsEnabled ( this , & FStaticMeshDetails : : CanReimport )
[
SNew ( STextBlock )
. Text ( LOCTEXT ( " Reimport " , " Reimport " ) )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
}
2014-03-14 14:13:41 -04:00
}
void SConvexDecomposition : : Construct ( const FArguments & InArgs )
{
StaticMeshEditorPtr = InArgs . _StaticMeshEditorPtr ;
2015-03-30 07:26:43 -04:00
CurrentHullAccuracy = DefaultHullAccuracy ;
2014-03-14 14:13:41 -04:00
CurrentMaxVertsPerHullCount = DefaultVertsPerHull ;
this - > ChildSlot
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 4.0f , 16.0f , 0.0f , 8.0f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
2015-03-30 07:26:43 -04:00
. Text ( LOCTEXT ( " HullAccuracy_ConvexDecomp " , " Accuracy " ) )
2014-03-14 14:13:41 -04:00
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 3.0f )
[
2015-03-30 07:26:43 -04:00
SAssignNew ( HullAccuracy , SSpinBox < float > )
. MinValue ( MinHullAccuracy )
. MaxValue ( MaxHullAccuracy )
. Delta ( HullAccuracyDelta )
. Value ( this , & SConvexDecomposition : : GetHullAccuracy )
. OnValueCommitted ( this , & SConvexDecomposition : : OnHullAccuracyCommitted )
. OnValueChanged ( this , & SConvexDecomposition : : OnHullAccuracyChanged )
2014-03-14 14:13:41 -04:00
]
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 4.0f , 8.0f , 0.0f , 16.0f )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. FillWidth ( 1.0f )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " MaxHullVerts_ConvexDecomp " , " Max Hull Verts " ) )
2014-03-14 14:13:41 -04:00
]
+ SHorizontalBox : : Slot ( )
. FillWidth ( 3.0f )
[
SAssignNew ( MaxVertsPerHull , SSpinBox < int32 > )
. MinValue ( MinVertsPerHullCount )
. MaxValue ( MaxVertsPerHullCount )
. Value ( this , & SConvexDecomposition : : GetVertsPerHullCount )
. OnValueCommitted ( this , & SConvexDecomposition : : OnVertsPerHullCountCommitted )
. OnValueChanged ( this , & SConvexDecomposition : : OnVertsPerHullCountChanged )
]
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. HAlign ( HAlign_Center )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 8.0f , 0.0f , 8.0f , 0.0f )
[
SNew ( SButton )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Apply_ConvexDecomp " , " Apply " ) )
2014-03-14 14:13:41 -04:00
. OnClicked ( this , & SConvexDecomposition : : OnApplyDecomp )
]
+ SHorizontalBox : : Slot ( )
. AutoWidth ( )
. Padding ( 8.0f , 0.0f , 8.0f , 0.0f )
[
SNew ( SButton )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Defaults_ConvexDecomp " , " Defaults " ) )
2014-03-14 14:13:41 -04:00
. OnClicked ( this , & SConvexDecomposition : : OnDefaults )
]
]
] ;
}
bool FStaticMeshDetails : : IsApplyNeeded ( ) const
{
return LevelOfDetailSettings . IsValid ( ) & & LevelOfDetailSettings - > IsApplyNeeded ( ) ;
}
void FStaticMeshDetails : : ApplyChanges ( )
{
if ( LevelOfDetailSettings . IsValid ( ) )
{
LevelOfDetailSettings - > ApplyChanges ( ) ;
}
}
2014-07-15 05:54:01 -04:00
FReply FStaticMeshDetails : : Reimport ( )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
FReimportManager : : Instance ( ) - > Reimport ( StaticMesh , true ) ;
return FReply : : Handled ( ) ;
}
bool FStaticMeshDetails : : CanReimport ( ) const
{
const UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
if ( StaticMesh - > AssetImportData )
{
return StaticMesh - > AssetImportData - > bDirty ;
}
return false ;
}
2014-03-14 14:13:41 -04:00
SConvexDecomposition : : ~ SConvexDecomposition ( )
{
}
FReply SConvexDecomposition : : OnApplyDecomp ( )
{
2015-03-30 07:26:43 -04:00
StaticMeshEditorPtr . Pin ( ) - > DoDecomp ( CurrentHullAccuracy , CurrentMaxVertsPerHullCount ) ;
2014-03-14 14:13:41 -04:00
return FReply : : Handled ( ) ;
}
FReply SConvexDecomposition : : OnDefaults ( )
{
2015-03-30 07:26:43 -04:00
CurrentHullAccuracy = DefaultHullAccuracy ;
2014-03-14 14:13:41 -04:00
CurrentMaxVertsPerHullCount = DefaultVertsPerHull ;
return FReply : : Handled ( ) ;
}
2015-03-30 07:26:43 -04:00
void SConvexDecomposition : : OnHullAccuracyCommitted ( float InNewValue , ETextCommit : : Type CommitInfo )
2014-03-14 14:13:41 -04:00
{
2015-03-30 07:26:43 -04:00
OnHullAccuracyChanged ( InNewValue ) ;
2014-03-14 14:13:41 -04:00
}
2015-03-30 07:26:43 -04:00
void SConvexDecomposition : : OnHullAccuracyChanged ( float InNewValue )
2014-03-14 14:13:41 -04:00
{
2015-03-30 07:26:43 -04:00
CurrentHullAccuracy = InNewValue ;
2014-03-14 14:13:41 -04:00
}
2015-03-30 07:26:43 -04:00
float SConvexDecomposition : : GetHullAccuracy ( ) const
2014-03-14 14:13:41 -04:00
{
2015-03-30 07:26:43 -04:00
return CurrentHullAccuracy ;
2014-03-14 14:13:41 -04:00
}
void SConvexDecomposition : : OnVertsPerHullCountCommitted ( int32 InNewValue , ETextCommit : : Type CommitInfo )
{
OnVertsPerHullCountChanged ( InNewValue ) ;
}
void SConvexDecomposition : : OnVertsPerHullCountChanged ( int32 InNewValue )
{
CurrentMaxVertsPerHullCount = InNewValue ;
}
int32 SConvexDecomposition : : GetVertsPerHullCount ( ) const
{
return CurrentMaxVertsPerHullCount ;
}
static UEnum & GetFeatureImportanceEnum ( )
{
static FName FeatureImportanceName ( TEXT ( " EMeshFeatureImportance::Off " ) ) ;
static UEnum * FeatureImportanceEnum = NULL ;
if ( FeatureImportanceEnum = = NULL )
{
UEnum : : LookupEnumName ( FeatureImportanceName , & FeatureImportanceEnum ) ;
check ( FeatureImportanceEnum ) ;
}
return * FeatureImportanceEnum ;
}
static void FillEnumOptions ( TArray < TSharedPtr < FString > > & OutStrings , UEnum & InEnum )
{
for ( int32 EnumIndex = 0 ; EnumIndex < InEnum . NumEnums ( ) - 1 ; + + EnumIndex )
{
OutStrings . Add ( MakeShareable ( new FString ( InEnum . GetEnumName ( EnumIndex ) ) ) ) ;
}
}
FMeshBuildSettingsLayout : : FMeshBuildSettingsLayout ( TSharedRef < FLevelOfDetailSettingsLayout > InParentLODSettings )
: ParentLODSettings ( InParentLODSettings )
{
}
FMeshBuildSettingsLayout : : ~ FMeshBuildSettingsLayout ( )
{
}
void FMeshBuildSettingsLayout : : GenerateHeaderRowContent ( FDetailWidgetRow & NodeRow )
{
NodeRow . NameContent ( )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " MeshBuildSettings " , " Build Settings " ) )
2014-03-14 14:13:41 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
] ;
}
2015-01-24 17:10:19 -05:00
FString FMeshBuildSettingsLayout : : GetCurrentDistanceFieldReplacementMeshPath ( ) const
{
return BuildSettings . DistanceFieldReplacementMesh ? BuildSettings . DistanceFieldReplacementMesh - > GetPathName ( ) : FString ( " " ) ;
}
void FMeshBuildSettingsLayout : : OnDistanceFieldReplacementMeshSelected ( const FAssetData & AssetData )
{
BuildSettings . DistanceFieldReplacementMesh = Cast < UStaticMesh > ( AssetData . GetAsset ( ) ) ;
}
2014-03-14 14:13:41 -04:00
void FMeshBuildSettingsLayout : : GenerateChildContent ( IDetailChildrenBuilder & ChildrenBuilder )
{
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " RecomputeNormals " , " Recompute Normals " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " RecomputeNormals " , " Recompute Normals " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldRecomputeNormals )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnRecomputeNormalsChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " RecomputeTangents " , " Recompute Tangents " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " RecomputeTangents " , " Recompute Tangents " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldRecomputeTangents )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnRecomputeTangentsChanged )
] ;
}
2014-12-02 11:42:29 -05:00
{
2015-04-21 11:52:55 -04:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " UseMikkTSpace " , " Use MikkTSpace Tangent Space " ) )
2014-12-02 11:42:29 -05:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2015-04-21 11:52:55 -04:00
. Text ( LOCTEXT ( " UseMikkTSpace " , " Use MikkTSpace Tangent Space " ) )
2014-12-02 11:42:29 -05:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldUseMikkTSpace )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnUseMikkTSpaceChanged )
] ;
}
2014-03-14 14:13:41 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " RemoveDegenerates " , " Remove Degenerates " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " RemoveDegenerates " , " Remove Degenerates " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldRemoveDegenerates )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnRemoveDegeneratesChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " UseFullPrecisionUVs " , " Use Full Precision UVs " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " UseFullPrecisionUVs " , " Use Full Precision UVs " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldUseFullPrecisionUVs )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnUseFullPrecisionUVsChanged )
] ;
}
2014-09-04 19:22:07 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " GenerateLightmapUVs " , " Generate Lightmap UVs " ) )
2014-09-04 19:22:07 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " GenerateLightmapUVs " , " Generate Lightmap UVs " ) )
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldGenerateLightmapUVs )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnGenerateLightmapUVsChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " MinLightmapResolution " , " Min Lightmap Resolution " ) )
2014-09-04 19:22:07 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-12-01 11:19:41 -05:00
. Text ( LOCTEXT ( " MinLightmapResolution " , " Min Lightmap Resolution " ) )
2014-09-04 19:22:07 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < int32 > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 1 )
. MaxValue ( 2048 )
. Value ( this , & FMeshBuildSettingsLayout : : GetMinLightmapResolution )
. OnValueChanged ( this , & FMeshBuildSettingsLayout : : OnMinLightmapResolutionChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " SourceLightmapIndex " , " Source Lightmap Index " ) )
2014-09-04 19:22:07 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-12-01 11:19:41 -05:00
. Text ( LOCTEXT ( " SourceLightmapIndex " , " Source Lightmap Index " ) )
2014-09-04 19:22:07 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < int32 > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0 )
2014-11-13 13:19:52 -05:00
. MaxValue ( 7 )
2014-09-04 19:22:07 -04:00
. Value ( this , & FMeshBuildSettingsLayout : : GetSrcLightmapIndex )
. OnValueChanged ( this , & FMeshBuildSettingsLayout : : OnSrcLightmapIndexChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " DestinationLightmapIndex " , " Destination Lightmap Index " ) )
2014-09-04 19:22:07 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-12-01 11:19:41 -05:00
. Text ( LOCTEXT ( " DestinationLightmapIndex " , " Destination Lightmap Index " ) )
2014-09-04 19:22:07 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < int32 > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0 )
2014-11-13 13:19:52 -05:00
. MaxValue ( 7 )
2014-09-04 19:22:07 -04:00
. Value ( this , & FMeshBuildSettingsLayout : : GetDstLightmapIndex )
. OnValueChanged ( this , & FMeshBuildSettingsLayout : : OnDstLightmapIndexChanged )
] ;
}
2014-03-14 14:13:41 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " BuildScale " , " Build Scale " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " BuildScale " , " Build Scale " ) )
2014-03-14 14:13:41 -04:00
. ToolTipText ( LOCTEXT ( " BuildScale_ToolTip " , " The local scale applied when building the mesh " ) )
]
. ValueContent ( )
2014-04-23 19:03:58 -04:00
. MinDesiredWidth ( 125.0f * 3.0f )
. MaxDesiredWidth ( 125.0f * 3.0f )
2014-03-14 14:13:41 -04:00
[
2014-04-23 19:03:58 -04:00
SNew ( SVectorInputBox )
. X ( this , & FMeshBuildSettingsLayout : : GetBuildScaleX )
. Y ( this , & FMeshBuildSettingsLayout : : GetBuildScaleY )
. Z ( this , & FMeshBuildSettingsLayout : : GetBuildScaleZ )
. bColorAxisLabels ( false )
. OnXCommitted ( this , & FMeshBuildSettingsLayout : : OnBuildScaleXChanged )
. OnYCommitted ( this , & FMeshBuildSettingsLayout : : OnBuildScaleYChanged )
2014-04-23 19:47:56 -04:00
. OnZCommitted ( this , & FMeshBuildSettingsLayout : : OnBuildScaleZChanged )
2014-04-23 19:03:58 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-03-14 14:13:41 -04:00
] ;
}
2014-06-03 15:53:13 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " DistanceFieldResolutionScale " , " Distance Field Resolution Scale " ) )
2014-06-03 15:53:13 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-12-01 11:19:41 -05:00
. Text ( LOCTEXT ( " DistanceFieldResolutionScale " , " Distance Field Resolution Scale " ) )
2014-06-03 15:53:13 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( 100.0f )
. Value ( this , & FMeshBuildSettingsLayout : : GetDistanceFieldResolutionScale )
. OnValueChanged ( this , & FMeshBuildSettingsLayout : : OnDistanceFieldResolutionScaleChanged )
2014-07-24 04:28:41 -04:00
. OnValueCommitted ( this , & FMeshBuildSettingsLayout : : OnDistanceFieldResolutionScaleCommitted )
2014-06-03 15:53:13 -04:00
] ;
}
2014-03-14 14:13:41 -04:00
2014-08-28 13:54:31 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " GenerateDistanceFieldAsIfTwoSided " , " Generate Distance Field as if TwoSided " ) )
2014-08-28 13:54:31 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-12-01 11:19:41 -05:00
. Text ( LOCTEXT ( " GenerateDistanceFieldAsIfTwoSided " , " Generate Distance Field as if TwoSided " ) )
2014-08-28 13:54:31 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshBuildSettingsLayout : : ShouldGenerateDistanceFieldAsIfTwoSided )
. OnCheckStateChanged ( this , & FMeshBuildSettingsLayout : : OnGenerateDistanceFieldAsIfTwoSidedChanged )
] ;
}
2015-01-24 17:10:19 -05:00
{
TSharedRef < SWidget > PropWidget = SNew ( SObjectPropertyEntryBox )
. AllowedClass ( UStaticMesh : : StaticClass ( ) )
. AllowClear ( true )
. ObjectPath ( this , & FMeshBuildSettingsLayout : : GetCurrentDistanceFieldReplacementMeshPath )
. OnObjectChanged ( this , & FMeshBuildSettingsLayout : : OnDistanceFieldReplacementMeshSelected ) ;
ChildrenBuilder . AddChildContent ( LOCTEXT ( " DistanceFieldReplacementMesh " , " Distance Field Replacement Mesh " ) )
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " DistanceFieldReplacementMesh " , " Distance Field Replacement Mesh " ) )
]
. ValueContent ( )
[
PropWidget
] ;
}
2014-03-14 14:13:41 -04:00
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. ValueContent ( )
. HAlign ( HAlign_Left )
[
SNew ( SButton )
. OnClicked ( this , & FMeshBuildSettingsLayout : : OnApplyChanges )
. IsEnabled ( ParentLODSettings . Pin ( ) . ToSharedRef ( ) , & FLevelOfDetailSettingsLayout : : IsApplyNeeded )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
}
}
void FMeshBuildSettingsLayout : : UpdateSettings ( const FMeshBuildSettings & InSettings )
{
BuildSettings = InSettings ;
}
FReply FMeshBuildSettingsLayout : : OnApplyChanges ( )
{
if ( ParentLODSettings . IsValid ( ) )
{
ParentLODSettings . Pin ( ) - > ApplyChanges ( ) ;
}
return FReply : : Handled ( ) ;
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldRecomputeNormals ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bRecomputeNormals ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldRecomputeTangents ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bRecomputeTangents ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldUseMikkTSpace ( ) const
2014-12-02 11:42:29 -05:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bUseMikkTSpace ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-12-02 11:42:29 -05:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldRemoveDegenerates ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bRemoveDegenerates ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldUseFullPrecisionUVs ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bUseFullPrecisionUVs ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldGenerateLightmapUVs ( ) const
2014-09-04 19:22:07 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bGenerateLightmapUVs ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-09-04 19:22:07 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshBuildSettingsLayout : : ShouldGenerateDistanceFieldAsIfTwoSided ( ) const
2014-08-28 13:54:31 -04:00
{
2014-12-10 14:24:09 -05:00
return BuildSettings . bGenerateDistanceFieldAsIfTwoSided ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-08-28 13:54:31 -04:00
}
2014-09-04 19:22:07 -04:00
int32 FMeshBuildSettingsLayout : : GetMinLightmapResolution ( ) const
{
return BuildSettings . MinLightmapResolution ;
}
int32 FMeshBuildSettingsLayout : : GetSrcLightmapIndex ( ) const
{
return BuildSettings . SrcLightmapIndex ;
}
int32 FMeshBuildSettingsLayout : : GetDstLightmapIndex ( ) const
{
return BuildSettings . DstLightmapIndex ;
}
2014-03-14 14:13:41 -04:00
TOptional < float > FMeshBuildSettingsLayout : : GetBuildScaleX ( ) const
{
return BuildSettings . BuildScale3D . X ;
}
TOptional < float > FMeshBuildSettingsLayout : : GetBuildScaleY ( ) const
{
return BuildSettings . BuildScale3D . Y ;
}
TOptional < float > FMeshBuildSettingsLayout : : GetBuildScaleZ ( ) const
{
return BuildSettings . BuildScale3D . Z ;
}
2014-06-03 15:53:13 -04:00
float FMeshBuildSettingsLayout : : GetDistanceFieldResolutionScale ( ) const
{
return BuildSettings . DistanceFieldResolutionScale ;
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnRecomputeNormalsChanged ( ECheckBoxState NewState )
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bRecomputeNormals = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-07-24 04:28:41 -04:00
if ( BuildSettings . bRecomputeNormals ! = bRecomputeNormals )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bRecomputeNormals " ) , bRecomputeNormals ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
2014-07-24 04:28:41 -04:00
}
BuildSettings . bRecomputeNormals = bRecomputeNormals ;
}
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnRecomputeTangentsChanged ( ECheckBoxState NewState )
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bRecomputeTangents = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-07-24 04:28:41 -04:00
if ( BuildSettings . bRecomputeTangents ! = bRecomputeTangents )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bRecomputeTangents " ) , bRecomputeTangents ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
2014-07-24 04:28:41 -04:00
}
BuildSettings . bRecomputeTangents = bRecomputeTangents ;
}
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnUseMikkTSpaceChanged ( ECheckBoxState NewState )
2014-12-02 11:42:29 -05:00
{
2014-12-10 14:24:09 -05:00
const bool bUseMikkTSpace = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-12-02 11:42:29 -05:00
if ( BuildSettings . bUseMikkTSpace ! = bUseMikkTSpace )
{
BuildSettings . bUseMikkTSpace = bUseMikkTSpace ;
}
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnRemoveDegeneratesChanged ( ECheckBoxState NewState )
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bRemoveDegenerates = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-07-24 04:28:41 -04:00
if ( BuildSettings . bRemoveDegenerates ! = bRemoveDegenerates )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bRemoveDegenerates " ) , bRemoveDegenerates ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
2014-07-24 04:28:41 -04:00
}
BuildSettings . bRemoveDegenerates = bRemoveDegenerates ;
}
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnUseFullPrecisionUVsChanged ( ECheckBoxState NewState )
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bUseFullPrecisionUVs = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-07-24 04:28:41 -04:00
if ( BuildSettings . bUseFullPrecisionUVs ! = bUseFullPrecisionUVs )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bUseFullPrecisionUVs " ) , bUseFullPrecisionUVs ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
2014-07-24 04:28:41 -04:00
}
BuildSettings . bUseFullPrecisionUVs = bUseFullPrecisionUVs ;
}
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnGenerateLightmapUVsChanged ( ECheckBoxState NewState )
2014-09-04 19:22:07 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bGenerateLightmapUVs = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-09-04 19:22:07 -04:00
if ( BuildSettings . bGenerateLightmapUVs ! = bGenerateLightmapUVs )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bGenerateLightmapUVs " ) , bGenerateLightmapUVs ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
}
BuildSettings . bGenerateLightmapUVs = bGenerateLightmapUVs ;
}
}
2014-12-10 14:24:09 -05:00
void FMeshBuildSettingsLayout : : OnGenerateDistanceFieldAsIfTwoSidedChanged ( ECheckBoxState NewState )
2014-08-28 13:54:31 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bGenerateDistanceFieldAsIfTwoSided = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-08-28 13:54:31 -04:00
if ( BuildSettings . bGenerateDistanceFieldAsIfTwoSided ! = bGenerateDistanceFieldAsIfTwoSided )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " bGenerateDistanceFieldAsIfTwoSided " ) , bGenerateDistanceFieldAsIfTwoSided ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
}
BuildSettings . bGenerateDistanceFieldAsIfTwoSided = bGenerateDistanceFieldAsIfTwoSided ;
}
}
2014-09-04 19:22:07 -04:00
void FMeshBuildSettingsLayout : : OnMinLightmapResolutionChanged ( int32 NewValue )
{
if ( BuildSettings . MinLightmapResolution ! = NewValue )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " MinLightmapResolution " ) , FString : : Printf ( TEXT ( " %i " ) , NewValue ) ) ;
}
BuildSettings . MinLightmapResolution = NewValue ;
}
}
void FMeshBuildSettingsLayout : : OnSrcLightmapIndexChanged ( int32 NewValue )
{
if ( BuildSettings . SrcLightmapIndex ! = NewValue )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " SrcLightmapIndex " ) , FString : : Printf ( TEXT ( " %i " ) , NewValue ) ) ;
}
BuildSettings . SrcLightmapIndex = NewValue ;
}
}
void FMeshBuildSettingsLayout : : OnDstLightmapIndexChanged ( int32 NewValue )
{
if ( BuildSettings . DstLightmapIndex ! = NewValue )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " DstLightmapIndex " ) , FString : : Printf ( TEXT ( " %i " ) , NewValue ) ) ;
}
BuildSettings . DstLightmapIndex = NewValue ;
}
}
2014-04-23 19:03:58 -04:00
void FMeshBuildSettingsLayout : : OnBuildScaleXChanged ( float NewScaleX , ETextCommit : : Type TextCommitType )
2014-03-14 14:13:41 -04:00
{
2014-07-24 04:28:41 -04:00
if ( ! FMath : : IsNearlyEqual ( NewScaleX , 0.0f ) & & BuildSettings . BuildScale3D . X ! = NewScaleX )
2014-04-25 10:40:02 -04:00
{
2014-07-24 04:28:41 -04:00
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " BuildScale3D.X " ) , FString : : Printf ( TEXT ( " %.3f " ) , NewScaleX ) ) ;
2014-07-24 04:28:41 -04:00
}
2014-04-25 10:40:02 -04:00
BuildSettings . BuildScale3D . X = NewScaleX ;
}
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:03:58 -04:00
void FMeshBuildSettingsLayout : : OnBuildScaleYChanged ( float NewScaleY , ETextCommit : : Type TextCommitType )
2014-03-14 14:13:41 -04:00
{
2014-07-24 04:28:41 -04:00
if ( ! FMath : : IsNearlyEqual ( NewScaleY , 0.0f ) & & BuildSettings . BuildScale3D . Y ! = NewScaleY )
2014-04-25 10:40:02 -04:00
{
2014-07-24 04:28:41 -04:00
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " BuildScale3D.Y " ) , FString : : Printf ( TEXT ( " %.3f " ) , NewScaleY ) ) ;
2014-07-24 04:28:41 -04:00
}
2014-04-25 10:40:02 -04:00
BuildSettings . BuildScale3D . Y = NewScaleY ;
}
2014-03-14 14:13:41 -04:00
}
2014-04-23 19:03:58 -04:00
void FMeshBuildSettingsLayout : : OnBuildScaleZChanged ( float NewScaleZ , ETextCommit : : Type TextCommitType )
2014-03-14 14:13:41 -04:00
{
2014-07-24 04:28:41 -04:00
if ( ! FMath : : IsNearlyEqual ( NewScaleZ , 0.0f ) & & BuildSettings . BuildScale3D . Z ! = NewScaleZ )
2014-04-25 10:40:02 -04:00
{
2014-07-24 04:28:41 -04:00
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " BuildScale3D.Z " ) , FString : : Printf ( TEXT ( " %.3f " ) , NewScaleZ ) ) ;
2014-07-24 04:28:41 -04:00
}
2014-04-25 10:40:02 -04:00
BuildSettings . BuildScale3D . Z = NewScaleZ ;
}
2014-03-14 14:13:41 -04:00
}
2014-06-03 15:53:13 -04:00
void FMeshBuildSettingsLayout : : OnDistanceFieldResolutionScaleChanged ( float NewValue )
{
BuildSettings . DistanceFieldResolutionScale = NewValue ;
}
2014-07-24 04:28:41 -04:00
void FMeshBuildSettingsLayout : : OnDistanceFieldResolutionScaleCommitted ( float NewValue , ETextCommit : : Type TextCommitType )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-01 05:31:22 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.BuildSettings " ) , TEXT ( " DistanceFieldResolutionScale " ) , FString : : Printf ( TEXT ( " %.3f " ) , NewValue ) ) ;
2014-07-24 04:28:41 -04:00
}
OnDistanceFieldResolutionScaleChanged ( NewValue ) ;
}
2014-03-14 14:13:41 -04:00
FMeshReductionSettingsLayout : : FMeshReductionSettingsLayout ( TSharedRef < FLevelOfDetailSettingsLayout > InParentLODSettings )
: ParentLODSettings ( InParentLODSettings )
{
FillEnumOptions ( ImportanceOptions , GetFeatureImportanceEnum ( ) ) ;
}
FMeshReductionSettingsLayout : : ~ FMeshReductionSettingsLayout ( )
{
}
void FMeshReductionSettingsLayout : : GenerateHeaderRowContent ( FDetailWidgetRow & NodeRow )
{
NodeRow . NameContent ( )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " MeshReductionSettings " , " Reduction Settings " ) )
2014-03-14 14:13:41 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
] ;
}
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void FMeshReductionSettingsLayout : : GenerateChildContent ( IDetailChildrenBuilder & ChildrenBuilder )
{
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " PercentTriangles " , " Percent Triangles " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " PercentTriangles " , " Percent Triangles " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( 100.0f )
. Value ( this , & FMeshReductionSettingsLayout : : GetPercentTriangles )
. OnValueChanged ( this , & FMeshReductionSettingsLayout : : OnPercentTrianglesChanged )
2014-07-24 04:28:41 -04:00
. OnValueCommitted ( this , & FMeshReductionSettingsLayout : : OnPercentTrianglesCommitted )
2014-03-14 14:13:41 -04:00
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " MaxDeviation " , " Max Deviation " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " MaxDeviation " , " Max Deviation " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( 1000.0f )
. Value ( this , & FMeshReductionSettingsLayout : : GetMaxDeviation )
. OnValueChanged ( this , & FMeshReductionSettingsLayout : : OnMaxDeviationChanged )
2014-07-24 04:28:41 -04:00
. OnValueCommitted ( this , & FMeshReductionSettingsLayout : : OnMaxDeviationCommitted )
2014-03-14 14:13:41 -04:00
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " Silhouette_MeshSimplification " , " Silhouette " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Silhouette_MeshSimplification " , " Silhouette " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SAssignNew ( SilhouetteCombo , STextComboBox )
//.Font( IDetailLayoutBuilder::GetDetailFont() )
. ContentPadding ( 0 )
. OptionsSource ( & ImportanceOptions )
. InitiallySelectedItem ( ImportanceOptions [ ReductionSettings . SilhouetteImportance ] )
. OnSelectionChanged ( this , & FMeshReductionSettingsLayout : : OnSilhouetteImportanceChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " Texture_MeshSimplification " , " Texture " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Texture_MeshSimplification " , " Texture " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SAssignNew ( TextureCombo , STextComboBox )
//.Font( IDetailLayoutBuilder::GetDetailFont() )
. ContentPadding ( 0 )
. OptionsSource ( & ImportanceOptions )
. InitiallySelectedItem ( ImportanceOptions [ ReductionSettings . TextureImportance ] )
. OnSelectionChanged ( this , & FMeshReductionSettingsLayout : : OnTextureImportanceChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " Shading_MeshSimplification " , " Shading " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Shading_MeshSimplification " , " Shading " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SAssignNew ( ShadingCombo , STextComboBox )
//.Font( IDetailLayoutBuilder::GetDetailFont() )
. ContentPadding ( 0 )
. OptionsSource ( & ImportanceOptions )
. InitiallySelectedItem ( ImportanceOptions [ ReductionSettings . ShadingImportance ] )
. OnSelectionChanged ( this , & FMeshReductionSettingsLayout : : OnShadingImportanceChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " WeldingThreshold " , " Welding Threshold " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " WeldingThreshold " , " Welding Threshold " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( 10.0f )
. Value ( this , & FMeshReductionSettingsLayout : : GetWeldingThreshold )
2014-07-24 04:28:41 -04:00
. OnValueChanged ( this , & FMeshReductionSettingsLayout : : OnWeldingThresholdChanged )
. OnValueCommitted ( this , & FMeshReductionSettingsLayout : : OnWeldingThresholdCommitted )
2014-03-14 14:13:41 -04:00
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " RecomputeNormals " , " Recompute Normals " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " RecomputeNormals " , " Recompute Normals " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshReductionSettingsLayout : : ShouldRecalculateNormals )
. OnCheckStateChanged ( this , & FMeshReductionSettingsLayout : : OnRecalculateNormalsChanged )
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " HardEdgeAngle " , " Hard Edge Angle " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " HardEdgeAngle " , " Hard Edge Angle " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( 180.0f )
. Value ( this , & FMeshReductionSettingsLayout : : GetHardAngleThreshold )
. OnValueChanged ( this , & FMeshReductionSettingsLayout : : OnHardAngleThresholdChanged )
2014-07-24 04:28:41 -04:00
. OnValueCommitted ( this , & FMeshReductionSettingsLayout : : OnHardAngleThresholdCommitted )
2014-03-14 14:13:41 -04:00
] ;
}
{
2014-12-01 11:19:41 -05:00
ChildrenBuilder . AddChildContent ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. ValueContent ( )
. HAlign ( HAlign_Left )
[
SNew ( SButton )
. OnClicked ( this , & FMeshReductionSettingsLayout : : OnApplyChanges )
. IsEnabled ( ParentLODSettings . Pin ( ) . ToSharedRef ( ) , & FLevelOfDetailSettingsLayout : : IsApplyNeeded )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
]
] ;
}
SilhouetteCombo - > SetSelectedItem ( ImportanceOptions [ ReductionSettings . SilhouetteImportance ] ) ;
TextureCombo - > SetSelectedItem ( ImportanceOptions [ ReductionSettings . TextureImportance ] ) ;
ShadingCombo - > SetSelectedItem ( ImportanceOptions [ ReductionSettings . ShadingImportance ] ) ;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
const FMeshReductionSettings & FMeshReductionSettingsLayout : : GetSettings ( ) const
{
return ReductionSettings ;
}
void FMeshReductionSettingsLayout : : UpdateSettings ( const FMeshReductionSettings & InSettings )
{
ReductionSettings = InSettings ;
}
FReply FMeshReductionSettingsLayout : : OnApplyChanges ( )
{
if ( ParentLODSettings . IsValid ( ) )
{
ParentLODSettings . Pin ( ) - > ApplyChanges ( ) ;
}
return FReply : : Handled ( ) ;
}
float FMeshReductionSettingsLayout : : GetPercentTriangles ( ) const
{
return ReductionSettings . PercentTriangles * 100.0f ; // Display fraction as percentage.
}
float FMeshReductionSettingsLayout : : GetMaxDeviation ( ) const
{
return ReductionSettings . MaxDeviation ;
}
float FMeshReductionSettingsLayout : : GetWeldingThreshold ( ) const
{
return ReductionSettings . WeldingThreshold ;
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshReductionSettingsLayout : : ShouldRecalculateNormals ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return ReductionSettings . bRecalculateNormals ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
float FMeshReductionSettingsLayout : : GetHardAngleThreshold ( ) const
{
return ReductionSettings . HardAngleThreshold ;
}
void FMeshReductionSettingsLayout : : OnPercentTrianglesChanged ( float NewValue )
{
// Percentage -> fraction.
ReductionSettings . PercentTriangles = NewValue * 0.01f ;
}
2014-07-24 04:28:41 -04:00
void FMeshReductionSettingsLayout : : OnPercentTrianglesCommitted ( float NewValue , ETextCommit : : Type TextCommitType )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " PercentTriangles " ) , FString : : Printf ( TEXT ( " %.1f " ) , NewValue ) ) ;
2014-07-24 04:28:41 -04:00
}
OnPercentTrianglesChanged ( NewValue ) ;
}
2014-03-14 14:13:41 -04:00
void FMeshReductionSettingsLayout : : OnMaxDeviationChanged ( float NewValue )
{
ReductionSettings . MaxDeviation = NewValue ;
}
2014-07-24 04:28:41 -04:00
void FMeshReductionSettingsLayout : : OnMaxDeviationCommitted ( float NewValue , ETextCommit : : Type TextCommitType )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " MaxDeviation " ) , FString : : Printf ( TEXT ( " %.1f " ) , NewValue ) ) ;
2014-07-24 04:28:41 -04:00
}
OnMaxDeviationChanged ( NewValue ) ;
}
2014-03-14 14:13:41 -04:00
void FMeshReductionSettingsLayout : : OnWeldingThresholdChanged ( float NewValue )
{
ReductionSettings . WeldingThreshold = NewValue ;
}
2014-07-24 04:28:41 -04:00
void FMeshReductionSettingsLayout : : OnWeldingThresholdCommitted ( float NewValue , ETextCommit : : Type TextCommitType )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " WeldingThreshold " ) , FString : : Printf ( TEXT ( " %.2f " ) , NewValue ) ) ;
2014-07-24 04:28:41 -04:00
}
OnWeldingThresholdChanged ( NewValue ) ;
}
2014-12-10 14:24:09 -05:00
void FMeshReductionSettingsLayout : : OnRecalculateNormalsChanged ( ECheckBoxState NewValue )
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
const bool bRecalculateNormals = NewValue = = ECheckBoxState : : Checked ;
2014-07-24 04:28:41 -04:00
if ( ReductionSettings . bRecalculateNormals ! = bRecalculateNormals )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " bRecalculateNormals " ) , bRecalculateNormals ? TEXT ( " True " ) : TEXT ( " False " ) ) ;
2014-07-24 04:28:41 -04:00
}
ReductionSettings . bRecalculateNormals = bRecalculateNormals ;
}
2014-03-14 14:13:41 -04:00
}
void FMeshReductionSettingsLayout : : OnHardAngleThresholdChanged ( float NewValue )
{
ReductionSettings . HardAngleThreshold = NewValue ;
}
2014-07-24 04:28:41 -04:00
void FMeshReductionSettingsLayout : : OnHardAngleThresholdCommitted ( float NewValue , ETextCommit : : Type TextCommitType )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " HardAngleThreshold " ) , FString : : Printf ( TEXT ( " %.3f " ) , NewValue ) ) ;
2014-07-24 04:28:41 -04:00
}
OnHardAngleThresholdChanged ( NewValue ) ;
}
2014-03-14 14:13:41 -04:00
void FMeshReductionSettingsLayout : : OnSilhouetteImportanceChanged ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
2014-07-24 04:28:41 -04:00
const EMeshFeatureImportance : : Type SilhouetteImportance = ( EMeshFeatureImportance : : Type ) ImportanceOptions . Find ( NewValue ) ;
if ( ReductionSettings . SilhouetteImportance ! = SilhouetteImportance )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " SilhouetteImportance " ) , * NewValue . Get ( ) ) ;
2014-07-24 04:28:41 -04:00
}
ReductionSettings . SilhouetteImportance = SilhouetteImportance ;
}
2014-03-14 14:13:41 -04:00
}
void FMeshReductionSettingsLayout : : OnTextureImportanceChanged ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
2014-07-24 04:28:41 -04:00
const EMeshFeatureImportance : : Type TextureImportance = ( EMeshFeatureImportance : : Type ) ImportanceOptions . Find ( NewValue ) ;
if ( ReductionSettings . TextureImportance ! = TextureImportance )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " TextureImportance " ) , * NewValue . Get ( ) ) ;
2014-07-24 04:28:41 -04:00
}
ReductionSettings . TextureImportance = TextureImportance ;
}
2014-03-14 14:13:41 -04:00
}
void FMeshReductionSettingsLayout : : OnShadingImportanceChanged ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
2014-07-24 04:28:41 -04:00
const EMeshFeatureImportance : : Type ShadingImportance = ( EMeshFeatureImportance : : Type ) ImportanceOptions . Find ( NewValue ) ;
if ( ReductionSettings . ShadingImportance ! = ShadingImportance )
{
if ( FEngineAnalytics : : IsAvailable ( ) )
{
2014-08-05 05:38:43 -04:00
FEngineAnalytics : : GetProvider ( ) . RecordEvent ( TEXT ( " Editor.Usage.StaticMesh.ReductionSettings " ) , TEXT ( " ShadingImportance " ) , * NewValue . Get ( ) ) ;
2014-07-24 04:28:41 -04:00
}
ReductionSettings . ShadingImportance = ShadingImportance ;
}
2014-03-14 14:13:41 -04:00
}
FMeshSectionSettingsLayout : : ~ FMeshSectionSettingsLayout ( )
{
}
UStaticMesh & FMeshSectionSettingsLayout : : GetStaticMesh ( ) const
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
return * StaticMesh ;
}
void FMeshSectionSettingsLayout : : AddToCategory ( IDetailCategoryBuilder & CategoryBuilder )
{
FMaterialListDelegates MaterialListDelegates ;
MaterialListDelegates . OnGetMaterials . BindSP ( this , & FMeshSectionSettingsLayout : : GetMaterials ) ;
MaterialListDelegates . OnMaterialChanged . BindSP ( this , & FMeshSectionSettingsLayout : : OnMaterialChanged ) ;
MaterialListDelegates . OnGenerateCustomNameWidgets . BindSP ( this , & FMeshSectionSettingsLayout : : OnGenerateNameWidgetsForMaterial ) ;
MaterialListDelegates . OnGenerateCustomMaterialWidgets . BindSP ( this , & FMeshSectionSettingsLayout : : OnGenerateWidgetsForMaterial ) ;
MaterialListDelegates . OnResetMaterialToDefaultClicked . BindSP ( this , & FMeshSectionSettingsLayout : : OnResetMaterialToDefaultClicked ) ;
CategoryBuilder . AddCustomBuilder ( MakeShareable ( new FMaterialList ( CategoryBuilder . GetParentLayout ( ) , MaterialListDelegates ) ) ) ;
}
void FMeshSectionSettingsLayout : : GetMaterials ( IMaterialListBuilder & ListBuilder )
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
FStaticMeshRenderData * RenderData = StaticMesh . RenderData ;
if ( RenderData & & RenderData - > LODResources . IsValidIndex ( LODIndex ) )
{
FStaticMeshLODResources & LOD = RenderData - > LODResources [ LODIndex ] ;
int32 NumSections = LOD . Sections . Num ( ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < NumSections ; + + SectionIndex )
{
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SectionIndex ) ;
UMaterialInterface * SectionMaterial = StaticMesh . GetMaterial ( Info . MaterialIndex ) ;
if ( SectionMaterial = = NULL )
{
SectionMaterial = UMaterial : : GetDefaultMaterial ( MD_Surface ) ;
}
ListBuilder . AddMaterial ( SectionIndex , SectionMaterial , /*bCanBeReplaced=*/ true ) ;
}
}
}
void FMeshSectionSettingsLayout : : OnMaterialChanged ( UMaterialInterface * NewMaterial , UMaterialInterface * PrevMaterial , int32 SlotIndex , bool bReplaceAll )
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
2014-06-03 10:17:00 -04:00
// flag the property (Materials) we're modifying so that not all of the object is rebuilt.
UProperty * ChangedProperty = NULL ;
ChangedProperty = FindField < UProperty > ( UStaticMesh : : StaticClass ( ) , " Materials " ) ;
check ( ChangedProperty ) ;
StaticMesh . PreEditChange ( ChangedProperty ) ;
2014-03-14 14:13:41 -04:00
check ( StaticMesh . RenderData ) ;
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SlotIndex ) ;
if ( LODIndex = = 0 )
{
check ( Info . MaterialIndex = = SlotIndex ) ;
check ( StaticMesh . Materials . IsValidIndex ( SlotIndex ) ) ;
StaticMesh . Materials [ SlotIndex ] = NewMaterial ;
}
else
{
int32 NumBaseSections = StaticMesh . RenderData - > LODResources [ 0 ] . Sections . Num ( ) ;
if ( Info . MaterialIndex < NumBaseSections )
{
// The LOD's section was using the same material as in the base LOD (common case).
Info . MaterialIndex = StaticMesh . Materials . Add ( NewMaterial ) ;
StaticMesh . SectionInfoMap . Set ( LODIndex , SlotIndex , Info ) ;
}
else
{
// The LOD's section was already overriding the base LOD material.
StaticMesh . Materials [ Info . MaterialIndex ] = NewMaterial ;
}
}
2014-06-03 10:17:00 -04:00
CallPostEditChange ( ChangedProperty ) ;
2014-03-14 14:13:41 -04:00
}
TSharedRef < SWidget > FMeshSectionSettingsLayout : : OnGenerateNameWidgetsForMaterial ( UMaterialInterface * Material , int32 SlotIndex )
{
return
SNew ( SCheckBox )
. IsChecked ( this , & FMeshSectionSettingsLayout : : IsSectionSelected , SlotIndex )
. OnCheckStateChanged ( this , & FMeshSectionSettingsLayout : : OnSectionSelectedChanged , SlotIndex )
2014-04-23 18:06:41 -04:00
. ToolTipText ( LOCTEXT ( " Highlight_ToolTip " , " Highlights this section in the viewport " ) )
2014-03-14 14:13:41 -04:00
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. ColorAndOpacity ( FLinearColor ( 0.4f , 0.4f , 0.4f , 1.0f ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " Highlight " , " Highlight " ) )
2014-03-14 14:13:41 -04:00
] ;
}
TSharedRef < SWidget > FMeshSectionSettingsLayout : : OnGenerateWidgetsForMaterial ( UMaterialInterface * Material , int32 SlotIndex )
{
return SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshSectionSettingsLayout : : DoesSectionCastShadow , SlotIndex )
. OnCheckStateChanged ( this , & FMeshSectionSettingsLayout : : OnSectionCastShadowChanged , SlotIndex )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " CastShadow " , " Cast Shadow " ) )
2014-03-14 14:13:41 -04:00
]
]
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
. Padding ( 0 , 2 , 0 , 0 )
[
SNew ( SCheckBox )
. IsChecked ( this , & FMeshSectionSettingsLayout : : DoesSectionCollide , SlotIndex )
. OnCheckStateChanged ( this , & FMeshSectionSettingsLayout : : OnSectionCollisionChanged , SlotIndex )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " EnableCollision " , " Enable Collision " ) )
2014-03-14 14:13:41 -04:00
]
] ;
}
void FMeshSectionSettingsLayout : : OnResetMaterialToDefaultClicked ( UMaterialInterface * Material , int32 SlotIndex )
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
if ( LODIndex = = 0 )
{
check ( StaticMesh . Materials . IsValidIndex ( SlotIndex ) ) ;
StaticMesh . Materials [ SlotIndex ] = UMaterial : : GetDefaultMaterial ( MD_Surface ) ;
}
else
{
// Reset this LOD's section to use the material in the corresponding section of LOD0.
StaticMesh . SectionInfoMap . Remove ( LODIndex , SlotIndex ) ;
}
CallPostEditChange ( ) ;
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshSectionSettingsLayout : : DoesSectionCastShadow ( int32 SectionIndex ) const
2014-03-14 14:13:41 -04:00
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SectionIndex ) ;
2014-12-10 14:24:09 -05:00
return Info . bCastShadow ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshSectionSettingsLayout : : OnSectionCastShadowChanged ( ECheckBoxState NewState , int32 SectionIndex )
2014-03-14 14:13:41 -04:00
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SectionIndex ) ;
2014-12-10 14:24:09 -05:00
Info . bCastShadow = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-03-14 14:13:41 -04:00
StaticMesh . SectionInfoMap . Set ( LODIndex , SectionIndex , Info ) ;
CallPostEditChange ( ) ;
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshSectionSettingsLayout : : DoesSectionCollide ( int32 SectionIndex ) const
2014-03-14 14:13:41 -04:00
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SectionIndex ) ;
2014-12-10 14:24:09 -05:00
return Info . bEnableCollision ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FMeshSectionSettingsLayout : : OnSectionCollisionChanged ( ECheckBoxState NewState , int32 SectionIndex )
2014-03-14 14:13:41 -04:00
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
FMeshSectionInfo Info = StaticMesh . SectionInfoMap . Get ( LODIndex , SectionIndex ) ;
2014-12-10 14:24:09 -05:00
Info . bEnableCollision = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-03-14 14:13:41 -04:00
StaticMesh . SectionInfoMap . Set ( LODIndex , SectionIndex , Info ) ;
CallPostEditChange ( ) ;
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FMeshSectionSettingsLayout : : IsSectionSelected ( int32 SectionIndex ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
ECheckBoxState State = ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
UStaticMeshComponent * Component = StaticMeshEditor . GetStaticMeshComponent ( ) ;
if ( Component )
{
2014-12-10 14:24:09 -05:00
State = Component - > SelectedEditorSection = = SectionIndex ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
return State ;
}
2014-12-10 14:24:09 -05:00
void FMeshSectionSettingsLayout : : OnSectionSelectedChanged ( ECheckBoxState NewState , int32 SectionIndex )
2014-03-14 14:13:41 -04:00
{
UStaticMeshComponent * Component = StaticMeshEditor . GetStaticMeshComponent ( ) ;
if ( Component )
{
2014-12-10 14:24:09 -05:00
if ( NewState = = ECheckBoxState : : Checked )
2014-03-14 14:13:41 -04:00
{
Component - > SelectedEditorSection = SectionIndex ;
}
2014-12-10 14:24:09 -05:00
else if ( NewState = = ECheckBoxState : : Unchecked )
2014-03-14 14:13:41 -04:00
{
Component - > SelectedEditorSection = INDEX_NONE ;
}
Component - > MarkRenderStateDirty ( ) ;
StaticMeshEditor . RefreshViewport ( ) ;
}
}
2014-06-03 10:17:00 -04:00
void FMeshSectionSettingsLayout : : CallPostEditChange ( UProperty * PropertyChanged /*=nullptr*/ )
2014-03-14 14:13:41 -04:00
{
UStaticMesh & StaticMesh = GetStaticMesh ( ) ;
2014-06-03 10:17:00 -04:00
if ( PropertyChanged )
{
FPropertyChangedEvent PropertyUpdateStruct ( PropertyChanged ) ;
StaticMesh . PostEditChangeProperty ( PropertyUpdateStruct ) ;
}
else
{
StaticMesh . Modify ( ) ;
StaticMesh . PostEditChange ( ) ;
}
2014-03-14 14:13:41 -04:00
if ( StaticMesh . BodySetup )
{
StaticMesh . BodySetup - > CreatePhysicsMeshes ( ) ;
}
StaticMeshEditor . RefreshViewport ( ) ;
}
/////////////////////////////////
// FLevelOfDetailSettingsLayout
/////////////////////////////////
FLevelOfDetailSettingsLayout : : FLevelOfDetailSettingsLayout ( FStaticMeshEditor & InStaticMeshEditor )
: StaticMeshEditor ( InStaticMeshEditor )
{
LODGroupNames . Reset ( ) ;
UStaticMesh : : GetLODGroups ( LODGroupNames ) ;
for ( int32 GroupIndex = 0 ; GroupIndex < LODGroupNames . Num ( ) ; + + GroupIndex )
{
LODGroupOptions . Add ( MakeShareable ( new FString ( LODGroupNames [ GroupIndex ] . GetPlainNameString ( ) ) ) ) ;
}
for ( int32 i = 0 ; i < MAX_STATIC_MESH_LODS ; + + i )
{
bBuildSettingsExpanded [ i ] = false ;
bReductionSettingsExpanded [ i ] = false ;
bSectionSettingsExpanded [ i ] = ( i = = 0 ) ;
2014-05-07 05:33:26 -04:00
LODScreenSizes [ i ] = 0.0f ;
2014-03-14 14:13:41 -04:00
}
LODCount = StaticMeshEditor . GetStaticMesh ( ) - > GetNumLODs ( ) ;
UpdateLODNames ( ) ;
}
/** Returns true if automatic mesh reduction is available. */
static bool IsAutoMeshReductionAvailable ( )
{
static bool bAutoMeshReductionAvailable = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshUtilities > ( " MeshUtilities " ) . GetMeshReductionInterface ( ) ! = NULL ;
return bAutoMeshReductionAvailable ;
}
void FLevelOfDetailSettingsLayout : : AddToDetailsPanel ( IDetailLayoutBuilder & DetailBuilder )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
IDetailCategoryBuilder & LODSettingsCategory =
2014-12-01 11:19:41 -05:00
DetailBuilder . EditCategory ( " LodSettings " , LOCTEXT ( " LodSettingsCategory " , " LOD Settings " ) ) ;
2014-03-14 14:13:41 -04:00
2015-04-20 10:31:58 -04:00
int32 LODGroupIndex = LODGroupNames . Find ( StaticMesh - > LODGroup ) ;
check ( LODGroupIndex = = INDEX_NONE | | LODGroupIndex < LODGroupOptions . Num ( ) ) ;
2014-03-14 14:13:41 -04:00
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " LODGroup " , " LOD Group " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " LODGroup " , " LOD Group " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( STextComboBox )
. ContentPadding ( 0 )
. OptionsSource ( & LODGroupOptions )
2015-04-20 10:31:58 -04:00
. InitiallySelectedItem ( LODGroupOptions [ ( LODGroupIndex = = INDEX_NONE ) ? 0 : LODGroupIndex ] )
2014-03-14 14:13:41 -04:00
. OnSelectionChanged ( this , & FLevelOfDetailSettingsLayout : : OnLODGroupChanged )
] ;
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " LODImport " , " LOD Import " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " LODImport " , " LOD Import " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( STextComboBox )
. ContentPadding ( 0 )
. OptionsSource ( & LODNames )
. InitiallySelectedItem ( LODNames [ 0 ] )
. OnSelectionChanged ( this , & FLevelOfDetailSettingsLayout : : OnImportLOD )
] ;
2015-03-02 13:07:20 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " MinLOD " , " Minimum LOD " ) )
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " MinLOD " , " Minimum LOD " ) )
]
. ValueContent ( )
[
SNew ( SSpinBox < int32 > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Value ( this , & FLevelOfDetailSettingsLayout : : GetMinLOD )
. OnValueChanged ( this , & FLevelOfDetailSettingsLayout : : OnMinLODChanged )
. OnValueCommitted ( this , & FLevelOfDetailSettingsLayout : : OnMinLODCommitted )
. MinValue ( 0 )
. MaxValue ( MAX_STATIC_MESH_LODS )
. ToolTipText ( this , & FLevelOfDetailSettingsLayout : : GetMinLODTooltip )
. IsEnabled ( FLevelOfDetailSettingsLayout : : GetLODCount ( ) > 1 )
] ;
2014-03-14 14:13:41 -04:00
// Add Number of LODs slider.
const int32 MinAllowedLOD = 1 ;
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " NumberOfLODs " , " Number of LODs " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " NumberOfLODs " , " Number of LODs " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < int32 > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Value ( this , & FLevelOfDetailSettingsLayout : : GetLODCount )
. OnValueChanged ( this , & FLevelOfDetailSettingsLayout : : OnLODCountChanged )
. OnValueCommitted ( this , & FLevelOfDetailSettingsLayout : : OnLODCountCommitted )
. MinValue ( MinAllowedLOD )
. MaxValue ( MAX_STATIC_MESH_LODS )
. ToolTipText ( this , & FLevelOfDetailSettingsLayout : : GetLODCountTooltip )
. IsEnabled ( IsAutoMeshReductionAvailable ( ) )
] ;
// Auto LOD distance check box.
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " AutoComputeLOD " , " Auto Compute LOD Distances " ) )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " AutoComputeLOD " , " Auto Compute LOD Distances " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SCheckBox )
. IsChecked ( this , & FLevelOfDetailSettingsLayout : : IsAutoLODChecked )
. OnCheckStateChanged ( this , & FLevelOfDetailSettingsLayout : : OnAutoLODChanged )
] ;
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. ValueContent ( )
. HAlign ( HAlign_Left )
[
SNew ( SButton )
. OnClicked ( this , & FLevelOfDetailSettingsLayout : : OnApply )
. IsEnabled ( this , & FLevelOfDetailSettingsLayout : : IsApplyNeeded )
[
SNew ( STextBlock )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " ApplyChanges " , " Apply Changes " ) )
2014-03-14 14:13:41 -04:00
. Font ( DetailBuilder . GetDetailFont ( ) )
]
] ;
bool bAdvanced = true ;
// Allowed pixel error.
2014-12-01 11:19:41 -05:00
LODSettingsCategory . AddCustomRow ( LOCTEXT ( " AllowedPixelError " , " Auto Distance Error " ) , bAdvanced )
2014-03-14 14:13:41 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
2014-04-23 18:06:41 -04:00
. Text ( LOCTEXT ( " AllowedPixelError " , " Auto Distance Error " ) )
2014-03-14 14:13:41 -04:00
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
. MinValue ( 1.0f )
. MaxValue ( 100.0f )
. MinSliderValue ( 1.0f )
. MaxSliderValue ( 5.0f )
. Value ( this , & FLevelOfDetailSettingsLayout : : GetPixelError )
. OnValueChanged ( this , & FLevelOfDetailSettingsLayout : : OnPixelErrorChanged )
. IsEnabled ( this , & FLevelOfDetailSettingsLayout : : IsAutoLODEnabled )
] ;
AddLODLevelCategories ( DetailBuilder ) ;
}
void FLevelOfDetailSettingsLayout : : AddLODLevelCategories ( IDetailLayoutBuilder & DetailBuilder )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
if ( StaticMesh )
{
const int32 StaticMeshLODCount = StaticMesh - > GetNumLODs ( ) ;
FStaticMeshRenderData * RenderData = StaticMesh - > RenderData ;
// Create information panel for each LOD level.
for ( int32 LODIndex = 0 ; LODIndex < StaticMeshLODCount ; + + LODIndex )
{
if ( IsAutoMeshReductionAvailable ( ) )
{
ReductionSettingsWidgets [ LODIndex ] = MakeShareable ( new FMeshReductionSettingsLayout ( AsShared ( ) ) ) ;
}
if ( LODIndex < StaticMesh - > SourceModels . Num ( ) )
{
FStaticMeshSourceModel & SrcModel = StaticMesh - > SourceModels [ LODIndex ] ;
if ( ReductionSettingsWidgets [ LODIndex ] . IsValid ( ) )
{
ReductionSettingsWidgets [ LODIndex ] - > UpdateSettings ( SrcModel . ReductionSettings ) ;
}
if ( SrcModel . RawMeshBulkData - > IsEmpty ( ) = = false )
{
BuildSettingsWidgets [ LODIndex ] = MakeShareable ( new FMeshBuildSettingsLayout ( AsShared ( ) ) ) ;
BuildSettingsWidgets [ LODIndex ] - > UpdateSettings ( SrcModel . BuildSettings ) ;
}
2014-05-07 05:33:26 -04:00
LODScreenSizes [ LODIndex ] = SrcModel . ScreenSize ;
2014-03-14 14:13:41 -04:00
}
else if ( LODIndex > 0 )
{
if ( ReductionSettingsWidgets [ LODIndex ] . IsValid ( ) & & ReductionSettingsWidgets [ LODIndex - 1 ] . IsValid ( ) )
{
FMeshReductionSettings ReductionSettings = ReductionSettingsWidgets [ LODIndex - 1 ] - > GetSettings ( ) ;
// By default create LODs with half the triangles of the previous LOD.
ReductionSettings . PercentTriangles * = 0.5f ;
ReductionSettingsWidgets [ LODIndex ] - > UpdateSettings ( ReductionSettings ) ;
}
2014-05-07 05:33:26 -04:00
if ( LODScreenSizes [ LODIndex ] > = LODScreenSizes [ LODIndex - 1 ] )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
const float DefaultScreenSizeDifference = 0.01f ;
LODScreenSizes [ LODIndex ] = LODScreenSizes [ LODIndex - 1 ] - DefaultScreenSizeDifference ;
2014-03-14 14:13:41 -04:00
}
}
FString CategoryName = FString ( TEXT ( " LOD " ) ) ;
CategoryName . AppendInt ( LODIndex ) ;
2014-12-01 11:19:41 -05:00
FText LODLevelString = FText : : Format ( LOCTEXT ( " LODLevel " , " LOD{0} " ) , FText : : AsNumber ( LODIndex ) ) ;
2014-03-14 14:13:41 -04:00
IDetailCategoryBuilder & LODCategory = DetailBuilder . EditCategory ( * CategoryName , LODLevelString , ECategoryPriority : : Important ) ;
LODCategory . HeaderContent
(
SNew ( SBox )
. HAlign ( HAlign_Right )
[
SNew ( SHorizontalBox )
+ SHorizontalBox : : Slot ( )
2014-05-07 05:33:26 -04:00
. Padding ( FMargin ( 5.0f , 0.0f ) )
2014-03-14 14:13:41 -04:00
. AutoWidth ( )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
2014-05-07 05:33:26 -04:00
. Text ( this , & FLevelOfDetailSettingsLayout : : GetLODScreenSizeTitle , LODIndex )
2014-03-14 14:13:41 -04:00
. Visibility ( LODIndex > 0 ? EVisibility : : Visible : EVisibility : : Collapsed )
]
+ SHorizontalBox : : Slot ( )
. Padding ( FMargin ( 5.0f , 0.0f ) )
. AutoWidth ( )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
. Text ( FText : : Format ( LOCTEXT ( " Triangles_MeshSimplification " , " Triangles: {0} " ) , FText : : AsNumber ( StaticMeshEditor . GetNumTriangles ( LODIndex ) ) ) )
]
+ SHorizontalBox : : Slot ( )
. Padding ( FMargin ( 5.0f , 0.0f ) )
. AutoWidth ( )
[
SNew ( STextBlock )
. Font ( FEditorStyle : : GetFontStyle ( " StaticMeshEditor.NormalFont " ) )
. Text ( FText : : Format ( LOCTEXT ( " Vertices_MeshSimplification " , " Vertices: {0} " ) , FText : : AsNumber ( StaticMeshEditor . GetNumVertices ( LODIndex ) ) ) )
]
]
) ;
SectionSettingsWidgets [ LODIndex ] = MakeShareable ( new FMeshSectionSettingsLayout ( StaticMeshEditor , LODIndex ) ) ;
SectionSettingsWidgets [ LODIndex ] - > AddToCategory ( LODCategory ) ;
2014-12-01 11:19:41 -05:00
LODCategory . AddCustomRow ( ( LOCTEXT ( " ScreenSizeRow " , " ScreenSize " ) ) )
2014-05-07 05:33:26 -04:00
. NameContent ( )
[
SNew ( STextBlock )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. Text ( LOCTEXT ( " ScreenSizeName " , " Screen Size " ) )
]
. ValueContent ( )
[
SNew ( SSpinBox < float > )
. Font ( IDetailLayoutBuilder : : GetDetailFont ( ) )
. MinValue ( 0.0f )
. MaxValue ( WORLD_MAX )
. SliderExponent ( 2.0f )
. Value ( this , & FLevelOfDetailSettingsLayout : : GetLODScreenSize , LODIndex )
. OnValueChanged ( this , & FLevelOfDetailSettingsLayout : : OnLODScreenSizeChanged , LODIndex )
. OnValueCommitted ( this , & FLevelOfDetailSettingsLayout : : OnLODScreenSizeCommitted , LODIndex )
. IsEnabled ( this , & FLevelOfDetailSettingsLayout : : CanChangeLODScreenSize )
] ;
2014-03-14 14:13:41 -04:00
if ( BuildSettingsWidgets [ LODIndex ] . IsValid ( ) )
{
LODCategory . AddCustomBuilder ( BuildSettingsWidgets [ LODIndex ] . ToSharedRef ( ) ) ;
}
if ( ReductionSettingsWidgets [ LODIndex ] . IsValid ( ) )
{
LODCategory . AddCustomBuilder ( ReductionSettingsWidgets [ LODIndex ] . ToSharedRef ( ) ) ;
}
}
}
}
FLevelOfDetailSettingsLayout : : ~ FLevelOfDetailSettingsLayout ( )
{
}
int32 FLevelOfDetailSettingsLayout : : GetLODCount ( ) const
{
return LODCount ;
}
2014-05-07 05:33:26 -04:00
float FLevelOfDetailSettingsLayout : : GetLODScreenSize ( int32 LODIndex ) const
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
check ( LODIndex < MAX_STATIC_MESH_LODS ) ;
UStaticMesh * Mesh = StaticMeshEditor . GetStaticMesh ( ) ;
float ScreenSize = LODScreenSizes [ FMath : : Clamp ( LODIndex , 0 , MAX_STATIC_MESH_LODS - 1 ) ] ;
if ( Mesh - > bAutoComputeLODScreenSize )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
ScreenSize = Mesh - > RenderData - > ScreenSize [ LODIndex ] ;
2014-03-14 14:13:41 -04:00
}
2014-05-07 05:33:26 -04:00
else if ( Mesh - > SourceModels . IsValidIndex ( LODIndex ) )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
ScreenSize = Mesh - > SourceModels [ LODIndex ] . ScreenSize ;
2014-03-14 14:13:41 -04:00
}
2014-05-07 05:33:26 -04:00
return ScreenSize ;
2014-03-14 14:13:41 -04:00
}
2014-05-07 05:33:26 -04:00
FText FLevelOfDetailSettingsLayout : : GetLODScreenSizeTitle ( int32 LODIndex ) const
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
return FText : : Format ( LOCTEXT ( " ScreenSize_MeshSimplification " , " Screen Size: {0} " ) , FText : : AsNumber ( GetLODScreenSize ( LODIndex ) ) ) ;
2014-03-14 14:13:41 -04:00
}
2014-05-07 05:33:26 -04:00
bool FLevelOfDetailSettingsLayout : : CanChangeLODScreenSize ( ) const
2014-03-14 14:13:41 -04:00
{
return ! IsAutoLODEnabled ( ) ;
}
2014-05-07 05:33:26 -04:00
void FLevelOfDetailSettingsLayout : : OnLODScreenSizeChanged ( float NewValue , int32 LODIndex )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
check ( LODIndex < MAX_STATIC_MESH_LODS ) ;
2014-03-14 14:13:41 -04:00
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
2014-05-07 05:33:26 -04:00
if ( ! StaticMesh - > bAutoComputeLODScreenSize )
2014-03-14 14:13:41 -04:00
{
// First propagate any changes from the source models to our local scratch.
for ( int32 i = 0 ; i < StaticMesh - > SourceModels . Num ( ) ; + + i )
{
2014-05-07 05:33:26 -04:00
LODScreenSizes [ i ] = StaticMesh - > SourceModels [ i ] . ScreenSize ;
2014-03-14 14:13:41 -04:00
}
2014-05-07 05:33:26 -04:00
// Update Display factors for further LODs
2014-09-17 09:45:51 -04:00
const float MinimumDifferenceInScreenSize = KINDA_SMALL_NUMBER ;
2014-05-07 05:33:26 -04:00
LODScreenSizes [ LODIndex ] = NewValue ;
// Make sure we aren't trying to ovelap or have more than one LOD for a value
2014-03-14 14:13:41 -04:00
for ( int32 i = 1 ; i < MAX_STATIC_MESH_LODS ; + + i )
{
2014-05-07 05:33:26 -04:00
float MaxValue = FMath : : Clamp ( LODScreenSizes [ i - 1 ] - MinimumDifferenceInScreenSize , 0.0f , 1.0f ) ;
LODScreenSizes [ i ] = FMath : : Min ( LODScreenSizes [ i ] , MaxValue ) ;
2014-03-14 14:13:41 -04:00
}
// Push changes immediately.
for ( int32 i = 0 ; i < MAX_STATIC_MESH_LODS ; + + i )
{
if ( StaticMesh - > SourceModels . IsValidIndex ( i ) )
{
2014-05-07 05:33:26 -04:00
StaticMesh - > SourceModels [ i ] . ScreenSize = LODScreenSizes [ i ] ;
2014-03-14 14:13:41 -04:00
}
if ( StaticMesh - > RenderData
& & StaticMesh - > RenderData - > LODResources . IsValidIndex ( i ) )
{
2014-05-07 05:33:26 -04:00
StaticMesh - > RenderData - > ScreenSize [ i ] = LODScreenSizes [ i ] ;
2014-03-14 14:13:41 -04:00
}
}
// Reregister static mesh components using this mesh.
{
FStaticMeshComponentRecreateRenderStateContext ReregisterContext ( StaticMesh , false ) ;
StaticMesh - > Modify ( ) ;
}
StaticMeshEditor . RefreshViewport ( ) ;
}
}
2014-05-07 05:33:26 -04:00
void FLevelOfDetailSettingsLayout : : OnLODScreenSizeCommitted ( float NewValue , ETextCommit : : Type CommitType , int32 LODIndex )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
OnLODScreenSizeChanged ( NewValue , LODIndex ) ;
2014-03-14 14:13:41 -04:00
}
void FLevelOfDetailSettingsLayout : : UpdateLODNames ( )
{
LODNames . Empty ( ) ;
LODNames . Add ( MakeShareable ( new FString ( LOCTEXT ( " BaseLOD " , " Base LOD " ) . ToString ( ) ) ) ) ;
for ( int32 LODLevelID = 1 ; LODLevelID < LODCount ; + + LODLevelID )
{
LODNames . Add ( MakeShareable ( new FString ( FText : : Format ( NSLOCTEXT ( " LODSettingsLayout " , " LODLevel_Reimport " , " Reimport LOD Level {0} " ) , FText : : AsNumber ( LODLevelID ) ) . ToString ( ) ) ) ) ;
}
LODNames . Add ( MakeShareable ( new FString ( FText : : Format ( NSLOCTEXT ( " LODSettingsLayout " , " LODLevel_Import " , " Import LOD Level {0} " ) , FText : : AsNumber ( LODCount ) ) . ToString ( ) ) ) ) ;
}
void FLevelOfDetailSettingsLayout : : OnBuildSettingsExpanded ( bool bIsExpanded , int32 LODIndex )
{
check ( LODIndex > = 0 & & LODIndex < MAX_STATIC_MESH_LODS ) ;
bBuildSettingsExpanded [ LODIndex ] = bIsExpanded ;
}
void FLevelOfDetailSettingsLayout : : OnReductionSettingsExpanded ( bool bIsExpanded , int32 LODIndex )
{
check ( LODIndex > = 0 & & LODIndex < MAX_STATIC_MESH_LODS ) ;
bReductionSettingsExpanded [ LODIndex ] = bIsExpanded ;
}
void FLevelOfDetailSettingsLayout : : OnSectionSettingsExpanded ( bool bIsExpanded , int32 LODIndex )
{
check ( LODIndex > = 0 & & LODIndex < MAX_STATIC_MESH_LODS ) ;
bSectionSettingsExpanded [ LODIndex ] = bIsExpanded ;
}
void FLevelOfDetailSettingsLayout : : OnLODGroupChanged ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
int32 GroupIndex = LODGroupOptions . Find ( NewValue ) ;
FName NewGroup = LODGroupNames [ GroupIndex ] ;
if ( StaticMesh - > LODGroup ! = NewGroup )
{
StaticMesh - > Modify ( ) ;
StaticMesh - > LODGroup = NewGroup ;
EAppReturnType : : Type DialogResult = FMessageDialog : : Open (
EAppMsgType : : YesNo ,
FText : : Format ( LOCTEXT ( " ApplyDefaultLODSettings " , " Overwrite settings with the defaults from LOD group '{0}'? " ) , FText : : FromString ( * * NewValue ) )
) ;
if ( DialogResult = = EAppReturnType : : Yes )
{
const ITargetPlatform * Platform = GetTargetPlatformManagerRef ( ) . GetRunningTargetPlatform ( ) ;
check ( Platform ) ;
const FStaticMeshLODGroup & GroupSettings = Platform - > GetStaticMeshLODSettings ( ) . GetLODGroup ( NewGroup ) ;
2015-02-10 13:26:36 -05:00
// Set the number of LODs to at least the default. If there are already LODs they will be preserved, with default settings of the new LOD group.
int32 DefaultLODCount = GroupSettings . GetDefaultNumLODs ( ) ;
while ( StaticMesh - > SourceModels . Num ( ) < DefaultLODCount )
2014-03-14 14:13:41 -04:00
{
new ( StaticMesh - > SourceModels ) FStaticMeshSourceModel ( ) ;
}
2015-02-10 13:26:36 -05:00
LODCount = DefaultLODCount ;
2014-03-14 14:13:41 -04:00
// Set reduction settings to the defaults.
for ( int32 LODIndex = 0 ; LODIndex < LODCount ; + + LODIndex )
{
StaticMesh - > SourceModels [ LODIndex ] . ReductionSettings = GroupSettings . GetDefaultSettings ( LODIndex ) ;
}
2014-05-07 05:33:26 -04:00
StaticMesh - > bAutoComputeLODScreenSize = true ;
2014-03-14 14:13:41 -04:00
StaticMesh - > LightMapResolution = GroupSettings . GetDefaultLightMapResolution ( ) ;
}
StaticMesh - > PostEditChange ( ) ;
StaticMeshEditor . RefreshTool ( ) ;
}
}
bool FLevelOfDetailSettingsLayout : : IsAutoLODEnabled ( ) const
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
2014-05-07 05:33:26 -04:00
return StaticMesh - > bAutoComputeLODScreenSize ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
ECheckBoxState FLevelOfDetailSettingsLayout : : IsAutoLODChecked ( ) const
2014-03-14 14:13:41 -04:00
{
2014-12-10 14:24:09 -05:00
return IsAutoLODEnabled ( ) ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 14:24:09 -05:00
void FLevelOfDetailSettingsLayout : : OnAutoLODChanged ( ECheckBoxState NewState )
2014-03-14 14:13:41 -04:00
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
StaticMesh - > Modify ( ) ;
2014-12-10 14:24:09 -05:00
StaticMesh - > bAutoComputeLODScreenSize = ( NewState = = ECheckBoxState : : Checked ) ? true : false ;
2014-05-07 05:33:26 -04:00
if ( ! StaticMesh - > bAutoComputeLODScreenSize )
2014-03-14 14:13:41 -04:00
{
if ( StaticMesh - > SourceModels . IsValidIndex ( 0 ) )
{
2014-05-07 05:33:26 -04:00
StaticMesh - > SourceModels [ 0 ] . ScreenSize = 1.0f ;
2014-03-14 14:13:41 -04:00
}
for ( int32 LODIndex = 1 ; LODIndex < StaticMesh - > SourceModels . Num ( ) ; + + LODIndex )
{
2014-05-07 05:33:26 -04:00
StaticMesh - > SourceModels [ LODIndex ] . ScreenSize = StaticMesh - > RenderData - > ScreenSize [ LODIndex ] ;
2014-03-14 14:13:41 -04:00
}
}
StaticMesh - > PostEditChange ( ) ;
StaticMeshEditor . RefreshTool ( ) ;
}
float FLevelOfDetailSettingsLayout : : GetPixelError ( ) const
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
return StaticMesh - > AutoLODPixelError ;
}
void FLevelOfDetailSettingsLayout : : OnPixelErrorChanged ( float NewValue )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
{
FStaticMeshComponentRecreateRenderStateContext ReregisterContext ( StaticMesh , false ) ;
StaticMesh - > AutoLODPixelError = NewValue ;
StaticMesh - > RenderData - > ResolveSectionInfo ( StaticMesh ) ;
StaticMesh - > Modify ( ) ;
}
StaticMeshEditor . RefreshViewport ( ) ;
}
void FLevelOfDetailSettingsLayout : : OnImportLOD ( TSharedPtr < FString > NewValue , ESelectInfo : : Type SelectInfo )
{
int32 LODIndex = 0 ;
if ( LODNames . Find ( NewValue , LODIndex ) & & LODIndex > 0 )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
FbxMeshUtils : : ImportMeshLODDialog ( StaticMesh , LODIndex ) ;
2014-04-02 18:09:23 -04:00
StaticMesh - > PostEditChange ( ) ;
2014-03-14 14:13:41 -04:00
StaticMeshEditor . RefreshTool ( ) ;
}
}
bool FLevelOfDetailSettingsLayout : : IsApplyNeeded ( ) const
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
if ( StaticMesh - > SourceModels . Num ( ) ! = LODCount )
{
return true ;
}
for ( int32 LODIndex = 0 ; LODIndex < LODCount ; + + LODIndex )
{
FStaticMeshSourceModel & SrcModel = StaticMesh - > SourceModels [ LODIndex ] ;
if ( BuildSettingsWidgets [ LODIndex ] . IsValid ( )
& & SrcModel . BuildSettings ! = BuildSettingsWidgets [ LODIndex ] - > GetSettings ( ) )
{
return true ;
}
if ( ReductionSettingsWidgets [ LODIndex ] . IsValid ( )
& & SrcModel . ReductionSettings ! = ReductionSettingsWidgets [ LODIndex ] - > GetSettings ( ) )
{
return true ;
}
}
return false ;
}
void FLevelOfDetailSettingsLayout : : ApplyChanges ( )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
// Calling Begin and EndSlowTask are rather dangerous because they tick
// Slate. Call them here and flush rendering commands to be sure!.
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " StaticMeshName " ) , FText : : FromString ( StaticMesh - > GetName ( ) ) ) ;
GWarn - > BeginSlowTask ( FText : : Format ( LOCTEXT ( " ApplyLODChanges " , " Applying changes to {StaticMeshName}... " ) , Args ) , true ) ;
FlushRenderingCommands ( ) ;
StaticMesh - > Modify ( ) ;
if ( StaticMesh - > SourceModels . Num ( ) > LODCount )
{
int32 NumToRemove = StaticMesh - > SourceModels . Num ( ) - LODCount ;
StaticMesh - > SourceModels . RemoveAt ( LODCount , NumToRemove ) ;
}
while ( StaticMesh - > SourceModels . Num ( ) < LODCount )
{
new ( StaticMesh - > SourceModels ) FStaticMeshSourceModel ( ) ;
}
check ( StaticMesh - > SourceModels . Num ( ) = = LODCount ) ;
for ( int32 LODIndex = 0 ; LODIndex < LODCount ; + + LODIndex )
{
FStaticMeshSourceModel & SrcModel = StaticMesh - > SourceModels [ LODIndex ] ;
if ( BuildSettingsWidgets [ LODIndex ] . IsValid ( ) )
{
SrcModel . BuildSettings = BuildSettingsWidgets [ LODIndex ] - > GetSettings ( ) ;
}
if ( ReductionSettingsWidgets [ LODIndex ] . IsValid ( ) )
{
SrcModel . ReductionSettings = ReductionSettingsWidgets [ LODIndex ] - > GetSettings ( ) ;
}
if ( LODIndex = = 0 )
{
2014-05-07 05:33:26 -04:00
SrcModel . ScreenSize = 1.0f ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-05-07 05:33:26 -04:00
SrcModel . ScreenSize = LODScreenSizes [ LODIndex ] ;
2014-03-14 14:13:41 -04:00
FStaticMeshSourceModel & PrevModel = StaticMesh - > SourceModels [ LODIndex - 1 ] ;
2014-05-07 05:33:26 -04:00
if ( SrcModel . ScreenSize > = PrevModel . ScreenSize )
2014-03-14 14:13:41 -04:00
{
2014-05-07 05:33:26 -04:00
const float DefaultScreenSizeDifference = 0.01f ;
LODScreenSizes [ LODIndex ] = LODScreenSizes [ LODIndex - 1 ] - DefaultScreenSizeDifference ;
// Make sure there are no incorrectly overlapping values
SrcModel . ScreenSize = 1.0f - 0.01f * LODIndex ;
2014-03-14 14:13:41 -04:00
}
}
}
StaticMesh - > PostEditChange ( ) ;
GWarn - > EndSlowTask ( ) ;
StaticMeshEditor . RefreshTool ( ) ;
}
FReply FLevelOfDetailSettingsLayout : : OnApply ( )
{
ApplyChanges ( ) ;
return FReply : : Handled ( ) ;
}
void FLevelOfDetailSettingsLayout : : OnLODCountChanged ( int32 NewValue )
{
LODCount = FMath : : Clamp < int32 > ( NewValue , 1 , MAX_STATIC_MESH_LODS ) ;
UpdateLODNames ( ) ;
}
void FLevelOfDetailSettingsLayout : : OnLODCountCommitted ( int32 InValue , ETextCommit : : Type CommitInfo )
{
OnLODCountChanged ( InValue ) ;
}
FText FLevelOfDetailSettingsLayout : : GetLODCountTooltip ( ) const
{
if ( IsAutoMeshReductionAvailable ( ) )
{
return LOCTEXT ( " LODCountTooltip " , " The number of LODs for this static mesh. If auto mesh reduction is available, setting this number will determine the number of LOD levels to auto generate. " ) ;
}
return LOCTEXT ( " LODCountTooltip_Disabled " , " Auto mesh reduction is unavailable! Please provide a mesh reduction interface such as Simplygon to use this feature or manually import LOD levels. " ) ;
}
2015-03-02 13:07:20 -05:00
int32 FLevelOfDetailSettingsLayout : : GetMinLOD ( ) const
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
return StaticMesh - > MinLOD ;
}
void FLevelOfDetailSettingsLayout : : OnMinLODChanged ( int32 NewValue )
{
UStaticMesh * StaticMesh = StaticMeshEditor . GetStaticMesh ( ) ;
check ( StaticMesh ) ;
{
FStaticMeshComponentRecreateRenderStateContext ReregisterContext ( StaticMesh , false ) ;
StaticMesh - > MinLOD = FMath : : Clamp < int32 > ( NewValue , 0 , MAX_STATIC_MESH_LODS - 1 ) ;
StaticMesh - > Modify ( ) ;
}
StaticMeshEditor . RefreshViewport ( ) ;
}
void FLevelOfDetailSettingsLayout : : OnMinLODCommitted ( int32 InValue , ETextCommit : : Type CommitInfo )
{
OnMinLODChanged ( InValue ) ;
}
FText FLevelOfDetailSettingsLayout : : GetMinLODTooltip ( ) const
{
return LOCTEXT ( " MinLODTooltip " , " The minimum LOD to use for rendering. This can be overridden in components. " ) ;
}
2014-03-14 14:13:41 -04:00
# undef LOCTEXT_NAMESPACE