From b23c19b9328fcdba65fb1bd741b2a310f552f148 Mon Sep 17 00:00:00 2001 From: Juan Portillo Date: Tue, 13 Jun 2023 11:39:25 -0400 Subject: [PATCH] Property Editor: - Fix properties under sub-categories not appearing at all when using Struct on Scope in Property Row Generator #jira UE-182375 #rb karen.jirak [CL 25953385 by Juan Portillo in ue5-main branch] --- .../Private/DetailLayoutBuilderImpl.cpp | 95 +++++++++++++++++-- 1 file changed, 87 insertions(+), 8 deletions(-) diff --git a/Engine/Source/Editor/PropertyEditor/Private/DetailLayoutBuilderImpl.cpp b/Engine/Source/Editor/PropertyEditor/Private/DetailLayoutBuilderImpl.cpp index 330802be0973..c6e1377a7f39 100644 --- a/Engine/Source/Editor/PropertyEditor/Private/DetailLayoutBuilderImpl.cpp +++ b/Engine/Source/Editor/PropertyEditor/Private/DetailLayoutBuilderImpl.cpp @@ -343,18 +343,97 @@ void FDetailLayoutBuilderImpl::GenerateDetailLayout() TArray> SimpleCategories; TArray> AdvancedOnlyCategories; - SubCategoryMap.Empty(); - for (FCategoryMap::TIterator It(DefaultCategoryMap); It; ++It) + // Remove all subcategories { - // Remove all subcategories - TSharedPtr DetailCategory = It.Value(); - // Note: Sub-categories are added later - int32 Index = INDEX_NONE; - if (DetailCategory->GetCategoryName().ToString().FindChar(FPropertyNodeConstants::CategoryDelimiterChar, Index)) + const TSharedRef This = SharedThis(this); + + // The map of Default Categories added after removing Sub categories + // Only used when there is no support for sub-categories + FCategoryMap DefaultCategoryMapToAppend; + + // Store the Default Category Map Num as it will be decreasing as sub category entries are removed + const int32 DefaultCategoryMapCount = DefaultCategoryMap.Num(); + + FName ParentStructPropertyName = NAME_None; + bool bSupportsSubCategory = false; + + if (TSharedPtr RootNodePtr = RootNode.Pin()) { - SubCategoryMap.Add(It.Key(), DetailCategory); + if (FStructProperty* const ParentStructProperty = CastField(RootNodePtr->GetProperty())) + { + ParentStructPropertyName = ParentStructProperty->GetFName(); + } + + // Currently only Object Nodes with Show Categories support Sub-categories + bSupportsSubCategory = RootNodePtr->AsObjectNode() && RootNodePtr->HasNodeFlags(EPropertyNodeFlags::ShowCategories); + } + + SubCategoryMap.Empty(); + + for (FCategoryMap::TIterator It(DefaultCategoryMap); It; ++It) + { + TSharedPtr DetailCategory = It.Value(); + + int32 Index = INDEX_NONE; + const FString CategoryNameStr = DetailCategory->GetCategoryName().ToString(); + if (!CategoryNameStr.FindChar(FPropertyNodeConstants::CategoryDelimiterChar, Index)) + { + // No category delimiter found + continue; + } + + // Note: Sub-categories are added later if supported + if (bSupportsSubCategory) + { + SubCategoryMap.Add(It.Key(), DetailCategory); + } + // When Sub category isn't supported, generate properties and move them to parent category + else + { + const FName ParentCategoryName = *CategoryNameStr.Left(Index); + + TSharedPtr* const ExistingParentDetailCategory = DefaultCategoryMap.Find(ParentCategoryName); + + TSharedPtr& ParentDetailCategory = ExistingParentDetailCategory + ? *ExistingParentDetailCategory + : DefaultCategoryMapToAppend.FindOrAdd(ParentCategoryName); + + if (!ParentDetailCategory.IsValid()) + { + ParentDetailCategory = MakeShared(ParentCategoryName, This); + ParentDetailCategory->SetSortOrder(DetailCategory->GetSortOrder()); + ParentDetailCategory->SetDisplayName(ParentCategoryName, FText::GetEmpty()); + } + + // Move the Property Nodes from the sub-category to the parent category + // To do this, generate a layout for the sub category here as they're unsupported and won't have an opportunity to do it later + FDetailNodeList ChildNodes; + DetailCategory->GenerateLayout(); + DetailCategory->GetGeneratedChildren(ChildNodes, /*bIgnoreVisibility*/true, /*bIgnoreAdvancedDropdown*/true); + + for (const TSharedRef& ChildNode : ChildNodes) + { + TSharedPtr PropertyNode = ChildNode->GetPropertyNode(); + if (!PropertyNode.IsValid()) + { + continue; + } + + // If there is no outer object then the class is the object root and there is only one instance + FName InstanceName = ParentStructPropertyName; + FPropertyNode* const ParentNode = PropertyNode->GetParentNode(); + if (ParentNode && ParentNode->GetProperty()) + { + InstanceName = ParentNode->GetProperty()->GetFName(); + } + ParentDetailCategory->AddPropertyNode(PropertyNode.ToSharedRef(), InstanceName); + } + } + It.RemoveCurrent(); } + + DefaultCategoryMap.Append(MoveTemp(DefaultCategoryMapToAppend)); } // Build default categories