2024-06-04 11:58:57 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
# include "SMaterialSubstrateTree.h"
# include "SMaterialLayersFunctionsTree.h"
# include "SMaterialLayersFunctionsTree.h"
# include "MaterialEditor/DEditorFontParameterValue.h"
# include "MaterialEditor/DEditorMaterialLayersParameterValue.h"
# include "MaterialEditor/DEditorRuntimeVirtualTextureParameterValue.h"
# include "MaterialEditor/DEditorScalarParameterValue.h"
# include "MaterialEditor/DEditorStaticComponentMaskParameterValue.h"
# include "MaterialEditor/DEditorStaticSwitchParameterValue.h"
# include "MaterialEditor/DEditorTextureParameterValue.h"
# include "MaterialEditor/DEditorVectorParameterValue.h"
# include "MaterialEditor/MaterialEditorInstanceConstant.h"
# include "Materials/Material.h"
# include "PropertyHandle.h"
# include "Modules/ModuleManager.h"
# include "PropertyEditorModule.h"
# include "ISinglePropertyView.h"
# include "Materials/MaterialInstanceConstant.h"
# include "Styling/AppStyle.h"
# include "PropertyCustomizationHelpers.h"
# include "ScopedTransaction.h"
# include "IPropertyRowGenerator.h"
# include "Widgets/Views/STreeView.h"
# include "IDetailTreeNode.h"
# include "AssetThumbnail.h"
2024-06-28 10:11:23 -04:00
# include "ContentBrowserModule.h"
2024-06-04 11:58:57 -04:00
# include "MaterialEditorInstanceDetailCustomization.h"
# include "MaterialPropertyHelpers.h"
# include "DetailWidgetRow.h"
# include "Widgets/Input/SCheckBox.h"
# include "EditorSupportDelegates.h"
# include "Widgets/Images/SImage.h"
# include "MaterialEditor/MaterialEditorPreviewParameters.h"
# include "Widgets/Input/SButton.h"
2024-06-28 10:11:23 -04:00
# include "Widgets/Layout/SSeparator.h"
2024-06-04 11:58:57 -04:00
# include "Widgets/Text/SInlineEditableTextBlock.h"
# include "Materials/MaterialFunctionInstance.h"
# include "Materials/MaterialExpressionTextureSampleParameter.h"
# include "Framework/Application/SlateApplication.h"
2024-06-28 10:11:23 -04:00
# include "Framework/MultiBox/MultiBoxBuilder.h"
2024-06-04 11:58:57 -04:00
# include "Widgets/Input/SEditableTextBox.h"
# include "Curves/CurveLinearColor.h"
# include "Curves/CurveLinearColorAtlas.h"
# include "Subsystems/AssetEditorSubsystem.h"
# include "Editor.h"
# include "EditorFontGlyphs.h"
2024-06-28 10:11:23 -04:00
# include "IContentBrowserSingleton.h"
2024-06-04 11:58:57 -04:00
# include "SResetToDefaultPropertyEditor.h"
# include "DragAndDrop/AssetDragDropOp.h"
# include "ThumbnailRendering/ThumbnailManager.h"
# include "Styling/AppStyle.h"
# include "Styling/StyleColors.h"
# include "MaterialEditorStyle.h"
2024-06-28 10:11:23 -04:00
# include "DetailTreeNode.h"
# include "Materials/MaterialFunctionMaterialLayerBlend.h"
2024-06-04 11:58:57 -04:00
# define LOCTEXT_NAMESPACE "MaterialSubstrateTree"
2024-06-19 13:54:35 -04:00
FString CreateNodeKeyForBackgroundParameter ( const FString & InNodeKeyBase )
{
return FString ( InNodeKeyBase + TEXT ( " _BackgroundParameter " ) ) ;
}
bool IsNodeKeyForBackgroundParameter ( const FString InNodeKey )
{
return ( InNodeKey . Find ( TEXT ( " _BackgroundParameter " ) ) > = 0 ) ;
}
2024-06-04 11:58:57 -04:00
/// ===========================================================================================================
/// SMaterialSubstrateItem Methods
/// ===========================================================================================================
FString SMaterialSubstrateTreeItem : : GetCurvePath ( UDEditorScalarParameterValue * Parameter ) const
{
FString Path = Parameter - > AtlasData . Curve - > GetPathName ( ) ;
return Path ;
}
const FSlateBrush * SMaterialSubstrateTreeItem : : GetBorderImage ( ) const
{
return FAppStyle : : Get ( ) . GetBrush ( " DetailsView.CategoryMiddle " ) ;
}
FSlateColor SMaterialSubstrateTreeItem : : GetOuterBackgroundColor ( TSharedPtr < FSortedParamData > InParamData ) const
{
if ( InParamData - > StackDataType = = EStackDataType : : Stack )
{
if ( bIsBeingDragged )
{
return FAppStyle : : Get ( ) . GetSlateColor ( " Colors.Recessed " ) ;
}
else if ( bIsHoveredDragTarget )
{
return FAppStyle : : Get ( ) . GetSlateColor ( " Colors.Highlight " ) ;
}
else
{
return FAppStyle : : Get ( ) . GetSlateColor ( " Colors.Header " ) ;
}
}
else if ( IsHovered ( ) | | InParamData - > StackDataType = = EStackDataType : : Group )
{
return FAppStyle : : Get ( ) . GetSlateColor ( " Colors.Header " ) ;
}
return FAppStyle : : Get ( ) . GetSlateColor ( " Colors.Panel " ) ;
}
void SMaterialSubstrateTreeItem : : RefreshOnRowChange ( const FAssetData & AssetData , SMaterialSubstrateTree * InTree )
{
if ( SMaterialLayersFunctionsInstanceWrapper * Wrapper = InTree - > GetWrapper ( ) )
{
if ( Wrapper - > OnLayerPropertyChanged . IsBound ( ) )
{
Wrapper - > OnLayerPropertyChanged . Execute ( ) ;
}
else
{
InTree - > CreateGroupsWidget ( ) ;
}
}
}
bool SMaterialSubstrateTreeItem : : GetFilterState ( SMaterialSubstrateTree * InTree , TSharedPtr < FSortedParamData > InStackData ) const
{
if ( InStackData - > ParameterInfo . Association = = EMaterialParameterAssociation : : LayerParameter )
{
return InTree - > FunctionInstance - > EditorOnly . RestrictToLayerRelatives [ InStackData - > ParameterInfo . Index ] ;
}
if ( InStackData - > ParameterInfo . Association = = EMaterialParameterAssociation : : BlendParameter )
{
return InTree - > FunctionInstance - > EditorOnly . RestrictToBlendRelatives [ InStackData - > ParameterInfo . Index ] ;
}
return false ;
}
void SMaterialSubstrateTreeItem : : FilterClicked ( const ECheckBoxState NewCheckedState , SMaterialSubstrateTree * InTree , TSharedPtr < FSortedParamData > InStackData )
{
if ( InStackData - > ParameterInfo . Association = = EMaterialParameterAssociation : : LayerParameter )
{
InTree - > FunctionInstance - > EditorOnly . RestrictToLayerRelatives [ InStackData - > ParameterInfo . Index ] = ! InTree - > FunctionInstance - > EditorOnly . RestrictToLayerRelatives [ InStackData - > ParameterInfo . Index ] ;
}
if ( InStackData - > ParameterInfo . Association = = EMaterialParameterAssociation : : BlendParameter )
{
InTree - > FunctionInstance - > EditorOnly . RestrictToBlendRelatives [ InStackData - > ParameterInfo . Index ] = ! InTree - > FunctionInstance - > EditorOnly . RestrictToBlendRelatives [ InStackData - > ParameterInfo . Index ] ;
}
}
ECheckBoxState SMaterialSubstrateTreeItem : : GetFilterChecked ( SMaterialSubstrateTree * InTree , TSharedPtr < FSortedParamData > InStackData ) const
{
return GetFilterState ( InTree , InStackData ) ? ECheckBoxState : : Checked : ECheckBoxState : : Unchecked ;
}
2024-06-19 13:54:35 -04:00
FReply SMaterialSubstrateTreeItem : : ToggleLayerVisibility ( )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
return Tree - > ToggleLayerVisibility ( LayerFuncIndex ) ;
2024-06-04 11:58:57 -04:00
}
2024-06-19 13:54:35 -04:00
bool SMaterialSubstrateTreeItem : : IsLayerVisible ( ) const
{
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
return Tree - > IsLayerVisible ( LayerFuncIndex ) ;
}
FReply SMaterialSubstrateTreeItem : : UnlinkLayer ( )
{
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
return Tree - > UnlinkLayer ( LayerFuncIndex ) ;
}
EVisibility SMaterialSubstrateTreeItem : : GetUnlinkLayerVisibility ( ) const
{
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
return Tree - > GetUnlinkLayerVisibility ( LayerFuncIndex ) ;
}
FText SMaterialSubstrateTreeItem : : GetLayerName ( ) const
{
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
return Tree - > FunctionInstance - > GetLayerName ( LayerFuncIndex ) ;
}
2024-06-28 10:11:23 -04:00
FText SMaterialSubstrateTreeItem : : GetLayerDesc ( ) const
{
const FString LayerDescText [ ] = { TEXT ( " Material Evaluation " ) , TEXT ( " Material Instance Attributes " ) } ;
return FText : : FromString ( LayerDescText [ GetIndentLevel ( ) ] ) ;
}
2024-06-19 13:54:35 -04:00
void SMaterialSubstrateTreeItem : : OnNameChanged ( const FText & InText , ETextCommit : : Type CommitInfo )
2024-06-04 11:58:57 -04:00
{
const FScopedTransaction Transaction ( LOCTEXT ( " RenamedSection " , " Renamed layer and blend section " ) ) ;
2024-06-19 13:54:35 -04:00
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
Tree - > FunctionInstanceHandle - > NotifyPreChange ( ) ;
Tree - > FunctionInstance - > EditorOnly . LayerNames [ LayerFuncIndex ] = InText ;
Tree - > FunctionInstance - > UnlinkLayerFromParent ( LayerFuncIndex ) ;
Tree - > MaterialEditorInstance - > CopyToSourceInstance ( true ) ;
Tree - > FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
2024-06-04 11:58:57 -04:00
}
2024-06-14 12:41:34 -04:00
TOptional < EItemDropZone > SMaterialSubstrateTreeItem : : CanAcceptDrop ( const FDragDropEvent & DragDropEvent , EItemDropZone DropZone , FSortedParamDataPtr Item )
{
TSharedPtr < FLayerDragDropOp > LayerDragDropOperation = DragDropEvent . GetOperationAs < FLayerDragDropOp > ( ) ;
TSharedPtr < FAssetDragDropOp > AssetDragDropOperation = DragDropEvent . GetOperationAs < FAssetDragDropOp > ( ) ;
2024-07-15 05:42:13 -04:00
if ( LayerDragDropOperation . IsValid ( ) )
2024-06-14 12:41:34 -04:00
{
2024-07-15 05:42:13 -04:00
// PREVENT LAYER DRAG FOR NOW
//return DropZone;
}
else if ( AssetDragDropOperation . IsValid ( ) )
{
// Identify the type of asset
bool HasLayerFuncAsset = false ;
bool HasBlendFuncAsset = false ;
for ( const FAssetData & AssetData : AssetDragDropOperation - > GetAssets ( ) )
{
if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayer " ) )
{
HasLayerFuncAsset = true ;
}
else if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayerBlend " ) )
{
HasBlendFuncAsset = true ;
}
}
// Drop above or below could CREATE a new layer node:
int32 TargetNodeId = StackParameterData - > ParameterInfo . Index ;
int32 ParentNodeId = Tree - > FunctionInstance - > GetNodeParent ( TargetNodeId ) ;
auto ChildrenNodeId = Tree - > FunctionInstance - > GetNodeChildren ( ParentNodeId ) ;
int32 SiblingIdx = - 1 ;
bool FoundTarget = ChildrenNodeId . Find ( TargetNodeId , SiblingIdx ) ;
switch ( DropZone )
{
case EItemDropZone : : AboveItem :
if ( ! HasLayerFuncAsset ) // Can only add above if drop a new layer function
{
return TOptional < EItemDropZone > ( ) ;
}
break ;
case EItemDropZone : : BelowItem :
if ( ! HasLayerFuncAsset // Can only add under if drop a new layer function
| | ( SiblingIdx = = 0 ) ) // Can't add BEFORE the first layer or sub layer
{
return TOptional < EItemDropZone > ( ) ;
}
break ;
case EItemDropZone : : OntoItem :
if ( ! ( HasLayerFuncAsset | | HasBlendFuncAsset ) // Can only drop valid assets
| | ( ! HasLayerFuncAsset & & HasBlendFuncAsset & & ( SiblingIdx = = 0 ) ) ) // Or just a blendfunc on the first layer
{
return TOptional < EItemDropZone > ( ) ;
}
break ;
default :
break ;
}
2024-06-14 12:41:34 -04:00
return DropZone ;
}
return TOptional < EItemDropZone > ( ) ;
}
FReply SMaterialSubstrateTreeItem : : OnLayerDrop ( const FDragDropEvent & DragDropEvent , EItemDropZone DropZone , FSortedParamDataPtr TargetItem )
2024-06-04 11:58:57 -04:00
{
if ( ! bIsHoveredDragTarget )
{
return FReply : : Unhandled ( ) ;
}
FScopedTransaction Transaction ( NSLOCTEXT ( " UnrealEd " , " MoveLayer " , " Move Layer " ) ) ;
Tree - > FunctionInstanceHandle - > NotifyPreChange ( ) ;
bIsHoveredDragTarget = false ;
2024-06-14 12:41:34 -04:00
TSharedPtr < FLayerDragDropOp > ArrayDropOp = DragDropEvent . GetOperationAs < FLayerDragDropOp > ( ) ;
2024-06-04 11:58:57 -04:00
TSharedPtr < SMaterialSubstrateTreeItem > LayerPtr = nullptr ;
if ( ArrayDropOp . IsValid ( ) & & ArrayDropOp - > OwningStack . IsValid ( ) )
{
2024-06-14 12:41:34 -04:00
LayerPtr = StaticCastWeakPtr < SMaterialSubstrateTreeItem > ( ArrayDropOp - > OwningStack ) . Pin ( ) ;
2024-06-04 11:58:57 -04:00
}
else
{
// see if it is an accepted asset drop
TSharedPtr < FAssetDragDropOp > AssetDropOp = DragDropEvent . GetOperationAs < FAssetDragDropOp > ( ) ;
if ( AssetDropOp . IsValid ( ) )
{
2024-07-15 05:42:13 -04:00
// Identify the type of asset
bool HasLayerFuncAsset = false ;
bool HasBlendFuncAsset = false ;
for ( const FAssetData & AssetData : AssetDropOp - > GetAssets ( ) )
{
if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayer " ) )
{
HasLayerFuncAsset = true ;
}
else if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayerBlend " ) )
{
HasBlendFuncAsset = true ;
}
}
2024-06-19 13:54:35 -04:00
// Drop above or below could CREATE a new layer node:
int32 TargetNodeId = StackParameterData - > ParameterInfo . Index ;
2024-07-15 05:42:13 -04:00
int32 TargetNodeDepth = Tree - > FunctionInstance - > GetNodeDepth ( TargetNodeId ) ;
int32 ParentNodeId = Tree - > FunctionInstance - > GetNodeParent ( TargetNodeId ) ;
2024-06-19 13:54:35 -04:00
auto ChildrenNodeId = Tree - > FunctionInstance - > GetNodeChildren ( ParentNodeId ) ;
int32 SiblingIdx = - 1 ;
bool FoundTarget = ChildrenNodeId . Find ( TargetNodeId , SiblingIdx ) ;
2024-07-15 05:42:13 -04:00
bool DidModifyTree = false ;
2024-06-19 13:54:35 -04:00
switch ( DropZone )
{
2024-07-15 05:42:13 -04:00
// NOTE: The drop cases Above and Below take into account the fact that the list is displayed bottom up!
2024-06-19 13:54:35 -04:00
case EItemDropZone : : AboveItem :
2024-07-15 05:42:13 -04:00
check ( HasLayerFuncAsset ) ; // Only add with a valid new LayerFunc asset
TargetNodeId = Tree - > FunctionInstance - > AppendLayerNode ( ParentNodeId , SiblingIdx + 1 ) ; // Above means insert after
DidModifyTree = true ;
2024-06-19 13:54:35 -04:00
break ;
case EItemDropZone : : BelowItem :
2024-07-15 05:42:13 -04:00
check ( HasLayerFuncAsset ) ; // Only add with a valid new LayerFunc asset
TargetNodeId = Tree - > FunctionInstance - > AppendLayerNode ( ParentNodeId , SiblingIdx ) ; // Under means insert at
DidModifyTree = true ;
break ;
case EItemDropZone : : OntoItem :
// Dropping LayerFunc asset (with blendfunc too maybe) on a top level layer means a NEW sub layer is created
if ( HasLayerFuncAsset & & ( TargetNodeDepth < = 1 ) ) // Top level Layers
{
// add a new layer in this target node last on the stack
TargetNodeId = Tree - > FunctionInstance - > AppendLayerNode ( TargetNodeId , - 1 ) ;
DidModifyTree = true ;
}
else
{
// Assign the new asset(s) to this particular target node
}
2024-06-19 13:54:35 -04:00
break ;
default :
break ;
}
// Then drop
2024-06-04 11:58:57 -04:00
for ( const FAssetData & AssetData : AssetDropOp - > GetAssets ( ) )
{
EMaterialParameterAssociation InAssociation = EMaterialParameterAssociation : : GlobalParameter ;
if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayer " ) )
{
InAssociation = EMaterialParameterAssociation : : LayerParameter ;
2024-06-19 13:54:35 -04:00
Tree - > RefreshOnAssetChange ( AssetData , TargetNodeId , InAssociation ) ;
2024-06-04 11:58:57 -04:00
DidModifyTree = true ;
}
else if ( AssetData . AssetClassPath . GetAssetName ( ) = = TEXT ( " MaterialFunctionMaterialLayerBlend " ) )
{
InAssociation = EMaterialParameterAssociation : : BlendParameter ;
2024-06-19 13:54:35 -04:00
Tree - > RefreshOnAssetChange ( AssetData , TargetNodeId , InAssociation ) ;
2024-06-04 11:58:57 -04:00
DidModifyTree = true ;
}
}
if ( DidModifyTree )
{
return FReply : : Handled ( ) ;
}
}
return FReply : : Unhandled ( ) ;
}
if ( ! LayerPtr . IsValid ( ) )
{
return FReply : : Unhandled ( ) ;
}
2024-06-14 12:41:34 -04:00
LayerPtr - > bIsBeingDragged = false ;
2024-06-04 11:58:57 -04:00
TSharedPtr < FSortedParamData > SwappingPropertyData = LayerPtr - > StackParameterData ;
TSharedPtr < FSortedParamData > SwappablePropertyData = StackParameterData ;
if ( SwappingPropertyData . IsValid ( ) & & SwappablePropertyData . IsValid ( ) )
{
if ( SwappingPropertyData ! = SwappablePropertyData )
{
int32 OriginalIndex = SwappingPropertyData - > ParameterInfo . Index ;
if ( SwappingPropertyData - > ParameterInfo . Association = = EMaterialParameterAssociation : : BlendParameter )
{
OriginalIndex + + ;
}
int32 NewIndex = SwappablePropertyData - > ParameterInfo . Index ;
if ( SwappablePropertyData - > ParameterInfo . Association = = EMaterialParameterAssociation : : BlendParameter )
{
NewIndex + + ;
}
if ( OriginalIndex ! = NewIndex )
{
2024-08-07 06:49:03 -04:00
if ( Tree - > MaterialEditorInstance - > GetMaterialInterface ( ) - > IsA < UMaterialInstanceConstant > ( ) )
{
UMaterialInstanceConstant * MaterialConstant = Cast < UMaterialInstanceConstant > ( Tree - > MaterialEditorInstance - > GetMaterialInterface ( ) ) ;
MaterialConstant - > SwapLayerParameterIndices ( OriginalIndex , NewIndex ) ;
}
2024-06-04 11:58:57 -04:00
// Need to save the moving and target expansion states before swapping
const bool bOriginalSwappableExpansion = IsItemExpanded ( ) ;
const bool bOriginalSwappingExpansion = LayerPtr - > IsItemExpanded ( ) ;
TArray < void * > StructPtrs ;
Tree - > FunctionInstanceHandle - > AccessRawData ( StructPtrs ) ;
FMaterialLayersFunctions * MaterialLayersFunctions = static_cast < FMaterialLayersFunctions * > ( StructPtrs [ 0 ] ) ;
MaterialLayersFunctions - > MoveBlendedLayer ( OriginalIndex , NewIndex ) ;
Tree - > OnExpansionChanged ( SwappablePropertyData , bOriginalSwappingExpansion ) ;
Tree - > OnExpansionChanged ( SwappingPropertyData , bOriginalSwappableExpansion ) ;
Tree - > FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
Tree - > CreateGroupsWidget ( ) ;
Tree - > RequestTreeRefresh ( ) ;
Tree - > SetParentsExpansionState ( ) ;
}
}
}
return FReply : : Handled ( ) ;
}
bool SMaterialSubstrateTree : : IsOverriddenExpression ( class UDEditorParameterValue * Parameter , int32 InIndex )
{
return FMaterialPropertyHelpers : : IsOverriddenExpression ( Parameter ) & & FunctionInstance - > EditorOnly . LayerStates [ InIndex ] ;
}
bool SMaterialSubstrateTree : : IsOverriddenExpression ( TObjectPtr < UDEditorParameterValue > Parameter , int32 InIndex )
{
return IsOverriddenExpression ( Parameter . Get ( ) , InIndex ) ;
}
FGetShowHiddenParameters SMaterialSubstrateTree : : GetShowHiddenDelegate ( ) const
{
return ShowHiddenDelegate ;
}
void SMaterialSubstrateTreeItem : : OnOverrideParameter ( bool NewValue , class UDEditorParameterValue * Parameter )
{
2024-08-07 06:49:03 -04:00
FMaterialPropertyHelpers : : OnOverrideParameter ( NewValue , Parameter , Cast < UMaterialEditorInstanceConstant > ( MaterialEditorInstance ) ) ;
2024-06-04 11:58:57 -04:00
}
void SMaterialSubstrateTreeItem : : OnOverrideParameter ( bool NewValue , TObjectPtr < UDEditorParameterValue > Parameter )
{
OnOverrideParameter ( NewValue , Parameter . Get ( ) ) ;
}
void SMaterialSubstrateTreeItem : : Construct ( const FArguments & InArgs , const TSharedRef < STableViewBase > & InOwnerTableView )
{
2024-06-28 10:11:23 -04:00
FOnTableRowDragEnter LayerDragDelegate = FOnTableRowDragEnter : : CreateSP ( this , & SMaterialSubstrateTreeItem : : OnLayerDragEnter ) ;
FOnTableRowDragLeave LayerDragLeaveDelegate = FOnTableRowDragLeave : : CreateSP ( this , & SMaterialSubstrateTreeItem : : OnLayerDragLeave ) ;
STableRow < TSharedPtr < FSortedParamData > > : : ConstructInternal (
STableRow < TSharedPtr < FSortedParamData > > : : FArguments ( )
. Style ( FSubstrateMaterialEditorStyle : : Get ( ) , " LayerView.Row " )
. ShowSelection ( true )
. OnCanAcceptDrop ( this , & SMaterialSubstrateTreeItem : : CanAcceptDrop )
. OnAcceptDrop ( this , & SMaterialSubstrateTreeItem : : OnLayerDrop )
. OnDragEnter ( LayerDragDelegate )
. OnDragLeave ( LayerDragLeaveDelegate ) ,
InOwnerTableView
) ;
2024-06-04 11:58:57 -04:00
StackParameterData = InArgs . _StackParameterData ;
MaterialEditorInstance = InArgs . _MaterialEditorInstance ;
Tree = InArgs . _InTree ;
TSharedRef < SWidget > LeftSideWidget = SNullWidget : : NullWidget ;
TSharedRef < SWidget > RightSideWidget = SNullWidget : : NullWidget ;
TSharedRef < SWidget > ResetWidget = SNullWidget : : NullWidget ;
FText NameOverride ;
2024-06-28 10:11:23 -04:00
TSharedPtr < SHorizontalBox > MainStack ;
2024-06-04 11:58:57 -04:00
TSharedRef < SVerticalBox > WrapperWidget = SNew ( SVerticalBox ) ;
2024-06-28 10:11:23 -04:00
if ( StackParameterData - > StackDataType = = EStackDataType : : Stack )
{
WrapperWidget - > AddSlot ( )
. Padding ( 10.0f ) /*.AutoHeight()*/
[
SAssignNew ( MainStack , SHorizontalBox )
] ;
}
2024-06-04 11:58:57 -04:00
EHorizontalAlignment ValueAlignment = HAlign_Left ;
2024-06-19 13:54:35 -04:00
bool bIsBackgroundItem = IsNodeKeyForBackgroundParameter ( StackParameterData - > NodeKey ) ;
bool bCanReorderLayer = ! ( bIsBackgroundItem | | StackParameterData - > ParameterInfo . Index = = 0 ) ;
2024-06-28 10:11:23 -04:00
bool bCanAppendSubLayer = Tree - > FunctionInstance - > CanAppendLayerNode ( StackParameterData - > ParameterInfo . Index ) & & ! bIsBackgroundItem ;
2024-06-04 11:58:57 -04:00
// STACK --------------------------------------------------
if ( StackParameterData - > StackDataType = = EStackDataType : : Stack )
{
# if WITH_EDITOR
2024-06-19 13:54:35 -04:00
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
int32 BlendFuncIndex = Tree - > FunctionInstance - > GetBlendFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
NameOverride = Tree - > FunctionInstance - > GetLayerName ( LayerFuncIndex ) ;
2024-06-04 11:58:57 -04:00
# endif
TSharedRef < SHorizontalBox > HeaderRowWidget = SNew ( SHorizontalBox ) ;
if ( StackParameterData - > ParameterInfo . Index ! = 0 )
{
2024-06-19 13:54:35 -04:00
TAttribute < bool > : : FGetter IsEnabledGetter = TAttribute < bool > : : FGetter : : CreateSP ( this , & SMaterialSubstrateTreeItem : : IsLayerVisible ) ;
2024-06-04 11:58:57 -04:00
TAttribute < bool > IsEnabledAttribute = TAttribute < bool > : : Create ( IsEnabledGetter ) ;
2024-06-19 13:54:35 -04:00
FOnClicked VisibilityClickedDelegate = FOnClicked : : CreateSP ( this , & SMaterialSubstrateTreeItem : : ToggleLayerVisibility ) ;
2024-06-04 11:58:57 -04:00
HeaderRowWidget - > AddSlot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
[
PropertyCustomizationHelpers : : MakeVisibilityButton ( VisibilityClickedDelegate , FText ( ) , IsEnabledAttribute )
] ;
}
const float ThumbnailSize = 64.0f ;
TArray < TSharedPtr < FSortedParamData > > AssetChildren = StackParameterData - > Children ;
2024-06-19 13:54:35 -04:00
// Extract the asset elements to represent them as thumbnail boxes
2024-06-04 11:58:57 -04:00
for ( TSharedPtr < FSortedParamData > AssetChild : AssetChildren )
{
2024-06-19 13:54:35 -04:00
if ( AssetChild - > StackDataType = = EStackDataType : : Asset )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
TSharedPtr < SBox > ThumbnailBox ;
UObject * AssetObject = nullptr ;
AssetChild - > ParameterHandle - > GetValue ( AssetObject ) ;
int32 PreviewIndex = INDEX_NONE ;
int32 ThumbnailIndex = INDEX_NONE ;
EMaterialParameterAssociation PreviewAssociation = EMaterialParameterAssociation : : GlobalParameter ;
2024-07-17 09:38:30 -04:00
if ( AssetChild - > ParameterInfo . Association = = LayerParameter )
2024-06-04 11:58:57 -04:00
{
2024-07-17 09:38:30 -04:00
PreviewIndex = LayerFuncIndex ;
PreviewAssociation = EMaterialParameterAssociation : : LayerParameter ;
Tree - > UpdateThumbnailMaterial ( PreviewAssociation , PreviewIndex ) ;
ThumbnailIndex = PreviewIndex ;
HeaderRowWidget - > AddSlot ( )
. AutoWidth ( )
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. Padding ( 4.0f )
. MaxWidth ( ThumbnailSize )
[
SAssignNew ( ThumbnailBox , SBox )
. MaxDesiredWidth ( ThumbnailSize )
. MinDesiredWidth ( ThumbnailSize )
. MaxDesiredHeight ( ThumbnailSize )
. MinDesiredHeight ( ThumbnailSize )
[
Tree - > CreateThumbnailWidget ( PreviewAssociation , ThumbnailIndex , ThumbnailSize )
]
] ;
2024-06-04 11:58:57 -04:00
}
2024-07-17 09:38:30 -04:00
// if blend asset, we set it up in the Wrapper Widget at the bottom of the VerticalBox
else if ( AssetChild - > ParameterInfo . Association = = BlendParameter )
{
WrapperWidget - > AddSlot ( )
. Padding ( 2.0f )
. AutoHeight ( )
[
SNew ( SSeparator )
. Thickness ( 2.0f ) // Set the thickness of the separator
] ;
IDetailTreeNode & Node = * AssetChild - > ParameterNode ;
TSharedPtr < IDetailPropertyRow > GeneratedRow = StaticCastSharedPtr < IDetailPropertyRow > ( Node . GetRow ( ) ) ;
IDetailPropertyRow & Row = * GeneratedRow . Get ( ) ;
TSharedRef < SWidget > AssetPickerWidget = SNew ( SObjectPropertyEntryBox )
. ObjectPath_Lambda ( [ = , this ] ( )
{
UObject * AssetObject = nullptr ;
AssetChild - > ParameterHandle - > GetValue ( AssetObject ) ;
return AssetObject - > GetPathName ( ) ;
} )
. OnObjectChanged_Lambda ( [ = , this ] ( const FAssetData & InAssetData )
{
FSoftObjectPath ObjPath = InAssetData . GetSoftObjectPath ( ) ;
AssetChild - > ParameterHandle - > SetValue ( ObjPath . TryLoad ( ) ) ;
Tree - > FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
Tree - > CreateGroupsWidget ( ) ;
Tree - > RequestTreeRefresh ( ) ;
} )
. AllowedClass ( UMaterialFunctionMaterialLayerBlend : : StaticClass ( ) )
. AllowClear ( true )
. DisplayUseSelected ( false )
. DisplayBrowse ( false ) ;
WrapperWidget - > AddSlot ( )
. Padding ( 5.0f )
. AutoHeight ( )
[
SNew ( SHorizontalBox )
// + SHorizontalBox::Slot()
// .AutoWidth()
// .VAlign(VAlign_Center)
// [
// PropertyCustomizationHelpers::MakeVisibilityButton(VisibilityClickedDelegate, FText(), IsEnabledAttribute)
// ]
+ SHorizontalBox : : Slot ( )
. Padding ( 5.0f )
. HAlign ( HAlign_Left )
. VAlign ( VAlign_Center )
[
SNew ( STextBlock )
. Justification ( ETextJustify : : Center )
. Text ( LOCTEXT ( " BlendLabel " , " Blend " ) )
]
+ SHorizontalBox : : Slot ( )
. Padding ( 5.0f )
[
AssetPickerWidget
// AssetChild->ParameterHandle->CreatePropertyValueWidget(false)
]
] ;
}
2024-06-19 13:54:35 -04:00
}
2024-06-04 11:58:57 -04:00
}
2024-06-28 10:11:23 -04:00
{
HeaderRowWidget - > AddSlot ( )
. VAlign ( VAlign_Center )
. AutoWidth ( )
. Padding ( 5.0f )
[
SNew ( SVerticalBox )
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( STextBlock )
. Text ( NameOverride )
. TextStyle ( FSubstrateMaterialEditorStyle : : Get ( ) , " LayerView.Row.HeaderText " )
]
2024-06-04 11:58:57 -04:00
2024-06-28 10:11:23 -04:00
+ SVerticalBox : : Slot ( )
. AutoHeight ( )
[
SNew ( STextBlock )
. Text ( TAttribute < FText > : : Create ( TAttribute < FText > : : FGetter : : CreateSP ( this , & SMaterialSubstrateTreeItem : : GetLayerDesc ) ) )
. TextStyle ( FSubstrateMaterialEditorStyle : : Get ( ) , " LayerView.Row.HeaderText.Small " )
]
2024-06-04 11:58:57 -04:00
] ;
}
// Unlink UI
HeaderRowWidget - > AddSlot ( )
. FillWidth ( 1.0f )
. VAlign ( VAlign_Center )
[
SNullWidget : : NullWidget
] ;
2024-06-19 13:54:35 -04:00
2024-06-04 11:58:57 -04:00
HeaderRowWidget - > AddSlot ( )
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( 0.0f , 0.0f , 0.0f , 0.0f )
[
SNew ( SButton )
. Text ( LOCTEXT ( " Unlink " , " Unlink " ) )
. HAlign ( HAlign_Center )
2024-06-19 13:54:35 -04:00
. OnClicked ( this , & SMaterialSubstrateTreeItem : : UnlinkLayer )
2024-06-04 11:58:57 -04:00
. ToolTipText ( LOCTEXT ( " UnlinkLayer " , " Whether or not to unlink this layer/blend combination from the parent. " ) )
2024-06-19 13:54:35 -04:00
. Visibility ( this , & SMaterialSubstrateTreeItem : : GetUnlinkLayerVisibility )
2024-06-04 11:58:57 -04:00
] ;
LeftSideWidget = HeaderRowWidget ;
}
// END STACK
// FINAL WRAPPER
if ( StackParameterData - > StackDataType = = EStackDataType : : Stack )
{
2024-06-28 10:11:23 -04:00
MainStack - > AddSlot ( )
. Padding ( FMargin ( 2.0f ) )
. VAlign ( VAlign_Center )
2024-06-04 11:58:57 -04:00
[
2024-06-28 10:11:23 -04:00
LeftSideWidget
2024-06-04 11:58:57 -04:00
] ;
2024-06-28 10:11:23 -04:00
2024-06-19 13:54:35 -04:00
if ( bCanReorderLayer )
2024-06-14 12:41:34 -04:00
{
2024-06-28 10:11:23 -04:00
MainStack - > AddSlot ( )
2024-06-14 12:41:34 -04:00
. HAlign ( HAlign_Center )
. VAlign ( VAlign_Center )
. Padding ( 2.5f , 0 )
. AutoWidth ( )
[
FMaterialPropertyHelpers : : MakeStackReorderHandle ( SharedThis ( this ) )
] ;
}
2024-06-19 13:54:35 -04:00
if ( bCanAppendSubLayer )
{
2024-06-28 10:11:23 -04:00
MainStack - > AddSlot ( )
2024-06-19 13:54:35 -04:00
. AutoWidth ( )
. VAlign ( VAlign_Center )
. Padding ( FMargin ( 2.0f ) )
[
SNew ( SExpanderArrow , SharedThis ( this ) )
] ;
}
2024-06-04 11:58:57 -04:00
}
this - > ChildSlot
[
WrapperWidget
] ;
2024-06-28 10:11:23 -04:00
this - > SetDesiredSizeScale ( FVector2d ( 1.0f , 1.2f ) ) ;
2024-06-04 11:58:57 -04:00
}
2024-06-28 10:11:23 -04:00
int32 SMaterialSubstrateTreeItem : : OnPaint ( const FPaintArgs & Args , const FGeometry & AllottedGeometry , const FSlateRect & MyCullingRect , FSlateWindowElementList & OutDrawElements , int32 LayerId , const FWidgetStyle & InWidgetStyle , bool bParentEnabled ) const
2024-06-04 11:58:57 -04:00
{
2024-06-28 10:11:23 -04:00
const FSlateBrush * BackgroundBrushResource = Tree - > BackgroundBrush . Get ( ) ;
const int32 IndentLevel = GetIndentLevel ( ) ;
// calculate children + self size
int NumStackChildren = 0 ;
for ( TSharedPtr < FSortedParamData > Child : this - > StackParameterData - > Children )
{
if ( Child - > StackDataType = = Stack )
NumStackChildren + + ;
}
float HeightAdjFactor = 1 ;
2024-06-04 11:58:57 -04:00
2024-06-28 10:11:23 -04:00
LayerId + = IndentLevel ;
if ( IsItemExpanded ( ) )
{
HeightAdjFactor = NumStackChildren + 1 ;
}
FVector2d OuterBorderSize = AllottedGeometry . GetLocalSize ( ) * FVector2d ( 1 , HeightAdjFactor ) ;
static float OffsetX = 30.0f ;
FVector2D Offset = FVector2D ( OffsetX * ( IndentLevel + 1 ) , 0.0f ) ;
2024-06-04 11:58:57 -04:00
FSlateDrawElement : : MakeBox (
2024-06-28 10:11:23 -04:00
OutDrawElements ,
+ + LayerId ,
AllottedGeometry . ToPaintGeometry ( OuterBorderSize - Offset , FSlateLayoutTransform ( Offset / 2 ) ) ,
BackgroundBrushResource ,
ESlateDrawEffect : : None ,
FStyleColors : : Black . GetSpecifiedColor ( ) * InWidgetStyle . GetColorAndOpacityTint ( )
2024-06-04 11:58:57 -04:00
) ;
2024-06-28 10:11:23 -04:00
// only need to draw gray part for first level
if ( IndentLevel < = 0 )
{
Offset = FVector2d ( OffsetX , - 5.0f ) ;
FSlateDrawElement : : MakeBox (
OutDrawElements ,
+ + LayerId ,
AllottedGeometry . ToPaintGeometry ( OuterBorderSize - Offset , FSlateLayoutTransform ( Offset / 2 ) ) ,
BackgroundBrushResource ,
ESlateDrawEffect : : None ,
FStyleColors : : Header . GetSpecifiedColor ( ) * InWidgetStyle . GetColorAndOpacityTint ( )
) ;
}
OffsetX = 20.0f ;
const float ReductionFactorX = 50.0f ;
const float ReductionFactorY = 15.0f ;
Offset = FVector2d ( OffsetX * IndentLevel + ReductionFactorX , ReductionFactorY ) ;
FGeometry BorderGeom = AllottedGeometry . MakeChild ( AllottedGeometry . GetLocalSize ( ) - Offset , FSlateLayoutTransform ( Offset / 2 ) ) ;
return STableRow < TSharedPtr < FSortedParamData > > : : OnPaint ( Args , BorderGeom , MyCullingRect , OutDrawElements , LayerId + 1 , InWidgetStyle , bParentEnabled ) ;
2024-06-04 11:58:57 -04:00
}
2024-06-28 10:11:23 -04:00
2024-06-04 11:58:57 -04:00
FString SMaterialSubstrateTreeItem : : GetInstancePath ( SMaterialSubstrateTree * InTree ) const
{
2024-06-19 13:54:35 -04:00
int32 LayerFuncIndex = Tree - > FunctionInstance - > GetLayerFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
int32 BlendFuncIndex = Tree - > FunctionInstance - > GetBlendFuncIndex ( StackParameterData - > ParameterInfo . Index ) ;
2024-06-04 11:58:57 -04:00
FString InstancePath ;
2024-06-19 13:54:35 -04:00
if ( StackParameterData - > ParameterInfo . Association = = EMaterialParameterAssociation : : BlendParameter & & InTree - > FunctionInstance - > Blends . IsValidIndex ( BlendFuncIndex ) )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
InstancePath = InTree - > FunctionInstance - > Blends [ BlendFuncIndex ] - > GetPathName ( ) ;
2024-06-04 11:58:57 -04:00
}
2024-06-19 13:54:35 -04:00
else if ( StackParameterData - > ParameterInfo . Association = = EMaterialParameterAssociation : : LayerParameter & & InTree - > FunctionInstance - > Layers . IsValidIndex ( LayerFuncIndex ) )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
InstancePath = InTree - > FunctionInstance - > Layers [ LayerFuncIndex ] - > GetPathName ( ) ;
2024-06-04 11:58:57 -04:00
}
return InstancePath ;
}
2024-06-28 10:11:23 -04:00
TSharedPtr < SWidget > SMaterialSubstrateTree : : CreateContextMenu ( )
{
const bool bCloseAfterSelection = true ;
FMenuBuilder MenuBuilder ( bCloseAfterSelection , TSharedPtr < FUICommandList > ( ) ) ;
TArray < FSortedParamDataPtr > SelectedItemsArray = GetSelectedItems ( ) ;
if ( SelectedItemsArray . Num ( ) > 0 )
{
FSortedParamDataPtr StackParameterData = SelectedItemsArray [ 0 ] ;
2024-07-15 05:42:13 -04:00
bool bCanAppendSubLayer = FunctionInstance - > CanAppendLayerNode ( StackParameterData - > ParameterInfo . Index ) ;
bool bCanRemoveLayer = FunctionInstance - > CanRemoveLayerNode ( StackParameterData - > ParameterInfo . Index ) ;
2024-06-28 10:11:23 -04:00
if ( bCanAppendSubLayer )
{
const FSlateIcon PlusIcon ( FAppStyle : : GetAppStyleSetName ( ) , " Plus " ) ;
2024-07-18 08:44:48 -04:00
MenuBuilder . AddMenuEntry ( LOCTEXT ( " AddNewLayer " , " Add New Layer " ) , FText ( ) , PlusIcon , FUIAction ( FExecuteAction : : CreateSP ( this , & SMaterialSubstrateTree : : AddNodeLayer , StackParameterData - > ParameterInfo . Index ) ) ) ;
2024-06-28 10:11:23 -04:00
}
if ( bCanRemoveLayer )
{
const FSlateIcon MinusIcon ( FAppStyle : : GetAppStyleSetName ( ) , " Icons.Minus " ) ;
2024-07-18 08:44:48 -04:00
MenuBuilder . AddMenuEntry ( LOCTEXT ( " RemoveLayer " , " Remove Layer " ) , FText ( ) , MinusIcon , FUIAction ( FExecuteAction : : CreateSP ( this , & SMaterialSubstrateTree : : RemoveNodeLayer , StackParameterData - > ParameterInfo . Index ) ) ) ;
2024-06-28 10:11:23 -04:00
}
}
return MenuBuilder . MakeWidget ( ) ;
}
2024-06-04 11:58:57 -04:00
void SMaterialSubstrateTree : : Construct ( const FArguments & InArgs )
{
ColumnSizeData . SetValueColumnWidth ( 0.5f ) ;
MaterialEditorInstance = InArgs . _InMaterialEditorInstance ;
2024-08-07 06:49:03 -04:00
Generator = InArgs . _InGenerator ;
2024-06-04 11:58:57 -04:00
Wrapper = InArgs . _InWrapper ;
ShowHiddenDelegate = InArgs . _InShowHiddenDelegate ;
CreateGroupsWidget ( ) ;
# if WITH_EDITOR
//Fixup for adding new bool arrays to the class
if ( FunctionInstance )
{
if ( FunctionInstance - > Layers . Num ( ) ! = FunctionInstance - > EditorOnly . RestrictToLayerRelatives . Num ( ) )
{
int32 OriginalSize = FunctionInstance - > EditorOnly . RestrictToLayerRelatives . Num ( ) ;
for ( int32 LayerIt = 0 ; LayerIt < FunctionInstance - > Layers . Num ( ) - OriginalSize ; LayerIt + + )
{
FunctionInstance - > EditorOnly . RestrictToLayerRelatives . Add ( false ) ;
}
}
if ( FunctionInstance - > Blends . Num ( ) ! = FunctionInstance - > EditorOnly . RestrictToBlendRelatives . Num ( ) )
{
int32 OriginalSize = FunctionInstance - > EditorOnly . RestrictToBlendRelatives . Num ( ) ;
for ( int32 BlendIt = 0 ; BlendIt < FunctionInstance - > Blends . Num ( ) - OriginalSize ; BlendIt + + )
{
FunctionInstance - > EditorOnly . RestrictToBlendRelatives . Add ( false ) ;
}
}
}
# endif
STreeView < TSharedPtr < FSortedParamData > > : : Construct (
STreeView : : FArguments ( )
. TreeItemsSource ( & LayerProperties )
2024-06-28 10:11:23 -04:00
. OnContextMenuOpening ( this , & SMaterialSubstrateTree : : CreateContextMenu )
2024-06-04 11:58:57 -04:00
. SelectionMode ( ESelectionMode : : Single )
. OnSelectionChanged ( this , & SMaterialSubstrateTree : : OnSelectionChangedMaterialSubstrateView )
. OnGenerateRow ( this , & SMaterialSubstrateTree : : OnGenerateRowMaterialLayersFunctionsTreeView )
. OnGetChildren ( this , & SMaterialSubstrateTree : : OnGetChildrenMaterialLayersFunctionsTreeView )
. OnExpansionChanged ( this , & SMaterialSubstrateTree : : OnExpansionChanged )
) ;
SetParentsExpansionState ( ) ;
}
void SMaterialSubstrateTree : : OnSelectionChangedMaterialSubstrateView ( TSharedPtr < FSortedParamData > InSelectedItem , ESelectInfo : : Type SelectInfo )
{
2024-08-07 06:49:03 -04:00
if ( MaterialEditorInstance - > IsA < UMaterialEditorInstanceConstant > ( ) )
{
UMaterialEditorInstanceConstant * MaterialEditorInstanceConstant = Cast < UMaterialEditorInstanceConstant > ( MaterialEditorInstance ) ;
if ( TSharedPtr < IDetailsView > DetailsViewPinned = MaterialEditorInstanceConstant - > DetailsView . Pin ( ) )
{
DetailsViewPinned - > ForceRefresh ( ) ;
}
}
2024-06-04 11:58:57 -04:00
}
TSharedRef < ITableRow > SMaterialSubstrateTree : : OnGenerateRowMaterialLayersFunctionsTreeView ( TSharedPtr < FSortedParamData > Item , const TSharedRef < STableViewBase > & OwnerTable )
{
TSharedRef < SMaterialSubstrateTreeItem > ReturnRow = SNew ( SMaterialSubstrateTreeItem , OwnerTable )
. StackParameterData ( Item )
. MaterialEditorInstance ( MaterialEditorInstance )
. InTree ( this ) ;
return ReturnRow ;
}
void SMaterialSubstrateTree : : OnGetChildrenMaterialLayersFunctionsTreeView ( TSharedPtr < FSortedParamData > InParent , TArray < TSharedPtr < FSortedParamData > > & OutChildren )
{
OutChildren = InParent - > Children ;
}
void SMaterialSubstrateTree : : OnExpansionChanged ( TSharedPtr < FSortedParamData > Item , bool bIsExpanded )
{
2024-08-07 06:49:03 -04:00
UMaterialInterface * MaterialInterface = MaterialEditorInstance - > GetMaterialInterface ( ) ;
bool * ExpansionValue = MaterialInterface - > LayerParameterExpansion . Find ( Item - > NodeKey ) ;
2024-06-04 11:58:57 -04:00
if ( ExpansionValue = = nullptr )
{
2024-08-07 06:49:03 -04:00
MaterialInterface - > LayerParameterExpansion . Add ( Item - > NodeKey , bIsExpanded ) ;
2024-06-04 11:58:57 -04:00
}
else if ( * ExpansionValue ! = bIsExpanded )
{
2024-08-07 06:49:03 -04:00
MaterialInterface - > LayerParameterExpansion . Emplace ( Item - > NodeKey , bIsExpanded ) ;
2024-06-04 11:58:57 -04:00
}
// Expand any children that are also expanded
for ( auto Child : Item - > Children )
{
2024-08-07 06:49:03 -04:00
bool * ChildExpansionValue = MaterialInterface - > LayerParameterExpansion . Find ( Child - > NodeKey ) ;
2024-06-04 11:58:57 -04:00
if ( ChildExpansionValue ! = nullptr & & * ChildExpansionValue = = true )
{
SetItemExpansion ( Child , true ) ;
}
}
}
void SMaterialSubstrateTree : : SetParentsExpansionState ( )
{
2024-08-07 06:49:03 -04:00
UMaterialInterface * MaterialInterface = MaterialEditorInstance - > GetMaterialInterface ( ) ;
2024-06-04 11:58:57 -04:00
for ( const auto & Pair : LayerProperties )
{
if ( Pair - > Children . Num ( ) )
{
2024-08-07 06:49:03 -04:00
bool * bIsExpanded = MaterialInterface - > LayerParameterExpansion . Find ( Pair - > NodeKey ) ;
2024-06-04 11:58:57 -04:00
if ( bIsExpanded )
{
SetItemExpansion ( Pair , * bIsExpanded ) ;
}
}
}
}
2024-06-19 13:54:35 -04:00
void SMaterialSubstrateTree : : RefreshOnAssetChange ( const struct FAssetData & InAssetData , int32 InNodeId , EMaterialParameterAssociation MaterialType )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
auto NodePayload = FunctionInstance - > GetNodePayload ( InNodeId ) ;
int32 Index = ( MaterialType = = EMaterialParameterAssociation : : BlendParameter ? NodePayload . Blend : NodePayload . Layer ) ;
// Early exit no op if the index for the asset modified is not valid
if ( Index < 0 )
return ;
2024-06-04 11:58:57 -04:00
FMaterialPropertyHelpers : : OnMaterialLayerAssetChanged ( InAssetData , Index , MaterialType , FunctionInstanceHandle , FunctionInstance ) ;
//set their overrides back to 0
MaterialEditorInstance - > CleanParameterStack ( Index , MaterialType ) ;
CreateGroupsWidget ( ) ;
MaterialEditorInstance - > ResetOverrides ( Index , MaterialType ) ;
RequestTreeRefresh ( ) ;
}
void SMaterialSubstrateTree : : ResetAssetToDefault ( TSharedPtr < FSortedParamData > InData )
{
2024-08-07 06:49:03 -04:00
if ( MaterialEditorInstance - > IsA < UMaterialEditorInstanceConstant > ( ) )
{
FMaterialPropertyHelpers : : ResetLayerAssetToDefault ( InData - > Parameter , InData - > ParameterInfo . Association , InData - > ParameterInfo . Index , Cast < UMaterialEditorInstanceConstant > ( MaterialEditorInstance ) ) ;
UpdateThumbnailMaterial ( InData - > ParameterInfo . Association , InData - > ParameterInfo . Index , false ) ;
CreateGroupsWidget ( ) ;
RequestTreeRefresh ( ) ;
}
2024-06-04 11:58:57 -04:00
}
2024-06-19 13:54:35 -04:00
void SMaterialSubstrateTree : : AddNodeLayer ( int32 InParent )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
/// Only if can really add a sub layer!
if ( ! FunctionInstance - > CanAppendLayerNode ( InParent ) )
return ;
const FScopedTransaction Transaction ( LOCTEXT ( " AddLayer " , " Add a new Layer in the tree " ) ) ;
2024-06-04 11:58:57 -04:00
FunctionInstanceHandle - > NotifyPreChange ( ) ;
2024-06-19 13:54:35 -04:00
// Create a new node
FunctionInstance - > AppendLayerNode ( InParent ) ;
2024-06-04 11:58:57 -04:00
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ArrayAdd ) ;
CreateGroupsWidget ( ) ;
RequestTreeRefresh ( ) ;
}
2024-06-19 13:54:35 -04:00
void SMaterialSubstrateTree : : RemoveNodeLayer ( int32 InNodeId )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
/// Only if can really remove a sub layer!
if ( ! FunctionInstance - > CanRemoveLayerNode ( InNodeId ) )
return ;
2024-06-04 11:58:57 -04:00
const FScopedTransaction Transaction ( LOCTEXT ( " RemoveLayerAndBlend " , " Remove a Layer and the attached Blend " ) ) ;
FunctionInstanceHandle - > NotifyPreChange ( ) ;
2024-06-19 13:54:35 -04:00
// Remove the node
auto NodePayload = FunctionInstance - > GetNodePayload ( InNodeId ) ;
FunctionInstance - > RemoveLayerNodeAt ( InNodeId ) ;
2024-08-07 06:49:03 -04:00
if ( MaterialEditorInstance - > IsA < UMaterialEditorInstanceConstant > ( ) )
{
UMaterialEditorInstanceConstant * MaterialEditorInstanceConstant = Cast < UMaterialEditorInstanceConstant > ( MaterialEditorInstance ) ;
if ( MaterialEditorInstanceConstant & & MaterialEditorInstanceConstant - > SourceInstance )
{
MaterialEditorInstanceConstant - > SourceInstance - > RemoveLayerParameterIndex ( NodePayload . Layer ) ;
}
}
2024-06-04 11:58:57 -04:00
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ArrayRemove ) ;
CreateGroupsWidget ( ) ;
RequestTreeRefresh ( ) ;
}
FReply SMaterialSubstrateTree : : UnlinkLayer ( int32 Index )
{
const FScopedTransaction Transaction ( LOCTEXT ( " UnlinkLayerFromParent " , " Unlink a layer from the parent " ) ) ;
FunctionInstanceHandle - > NotifyPreChange ( ) ;
FunctionInstance - > UnlinkLayerFromParent ( Index ) ;
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
CreateGroupsWidget ( ) ;
return FReply : : Handled ( ) ;
}
FReply SMaterialSubstrateTree : : RelinkLayersToParent ( )
{
const FScopedTransaction Transaction ( LOCTEXT ( " RelinkLayersToParent " , " Relink layers to parent " ) ) ;
FunctionInstanceHandle - > NotifyPreChange ( ) ;
FunctionInstance - > RelinkLayersToParent ( ) ;
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
MaterialEditorInstance - > RegenerateArrays ( ) ;
CreateGroupsWidget ( ) ;
return FReply : : Handled ( ) ;
}
EVisibility SMaterialSubstrateTree : : GetUnlinkLayerVisibility ( int32 Index ) const
{
2024-08-07 06:49:03 -04:00
if ( FunctionInstance - > IsLayerLinkedToParent ( Index ) & & MaterialEditorInstance - > IsA < UMaterialEditorInstanceConstant > ( ) )
2024-06-04 11:58:57 -04:00
{
return EVisibility : : Visible ;
}
return EVisibility : : Collapsed ;
}
EVisibility SMaterialSubstrateTree : : GetRelinkLayersToParentVisibility ( ) const
{
if ( FunctionInstance - > HasAnyUnlinkedLayers ( ) )
{
return EVisibility : : Visible ;
}
return EVisibility : : Collapsed ;
}
FReply SMaterialSubstrateTree : : ToggleLayerVisibility ( int32 Index )
{
if ( ! FSlateApplication : : Get ( ) . GetModifierKeys ( ) . AreModifersDown ( EModifierKey : : Alt ) )
{
bLayerIsolated = false ;
const FScopedTransaction Transaction ( LOCTEXT ( " ToggleLayerAndBlendVisibility " , " Toggles visibility for a blended layer " ) ) ;
FunctionInstanceHandle - > NotifyPreChange ( ) ;
FunctionInstance - > ToggleBlendedLayerVisibility ( Index ) ;
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
CreateGroupsWidget ( ) ;
return FReply : : Handled ( ) ;
}
else
{
const FScopedTransaction Transaction ( LOCTEXT ( " ToggleLayerAndBlendVisibility " , " Toggles visibility for a blended layer " ) ) ;
FunctionInstanceHandle - > NotifyPreChange ( ) ;
if ( FunctionInstance - > GetLayerVisibility ( Index ) = = false )
{
// Reset if clicking on a disabled layer
FunctionInstance - > SetBlendedLayerVisibility ( Index , true ) ;
bLayerIsolated = false ;
}
for ( int32 LayerIt = 1 ; LayerIt < FunctionInstance - > EditorOnly . LayerStates . Num ( ) ; LayerIt + + )
{
if ( LayerIt ! = Index )
{
FunctionInstance - > SetBlendedLayerVisibility ( LayerIt , bLayerIsolated ) ;
}
}
bLayerIsolated = ! bLayerIsolated ;
FunctionInstanceHandle - > NotifyPostChange ( EPropertyChangeType : : ValueSet ) ;
CreateGroupsWidget ( ) ;
return FReply : : Handled ( ) ;
}
}
TSharedPtr < class FAssetThumbnailPool > SMaterialSubstrateTree : : GetTreeThumbnailPool ( )
{
return UThumbnailManager : : Get ( ) . GetSharedThumbnailPool ( ) ;
}
TSharedPtr < IDetailTreeNode > SMaterialSubstrateTree : : FindParameterGroupsNode ( TSharedPtr < IPropertyRowGenerator > PropertyRowGenerator )
{
const TArray < TSharedRef < IDetailTreeNode > > RootNodes = PropertyRowGenerator - > GetRootTreeNodes ( ) ;
if ( RootNodes . Num ( ) > 0 )
{
TSharedPtr < IDetailTreeNode > Category = RootNodes [ 0 ] ;
TArray < TSharedRef < IDetailTreeNode > > Children ;
Category - > GetChildren ( Children ) ;
for ( int32 ChildIdx = 0 ; ChildIdx < Children . Num ( ) ; ChildIdx + + )
{
TSharedPtr < IPropertyHandle > PropertyHandle = Children [ ChildIdx ] - > CreatePropertyHandle ( ) ;
if ( PropertyHandle . IsValid ( ) & & PropertyHandle - > GetProperty ( ) & & PropertyHandle - > GetProperty ( ) - > GetName ( ) = = " ParameterGroups " )
{
return Children [ ChildIdx ] ;
}
}
}
return nullptr ;
}
2024-06-19 13:54:35 -04:00
struct FRecursiveCreateWidgetsContext
{
UDEditorParameterValue * Parameter ;
TSharedPtr < IPropertyHandle > LayerHandle ;
TSharedPtr < IPropertyHandle > BlendHandle ;
} ;
2024-07-15 05:42:13 -04:00
void SMaterialSubstrateTree : : RecursiveCreateWidgets ( FRecursiveCreateWidgetsContext * InContext , FNodeId InNodeId , TArray < TSharedPtr < FSortedParamData > > & InParentContainer , bool GenerateChildren )
2024-06-19 13:54:35 -04:00
{
auto Payload = FunctionInstance - > Tree . Payloads [ InNodeId ] ;
TSharedRef < FSortedParamData > StackProperty = MakeShared < FSortedParamData > ( ) ;
StackProperty - > StackDataType = EStackDataType : : Stack ;
StackProperty - > Parameter = InContext - > Parameter ;
StackProperty - > ParameterInfo . Index = InNodeId ;
StackProperty - > NodeKey = FString : : FromInt ( StackProperty - > ParameterInfo . Index ) ;
if ( GenerateChildren )
{
// Sub layers
auto RootChildren = FunctionInstance - > GetNodeChildren ( InNodeId ) ;
for ( int i = 0 ; i < RootChildren . Num ( ) ; + + i )
{
2024-07-15 05:42:13 -04:00
int Index = i ;
Index = RootChildren . Num ( ) - 1 - i ; // Reverse the order to display the layers bottom up
RecursiveCreateWidgets ( InContext , RootChildren [ Index ] , StackProperty - > Children , false ) ;
2024-06-19 13:54:35 -04:00
}
}
if ( Payload . Layer ! = - 1 )
{
TSharedRef < FSortedParamData > ChildProperty = MakeShared < FSortedParamData > ( ) ;
ChildProperty - > StackDataType = EStackDataType : : Asset ;
ChildProperty - > Parameter = InContext - > Parameter ;
ChildProperty - > ParameterHandle = InContext - > LayerHandle - > AsArray ( ) - > GetElement ( Payload . Layer ) ;
ChildProperty - > ParameterNode = Generator - > FindTreeNode ( ChildProperty - > ParameterHandle ) ;
ChildProperty - > ParameterInfo . Index = Payload . Layer ;
ChildProperty - > ParameterInfo . Association = EMaterialParameterAssociation : : LayerParameter ;
ChildProperty - > NodeKey = FString : : FromInt ( ChildProperty - > ParameterInfo . Index ) + FString : : FromInt ( ChildProperty - > ParameterInfo . Association ) ;
{
UObject * AssetObject = nullptr ;
ChildProperty - > ParameterHandle - > GetValue ( AssetObject ) ;
if ( AssetObject )
{
if ( MaterialEditorInstance - > StoredLayerPreviews [ Payload . Layer ] = = nullptr )
{
MaterialEditorInstance - > StoredLayerPreviews [ Payload . Layer ] = ( NewObject < UMaterialInstanceConstant > ( MaterialEditorInstance , NAME_None ) ) ;
}
UMaterialInterface * EditedMaterial = Cast < UMaterialFunctionInterface > ( AssetObject ) - > GetPreviewMaterial ( ) ;
if ( MaterialEditorInstance - > StoredLayerPreviews [ Payload . Layer ] & & MaterialEditorInstance - > StoredLayerPreviews [ Payload . Layer ] - > Parent ! = EditedMaterial )
{
MaterialEditorInstance - > StoredLayerPreviews [ Payload . Layer ] - > SetParentEditorOnly ( EditedMaterial ) ;
}
}
}
StackProperty - > Children . Add ( ChildProperty ) ;
2024-06-26 11:40:26 -04:00
ShowSubParameters ( ChildProperty ) ;
2024-06-19 13:54:35 -04:00
}
2024-07-15 05:42:13 -04:00
if ( Payload . Blend ! = - 1 )
2024-06-19 13:54:35 -04:00
{
TSharedRef < FSortedParamData > ChildProperty = MakeShared < FSortedParamData > ( ) ;
ChildProperty - > StackDataType = EStackDataType : : Asset ;
ChildProperty - > Parameter = InContext - > Parameter ;
ChildProperty - > ParameterHandle = InContext - > BlendHandle - > AsArray ( ) - > GetElement ( Payload . Blend ) ;
ChildProperty - > ParameterNode = Generator - > FindTreeNode ( ChildProperty - > ParameterHandle ) ;
ChildProperty - > ParameterInfo . Index = Payload . Blend ;
ChildProperty - > ParameterInfo . Association = EMaterialParameterAssociation : : BlendParameter ;
ChildProperty - > NodeKey = FString : : FromInt ( ChildProperty - > ParameterInfo . Index ) + FString : : FromInt ( ChildProperty - > ParameterInfo . Association ) ;
{
UObject * AssetObject = nullptr ;
ChildProperty - > ParameterHandle - > GetValue ( AssetObject ) ;
if ( AssetObject )
{
if ( MaterialEditorInstance - > StoredBlendPreviews [ Payload . Blend ] = = nullptr )
{
MaterialEditorInstance - > StoredBlendPreviews [ Payload . Blend ] = ( NewObject < UMaterialInstanceConstant > ( MaterialEditorInstance , NAME_None ) ) ;
}
UMaterialInterface * EditedMaterial = Cast < UMaterialFunctionInterface > ( AssetObject ) - > GetPreviewMaterial ( ) ;
if ( MaterialEditorInstance - > StoredBlendPreviews [ Payload . Blend ] & & MaterialEditorInstance - > StoredBlendPreviews [ Payload . Blend ] - > Parent ! = EditedMaterial )
{
MaterialEditorInstance - > StoredBlendPreviews [ Payload . Blend ] - > SetParentEditorOnly ( EditedMaterial ) ;
}
}
}
StackProperty - > Children . Add ( ChildProperty ) ;
2024-06-26 11:40:26 -04:00
ShowSubParameters ( ChildProperty ) ;
2024-06-19 13:54:35 -04:00
}
InParentContainer . Add ( StackProperty ) ;
}
2024-06-04 11:58:57 -04:00
void SMaterialSubstrateTree : : CreateGroupsWidget ( )
{
check ( MaterialEditorInstance ) ;
2024-08-07 06:49:03 -04:00
if ( MaterialEditorInstance - > IsA < UMaterialEditorInstanceConstant > ( ) )
{
MaterialEditorInstance - > RegenerateArrays ( ) ;
}
2024-06-04 11:58:57 -04:00
NonLayerProperties . Empty ( ) ;
LayerProperties . Empty ( ) ;
FunctionParameter = nullptr ;
2024-06-26 11:40:26 -04:00
TSharedPtr < IPropertyHandle > FunctionParameterHandle ;
2024-06-04 11:58:57 -04:00
FPropertyEditorModule & Module = FModuleManager : : LoadModuleChecked < FPropertyEditorModule > ( " PropertyEditor " ) ;
2024-08-07 06:49:03 -04:00
2024-06-04 11:58:57 -04:00
if ( ! Generator . IsValid ( ) )
{
FPropertyRowGeneratorArgs Args ;
Generator = Module . CreatePropertyRowGenerator ( Args ) ;
// the sizes of the parameter lists are only based on the parent material and not changed out from under the details panel
// When a parameter is added open MI editors are refreshed
// the tree should also refresh if one of the layer or blend assets is swapped
auto ValidationLambda = ( [ ] ( const FRootPropertyNodeList & PropertyNodeList ) { return true ; } ) ;
Generator - > SetCustomValidatePropertyNodesFunction ( FOnValidatePropertyRowGeneratorNodes : : CreateLambda ( MoveTemp ( ValidationLambda ) ) ) ;
TArray < UObject * > Objects ;
Objects . Add ( MaterialEditorInstance ) ;
Generator - > SetObjects ( Objects ) ;
}
else
{
TArray < UObject * > Objects ;
Objects . Add ( MaterialEditorInstance ) ;
Generator - > SetObjects ( Objects ) ;
}
2024-08-07 06:49:03 -04:00
2024-06-26 11:40:26 -04:00
2024-06-04 11:58:57 -04:00
TSharedPtr < IDetailTreeNode > ParameterGroups = FindParameterGroupsNode ( Generator ) ;
if ( ParameterGroups . IsValid ( ) )
{
TArray < TSharedRef < IDetailTreeNode > > Children ;
ParameterGroups - > GetChildren ( Children ) ;
// the order of DeferredSearches should correspond to NonLayerProperties exactly
TArray < TSharedPtr < IPropertyHandle > > DeferredSearches ;
for ( int32 GroupIdx = 0 ; GroupIdx < Children . Num ( ) ; + + GroupIdx )
{
TArray < void * > GroupPtrs ;
TSharedPtr < IPropertyHandle > ChildHandle = Children [ GroupIdx ] - > CreatePropertyHandle ( ) ;
ChildHandle - > AccessRawData ( GroupPtrs ) ;
auto GroupIt = GroupPtrs . CreateConstIterator ( ) ;
const FEditorParameterGroup * ParameterGroupPtr = reinterpret_cast < FEditorParameterGroup * > ( * GroupIt ) ;
const FEditorParameterGroup & ParameterGroup = * ParameterGroupPtr ;
for ( int32 ParamIdx = 0 ; ParamIdx < ParameterGroup . Parameters . Num ( ) ; ParamIdx + + )
{
UDEditorParameterValue * Parameter = ParameterGroup . Parameters [ ParamIdx ] ;
TSharedPtr < IPropertyHandle > ParametersArrayProperty = ChildHandle - > GetChildHandle ( " Parameters " ) ;
TSharedPtr < IPropertyHandle > ParameterProperty = ParametersArrayProperty - > GetChildHandle ( ParamIdx ) ;
TSharedPtr < IPropertyHandle > ParameterValueProperty = ParameterProperty - > GetChildHandle ( " ParameterValue " ) ;
if ( Cast < UDEditorMaterialLayersParameterValue > ( Parameter ) )
{
2024-06-26 11:40:26 -04:00
FunctionParameterHandle = ChildHandle ;
2024-06-04 11:58:57 -04:00
if ( FunctionParameter = = nullptr )
{
FunctionParameter = Parameter ;
}
TArray < void * > StructPtrs ;
ParameterValueProperty - > AccessRawData ( StructPtrs ) ;
auto It = StructPtrs . CreateConstIterator ( ) ;
FunctionInstance = reinterpret_cast < FMaterialLayersFunctions * > ( * It ) ;
FunctionInstanceHandle = ParameterValueProperty ;
}
else
{
FUnsortedParamData NonLayerProperty ;
UDEditorScalarParameterValue * ScalarParam = Cast < UDEditorScalarParameterValue > ( Parameter ) ;
if ( ScalarParam & & ScalarParam - > SliderMax > ScalarParam - > SliderMin )
{
ParameterValueProperty - > SetInstanceMetaData ( " UIMin " , FString : : Printf ( TEXT ( " %f " ) , ScalarParam - > SliderMin ) ) ;
ParameterValueProperty - > SetInstanceMetaData ( " UIMax " , FString : : Printf ( TEXT ( " %f " ) , ScalarParam - > SliderMax ) ) ;
}
NonLayerProperty . Parameter = Parameter ;
NonLayerProperty . ParameterGroup = ParameterGroup ;
DeferredSearches . Add ( ParameterValueProperty ) ;
NonLayerProperty . UnsortedName = Parameter - > ParameterInfo . Name ;
NonLayerProperties . Add ( NonLayerProperty ) ;
}
}
}
checkf ( NonLayerProperties . Num ( ) = = DeferredSearches . Num ( ) , TEXT ( " Internal inconsistency: number of node searches does not match the number of properties " ) ) ;
TArray < TSharedPtr < IDetailTreeNode > > DeferredResults = Generator - > FindTreeNodes ( DeferredSearches ) ;
checkf ( NonLayerProperties . Num ( ) = = DeferredResults . Num ( ) , TEXT ( " Internal inconsistency: number of node search results does not match the number of properties " ) ) ;
for ( int Idx = 0 , NumUnsorted = NonLayerProperties . Num ( ) ; Idx < NumUnsorted ; + + Idx )
{
FUnsortedParamData & NonLayerProperty = NonLayerProperties [ Idx ] ;
NonLayerProperty . ParameterNode = DeferredResults [ Idx ] ;
NonLayerProperty . ParameterHandle = NonLayerProperty . ParameterNode - > CreatePropertyHandle ( ) ;
}
DeferredResults . Empty ( ) ;
DeferredSearches . Empty ( ) ;
2024-06-26 11:40:26 -04:00
// Create the hierarchy of Sorted items recursivelly following the LayerFunctions Tree
# ifdef ENABLE_MATERIAL_LAYER_PROTOTYPE
if ( FunctionParameterHandle )
2024-06-04 11:58:57 -04:00
{
2024-06-26 11:40:26 -04:00
TSharedPtr < IPropertyHandle > LayerHandle = FunctionParameterHandle - > GetChildHandle ( " Layers " ) . ToSharedRef ( ) ;
TSharedPtr < IPropertyHandle > BlendHandle = FunctionParameterHandle - > GetChildHandle ( " Blends " ) . ToSharedRef ( ) ;
uint32 NumLayerChildren ;
LayerHandle - > GetNumChildren ( NumLayerChildren ) ;
uint32 NumBlendChildren ;
BlendHandle - > GetNumChildren ( NumBlendChildren ) ;
if ( MaterialEditorInstance - > StoredLayerPreviews . Num ( ) ! = NumLayerChildren )
2024-06-04 11:58:57 -04:00
{
2024-06-26 11:40:26 -04:00
MaterialEditorInstance - > StoredLayerPreviews . Empty ( ) ;
MaterialEditorInstance - > StoredLayerPreviews . AddDefaulted ( NumLayerChildren ) ;
}
if ( MaterialEditorInstance - > StoredBlendPreviews . Num ( ) ! = NumBlendChildren )
{
MaterialEditorInstance - > StoredBlendPreviews . Empty ( ) ;
MaterialEditorInstance - > StoredBlendPreviews . AddDefaulted ( NumBlendChildren ) ;
}
// root
auto StrongFunctionParameter = FunctionParameter . Pin ( ) ;
FRecursiveCreateWidgetsContext Context {
. Parameter = StrongFunctionParameter . Get ( ) ,
. LayerHandle = LayerHandle ,
. BlendHandle = BlendHandle
} ;
auto RootChildren = FunctionInstance - > GetNodeChildren ( - 1 ) ;
for ( int i = 0 ; i < RootChildren . Num ( ) ; + + i )
{
2024-07-15 05:42:13 -04:00
int Index = i ;
Index = RootChildren . Num ( ) - 1 - i ; // Reverse the order to display the layers bottom up
RecursiveCreateWidgets ( & Context , RootChildren [ Index ] , LayerProperties , true ) ;
2024-06-04 11:58:57 -04:00
}
}
2024-06-26 11:40:26 -04:00
# endif // ENABLE_MATERIAL_LAYER_PROTOTYPE
2024-06-04 11:58:57 -04:00
}
2024-06-26 11:40:26 -04:00
2024-06-04 11:58:57 -04:00
SetParentsExpansionState ( ) ;
}
bool SMaterialSubstrateTree : : IsLayerVisible ( int32 Index ) const
{
if ( FunctionParameter . IsValid ( ) )
{
return FunctionInstance - > GetLayerVisibility ( Index ) ;
}
return false ;
}
TSharedRef < SWidget > SMaterialSubstrateTree : : CreateThumbnailWidget ( EMaterialParameterAssociation InAssociation , int32 InIndex , float InThumbnailSize )
{
UObject * ThumbnailObject = nullptr ;
if ( InAssociation = = EMaterialParameterAssociation : : LayerParameter )
{
ThumbnailObject = MaterialEditorInstance - > StoredLayerPreviews [ InIndex ] ;
}
else if ( InAssociation = = EMaterialParameterAssociation : : BlendParameter )
{
ThumbnailObject = MaterialEditorInstance - > StoredBlendPreviews [ InIndex ] ;
}
const TSharedPtr < FAssetThumbnail > AssetThumbnail = MakeShareable ( new FAssetThumbnail ( ThumbnailObject , InThumbnailSize , InThumbnailSize , GetTreeThumbnailPool ( ) ) ) ;
TSharedRef < SWidget > ThumbnailWidget = AssetThumbnail - > MakeThumbnailWidget ( ) ;
AssetThumbnail - > SetRealTime ( true ) ;
ThumbnailWidget - > SetOnMouseDoubleClick ( FPointerEventHandler : : CreateSP ( this , & SMaterialSubstrateTree : : OnThumbnailDoubleClick , InAssociation , InIndex ) ) ;
return ThumbnailWidget ;
}
void SMaterialSubstrateTree : : UpdateThumbnailMaterial ( TEnumAsByte < EMaterialParameterAssociation > InAssociation , int32 InIndex , bool bAlterBlendIndex )
{
UMaterialInstanceConstant * MaterialToUpdate = nullptr ;
int32 ParameterIndex = InIndex ;
if ( InAssociation = = EMaterialParameterAssociation : : LayerParameter )
{
MaterialToUpdate = MaterialEditorInstance - > StoredLayerPreviews [ ParameterIndex ] ;
}
if ( InAssociation = = EMaterialParameterAssociation : : BlendParameter )
{
if ( bAlterBlendIndex )
{
ParameterIndex - - ;
}
MaterialToUpdate = MaterialEditorInstance - > StoredBlendPreviews [ ParameterIndex ] ;
}
2024-07-15 05:42:13 -04:00
return ;
2024-06-19 13:54:35 -04:00
if ( MaterialToUpdate ! = nullptr )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
// Need to invert index b/c layer properties is generated in reverse order
2024-07-15 05:42:13 -04:00
TArray < TSharedPtr < FSortedParamData > > AssetChildren = LayerProperties [ LayerProperties . Num ( ) - 1 - InIndex ] - > Children ;
2024-06-19 13:54:35 -04:00
TArray < FEditorParameterGroup > ParameterGroups ;
for ( TSharedPtr < FSortedParamData > AssetChild : AssetChildren )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
for ( TSharedPtr < FSortedParamData > Group : AssetChild - > Children )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
if ( Group - > ParameterInfo . Association = = InAssociation )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
FEditorParameterGroup DuplicatedGroup = FEditorParameterGroup ( ) ;
DuplicatedGroup . GroupAssociation = Group - > Group . GroupAssociation ;
DuplicatedGroup . GroupName = Group - > Group . GroupName ;
DuplicatedGroup . GroupSortPriority = Group - > Group . GroupSortPriority ;
for ( UDEditorParameterValue * Parameter : Group - > Group . Parameters )
2024-06-04 11:58:57 -04:00
{
2024-06-19 13:54:35 -04:00
if ( Parameter - > ParameterInfo . Index = = ParameterIndex )
{
DuplicatedGroup . Parameters . Add ( Parameter ) ;
}
2024-06-04 11:58:57 -04:00
}
2024-06-19 13:54:35 -04:00
ParameterGroups . Add ( DuplicatedGroup ) ;
2024-06-04 11:58:57 -04:00
}
}
2024-06-19 13:54:35 -04:00
}
2024-06-04 11:58:57 -04:00
FMaterialPropertyHelpers : : TransitionAndCopyParameters ( MaterialToUpdate , ParameterGroups , true ) ;
}
}
FReply SMaterialSubstrateTree : : OnThumbnailDoubleClick ( const FGeometry & Geometry , const FPointerEvent & MouseEvent , EMaterialParameterAssociation InAssociation , int32 InIndex )
{
UMaterialFunctionInterface * AssetToOpen = nullptr ;
if ( InAssociation = = EMaterialParameterAssociation : : BlendParameter )
{
AssetToOpen = FunctionInstance - > Blends [ InIndex ] ;
}
else if ( InAssociation = = EMaterialParameterAssociation : : LayerParameter )
{
AssetToOpen = FunctionInstance - > Layers [ InIndex ] ;
}
if ( AssetToOpen ! = nullptr )
{
GEditor - > GetEditorSubsystem < UAssetEditorSubsystem > ( ) - > OpenEditorForAsset ( AssetToOpen ) ;
return FReply : : Handled ( ) ;
}
return FReply : : Unhandled ( ) ;
}
void SMaterialSubstrateTree : : ShowSubParameters ( TSharedPtr < FSortedParamData > ParentParameter )
{
for ( FUnsortedParamData Property : NonLayerProperties )
{
UDEditorParameterValue * Parameter = Property . Parameter ;
if ( Parameter - > ParameterInfo . Index = = ParentParameter - > ParameterInfo . Index
& & Parameter - > ParameterInfo . Association = = ParentParameter - > ParameterInfo . Association )
{
TSharedPtr < FSortedParamData > GroupProperty ( new FSortedParamData ( ) ) ;
GroupProperty - > StackDataType = EStackDataType : : Group ;
GroupProperty - > ParameterInfo . Index = Parameter - > ParameterInfo . Index ;
GroupProperty - > ParameterInfo . Association = Parameter - > ParameterInfo . Association ;
GroupProperty - > Group = Property . ParameterGroup ;
GroupProperty - > NodeKey = FString : : FromInt ( GroupProperty - > ParameterInfo . Index ) + FString : : FromInt ( GroupProperty - > ParameterInfo . Association ) + Property . ParameterGroup . GroupName . ToString ( ) ;
bool bAddNewGroup = true ;
for ( TSharedPtr < struct FSortedParamData > GroupChild : ParentParameter - > Children )
{
if ( GroupChild - > NodeKey = = GroupProperty - > NodeKey )
{
bAddNewGroup = false ;
}
}
if ( bAddNewGroup )
{
ParentParameter - > Children . Add ( GroupProperty ) ;
}
TSharedPtr < FSortedParamData > ChildProperty ( new FSortedParamData ( ) ) ;
ChildProperty - > StackDataType = EStackDataType : : Property ;
ChildProperty - > Parameter = Parameter ;
ChildProperty - > ParameterInfo . Index = Parameter - > ParameterInfo . Index ;
ChildProperty - > ParameterInfo . Association = Parameter - > ParameterInfo . Association ;
ChildProperty - > ParameterNode = Property . ParameterNode ;
ChildProperty - > PropertyName = Property . UnsortedName ;
ChildProperty - > NodeKey = FString : : FromInt ( ChildProperty - > ParameterInfo . Index ) + FString : : FromInt ( ChildProperty - > ParameterInfo . Association ) + Property . ParameterGroup . GroupName . ToString ( ) + Property . UnsortedName . ToString ( ) ;
UDEditorStaticComponentMaskParameterValue * CompMaskParam = Cast < UDEditorStaticComponentMaskParameterValue > ( Parameter ) ;
if ( ! CompMaskParam )
{
TArray < TSharedRef < IDetailTreeNode > > ParamChildren ;
Property . ParameterNode - > GetChildren ( ParamChildren ) ;
for ( int32 ParamChildIdx = 0 ; ParamChildIdx < ParamChildren . Num ( ) ; ParamChildIdx + + )
{
TSharedPtr < FSortedParamData > ParamChildProperty ( new FSortedParamData ( ) ) ;
ParamChildProperty - > StackDataType = EStackDataType : : PropertyChild ;
ParamChildProperty - > ParameterNode = ParamChildren [ ParamChildIdx ] ;
ParamChildProperty - > ParameterHandle = ParamChildProperty - > ParameterNode - > CreatePropertyHandle ( ) ;
ParamChildProperty - > ParameterInfo . Index = Parameter - > ParameterInfo . Index ;
ParamChildProperty - > ParameterInfo . Association = Parameter - > ParameterInfo . Association ;
ParamChildProperty - > Parameter = ChildProperty - > Parameter ;
ChildProperty - > Children . Add ( ParamChildProperty ) ;
}
}
for ( TSharedPtr < struct FSortedParamData > GroupChild : ParentParameter - > Children )
{
if ( GroupChild - > Group . GroupName = = Property . ParameterGroup . GroupName
& & GroupChild - > ParameterInfo . Association = = ChildProperty - > ParameterInfo . Association
& & GroupChild - > ParameterInfo . Index = = ChildProperty - > ParameterInfo . Index )
{
GroupChild - > Children . Add ( ChildProperty ) ;
}
}
}
}
}
# undef LOCTEXT_NAMESPACE