// Copyright Epic Games, Inc. All Rights Reserved. #include "CustomChildBuilder.h" #include "Modules/ModuleManager.h" #include "DetailGroup.h" #include "PropertyHandleImpl.h" #include "DetailPropertyRow.h" #include "ObjectPropertyNode.h" IDetailChildrenBuilder& FCustomChildrenBuilder::AddCustomBuilder( TSharedRef InCustomBuilder ) { FDetailLayoutCustomization NewCustomization; NewCustomization.CustomBuilderRow = MakeShareable( new FDetailCustomBuilderRow( InCustomBuilder ) ); ChildCustomizations.Add( NewCustomization ); return *this; } IDetailGroup& FCustomChildrenBuilder::AddGroup( FName GroupName, const FText& LocalizedDisplayName ) { FDetailLayoutCustomization NewCustomization; NewCustomization.DetailGroup = MakeShareable( new FDetailGroup( GroupName, ParentCategory.Pin().ToSharedRef(), LocalizedDisplayName ) ); ChildCustomizations.Add( NewCustomization ); return *NewCustomization.DetailGroup; } FDetailWidgetRow& FCustomChildrenBuilder::AddCustomRow( const FText& SearchString ) { TSharedRef NewRow = MakeShareable( new FDetailWidgetRow ); FDetailLayoutCustomization NewCustomization; NewRow->FilterString( SearchString ); NewCustomization.WidgetDecl = NewRow; ChildCustomizations.Add( NewCustomization ); return *NewRow; } IDetailPropertyRow& FCustomChildrenBuilder::AddProperty( TSharedRef PropertyHandle ) { check( PropertyHandle->IsValidHandle() ) FDetailLayoutCustomization NewCustomization; NewCustomization.PropertyRow = MakeShareable( new FDetailPropertyRow( StaticCastSharedRef( PropertyHandle )->GetPropertyNode(), ParentCategory.Pin().ToSharedRef() ) ); if (CustomResetChildToDefault.IsSet()) { NewCustomization.PropertyRow->OverrideResetToDefault(CustomResetChildToDefault.GetValue()); } ChildCustomizations.Add( NewCustomization ); return *NewCustomization.PropertyRow; } IDetailPropertyRow* FCustomChildrenBuilder::AddExternalStructure(TSharedRef ChildStructure, FName UniqueIdName) { return AddExternalStructureProperty(ChildStructure, NAME_None, FAddPropertyParams().UniqueId(UniqueIdName)); } IDetailPropertyRow* FCustomChildrenBuilder::AddExternalStructureProperty(TSharedRef ChildStructure, FName PropertyName, const FAddPropertyParams& Params) { FDetailLayoutCustomization NewCustomization; TSharedRef ParentCategoryRef = ParentCategory.Pin().ToSharedRef(); FDetailPropertyRow::MakeExternalPropertyRowCustomization(ChildStructure, PropertyName, ParentCategoryRef, NewCustomization, Params); TSharedPtr NewRow = NewCustomization.PropertyRow; if (NewRow.IsValid()) { NewRow->SetCustomExpansionId(Params.GetUniqueId()); TSharedPtr PropertyNode = NewRow->GetPropertyNode(); TSharedPtr RootNode = StaticCastSharedRef(PropertyNode->FindComplexParent()->AsShared()); ChildCustomizations.Add(NewCustomization); } return NewRow.Get(); } IDetailPropertyRow* FCustomChildrenBuilder::AddExternalObjects(const TArray& Objects, FName UniqueIdName) { return AddExternalObjectProperty(Objects, NAME_None, FAddPropertyParams().UniqueId(UniqueIdName)); } TArray> FCustomChildrenBuilder::AddAllExternalStructureProperties(TSharedRef ChildStructure) { return ParentCategory.Pin()->AddAllExternalStructureProperties(ChildStructure); } IDetailPropertyRow* FCustomChildrenBuilder::AddExternalObjectProperty(const TArray& Objects, FName PropertyName, const FAddPropertyParams& Params) { FDetailLayoutCustomization NewCustomization; TSharedRef ParentCategoryRef = ParentCategory.Pin().ToSharedRef(); FDetailPropertyRow::MakeExternalPropertyRowCustomization(Objects, PropertyName, ParentCategoryRef, NewCustomization, Params); TSharedPtr NewRow = NewCustomization.PropertyRow; if (NewRow.IsValid()) { NewRow->SetCustomExpansionId(Params.GetUniqueId()); TSharedPtr PropertyNode = NewRow->GetPropertyNode(); TSharedPtr RootNode = StaticCastSharedRef(PropertyNode->FindObjectItemParent()->AsShared()); ChildCustomizations.Add(NewCustomization); } return NewRow.Get(); } class SStandaloneCustomStructValue : public SCompoundWidget, public IPropertyTypeCustomizationUtils { public: SLATE_BEGIN_ARGS( SStandaloneCustomStructValue ) {} SLATE_END_ARGS() void Construct( const FArguments& InArgs, TSharedPtr InCustomizationInterface, TSharedRef InStructPropertyHandle, TSharedRef InParentCategory ) { CustomizationInterface = InCustomizationInterface; StructPropertyHandle = InStructPropertyHandle; ParentCategory = InParentCategory; CustomPropertyWidget = MakeShareable(new FDetailWidgetRow); CustomizationInterface->CustomizeHeader(InStructPropertyHandle, *CustomPropertyWidget, *this); ChildSlot [ CustomPropertyWidget->ValueWidget.Widget ]; } virtual TSharedPtr GetThumbnailPool() const override { TSharedPtr ParentCategoryPinned = ParentCategory.Pin(); return ParentCategoryPinned.IsValid() ? ParentCategoryPinned->GetParentLayout().GetThumbnailPool() : NULL; } private: TWeakPtr ParentCategory; TSharedPtr CustomizationInterface; TSharedPtr StructPropertyHandle; TSharedPtr CustomPropertyWidget; }; TSharedRef FCustomChildrenBuilder::GenerateStructValueWidget( TSharedRef StructPropertyHandle ) { FStructProperty* StructProperty = CastFieldChecked( StructPropertyHandle->GetProperty() ); FPropertyEditorModule& PropertyEditorModule = FModuleManager::GetModuleChecked("PropertyEditor"); IDetailsViewPrivate* DetailsView = ParentCategory.Pin()->GetDetailsView(); FPropertyTypeLayoutCallback LayoutCallback = PropertyEditorModule.GetPropertyTypeCustomization(StructProperty, *StructPropertyHandle, DetailsView ? DetailsView->GetCustomPropertyTypeLayoutMap() : FCustomPropertyTypeLayoutMap() ); if (LayoutCallback.IsValid()) { TSharedRef CustomStructInterface = LayoutCallback.GetCustomizationInstance(); return SNew( SStandaloneCustomStructValue, CustomStructInterface, StructPropertyHandle, ParentCategory.Pin().ToSharedRef() ); } else { // Uncustomized structs have nothing for their value content return SNullWidget::NullWidget; } } IDetailCategoryBuilder& FCustomChildrenBuilder::GetParentCategory() const { return *ParentCategory.Pin(); } FCustomChildrenBuilder& FCustomChildrenBuilder::OverrideResetChildrenToDefault(const FResetToDefaultOverride& ResetToDefault) { CustomResetChildToDefault = ResetToDefault; return *this; } IDetailGroup* FCustomChildrenBuilder::GetParentGroup() const { return ParentGroup.IsValid() ? ParentGroup.Pin().Get() : nullptr; }