// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved. #include "MaterialEditorInstanceDetailCustomization.h" #include "Misc/MessageDialog.h" #include "Misc/Guid.h" #include "UObject/UnrealType.h" #include "Layout/Margin.h" #include "Misc/Attribute.h" #include "Widgets/DeclarativeSyntaxSupport.h" #include "Widgets/SBoxPanel.h" #include "Widgets/Text/STextBlock.h" #include "EditorStyleSet.h" #include "Materials/MaterialInterface.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/MaterialInterface.h" #include "Materials/MaterialInstance.h" #include "Materials/MaterialExpressionParameter.h" #include "Materials/MaterialExpressionTextureSampleParameter.h" #include "Materials/MaterialExpressionFontSampleParameter.h" #include "Materials/MaterialExpressionMaterialAttributeLayers.h" #include "EditorSupportDelegates.h" #include "DetailWidgetRow.h" #include "PropertyHandle.h" #include "IDetailPropertyRow.h" #include "DetailLayoutBuilder.h" #include "IDetailGroup.h" #include "DetailCategoryBuilder.h" #include "PropertyCustomizationHelpers.h" #include "ScopedTransaction.h" #include "Materials/MaterialInstanceConstant.h" #include "MaterialPropertyHelpers.h" #include "Widgets/Input/SButton.h" #include "Widgets/Layout/SBox.h" #include "Factories/MaterialInstanceConstantFactoryNew.h" #include "Modules/ModuleManager.h" #include "AssetToolsModule.h" #include "Materials/MaterialFunctionInterface.h" #include "Materials/MaterialFunction.h" #include "Materials/MaterialFunctionInstance.h" #include "Curves/CurveLinearColor.h" #include "IPropertyUtilities.h" #define LOCTEXT_NAMESPACE "MaterialInstanceEditor" TSharedRef FMaterialInstanceParameterDetails::MakeInstance(UMaterialEditorInstanceConstant* MaterialInstance, FGetShowHiddenParameters InShowHiddenDelegate) { return MakeShareable(new FMaterialInstanceParameterDetails(MaterialInstance, InShowHiddenDelegate)); } FMaterialInstanceParameterDetails::FMaterialInstanceParameterDetails(UMaterialEditorInstanceConstant* MaterialInstance, FGetShowHiddenParameters InShowHiddenDelegate) : MaterialEditorInstance(MaterialInstance) , ShowHiddenDelegate(InShowHiddenDelegate) { } TOptional FMaterialInstanceParameterDetails::OnGetValue(TSharedRef PropertyHandle) { float Value = 0.0f; if (PropertyHandle->GetValue(Value) == FPropertyAccess::Success) { return TOptional(Value); } // Value couldn't be accessed. Return an unset value return TOptional(); } void FMaterialInstanceParameterDetails::OnValueCommitted(float NewValue, ETextCommit::Type CommitType, TSharedRef PropertyHandle) { // Try setting as float, if that fails then set as int ensure(PropertyHandle->SetValue(NewValue) == FPropertyAccess::Success); } FString FMaterialInstanceParameterDetails::GetFunctionParentPath() const { FString PathString; if (MaterialEditorInstance->SourceFunction) { PathString = MaterialEditorInstance->SourceFunction->Parent->GetPathName(); } return PathString; } void FMaterialInstanceParameterDetails::CustomizeDetails(IDetailLayoutBuilder& DetailLayout) { PropertyUtilities = DetailLayout.GetPropertyUtilities(); // Create a new category for a custom layout for the MIC parameters at the very top FName GroupsCategoryName = TEXT("ParameterGroups"); IDetailCategoryBuilder& GroupsCategory = DetailLayout.EditCategory(GroupsCategoryName, LOCTEXT("MICParamGroupsTitle", "Parameter Groups")); TSharedRef ParameterGroupsProperty = DetailLayout.GetProperty("ParameterGroups"); CreateGroupsWidget(ParameterGroupsProperty, GroupsCategory); // Create default category for class properties const FName DefaultCategoryName = NAME_None; IDetailCategoryBuilder& DefaultCategory = DetailLayout.EditCategory(DefaultCategoryName); DetailLayout.HideProperty("MaterialLayersParameterValues"); if (MaterialEditorInstance->bIsFunctionPreviewMaterial) { // Customize Parent property so we can check for recursively set parents bool bShowParent = false; if(MaterialEditorInstance->SourceFunction->GetMaterialFunctionUsage() != EMaterialFunctionUsage::Default) { bShowParent = true; } if (bShowParent) { TSharedRef ParentPropertyHandle = DetailLayout.GetProperty("Parent"); IDetailPropertyRow& ParentPropertyRow = DefaultCategory.AddProperty(ParentPropertyHandle); ParentPropertyHandle->MarkResetToDefaultCustomized(); TSharedPtr NameWidget; TSharedPtr ValueWidget; FDetailWidgetRow Row; ParentPropertyRow.GetDefaultWidgets(NameWidget, ValueWidget, Row); ParentPropertyHandle->ClearResetToDefaultCustomized(); const bool bShowChildren = true; ParentPropertyRow.CustomWidget(bShowChildren) .NameContent() .MinDesiredWidth(Row.NameWidget.MinWidth) .MaxDesiredWidth(Row.NameWidget.MaxWidth) [ NameWidget.ToSharedRef() ] .ValueContent() .MinDesiredWidth(Row.ValueWidget.MinWidth) .MaxDesiredWidth(Row.ValueWidget.MaxWidth) [ SNew(SObjectPropertyEntryBox) .ObjectPath(this, &FMaterialInstanceParameterDetails::GetFunctionParentPath) .AllowedClass(UMaterialFunctionInterface::StaticClass()) .ThumbnailPool(DetailLayout.GetThumbnailPool()) .AllowClear(true) .OnObjectChanged(this, &FMaterialInstanceParameterDetails::OnAssetChanged, ParentPropertyHandle) .OnShouldSetAsset(this, &FMaterialInstanceParameterDetails::OnShouldSetAsset) .NewAssetFactories(TArray()) ]; ValueWidget.Reset(); } else { DetailLayout.HideProperty("Parent"); } DetailLayout.HideProperty("PhysMaterial"); DetailLayout.HideProperty("LightmassSettings"); DetailLayout.HideProperty("bUseOldStyleMICEditorGroups"); DetailLayout.HideProperty("ParameterGroups"); DetailLayout.HideProperty("RefractionDepthBias"); DetailLayout.HideProperty("bOverrideSubsurfaceProfile"); DetailLayout.HideProperty("SubsurfaceProfile"); DetailLayout.HideProperty("BasePropertyOverrides"); } else { // Add PhysMaterial property DefaultCategory.AddProperty("PhysMaterial"); // Customize Parent property so we can check for recursively set parents TSharedRef ParentPropertyHandle = DetailLayout.GetProperty("Parent"); IDetailPropertyRow& ParentPropertyRow = DefaultCategory.AddProperty(ParentPropertyHandle); ParentPropertyHandle->MarkResetToDefaultCustomized(); TSharedPtr NameWidget; TSharedPtr ValueWidget; FDetailWidgetRow Row; ParentPropertyRow.GetDefaultWidgets(NameWidget, ValueWidget, Row); ParentPropertyHandle->ClearResetToDefaultCustomized(); const bool bShowChildren = true; ParentPropertyRow.CustomWidget(bShowChildren) .NameContent() .MinDesiredWidth(Row.NameWidget.MinWidth) .MaxDesiredWidth(Row.NameWidget.MaxWidth) [ NameWidget.ToSharedRef() ] .ValueContent() .MinDesiredWidth(Row.ValueWidget.MinWidth) .MaxDesiredWidth(Row.ValueWidget.MaxWidth) [ SNew(SObjectPropertyEntryBox) .PropertyHandle(ParentPropertyHandle) .AllowedClass(UMaterialInterface::StaticClass()) .ThumbnailPool(DetailLayout.GetThumbnailPool()) .AllowClear(true) .OnShouldSetAsset(this, &FMaterialInstanceParameterDetails::OnShouldSetAsset) ]; ValueWidget.Reset(); // Add/hide other properties DetailLayout.HideProperty("LightmassSettings"); CreateLightmassOverrideWidgets(DetailLayout); DetailLayout.HideProperty("bUseOldStyleMICEditorGroups"); DetailLayout.HideProperty("ParameterGroups"); { FIsResetToDefaultVisible IsRefractionDepthBiasPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { float BiasValue; float ParentBiasValue; return MaterialEditorInstance->SourceInstance->GetRefractionSettings(BiasValue) && MaterialEditorInstance->Parent->GetRefractionSettings(ParentBiasValue) && BiasValue != ParentBiasValue; }); FResetToDefaultHandler ResetRefractionDepthBiasPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { MaterialEditorInstance->Parent->GetRefractionSettings(MaterialEditorInstance->RefractionDepthBias); }); FResetToDefaultOverride ResetRefractionDepthBiasPropertyOverride = FResetToDefaultOverride::Create(IsRefractionDepthBiasPropertyResetVisible, ResetRefractionDepthBiasPropertyHandler); IDetailPropertyRow& PropertyRow = DefaultCategory.AddProperty("RefractionDepthBias"); PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::ShouldShowMaterialRefractionSettings))); PropertyRow.OverrideResetToDefault(ResetRefractionDepthBiasPropertyOverride); } { IDetailPropertyRow& PropertyRow = DefaultCategory.AddProperty("bOverrideSubsurfaceProfile"); PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::ShouldShowSubsurfaceProfile))); } { IDetailPropertyRow& PropertyRow = DefaultCategory.AddProperty("SubsurfaceProfile"); PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::ShouldShowSubsurfaceProfile))); } DetailLayout.HideProperty("BasePropertyOverrides"); CreateBasePropertyOverrideWidgets(DetailLayout); } // Add the preview mesh property directly from the material instance FName PreviewingCategoryName = TEXT("Previewing"); IDetailCategoryBuilder& PreviewingCategory = DetailLayout.EditCategory(PreviewingCategoryName, LOCTEXT("MICPreviewingCategoryTitle", "Previewing")); TArray ExternalObjects; ExternalObjects.Add(MaterialEditorInstance->SourceInstance); PreviewingCategory.AddExternalObjectProperty(ExternalObjects, TEXT("PreviewMesh")); DefaultCategory.AddExternalObjectProperty(ExternalObjects, TEXT("AssetUserData"), EPropertyLocation::Advanced); } void FMaterialInstanceParameterDetails::CreateGroupsWidget(TSharedRef ParameterGroupsProperty, IDetailCategoryBuilder& GroupsCategory) { bool bShowSaveButtons = false; check(MaterialEditorInstance); for (int32 GroupIdx = 0; GroupIdx < MaterialEditorInstance->ParameterGroups.Num(); ++GroupIdx) { FEditorParameterGroup& ParameterGroup = MaterialEditorInstance->ParameterGroups[GroupIdx]; if (ParameterGroup.GroupAssociation == EMaterialParameterAssociation::GlobalParameter && ParameterGroup.GroupName != FMaterialPropertyHelpers::LayerParamName) { bShowSaveButtons = true; bool bCreateGroup = false; for (int32 ParamIdx = 0; ParamIdx < ParameterGroup.Parameters.Num(); ++ParamIdx) { UDEditorParameterValue* Parameter = ParameterGroup.Parameters[ParamIdx]; if (MaterialEditorInstance->bShowOnlyOverrides) { if (MaterialEditorInstance->VisibleExpressions.Contains(Parameter->ParameterInfo) && FMaterialPropertyHelpers::IsOverriddenExpression(Parameter)) { bCreateGroup = true; } } else { if (MaterialEditorInstance->VisibleExpressions.Contains(Parameter->ParameterInfo)) { bCreateGroup = true; } } } if (bCreateGroup) { IDetailGroup& DetailGroup = GroupsCategory.AddGroup(ParameterGroup.GroupName, FText::FromName(ParameterGroup.GroupName), false, true); CreateSingleGroupWidget(ParameterGroup, ParameterGroupsProperty->GetChildHandle(GroupIdx), DetailGroup); } } } if (bShowSaveButtons) { FDetailWidgetRow& SaveInstanceRow = GroupsCategory.AddCustomRow(LOCTEXT("SaveInstances", "Save Instances")); FOnClicked OnChildButtonClicked; FOnClicked OnSiblingButtonClicked; UMaterialInterface* LocalSourceInstance = MaterialEditorInstance->SourceInstance; UObject* LocalEditorInstance = MaterialEditorInstance; if (!MaterialEditorInstance->bIsFunctionPreviewMaterial) { OnChildButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewMaterialInstance, LocalSourceInstance, LocalEditorInstance); OnSiblingButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewMaterialInstance, MaterialEditorInstance->SourceInstance->Parent, LocalEditorInstance); } else { OnChildButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewFunctionInstance, ImplicitConv(MaterialEditorInstance->SourceFunction), LocalSourceInstance, LocalEditorInstance); OnSiblingButtonClicked = FOnClicked::CreateStatic(&FMaterialPropertyHelpers::OnClickedSaveNewFunctionInstance, ImplicitConv(MaterialEditorInstance->SourceFunction->Parent), LocalSourceInstance, LocalEditorInstance); } SaveInstanceRow.ValueContent() .HAlign(HAlign_Fill) [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .FillWidth(1.0f) [ SNullWidget::NullWidget ] + SHorizontalBox::Slot() .AutoWidth() .Padding(2.0f) [ SNew(SButton) .ButtonStyle(FEditorStyle::Get(), "FlatButton.Dark") .HAlign(HAlign_Center) .OnClicked(OnSiblingButtonClicked) .ToolTipText(LOCTEXT("SaveToSiblingInstance", "Save To Sibling Instance")) .Content() [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.10")) .TextStyle(FEditorStyle::Get(), "NormalText.Important") .Text(FText::FromString(FString(TEXT("\xf0c7 \xf178"))) /*fa-filter*/) ] + SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .TextStyle(FEditorStyle::Get(), "NormalText.Important") .Text(FText::FromString(FString(TEXT(" Save Sibling"))) /*fa-filter*/) ] ] ] + SHorizontalBox::Slot() .AutoWidth() .Padding(2.0f) [ SNew(SButton) .ButtonStyle(FEditorStyle::Get(), "FlatButton.Dark") .HAlign(HAlign_Center) .OnClicked(OnChildButtonClicked) .ToolTipText(LOCTEXT("SaveToChildInstance", "Save To Child Instance")) .Content() [ SNew(SHorizontalBox) + SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .Font(FEditorStyle::Get().GetFontStyle("FontAwesome.10")) .TextStyle(FEditorStyle::Get(), "NormalText.Important") .Text(FText::FromString(FString(TEXT("\xf0c7 \xf149"))) /*fa-filter*/) ] + SHorizontalBox::Slot() .AutoWidth() [ SNew(STextBlock) .TextStyle(FEditorStyle::Get(), "NormalText.Important") .Text(FText::FromString(FString(TEXT(" Save Child"))) /*fa-filter*/) ] ] ] ]; } } void FMaterialInstanceParameterDetails::CreateSingleGroupWidget(FEditorParameterGroup& ParameterGroup, TSharedPtr ParameterGroupProperty, IDetailGroup& DetailGroup ) { TSharedPtr ParametersArrayProperty = ParameterGroupProperty->GetChildHandle("Parameters"); // Create a custom widget for each parameter in the group for (int32 ParamIdx = 0; ParamIdx < ParameterGroup.Parameters.Num(); ++ParamIdx) { TSharedPtr ParameterProperty = ParametersArrayProperty->GetChildHandle(ParamIdx); UDEditorParameterValue* Parameter = ParameterGroup.Parameters[ParamIdx]; UDEditorFontParameterValue* FontParam = Cast(Parameter); UDEditorMaterialLayersParameterValue* LayersParam = Cast(Parameter); UDEditorScalarParameterValue* ScalarParam = Cast(Parameter); UDEditorStaticComponentMaskParameterValue* CompMaskParam = Cast(Parameter); UDEditorStaticSwitchParameterValue* SwitchParam = Cast(Parameter); UDEditorTextureParameterValue* TextureParam = Cast(Parameter); UDEditorVectorParameterValue* VectorParam = Cast(Parameter); if (Parameter->ParameterInfo.Association == EMaterialParameterAssociation::GlobalParameter) { if (VectorParam && VectorParam->bIsUsedAsChannelMask) { CreateVectorChannelMaskParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } if (ScalarParam && ScalarParam->AtlasData.bIsUsedAsAtlasPosition) { CreateScalarAtlasPositionParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } else if (ScalarParam || SwitchParam || TextureParam || VectorParam || FontParam) { if (ScalarParam && ScalarParam->SliderMax > ScalarParam->SliderMin) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); ParameterValueProperty->SetInstanceMetaData("UIMin", FString::Printf(TEXT("%f"), ScalarParam->SliderMin)); ParameterValueProperty->SetInstanceMetaData("UIMax", FString::Printf(TEXT("%f"), ScalarParam->SliderMax)); } CreateParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } else if (LayersParam) { } else if (CompMaskParam) { CreateMaskParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } else { // Unsupported parameter type check(false); } } } } void FMaterialInstanceParameterDetails::CreateParameterValueWidget(UDEditorParameterValue* Parameter, TSharedPtr ParameterProperty, IDetailGroup& DetailGroup) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); if (ParameterValueProperty->IsValidHandle()) { TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, Parameter)); IDetailPropertyRow& PropertyRow = DetailGroup.AddPropertyRow(ParameterValueProperty.ToSharedRef()); FIsResetToDefaultVisible IsResetVisible = FIsResetToDefaultVisible::CreateStatic(&FMaterialPropertyHelpers::ShouldShowResetToDefault, Parameter, MaterialEditorInstance); FResetToDefaultHandler ResetHandler = FResetToDefaultHandler::CreateStatic(&FMaterialPropertyHelpers::ResetToDefault, Parameter, MaterialEditorInstance); FResetToDefaultOverride ResetOverride = FResetToDefaultOverride::Create(IsResetVisible, ResetHandler); PropertyRow .DisplayName(FText::FromName(Parameter->ParameterInfo.Name)) .ToolTip(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateStatic(&FMaterialPropertyHelpers::OnOverrideParameter, Parameter, MaterialEditorInstance)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowExpression, Parameter, MaterialEditorInstance, ShowHiddenDelegate))) .OverrideResetToDefault(ResetOverride); } } void FMaterialInstanceParameterDetails::CreateMaskParameterValueWidget(UDEditorParameterValue* Parameter, TSharedPtr ParameterProperty, IDetailGroup& DetailGroup ) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); TSharedPtr RMaskProperty = ParameterValueProperty->GetChildHandle("R"); TSharedPtr GMaskProperty = ParameterValueProperty->GetChildHandle("G"); TSharedPtr BMaskProperty = ParameterValueProperty->GetChildHandle("B"); TSharedPtr AMaskProperty = ParameterValueProperty->GetChildHandle("A"); if (ParameterValueProperty->IsValidHandle()) { TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, Parameter)); IDetailPropertyRow& PropertyRow = DetailGroup.AddPropertyRow(ParameterValueProperty.ToSharedRef()); PropertyRow.EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateStatic(&FMaterialPropertyHelpers::OnOverrideParameter, Parameter, MaterialEditorInstance)); // Handle reset to default manually PropertyRow.OverrideResetToDefault(FResetToDefaultOverride::Create(FResetToDefaultHandler::CreateStatic(&FMaterialPropertyHelpers::ResetToDefault, Parameter, MaterialEditorInstance))); PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowExpression, Parameter, MaterialEditorInstance, ShowHiddenDelegate))); const FText ParameterName = FText::FromName(Parameter->ParameterInfo.Name); FDetailWidgetRow& CustomWidget = PropertyRow.CustomWidget(); CustomWidget .FilterString(ParameterName) .NameContent() [ SNew(STextBlock) .Text(ParameterName) .ToolTipText(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .Font(FEditorStyle::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(FText::GetEmpty(), FText::GetEmpty(), false) ] + 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(FText::GetEmpty(), FText::GetEmpty(), false) ] + 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(FText::GetEmpty(), FText::GetEmpty(), false) ] + 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(FText::GetEmpty(), FText::GetEmpty(), false) ] + SHorizontalBox::Slot() .HAlign(HAlign_Left) .AutoWidth() [ AMaskProperty->CreatePropertyValueWidget() ] ] ]; } } void FMaterialInstanceParameterDetails::CreateVectorChannelMaskParameterValueWidget(UDEditorParameterValue* Parameter, TSharedPtr ParameterProperty, IDetailGroup& DetailGroup) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); if (ParameterValueProperty->IsValidHandle()) { TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, Parameter)); IDetailPropertyRow& PropertyRow = DetailGroup.AddPropertyRow(ParameterValueProperty.ToSharedRef()); PropertyRow.EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateStatic(&FMaterialPropertyHelpers::OnOverrideParameter, Parameter, MaterialEditorInstance)); // Handle reset to default manually PropertyRow.OverrideResetToDefault(FResetToDefaultOverride::Create(FResetToDefaultHandler::CreateStatic(&FMaterialPropertyHelpers::ResetToDefault, Parameter, MaterialEditorInstance))); PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowExpression, Parameter, MaterialEditorInstance, ShowHiddenDelegate))); const FText ParameterName = FText::FromName(Parameter->ParameterInfo.Name); // Combo box hooks for converting between our "enum" and colors FOnGetPropertyComboBoxStrings GetMaskStrings = FOnGetPropertyComboBoxStrings::CreateStatic(&FMaterialPropertyHelpers::GetVectorChannelMaskComboBoxStrings); FOnGetPropertyComboBoxValue GetMaskValue = FOnGetPropertyComboBoxValue::CreateStatic(&FMaterialPropertyHelpers::GetVectorChannelMaskValue, Parameter); FOnPropertyComboBoxValueSelected SetMaskValue = FOnPropertyComboBoxValueSelected::CreateStatic(&FMaterialPropertyHelpers::SetVectorChannelMaskValue, ParameterValueProperty, Parameter, (UObject*)MaterialEditorInstance); // Widget replaces color picker with combo box FDetailWidgetRow& CustomWidget = PropertyRow.CustomWidget(); CustomWidget .FilterString(ParameterName) .NameContent() [ SNew(STextBlock) .Text(ParameterName) .ToolTipText(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .Font(FEditorStyle::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(ParameterValueProperty, GetMaskStrings, GetMaskValue, SetMaskValue) ] ] ]; } } void FMaterialInstanceParameterDetails::CreateScalarAtlasPositionParameterValueWidget(class UDEditorParameterValue* Parameter, TSharedPtr ParameterProperty, IDetailGroup& DetailGroup) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); if (ParameterValueProperty->IsValidHandle()) { TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, Parameter)); IDetailPropertyRow& PropertyRow = DetailGroup.AddPropertyRow(ParameterValueProperty.ToSharedRef()); PropertyRow.EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateStatic(&FMaterialPropertyHelpers::OnOverrideParameter, Parameter, MaterialEditorInstance)); // Handle reset to default manually PropertyRow.Visibility(TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowExpression, Parameter, MaterialEditorInstance, ShowHiddenDelegate))); const FText ParameterName = FText::FromName(Parameter->ParameterInfo.Name); UDEditorScalarParameterValue* AtlasParameter = Cast(Parameter); FIsResetToDefaultVisible IsResetVisible = FIsResetToDefaultVisible::CreateStatic(&FMaterialPropertyHelpers::ShouldShowResetToDefault, Parameter, MaterialEditorInstance); FResetToDefaultHandler ResetHandler = FResetToDefaultHandler::CreateStatic(&FMaterialPropertyHelpers::ResetCurveToDefault, Parameter, MaterialEditorInstance); FResetToDefaultOverride ResetOverride = FResetToDefaultOverride::Create(IsResetVisible, ResetHandler); PropertyRow.OverrideResetToDefault(ResetOverride); FDetailWidgetRow& CustomWidget = PropertyRow.CustomWidget(); CustomWidget .FilterString(ParameterName) .NameContent() [ SNew(STextBlock) .Text(ParameterName) .ToolTipText(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .Font(FEditorStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont"))) ] .ValueContent() .HAlign(HAlign_Fill) .MaxDesiredWidth(400.0f) [ SNew(SObjectPropertyEntryBox) .ObjectPath(this, &FMaterialInstanceParameterDetails::GetCurvePath, AtlasParameter) .AllowedClass(UCurveLinearColor::StaticClass()) .NewAssetFactories(TArray()) .DisplayThumbnail(true) .ThumbnailPool(PropertyUtilities.Pin()->GetThumbnailPool()) .OnShouldSetAsset(FOnShouldSetAsset::CreateStatic(&FMaterialPropertyHelpers::OnShouldSetCurveAsset, AtlasParameter->AtlasData.Atlas)) .OnObjectChanged(FOnSetObject::CreateStatic(&FMaterialPropertyHelpers::SetPositionFromCurveAsset, AtlasParameter->AtlasData.Atlas, AtlasParameter, ParameterProperty, (UObject*)MaterialEditorInstance)) .DisplayCompactSize(true) ]; } } FString FMaterialInstanceParameterDetails::GetCurvePath(UDEditorScalarParameterValue* Parameter) const { FString Path = Parameter->AtlasData.Curve->GetPathName(); return Path; } bool FMaterialInstanceParameterDetails::IsVisibleExpression(UDEditorParameterValue* Parameter) { return MaterialEditorInstance->VisibleExpressions.Contains(Parameter->ParameterInfo); } EVisibility FMaterialInstanceParameterDetails::ShouldShowExpression(UDEditorParameterValue* Parameter) const { return FMaterialPropertyHelpers::ShouldShowExpression(Parameter, MaterialEditorInstance, ShowHiddenDelegate); } bool FMaterialInstanceParameterDetails::OnShouldSetAsset(const FAssetData& AssetData) const { if (MaterialEditorInstance->bIsFunctionPreviewMaterial) { if (MaterialEditorInstance->SourceFunction->GetMaterialFunctionUsage() == EMaterialFunctionUsage::Default) { return false; } else { UMaterialFunctionInstance* FunctionInstance = Cast(AssetData.GetAsset()); if (FunctionInstance != nullptr) { bool bIsChild = FunctionInstance->IsDependent(MaterialEditorInstance->SourceFunction); if (bIsChild) { FMessageDialog::Open( EAppMsgType::Ok, FText::Format(LOCTEXT("CannotSetExistingChildFunctionAsParent", "Cannot set {0} as a parent as it is already a child of this material function instance."), FText::FromName(AssetData.AssetName))); } return !bIsChild; } } } UMaterialInstance* MaterialInstance = Cast(AssetData.GetAsset()); if (MaterialInstance != nullptr) { bool bIsChild = MaterialInstance->IsChildOf(MaterialEditorInstance->SourceInstance); if (bIsChild) { FMessageDialog::Open( EAppMsgType::Ok, FText::Format(LOCTEXT("CannotSetExistingChildAsParent", "Cannot set {0} as a parent as it is already a child of this material instance."), FText::FromName(AssetData.AssetName))); } return !bIsChild; } return true; } void FMaterialInstanceParameterDetails::OnAssetChanged(const FAssetData & InAssetData, TSharedRef InHandle) { if (MaterialEditorInstance->bIsFunctionPreviewMaterial && MaterialEditorInstance->SourceFunction->GetMaterialFunctionUsage() != EMaterialFunctionUsage::Default) { UMaterialFunctionInterface* NewParent = Cast(InAssetData.GetAsset()); if (NewParent != nullptr) { MaterialEditorInstance->SourceFunction->SetParent(NewParent); FPropertyChangedEvent ParentChanged = FPropertyChangedEvent(InHandle->GetProperty()); MaterialEditorInstance->PostEditChangeProperty(ParentChanged); } } } EVisibility FMaterialInstanceParameterDetails::ShouldShowMaterialRefractionSettings() const { return (MaterialEditorInstance->SourceInstance->GetMaterial()->bUsesDistortion && IsTranslucentBlendMode(MaterialEditorInstance->SourceInstance->GetBlendMode())) ? EVisibility::Visible : EVisibility::Collapsed; } EVisibility FMaterialInstanceParameterDetails::ShouldShowSubsurfaceProfile() const { FMaterialShadingModelField ShadingModels = MaterialEditorInstance->SourceInstance->GetShadingModels(); return UseSubsurfaceProfile(ShadingModels) ? EVisibility::Visible : EVisibility::Collapsed; } void FMaterialInstanceParameterDetails::CreateLightmassOverrideWidgets(IDetailLayoutBuilder& DetailLayout) { IDetailCategoryBuilder& DetailCategory = DetailLayout.EditCategory(NAME_None); static FName GroupName(TEXT("LightmassSettings")); IDetailGroup& LightmassSettingsGroup = DetailCategory.AddGroup(GroupName, LOCTEXT("LightmassSettingsGroup", "Lightmass Settings"), false, false); TAttribute IsOverrideCastShadowAsMaskedEnabled = TAttribute::Create(TAttribute::FGetter::CreateLambda([this] { return (bool)MaterialEditorInstance->LightmassSettings.CastShadowAsMasked.bOverride; })); TAttribute IsOverrideEmissiveBoostEnabled = TAttribute::Create(TAttribute::FGetter::CreateLambda([this] { return (bool)MaterialEditorInstance->LightmassSettings.EmissiveBoost.bOverride; })); TAttribute IsOverrideDiffuseBoostEnabled = TAttribute::Create(TAttribute::FGetter::CreateLambda([this] { return (bool)MaterialEditorInstance->LightmassSettings.DiffuseBoost.bOverride; })); TAttribute IsOverrideExportResolutionScaleEnabled = TAttribute::Create(TAttribute::FGetter::CreateLambda([this] { return (bool)MaterialEditorInstance->LightmassSettings.ExportResolutionScale.bOverride; })); TSharedRef LightmassSettings = DetailLayout.GetProperty("LightmassSettings"); TSharedPtr CastShadowAsMaskedProperty = LightmassSettings->GetChildHandle("CastShadowAsMasked"); TSharedPtr EmissiveBoostProperty = LightmassSettings->GetChildHandle("EmissiveBoost"); TSharedPtr DiffuseBoostProperty = LightmassSettings->GetChildHandle("DiffuseBoost"); TSharedPtr ExportResolutionScaleProperty = LightmassSettings->GetChildHandle("ExportResolutionScale"); FIsResetToDefaultVisible IsCastShadowAsMaskedPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->LightmassSettings.CastShadowAsMasked.ParameterValue != MaterialEditorInstance->Parent->GetCastShadowAsMasked() : false; }); FResetToDefaultHandler ResetCastShadowAsMaskedPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->LightmassSettings.CastShadowAsMasked.ParameterValue = MaterialEditorInstance->Parent->GetCastShadowAsMasked(); } }); FResetToDefaultOverride ResetCastShadowAsMaskedPropertyOverride = FResetToDefaultOverride::Create(IsCastShadowAsMaskedPropertyResetVisible, ResetCastShadowAsMaskedPropertyHandler); IDetailPropertyRow& CastShadowAsMaskedPropertyRow = LightmassSettingsGroup.AddPropertyRow(CastShadowAsMaskedProperty->GetChildHandle(0).ToSharedRef()); CastShadowAsMaskedPropertyRow .DisplayName(CastShadowAsMaskedProperty->GetPropertyDisplayName()) .ToolTip(CastShadowAsMaskedProperty->GetToolTipText()) .EditCondition(IsOverrideCastShadowAsMaskedEnabled, FOnBooleanValueChanged::CreateLambda([this](bool NewValue) { MaterialEditorInstance->LightmassSettings.CastShadowAsMasked.bOverride = (uint32)NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); })) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideCastShadowAsMaskedEnabled))) .OverrideResetToDefault(ResetCastShadowAsMaskedPropertyOverride); FIsResetToDefaultVisible IsEmissiveBoostPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->LightmassSettings.EmissiveBoost.ParameterValue != MaterialEditorInstance->Parent->GetEmissiveBoost() : false; }); FResetToDefaultHandler ResetEmissiveBoostPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->LightmassSettings.EmissiveBoost.ParameterValue = MaterialEditorInstance->Parent->GetEmissiveBoost(); } }); FResetToDefaultOverride ResetEmissiveBoostPropertyOverride = FResetToDefaultOverride::Create(IsEmissiveBoostPropertyResetVisible, ResetEmissiveBoostPropertyHandler); IDetailPropertyRow& EmissiveBoostPropertyRow = LightmassSettingsGroup.AddPropertyRow(EmissiveBoostProperty->GetChildHandle(0).ToSharedRef()); EmissiveBoostPropertyRow .DisplayName(EmissiveBoostProperty->GetPropertyDisplayName()) .ToolTip(EmissiveBoostProperty->GetToolTipText()) .EditCondition(IsOverrideEmissiveBoostEnabled, FOnBooleanValueChanged::CreateLambda([this](bool NewValue) { MaterialEditorInstance->LightmassSettings.EmissiveBoost.bOverride = (uint32)NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); })) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideEmissiveBoostEnabled))) .OverrideResetToDefault(ResetEmissiveBoostPropertyOverride); FIsResetToDefaultVisible IsDiffuseBoostPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->LightmassSettings.DiffuseBoost.ParameterValue != MaterialEditorInstance->Parent->GetDiffuseBoost() : false; }); FResetToDefaultHandler ResetDiffuseBoostPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->LightmassSettings.DiffuseBoost.ParameterValue = MaterialEditorInstance->Parent->GetDiffuseBoost(); } }); FResetToDefaultOverride ResetDiffuseBoostPropertyOverride = FResetToDefaultOverride::Create(IsDiffuseBoostPropertyResetVisible, ResetDiffuseBoostPropertyHandler); IDetailPropertyRow& DiffuseBoostPropertyRow = LightmassSettingsGroup.AddPropertyRow(DiffuseBoostProperty->GetChildHandle(0).ToSharedRef()); DiffuseBoostPropertyRow .DisplayName(DiffuseBoostProperty->GetPropertyDisplayName()) .ToolTip(DiffuseBoostProperty->GetToolTipText()) .EditCondition(IsOverrideDiffuseBoostEnabled, FOnBooleanValueChanged::CreateLambda([this](bool NewValue) { MaterialEditorInstance->LightmassSettings.DiffuseBoost.bOverride = (uint32)NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); })) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideDiffuseBoostEnabled))) .OverrideResetToDefault(ResetDiffuseBoostPropertyOverride); FIsResetToDefaultVisible IsExportResolutionScalePropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->LightmassSettings.ExportResolutionScale.ParameterValue != MaterialEditorInstance->Parent->GetDiffuseBoost() : false; }); FResetToDefaultHandler ResetExportResolutionScalePropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->LightmassSettings.ExportResolutionScale.ParameterValue = MaterialEditorInstance->Parent->GetDiffuseBoost(); } }); FResetToDefaultOverride ResetExportResolutionScalePropertyOverride = FResetToDefaultOverride::Create(IsExportResolutionScalePropertyResetVisible, ResetExportResolutionScalePropertyHandler); IDetailPropertyRow& ExportResolutionScalePropertyRow = LightmassSettingsGroup.AddPropertyRow(ExportResolutionScaleProperty->GetChildHandle(0).ToSharedRef()); ExportResolutionScalePropertyRow .DisplayName(ExportResolutionScaleProperty->GetPropertyDisplayName()) .ToolTip(ExportResolutionScaleProperty->GetToolTipText()) .EditCondition(IsOverrideExportResolutionScaleEnabled, FOnBooleanValueChanged::CreateLambda([this](bool NewValue) { MaterialEditorInstance->LightmassSettings.ExportResolutionScale.bOverride = (uint32)NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); })) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideExportResolutionScaleEnabled))) .OverrideResetToDefault(ResetExportResolutionScalePropertyOverride); } void FMaterialInstanceParameterDetails::CreateBasePropertyOverrideWidgets(IDetailLayoutBuilder& DetailLayout) { IDetailCategoryBuilder& DetailCategory = DetailLayout.EditCategory(NAME_None); static FName GroupName(TEXT("BasePropertyOverrideGroup")); IDetailGroup& BasePropertyOverrideGroup = DetailCategory.AddGroup(GroupName, LOCTEXT("BasePropertyOverrideGroup", "Material Property Overrides"), false, false); TAttribute IsOverrideOpacityClipMaskValueEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideOpacityClipMaskValueEnabled)); TAttribute IsOverrideBlendModeEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideBlendModeEnabled)); TAttribute IsOverrideShadingModelEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideShadingModelEnabled)); TAttribute IsOverrideTwoSidedEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideTwoSidedEnabled)); TAttribute IsOverrideDitheredLODTransitionEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideDitheredLODTransitionEnabled)); TSharedRef BasePropertyOverridePropery = DetailLayout.GetProperty("BasePropertyOverrides"); TSharedPtr OpacityClipMaskValueProperty = BasePropertyOverridePropery->GetChildHandle("OpacityMaskClipValue"); TSharedPtr BlendModeProperty = BasePropertyOverridePropery->GetChildHandle("BlendMode"); TSharedPtr ShadingModelProperty = BasePropertyOverridePropery->GetChildHandle("ShadingModel"); TSharedPtr TwoSidedProperty = BasePropertyOverridePropery->GetChildHandle("TwoSided"); TSharedPtr DitheredLODTransitionProperty = BasePropertyOverridePropery->GetChildHandle("DitheredLODTransition"); FIsResetToDefaultVisible IsOpacityClipMaskValuePropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.OpacityMaskClipValue != MaterialEditorInstance->Parent->GetOpacityMaskClipValue() : false; }); FResetToDefaultHandler ResetOpacityClipMaskValuePropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.OpacityMaskClipValue = MaterialEditorInstance->Parent->GetOpacityMaskClipValue(); } }); FResetToDefaultOverride ResetOpacityClipMaskValuePropertyOverride = FResetToDefaultOverride::Create(IsOpacityClipMaskValuePropertyResetVisible, ResetOpacityClipMaskValuePropertyHandler); IDetailPropertyRow& OpacityClipMaskValuePropertyRow = BasePropertyOverrideGroup.AddPropertyRow(OpacityClipMaskValueProperty.ToSharedRef()); OpacityClipMaskValuePropertyRow .DisplayName(OpacityClipMaskValueProperty->GetPropertyDisplayName()) .ToolTip(OpacityClipMaskValueProperty->GetToolTipText()) .EditCondition(IsOverrideOpacityClipMaskValueEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideOpacityClipMaskValueChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideOpacityClipMaskValueEnabled))) .OverrideResetToDefault(ResetOpacityClipMaskValuePropertyOverride); FIsResetToDefaultVisible IsBlendModePropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.BlendMode != MaterialEditorInstance->Parent->GetBlendMode() : false; }); FResetToDefaultHandler ResetBlendModePropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.BlendMode = MaterialEditorInstance->Parent->GetBlendMode(); } }); FResetToDefaultOverride ResetBlendModePropertyOverride = FResetToDefaultOverride::Create(IsBlendModePropertyResetVisible, ResetBlendModePropertyHandler); IDetailPropertyRow& BlendModePropertyRow = BasePropertyOverrideGroup.AddPropertyRow(BlendModeProperty.ToSharedRef()); BlendModePropertyRow .DisplayName(BlendModeProperty->GetPropertyDisplayName()) .ToolTip(BlendModeProperty->GetToolTipText()) .EditCondition(IsOverrideBlendModeEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideBlendModeChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideBlendModeEnabled))) .OverrideResetToDefault(ResetBlendModePropertyOverride); FIsResetToDefaultVisible IsShadingModelPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { if (MaterialEditorInstance->Parent->IsShadingModelFromMaterialExpression()) { return MaterialEditorInstance->BasePropertyOverrides.ShadingModel != MSM_FromMaterialExpression; } else { return MaterialEditorInstance->BasePropertyOverrides.ShadingModel != MaterialEditorInstance->Parent->GetShadingModels().GetFirstShadingModel(); } } else { return false; } }); FResetToDefaultHandler ResetShadingModelPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { if (MaterialEditorInstance->Parent->IsShadingModelFromMaterialExpression()) { MaterialEditorInstance->BasePropertyOverrides.ShadingModel = MSM_FromMaterialExpression; } else { MaterialEditorInstance->BasePropertyOverrides.ShadingModel = MaterialEditorInstance->Parent->GetShadingModels().GetFirstShadingModel(); } } }); FResetToDefaultOverride ResetShadingModelPropertyOverride = FResetToDefaultOverride::Create(IsShadingModelPropertyResetVisible, ResetShadingModelPropertyHandler); IDetailPropertyRow& ShadingModelPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(ShadingModelProperty.ToSharedRef()); ShadingModelPropertyRow .DisplayName(ShadingModelProperty->GetPropertyDisplayName()) .ToolTip(ShadingModelProperty->GetToolTipText()) .EditCondition(IsOverrideShadingModelEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideShadingModelChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideShadingModelEnabled))) .OverrideResetToDefault(ResetShadingModelPropertyOverride); FIsResetToDefaultVisible IsTwoSidedPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.TwoSided != MaterialEditorInstance->Parent->IsTwoSided() : false; }); FResetToDefaultHandler ResetTwoSidedValuePropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.TwoSided = MaterialEditorInstance->Parent->IsTwoSided(); } }); FResetToDefaultOverride ResetTwoSidedPropertyOverride = FResetToDefaultOverride::Create(IsTwoSidedPropertyResetVisible, ResetTwoSidedValuePropertyHandler); IDetailPropertyRow& TwoSidedPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(TwoSidedProperty.ToSharedRef()); TwoSidedPropertyRow .DisplayName(TwoSidedProperty->GetPropertyDisplayName()) .ToolTip(TwoSidedProperty->GetToolTipText()) .EditCondition(IsOverrideTwoSidedEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideTwoSidedChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideTwoSidedEnabled))) .OverrideResetToDefault(ResetTwoSidedPropertyOverride); FIsResetToDefaultVisible IsDitheredLODTransitionPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.DitheredLODTransition != MaterialEditorInstance->Parent->IsDitheredLODTransition() : false; }); FResetToDefaultHandler ResetDitheredLODTransitionPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.DitheredLODTransition = MaterialEditorInstance->Parent->IsDitheredLODTransition(); } }); FResetToDefaultOverride ResetDitheredLODTransitionPropertyOverride = FResetToDefaultOverride::Create(IsDitheredLODTransitionPropertyResetVisible, ResetDitheredLODTransitionPropertyHandler); IDetailPropertyRow& DitheredLODTransitionPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(DitheredLODTransitionProperty.ToSharedRef()); DitheredLODTransitionPropertyRow .DisplayName(DitheredLODTransitionProperty->GetPropertyDisplayName()) .ToolTip(DitheredLODTransitionProperty->GetToolTipText()) .EditCondition(IsOverrideDitheredLODTransitionEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideDitheredLODTransitionChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideDitheredLODTransitionEnabled))) .OverrideResetToDefault(ResetDitheredLODTransitionPropertyOverride); } EVisibility FMaterialInstanceParameterDetails::IsOverriddenAndVisible(TAttribute IsOverridden) const { bool bShouldBeVisible = true; if (MaterialEditorInstance->bShowOnlyOverrides) { bShouldBeVisible = IsOverridden.Get(); } return bShouldBeVisible ? EVisibility::Visible : EVisibility::Collapsed; } bool FMaterialInstanceParameterDetails::OverrideOpacityClipMaskValueEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_OpacityMaskClipValue; } bool FMaterialInstanceParameterDetails::OverrideBlendModeEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_BlendMode; } bool FMaterialInstanceParameterDetails::OverrideShadingModelEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_ShadingModel; } bool FMaterialInstanceParameterDetails::OverrideTwoSidedEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_TwoSided; } bool FMaterialInstanceParameterDetails::OverrideDitheredLODTransitionEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_DitheredLODTransition; } void FMaterialInstanceParameterDetails::OnOverrideOpacityClipMaskValueChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_OpacityMaskClipValue = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideBlendModeChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_BlendMode = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideShadingModelChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_ShadingModel = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideTwoSidedChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_TwoSided = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideDitheredLODTransitionChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_DitheredLODTransition = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } #undef LOCTEXT_NAMESPACE