// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "CoreMinimal.h" #include "SlateFwd.h" #include "Engine/EngineTypes.h" #include "Layout/Visibility.h" #include "Input/Reply.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SWidget.h" #include "Widgets/SCompoundWidget.h" #include "Widgets/SBoxPanel.h" #include "Engine/MeshMerging.h" #include "Engine/StaticMesh.h" #include "IDetailCustomization.h" #include "Widgets/Input/SSpinBox.h" #include "IDetailCustomNodeBuilder.h" struct FAssetData; class FAssetThumbnailPool; class FDetailWidgetRow; class FLevelOfDetailSettingsLayout; class FNaniteSettingsLayout; class FStaticMeshEditor; class IDetailCategoryBuilder; class IDetailChildrenBuilder; class IDetailLayoutBuilder; class IDetailGroup; class IStaticMeshEditor; class UMaterialInterface; struct FSectionLocalizer; enum ECreationModeChoice { CreateNew, UseChannel0, }; enum ELimitModeChoice { Stretching, Charts }; class FStaticMeshDetails : public IDetailCustomization { public: FStaticMeshDetails( class FStaticMeshEditor& InStaticMeshEditor ); ~FStaticMeshDetails(); /** IDetailCustomization interface */ virtual void CustomizeDetails( class IDetailLayoutBuilder& DetailBuilder ) override; /** @return true if settings have been changed and need to be applied to the static mesh */ bool IsApplyNeeded() const; /** Applies changes to the static mesh */ void ApplyChanges(); private: /** Level of detail settings for the details panel */ TSharedPtr LevelOfDetailSettings; /** Nanite settings for the details panel. */ TSharedPtr NaniteSettings; /** Static mesh editor */ class FStaticMeshEditor& StaticMeshEditor; // Property handle used to determine if the VertexColorImportOverride property should be enabled. TSharedPtr VertexColorImportOptionHandle; // Property handle used during UI construction TSharedPtr VertexColorImportOverrideHandle; // Delegate implementation of FOnInstancedPropertyIteration used during DataImport UI construction void OnInstancedFbxStaticMeshImportDataPropertyIteration(IDetailCategoryBuilder& BaseCategory, IDetailGroup* PropertyGroup, TSharedRef& Property) const; // Delegate to ensure the lightmap settings are always valid. void OnLightmapSettingsChanged(); // Delegate used at runtime to determine the state of the VertexOverrideColor property bool GetVertexOverrideColorEnabledState() const; }; /** * Window handles convex decomposition, settings and controls. */ class SConvexDecomposition : public SCompoundWidget { public: SLATE_BEGIN_ARGS( SConvexDecomposition ) : _StaticMeshEditorPtr() { } /** The Static Mesh Editor this tool is associated with. */ SLATE_ARGUMENT( TWeakPtr< IStaticMeshEditor >, StaticMeshEditorPtr ) SLATE_END_ARGS() void Construct(const FArguments& InArgs); virtual ~SConvexDecomposition(); private: /** Callback when the "Apply" button is clicked. */ FReply OnApplyDecomp(); /** Callback when the "Defaults" button is clicked. */ FReply OnDefaults(); /** Assigns the accuracy of hulls based on the spinbox's value. */ void OnHullCountCommitted(uint32 InNewValue, ETextCommit::Type CommitInfo); /** Assigns the accuracy of hulls based on the spinbox's value. */ void OnHullCountChanged(uint32 InNewValue); /** Retrieves the precision of hulls created. */ uint32 GetHullPrecision() const; /** Assigns the precision of hulls based on the spinbox's value. */ void OnHullPrecisionCommitted(uint32 InNewValue, ETextCommit::Type CommitInfo); /** Assigns the precision of hulls based on the spinbox's value. */ void OnHullPrecisionChanged(uint32 InNewValue); /** Retrieves the accuracy of hulls created. */ uint32 GetHullCount() const; /** Assigns the max number of hulls based on the spinbox's value. */ void OnVertsPerHullCountCommitted(int32 InNewValue, ETextCommit::Type CommitInfo); /** Assigns the max number of hulls based on the spinbox's value. */ void OnVertsPerHullCountChanged(int32 InNewValue); /** * Retrieves the max number of verts per hull allowed. * * @return The max number of verts per hull selected. */ int32 GetVertsPerHullCount() const; private: /** The Static Mesh Editor this tool is associated with. */ TWeakPtr StaticMeshEditorPtr; /** Spinbox for the max number of hulls allowed. */ TSharedPtr< SSpinBox > HullCount; /** Spinbox for the convex decomposition precision allowed. */ TSharedPtr< SSpinBox > HullPrecision; /** The current number of max number of hulls selected. */ uint32 CurrentHullCount; /** The current precision level for convex decomposition */ uint32 CurrentHullPrecision; /** Spinbox for the max number of verts per hulls allowed. */ TSharedPtr< SSpinBox > MaxVertsPerHull; /** The current number of max verts per hull selected. */ int32 CurrentMaxVertsPerHullCount; }; class FMeshBuildSettingsLayout : public IDetailCustomNodeBuilder, public TSharedFromThis { public: FMeshBuildSettingsLayout( TSharedRef InParentLODSettings, int32 InLODIndex ); virtual ~FMeshBuildSettingsLayout(); const FMeshBuildSettings& GetSettings() const { return BuildSettings; } void UpdateSettings(const FMeshBuildSettings& InSettings); private: /** IDetailCustomNodeBuilder Interface*/ virtual void SetOnRebuildChildren( FSimpleDelegate InOnRegenerateChildren ) override {} virtual void GenerateHeaderRowContent( FDetailWidgetRow& NodeRow ) override; virtual void GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder ) override; virtual void Tick( float DeltaTime ) override{} virtual bool RequiresTick() const override { return false; } virtual FName GetName() const override { static FName MeshBuildSettings("MeshBuildSettings"); return MeshBuildSettings; } virtual bool InitiallyCollapsed() const override { return true; } FReply OnApplyChanges(); ECheckBoxState ShouldRecomputeNormals() const; ECheckBoxState ShouldRecomputeTangents() const; ECheckBoxState ShouldUseMikkTSpace() const; ECheckBoxState ShouldComputeWeightedNormals() const; ECheckBoxState ShouldRemoveDegenerates() const; ECheckBoxState ShouldBuildReversedIndexBuffer() const; ECheckBoxState ShouldUseHighPrecisionTangentBasis() const; ECheckBoxState ShouldUseFullPrecisionUVs() const; ECheckBoxState ShouldUseBackwardsCompatibleF16TruncUVs() const; ECheckBoxState ShouldGenerateLightmapUVs() const; ECheckBoxState ShouldGenerateDistanceFieldAsIfTwoSided() const; bool IsRemoveDegeneratesDisabled() const; int32 GetMinLightmapResolution() const; int32 GetSrcLightmapIndex() const; int32 GetDstLightmapIndex() const; TOptional GetBuildScaleX() const; TOptional GetBuildScaleY() const; TOptional GetBuildScaleZ() const; float GetDistanceFieldResolutionScale() const; int32 GetMaxLumenMeshCards() const; void OnRecomputeNormalsChanged(ECheckBoxState NewState); void OnRecomputeTangentsChanged(ECheckBoxState NewState); void OnUseMikkTSpaceChanged(ECheckBoxState NewState); void OnComputeWeightedNormalsChanged(ECheckBoxState NewState); void OnRemoveDegeneratesChanged(ECheckBoxState NewState); void OnBuildReversedIndexBufferChanged(ECheckBoxState NewState); void OnUseHighPrecisionTangentBasisChanged(ECheckBoxState NewState); void OnUseFullPrecisionUVsChanged(ECheckBoxState NewState); void OnUseBackwardsCompatibleF16TruncUVsChanged(ECheckBoxState NewState); void OnGenerateLightmapUVsChanged(ECheckBoxState NewState); void OnGenerateDistanceFieldAsIfTwoSidedChanged(ECheckBoxState NewState); void OnMinLightmapResolutionChanged( int32 NewValue ); void OnSrcLightmapIndexChanged( int32 NewValue ); void OnDstLightmapIndexChanged( int32 NewValue ); void OnBuildScaleXChanged( float NewScaleX, ETextCommit::Type TextCommitType ); void OnBuildScaleYChanged( float NewScaleY, ETextCommit::Type TextCommitType ); void OnBuildScaleZChanged( float NewScaleZ, ETextCommit::Type TextCommitType ); void OnDistanceFieldResolutionScaleChanged(float NewValue); void OnDistanceFieldResolutionScaleCommitted(float NewValue, ETextCommit::Type TextCommitType); FString GetCurrentDistanceFieldReplacementMeshPath() const; void OnDistanceFieldReplacementMeshSelected(const FAssetData& AssetData); void OnMaxLumenMeshCardsChanged(int32 NewValue); void OnMaxLumenMeshCardsCommitted(int32 NewValue, ETextCommit::Type TextCommitType); private: TWeakPtr ParentLODSettings; FMeshBuildSettings BuildSettings; int32 LODIndex; }; class FMeshReductionSettingsLayout : public IDetailCustomNodeBuilder, public TSharedFromThis { public: FMeshReductionSettingsLayout(TSharedRef InParentLODSettings, int32 InCurrentLODIndex, bool InCanReduceMyself); virtual ~FMeshReductionSettingsLayout(); const FMeshReductionSettings& GetSettings() const; void UpdateSettings(const FMeshReductionSettings& InSettings); private: /** IDetailCustomNodeBuilder Interface*/ virtual void SetOnRebuildChildren( FSimpleDelegate InOnRegenerateChildren ) override {} virtual void GenerateHeaderRowContent( FDetailWidgetRow& NodeRow ) override; virtual void GenerateChildContent( IDetailChildrenBuilder& ChildrenBuilder ) override; virtual void Tick( float DeltaTime ) override{} virtual bool RequiresTick() const override { return false; } virtual FName GetName() const override { static FName MeshReductionSettings("MeshReductionSettings"); return MeshReductionSettings; } virtual bool InitiallyCollapsed() const override { return true; } FReply OnApplyChanges(); // used by native tool and simplygon float GetPercentTriangles() const; // used by native quadric simplifier float GetPercentVertices() const; // used by simplygon only float GetMaxDeviation() const; float GetPixelError() const; float GetWeldingThreshold() const; ECheckBoxState ShouldRecalculateNormals() const; float GetHardAngleThreshold() const; // used by native tool and simplygon void OnPercentTrianglesChanged(float NewValue); void OnPercentTrianglesCommitted(float NewValue, ETextCommit::Type TextCommitType); // Used by native code only void OnPercentVerticesChanged(float NewValue); void OnPercentVerticesCommitted(float NewValue, ETextCommit::Type TextCommitType); //used by simplygon only void OnMaxDeviationChanged(float NewValue); void OnMaxDeviationCommitted(float NewValue, ETextCommit::Type TextCommitType); void OnPixelErrorChanged(float NewValue); void OnPixelErrorCommitted(float NewValue, ETextCommit::Type TextCommitType); void OnRecalculateNormalsChanged(ECheckBoxState NewValue); // used by native tool and simplygon void OnWeldingThresholdChanged(float NewValue); void OnWeldingThresholdCommitted(float NewValue, ETextCommit::Type TextCommitType); // used by simplygon only void OnHardAngleThresholdChanged(float NewValue); void OnHardAngleThresholdCommitted(float NewValue, ETextCommit::Type TextCommitType); void OnSilhouetteImportanceChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); void OnTextureImportanceChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); void OnShadingImportanceChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); // Used by native tool only. void OnTerminationCriterionChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); // Are we using our tool, or simplygon? The tool is only changed during editor restarts bool UseNativeToolLayout() const; EVisibility GetTriangleCriterionVisibility() const; EVisibility GetVertexCriterionVisibility() const; TOptional GetBaseLODIndex() const; void SetBaseLODIndex(int32 NewLODBaseIndex); private: TWeakPtr ParentLODSettings; FMeshReductionSettings ReductionSettings; int32 CurrentLODIndex; bool bCanReduceMyself; // Used by simplygon TArray > ImportanceOptions; TSharedPtr SilhouetteCombo; TSharedPtr TextureCombo; TSharedPtr ShadingCombo; // Used by quadric simplifier TSharedPtr TerminationCriterionCombo; TArray > TerminationOptions; // Identify the actual that this UI drives bool bUseQuadricSimplifier; }; class FMeshSectionSettingsLayout : public TSharedFromThis { public: FMeshSectionSettingsLayout( IStaticMeshEditor& InStaticMeshEditor, int32 InLODIndex, TArray &InLodCategories) : StaticMeshEditor( InStaticMeshEditor ) , LODIndex( InLODIndex ) , LodCategoriesPtr(&InLodCategories) {} virtual ~FMeshSectionSettingsLayout(); void AddToCategory( IDetailCategoryBuilder& CategoryBuilder ); void SetCurrentLOD(int32 NewLodIndex); private: UStaticMesh& GetStaticMesh() const; void OnCopySectionList(int32 CurrentLODIndex); bool OnCanCopySectionList(int32 CurrentLODIndex) const; void OnPasteSectionList(int32 CurrentLODIndex); void OnCopySectionItem(int32 CurrentLODIndex, int32 SectionIndex); bool OnCanCopySectionItem(int32 CurrentLODIndex, int32 SectionIndex) const; void OnPasteSectionItem(int32 CurrentLODIndex, int32 SectionIndex); /** * Called by the material list widget when we need to get new materials for the list * * @param OutMaterials Handle to a material list builder that materials should be added to */ void OnGetSectionsForView(class ISectionListBuilder& OutSections, int32 ForLODIndex); /** * Called when a user drags a new material over a list item to replace it * * @param NewMaterial The material that should replace the existing material * @param PrevMaterial The material that should be replaced * @param SlotIndex The index of the slot on the component where materials should be replaces * @param bReplaceAll If true all materials in the slot should be replaced not just ones using PrevMaterial */ void OnSectionChanged(int32 ForLODIndex, int32 SectionIndex, int32 NewMaterialSlotIndex, FName NewMaterialSlotName); /** * Called by the material list widget on generating each name widget * * @param Material The material that is being displayed * @param SlotIndex The index of the material slot */ TSharedRef OnGenerateCustomNameWidgetsForSection(int32 ForLODIndex, int32 SectionIndex); /** * Called by the material list widget on generating each thumbnail widget * * @param Material The material that is being displayed * @param SlotIndex The index of the material slot */ TSharedRef OnGenerateCustomSectionWidgetsForSection(int32 ForLODIndex, int32 SectionIndex); ECheckBoxState IsSectionVisibleInRayTracing(int32 SectionIndex) const; void OnSectionVisibleInRayTracingChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState DoesSectionAffectDistanceFieldLighting(int32 SectionIndex) const; void OnSectionAffectDistanceFieldLightingChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState IsSectionOpaque(int32 SectionIndex) const; void OnSectionForceOpaqueFlagChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState DoesSectionCastShadow(int32 SectionIndex) const; void OnSectionCastShadowChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState DoesSectionCollide(int32 SectionIndex) const; bool SectionCollisionEnabled() const; FText GetCollisionEnabledToolTip() const; void OnSectionCollisionChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState IsSectionHighlighted(int32 SectionIndex) const; void OnSectionHighlightedChanged(ECheckBoxState NewState, int32 SectionIndex); ECheckBoxState IsSectionIsolatedEnabled(int32 SectionIndex) const; void OnSectionIsolatedChanged(ECheckBoxState NewState, int32 SectionIndex); void CallPostEditChange(FProperty* PropertyChanged=nullptr); void UpdateLODCategoryVisibility(); IStaticMeshEditor& StaticMeshEditor; int32 LODIndex; TArray *LodCategoriesPtr; }; struct FSectionLocalizer { FSectionLocalizer(int32 InLODIndex, int32 InSectionIndex) : LODIndex(InLODIndex) , SectionIndex(InSectionIndex) {} bool operator==(const FSectionLocalizer& Other) const { return (LODIndex == Other.LODIndex && SectionIndex == Other.SectionIndex); } bool operator!=(const FSectionLocalizer& Other) const { return !((*this) == Other); } int32 LODIndex; int32 SectionIndex; }; class FMeshMaterialsLayout : public TSharedFromThis { public: FMeshMaterialsLayout(IStaticMeshEditor& InStaticMeshEditor) : StaticMeshEditor(InStaticMeshEditor) { bDeleteWarningConsumed = false; } virtual ~FMeshMaterialsLayout(); void AddToCategory(IDetailCategoryBuilder& CategoryBuilder, const TArray& AssetDataArray); private: UStaticMesh& GetStaticMesh() const; FReply AddMaterialSlot(); FText GetMaterialArrayText() const; void GetMaterials(class IMaterialListBuilder& ListBuilder); void OnMaterialChanged(UMaterialInterface* NewMaterial, UMaterialInterface* PrevMaterial, int32 SlotIndex, bool bReplaceAll); TSharedRef OnGenerateWidgetsForMaterial(UMaterialInterface* Material, int32 SlotIndex); TSharedRef OnGenerateNameWidgetsForMaterial(UMaterialInterface* Material, int32 SlotIndex); void OnResetMaterialToDefaultClicked(UMaterialInterface* Material, int32 SlotIndex); ECheckBoxState IsMaterialHighlighted(int32 SlotIndex) const; void OnMaterialHighlightedChanged(ECheckBoxState NewState, int32 SlotIndex); ECheckBoxState IsMaterialIsolatedEnabled(int32 SlotIndex) const; void OnMaterialIsolatedChanged(ECheckBoxState NewState, int32 SlotIndex); FText GetOriginalImportMaterialNameText(int32 MaterialIndex) const; FText GetMaterialNameText(int32 MaterialIndex) const; void OnMaterialNameCommitted(const FText& InValue, ETextCommit::Type CommitType, int32 MaterialIndex); bool CanDeleteMaterialSlot(int32 MaterialIndex) const; void OnDeleteMaterialSlot(int32 MaterialIndex); TSharedRef OnGetMaterialSlotUsedByMenuContent(int32 MaterialIndex); FText GetFirstMaterialSlotUsedBySection(int32 MaterialIndex) const; /* If the material list is dirty this function will return true */ bool OnMaterialListDirty(); ECheckBoxState IsShadowCastingEnabled(int32 SlotIndex) const; void OnShadowCastingChanged(ECheckBoxState NewState, int32 SlotIndex); EVisibility GetOverrideUVDensityVisibililty() const; ECheckBoxState IsUVDensityOverridden(int32 SlotIndex) const; void OnOverrideUVDensityChanged(ECheckBoxState NewState, int32 SlotIndex); EVisibility GetUVDensityVisibility(int32 SlotIndex, int32 UVChannelIndex) const; TOptional GetUVDensityValue(int32 SlotIndex, int32 UVChannelIndex) const; void SetUVDensityValue(float InDensity, ETextCommit::Type CommitType, int32 SlotIndex, int32 UVChannelIndex); SVerticalBox::FSlot& GetUVDensitySlot(int32 SlotIndex, int32 UVChannelIndex) const; void CallPostEditChange(FProperty* PropertyChanged = nullptr); void OnCopyMaterialList(); bool OnCanCopyMaterialList() const; void OnPasteMaterialList(); void OnCopyMaterialItem(int32 CurrentSlot); bool OnCanCopyMaterialItem(int32 CurrentSlot) const; void OnPasteMaterialItem(int32 CurrentSlot); IStaticMeshEditor& StaticMeshEditor; /* This is to know if material are used by any LODs sections. */ TMap> MaterialUsedMap; /* * This prevent showing the delete material slot warning dialog more then once per editor session */ bool bDeleteWarningConsumed; }; /** * Window for adding and removing LOD. */ class FLevelOfDetailSettingsLayout : public TSharedFromThis { public: FLevelOfDetailSettingsLayout( FStaticMeshEditor& StaticMeshEditor ); virtual ~FLevelOfDetailSettingsLayout(); void AddToDetailsPanel( IDetailLayoutBuilder& DetailBuilder ); /** Returns true if settings have been changed and an Apply is needed to update the asset. */ bool IsApplyNeeded() const; /** Apply current LOD settings to the mesh. */ void ApplyChanges(); /** Returns true if the LOD's static mesh has Nanite enabled */ bool IsNaniteEnabled() const; private: /** Creates the UI for Current LOD panel */ void AddLODLevelCategories( class IDetailLayoutBuilder& DetailBuilder ); /** Callbacks. */ FReply OnApply(); void OnLODCountChanged(int32 NewValue); void OnLODCountCommitted(int32 InValue, ETextCommit::Type CommitInfo); int32 GetLODCount() const; void OnSelectedLODChanged(int32 NewLodIndex); void OnMinLODChanged(int32 NewValue, FName Platform); void OnMinLODCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName Platform); int32 GetMinLOD(FName Platform) const; FPerPlatformInt GetMinLOD() const; TSharedRef GetMinLODWidget(FName PlatformGroupName) const; bool AddMinLODPlatformOverride(FName PlatformGroupName); bool RemoveMinLODPlatformOverride(FName PlatformGroupName); TArray GetMinLODPlatformOverrideNames() const; void OnMinQualityLevelLODChanged(int32 NewValue, FName QualityLevel); void OnMinQualityLevelLODCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName QualityLevel); int32 GetMinQualityLevelLOD(FName QualityLevel) const; TSharedRef GetMinQualityLevelLODWidget(FName QualityLevelName) const; bool AddMinLODQualityLevelOverride(FName QualityLevelName); bool RemoveMinLODQualityLevelOverride(FName QualityLevelName); TArray GetMinQualityLevelLODOverrideNames() const; FReply ResetToDefault(); void OnNoRefStreamingLODBiasChanged(int32 NewValue, FName QualityLevel); void OnNoRefStreamingLODBiasCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName QualityLevel); int32 GetNoRefStreamingLODBias(FName QualityLevel) const; TSharedRef GetNoRefStreamingLODBiasWidget(FName QualityLevelName) const; bool AddNoRefStreamingLODBiasOverride(FName QualityLevelName); bool RemoveNoRefStreamingLODBiasOverride(FName QualityLevelName); TArray GetNoRefStreamingLODBiasOverrideNames() const; void OnNumStreamedLODsChanged(int32 NewValue, FName Platform); void OnNumStreamedLODsCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName Platform); int32 GetNumStreamedLODs(FName Platform) const; TSharedRef GetNumStreamedLODsWidget(FName PlatformGroupName) const; bool AddNumStreamedLODsPlatformOverride(FName PlatformGroupName); bool RemoveNumStreamedLODsPlatformOverride(FName PlatformGroupName); TArray GetNumStreamedLODsPlatformOverrideNames() const; bool CanRemoveLOD(int32 LODIndex) const; FReply OnRemoveLOD(int32 LODIndex); float GetLODScreenSize(FName PlatformGroupName, int32 LODIndex)const; FText GetLODScreenSizeTitle(int32 LODIndex) const; bool CanChangeLODScreenSize() const; TSharedRef GetLODScreenSizeWidget(FName PlatformGroupName, int32 LODIndex) const; TArray GetLODScreenSizePlatformOverrideNames(int32 LODIndex) const; bool AddLODScreenSizePlatformOverride(FName PlatformGroupName, int32 LODIndex); bool RemoveLODScreenSizePlatformOverride(FName PlatformGroupName, int32 LODIndex); void OnLODScreenSizeChanged(float NewValue, FName PlatformGroupName, int32 LODIndex); void OnLODScreenSizeCommitted(float NewValue, ETextCommit::Type CommitType, FName PlatformGroupName, int32 LODIndex); float GetScreenSizeWidgetWidth(int32 LODIndex) const; FString GetSourceImportFilename(int32 LODIndex) const; void SetSourceImportFilename(const FString& SourceFileName, int32 LODIndex) const; void OnBuildSettingsExpanded(bool bIsExpanded, int32 LODIndex); void OnReductionSettingsExpanded(bool bIsExpanded, int32 LODIndex); void OnSectionSettingsExpanded(bool bIsExpanded, int32 LODIndex); void OnLODGroupChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); bool IsAutoLODEnabled() const; ECheckBoxState IsAutoLODChecked() const; void OnAutoLODChanged(ECheckBoxState NewState); void OnImportLOD(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); void UpdateLODNames(); FText GetLODCountTooltip() const; FText GetMinLODTooltip() const; FText GetNoRefStreamingLODBiasTooltip() const; FText GetNumStreamedLODsTooltip() const; FText GetLODCustomModeNameContent(int32 LODIndex) const; ECheckBoxState IsLODCustomModeCheck(int32 LODIndex) const; void SetLODCustomModeCheck(ECheckBoxState NewState, int32 LODIndex); bool IsLODCustomModeEnable(int32 LODIndex) const; TSharedRef OnGenerateLodComboBoxForLodPicker(); EVisibility LodComboBoxVisibilityForLodPicker() const; bool IsLodComboBoxEnabledForLodPicker() const; TSharedRef OnGenerateLodMenuForLodPicker(); FText GetCurrentLodName() const; FText GetCurrentLodTooltip() const; private: /** The Static Mesh Editor this tool is associated with. */ FStaticMeshEditor& StaticMeshEditor; /** LOD group options. */ TArray LODGroupNames; TArray > LODGroupOptions; /** LOD import options */ TArray > LODNames; /** Simplification options for each LOD level (in the LOD Chain tool). */ TSharedPtr ReductionSettingsWidgets[MAX_STATIC_MESH_LODS]; TSharedPtr BuildSettingsWidgets[MAX_STATIC_MESH_LODS]; TSharedPtr SectionSettingsWidgets[MAX_STATIC_MESH_LODS]; TSharedPtr MaterialsLayoutWidget; /** ComboBox widget for the LOD Group property */ TSharedPtr LODGroupComboBox; /** The display factors at which LODs swap */ FPerPlatformFloat LODScreenSizes[MAX_STATIC_MESH_LODS]; /** Helper value that corresponds to the 'Number of LODs' spinbox.*/ int32 LODCount; /** Whether certain parts of the UI are expanded so changes persist across recreating the UI. */ bool bBuildSettingsExpanded[MAX_STATIC_MESH_LODS]; bool bReductionSettingsExpanded[MAX_STATIC_MESH_LODS]; bool bSectionSettingsExpanded[MAX_STATIC_MESH_LODS]; TArray LodCategories; IDetailCategoryBuilder* LodCustomCategory; bool DetailDisplayLODs[MAX_STATIC_MESH_LODS]; }; /** * Window for Nanite settings. */ class FNaniteSettingsLayout : public TSharedFromThis { public: FNaniteSettingsLayout(FStaticMeshEditor& StaticMeshEditor); virtual ~FNaniteSettingsLayout(); const FMeshNaniteSettings& GetSettings() const; void UpdateSettings(const FMeshNaniteSettings& InSettings); void AddToDetailsPanel(IDetailLayoutBuilder& DetailBuilder); /** Returns true if settings have been changed and an Apply is needed to update the asset. */ bool IsApplyNeeded() const; /** Apply current Nanite settings to the mesh. */ void ApplyChanges(); /** Position Precision range selectable in the UI. */ static const int32 DisplayPositionPrecisionMin = -6; static const int32 DisplayPositionPrecisionMax = 13; static int32 PositionPrecisionIndexToValue(int32 Index); static int32 PositionPrecisionValueToIndex(int32 Value); /** Display string to show in menus. */ static FString PositionPrecisionValueToDisplayString(int32 Value); /** Residency range selectable in the UI. */ static const int32 DisplayMinimumResidencyMinimalIndex = 0; static const int32 DisplayMinimumResidencyExpRangeMin = 6; static const int32 DisplayMinimumResidencyExpRangeMax = 16; static const int32 DisplayMinimumResidencyFullIndex = DisplayMinimumResidencyExpRangeMax - DisplayMinimumResidencyExpRangeMin + 2; static uint32 MinimumResidencyIndexToValue(int32 Index); static int32 MinimumResidencyValueToIndex(uint32 Value); /** Display string to show in menus. */ static FString MinimumResidencyValueToDisplayString(uint32 Value); private: FReply OnApply(); ECheckBoxState IsEnabledChecked() const; void OnEnabledChanged(ECheckBoxState NewState); void OnPositionPrecisionChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); void OnResidencyChanged(TSharedPtr NewValue, ESelectInfo::Type SelectInfo); float GetKeepPercentTriangles() const; void OnKeepPercentTrianglesChanged(float NewValue); void OnKeepPercentTrianglesCommitted(float NewValue, ETextCommit::Type TextCommitType); float GetTrimRelativeError() const; void OnTrimRelativeErrorChanged(float NewValue); float GetFallbackPercentTriangles() const; void OnFallbackPercentTrianglesChanged(float NewValue); void OnFallbackPercentTrianglesCommitted(float NewValue, ETextCommit::Type TextCommitType); float GetFallbackRelativeError() const; void OnFallbackRelativeErrorChanged(float NewValue); private: /** The Static Mesh Editor this tool is associated with. */ FStaticMeshEditor& StaticMeshEditor; FMeshNaniteSettings NaniteSettings; TArray > PositionPrecisionOptions; TArray > ResidencyOptions; };