// Copyright 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 "Styling/AppStyle.h" #include "Materials/MaterialInterface.h" #include "MaterialEditor/DEditorFontParameterValue.h" #include "MaterialEditor/DEditorMaterialLayersParameterValue.h" #include "MaterialEditor/DEditorRuntimeVirtualTextureParameterValue.h" #include "MaterialEditor/DEditorSparseVolumeTextureParameterValue.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 "MaterialShared.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" #include "Engine/Texture.h" #include "HAL/PlatformApplicationMisc.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); } { // Add the material property override group static FName GroupName(TEXT("MaterialPropertyOverrideGroup")); IDetailGroup& MaterialPropertyOverrideGroup = DefaultCategory.AddGroup(GroupName, LOCTEXT("MaterialPropertyOverrideGroup", "Material Property Overrides"), false, false); // Hide the originals, these will be recreated manually DetailLayout.HideProperty("bOverrideSubsurfaceProfile"); DetailLayout.HideProperty("SubsurfaceProfile"); DetailLayout.HideProperty("BasePropertyOverrides"); // Set up the override logic for the subsurface profile TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateLambda([this](){ return (bool)MaterialEditorInstance->bOverrideSubsurfaceProfile; })); IDetailPropertyRow& PropertyRow = MaterialPropertyOverrideGroup.AddPropertyRow(DetailLayout.GetProperty("SubsurfaceProfile")); PropertyRow .EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateLambda([this](bool NewValue) { MaterialEditorInstance->bOverrideSubsurfaceProfile = (uint32)NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); })) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::ShouldShowSubsurfaceProfile))); // Append the base property overrides to the Material Property Override Group CreateBasePropertyOverrideWidgets(DetailLayout, MaterialPropertyOverrideGroup); // Append the nanite material override. MaterialPropertyOverrideGroup.AddPropertyRow(DetailLayout.GetProperty("NaniteOverrideMaterial")); } } // 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() && !bCreateGroup; ++ParamIdx) { UDEditorParameterValue* Parameter = ParameterGroup.Parameters[ParamIdx]; const bool bIsVisible = MaterialEditorInstance->VisibleExpressions.Contains(Parameter->ParameterInfo); bCreateGroup = bIsVisible && (!MaterialEditorInstance->bShowOnlyOverrides || FMaterialPropertyHelpers::IsOverriddenExpression(Parameter)); } if (bCreateGroup) { IDetailGroup& DetailGroup = GroupsCategory.AddGroup(ParameterGroup.GroupName, FText::FromName(ParameterGroup.GroupName), false, true); FUIAction CopyAction( FExecuteAction::CreateSP(this, &FMaterialInstanceParameterDetails::OnCopyParameterValues, GroupIdx), FCanExecuteAction::CreateSP(this, &FMaterialInstanceParameterDetails::CanCopyParameterValues, GroupIdx)); FUIAction PasteAction( FExecuteAction::CreateSP(this, &FMaterialInstanceParameterDetails::OnPasteParameterValues, GroupIdx), FCanExecuteAction::CreateSP(this, &FMaterialInstanceParameterDetails::CanPasteParameterValues, GroupIdx)); DetailGroup.HeaderRow() .CopyAction(CopyAction) .PasteAction(PasteAction) .NameContent() [ SNew(STextBlock) .Text(FText::FromName(DetailGroup.GetGroupName())) ]; 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, ToRawPtr(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) .Text(LOCTEXT("SaveSibling", "Save Sibling")) .HAlign(HAlign_Center) .OnClicked(OnSiblingButtonClicked) .ToolTipText(LOCTEXT("SaveToSiblingInstance", "Save to Sibling Instance")) ] + SHorizontalBox::Slot() .AutoWidth() .Padding(2.0f) [ SNew(SButton) .Text(LOCTEXT("SaveChild", "Save Child")) .HAlign(HAlign_Center) .OnClicked(OnChildButtonClicked) .ToolTipText(LOCTEXT("SaveToChildInstance", "Save to Child Instance")) ] ]; } } 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); UDEditorRuntimeVirtualTextureParameterValue* RuntimeVirtualTextureParam = Cast(Parameter); UDEditorSparseVolumeTextureParameterValue* SparseVolumeTextureParam = 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); } if (TextureParam && ( !TextureParam->ChannelNames.R.IsEmpty() || !TextureParam->ChannelNames.G.IsEmpty() || !TextureParam->ChannelNames.B.IsEmpty() || !TextureParam->ChannelNames.A.IsEmpty())) { CreateLabeledTextureParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } else if (LayersParam) { } else if (CompMaskParam) { CreateMaskParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } else { 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)); } 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); } } CreateParameterValueWidget(Parameter, ParameterProperty, DetailGroup); } } } } 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()); TAttribute IsResetVisible = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowResetToDefault, Parameter, MaterialEditorInstance)); FSimpleDelegate ResetHandler = FSimpleDelegate::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); // Textures need a special widget that filters based on VT or not UDEditorTextureParameterValue* TextureParam = Cast(Parameter); if (TextureParam != nullptr) { UMaterial *Material = MaterialEditorInstance->SourceInstance->GetMaterial(); if (Material != nullptr) { UMaterialExpressionTextureSampleParameter* Expression = Material->FindExpressionByGUID(TextureParam->ExpressionId); if (Expression != nullptr) { TWeakObjectPtr SamplerExpression = Expression; PropertyRow.CustomWidget() .NameContent() [ ParameterValueProperty->CreatePropertyNameWidget() ] .ValueContent() .MaxDesiredWidth(TOptional()) [ SNew(SObjectPropertyEntryBox) .PropertyHandle(ParameterValueProperty) .AllowedClass(UTexture::StaticClass()) .ThumbnailPool(PropertyUtilities.Pin()->GetThumbnailPool()) .OnShouldFilterAsset_Lambda([SamplerExpression](const FAssetData& AssetData) { if (SamplerExpression.Get()) { bool VirtualTextured = false; AssetData.GetTagValue("VirtualTextureStreaming", VirtualTextured); bool ExpressionIsVirtualTextured = IsVirtualSamplerType(SamplerExpression->SamplerType); return VirtualTextured != ExpressionIsVirtualTextured; } else { return false; } }) ]; } } } } } 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(FSimpleDelegate::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(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() ] ] ]; } } 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(FSimpleDelegate::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(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(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); TAttribute IsResetVisible = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowResetToDefault, Parameter, MaterialEditorInstance)); FSimpleDelegate ResetHandler = FSimpleDelegate::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(FAppStyle::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()) .OnShouldFilterAsset(FOnShouldFilterAsset::CreateStatic(&FMaterialPropertyHelpers::OnShouldFilterCurveAsset, AtlasParameter->AtlasData.Atlas)) .OnShouldSetAsset(FOnShouldSetAsset::CreateStatic(&FMaterialPropertyHelpers::OnShouldSetCurveAsset, AtlasParameter->AtlasData.Atlas)) .OnObjectChanged(FOnSetObject::CreateStatic(&FMaterialPropertyHelpers::SetPositionFromCurveAsset, AtlasParameter->AtlasData.Atlas, AtlasParameter, ParameterProperty, (UObject*)MaterialEditorInstance)) .DisplayCompactSize(true) ]; } } void FMaterialInstanceParameterDetails::CreateLabeledTextureParameterValueWidget(class UDEditorParameterValue* Parameter, TSharedPtr ParameterProperty, IDetailGroup& DetailGroup) { TSharedPtr ParameterValueProperty = ParameterProperty->GetChildHandle("ParameterValue"); if (ParameterValueProperty->IsValidHandle()) { UDEditorTextureParameterValue* TextureParam = Cast(Parameter); if (TextureParam) { UMaterial *Material = MaterialEditorInstance->SourceInstance->GetMaterial(); if (Material != nullptr) { UMaterialExpressionTextureSampleParameter* Expression = Material->FindExpressionByGUID(TextureParam->ExpressionId); if (Expression != nullptr) { TWeakObjectPtr SamplerExpression = Expression; TAttribute IsParamEnabled = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::IsOverriddenExpression, Parameter)); IDetailPropertyRow& PropertyRow = DetailGroup.AddPropertyRow(ParameterValueProperty.ToSharedRef()); TAttribute IsResetVisible = TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowResetToDefault, Parameter, MaterialEditorInstance)); FSimpleDelegate ResetHandler = FSimpleDelegate::CreateStatic(&FMaterialPropertyHelpers::ResetToDefault, Parameter, MaterialEditorInstance); FResetToDefaultOverride ResetOverride = FResetToDefaultOverride::Create(IsResetVisible, ResetHandler); PropertyRow .DisplayName(FText::FromName(Parameter->ParameterInfo.Name)) .EditCondition(IsParamEnabled, FOnBooleanValueChanged::CreateStatic(&FMaterialPropertyHelpers::OnOverrideParameter, Parameter, MaterialEditorInstance)) .ToolTip(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateStatic(&FMaterialPropertyHelpers::ShouldShowExpression, Parameter, MaterialEditorInstance, ShowHiddenDelegate))); TSharedPtr NameWidget; TSharedPtr ValueWidget; FDetailWidgetRow Row; PropertyRow.GetDefaultWidgets(NameWidget, ValueWidget, Row); FDetailWidgetRow &DetailWidgetRow = PropertyRow.CustomWidget(); TSharedPtr NameVerticalBox; DetailWidgetRow.NameContent() [ SAssignNew(NameVerticalBox, SVerticalBox) + SVerticalBox::Slot() .AutoHeight() [ SNew(STextBlock) .Text(FText::FromName(Parameter->ParameterInfo.Name)) .ToolTipText(FMaterialPropertyHelpers::GetParameterTooltip(Parameter, MaterialEditorInstance)) .Font(FAppStyle::GetFontStyle(TEXT("PropertyWindow.NormalFont"))) ] ]; DetailWidgetRow.ValueContent() .MinDesiredWidth(Row.ValueWidget.MinWidth) .MaxDesiredWidth(Row.ValueWidget.MaxWidth) [ SNew(SObjectPropertyEntryBox) .PropertyHandle(ParameterValueProperty) .AllowedClass(UTexture::StaticClass()) .ThumbnailPool(PropertyUtilities.Pin()->GetThumbnailPool()) .OnShouldFilterAsset_Lambda([SamplerExpression](const FAssetData& AssetData) { if (SamplerExpression.Get()) { bool VirtualTextured = false; AssetData.GetTagValue("VirtualTextureStreaming", VirtualTextured); bool ExpressionIsVirtualTextured = IsVirtualSamplerType(SamplerExpression->SamplerType); return VirtualTextured != ExpressionIsVirtualTextured; } else { return false; } }) ]; DetailWidgetRow.OverrideResetToDefault(ResetOverride); 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"))) ] ]; } } } } } } 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))); } if (bIsChild) { return false; } } 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)) ? EVisibility::Visible : EVisibility::Collapsed; } EVisibility FMaterialInstanceParameterDetails::ShouldShowSubsurfaceProfile() const { FMaterialShadingModelField ShadingModels = MaterialEditorInstance->SourceInstance->GetShadingModels(); return UseSubsurfaceProfile(ShadingModels) ? EVisibility::Visible : EVisibility::Collapsed; } void FMaterialInstanceParameterDetails::OnCopyParameterValues(int32 ParameterGroupIndex) { if (!MaterialEditorInstance || !MaterialEditorInstance->ParameterGroups.IsValidIndex(ParameterGroupIndex)) { return; } FEditorParameterGroup& ParameterGroup = MaterialEditorInstance->ParameterGroups[ParameterGroupIndex]; TStringBuilder<4096> CombinedValue; const int32 NumParams = ParameterGroup.Parameters.Num(); for (int32 ParamIdx = 0; ParamIdx < NumParams; ++ParamIdx) { UDEditorParameterValue* Parameter = ParameterGroup.Parameters[ParamIdx]; const FName ParamName = Parameter->ParameterInfo.Name; const TCHAR* Prefix = (ParamIdx == 0) ? TEXT("") : TEXT(","); // Include the value in the result entry only if the parameter is overridden. const bool bOverride = FMaterialPropertyHelpers::IsOverriddenExpression(Parameter); if (bOverride) { FProperty* ParameterValueProperty = Parameter->GetClass()->FindPropertyByName("ParameterValue"); if (ParameterValueProperty != nullptr) { FString ParameterValueString; if (ParameterValueProperty->ExportText_InContainer(0, ParameterValueString, Parameter, Parameter, Parameter, PPF_Copy)) { CombinedValue.Appendf(TEXT("%s%s.Override=True,%s.Value=\"%s\""), Prefix, *(ParamName.ToString()), *(ParamName.ToString()), *(ParameterValueString.ReplaceCharWithEscapedChar())); } } } else { CombinedValue.Appendf(TEXT("%s%s.Override=False"), Prefix, *(ParamName.ToString())); } } if (CombinedValue.Len()) { // Copy. FPlatformApplicationMisc::ClipboardCopy(*CombinedValue); } } bool FMaterialInstanceParameterDetails::CanCopyParameterValues(int32 ParameterGroupIndex) { return MaterialEditorInstance && MaterialEditorInstance->ParameterGroups.IsValidIndex(ParameterGroupIndex) && (MaterialEditorInstance->ParameterGroups[ParameterGroupIndex].Parameters.Num() > 0); } void FMaterialInstanceParameterDetails::OnPasteParameterValues(int32 ParameterGroupIndex) { if (!MaterialEditorInstance || !MaterialEditorInstance->ParameterGroups.IsValidIndex(ParameterGroupIndex)) { return; } FString ClipboardContent; FPlatformApplicationMisc::ClipboardPaste(ClipboardContent); if (!ClipboardContent.IsEmpty()) { FScopedTransaction Transaction(LOCTEXT("PasteMaterialInstanceParameters", "Paste Material Instance Parameters")); MaterialEditorInstance->Modify(); for (int32 ParamIdx = 0; ParamIdx < MaterialEditorInstance->ParameterGroups[ParameterGroupIndex].Parameters.Num(); ++ParamIdx) { UDEditorParameterValue* Parameter = MaterialEditorInstance->ParameterGroups[ParameterGroupIndex].Parameters[ParamIdx]; Parameter->Modify(); const FName ParamName = Parameter->ParameterInfo.Name; const FString OverrideKey = FString::Printf(TEXT("%s.Override="), *(ParamName.ToString())); bool bParsedOverride = false; if (FParse::Bool(*ClipboardContent, *OverrideKey, bParsedOverride)) { Parameter->bOverride = bParsedOverride; if (bParsedOverride) { // Paste value. const FString ValueKey = FString::Printf(TEXT("%s.Value="), *(ParamName.ToString())); FString ParsedValueString; if (FParse::Value(*ClipboardContent, *ValueKey, ParsedValueString)) { ParsedValueString = ParsedValueString.ReplaceEscapedCharWithChar(); FProperty* ParameterValueProperty = Parameter->GetClass()->FindPropertyByName("ParameterValue"); if (ParameterValueProperty != nullptr) { ParameterValueProperty->ImportText_InContainer(*ParsedValueString, Parameter, Parameter, PPF_Copy); } } } } } MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } } bool FMaterialInstanceParameterDetails::CanPasteParameterValues(int32 ParameterGroupIndex) { // First check the same criteria as copying. if (!CanCopyParameterValues(ParameterGroupIndex)) { return false; } // Now see if there's anything to paste from the clipboard. FString ClipboardContent; FPlatformApplicationMisc::ClipboardPaste(ClipboardContent); return !ClipboardContent.IsEmpty(); } 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); } UEnum* GetBlendModeEnum(); void FMaterialInstanceParameterDetails::CreateBasePropertyOverrideWidgets(IDetailLayoutBuilder& DetailLayout, IDetailGroup& MaterialPropertyOverrideGroup) { IDetailGroup& BasePropertyOverrideGroup = MaterialPropertyOverrideGroup; 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 IsOverrideIsThinSurfaceEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideIsThinSurfaceEnabled)); TAttribute IsOverrideDitheredLODTransitionEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideDitheredLODTransitionEnabled)); TAttribute IsOverrideOutputTranslucentVelocityEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideOutputTranslucentVelocityEnabled)); TAttribute IsOverrideDisplacementScalingEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideDisplacementScalingEnabled)); TAttribute IsOverrideMaxWorldPositionOffsetDisplacementEnabled = TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::OverrideMaxWorldPositionOffsetDisplacementEnabled)); 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 IsThinSurfaceProperty = BasePropertyOverridePropery->GetChildHandle("IsThinSurface"); TSharedPtr DitheredLODTransitionProperty = BasePropertyOverridePropery->GetChildHandle("DitheredLODTransition"); TSharedPtr OutputTranslucentVelocityProperty = BasePropertyOverridePropery->GetChildHandle("bOutputTranslucentVelocity"); TSharedPtr DisplacementScalingProperty = BasePropertyOverridePropery->GetChildHandle("DisplacementScaling"); TSharedPtr MaxWorldPositionOffsetDisplacementProperty = BasePropertyOverridePropery->GetChildHandle("MaxWorldPositionOffsetDisplacement"); const FText ParameterDisabledToolTipString = FText::FromString(TEXT("This material instance parent restricts the creation of new shader permutations. Overriding this parameter would result in the generation of additional shader permutations.")); const bool bStaticParametersOverrideDisabled = MaterialEditorInstance->SourceInstance->bDisallowStaticParameterPermutations; // Update blend mode display names if (FByteProperty* BlendModeByteProperty = (FByteProperty*)BlendModeProperty->GetProperty()) { BlendModeByteProperty->Enum = GetBlendModeEnum(); } { 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(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : 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(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : 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(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : 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(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : TwoSidedProperty->GetToolTipText()) .EditCondition(IsOverrideTwoSidedEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideTwoSidedChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideTwoSidedEnabled))) .OverrideResetToDefault(ResetTwoSidedPropertyOverride); } if (IsThinSurfaceProperty) { FIsResetToDefaultVisible IsThinSurfacePropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.bIsThinSurface != MaterialEditorInstance->Parent->IsThinSurface() : false; }); FResetToDefaultHandler ResetIsThinSurfaceValuePropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.bIsThinSurface = MaterialEditorInstance->Parent->IsThinSurface(); } }); FResetToDefaultOverride ResetIsThinSurfacePropertyOverride = FResetToDefaultOverride::Create(IsThinSurfacePropertyResetVisible, ResetIsThinSurfaceValuePropertyHandler); IDetailPropertyRow& IsThinSurfacePropertyRow = BasePropertyOverrideGroup.AddPropertyRow(IsThinSurfaceProperty.ToSharedRef()); IsThinSurfacePropertyRow .DisplayName(IsThinSurfaceProperty->GetPropertyDisplayName()) .ToolTip(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : IsThinSurfaceProperty->GetToolTipText()) .EditCondition(IsOverrideIsThinSurfaceEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideIsThinSurfaceChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideIsThinSurfaceEnabled))) .OverrideResetToDefault(ResetIsThinSurfacePropertyOverride); } { 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(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : DitheredLODTransitionProperty->GetToolTipText()) .EditCondition(IsOverrideDitheredLODTransitionEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideDitheredLODTransitionChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideDitheredLODTransitionEnabled))) .OverrideResetToDefault(ResetDitheredLODTransitionPropertyOverride); } { FIsResetToDefaultVisible IsOutputTranslucentVelocityPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.bOutputTranslucentVelocity != MaterialEditorInstance->Parent->IsTranslucencyWritingVelocity() : false; }); FResetToDefaultHandler ResetOutputTranslucentVelocityPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.bOutputTranslucentVelocity = MaterialEditorInstance->Parent->IsTranslucencyWritingVelocity(); } }); FResetToDefaultOverride ResetOutputTranslucentVelocityPropertyOverride = FResetToDefaultOverride::Create(IsOutputTranslucentVelocityPropertyResetVisible, ResetOutputTranslucentVelocityPropertyHandler); IDetailPropertyRow& OutputTranslucentVelocityPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(OutputTranslucentVelocityProperty.ToSharedRef()); OutputTranslucentVelocityPropertyRow .DisplayName(OutputTranslucentVelocityProperty->GetPropertyDisplayName()) .ToolTip(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : OutputTranslucentVelocityProperty->GetToolTipText()) .EditCondition(IsOverrideOutputTranslucentVelocityEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideOutputTranslucentVelocityChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideOutputTranslucentVelocityEnabled))) .OverrideResetToDefault(ResetOutputTranslucentVelocityPropertyOverride); } { FIsResetToDefaultVisible IsDisplacementScalingPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.DisplacementScaling != MaterialEditorInstance->Parent->GetDisplacementScaling() : false; }); FResetToDefaultHandler ResetDisplacementScalingPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.DisplacementScaling = MaterialEditorInstance->Parent->GetDisplacementScaling(); } }); FResetToDefaultOverride ResetDisplacementScalingPropertyOverride = FResetToDefaultOverride::Create(IsDisplacementScalingPropertyResetVisible, ResetDisplacementScalingPropertyHandler); IDetailPropertyRow& DisplacementScalingPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(DisplacementScalingProperty.ToSharedRef()); DisplacementScalingPropertyRow .DisplayName(DisplacementScalingProperty->GetPropertyDisplayName()) .ToolTip(DisplacementScalingProperty->GetToolTipText()) .EditCondition(IsOverrideDisplacementScalingEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideDisplacementScalingChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideDisplacementScalingEnabled))) .OverrideResetToDefault(ResetDisplacementScalingPropertyOverride); } { FIsResetToDefaultVisible IsMaxWorldPositionOffsetDisplacementPropertyResetVisible = FIsResetToDefaultVisible::CreateLambda([this](TSharedPtr InHandle) { return MaterialEditorInstance->Parent != nullptr ? MaterialEditorInstance->BasePropertyOverrides.MaxWorldPositionOffsetDisplacement != MaterialEditorInstance->Parent->GetMaxWorldPositionOffsetDisplacement() : false; }); FResetToDefaultHandler ResetMaxWorldPositionOffsetDisplacementPropertyHandler = FResetToDefaultHandler::CreateLambda([this](TSharedPtr InHandle) { if (MaterialEditorInstance->Parent != nullptr) { MaterialEditorInstance->BasePropertyOverrides.MaxWorldPositionOffsetDisplacement = MaterialEditorInstance->Parent->GetMaxWorldPositionOffsetDisplacement(); } }); FResetToDefaultOverride ResetMaxWorldPositionOffsetDisplacementPropertyOverride = FResetToDefaultOverride::Create(IsMaxWorldPositionOffsetDisplacementPropertyResetVisible, ResetMaxWorldPositionOffsetDisplacementPropertyHandler); IDetailPropertyRow& MaxWorldPositionOffsetDisplacementPropertyRow = BasePropertyOverrideGroup.AddPropertyRow(MaxWorldPositionOffsetDisplacementProperty.ToSharedRef()); MaxWorldPositionOffsetDisplacementPropertyRow .DisplayName(MaxWorldPositionOffsetDisplacementProperty->GetPropertyDisplayName()) .ToolTip(bStaticParametersOverrideDisabled ? ParameterDisabledToolTipString : MaxWorldPositionOffsetDisplacementProperty->GetToolTipText()) .EditCondition(IsOverrideMaxWorldPositionOffsetDisplacementEnabled, FOnBooleanValueChanged::CreateSP(this, &FMaterialInstanceParameterDetails::OnOverrideMaxWorldPositionOffsetDisplacementChanged)) .Visibility(TAttribute::Create(TAttribute::FGetter::CreateSP(this, &FMaterialInstanceParameterDetails::IsOverriddenAndVisible, IsOverrideMaxWorldPositionOffsetDisplacementEnabled))) .OverrideResetToDefault(ResetMaxWorldPositionOffsetDisplacementPropertyOverride); } } 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::OverrideIsThinSurfaceEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_bIsThinSurface; } bool FMaterialInstanceParameterDetails::OverrideDitheredLODTransitionEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_DitheredLODTransition; } bool FMaterialInstanceParameterDetails::OverrideOutputTranslucentVelocityEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_OutputTranslucentVelocity; } bool FMaterialInstanceParameterDetails::OverrideDisplacementScalingEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_DisplacementScaling; } bool FMaterialInstanceParameterDetails::OverrideMaxWorldPositionOffsetDisplacementEnabled() const { return MaterialEditorInstance->BasePropertyOverrides.bOverride_MaxWorldPositionOffsetDisplacement; } /** Helper function used by some parameters to verify that they are allowed to be overridden. This * must be prevented if the source material instance disallows the creation of new static parameter * permutations as that would trigger a new shader creation. */ static bool DoesSourceMaterialInstanceDisallowStaticParameterPermutation(const UMaterialEditorInstanceConstant* mi, bool NewValue) { if (NewValue && mi->SourceInstance->bDisallowStaticParameterPermutations) { return true; } return false; } void FMaterialInstanceParameterDetails::OnOverrideOpacityClipMaskValueChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_OpacityMaskClipValue = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideBlendModeChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_BlendMode = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideShadingModelChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_ShadingModel = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideTwoSidedChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_TwoSided = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideIsThinSurfaceChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_bIsThinSurface = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideDitheredLODTransitionChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_DitheredLODTransition = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideOutputTranslucentVelocityChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_OutputTranslucentVelocity = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideDisplacementScalingChanged(bool NewValue) { MaterialEditorInstance->BasePropertyOverrides.bOverride_DisplacementScaling = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } void FMaterialInstanceParameterDetails::OnOverrideMaxWorldPositionOffsetDisplacementChanged(bool NewValue) { if (DoesSourceMaterialInstanceDisallowStaticParameterPermutation(MaterialEditorInstance, NewValue)) { return; } MaterialEditorInstance->BasePropertyOverrides.bOverride_MaxWorldPositionOffsetDisplacement = NewValue; MaterialEditorInstance->PostEditChange(); FEditorSupportDelegates::RedrawAllViewports.Broadcast(); } #undef LOCTEXT_NAMESPACE