Files
UnrealEngine/Engine/Source/Editor/MaterialEditor/Private/SMaterialEditorCustomPrimitiveDataWidget.cpp
2025-05-18 13:04:45 +08:00

181 lines
5.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "SMaterialEditorCustomPrimitiveDataWidget.h"
#include "Widgets/Layout/SScrollBox.h"
#include "MaterialEditor/MaterialEditorPreviewParameters.h"
#include "Materials/MaterialExpressionScalarParameter.h"
#include "Materials/MaterialExpressionVectorParameter.h"
#include "EdGraph/EdGraphNode.h"
#include "EdGraph/EdGraph.h"
#include "Widgets/SToolTip.h"
class SCustomPrimitiveDataRow : public SMultiColumnTableRow<TSharedPtr<FCustomPrimitiveDataRowData>>
{
public:
SLATE_BEGIN_ARGS(SCustomPrimitiveDataRow) {}
SLATE_ARGUMENT(TSharedPtr<FCustomPrimitiveDataRowData>, Entry)
SLATE_END_ARGS()
void Construct(const FArguments& Args, const TSharedRef<STableViewBase>& OwnerTableView)
{
RowData = Args._Entry;
FSuperRowType::Construct(
FSuperRowType::FArguments()
.Padding(1.0f),
OwnerTableView
);
}
/** Overridden from SMultiColumnTableRow. Generates a widget for this column of the list view. */
virtual TSharedRef<SWidget> GenerateWidgetForColumn(const FName& ColumnName) override
{
TSharedRef<STextBlock> TextBlock = SNew(STextBlock);
if (RowData->bIsDuplicate)
{
TextBlock->SetToolTip(SNew(SToolTip).Text(FText::FromString("This slot is potentially incorrectly overlapping")).BorderImage(FCoreStyle::Get().GetBrush("ToolTip.BrightBackground")));
TextBlock->SetColorAndOpacity(FSlateColor(FLinearColor::Red));
}
if (ColumnName == "Slot")
{
TextBlock->SetText(FText::FromString(FString::FormatAsNumber(RowData->Slot)));
return TextBlock;
}
else if (ColumnName == "Name")
{
TextBlock->SetText(FText::FromString(RowData->Name));
return TextBlock;
}
return SNullWidget::NullWidget;
}
private:
TSharedPtr<FCustomPrimitiveDataRowData> RowData;
};
void SMaterialCustomPrimitiveDataPanel::Refresh()
{
TMap<int32, TSet<FString>> IndexBuckets;
if (MaterialEditorInstance && MaterialEditorInstance->PreviewMaterial)
{
TArray<UMaterialExpressionScalarParameter*> Scalars;
MaterialEditorInstance->PreviewMaterial->GetAllExpressionsInMaterialAndFunctionsOfType<UMaterialExpressionScalarParameter>(Scalars);
for (const UMaterialExpressionScalarParameter* Expr : Scalars)
{
if (Expr->bUseCustomPrimitiveData)
{
TSet<FString>& Params = IndexBuckets.FindOrAdd((int32)Expr->PrimitiveDataIndex);
Params.Add(Expr->GetParameterName().ToString());
}
}
TArray<UMaterialExpressionVectorParameter*> Vectors;
MaterialEditorInstance->PreviewMaterial->GetAllExpressionsInMaterialAndFunctionsOfType<UMaterialExpressionVectorParameter>(Vectors);
for (const UMaterialExpressionVectorParameter* Expr : Vectors)
{
if (Expr->bUseCustomPrimitiveData)
{
TArray<FString> Elements({".r", ".g" , ".b", ".a" });
for (int32 i = 0; i < 4; i++)
{
TSet<FString>& Params = IndexBuckets.FindOrAdd((int32)Expr->PrimitiveDataIndex + i);
Params.Add(Expr->GetParameterName().ToString() + Elements[i]);
}
}
}
Items.Empty();
// Go through and mark slots as duplicate while copying over to the shared ptr array
for (auto& Params : IndexBuckets)
{
for (FString& ParamName : Params.Value)
{
Items.Add(MakeShareable(new FCustomPrimitiveDataRowData(Params.Key, ParamName, Params.Value.Num() > 1)));
}
}
// Sort the items
Items.StableSort([](const TSharedPtr<FCustomPrimitiveDataRowData>& A, const TSharedPtr<FCustomPrimitiveDataRowData>& B) {
int32 SlotA = A->Slot;
int32 SlotB = B->Slot;
if (SlotA == SlotB)
{
return A->Name < B->Name;
}
return SlotA < SlotB;
});
}
ListViewWidget->RequestListRefresh();
}
void SMaterialCustomPrimitiveDataPanel::Construct(const FArguments& InArgs, UMaterialEditorPreviewParameters* InMaterialEditorInstance)
{
this->ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("DetailsView.CategoryTop_Hovered"))
.Padding(FMargin(4.0f))
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.Padding(FMargin(3.0f, 4.0f))
.HAlign(HAlign_Left)
.AutoWidth()
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Custom Primitive Data Parameters"))
.Font(FAppStyle::GetFontStyle("DetailsView.CategoryFontStyle"))
.ShadowOffset(FVector2D(1.0f, 1.0f))
]
]
+ SVerticalBox::Slot()
.Padding(FMargin(3.0f, 2.0f, 3.0f, 3.0f))
[
SNew(SBorder)
.BorderImage(FAppStyle::GetBrush("DetailsView.CategoryTop"))
[
SNew(SScrollBox)
+ SScrollBox::Slot()
[
SAssignNew(ListViewWidget, SListView<TSharedPtr<FCustomPrimitiveDataRowData>>)
.ListItemsSource(&Items)
.OnGenerateRow(this, &SMaterialCustomPrimitiveDataPanel::OnGenerateRowForList)
.SelectionMode(ESelectionMode::None)
.HeaderRow
(
SNew(SHeaderRow)
+ SHeaderRow::Column("Slot").DefaultLabel(FText::FromString("Slot")).ManualWidth(48.0f)
+ SHeaderRow::Column("Name").DefaultLabel(FText::FromString("Name"))
)
]
]
]
]
]
];
MaterialEditorInstance = InMaterialEditorInstance;
Refresh();
}
TSharedRef<ITableRow> SMaterialCustomPrimitiveDataPanel::OnGenerateRowForList(TSharedPtr<FCustomPrimitiveDataRowData> Item, const TSharedRef<STableViewBase>& OwnerTable)
{
return SNew(SCustomPrimitiveDataRow, OwnerTable).Entry(Item);
}