973 lines
33 KiB
C++
973 lines
33 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "SMaterialParametersOverviewWidget.h"
|
|
#include "MaterialEditor/DEditorFontParameterValue.h"
|
|
#include "MaterialEditor/DEditorMaterialLayersParameterValue.h"
|
|
#include "MaterialEditor/DEditorScalarParameterValue.h"
|
|
#include "MaterialEditor/DEditorStaticComponentMaskParameterValue.h"
|
|
#include "MaterialEditor/DEditorStaticSwitchParameterValue.h"
|
|
#include "MaterialEditor/DEditorTextureParameterValue.h"
|
|
#include "MaterialEditor/DEditorVectorParameterValue.h"
|
|
#include "MaterialEditor/MaterialEditorInstanceConstant.h"
|
|
#include "Materials/Material.h"
|
|
#include "PropertyHandle.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "PropertyEditorModule.h"
|
|
#include "ISinglePropertyView.h"
|
|
#include "Materials/MaterialInstanceConstant.h"
|
|
#include "Styling/AppStyle.h"
|
|
#include "PropertyCustomizationHelpers.h"
|
|
#include "ScopedTransaction.h"
|
|
#include "IPropertyRowGenerator.h"
|
|
#include "Widgets/Views/STreeView.h"
|
|
#include "IDetailTreeNode.h"
|
|
#include "AssetThumbnail.h"
|
|
#include "MaterialEditorInstanceDetailCustomization.h"
|
|
#include "MaterialPropertyHelpers.h"
|
|
#include "DetailWidgetRow.h"
|
|
#include "Widgets/Input/SCheckBox.h"
|
|
#include "EditorSupportDelegates.h"
|
|
#include "Widgets/Images/SImage.h"
|
|
#include "MaterialEditor/MaterialEditorPreviewParameters.h"
|
|
#include "Widgets/Input/SButton.h"
|
|
#include "Widgets/Text/SInlineEditableTextBlock.h"
|
|
#include "Materials/MaterialFunction.h"
|
|
#include "Materials/MaterialFunctionInstance.h"
|
|
#include "Materials/MaterialFunctionInterface.h"
|
|
#include "Materials/MaterialExpressionTextureSampleParameter.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
|
|
#include "Widgets/Input/SEditableTextBox.h"
|
|
#include "Curves/CurveLinearColor.h"
|
|
#include "Curves/CurveLinearColorAtlas.h"
|
|
#include "Widgets/Views/SExpanderArrow.h"
|
|
#include "Widgets/Layout/SWidgetSwitcher.h"
|
|
#include "MaterialEditor/DEditorRuntimeVirtualTextureParameterValue.h"
|
|
#include "MaterialEditor/DEditorSparseVolumeTextureParameterValue.h"
|
|
#include "ThumbnailRendering/ThumbnailManager.h"
|
|
#include "Styling/StyleColors.h"
|
|
|
|
|
|
|
|
#define LOCTEXT_NAMESPACE "MaterialLayerCustomization"
|
|
|
|
FString SMaterialParametersOverviewTreeItem::GetCurvePath(UDEditorScalarParameterValue* Parameter) const
|
|
{
|
|
FString Path = Parameter->AtlasData.Curve->GetPathName();
|
|
return Path;
|
|
}
|
|
|
|
const FSlateBrush* SMaterialParametersOverviewTreeItem::GetBorderImage() const
|
|
{
|
|
return FAppStyle::Get().GetBrush("DetailsView.CategoryMiddle");
|
|
}
|
|
|
|
FSlateColor SMaterialParametersOverviewTreeItem::GetOuterBackgroundColor(TSharedPtr<FSortedParamData> InParamData) const
|
|
{
|
|
if (IsHovered() || InParamData->StackDataType == EStackDataType::Group)
|
|
{
|
|
return FAppStyle::Get().GetSlateColor("Colors.Header");
|
|
}
|
|
|
|
return FAppStyle::Get().GetSlateColor("Colors.Panel");
|
|
}
|
|
|
|
void SMaterialParametersOverviewTreeItem::RefreshOnRowChange(const FAssetData& AssetData, TSharedPtr<SMaterialParametersOverviewTree> InTree)
|
|
{
|
|
if (InTree.IsValid())
|
|
{
|
|
InTree->CreateGroupsWidget();
|
|
}
|
|
}
|
|
|
|
void SMaterialParametersOverviewTreeItem::Construct(const FArguments& InArgs, const TSharedRef<STableViewBase>& InOwnerTableView)
|
|
{
|
|
StackParameterData = InArgs._StackParameterData;
|
|
MaterialEditorInstance = InArgs._MaterialEditorInstance;
|
|
Tree = InArgs._InTree;
|
|
|
|
TSharedRef<SWidget> LeftSideWidget = SNullWidget::NullWidget;
|
|
TSharedRef<SWidget> RightSideWidget = SNullWidget::NullWidget;
|
|
FText NameOverride;
|
|
TSharedRef<SVerticalBox> WrapperWidget = SNew(SVerticalBox);
|
|
|
|
// GROUP --------------------------------------------------
|
|
if (StackParameterData->StackDataType == EStackDataType::Group)
|
|
{
|
|
NameOverride = FText::FromName(StackParameterData->Group.GroupName);
|
|
LeftSideWidget = SNew(STextBlock)
|
|
.TransformPolicy(ETextTransformPolicy::ToUpper)
|
|
.Text(NameOverride)
|
|
.Font(FAppStyle::Get().GetFontStyle("PropertyWindow.BoldFont"))
|
|
.TextStyle(FAppStyle::Get(), "DetailsView.CategoryTextStyle");
|
|
}
|
|
// END GROUP
|
|
|
|
// PROPERTY ----------------------------------------------
|
|
bool bisPaddedProperty = false;
|
|
if (StackParameterData->StackDataType == EStackDataType::Property)
|
|
{
|
|
UDEditorStaticComponentMaskParameterValue* CompMaskParam = Cast<UDEditorStaticComponentMaskParameterValue>(StackParameterData->Parameter);
|
|
UDEditorVectorParameterValue* VectorParam = Cast<UDEditorVectorParameterValue>(StackParameterData->Parameter);
|
|
UDEditorScalarParameterValue* ScalarParam = Cast<UDEditorScalarParameterValue>(StackParameterData->Parameter);
|
|
UDEditorTextureParameterValue* TextureParam = Cast<UDEditorTextureParameterValue>(StackParameterData->Parameter);
|
|
|
|
TAttribute<bool> IsParamEnabled = TAttribute<bool>::Create(TAttribute<bool>::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, StackParameterData->Parameter));
|
|
NameOverride = FText::FromName(StackParameterData->Parameter->ParameterInfo.Name);
|
|
|
|
IDetailTreeNode& Node = *StackParameterData->ParameterNode;
|
|
TSharedPtr<IDetailPropertyRow> GeneratedRow = StaticCastSharedPtr<IDetailPropertyRow>(Node.GetRow());
|
|
IDetailPropertyRow& Row = *GeneratedRow.Get();
|
|
Row.DisplayName(NameOverride);
|
|
|
|
if (VectorParam && VectorParam->bIsUsedAsChannelMask)
|
|
{
|
|
FOnGetPropertyComboBoxStrings GetMaskStrings = FOnGetPropertyComboBoxStrings::CreateStatic(&FMaterialPropertyHelpers::GetVectorChannelMaskComboBoxStrings);
|
|
FOnGetPropertyComboBoxValue GetMaskValue = FOnGetPropertyComboBoxValue::CreateStatic(&FMaterialPropertyHelpers::GetVectorChannelMaskValue, StackParameterData->Parameter);
|
|
FOnPropertyComboBoxValueSelected SetMaskValue = FOnPropertyComboBoxValueSelected::CreateStatic(&FMaterialPropertyHelpers::SetVectorChannelMaskValue, StackParameterData->ParameterNode->CreatePropertyHandle(), StackParameterData->Parameter, (UObject*)MaterialEditorInstance);
|
|
|
|
FDetailWidgetRow& CustomWidget = Row.CustomWidget();
|
|
CustomWidget
|
|
.FilterString(NameOverride)
|
|
.NameContent()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(NameOverride)
|
|
.ToolTipText(FMaterialPropertyHelpers::GetParameterExpressionDescription(StackParameterData->Parameter, MaterialEditorInstance))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
.ValueContent()
|
|
.MaxDesiredWidth(200.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
PropertyCustomizationHelpers::MakePropertyComboBox(StackParameterData->ParameterNode->CreatePropertyHandle(), GetMaskStrings, GetMaskValue, SetMaskValue)
|
|
]
|
|
]
|
|
];
|
|
}
|
|
else if (ScalarParam && ScalarParam->AtlasData.bIsUsedAsAtlasPosition)
|
|
{
|
|
const FText ParameterName = FText::FromName(StackParameterData->Parameter->ParameterInfo.Name);
|
|
|
|
FDetailWidgetRow& CustomWidget = Row.CustomWidget();
|
|
CustomWidget
|
|
.FilterString(ParameterName)
|
|
.NameContent()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(ParameterName)
|
|
.ToolTipText(FMaterialPropertyHelpers::GetParameterExpressionDescription(StackParameterData->Parameter, MaterialEditorInstance))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
.ValueContent()
|
|
.HAlign(HAlign_Fill)
|
|
.MaxDesiredWidth(400.0f)
|
|
[
|
|
SNew(SObjectPropertyEntryBox)
|
|
.ObjectPath(this, &SMaterialParametersOverviewTreeItem::GetCurvePath, ScalarParam)
|
|
.AllowedClass(UCurveLinearColor::StaticClass())
|
|
.NewAssetFactories(TArray<UFactory*>())
|
|
.DisplayThumbnail(true)
|
|
.ThumbnailPool(Tree.Pin()->GetTreeThumbnailPool())
|
|
.OnShouldFilterAsset(FOnShouldFilterAsset::CreateStatic(&FMaterialPropertyHelpers::OnShouldFilterCurveAsset, ScalarParam->AtlasData.Atlas))
|
|
.OnShouldSetAsset(FOnShouldSetAsset::CreateStatic(&FMaterialPropertyHelpers::OnShouldSetCurveAsset, ScalarParam->AtlasData.Atlas))
|
|
.OnObjectChanged(FOnSetObject::CreateStatic(&FMaterialPropertyHelpers::SetPositionFromCurveAsset, ScalarParam->AtlasData.Atlas, ScalarParam, StackParameterData->ParameterHandle, (UObject*)MaterialEditorInstance))
|
|
.DisplayCompactSize(true)
|
|
];
|
|
|
|
}
|
|
else if (TextureParam)
|
|
{
|
|
UMaterial *Material = MaterialEditorInstance->PreviewMaterial;
|
|
if (Material != nullptr)
|
|
{
|
|
UMaterialExpressionTextureSampleParameter* Expression = Material->FindExpressionByGUID<UMaterialExpressionTextureSampleParameter>(TextureParam->ExpressionId);
|
|
if (Expression != nullptr)
|
|
{
|
|
TWeakObjectPtr<UMaterialExpressionTextureSampleParameter> SamplerExpression = Expression;
|
|
TSharedPtr<SWidget> NameWidget;
|
|
TSharedPtr<SWidget> ValueWidget;
|
|
FDetailWidgetRow DefaultRow;
|
|
Row.GetDefaultWidgets(NameWidget, ValueWidget, DefaultRow);
|
|
|
|
FDetailWidgetRow &DetailWidgetRow = Row.CustomWidget();
|
|
TSharedPtr<SVerticalBox> NameVerticalBox;
|
|
DetailWidgetRow.NameContent()
|
|
[
|
|
SAssignNew(NameVerticalBox, SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(StackParameterData->Parameter->ParameterInfo.Name))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
|
|
DetailWidgetRow.ValueContent()
|
|
.MinDesiredWidth(DefaultRow.ValueWidget.MinWidth)
|
|
.MaxDesiredWidth(DefaultRow.ValueWidget.MaxWidth)
|
|
[
|
|
SNew(SObjectPropertyEntryBox)
|
|
.PropertyHandle(StackParameterData->ParameterNode->CreatePropertyHandle())
|
|
.AllowedClass(UTexture::StaticClass())
|
|
.ThumbnailPool(Tree.Pin()->GetTreeThumbnailPool())
|
|
.OnShouldFilterAsset_Lambda([SamplerExpression](const FAssetData& AssetData)
|
|
{
|
|
if (SamplerExpression.Get())
|
|
{
|
|
bool VirtualTextured = false;
|
|
AssetData.GetTagValue<bool>("VirtualTextureStreaming", VirtualTextured);
|
|
|
|
bool ExpressionIsVirtualTextured = IsVirtualSamplerType(SamplerExpression->SamplerType);
|
|
|
|
return VirtualTextured != ExpressionIsVirtualTextured;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
})
|
|
];
|
|
|
|
static const FName Red("R");
|
|
static const FName Green("G");
|
|
static const FName Blue("B");
|
|
static const FName Alpha("A");
|
|
|
|
if (!TextureParam->ChannelNames.R.IsEmpty())
|
|
{
|
|
NameVerticalBox->AddSlot()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.Padding(20.0, 2.0, 4.0, 2.0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(Red))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.BoldFont")))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(4.0, 2.0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(TextureParam->ChannelNames.R)
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
}
|
|
if (!TextureParam->ChannelNames.G.IsEmpty())
|
|
{
|
|
NameVerticalBox->AddSlot()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(20.0, 2.0, 4.0, 2.0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(Green))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.BoldFont")))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(4.0, 2.0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(TextureParam->ChannelNames.G)
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
}
|
|
if (!TextureParam->ChannelNames.B.IsEmpty())
|
|
{
|
|
NameVerticalBox->AddSlot()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(20.0, 2.0, 4.0, 2.0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(Blue))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.BoldFont")))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(4.0, 2.0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(TextureParam->ChannelNames.B)
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
}
|
|
if (!TextureParam->ChannelNames.A.IsEmpty())
|
|
{
|
|
NameVerticalBox->AddSlot()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(20.0, 2.0, 4.0, 2.0)
|
|
.AutoWidth()
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(FText::FromName(Alpha))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.BoldFont")))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(4.0, 2.0)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(TextureParam->ChannelNames.A)
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
else if (CompMaskParam)
|
|
{
|
|
TSharedPtr<IPropertyHandle> RMaskProperty = StackParameterData->ParameterNode->CreatePropertyHandle()->GetChildHandle("R");
|
|
TSharedPtr<IPropertyHandle> GMaskProperty = StackParameterData->ParameterNode->CreatePropertyHandle()->GetChildHandle("G");
|
|
TSharedPtr<IPropertyHandle> BMaskProperty = StackParameterData->ParameterNode->CreatePropertyHandle()->GetChildHandle("B");
|
|
TSharedPtr<IPropertyHandle> AMaskProperty = StackParameterData->ParameterNode->CreatePropertyHandle()->GetChildHandle("A");
|
|
FDetailWidgetRow& CustomWidget = Row.CustomWidget();
|
|
CustomWidget
|
|
.FilterString(NameOverride)
|
|
.NameContent()
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(NameOverride)
|
|
.ToolTipText(FMaterialPropertyHelpers::GetParameterExpressionDescription(StackParameterData->Parameter, MaterialEditorInstance))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
]
|
|
.ValueContent()
|
|
.MaxDesiredWidth(200.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
RMaskProperty->CreatePropertyNameWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
RMaskProperty->CreatePropertyValueWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(FMargin(10.0f, 0.0f, 0.0f, 0.0f))
|
|
.AutoWidth()
|
|
[
|
|
GMaskProperty->CreatePropertyNameWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
GMaskProperty->CreatePropertyValueWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(FMargin(10.0f, 0.0f, 0.0f, 0.0f))
|
|
.AutoWidth()
|
|
[
|
|
BMaskProperty->CreatePropertyNameWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
BMaskProperty->CreatePropertyValueWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.Padding(FMargin(10.0f, 0.0f, 0.0f, 0.0f))
|
|
.AutoWidth()
|
|
[
|
|
AMaskProperty->CreatePropertyNameWidget()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Left)
|
|
.AutoWidth()
|
|
[
|
|
AMaskProperty->CreatePropertyValueWidget()
|
|
]
|
|
]
|
|
];
|
|
}
|
|
else
|
|
{
|
|
if (TSharedPtr<IPropertyHandle> PropertyHandle = StackParameterData->ParameterNode->CreatePropertyHandle())
|
|
{
|
|
PropertyHandle->MarkResetToDefaultCustomized(true);
|
|
}
|
|
|
|
FDetailWidgetDecl* CustomNameWidget = Row.CustomNameWidget();
|
|
if (CustomNameWidget)
|
|
{
|
|
(*CustomNameWidget)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+SHorizontalBox::Slot()
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(NameOverride)
|
|
.ToolTipText(FMaterialPropertyHelpers::GetParameterExpressionDescription(StackParameterData->Parameter, MaterialEditorInstance))
|
|
.Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont")))
|
|
]
|
|
];
|
|
}
|
|
else
|
|
{
|
|
Row.ToolTip(FMaterialPropertyHelpers::GetParameterExpressionDescription(StackParameterData->Parameter, MaterialEditorInstance));
|
|
}
|
|
|
|
bisPaddedProperty = true;
|
|
}
|
|
|
|
FNodeWidgets NodeWidgets = Node.CreateNodeWidgets();
|
|
LeftSideWidget = NodeWidgets.NameWidget.ToSharedRef();
|
|
RightSideWidget = NodeWidgets.ValueWidget.ToSharedRef();
|
|
}
|
|
// END PROPERTY
|
|
|
|
// PROPERTY CHILD ----------------------------------------
|
|
if (StackParameterData->StackDataType == EStackDataType::PropertyChild)
|
|
{
|
|
FNodeWidgets NodeWidgets = StackParameterData->ParameterNode->CreateNodeWidgets();
|
|
LeftSideWidget = NodeWidgets.NameWidget.ToSharedRef();
|
|
RightSideWidget = NodeWidgets.ValueWidget.ToSharedRef();
|
|
}
|
|
// END PROPERTY CHILD
|
|
|
|
// FINAL WRAPPER
|
|
|
|
{
|
|
FDetailColumnSizeData& ColumnSizeData = InArgs._InTree->GetColumnSizeData();
|
|
|
|
float ValuePadding = bisPaddedProperty ? 20.0f : 0.0f;
|
|
WrapperWidget->AddSlot()
|
|
.AutoHeight()
|
|
[
|
|
SNew(SBorder)
|
|
.BorderImage(FAppStyle::Get().GetBrush("DetailsView.GridLine"))
|
|
.Padding(FMargin(0, 0, 0, 1))
|
|
[
|
|
SNew(SBorder)
|
|
.Padding(3.0f)
|
|
.BorderImage(this, &SMaterialParametersOverviewTreeItem::GetBorderImage)
|
|
.BorderBackgroundColor(this, &SMaterialParametersOverviewTreeItem::GetOuterBackgroundColor, StackParameterData)
|
|
[
|
|
SNew(SSplitter)
|
|
.Style(FAppStyle::Get(), "DetailsView.Splitter")
|
|
.PhysicalSplitterHandleSize(1.0f)
|
|
.HitDetectionSplitterHandleSize(5.0f)
|
|
+ SSplitter::Slot()
|
|
.Value(ColumnSizeData.GetNameColumnWidth())
|
|
.OnSlotResized(ColumnSizeData.GetOnNameColumnResized())
|
|
.Value(0.25f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.AutoWidth()
|
|
.VAlign(VAlign_Center)
|
|
.Padding(FMargin(3.0f))
|
|
[
|
|
SNew(SExpanderArrow, SharedThis(this))
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(2.0f))
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
LeftSideWidget
|
|
]
|
|
]
|
|
+ SSplitter::Slot()
|
|
.Value(ColumnSizeData.GetValueColumnWidth())
|
|
.OnSlotResized(ColumnSizeData.GetOnValueColumnResized())
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.Padding(FMargin(5.0f, 2.0f, 5.0, 2.0f))
|
|
.HAlign(HAlign_Left)
|
|
.VAlign(VAlign_Center)
|
|
[
|
|
RightSideWidget
|
|
]
|
|
]
|
|
]
|
|
]
|
|
];
|
|
}
|
|
|
|
this->ChildSlot
|
|
[
|
|
WrapperWidget
|
|
];
|
|
|
|
STableRow< TSharedPtr<FSortedParamData> >::ConstructInternal(
|
|
STableRow::FArguments()
|
|
.Style(FAppStyle::Get(), "DetailsView.TreeView.TableRow")
|
|
.ShowSelection(false),
|
|
InOwnerTableView
|
|
);
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::Construct(const FArguments& InArgs)
|
|
{
|
|
bHasAnyParameters = false;
|
|
MaterialEditorInstance = InArgs._InMaterialEditorInstance;
|
|
Owner = InArgs._InOwner;
|
|
SelectMaterialNodeDelegate = InArgs._SelectMaterialNode;
|
|
CreateGroupsWidget();
|
|
|
|
STreeView<TSharedPtr<FSortedParamData>>::Construct(
|
|
STreeView::FArguments()
|
|
.TreeItemsSource(&SortedParameters)
|
|
.SelectionMode(ESelectionMode::None)
|
|
.OnGenerateRow(this, &SMaterialParametersOverviewTree::OnGenerateRowMaterialLayersFunctionsTreeView)
|
|
.OnGetChildren(this, &SMaterialParametersOverviewTree::OnGetChildrenMaterialLayersFunctionsTreeView)
|
|
.OnExpansionChanged(this, &SMaterialParametersOverviewTree::OnExpansionChanged)
|
|
.ExternalScrollbar(InArgs._InScrollbar)
|
|
);
|
|
}
|
|
|
|
TSharedRef< ITableRow > SMaterialParametersOverviewTree::OnGenerateRowMaterialLayersFunctionsTreeView(TSharedPtr<FSortedParamData> Item, const TSharedRef< STableViewBase >& OwnerTable)
|
|
{
|
|
TSharedRef< SMaterialParametersOverviewTreeItem > ReturnRow = SNew(SMaterialParametersOverviewTreeItem, OwnerTable)
|
|
.StackParameterData(Item)
|
|
.MaterialEditorInstance(MaterialEditorInstance)
|
|
.InTree(SharedThis(this));
|
|
return ReturnRow;
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::OnGetChildrenMaterialLayersFunctionsTreeView(TSharedPtr<FSortedParamData> InParent, TArray< TSharedPtr<FSortedParamData> >& OutChildren)
|
|
{
|
|
OutChildren = InParent->Children;
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::OnExpansionChanged(TSharedPtr<FSortedParamData> Item, bool bIsExpanded)
|
|
{
|
|
bool* ExpansionValue = MaterialEditorInstance->OriginalMaterial->ParameterOverviewExpansion.Find(Item->NodeKey);
|
|
if (ExpansionValue == nullptr)
|
|
{
|
|
MaterialEditorInstance->OriginalMaterial->ParameterOverviewExpansion.Add(Item->NodeKey, bIsExpanded);
|
|
}
|
|
else if (*ExpansionValue != bIsExpanded)
|
|
{
|
|
MaterialEditorInstance->OriginalMaterial->ParameterOverviewExpansion.Emplace(Item->NodeKey, bIsExpanded);
|
|
}
|
|
// Expand any children that are also expanded
|
|
for (auto Child : Item->Children)
|
|
{
|
|
bool* ChildExpansionValue = MaterialEditorInstance->OriginalMaterial->ParameterOverviewExpansion.Find(Child->NodeKey);
|
|
if (ChildExpansionValue != nullptr && *ChildExpansionValue == true)
|
|
{
|
|
SetItemExpansion(Child, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::SetParentsExpansionState()
|
|
{
|
|
for (const auto& Pair : SortedParameters)
|
|
{
|
|
if (Pair->Children.Num())
|
|
{
|
|
bool* bIsExpanded = MaterialEditorInstance->OriginalMaterial->ParameterOverviewExpansion.Find(Pair->NodeKey);
|
|
if (bIsExpanded)
|
|
{
|
|
SetItemExpansion(Pair, *bIsExpanded);
|
|
}
|
|
else
|
|
{
|
|
SetItemExpansion(Pair, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TSharedPtr<class FAssetThumbnailPool> SMaterialParametersOverviewTree::GetTreeThumbnailPool()
|
|
{
|
|
return UThumbnailManager::Get().GetSharedThumbnailPool();
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::CreateGroupsWidget()
|
|
{
|
|
check(MaterialEditorInstance);
|
|
UnsortedParameters.Reset();
|
|
SortedParameters.Reset();
|
|
|
|
const TArray<TSharedRef<IDetailTreeNode>> TestData = GetOwner().Pin()->GetGenerator()->GetRootTreeNodes();
|
|
if (TestData.Num() == 0)
|
|
{
|
|
return;
|
|
}
|
|
TSharedPtr<IDetailTreeNode> Category = TestData[0];
|
|
TSharedPtr<IDetailTreeNode> ParameterGroups;
|
|
TArray<TSharedRef<IDetailTreeNode>> Children;
|
|
Category->GetChildren(Children);
|
|
|
|
for (int32 ChildIdx = 0; ChildIdx < Children.Num(); ChildIdx++)
|
|
{
|
|
TSharedPtr<IPropertyHandle> PropertyHandle = Children[ChildIdx]->CreatePropertyHandle();
|
|
if (PropertyHandle.IsValid() && PropertyHandle->GetProperty() && PropertyHandle->GetProperty()->GetName() == "ParameterGroups")
|
|
{
|
|
ParameterGroups = Children[ChildIdx];
|
|
break;
|
|
}
|
|
}
|
|
|
|
Children.Empty();
|
|
// the order should correspond to UnsortedParameters exactly
|
|
TArray<TSharedPtr<IPropertyHandle>> DeferredSearches;
|
|
|
|
if (ParameterGroups.IsValid())
|
|
{
|
|
ParameterGroups->GetChildren(Children);
|
|
for (int32 GroupIdx = 0; GroupIdx < Children.Num(); ++GroupIdx)
|
|
{
|
|
TArray<void*> GroupPtrs;
|
|
TSharedPtr<IPropertyHandle> ChildHandle = Children[GroupIdx]->CreatePropertyHandle();
|
|
ChildHandle->AccessRawData(GroupPtrs);
|
|
auto GroupIt = GroupPtrs.CreateConstIterator();
|
|
const FEditorParameterGroup* ParameterGroupPtr = reinterpret_cast<FEditorParameterGroup*>(*GroupIt);
|
|
if (!ParameterGroupPtr)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
const FEditorParameterGroup& ParameterGroup = *ParameterGroupPtr;
|
|
if (ParameterGroup.GroupName == FMaterialPropertyHelpers::LayerParamName)
|
|
{
|
|
// Don't create or show the material layer parameter info in this UI
|
|
continue;
|
|
}
|
|
|
|
for (int32 ParamIdx = 0; ParamIdx < ParameterGroup.Parameters.Num(); ParamIdx++)
|
|
{
|
|
UDEditorParameterValue* Parameter = ParameterGroup.Parameters[ParamIdx];
|
|
if (Parameter->ParameterInfo.Association == EMaterialParameterAssociation::GlobalParameter)
|
|
{
|
|
bHasAnyParameters = true;
|
|
TSharedPtr<IPropertyHandle> ParametersArrayProperty = ChildHandle->GetChildHandle("Parameters");
|
|
TSharedPtr<IPropertyHandle> ParameterProperty = ParametersArrayProperty->GetChildHandle(ParamIdx);
|
|
TSharedPtr<IPropertyHandle> ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue");
|
|
|
|
|
|
FUnsortedParamData NonLayerProperty;
|
|
UDEditorScalarParameterValue* ScalarParam = Cast<UDEditorScalarParameterValue>(Parameter);
|
|
UDEditorVectorParameterValue* VectorParam = Cast<UDEditorVectorParameterValue>(Parameter);
|
|
|
|
if (ScalarParam && ScalarParam->SliderMax > ScalarParam->SliderMin)
|
|
{
|
|
ParameterValueProperty->SetInstanceMetaData("UIMin", FString::Printf(TEXT("%f"), ScalarParam->SliderMin));
|
|
ParameterValueProperty->SetInstanceMetaData("UIMax", FString::Printf(TEXT("%f"), ScalarParam->SliderMax));
|
|
}
|
|
|
|
if (VectorParam)
|
|
{
|
|
static const FName Red("R");
|
|
static const FName Green("G");
|
|
static const FName Blue("B");
|
|
static const FName Alpha("A");
|
|
if (!VectorParam->ChannelNames.R.IsEmpty())
|
|
{
|
|
ParameterProperty->GetChildHandle(Red)->SetPropertyDisplayName(VectorParam->ChannelNames.R);
|
|
}
|
|
if (!VectorParam->ChannelNames.G.IsEmpty())
|
|
{
|
|
ParameterProperty->GetChildHandle(Green)->SetPropertyDisplayName(VectorParam->ChannelNames.G);
|
|
}
|
|
if (!VectorParam->ChannelNames.B.IsEmpty())
|
|
{
|
|
ParameterProperty->GetChildHandle(Blue)->SetPropertyDisplayName(VectorParam->ChannelNames.B);
|
|
}
|
|
if (!VectorParam->ChannelNames.A.IsEmpty())
|
|
{
|
|
ParameterProperty->GetChildHandle(Alpha)->SetPropertyDisplayName(VectorParam->ChannelNames.A);
|
|
}
|
|
}
|
|
|
|
NonLayerProperty.Parameter = Parameter;
|
|
NonLayerProperty.ParameterGroup = ParameterGroup;
|
|
NonLayerProperty.UnsortedName = Parameter->ParameterInfo.Name;
|
|
|
|
DeferredSearches.Add(ParameterValueProperty);
|
|
UnsortedParameters.Add(NonLayerProperty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
checkf(UnsortedParameters.Num() == DeferredSearches.Num(), TEXT("Internal inconsistency: number of node searches does not match the number of properties"));
|
|
TArray<TSharedPtr<IDetailTreeNode>> DeferredResults = GetOwner().Pin()->GetGenerator()->FindTreeNodes(DeferredSearches);
|
|
checkf(UnsortedParameters.Num() == DeferredResults.Num(), TEXT("Internal inconsistency: number of node search results does not match the number of properties"));
|
|
|
|
for (int Idx = 0, NumUnsorted = UnsortedParameters.Num(); Idx < NumUnsorted; ++Idx)
|
|
{
|
|
FUnsortedParamData& NonLayerProperty = UnsortedParameters[Idx];
|
|
NonLayerProperty.ParameterNode = DeferredResults[Idx];
|
|
NonLayerProperty.ParameterHandle = NonLayerProperty.ParameterNode->CreatePropertyHandle();
|
|
}
|
|
|
|
ShowSubParameters();
|
|
RequestTreeRefresh();
|
|
SetParentsExpansionState();
|
|
}
|
|
|
|
|
|
bool SMaterialParametersOverviewTree::Private_OnItemDoubleClicked(TSharedPtr<FSortedParamData> TheItem)
|
|
{
|
|
if (STreeView<TSharedPtr<FSortedParamData>>::Private_OnItemDoubleClicked(TheItem))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!SelectMaterialNodeDelegate.IsBound() || !TheItem.IsValid() || !TheItem->Parameter ||
|
|
!TheItem->Parameter->ExpressionId.IsValid())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SelectMaterialNodeDelegate.Execute(TheItem->Parameter->ExpressionId);
|
|
|
|
return true;
|
|
}
|
|
|
|
void SMaterialParametersOverviewTree::ShowSubParameters()
|
|
{
|
|
for (FUnsortedParamData Property : UnsortedParameters)
|
|
{
|
|
UDEditorParameterValue* Parameter = Property.Parameter;
|
|
{
|
|
TSharedPtr<FSortedParamData> GroupProperty(new FSortedParamData());
|
|
GroupProperty->StackDataType = EStackDataType::Group;
|
|
GroupProperty->ParameterInfo.Index = Parameter->ParameterInfo.Index;
|
|
GroupProperty->ParameterInfo.Association = Parameter->ParameterInfo.Association;
|
|
GroupProperty->Group = Property.ParameterGroup;
|
|
GroupProperty->NodeKey = FString::FromInt(GroupProperty->ParameterInfo.Index) + FString::FromInt(GroupProperty->ParameterInfo.Association) + Property.ParameterGroup.GroupName.ToString();
|
|
|
|
bool bAddNewGroup = true;
|
|
for (TSharedPtr<struct FSortedParamData> GroupChild : SortedParameters)
|
|
{
|
|
if (GroupChild->NodeKey == GroupProperty->NodeKey)
|
|
{
|
|
bAddNewGroup = false;
|
|
}
|
|
}
|
|
if (bAddNewGroup)
|
|
{
|
|
SortedParameters.Add(GroupProperty);
|
|
}
|
|
|
|
TSharedPtr<FSortedParamData> ChildProperty(new FSortedParamData());
|
|
ChildProperty->StackDataType = EStackDataType::Property;
|
|
ChildProperty->Parameter = Parameter;
|
|
ChildProperty->ParameterInfo.Index = Parameter->ParameterInfo.Index;
|
|
ChildProperty->ParameterInfo.Association = Parameter->ParameterInfo.Association;
|
|
ChildProperty->ParameterNode = Property.ParameterNode;
|
|
ChildProperty->PropertyName = Property.UnsortedName;
|
|
ChildProperty->NodeKey = FString::FromInt(ChildProperty->ParameterInfo.Index) + FString::FromInt(ChildProperty->ParameterInfo.Association) + Property.ParameterGroup.GroupName.ToString() + Property.UnsortedName.ToString();
|
|
|
|
|
|
UDEditorStaticComponentMaskParameterValue* CompMaskParam = Cast<UDEditorStaticComponentMaskParameterValue>(Parameter);
|
|
// No children for masks
|
|
if (!CompMaskParam)
|
|
{
|
|
TArray<TSharedRef<IDetailTreeNode>> ParamChildren;
|
|
Property.ParameterNode->GetChildren(ParamChildren);
|
|
for (int32 ParamChildIdx = 0; ParamChildIdx < ParamChildren.Num(); ParamChildIdx++)
|
|
{
|
|
TSharedPtr<FSortedParamData> ParamChildProperty(new FSortedParamData());
|
|
ParamChildProperty->StackDataType = EStackDataType::PropertyChild;
|
|
ParamChildProperty->ParameterNode = ParamChildren[ParamChildIdx];
|
|
ParamChildProperty->ParameterHandle = ParamChildProperty->ParameterNode->CreatePropertyHandle();
|
|
ParamChildProperty->ParameterInfo.Index = Parameter->ParameterInfo.Index;
|
|
ParamChildProperty->ParameterInfo.Association = Parameter->ParameterInfo.Association;
|
|
ParamChildProperty->Parameter = ChildProperty->Parameter;
|
|
ChildProperty->Children.Add(ParamChildProperty);
|
|
}
|
|
}
|
|
|
|
UDEditorRuntimeVirtualTextureParameterValue* VTParameter = Cast<UDEditorRuntimeVirtualTextureParameterValue>(Parameter);
|
|
UDEditorSparseVolumeTextureParameterValue* SVTParameter = Cast<UDEditorSparseVolumeTextureParameterValue>(Parameter);
|
|
|
|
// Don't add child property to this group if parameter is of type 'Virtual Texture' or 'Sparse Volume Texture'
|
|
if (!VTParameter && !SVTParameter)
|
|
{
|
|
for (TSharedPtr<struct FSortedParamData> GroupChild : SortedParameters)
|
|
{
|
|
if (GroupChild->Group.GroupName == Property.ParameterGroup.GroupName
|
|
&& GroupChild->ParameterInfo.Association == ChildProperty->ParameterInfo.Association
|
|
&& GroupChild->ParameterInfo.Index == ChildProperty->ParameterInfo.Index)
|
|
{
|
|
GroupChild->Children.Add(ChildProperty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const FSlateBrush* SMaterialParametersOverviewPanel::GetBackgroundImage() const
|
|
{
|
|
return FAppStyle::GetBrush("DetailsView.CategoryTop");
|
|
}
|
|
|
|
int32 SMaterialParametersOverviewPanel::GetPanelIndex() const
|
|
{
|
|
return NestedTree && NestedTree->HasAnyParameters() ? 1 : 0;
|
|
}
|
|
|
|
void SMaterialParametersOverviewPanel::Refresh()
|
|
{
|
|
TSharedPtr<SHorizontalBox> HeaderBox;
|
|
NestedTree->CreateGroupsWidget();
|
|
|
|
FOnClicked OnChildButtonClicked = FOnClicked();
|
|
if (MaterialEditorInstance->OriginalFunction)
|
|
{
|
|
OnChildButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewFunctionInstance, ImplicitConv<UMaterialFunctionInterface*>(MaterialEditorInstance->OriginalFunction), ImplicitConv<UMaterialInterface*>(MaterialEditorInstance->PreviewMaterial), ImplicitConv<UObject*>(MaterialEditorInstance));
|
|
}
|
|
else
|
|
{
|
|
OnChildButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewMaterialInstance, ImplicitConv<UMaterialInterface*>(MaterialEditorInstance->OriginalMaterial), ImplicitConv<UObject*>(MaterialEditorInstance));
|
|
}
|
|
|
|
if (NestedTree->HasAnyParameters())
|
|
{
|
|
this->ChildSlot
|
|
[
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.Padding(0.0f)
|
|
[
|
|
|
|
SNew(SVerticalBox)
|
|
+ SVerticalBox::Slot()
|
|
.AutoHeight()
|
|
[
|
|
SAssignNew(HeaderBox, SHorizontalBox)
|
|
]
|
|
+ SVerticalBox::Slot()
|
|
.Padding(0.0f)
|
|
[
|
|
SNew(SHorizontalBox)
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Fill)
|
|
[
|
|
NestedTree.ToSharedRef()
|
|
]
|
|
+ SHorizontalBox::Slot()
|
|
.HAlign(HAlign_Right)
|
|
.AutoWidth()
|
|
[
|
|
SNew(SBox)
|
|
.WidthOverride(16.0f)
|
|
[
|
|
ExternalScrollbar.ToSharedRef()
|
|
]
|
|
]
|
|
|
|
]
|
|
|
|
]
|
|
];
|
|
|
|
HeaderBox->AddSlot()
|
|
.FillWidth(1.0f)
|
|
[
|
|
SNullWidget::NullWidget
|
|
];
|
|
|
|
if (NestedTree->HasAnyParameters())
|
|
{
|
|
HeaderBox->AddSlot()
|
|
.AutoWidth()
|
|
.Padding(2.0f)
|
|
[
|
|
SNew(SButton)
|
|
.Text(LOCTEXT("SaveChild", "Save Child"))
|
|
.HAlign(HAlign_Center)
|
|
.OnClicked(OnChildButtonClicked)
|
|
.ToolTipText(LOCTEXT("SaveToChildInstance", "Save To Child Instance"))
|
|
];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this->ChildSlot
|
|
[
|
|
SNew(SBox)
|
|
.Padding(10.0f)
|
|
.HAlign(HAlign_Center)
|
|
[
|
|
SNew(STextBlock)
|
|
.Text(LOCTEXT("ConnectMaterialParametersToFillList", "Connect a parameter to see it here."))
|
|
]
|
|
];
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void SMaterialParametersOverviewPanel::Construct(const FArguments& InArgs)
|
|
{
|
|
ExternalScrollbar = SNew(SScrollBar);
|
|
TSharedPtr<IPropertyRowGenerator> InGenerator = InArgs._InGenerator;
|
|
Generator = InGenerator;
|
|
|
|
NestedTree = SNew(SMaterialParametersOverviewTree)
|
|
.InMaterialEditorInstance(InArgs._InMaterialEditorInstance)
|
|
.InOwner(SharedThis(this))
|
|
.InScrollbar(ExternalScrollbar)
|
|
.SelectMaterialNode(InArgs._SelectMaterialNode);
|
|
|
|
MaterialEditorInstance = InArgs._InMaterialEditorInstance;
|
|
Refresh();
|
|
}
|
|
|
|
void SMaterialParametersOverviewPanel::UpdateEditorInstance(UMaterialEditorPreviewParameters* InMaterialEditorInstance)
|
|
{
|
|
NestedTree->MaterialEditorInstance = InMaterialEditorInstance;
|
|
Refresh();
|
|
}
|
|
|
|
|
|
TSharedPtr<class IPropertyRowGenerator> SMaterialParametersOverviewPanel::GetGenerator()
|
|
{
|
|
return Generator.Pin();
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|