Files
UnrealEngineUWP/Engine/Source/Editor/PropertyEditor/Private/SStructureDetailsView.cpp
jamie dale 7519468dff Exposed RequestForceRefresh for detail customizations to use
This was available within SDetailsViewBase, but the only publicly available function was ForceRefresh which isn't deferred

Using RequestForceRefresh is preferable when the refresh can be deferred, as it can prevent performance problems from refreshing the view multiple times within a single frame

#rb Rex.Hill

[CL 31275746 by jamie dale in ue5-main branch]
2024-02-07 18:10:19 -05:00

351 lines
10 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SStructureDetailsView.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SComboButton.h"
#include "AssetSelection.h"
#include "DetailCategoryBuilderImpl.h"
#include "UserInterface/PropertyDetails/PropertyDetailsUtilities.h"
#include "StructurePropertyNode.h"
#include "Widgets/Colors/SColorPicker.h"
#include "Widgets/Input/SSearchBox.h"
#include "DetailsViewPropertyGenerationUtilities.h"
#define LOCTEXT_NAMESPACE "SStructureDetailsView"
SStructureDetailsView::~SStructureDetailsView()
{
auto RootNodeLocal = GetRootNode();
if (RootNodeLocal.IsValid())
{
SaveExpandedItems(RootNodeLocal.ToSharedRef());
}
}
UStruct* SStructureDetailsView::GetBaseScriptStruct() const
{
const UStruct* Struct = StructProvider.IsValid() ? StructProvider->GetBaseStructure() : nullptr;
return const_cast<UStruct*>(Struct);
}
void SStructureDetailsView::Construct(const FArguments& InArgs)
{
DetailsViewArgs = InArgs._DetailsViewArgs;
ColumnSizeData.SetValueColumnWidth(DetailsViewArgs.ColumnWidth);
ColumnSizeData.SetRightColumnMinWidth(DetailsViewArgs.RightColumnMinWidth);
CustomName = InArgs._CustomName;
// Create the root property now
// Only one root node in a structure details view
RootNodes.Empty(1);
RootNodes.Add(MakeShareable(new FStructurePropertyNode));
PropertyUtilities = MakeShareable( new FPropertyDetailsUtilities( *this ) );
PropertyGenerationUtilities = MakeShareable(new FDetailsViewPropertyGenerationUtilities(*this));
TSharedRef<SScrollBar> ExternalScrollbar = SNew(SScrollBar);
// See note in SDetailsView for why visibility is set after construction
ExternalScrollbar->SetVisibility( TAttribute<EVisibility>(this, &SStructureDetailsView::GetScrollBarVisibility) );
FMenuBuilder DetailViewOptions( true, nullptr );
FUIAction ShowOnlyModifiedAction(
FExecuteAction::CreateSP(this, &SStructureDetailsView::OnShowOnlyModifiedClicked),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SStructureDetailsView::IsShowOnlyModifiedChecked)
);
if (DetailsViewArgs.bShowModifiedPropertiesOption)
{
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowOnlyModified", "Show Only Modified Properties"),
LOCTEXT("ShowOnlyModified_ToolTip", "Displays only properties which have been changed from their default"),
FSlateIcon(),
ShowOnlyModifiedAction,
NAME_None,
EUserInterfaceActionType::ToggleButton
);
}
if (DetailsViewArgs.bShowKeyablePropertiesOption)
{
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowOnlyKeyable", "Show Only Keyable Properties"),
LOCTEXT("ShowOnlyKeyable_ToolTip", "Displays only properties which are keyable"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateSP(this, &SStructureDetailsView::OnShowKeyableClicked),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SStructureDetailsView::IsShowKeyableChecked)
),
NAME_None,
EUserInterfaceActionType::ToggleButton
);
}
if (DetailsViewArgs.bShowAnimatedPropertiesOption)
{
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowAnimated", "Show Only Animated Properties"),
LOCTEXT("ShowAnimated_ToolTip", "Displays only properties which are animated (have tracks)"),
FSlateIcon(),
FUIAction(
FExecuteAction::CreateSP(this, &SStructureDetailsView::OnShowAnimatedClicked),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SStructureDetailsView::IsShowAnimatedChecked)
),
NAME_None,
EUserInterfaceActionType::ToggleButton
);
}
FUIAction ShowAllAdvancedAction(
FExecuteAction::CreateSP(this, &SStructureDetailsView::OnShowAllAdvancedClicked),
FCanExecuteAction(),
FIsActionChecked::CreateSP(this, &SStructureDetailsView::IsShowAllAdvancedChecked)
);
DetailViewOptions.AddMenuEntry(
LOCTEXT("ShowAllAdvanced", "Show All Advanced Details"),
LOCTEXT("ShowAllAdvanced_ToolTip", "Shows all advanced detail sections in each category"),
FSlateIcon(),
ShowAllAdvancedAction,
NAME_None,
EUserInterfaceActionType::ToggleButton
);
DetailViewOptions.AddMenuEntry(
LOCTEXT("CollapseAll", "Collapse All Categories"),
LOCTEXT("CollapseAll_ToolTip", "Collapses all root level categories"),
FSlateIcon(),
FUIAction(FExecuteAction::CreateSP(this, &SStructureDetailsView::SetRootExpansionStates, /*bExpanded=*/false, /*bRecurse=*/false)));
DetailViewOptions.AddMenuEntry(
LOCTEXT("ExpandAll", "Expand All Categories"),
LOCTEXT("ExpandAll_ToolTip", "Expands all root level categories"),
FSlateIcon(),
FUIAction(FExecuteAction::CreateSP(this, &SStructureDetailsView::SetRootExpansionStates, /*bExpanded=*/true, /*bRecurse=*/false)));
TSharedRef<SHorizontalBox> FilterBoxRow = SNew( SHorizontalBox )
.Visibility(this, &SStructureDetailsView::GetFilterBoxVisibility)
+SHorizontalBox::Slot()
.FillWidth( 1 )
.VAlign( VAlign_Center )
[
// Create the search box
SAssignNew( SearchBox, SSearchBox )
.OnTextChanged(this, &SStructureDetailsView::OnFilterTextChanged)
];
if (DetailsViewArgs.bShowOptions)
{
FilterBoxRow->AddSlot()
.HAlign(HAlign_Right)
.AutoWidth()
[
SNew( SComboButton )
.ContentPadding(0.0f)
.ForegroundColor( FSlateColor::UseForeground() )
.ButtonStyle( FAppStyle::Get(), "ToggleButton" )
.MenuContent()
[
DetailViewOptions.MakeWidget()
]
.ButtonContent()
[
SNew(SImage)
.Image( FAppStyle::GetBrush("GenericViewButton") )
]
];
}
SAssignNew(DetailTree, SDetailTree)
.Visibility(this, &SStructureDetailsView::GetTreeVisibility)
.TreeItemsSource(&RootTreeNodes)
.OnGetChildren(this, &SStructureDetailsView::OnGetChildrenForDetailTree)
.OnSetExpansionRecursive(this, &SStructureDetailsView::SetNodeExpansionStateRecursive)
.OnGenerateRow(this, &SStructureDetailsView::OnGenerateRowForDetailTree)
.OnExpansionChanged(this, &SStructureDetailsView::OnItemExpansionChanged)
.SelectionMode(ESelectionMode::None)
.ExternalScrollbar(ExternalScrollbar);
ChildSlot
[
SNew( SBox )
.Visibility(this, &SStructureDetailsView::GetPropertyEditingVisibility)
[
SNew( SVerticalBox )
+ SVerticalBox::Slot()
.AutoHeight()
.Padding( 0.0f, 0.0f, 0.0f, 2.0f )
[
FilterBoxRow
]
+ SVerticalBox::Slot()
.FillHeight(1.0f)
.Padding(0.0f)
[
SNew( SOverlay )
+ SOverlay::Slot()
[
DetailTree.ToSharedRef()
]
+ SOverlay::Slot()
.HAlign(HAlign_Right)
[
SNew( SBox )
.WidthOverride( 16.0f )
[
ExternalScrollbar
]
]
]
]
];
}
void SStructureDetailsView::SetStructureData(TSharedPtr<FStructOnScope> InStructData)
{
SetStructureProvider(InStructData ? MakeShared<FStructOnScopeStructureDataProvider>(InStructData) : TSharedPtr<IStructureDataProvider>());
}
void SStructureDetailsView::SetStructureProvider(TSharedPtr<IStructureDataProvider> InStructProvider)
{
TSharedPtr<FComplexPropertyNode> RootNode = GetRootNode();
//PRE SET
SaveExpandedItems(RootNode.ToSharedRef() );
RootNode->AsStructureNode()->RemoveStructure();
RootNodesPendingKill.Add(RootNode);
RootNodes.Empty(1);
ExpandedDetailNodes.Clear();
RootNode = MakeShareable(new FStructurePropertyNode);
RootNodes.Add(RootNode);
//SET
StructProvider = InStructProvider;
RootNode->AsStructureNode()->SetStructure(StructProvider);
if (!StructProvider.IsValid())
{
bIsLocked = false;
}
//POST SET
TSharedPtr<SColorPicker> ExistingColorPicker = GetColorPicker();
if (ExistingColorPicker.IsValid()
&& (!ExistingColorPicker->GetOptionalOwningDetailsView().IsValid()
|| ExistingColorPicker->GetOptionalOwningDetailsView().Get() == this))
{
DestroyColorPicker();
bHasOpenColorPicker = false;
}
FPropertyNodeInitParams InitParams;
InitParams.ParentNode = nullptr;
InitParams.Property = nullptr;
InitParams.ArrayOffset = 0;
InitParams.ArrayIndex = INDEX_NONE;
InitParams.bAllowChildren = true;
InitParams.bForceHiddenPropertyVisibility = FPropertySettings::Get().ShowHiddenProperties() || DetailsViewArgs.bForceHiddenPropertyVisibility;
InitParams.bCreateCategoryNodes = false;
RootNode->InitNode(InitParams);
RootNode->SetDisplayNameOverride(CustomName);
RestoreExpandedItems(RootNode.ToSharedRef());
UpdatePropertyMaps();
UpdateFilteredDetails();
}
void SStructureDetailsView::SetCustomName(const FText& Text)
{
CustomName = Text;
}
void SStructureDetailsView::ForceRefresh()
{
ClearPendingRefreshTimer();
SetStructureProvider(StructProvider);
}
void SStructureDetailsView::ClearSearch()
{
CurrentFilter.FilterStrings.Empty();
SearchBox->SetText(FText::GetEmpty());
RerunCurrentFilter();
}
const TArray< TWeakObjectPtr<UObject> >& SStructureDetailsView::GetSelectedObjects() const
{
static const TArray< TWeakObjectPtr<UObject> > DummyRef;
return DummyRef;
}
const TArray< TWeakObjectPtr<AActor> >& SStructureDetailsView::GetSelectedActors() const
{
static const TArray< TWeakObjectPtr<AActor> > DummyRef;
return DummyRef;
}
const FSelectedActorInfo& SStructureDetailsView::GetSelectedActorInfo() const
{
static const FSelectedActorInfo DummyRef;
return DummyRef;
}
bool SStructureDetailsView::IsConnected() const
{
const FStructurePropertyNode* RootNode = GetRootNode().IsValid() ? GetRootNode()->AsStructureNode() : nullptr;
return StructProvider.IsValid() && StructProvider->IsValid() && RootNode && RootNode->HasValidStructData();
}
FRootPropertyNodeList& SStructureDetailsView::GetRootNodes()
{
return RootNodes;
}
TSharedPtr<class FComplexPropertyNode> SStructureDetailsView::GetRootNode()
{
return RootNodes[0];
}
const TSharedPtr<class FComplexPropertyNode> SStructureDetailsView::GetRootNode() const
{
return RootNodes[0];
}
void SStructureDetailsView::CustomUpdatePropertyMap(TSharedPtr<FDetailLayoutBuilderImpl>& InDetailLayout)
{
FName StructCategoryName = NAME_None;
const UStruct* Struct = StructProvider.IsValid() ? StructProvider->GetBaseStructure() : nullptr;
if (Struct)
{
TArray<FName> CategoryNames;
InDetailLayout->GetCategoryNames(CategoryNames);
int32 StructCategoryNameIndex = INDEX_NONE;
CategoryNames.Find(Struct->GetFName(), StructCategoryNameIndex);
StructCategoryName = StructCategoryNameIndex != INDEX_NONE ? CategoryNames[StructCategoryNameIndex] : NAME_None;
}
InDetailLayout->DefaultCategory(StructCategoryName).SetDisplayName(NAME_None, CustomName);
}
EVisibility SStructureDetailsView::GetPropertyEditingVisibility() const
{
const FStructurePropertyNode* RootNode = GetRootNode().IsValid() ? GetRootNode()->AsStructureNode() : nullptr;
return StructProvider.IsValid() && StructProvider->IsValid() && RootNode && RootNode->HasValidStructData() ? EVisibility::Visible : EVisibility::Collapsed;
}
#undef LOCTEXT_NAMESPACE