bool FDetailCategoryImpl::GenerateChildrenForSingleLayout( const FName RequiredGroupName, bool bDefaultLayout, bool bNeedsGroup, const FCustomizationList& LayoutList, FDetailNodeList& OutChildren, bool& bOutLastItemHasMultipleColumns )
{
	bool bGeneratedAnyChildren = false;
	if( LayoutList.Num() > 0 )
	{
		FDetailNodeList GeneratedChildren;
		GenerateNodesFromCustomizations( LayoutList, bDefaultLayout, GeneratedChildren, bOutLastItemHasMultipleColumns );

		if( GeneratedChildren.Num() > 0 )
		{
			bGeneratedAnyChildren = true;
			if( bNeedsGroup )
			{
				TSharedRef<IDetailTreeNode> GroupNode = MakeShareable( new FDetailCategoryGroupNode( GeneratedChildren, RequiredGroupName, *this ) );
				OutChildren.Add( GroupNode );
			}
			else
			{
				OutChildren.Append( GeneratedChildren );
			}
		}
	}

	return bGeneratedAnyChildren;
}
void FDetailPropertyRow::GenerateChildrenForPropertyNode( TSharedPtr<FPropertyNode>& RootPropertyNode, FDetailNodeList& OutChildren )
{
	// Children should be disabled if we are disabled
	TAttribute<bool> ParentEnabledState = CustomIsEnabledAttrib;
	if( IsParentEnabled.IsBound() || HasEditCondition() )
	{
		// Bind a delegate to the edit condition so our children will be disabled if the edit condition fails
		ParentEnabledState.Bind( this, &FDetailPropertyRow::GetEnabledState );
	}

	if( PropertyTypeLayoutBuilder.IsValid() && bShowCustomPropertyChildren )
	{
		const TArray< FDetailLayoutCustomization >& ChildRows = PropertyTypeLayoutBuilder->GetChildCustomizations();

		for( int32 ChildIndex = 0; ChildIndex < ChildRows.Num(); ++ChildIndex )
		{
			TSharedRef<FDetailItemNode> ChildNodeItem = MakeShareable( new FDetailItemNode( ChildRows[ChildIndex], ParentCategory.Pin().ToSharedRef(), ParentEnabledState ) );
			ChildNodeItem->Initialize();
			OutChildren.Add( ChildNodeItem );
		}
	}
	else if (bShowCustomPropertyChildren || !CustomPropertyWidget.IsValid() )
	{
		TSharedRef<FDetailCategoryImpl> ParentCategoryRef = ParentCategory.Pin().ToSharedRef();
		IDetailLayoutBuilder& LayoutBuilder = ParentCategoryRef->GetParentLayout();
		UProperty* ParentProperty = RootPropertyNode->GetProperty();

		const bool bStructProperty = ParentProperty && ParentProperty->IsA<UStructProperty>();

		for( int32 ChildIndex = 0; ChildIndex < RootPropertyNode->GetNumChildNodes(); ++ChildIndex )
		{
			TSharedPtr<FPropertyNode> ChildNode = RootPropertyNode->GetChildNode(ChildIndex);

			if( ChildNode.IsValid() && ChildNode->HasNodeFlags( EPropertyNodeFlags::IsCustomized ) == 0 )
			{
				if( ChildNode->AsObjectNode() )
				{
					// Skip over object nodes and generate their children.  Object nodes are not visible
					GenerateChildrenForPropertyNode( ChildNode, OutChildren );
				}
				// Only struct children can have custom visibility that is different from their parent.
				else if ( !bStructProperty || LayoutBuilder.IsPropertyVisible( FPropertyAndParent(*ChildNode->GetProperty(), ParentProperty ) ) )
				{			
					FDetailLayoutCustomization Customization;
					Customization.PropertyRow = MakeShareable( new FDetailPropertyRow( ChildNode, ParentCategoryRef ) );
					TSharedRef<FDetailItemNode> ChildNodeItem = MakeShareable( new FDetailItemNode( Customization, ParentCategoryRef, ParentEnabledState ) );
					ChildNodeItem->Initialize();
					OutChildren.Add( ChildNodeItem );
				}
			}
		}
	}
}
void FDetailItemNode::GetChildren( FDetailNodeList& OutChildren )
{
	for( int32 ChildIndex = 0; ChildIndex < Children.Num(); ++ChildIndex )
	{
		TSharedRef<IDetailTreeNode>& Child = Children[ChildIndex];

		ENodeVisibility ChildVisibility = Child->GetVisibility();

		// Report the child if the child is visible or we are visible due to filtering and there were no filtered children.  
		// If we are visible due to filtering and so is a child, we only show that child.  
		// If we are visible due to filtering and no child is visible, we show all children

		if( ChildVisibility == ENodeVisibility::Visible ||
			( !bShouldBeVisibleDueToChildFiltering && bShouldBeVisibleDueToFiltering && ChildVisibility != ENodeVisibility::ForcedHidden ) )
		{
			if( Child->ShouldShowOnlyChildren() )
			{
				Child->GetChildren( OutChildren );
			}
			else
			{
				OutChildren.Add( Child );
			}
		}
	}
}
Beispiel #4
0
void FDetailGroup::OnGenerateChildren( FDetailNodeList& OutChildren )
{
	for( int32 ChildIndex = 0; ChildIndex < GroupChildren.Num(); ++ChildIndex )
	{
		TSharedRef<FDetailItemNode> NewNode = MakeShareable( new FDetailItemNode( GroupChildren[ChildIndex], ParentCategory.Pin().ToSharedRef(), IsParentEnabled ) );
		NewNode->Initialize();
		OutChildren.Add( NewNode );
	}
}
void FDetailCustomBuilderRow::OnGenerateChildren( FDetailNodeList& OutChildren )
{
	ChildrenBuilder = MakeShareable( new FCustomChildrenBuilder( ParentCategory.Pin().ToSharedRef() ) );

	CustomNodeBuilder->GenerateChildContent( *ChildrenBuilder );
		
	const TArray< FDetailLayoutCustomization >& ChildRows = ChildrenBuilder->GetChildCustomizations();

	for( int32 ChildIndex = 0; ChildIndex < ChildRows.Num(); ++ChildIndex )
	{
		TSharedRef<FDetailItemNode> ChildNodeItem = MakeShareable( new FDetailItemNode( ChildRows[ChildIndex], ParentCategory.Pin().ToSharedRef(), IsParentEnabled ) );
		ChildNodeItem->Initialize();
		OutChildren.Add( ChildNodeItem );
	}
}
void FDetailCategoryImpl::GenerateNodesFromCustomizations( const FCustomizationList& InCustomizationList, bool bDefaultLayouts, FDetailNodeList& OutNodeList, bool &bOutLastItemHasMultipleColumns )
{
	bOutLastItemHasMultipleColumns = false;
	for( int32 CustomizationIndex = 0; CustomizationIndex < InCustomizationList.Num(); ++CustomizationIndex )
	{
		const FDetailLayoutCustomization& Customization = InCustomizationList[CustomizationIndex];
		// When building default layouts cull default properties which have been customized
		if( Customization.IsValidCustomization() && ( !bDefaultLayouts || !IsCustomProperty( Customization.GetPropertyNode() ) ) )
		{
			bool bParentEnabled = true;
			TSharedRef<FDetailItemNode> NewNode = MakeShareable( new FDetailItemNode( Customization, AsShared(), bParentEnabled ) );
			NewNode->Initialize();

			if( CustomizationIndex == InCustomizationList.Num()-1 )
			{
				bOutLastItemHasMultipleColumns = NewNode->HasMultiColumnWidget();
			}

			OutNodeList.Add( NewNode );
		}
	}
}
void SDetailsViewBase::UpdateFilteredDetails()
{
	RootTreeNodes.Reset();

	FDetailNodeList InitialRootNodeList;
	
	NumVisbleTopLevelObjectNodes = 0;
	FRootPropertyNodeList& RootPropertyNodes = GetRootNodes();

	CurrentFilter.bShowAllAdvanced = GetDefault<UEditorStyleSettings>()->bShowAllAdvancedDetails;

	for(int32 RootNodeIndex = 0; RootNodeIndex < RootPropertyNodes.Num(); ++RootNodeIndex)
	{
		TSharedPtr<FComplexPropertyNode>& RootPropertyNode = RootPropertyNodes[RootNodeIndex];
		if(RootPropertyNode.IsValid())
		{
			RootPropertyNode->FilterNodes(CurrentFilter.FilterStrings);
			RootPropertyNode->ProcessSeenFlags(true);

			for(int32 NodeIndex = 0; NodeIndex < ExternalRootPropertyNodes.Num(); ++NodeIndex)
			{
				TSharedPtr<FPropertyNode> PropertyNode = ExternalRootPropertyNodes[NodeIndex].Pin();

				if(PropertyNode.IsValid())
				{
					PropertyNode->FilterNodes(CurrentFilter.FilterStrings);
					PropertyNode->ProcessSeenFlags(true);
				}
			}

			TSharedPtr<FDetailLayoutBuilderImpl>& DetailLayout = DetailLayouts[RootNodeIndex].DetailLayout;
			if(DetailLayout.IsValid())
			{
				DetailLayout->FilterDetailLayout(CurrentFilter);
			}

			FDetailNodeList& LayoutRoots = DetailLayout->GetRootTreeNodes();
			if(LayoutRoots.Num() > 0)
			{
				// A top level object nodes has a non-filtered away root so add one to the total number we have
				++NumVisbleTopLevelObjectNodes;

				InitialRootNodeList.Append(LayoutRoots);
			}
		
		}
	}


	// for multiple top level object we need to do a secondary pass on top level object nodes after we have determined if there is any nodes visible at all.  If there are then we ask the details panel if it wants to show childen
	for(TSharedRef<class IDetailTreeNode> RootNode : InitialRootNodeList)
	{
		if(RootNode->ShouldShowOnlyChildren())
		{
			RootNode->GetChildren(RootTreeNodes);
		}
		else
		{
			RootTreeNodes.Add(RootNode);
		}
	}

	RefreshTree();
}