Files
UnrealEngine/Engine/Source/Editor/Persona/Private/PersonaMeshDetails.h
2025-05-18 13:04:45 +08:00

866 lines
34 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Layout/Visibility.h"
#include "Input/Reply.h"
#include "Widgets/SWidget.h"
#include "Widgets/SBoxPanel.h"
#include "EngineDefines.h"
#include "Engine/SkeletalMesh.h"
#include "PropertyHandle.h"
#include "IDetailCustomNodeBuilder.h"
#include "IDetailCustomization.h"
#include "SkeletalMeshReductionSettings.h"
#include "Widgets/Input/SComboBox.h"
DECLARE_LOG_CATEGORY_EXTERN(LogSkeletalMeshPersonaMeshDetail, Log, All);
struct FAssetData;
class FNaniteSkeletalMeshLayout;
class FDetailWidgetRow;
class FPersonaMeshDetails;
class IDetailChildrenBuilder;
class IDetailLayoutBuilder;
class IPersonaToolkit;
class SUniformGridPanel;
struct FSectionLocalizer;
class IDetailCategoryBuilder;
class IDetailGroup;
//The parameter is the LOD index so we know which LOD need to be rebuild
DECLARE_DELEGATE_RetVal_OneParam(bool, FIsLODSettingsEnabledDelegate, int32)
DECLARE_DELEGATE_OneParam(FModifyMeshLODSettingsDelegate, int32)
/**
* Struct to uniquely identify clothing applied to a material section
* Contains index into the ClothingAssets array and the submesh index.
*/
struct FClothAssetSubmeshIndex
{
FClothAssetSubmeshIndex(int32 InAssetIndex, int32 InSubmeshIndex)
: AssetIndex(InAssetIndex)
, SubmeshIndex(InSubmeshIndex)
{}
int32 AssetIndex;
int32 SubmeshIndex;
bool operator==(const FClothAssetSubmeshIndex& Other) const
{
return (AssetIndex == Other.AssetIndex
&& SubmeshIndex == Other.SubmeshIndex
);
}
};
struct FClothingComboInfo
{
/* Per-material clothing combo boxes, array size must be same to # of sections */
TArray<TSharedPtr< class STextComboBox >> ClothingComboBoxes;
/* Clothing combo box strings */
TArray<TSharedPtr<FString> > ClothingComboStrings;
/* Mapping from a combo box string to the asset and submesh it was generated from */
TMap<FString, FClothAssetSubmeshIndex> ClothingComboStringReverseLookup;
/* The currently-selected index from each clothing combo box */
TArray<int32> ClothingComboSelectedIndices;
};
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 FSkeletalMeshReductionSettingsLayout : public IDetailCustomNodeBuilder, public TSharedFromThis<FSkeletalMeshReductionSettingsLayout>
{
public:
FSkeletalMeshReductionSettingsLayout(FSkeletalMeshOptimizationSettings& InReductionettings, bool InbIsLODModelbuildDataAvailable, int32 InLODIndex, FIsLODSettingsEnabledDelegate InIsLODSettingsEnabledDelegate, FModifyMeshLODSettingsDelegate InModifyMeshLODSettingsDelegate);
virtual ~FSkeletalMeshReductionSettingsLayout() {};
enum EImportanceType
{
ID_Silhouette,
ID_Texture,
ID_Shading,
ID_Skinning
};
DECLARE_DELEGATE_RetVal(float, FGetFloatDelegate);
DECLARE_DELEGATE_OneParam(FSetFloatDelegate, float);
DECLARE_DELEGATE_RetVal(int32, FGetIntegerDelegate);
DECLARE_DELEGATE_OneParam(FSetIntegerDelegate, int32);
DECLARE_DELEGATE_RetVal(uint32, FGetUnsignedIntegerDelegate);
DECLARE_DELEGATE_OneParam(FSetUnsignedIntegerDelegate, uint32);
DECLARE_DELEGATE_RetVal(ECheckBoxState, FGetCheckBoxStateDelegate);
DECLARE_DELEGATE_OneParam(FSetCheckBoxStateDelegate, ECheckBoxState);
void UnbindReductionSettings()
{
IsLODSettingsEnabledDelegate.Unbind();
}
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("SkeletalMeshOptimizationSettings"); return MeshReductionSettings; }
virtual bool InitiallyCollapsed() const override { return true; }
bool IsReductionEnabled() const;
//Custom Row Add utilities
FDetailWidgetRow& AddFloatRow(IDetailChildrenBuilder& ChildrenBuilder, const FText RowTitleText, const FText RowNameContentText, const FText RowNameContentTootlipText, FName RowTag, const float MinSliderValue, const float MaxSliderValue, FGetFloatDelegate GetterDelegate, FSetFloatDelegate SetterDelegate);
FDetailWidgetRow& AddBoolRow(IDetailChildrenBuilder& ChildrenBuilder, const FText RowTitleText, const FText RowNameContentText, const FText RowNameContentToolitipText, FName RowTag, FGetCheckBoxStateDelegate GetterDelegate, FSetCheckBoxStateDelegate SetterDelegate);
FDetailWidgetRow& AddIntegerRow(IDetailChildrenBuilder& ChildrenBuilder, const FText RowTitleText, const FText RowNameContentText, const FText RowNameContentTootlipText, FName RowTag, const int32 MinSliderValue, const int32 MaxSliderValue, FGetIntegerDelegate GetterDelegate, FSetIntegerDelegate SetterDelegate);
FDetailWidgetRow& AddUnsignedIntegerRow(IDetailChildrenBuilder& ChildrenBuilder, const FText RowTitleText, const FText RowNameContentText, const FText RowNameContentTootlipText, FName RowTag, const uint32 MinSliderValue, const uint32 MaxSliderValue, FGetUnsignedIntegerDelegate GetterDelegate, FSetUnsignedIntegerDelegate SetterDelegate);
void AddBaseLODRow(IDetailChildrenBuilder& ChildrenBuilder);
void SetPercentAndAbsoluteVisibility(FDetailWidgetRow& Row, SkeletalMeshTerminationCriterion FirstCriterion, SkeletalMeshTerminationCriterion SecondCriterion);
int32 GetBaseLODValue() const
{
return ReductionSettings.BaseLOD;
}
void SetBaseLODValue(int32 Value)
{
ReductionSettings.BaseLOD = Value;
}
TSharedRef<class SWidget> FillReductionMethodMenu();
FText GetReductionMethodText() const;
TSharedRef<class SWidget> FillReductionImportanceMenu(const EImportanceType Importance);
FText GetReductionImportanceText(const EImportanceType Importance) const;
TSharedRef<class SWidget> FillReductionTerminationCriterionMenu();
FText GetReductionTerminationCriterionText() const;
float GetNumTrianglesPercentage() const;
void SetNumTrianglesPercentage(float Value);
float GetNumVerticesPercentage() const;
void SetNumVerticesPercentage(float Value);
int32 GetNumMaxTrianglesCount() const;
void SetNumMaxTrianglesCount(int32 Value);
int32 GetNumMaxVerticesCount() const;
void SetNumMaxVerticesCount(int32 Value);
uint32 GetNumMaxTrianglesPercentageCount() const;
void SetNumMaxTrianglesPercentageCount(uint32 Value);
uint32 GetNumMaxVerticesPercentageCount() const;
void SetNumMaxVerticesPercentageCount(uint32 Value);
float GetAccuracyPercentage() const;
void SetAccuracyPercentage(float Value);
ECheckBoxState ShouldRecomputeNormals() const;
void OnRecomputeNormalsChanged(ECheckBoxState NewState);
float GetNormalsThreshold() const;
void SetNormalsThreshold(float Value);
float GetWeldingThreshold() const;
void SetWeldingThreshold(float Value);
ECheckBoxState GetLockEdges() const;
void SetLockEdges(ECheckBoxState NewState);
ECheckBoxState GetLockColorBounaries() const;
void SetLockColorBounaries(ECheckBoxState NewState);
ECheckBoxState GetImproveTrianglesForCloth() const;
void SetImproveTrianglesForCloth(ECheckBoxState NewState);
ECheckBoxState GetEnforceBoneBoundaries() const;
void SetEnforceBoneBoundaries(ECheckBoxState NewState);
ECheckBoxState GetMergeCoincidentVertBones() const;
void SetMergeCoincidentVertBones(ECheckBoxState NewState);
float GetVolumeImportance() const;
void SetVolumeImportance(float Value);
ECheckBoxState GetRemapMorphTargets() const;
void SetRemapMorphTargets(ECheckBoxState NewState);
int32 GetMaxBonesPerVertex() const;
void SetMaxBonesPerVertex(int32 Value);
// Used the the thrid-party UI.
EVisibility GetVisibiltyIfCurrentReductionMethodIsNot(SkeletalMeshOptimizationType ReductionType) const;
// Used by the native tool UI.
EVisibility ShowIfCurrentCriterionIs(TArray<SkeletalMeshTerminationCriterion> TerminationCriterionArray) const;
/** Detect usage of thirdparty vs native tool */
bool UseNativeLODTool() const;
bool UseNativeReductionTool() const;
/**
Used to hide parameters that only make sense for the third party tool.
@return EVisibility::Visible if we are using the simplygon tool, otherwise EVisibility::Hidden
*/
EVisibility GetVisibilityForThirdPartyTool() const;
private:
FSkeletalMeshOptimizationSettings& ReductionSettings;
bool bIsLODModelbuildDataAvailable;
int32 LODIndex;
FIsLODSettingsEnabledDelegate IsLODSettingsEnabledDelegate;
FModifyMeshLODSettingsDelegate ModifyMeshLODSettingsDelegate;
UEnum* EnumReductionMethod;
UEnum* EnumImportance;
UEnum* EnumTerminationCriterion;
//Use this data to keep a valid reference so the helper lambda can have persistent data
//Helper lambda are use with spinner to not do a transaction when spinning with mouse movement
struct FSliderStateData
{
float MovementValueFloat = 0.0f;
int32 MovementValueInt = 0;
uint32 MovementValueUnsignedInt = 0;
bool bSliderActiveMode = false;
};
TArray<FSliderStateData> SliderStateDataArray;
};
class FSkeletalMeshBuildSettingsLayout : public IDetailCustomNodeBuilder, public TSharedFromThis<FSkeletalMeshBuildSettingsLayout>
{
public:
FSkeletalMeshBuildSettingsLayout(FSkeletalMeshBuildSettings& InBuildSettings, int32 InLODIndex, FIsLODSettingsEnabledDelegate InIsBuildSettingsEnabledDelegate, FModifyMeshLODSettingsDelegate InModifyMeshLODSettingsDelegate);
virtual ~FSkeletalMeshBuildSettingsLayout() {};
DECLARE_DELEGATE_RetVal(float, FGetFloatDelegate);
DECLARE_DELEGATE_OneParam(FSetFloatDelegate, float);
DECLARE_DELEGATE_RetVal(int32, FGetIntegerDelegate);
DECLARE_DELEGATE_OneParam(FSetIntegerDelegate, int32);
void UnbindBuildSettings()
{
IsBuildSettingsEnabledDelegate.Unbind();
}
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; }
bool IsBuildEnabled() const;
//Custom Row Add utilities
FDetailWidgetRow& AddFloatRow(IDetailChildrenBuilder& ChildrenBuilder, const FText RowTitleText, const FText RowNameContentText, const FText RowNameContentTootlipText, const float MinSliderValue, const float MaxSliderValue, FGetFloatDelegate GetterDelegate, FSetFloatDelegate SetterDelegate);
FDetailWidgetRow& AddIntegerRow(
IDetailChildrenBuilder& ChildrenBuilder,
const FText& RowTitleText,
const FText& RowNameContentText,
const FText& RowNameContentTooltipText,
FName RowTag,
const int32 MinSliderValue,
const int32 MaxSliderValue,
const FGetIntegerDelegate& GetterDelegate,
const FSetIntegerDelegate& SetterDelegate);
float GetThresholdPosition() const;
void SetThresholdPosition(float Value);
float GetThresholdTangentNormal() const;
void SetThresholdTangentNormal(float Value);
float GetThresholdUV() const;
void SetThresholdUV(float Value);
float GetMorphThresholdPosition() const;
void SetMorphThresholdPosition(float Value);
int32 GetBoneInfluenceLimit() const;
void SetBoneInfluenceLimit(int32 Value);
ECheckBoxState ShouldRecomputeNormals() const;
ECheckBoxState ShouldRecomputeTangents() const;
ECheckBoxState ShouldUseMikkTSpace() const;
ECheckBoxState ShouldComputeWeightedNormals() const;
ECheckBoxState ShouldRemoveDegenerates() const;
ECheckBoxState ShouldUseHighPrecisionTangentBasis() const;
ECheckBoxState ShouldUseHighPrecisionSkinWeights() const;
ECheckBoxState ShouldUseFullPrecisionUVs() const;
ECheckBoxState ShouldUseBackwardsCompatibleF16TruncUVs() const;
void OnRecomputeNormalsChanged(ECheckBoxState NewState);
void OnRecomputeTangentsChanged(ECheckBoxState NewState);
void OnUseMikkTSpaceChanged(ECheckBoxState NewState);
void OnComputeWeightedNormalsChanged(ECheckBoxState NewState);
void OnRemoveDegeneratesChanged(ECheckBoxState NewState);
void OnUseHighPrecisionTangentBasisChanged(ECheckBoxState NewState);
void OnUseHighPrecisionSkinWeightsChanged(ECheckBoxState NewState);
void OnUseFullPrecisionUVsChanged(ECheckBoxState NewState);
void OnUseBackwardsCompatibleF16TruncUVsChanged(ECheckBoxState NewState);
private:
FSkeletalMeshBuildSettings& BuildSettings;
int32 LODIndex;
FIsLODSettingsEnabledDelegate IsBuildSettingsEnabledDelegate;
FModifyMeshLODSettingsDelegate ModifyMeshLODSettingsDelegate;
//Use this data to keep a valid reference so the helper lambda can have persistent data
//Helper lambda are use with spinner to not do a transaction when spinning with mouse movement
struct FSliderStateData
{
float MovementValueFloat = 0.0f;
int32 MovementValueInt = 0;
bool bSliderActiveMode = false;
};
TArray<FSliderStateData> SliderStateDataArray;
};
class FPersonaMeshDetails : public IDetailCustomization
{
public:
FPersonaMeshDetails(TSharedRef<class IPersonaToolkit> InPersonaToolkit);
~FPersonaMeshDetails();
/** Makes a new instance of this detail layout class for a specific detail view requesting it */
static TSharedRef<IDetailCustomization> MakeInstance(TWeakPtr<class IPersonaToolkit> InPersonaToolkit);
/** IDetailCustomization interface */
virtual void CustomizeDetails( IDetailLayoutBuilder& DetailLayout ) override;
public:
void ForceLayoutRebuild();
void RequestLayoutUpdate();
private:
//Prevent attribute change calling post edit change
void OnAttributePreChangePreventPostEditChange(int32 LODIndex, FName LODInfoPropertyName) const;
void OnAttributeChangedPreventPostEditChange(const int32 LODIndex, const FName LODInfoPropertyName, const bool bForceComponentRefresh) const;
void PreventAttributePostEditChange(TSharedPtr<IPropertyHandle> AttributeHandle, const int32 LODIndex, const FName PropertyName, const bool bForceComponentRefresh) const;
//This function customize the LODInfo temporary object
void CustomizeLODInfoSetingsDetails(IDetailLayoutBuilder& DetailLayout, class ULODInfoUILayout* LODInfoUILayout, TSharedRef<IPropertyHandle> LODInfoProperty, IDetailCategoryBuilder& LODCategory);
FReply AddMaterialSlot();
FText GetMaterialArrayText() const;
/**
* 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 LODIndex );
/**
* 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 LODIndex, int32 SectionIndex, int32 NewMaterialSlotIndex, FName NewMaterialSlotName);
/**
* 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 OnGetMaterialsForArray(class IMaterialListBuilder& OutMaterials, int32 LODIndex);
/**
* 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 OnMaterialArrayChanged(UMaterialInterface* NewMaterial, UMaterialInterface* PrevMaterial, int32 SlotIndex, bool bReplaceAll, int32 LODIndex);
/**
* 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<SWidget> OnGenerateCustomNameWidgetsForSection(int32 LodIndex, 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<SWidget> OnGenerateCustomSectionWidgetsForSection(int32 LODIndex, int32 SectionIndex);
bool IsSectionEnabled(int32 LodIndex, int32 SectionIndex) const;
EVisibility ShowEnabledSectionDetail(int32 LodIndex, int32 SectionIndex) const;
EVisibility ShowDisabledSectionDetail(int32 LodIndex, int32 SectionIndex) const;
void OnSectionEnabledChanged(int32 LodIndex, int32 SectionIndex, bool bEnable);
TOptional<int8> GetSectionGenerateUpToValue(int32 LodIndex, int32 SectionIndex) const;
void SetSectionGenerateUpToValue(int8 Value, int32 LodIndex, int32 SectionIndex);
void SetSectionGenerateUpToValueCommitted(int8 Value, ETextCommit::Type CommitInfo, int32 LodIndex, int32 SectionIndex);
EVisibility ShowSectionGenerateUpToSlider(int32 LodIndex, int32 SectionIndex) const;
ECheckBoxState IsGenerateUpToSectionEnabled(int32 LodIndex, int32 SectionIndex) const;
void OnSectionGenerateUpToChanged(ECheckBoxState NewState, int32 LodIndex, int32 SectionIndex);
TSharedRef<SWidget> OnGenerateLodComboBoxForLodPicker();
EVisibility LodComboBoxVisibilityForLodPicker() const;
bool IsLodComboBoxEnabledForLodPicker() const;
/*
* Generate the context menu to choose the LOD we will display the picker list
*/
TSharedRef<SWidget> OnGenerateLodMenuForLodPicker();
FText GetCurrentLodName() const;
FText GetCurrentLodTooltip() const;
static bool GetAutoLod(USkeletalMeshComponent* InMeshComponent);
static int32 GetCurrentDisplayLODIndex(USkeletalMeshComponent* InMeshComponent);
void SetCurrentLOD(int32 NewLodIndex);
void UpdateLODCategoryVisibility() const;
FText GetMaterialNameText(int32 MaterialIndex)const ;
void OnMaterialNameCommitted(const FText& InValue, ETextCommit::Type CommitType, int32 MaterialIndex);
FText GetOriginalImportMaterialNameText(int32 MaterialIndex)const;
/**
* Called by the material list widget on generating name side content
*
* @param Material The material that is being displayed
* @param MaterialIndex The index of the material slot
*/
TSharedRef<SWidget> OnGenerateCustomNameWidgetsForMaterialArray(UMaterialInterface* Material, int32 MaterialIndex);
/**
* Called by the material list widget on generating each thumbnail widget
*
* @param Material The material that is being displayed
* @param MaterialIndex The index of the material slot
*/
TSharedRef<SWidget> OnGenerateCustomMaterialWidgetsForMaterialArray(UMaterialInterface* Material, int32 MaterialIndex, int32 LODIndex);
/**
* Called by the material list widget on generating each thumbnail widget
* Those generated widget will be stack under the material list row
*
* @param Material The material that is being displayed
* @param MaterialIndex The index of the material slot
*/
TSharedRef<SWidget> OnGenerateMaterialListExtraBottomWidget(UMaterialInterface* Material, int32 MaterialIndex, int32 LODIndex);
/* If the material list is dirty this function will return true */
bool OnMaterialListDirty();
bool CanDeleteMaterialSlot(int32 MaterialIndex) const;
void OnDeleteMaterialSlot(int32 MaterialIndex);
/* Call when user change the material slot overlay material. */
void OnMaterialSlotOverlayMaterialChanged(UMaterialInterface* NewOverlayMaterial, int32 MaterialIndex);
/**
* Handler for check box display based on whether the material is highlighted
*
* @param MaterialIndex The material index that is being selected
*/
ECheckBoxState IsMaterialSelected(int32 MaterialIndex) const;
/**
* Handler for changing highlight status on a material
*
* @param MaterialIndex The material index that is being selected
*/
void OnMaterialSelectedChanged(ECheckBoxState NewState, int32 MaterialIndex);
/**
* Handler for check box display based on whether the material is isolated
*
* @param MaterialIndex The material index that is being isolate
*/
ECheckBoxState IsIsolateMaterialEnabled(int32 MaterialIndex) const;
/**
* Handler for changing isolated status on a material
*
* @param MaterialIndex The material index that is being isolate
*/
void OnMaterialIsolatedChanged(ECheckBoxState NewState, int32 MaterialIndex);
/**
* Handler for check box display based on whether the material is highlighted
*
* @param SectionIndex The material section that is being tested
*/
ECheckBoxState IsSectionSelected(int32 SectionIndex) const;
/**
* Handler for changing highlight status on a material
*
* @param SectionIndex The material section that is being tested
*/
void OnSectionSelectedChanged(ECheckBoxState NewState, int32 SectionIndex);
/**
* Handler for check box display based on whether the material is isolated
*
* @param SectionIndex The material section that is being tested
*/
ECheckBoxState IsIsolateSectionEnabled(int32 SectionIndex) const;
/**
* Handler for changing isolated status on a material
*
* @param SectionIndex The material section that is being tested
*/
void OnSectionIsolatedChanged(ECheckBoxState NewState, int32 SectionIndex);
/**
* Handler for check box display based on whether the material has shadow casting enabled
*
* @param LODIndex The LODIndex we want to change
* @param SectionIndex The SectionIndex we change the ShadowCasting flag
*/
ECheckBoxState IsSectionShadowCastingEnabled(int32 LODIndex, int32 SectionIndex) const;
/**
* Handler for changing shadow casting status on a section
*
* @param LODIndex The LODIndex we want to change
* @param SectionIndex The SectionIndex we change the ShadowCasting flag
*/
void OnSectionShadowCastingChanged(ECheckBoxState NewState, int32 LODIndex, int32 SectionIndex);
/**
* Handler for check box display based on whether the material has VisibleInRayTracing enabled
*
* @param LODIndex The LODIndex we want to change
* @param SectionIndex The SectionIndex we change the VisibleInRayTracing flag
*/
ECheckBoxState IsSectionVisibleInRayTracingEnabled(int32 LODIndex, int32 SectionIndex) const;
/**
* Handler for changing VisibleInRayTracing status on a section
*
* @param LODIndex The LODIndex we want to change
* @param SectionIndex The SectionIndex we change the VisibleInRayTracing flag
*/
void OnSectionVisibleInRayTracingChanged(ECheckBoxState NewState, int32 LODIndex, int32 SectionIndex);
/**
* Handler for selecting which vertex color to mask the blending of recomputing tangents
*
* @param LODIndex The LODIndex we want to change
* @param SectionIndex The SectionIndex we change the RecomputeTangent
*/
TSharedRef<class SWidget> OnGenerateRecomputeTangentsSetting(int32 LODIndex, int32 SectionIndex);
FText GetCurrentRecomputeTangentsSetting(int32 LODIndex, int32 SectionIndex) const;
void SetCurrentRecomputeTangentsSetting(int32 LODIndex, int32 SectionIndex, int32 Index);
/**
* Handler for enabling delete button on materials
*
* @param SectionIndex - index of the section to check
*/
bool CanDeleteMaterialElement(int32 LODIndex, int32 SectionIndex) const;
/** Creates the UI for Current LOD panel */
void AddLODLevelCategories(IDetailLayoutBuilder& DetailLayout);
/** Get a material index from LOD index and section index */
int32 GetMaterialIndex(int32 LODIndex, int32 SectionIndex) const;
/** for LOD settings category */
void CustomizeLODSettingsCategories(IDetailLayoutBuilder& DetailLayout);
/** Called when a LOD is imported. Refreshes the UI. */
void OnAssetPostLODImported(UObject* InObject, int32 InLODIndex);
void OnAssetReimport(UObject* InObject);
/** Called from the PersonalMeshDetails UI to import a LOD. */
void OnImportLOD(TSharedPtr<FString> NewValue, ESelectInfo::Type SelectInfo, IDetailLayoutBuilder* DetailLayout);
void UpdateLODNames();
int32 GetLODCount() const;
void OnLODCountChanged(int32 NewValue);
void OnLODCountCommitted(int32 InValue, ETextCommit::Type CommitInfo);
FText GetLODCountTooltip() const;
FText GetLODImportedText(int32 LODIndex) const;
FText GetMaterialSlotNameText(int32 MaterialIndex) const;
void OnNoRefStreamingLODBiasChanged(int32 NewValue, FName QualityLevel);
void OnNoRefStreamingLODBiasCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName QualityLevel);
int32 GetNoRefStreamingLODBias(FName QualityLevel) const;
TSharedRef<SWidget> GetNoRefStreamingLODBiasWidget(FName QualityLevelName) const;
bool AddNoRefStreamingLODBiasOverride(FName QualityLevelName);
bool RemoveNoRefStreamingLODBiasOverride(FName QualityLevelName);
TArray<FName> GetNoRefStreamingLODBiasOverrideNames() const;
FText GetNoRefStreamingLODBiasTooltip() const;
void OnMinQualityLevelLodChanged(int32 NewValue, FName QualityLevel);
void OnMinQualityLevelLodCommitted(int32 InValue, ETextCommit::Type CommitInfo, FName QualityLevel);
int32 GetMinQualityLevelLod(FName QualityLevel) const;
TSharedRef<SWidget> GetMinQualityLevelLodWidget(FName QualityLevelName) const;
bool AddMinLodQualityLevelOverride(FName QualityLevelName);
bool RemoveMinLodQualityLevelOverride(FName QualityLevelName);
TArray<FName> GetMinQualityLevelLodOverrideNames() const;
FReply ResetToDefault();
FPerPlatformInt GetMinLod();
/** apply LOD changes if the user modified LOD reduction settings */
FReply OnApplyChanges();
/** regenerate one specific LOD Index no dependencies*/
void RegenerateOneLOD(int32 LODIndex);
/** regenerate the specific all LODs dependent of InLODIndex. This is not regenerating the InLODIndex*/
void RegenerateDependentLODs(int32 LODIndex);
/** Apply specified LOD Index */
FReply ApplyLODChanges(int32 LODIndex);
/** Apply specified LOD Index */
FReply RegenerateLOD(int32 LODIndex);
/** Removes the specified lod from the skeletal mesh */
FReply RemoveOneLOD(int32 LODIndex);
/** Removes any editable geometry from the given LOD, making it auto-generated */
FReply RemoveGeometryFromLOD(int32 LODIndex);
/** Restore the LOD imported data if the LOD is no longer reduced */
void RestoreNonReducedLOD(int32 LODIndex);
/** hide properties which don't need to be showed to end users */
void HideUnnecessaryProperties(IDetailLayoutBuilder& DetailLayout);
// Handling functions for post process blueprint selection combo box
void OnPostProcessBlueprintChanged(IDetailLayoutBuilder* DetailBuilder);
FString GetCurrentPostProcessBlueprintPath() const;
bool OnShouldFilterPostProcessBlueprint(const FAssetData& AssetData) const;
void OnSetPostProcessBlueprint(const FAssetData& AssetData, TSharedRef<IPropertyHandle> BlueprintProperty);
/** Access the persona toolkit ptr. It should always be valid in the lifetime of this customization */
TSharedRef<IPersonaToolkit> GetPersonaToolkit() const { check(PersonaToolkitPtr.IsValid()); return PersonaToolkitPtr.Pin().ToSharedRef(); }
bool HasValidPersonaToolkit() const { return PersonaToolkitPtr.IsValid(); }
EVisibility GetOverrideUVDensityVisibililty() const;
ECheckBoxState IsUVDensityOverridden(int32 MaterialIndex) const;
void OnOverrideUVDensityChanged(ECheckBoxState NewState, int32 MaterialIndex);
EVisibility GetUVDensityVisibility(int32 MaterialIndex, int32 UVChannelIndex) const;
TOptional<float> GetUVDensityValue(int32 MaterialIndex, int32 UVChannelIndex) const;
void SetUVDensityValue(float InDensity, ETextCommit::Type CommitType, int32 MaterialIndex, int32 UVChannelIndex);
SVerticalBox::FSlot& GetUVDensitySlot(int32 MaterialIndex, int32 UVChannelIndex) const;
// Used to control the type of reimport to do with a named parameter
enum class EReimportButtonType : uint8
{
Reimport,
ReimportWithNewFile
};
// Handler for reimport buttons in LOD details
FReply OnReimportLodClicked(EReimportButtonType InReimportType, int32 InLODIndex);
void OnCopySectionList(int32 LODIndex);
bool OnCanCopySectionList(int32 LODIndex) const;
void OnPasteSectionList(int32 LODIndex);
void OnCopySectionItem(int32 LODIndex, int32 SectionIndex);
bool OnCanCopySectionItem(int32 LODIndex, int32 SectionIndex) const;
void OnPasteSectionItem(int32 LODIndex, int32 SectionIndex);
void OnCopyMaterialList();
bool OnCanCopyMaterialList() const;
void OnPasteMaterialList();
void OnCopyMaterialItem(int32 CurrentSlot);
bool OnCanCopyMaterialItem(int32 CurrentSlot) const;
void OnPasteMaterialItem(int32 CurrentSlot);
void OnPreviewMeshChanged(USkeletalMesh* OldSkeletalMesh, USkeletalMesh* NewMesh);
bool FilterOutBakePose(const struct FAssetData& AssetData, USkeleton* Skeleton) const;
bool FilterOutBakePose(const struct FAssetData& AssetData, TObjectPtr<USkeleton> Skeleton) const { return FilterOutBakePose(AssetData, Skeleton.Get()); }
FText GetLODCustomModeNameContent(int32 LODIndex) const;
ECheckBoxState IsLODCustomModeCheck(int32 LODIndex) const;
void SetLODCustomModeCheck(ECheckBoxState NewState, int32 LODIndex);
bool IsLODCustomModeEnable(int32 LODIndex) const;
/** Gets the max LOD that can be set from the lod count slider (current num plus an interval) */
TOptional<int32> GetLodSliderMaxValue() const;
void CustomizeSkinWeightProfiles(IDetailLayoutBuilder& DetailLayout);
TSharedRef<SWidget> CreateSkinWeightProfileMenuContent();
public:
bool IsApplyNeeded() const;
bool IsGenerateAvailable() const;
void ApplyChanges();
FText GetApplyButtonText() const;
private:
// Container for the objects to display
TWeakObjectPtr<USkeletalMesh> SkeletalMeshPtr;
// Reference the persona toolkit
TWeakPtr<class IPersonaToolkit> PersonaToolkitPtr;
/** Nanite settings for the details panel. */
TSharedPtr<FNaniteSkeletalMeshLayout> NaniteSettings;
IDetailLayoutBuilder* MeshDetailLayout;
//This is the mockup UObjects to modify a copy of the LODInfo
TArray<class ULODInfoUILayout*> LODInfoUILayouts;
TArray<TSharedRef<IDetailsView>> LODInfoUILayoutDetailsViews;
/** LOD import options */
TArray<TSharedPtr<FString> > LODNames;
/** Helper value that corresponds to the 'Number of LODs' spinbox.*/
int32 LODCount;
/* This is to know if material are used by any LODs sections. */
TMap<int32, TArray<FSectionLocalizer>> MaterialUsedMap;
TArray<class IDetailCategoryBuilder*> LodCategories;
IDetailCategoryBuilder* LodCustomCategory;
bool CustomLODEditMode;
TArray<bool> DetailDisplayLODs;
/*
* Helper to keep the old GenerateUpTo slider value to register transaction correctly.
* The key is the union of LOD index and section index.
*/
TMap<int64, int8> OldGenerateUpToSliderValues;
/*
* This prevent showing the delete material slot warning dialog more then once per editor session
*/
bool bDeleteWarningConsumed;
private:
// info about clothing combo boxes for multiple LOD
TArray<FClothingComboInfo> ClothingComboLODInfos;
TArray<int32> ClothingSelectedSubmeshIndices;
// Menu entry for clothing dropdown
struct FClothingEntry
{
// Asset index inside the mesh
int32 AssetIndex;
// LOD index inside the clothing asset
int32 AssetLodIndex;
// Pointer back to the asset for this clothing entry
TWeakObjectPtr<UClothingAssetBase> Asset;
};
// Cloth combo box tracking for refreshes post-import/creation
typedef SComboBox<TSharedPtr<FClothingEntry>> SClothComboBox;
typedef TSharedPtr<SClothComboBox> SClothComboBoxPtr;
TArray<SClothComboBoxPtr> ClothComboBoxes;
// Clothing entries available to bind to the mesh
TArray<TSharedPtr<FClothingEntry>> NewClothingAssetEntries;
// Cached item in above array that is used as the "None" entry in the list
TSharedPtr<FClothingEntry> ClothingNoneEntry;
// Update the list of valid entries
void UpdateClothingEntries();
// Refreshes clothing combo boxes that are currently active
void RefreshClothingComboBoxes();
// Called as clothing combo boxes open to validate option entries
void OnClothingComboBoxOpening();
// Generate a widget for the clothing details panel
TSharedRef<SWidget> OnGenerateWidgetForClothingEntry(TSharedPtr<FClothingEntry> InEntry);
// Get the current text for the clothing selection combo box for the specified LOD and section
FText OnGetClothingComboText(int32 InLodIdx, int32 InSectionIdx) const;
// Callback when the clothing asset is changed
void OnClothingSelectionChanged(TSharedPtr<FClothingEntry> InNewEntry, ESelectInfo::Type InSelectType, int32 BoxIndex, int32 InLodIdx, int32 InSectionIdx);
// If the clothing details widget is editable
bool IsClothingPanelEnabled() const;
/* Generate slate UI for Clothing category */
void CustomizeClothingProperties(class IDetailLayoutBuilder& DetailLayout, class IDetailCategoryBuilder& ClothingFilesCategory);
/* Generate each ClothingAsset array entry */
void OnGenerateElementForClothingAsset( TSharedRef<IPropertyHandle> ElementProperty, int32 ElementIndex, IDetailChildrenBuilder& ChildrenBuilder, IDetailLayoutBuilder* DetailLayout );
/* Make uniform grid widget for Apex details */
TSharedRef<SUniformGridPanel> MakeClothingDetailsWidget(int32 AssetIndex) const;
/* Removes a clothing asset */
FReply OnRemoveClothingAssetClicked(int32 AssetIndex, IDetailLayoutBuilder* DetailLayout);
/* Create LOD setting assets from current setting */
FReply OnSaveLODSettings();
/** LOD Settings Selected */
void OnLODSettingsSelected(const FAssetData& AssetData);
/** LOD Info editing is enabled? LODIndex == -1, then it just verifies if the asset exists */
bool IsLODInfoEditingEnabled(int32 LODIndex) const;
bool IsMinLodEnable() const;
bool IsQualityLevelMinLodEnable() const;
void ModifyMeshLODSettings(int32 LODIndex);
TMap<int32, TSharedPtr<FSkeletalMeshBuildSettingsLayout>> BuildSettingsWidgetsPerLOD;
TMap<int32, TSharedPtr<FSkeletalMeshReductionSettingsLayout>> ReductionSettingsWidgetsPerLOD;
// Property handle used to determine if the VertexColorImportOverride property should be enabled.
TSharedPtr<IPropertyHandle> VertexColorImportOptionHandle;
// Property handle used during UI construction
TSharedPtr<IPropertyHandle> VertexColorImportOverrideHandle;
// Delegate implementation of FOnInstancedPropertyIteration used during DataImport UI construction
void OnInstancedFbxSkeletalMeshImportDataPropertyIteration(IDetailCategoryBuilder& BaseCategory, IDetailGroup* PropertyGroup, TSharedRef<IPropertyHandle>& Property) const;
// Delegate used at runtime to determine the state of the VertexOverrideColor property
bool GetVertexOverrideColorEnabledState() const;
// Called when the skeletal mesh has finished rebuilding. This may affect some settings, such as vertex attributes.
void OnMeshRebuildCompleted(USkeletalMesh* InMesh);
};