// Copyright Epic Games, Inc. All Rights Reserved. #include "Customization/SkeletalMeshRegionCustomization.h" #include "Engine/SkeletalMesh.h" #include "Engine/SkeletalMeshSampling.h" #include "Engine/SkinnedAssetCommon.h" #include "UObject/ObjectMacros.h" #include "UObject/Class.h" #include "IDetailsView.h" #include "Styling/AppStyle.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "PropertyHandle.h" #include "DetailLayoutBuilder.h" #include "DetailCategoryBuilder.h" #include "Widgets/Text/STextBlock.h" #include "Widgets/Input/SNumericEntryBox.h" #include "Animation/AnimSequence.h" #include "Animation/BlendSpace.h" #include "Animation/BlendSpace1D.h" #include "SAnimationBlendSpaceGridWidget.h" #include "PropertyCustomizationHelpers.h" #include "PackageTools.h" #include "IDetailGroup.h" #include "Editor.h" #include "IDetailChildrenBuilder.h" #include "Widgets/Input/SComboBox.h" #define LOCTEXT_NAMESPACE "SkeletalMeshRegionCustomization" void FNiagaraSkeletalMeshRegionBoneFilterDetails::CustomizeHeader(TSharedRef StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { HeaderRow .NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ]; } void FNiagaraSkeletalMeshRegionBoneFilterDetails::CustomizeChildren(TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { TArray> SelectedObjects; ChildBuilder.GetParentCategory().GetParentLayout().GetObjectsBeingCustomized(SelectedObjects); check(SelectedObjects.Num() == 1); MeshObject = Cast(SelectedObjects[0].Get()); check(MeshObject); uint32 NumChildren; StructPropertyHandle->GetNumChildren(NumChildren); for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex) { TSharedRef ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef(); const FName ChildName = ChildHandle->GetProperty()->GetFName(); // Pick out Min and Max range value properties if (ChildName == GET_MEMBER_NAME_CHECKED(FSkeletalMeshSamplingRegionBoneFilter, BoneName)) { BoneNameHandle = ChildHandle; ChildBuilder.AddCustomRow(BoneNameHandle->GetPropertyDisplayName()) .NameWidget [ BoneNameHandle->CreatePropertyNameWidget() ] .ValueWidget [ SNew(SComboBox) .OptionsSource(&PossibleBoneNames) .ContentPadding(2.0f) .OnGenerateWidget(this, &FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxGenerateWidget) .OnSelectionChanged(this, &FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxSelectionChanged) .OnComboBoxOpening(this, &FNiagaraSkeletalMeshRegionBoneFilterDetails::OnComboOpening) [ SNew(STextBlock) .Text(this, &FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxContentText) ] ]; } else { ChildBuilder.AddProperty(ChildHandle); } } } FText FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxContentText() const { FName OutName; BoneNameHandle->GetValue(OutName); return FText::FromName(OutName); } TSharedRef FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxGenerateWidget(FName StringItem) { return SNew(STextBlock) .Text(FText::FromName(StringItem)); } void FNiagaraSkeletalMeshRegionBoneFilterDetails::HandleBoneNameComboBoxSelectionChanged(FName StringItem, ESelectInfo::Type SelectInfo) { BoneNameHandle->SetValue(StringItem); } void FNiagaraSkeletalMeshRegionBoneFilterDetails::OnComboOpening() { PossibleBoneNames.Reset(); if (MeshObject->GetSkeleton() != nullptr) { //Populate PossibleBonesNames for (FMeshBoneInfo Bone : MeshObject->GetSkeleton()->GetReferenceSkeleton().GetRefBoneInfo()) { PossibleBoneNames.Add(Bone.Name); } } } ////////////////////////////////////////////////////////////////////////// void FNiagaraSkeletalMeshRegionMaterialFilterDetails::CustomizeHeader(TSharedRef StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { HeaderRow .NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ]; } void FNiagaraSkeletalMeshRegionMaterialFilterDetails::CustomizeChildren(TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { TArray> SelectedObjects; ChildBuilder.GetParentCategory().GetParentLayout().GetObjectsBeingCustomized(SelectedObjects); check(SelectedObjects.Num() == 1); MeshObject = Cast(SelectedObjects[0].Get()); check(MeshObject); uint32 NumChildren; StructPropertyHandle->GetNumChildren(NumChildren); for (uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex) { TSharedRef ChildHandle = StructPropertyHandle->GetChildHandle(ChildIndex).ToSharedRef(); const FName ChildName = ChildHandle->GetProperty()->GetFName(); // Pick out Min and Max range value properties if (ChildName == GET_MEMBER_NAME_CHECKED(FSkeletalMeshSamplingRegionMaterialFilter, MaterialName)) { MaterialNameHandle = ChildHandle; ChildBuilder.AddCustomRow(MaterialNameHandle->GetPropertyDisplayName()) .NameWidget [ MaterialNameHandle->CreatePropertyNameWidget() ] .ValueWidget [ SNew(SComboBox>) .OptionsSource(&PossibleMaterialNames) .ContentPadding(2.0f) .OnGenerateWidget(this, &FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxGenerateWidget) .OnSelectionChanged(this, &FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxSelectionChanged) .OnComboBoxOpening(this, &FNiagaraSkeletalMeshRegionMaterialFilterDetails::OnComboOpening) [ SNew(STextBlock) .Text(this, &FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxContentText) ] ]; } else { ChildBuilder.AddProperty(ChildHandle); } } } FText FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxContentText() const { FName OutName; MaterialNameHandle->GetValue(OutName); return FText::FromName(OutName); } TSharedRef FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxGenerateWidget(TSharedPtr StringItem) { FName DefaultName = StringItem.IsValid() ? *StringItem : NAME_None; return SNew(STextBlock).Text(FText::FromName(DefaultName)); } void FNiagaraSkeletalMeshRegionMaterialFilterDetails::HandleMaterialNameComboBoxSelectionChanged(TSharedPtr StringItem, ESelectInfo::Type SelectInfo) { if (StringItem) { MaterialNameHandle->SetValue(*StringItem); } } void FNiagaraSkeletalMeshRegionMaterialFilterDetails::OnComboOpening() { PossibleMaterialNames.Reset(); if (MeshObject->GetSkeleton() != nullptr) { //Populate PossibleMaterialsNames for (FSkeletalMaterial Material : MeshObject->GetMaterials()) { TSharedPtr MaterialName(new FName(Material.MaterialSlotName)); PossibleMaterialNames.Add(MaterialName); } } } #undef LOCTEXT_NAMESPACE