void FPrimaryAssetIdCustomization::CustomizeHeader(TSharedRef<class IPropertyHandle> InStructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils) { if (!UAssetManager::IsValid()) { HeaderRow .NameContent() [ InStructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(250.0f) .MaxDesiredWidth(0.0f) [ SNew(STextBlock) .Text(LOCTEXT("NoAssetManager", "Enable Asset Manager to edit Primary Asset Ids")) ]; return; } StructPropertyHandle = InStructPropertyHandle; const FString& TypeFilterString = StructPropertyHandle->GetMetaData("AllowedTypes"); if( !TypeFilterString.IsEmpty() ) { TArray<FString> CustomTypeFilterNames; TypeFilterString.ParseIntoArray(CustomTypeFilterNames, TEXT(","), true); for(auto It = CustomTypeFilterNames.CreateConstIterator(); It; ++It) { const FString& TypeName = *It; AllowedTypes.Add(*TypeName); } } FOnShouldFilterAsset AssetFilter = FOnShouldFilterAsset::CreateStatic(&IAssetManagerEditorModule::OnShouldFilterPrimaryAsset, AllowedTypes); // Can the field be cleared const bool bAllowClear = !(StructPropertyHandle->GetMetaDataProperty()->PropertyFlags & CPF_NoClear); HeaderRow .NameContent() [ InStructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(250.0f) .MaxDesiredWidth(0.0f) [ // Add an object entry box. Even though this isn't an object entry, we will simulate one SNew( SObjectPropertyEntryBox ) .ObjectPath(this, &FPrimaryAssetIdCustomization::OnGetObjectPath) .PropertyHandle(InStructPropertyHandle) .ThumbnailPool(StructCustomizationUtils.GetThumbnailPool()) .OnShouldFilterAsset(AssetFilter) .OnObjectChanged(this, &FPrimaryAssetIdCustomization::OnSetObject) .AllowClear(bAllowClear) ]; }
void FBlackboardSelectorDetails::CustomizeHeader( TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { MyStructProperty = StructPropertyHandle; PropUtils = StructCustomizationUtils.GetPropertyUtilities().Get(); CacheBlackboardData(); HeaderRow.IsEnabled(TAttribute<bool>::Create(TAttribute<bool>::FGetter::CreateSP(this, &FBlackboardSelectorDetails::IsEditingEnabled))) .NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() [ SNew(SComboButton) .OnGetMenuContent(this, &FBlackboardSelectorDetails::OnGetKeyContent) .ContentPadding(FMargin( 2.0f, 2.0f )) .IsEnabled(this, &FBlackboardSelectorDetails::IsEditingEnabled) .ButtonContent() [ SNew(STextBlock) .Text(this, &FBlackboardSelectorDetails::GetCurrentKeyDesc) .Font(IDetailLayoutBuilder::GetDetailFont()) ] ]; InitKeyFromProperty(); }
void FFoliageTypeObjectCustomization::CustomizeHeader(TSharedRef<IPropertyHandle> PropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& CustomizationUtils) { TSharedPtr<IPropertyHandle> FoliageTypeHandle = PropertyHandle->GetChildHandle("FoliageTypeObject"); // Only allow foliage type assets to be created (i.e. don't show all the factories for blueprints) TArray<const UClass*> SupportedClasses; SupportedClasses.Add(UFoliageType_InstancedStaticMesh::StaticClass()); HeaderRow .NameContent() [ FoliageTypeHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(250.f) .MaxDesiredWidth(0.f) [ SNew(SObjectPropertyEntryBox) .PropertyHandle(FoliageTypeHandle) .ThumbnailPool(CustomizationUtils.GetThumbnailPool()) .NewAssetFactories(PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(SupportedClasses)) .OnShouldFilterAsset(this, &FFoliageTypeObjectCustomization::OnShouldFilterAsset) ]; //PropertyCustomizationHelpers::MakeInsertDeleteDuplicateButton <-- not sure how to get that to show up properly, since the struct doesn't know it's an array }
void FKeyStructCustomization::CustomizeHeader( TSharedRef<class IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { PropertyHandle = StructPropertyHandle; // create struct header HeaderRow.NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(125.0f) .MaxDesiredWidth(325.0f) [ SNew(SKeySelector) .CurrentKey(this, &FKeyStructCustomization::GetCurrentKey) .OnKeyChanged(this, &FKeyStructCustomization::OnKeyChanged) .Font(StructCustomizationUtils.GetRegularFont()) ]; }
void FNavLinkStructCustomization::CustomizeHeader( TSharedRef<IPropertyHandle> StructPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { TSharedPtr<IPropertyHandle> CommentHandle = StructPropertyHandle->GetChildHandle(GET_MEMBER_NAME_CHECKED(FNavigationLinkBase,Description)); FString Desc; if (CommentHandle.IsValid()) { CommentHandle->GetValue(Desc); } HeaderRow.NameContent() [ StructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(400.0f) [ SNew(STextBlock) .Text(FText::FromString(Desc)) .Font(StructCustomizationUtils.GetRegularFont()) ]; }
void FAttenuationSettingsCustomization::CustomizeChildren( TSharedRef<IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& ChildBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { uint32 NumChildren; StructPropertyHandle->GetNumChildren( NumChildren ); TMap<FName, TSharedPtr< IPropertyHandle > > PropertyHandles; for( uint32 ChildIndex = 0; ChildIndex < NumChildren; ++ChildIndex ) { TSharedRef<IPropertyHandle> ChildHandle = StructPropertyHandle->GetChildHandle( ChildIndex ).ToSharedRef(); const FName PropertyName = ChildHandle->GetProperty()->GetFName(); PropertyHandles.Add(PropertyName, ChildHandle); } // We'll set up reset to default ourselves const bool bDisplayResetToDefault = false; const FString DisplayNameOverride = TEXT(""); AttenuationShapeHandle = PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, AttenuationShape)); DistanceAlgorithmHandle = PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, DistanceAlgorithm)); SpatializationAlgorithmHandle = PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, SpatializationAlgorithm)); TSharedRef<IPropertyHandle> AttenuationExtentsHandle = PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, AttenuationShapeExtents)).ToSharedRef(); uint32 NumExtentChildren; AttenuationExtentsHandle->GetNumChildren( NumExtentChildren ); TSharedPtr< IPropertyHandle > ExtentXHandle; TSharedPtr< IPropertyHandle > ExtentYHandle; TSharedPtr< IPropertyHandle > ExtentZHandle; for( uint32 ExtentChildIndex = 0; ExtentChildIndex < NumExtentChildren; ++ExtentChildIndex ) { TSharedRef<IPropertyHandle> ChildHandle = AttenuationExtentsHandle->GetChildHandle( ExtentChildIndex ).ToSharedRef(); const FName PropertyName = ChildHandle->GetProperty()->GetFName(); if (PropertyName == GET_MEMBER_NAME_CHECKED(FVector, X)) { ExtentXHandle = ChildHandle; } else if (PropertyName == GET_MEMBER_NAME_CHECKED(FVector, Y)) { ExtentYHandle = ChildHandle; } else { check(PropertyName == GET_MEMBER_NAME_CHECKED(FVector, Z)); ExtentZHandle = ChildHandle; } } ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, bAttenuate)).ToSharedRef()); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, bSpatialize)).ToSharedRef()); ChildBuilder.AddChildProperty(DistanceAlgorithmHandle.ToSharedRef() ); // Check to see if a spatialization plugin is enabled if (IsAudioPluginEnabled(EAudioPlugin::SPATIALIZATION)) { ChildBuilder.AddChildProperty(SpatializationAlgorithmHandle.ToSharedRef()); } IDetailPropertyRow& CustomCurveRow = ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, CustomAttenuationCurve)).ToSharedRef()); CustomCurveRow.Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsCustomCurveSelected)); IDetailPropertyRow& dbAttenuationRow = ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, dBAttenuationAtMax)).ToSharedRef()); dbAttenuationRow.Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsNaturalSoundSelected)); IDetailPropertyRow& AttenuationShapeRow = ChildBuilder.AddChildProperty( AttenuationShapeHandle.ToSharedRef() ); ChildBuilder.AddChildProperty(AttenuationExtentsHandle) .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsBoxSelected)) .DisplayName(NSLOCTEXT("AttenuationSettings", "BoxExtentsLabel", "Extents")) .ToolTip(NSLOCTEXT("AttenuationSettings", "BoxExtents", "The dimensions of the of the box.")); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "RadiusLabel", "Radius")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "RadiusLabel", "Radius")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "RadiusToolTip", "The distance from the location of the sound at which falloff begins.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentXHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsSphereSelected)); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "CapsuleHalfHeightLabel", "Capsule Half Height")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "CapsuleHalfHeightLabel", "Capsule Half Height")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "CapsuleHalfHeightToolTip", "The attenuation capsule's half height.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentXHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsCapsuleSelected)); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "CapsuleRadiusLabel", "Capsule Radius")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "CapsuleRadiusLabel", "Capsule Radius")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "CapsuleRadiusToolTip", "The attenuation capsule's radius.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentYHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsCapsuleSelected)); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "ConeRadiusLabel", "Cone Radius")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "ConeRadiusLabel", "Cone Radius")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "ConeRadiusToolTip", "The attenuation cone's radius.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentXHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsConeSelected)); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "ConeAngleLabel", "Cone Angle")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "ConeAngleLabel", "Cone Angle")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "ConeAngleToolTip", "The angle of the inner edge of the attenuation cone's falloff. Inside this angle sounds will be at full volume.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentYHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsConeSelected)); ChildBuilder.AddChildContent(NSLOCTEXT("AttenuationSettings", "ConeFalloffAngleLabel", "Cone Falloff Angle")) .NameContent() [ SNew(STextBlock) .Text(NSLOCTEXT("AttenuationSettings", "ConeFalloffAngleLabel", "Cone Falloff Angle")) .ToolTipText(NSLOCTEXT("AttenuationSettings", "ConeFalloffAngleToolTip", "The angle of the outer edge of the attenuation cone's falloff. Outside this angle sounds will be inaudible.")) .Font(StructCustomizationUtils.GetRegularFont()) ] .ValueContent() [ ExtentZHandle->CreatePropertyValueWidget() ] .Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsConeSelected)); IDetailPropertyRow& ConeOffsetRow = ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, ConeOffset)).ToSharedRef()); ConeOffsetRow.Visibility(TAttribute<EVisibility>(this, &FAttenuationSettingsCustomization::IsConeSelected)); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, FalloffDistance)).ToSharedRef()); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, OmniRadius)).ToSharedRef()); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, bAttenuateWithLPF)).ToSharedRef()); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, LPFRadiusMin)).ToSharedRef()); ChildBuilder.AddChildProperty(PropertyHandles.FindChecked(GET_MEMBER_NAME_CHECKED(FAttenuationSettings, LPFRadiusMax)).ToSharedRef()); if (PropertyHandles.Num() != 14) { FString PropertyList; for (auto It(PropertyHandles.CreateConstIterator()); It; ++It) { PropertyList += It.Key().ToString() + TEXT(", "); } ensureMsgf(false, TEXT("Unexpected property handle(s) customizing FAttenuationSettings: %s"), *PropertyList); } }
void FTextCustomization::CustomizeHeader( TSharedRef<class IPropertyHandle> InPropertyHandle, class FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& PropertyTypeCustomizationUtils ) { TSharedRef<IEditableTextProperty> EditableTextProperty = MakeShareable(new FEditableTextPropertyHandle(InPropertyHandle, PropertyTypeCustomizationUtils.GetPropertyUtilities())); const bool bIsMultiLine = EditableTextProperty->IsMultiLineText(); HeaderRow.FilterString(InPropertyHandle->GetPropertyDisplayName()) .NameContent() [ InPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(bIsMultiLine ? 250.f : 125.f) .MaxDesiredWidth(600.f) [ SNew(STextPropertyEditableTextBox, EditableTextProperty) .Font(FEditorStyle::GetFontStyle("PropertyWindow.NormalFont")) .AutoWrapText(true) ]; }
void FStringAssetReferenceCustomization::CustomizeHeader( TSharedRef<IPropertyHandle> InStructPropertyHandle, FDetailWidgetRow& HeaderRow, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) { StructPropertyHandle = InStructPropertyHandle; FString ClassFilterString = StructPropertyHandle->GetMetaData("AllowedClasses"); if( !ClassFilterString.IsEmpty() ) { TArray<FString> CustomClassFilterNames; ClassFilterString.ParseIntoArray(&CustomClassFilterNames, TEXT(","), true); for(auto It = CustomClassFilterNames.CreateConstIterator(); It; ++It) { const FString& ClassName = *It; UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName); if(!Class) { Class = LoadObject<UClass>(nullptr, *ClassName); } if(Class) { CustomClassFilters.Add(Class); } } } bExactClass = StructPropertyHandle->GetBoolMetaData("ExactClass"); FOnShouldFilterAsset AssetFilter; UClass* ClassFilter = UObject::StaticClass(); if(CustomClassFilters.Num() == 1 && !bExactClass) { // If we only have one class to filter on, set it as the class type filter rather than use a filter callback // We can only do this if we don't need an exact match, as the class filter also allows derived types // The class filter is much faster than the callback as we're not performing two different sets of type tests // (one against UObject, one against the actual type) ClassFilter = CustomClassFilters[0]; } else if(CustomClassFilters.Num() > 0) { // Only bind the filter if we have classes that need filtering AssetFilter.BindSP(this, &FStringAssetReferenceCustomization::OnShouldFilterAsset); } // Can the field be cleared const bool bAllowClear = !(StructPropertyHandle->GetMetaDataProperty()->PropertyFlags & CPF_NoClear); HeaderRow .NameContent() [ InStructPropertyHandle->CreatePropertyNameWidget() ] .ValueContent() .MinDesiredWidth(250.0f) .MaxDesiredWidth(0.0f) [ // Add an object entry box. Even though this isn't an object entry, we will simulate one SNew( SObjectPropertyEntryBox ) .PropertyHandle( InStructPropertyHandle ) .ThumbnailPool( StructCustomizationUtils.GetThumbnailPool() ) .AllowedClass( ClassFilter ) .OnShouldFilterAsset( AssetFilter ) .AllowClear( bAllowClear ) ]; }