2014-12-07 19:09:38 -05:00
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "MaterialEditorModule.h"
2014-05-22 11:33:54 -04:00
# include "Materials/MaterialExpressionFunctionInput.h"
# include "Materials/MaterialExpressionFunctionOutput.h"
# include "Materials/MaterialExpressionStaticBoolParameter.h"
# include "Materials/MaterialExpressionStaticBool.h"
# include "Materials/MaterialExpressionStaticSwitch.h"
# include "Materials/MaterialExpressionComment.h"
# include "Materials/MaterialExpressionParameter.h"
# include "Materials/MaterialExpressionTextureSampleParameter.h"
# include "Materials/MaterialExpressionFontSampleParameter.h"
# include "Materials/MaterialExpressionScalarParameter.h"
# include "Materials/MaterialExpressionVectorParameter.h"
# include "Materials/MaterialExpressionStaticSwitchParameter.h"
# include "Materials/MaterialFunction.h"
2014-03-14 14:13:41 -04:00
# include "MaterialEditorUtilities.h"
# include "Toolkits/ToolkitManager.h"
# include "MaterialExpressionClasses.h"
2014-11-12 04:43:54 -05:00
# include "Materials/MaterialInstance.h"
2014-03-14 14:13:41 -04:00
# define LOCTEXT_NAMESPACE "MaterialEditorUtilities"
DEFINE_LOG_CATEGORY_STATIC ( LogMaterialEditorUtilities , Log , All ) ;
UMaterialExpression * FMaterialEditorUtilities : : CreateNewMaterialExpression ( const class UEdGraph * Graph , UClass * NewExpressionClass , const FVector2D & NodePos , bool bAutoSelect , bool bAutoAssignResource )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
return MaterialEditor - > CreateNewMaterialExpression ( NewExpressionClass , NodePos , bAutoSelect , bAutoAssignResource ) ;
}
return NULL ;
}
UMaterialExpressionComment * FMaterialEditorUtilities : : CreateNewMaterialExpressionComment ( const class UEdGraph * Graph , const FVector2D & NodePos )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
return MaterialEditor - > CreateNewMaterialExpressionComment ( NodePos ) ;
}
return NULL ;
}
void FMaterialEditorUtilities : : ForceRefreshExpressionPreviews ( const class UEdGraph * Graph )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > ForceRefreshExpressionPreviews ( ) ;
}
}
void FMaterialEditorUtilities : : AddToSelection ( const class UEdGraph * Graph , UMaterialExpression * Expression )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > AddToSelection ( Expression ) ;
}
}
void FMaterialEditorUtilities : : DeleteSelectedNodes ( const class UEdGraph * Graph )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > DeleteSelectedNodes ( ) ;
}
}
2014-11-25 17:51:09 -05:00
FText FMaterialEditorUtilities : : GetOriginalObjectName ( const class UEdGraph * Graph )
2014-03-14 14:13:41 -04:00
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
return MaterialEditor - > GetOriginalObjectName ( ) ;
}
2014-11-25 17:51:09 -05:00
return FText : : GetEmpty ( ) ;
2014-03-14 14:13:41 -04:00
}
void FMaterialEditorUtilities : : UpdateMaterialAfterGraphChange ( const class UEdGraph * Graph )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > UpdateMaterialAfterGraphChange ( ) ;
}
}
bool FMaterialEditorUtilities : : CanPasteNodes ( const class UEdGraph * Graph )
{
bool bCanPaste = false ;
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
bCanPaste = MaterialEditor - > CanPasteNodes ( ) ;
}
return bCanPaste ;
}
void FMaterialEditorUtilities : : PasteNodesHere ( class UEdGraph * Graph , const FVector2D & Location )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > PasteNodesHere ( Location ) ;
}
}
int32 FMaterialEditorUtilities : : GetNumberOfSelectedNodes ( const class UEdGraph * Graph )
{
int32 SelectedNodes = 0 ;
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
SelectedNodes = MaterialEditor - > GetNumberOfSelectedNodes ( ) ;
}
return SelectedNodes ;
}
void FMaterialEditorUtilities : : GetMaterialExpressionActions ( FGraphActionMenuBuilder & ActionMenuBuilder , bool bMaterialFunction )
{
// TODO: Not sure if this is necessary/usable anymore
// Get all menu extenders for this context menu from the material editor module
/*IMaterialEditorModule& MaterialEditor = FModuleManager::GetModuleChecked<IMaterialEditorModule>( TEXT("MaterialEditor") );
TArray < IMaterialEditorModule : : FMaterialMenuExtender > MenuExtenderDelegates = MaterialEditor . GetAllMaterialCanvasMenuExtenders ( ) ;
TArray < TSharedPtr < FExtender > > Extenders ;
for ( int32 i = 0 ; i < MenuExtenderDelegates . Num ( ) ; + + i )
{
if ( MenuExtenderDelegates [ i ] . IsBound ( ) )
{
Extenders . Add ( MenuExtenderDelegates [ i ] . Execute ( MaterialEditorPtr . Pin ( ) - > GetToolkitCommands ( ) ) ) ;
}
}
TSharedPtr < FExtender > MenuExtender = FExtender : : Combine ( Extenders ) ; */
bool bUseUnsortedMenus = false ;
MaterialExpressionClasses * ExpressionClasses = MaterialExpressionClasses : : Get ( ) ;
if ( bUseUnsortedMenus )
{
AddMaterialExpressionCategory ( ActionMenuBuilder , TEXT ( " " ) , & ExpressionClasses - > AllExpressionClasses , bMaterialFunction ) ;
}
else
{
// Add Favourite expressions as a category
const FText FavouritesCategory = LOCTEXT ( " FavoritesMenu " , " Favorites " ) ;
AddMaterialExpressionCategory ( ActionMenuBuilder , FavouritesCategory . ToString ( ) , & ExpressionClasses - > FavoriteExpressionClasses , bMaterialFunction ) ;
// Add each category to the menu
for ( int32 CategoryIndex = 0 ; CategoryIndex < ExpressionClasses - > CategorizedExpressionClasses . Num ( ) ; + + CategoryIndex )
{
FCategorizedMaterialExpressionNode * CategoryNode = & ( ExpressionClasses - > CategorizedExpressionClasses [ CategoryIndex ] ) ;
AddMaterialExpressionCategory ( ActionMenuBuilder , CategoryNode - > CategoryName , & CategoryNode - > MaterialExpressions , bMaterialFunction ) ;
}
if ( ExpressionClasses - > UnassignedExpressionClasses . Num ( ) > 0 )
{
AddMaterialExpressionCategory ( ActionMenuBuilder , TEXT ( " " ) , & ExpressionClasses - > UnassignedExpressionClasses , bMaterialFunction ) ;
}
}
}
bool FMaterialEditorUtilities : : IsMaterialExpressionInFavorites ( UMaterialExpression * InExpression )
{
return MaterialExpressionClasses : : Get ( ) - > IsMaterialExpressionInFavorites ( InExpression ) ;
}
FMaterialRenderProxy * FMaterialEditorUtilities : : GetExpressionPreview ( const class UEdGraph * Graph , UMaterialExpression * InExpression )
{
FMaterialRenderProxy * ExpressionPreview = NULL ;
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
ExpressionPreview = MaterialEditor - > GetExpressionPreview ( InExpression ) ;
}
return ExpressionPreview ;
}
void FMaterialEditorUtilities : : UpdateSearchResults ( const class UEdGraph * Graph )
{
TSharedPtr < class IMaterialEditor > MaterialEditor = GetIMaterialEditorForObject ( Graph ) ;
if ( MaterialEditor . IsValid ( ) )
{
MaterialEditor - > UpdateSearch ( false ) ;
}
}
/////////////////////////////////////////////////////
// Static functions moved from SMaterialEditorCanvas
2014-10-23 21:38:06 -04:00
void FMaterialEditorUtilities : : GetVisibleMaterialParameters ( const UMaterial * Material , UMaterialInstance * MaterialInstance , TArray < FGuid > & VisibleExpressions )
2014-03-14 14:13:41 -04:00
{
VisibleExpressions . Empty ( ) ;
2014-10-23 21:38:06 -04:00
TScopedPointer < FGetVisibleMaterialParametersFunctionState > FunctionState ( new FGetVisibleMaterialParametersFunctionState ( NULL ) ) ;
TArray < FGetVisibleMaterialParametersFunctionState * > FunctionStack ;
FunctionStack . Push ( FunctionState . GetOwnedPointer ( ) ) ;
2014-03-14 14:13:41 -04:00
for ( uint32 i = 0 ; i < MP_MAX ; + + i )
{
2014-10-08 15:27:19 -04:00
FExpressionInput * ExpressionInput = ( ( UMaterial * ) Material ) - > GetExpressionInputForProperty ( ( EMaterialProperty ) i ) ;
2014-03-14 14:13:41 -04:00
2014-10-08 15:27:19 -04:00
if ( ExpressionInput )
{
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( ExpressionInput - > Expression , ExpressionInput - > OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-10-08 15:27:19 -04:00
}
2014-03-14 14:13:41 -04:00
}
}
2014-12-10 08:52:59 -05:00
bool FMaterialEditorUtilities : : GetStaticSwitchExpressionValue ( UMaterialInstance * MaterialInstance , UMaterialExpression * SwitchValueExpression , bool & OutValue , FGuid & OutExpressionID , TArray < FGetVisibleMaterialParametersFunctionState * > & FunctionStack )
2014-03-14 14:13:41 -04:00
{
// If switch value is a function input expression then we must recursively find the associated input expressions from the parent function/material to evaluate the value.
UMaterialExpressionFunctionInput * FunctionInputExpression = Cast < UMaterialExpressionFunctionInput > ( SwitchValueExpression ) ;
if ( FunctionInputExpression & & FunctionInputExpression - > InputType = = FunctionInput_StaticBool )
{
2014-12-10 08:52:59 -05:00
FGetVisibleMaterialParametersFunctionState * TopmostFunctionState = FunctionStack . Pop ( ) ;
const TArray < FFunctionExpressionInput > * FunctionInputs = TopmostFunctionState - > FunctionCall ? & TopmostFunctionState - > FunctionCall - > FunctionInputs : NULL ;
2014-03-14 14:13:41 -04:00
// Get the FFunctionExpressionInput which stores information about the input node from the parent that this is linked to.
const FFunctionExpressionInput * MatchingInput = FindInputById ( FunctionInputExpression , * FunctionInputs ) ;
if ( MatchingInput & & ( MatchingInput - > Input . Expression | | ! FunctionInputExpression - > bUsePreviewValueAsDefault ) )
{
2014-12-10 08:52:59 -05:00
GetStaticSwitchExpressionValue ( MaterialInstance , MatchingInput - > Input . Expression , OutValue , OutExpressionID , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-12-10 08:52:59 -05:00
GetStaticSwitchExpressionValue ( MaterialInstance , FunctionInputExpression - > Preview . Expression , OutValue , OutExpressionID , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
2014-12-10 08:52:59 -05:00
FunctionStack . Push ( TopmostFunctionState ) ;
2014-03-14 14:13:41 -04:00
}
2014-10-23 21:38:06 -04:00
if ( SwitchValueExpression )
2014-03-14 14:13:41 -04:00
{
UMaterialExpressionStaticBoolParameter * SwitchParamValue = Cast < UMaterialExpressionStaticBoolParameter > ( SwitchValueExpression ) ;
if ( SwitchParamValue )
{
MaterialInstance - > GetStaticSwitchParameterValue ( SwitchParamValue - > ParameterName , OutValue , OutExpressionID ) ;
return true ;
}
}
UMaterialExpressionStaticBool * StaticSwitchValue = Cast < UMaterialExpressionStaticBool > ( SwitchValueExpression ) ;
if ( StaticSwitchValue )
{
OutValue = StaticSwitchValue - > Value ;
return true ;
}
return false ;
}
bool FMaterialEditorUtilities : : IsFunctionContainingSwitchExpressions ( UMaterialFunction * MaterialFunction )
{
if ( MaterialFunction )
{
TArray < UMaterialFunction * > DependentFunctions ;
MaterialFunction - > GetDependentFunctions ( DependentFunctions ) ;
DependentFunctions . AddUnique ( MaterialFunction ) ;
for ( int32 FunctionIndex = 0 ; FunctionIndex < DependentFunctions . Num ( ) ; + + FunctionIndex )
{
UMaterialFunction * CurrentFunction = DependentFunctions [ FunctionIndex ] ;
for ( int32 ExpressionIndex = 0 ; ExpressionIndex < CurrentFunction - > FunctionExpressions . Num ( ) ; + + ExpressionIndex )
{
UMaterialExpressionStaticSwitch * StaticSwitchExpression = Cast < UMaterialExpressionStaticSwitch > ( CurrentFunction - > FunctionExpressions [ ExpressionIndex ] ) ;
if ( StaticSwitchExpression )
{
return true ;
}
}
}
}
return false ;
}
const FFunctionExpressionInput * FMaterialEditorUtilities : : FindInputById ( const UMaterialExpressionFunctionInput * InputExpression , const TArray < FFunctionExpressionInput > & Inputs )
{
for ( int32 InputIndex = 0 ; InputIndex < Inputs . Num ( ) ; InputIndex + + )
{
const FFunctionExpressionInput & CurrentInput = Inputs [ InputIndex ] ;
if ( CurrentInput . ExpressionInputId = = InputExpression - > Id & & CurrentInput . ExpressionInput - > GetOuter ( ) = = InputExpression - > GetOuter ( ) )
{
return & CurrentInput ;
}
}
return NULL ;
}
void FMaterialEditorUtilities : : InitExpressions ( UMaterial * Material )
{
FString ParmName ;
Material - > EditorComments . Empty ( ) ;
Material - > Expressions . Empty ( ) ;
TArray < UObject * > ChildObjects ;
GetObjectsWithOuter ( Material , ChildObjects , /*bIncludeNestedObjects=*/ false ) ;
for ( int32 ChildIdx = 0 ; ChildIdx < ChildObjects . Num ( ) ; + + ChildIdx )
{
UMaterialExpression * MaterialExpression = Cast < UMaterialExpression > ( ChildObjects [ ChildIdx ] ) ;
if ( MaterialExpression ! = NULL & & ! MaterialExpression - > IsPendingKill ( ) )
{
// Comment expressions are stored in a separate list.
if ( MaterialExpression - > IsA ( UMaterialExpressionComment : : StaticClass ( ) ) )
{
Material - > EditorComments . Add ( static_cast < UMaterialExpressionComment * > ( MaterialExpression ) ) ;
}
else
{
Material - > Expressions . Add ( MaterialExpression ) ;
}
}
}
Material - > BuildEditorParameterList ( ) ;
// Propagate RF_Transactional to all referenced material expressions.
Material - > SetFlags ( RF_Transactional ) ;
for ( int32 MaterialExpressionIndex = 0 ; MaterialExpressionIndex < Material - > Expressions . Num ( ) ; + + MaterialExpressionIndex )
{
UMaterialExpression * MaterialExpression = Material - > Expressions [ MaterialExpressionIndex ] ;
if ( MaterialExpression )
{
MaterialExpression - > SetFlags ( RF_Transactional ) ;
}
}
for ( int32 MaterialExpressionIndex = 0 ; MaterialExpressionIndex < Material - > EditorComments . Num ( ) ; + + MaterialExpressionIndex )
{
UMaterialExpressionComment * Comment = Material - > EditorComments [ MaterialExpressionIndex ] ;
Comment - > SetFlags ( RF_Transactional ) ;
}
}
///////////
// private
2014-10-23 21:38:06 -04:00
void FMaterialEditorUtilities : : GetVisibleMaterialParametersFromExpression (
FMaterialExpressionKey MaterialExpressionKey ,
UMaterialInstance * MaterialInstance ,
TArray < FGuid > & VisibleExpressions ,
TArray < FGetVisibleMaterialParametersFunctionState * > & FunctionStack )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
if ( ! MaterialExpressionKey . Expression )
2014-03-14 14:13:41 -04:00
{
return ;
}
check ( MaterialInstance ) ;
2014-10-23 21:38:06 -04:00
// Bail if we already parsed this expression
if ( FunctionStack . Top ( ) - > VisitedExpressions . Contains ( MaterialExpressionKey ) )
2014-03-14 14:13:41 -04:00
{
return ;
}
2014-10-23 21:38:06 -04:00
FunctionStack . Top ( ) - > VisitedExpressions . Add ( MaterialExpressionKey ) ;
FunctionStack . Top ( ) - > ExpressionStack . Push ( MaterialExpressionKey ) ;
const int32 FunctionDepth = FunctionStack . Num ( ) ;
2014-03-14 14:13:41 -04:00
{
// if it's a material parameter it must be visible so add it to the map
2014-10-23 21:38:06 -04:00
UMaterialExpressionParameter * Param = Cast < UMaterialExpressionParameter > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionTextureSampleParameter * TexParam = Cast < UMaterialExpressionTextureSampleParameter > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionFontSampleParameter * FontParam = Cast < UMaterialExpressionFontSampleParameter > ( MaterialExpressionKey . Expression ) ;
if ( Param )
2014-03-14 14:13:41 -04:00
{
VisibleExpressions . AddUnique ( Param - > ExpressionGUID ) ;
2014-10-23 21:38:06 -04:00
UMaterialExpressionScalarParameter * ScalarParam = Cast < UMaterialExpressionScalarParameter > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionVectorParameter * VectorParam = Cast < UMaterialExpressionVectorParameter > ( MaterialExpressionKey . Expression ) ;
2014-03-14 14:13:41 -04:00
TArray < FName > Names ;
TArray < FGuid > Ids ;
2014-10-23 21:38:06 -04:00
if ( ScalarParam )
2014-03-14 14:13:41 -04:00
{
MaterialInstance - > GetMaterial ( ) - > GetAllScalarParameterNames ( Names , Ids ) ;
for ( int32 i = 0 ; i < Names . Num ( ) ; i + + )
{
if ( Names [ i ] = = ScalarParam - > ParameterName )
{
VisibleExpressions . AddUnique ( Ids [ i ] ) ;
}
}
}
2014-10-23 21:38:06 -04:00
else if ( VectorParam )
2014-03-14 14:13:41 -04:00
{
MaterialInstance - > GetMaterial ( ) - > GetAllVectorParameterNames ( Names , Ids ) ;
for ( int32 i = 0 ; i < Names . Num ( ) ; i + + )
{
if ( Names [ i ] = = VectorParam - > ParameterName )
{
VisibleExpressions . AddUnique ( Ids [ i ] ) ;
}
}
}
}
2014-10-23 21:38:06 -04:00
else if ( TexParam )
2014-03-14 14:13:41 -04:00
{
VisibleExpressions . AddUnique ( TexParam - > ExpressionGUID ) ;
TArray < FName > Names ;
TArray < FGuid > Ids ;
MaterialInstance - > GetMaterial ( ) - > GetAllTextureParameterNames ( Names , Ids ) ;
for ( int32 i = 0 ; i < Names . Num ( ) ; i + + )
{
if ( Names [ i ] = = TexParam - > ParameterName )
{
VisibleExpressions . AddUnique ( Ids [ i ] ) ;
}
}
}
2014-10-23 21:38:06 -04:00
else if ( FontParam )
2014-03-14 14:13:41 -04:00
{
VisibleExpressions . AddUnique ( FontParam - > ExpressionGUID ) ;
TArray < FName > Names ;
TArray < FGuid > Ids ;
MaterialInstance - > GetMaterial ( ) - > GetAllFontParameterNames ( Names , Ids ) ;
for ( int32 i = 0 ; i < Names . Num ( ) ; i + + )
{
if ( Names [ i ] = = FontParam - > ParameterName )
{
VisibleExpressions . AddUnique ( Ids [ i ] ) ;
}
}
}
}
// check if it's a switch expression and branch according to its value
2014-10-23 21:38:06 -04:00
UMaterialExpressionStaticSwitchParameter * StaticSwitchParamExpression = Cast < UMaterialExpressionStaticSwitchParameter > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionStaticSwitch * StaticSwitchExpression = Cast < UMaterialExpressionStaticSwitch > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionMaterialFunctionCall * FunctionCallExpression = Cast < UMaterialExpressionMaterialFunctionCall > ( MaterialExpressionKey . Expression ) ;
UMaterialExpressionFunctionInput * FunctionInputExpression = Cast < UMaterialExpressionFunctionInput > ( MaterialExpressionKey . Expression ) ;
if ( StaticSwitchParamExpression )
2014-03-14 14:13:41 -04:00
{
bool Value = false ;
FGuid ExpressionID ;
MaterialInstance - > GetStaticSwitchParameterValue ( StaticSwitchParamExpression - > ParameterName , Value , ExpressionID ) ;
VisibleExpressions . AddUnique ( ExpressionID ) ;
2014-10-23 21:38:06 -04:00
if ( Value )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( StaticSwitchParamExpression - > A . Expression , StaticSwitchParamExpression - > A . OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( StaticSwitchParamExpression - > B . Expression , StaticSwitchParamExpression - > B . OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-10-23 21:38:06 -04:00
else if ( StaticSwitchExpression )
2014-03-14 14:13:41 -04:00
{
bool bValue = StaticSwitchExpression - > DefaultValue ;
FGuid ExpressionID ;
2014-10-23 21:38:06 -04:00
if ( StaticSwitchExpression - > Value . Expression )
2014-03-14 14:13:41 -04:00
{
2014-12-10 08:52:59 -05:00
GetStaticSwitchExpressionValue ( MaterialInstance , StaticSwitchExpression - > Value . Expression , bValue , ExpressionID , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
2014-10-23 21:38:06 -04:00
if ( ExpressionID . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
VisibleExpressions . AddUnique ( ExpressionID ) ;
2014-03-14 14:13:41 -04:00
}
}
if ( bValue )
{
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( StaticSwitchExpression - > A . Expression , StaticSwitchExpression - > A . OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( StaticSwitchExpression - > B . Expression , StaticSwitchExpression - > B . OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-10-23 21:38:06 -04:00
else if ( FunctionCallExpression )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
if ( FunctionCallExpression - > MaterialFunction )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
for ( int32 FunctionCallIndex = 0 ; FunctionCallIndex < FunctionStack . Num ( ) ; FunctionCallIndex + + )
2014-03-14 14:13:41 -04:00
{
2014-10-23 21:38:06 -04:00
checkSlow ( FunctionStack [ FunctionCallIndex ] - > FunctionCall ! = FunctionCallExpression ) ;
2014-03-14 14:13:41 -04:00
}
2014-10-23 21:38:06 -04:00
TScopedPointer < FGetVisibleMaterialParametersFunctionState > NewFunctionState ( new FGetVisibleMaterialParametersFunctionState ( FunctionCallExpression ) ) ;
FunctionStack . Push ( NewFunctionState . GetOwnedPointer ( ) ) ;
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( FunctionCallExpression - > FunctionOutputs [ MaterialExpressionKey . OutputIndex ] . ExpressionOutput , 0 ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
check ( FunctionStack . Top ( ) - > ExpressionStack . Num ( ) = = 0 ) ;
FunctionStack . Pop ( ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-10-23 21:38:06 -04:00
else if ( FunctionInputExpression )
{
FGetVisibleMaterialParametersFunctionState * FunctionState = FunctionStack . Pop ( ) ;
const FFunctionExpressionInput * MatchingInput = FindInputById ( FunctionInputExpression , FunctionState - > FunctionCall - > FunctionInputs ) ;
check ( MatchingInput ) ;
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( MatchingInput - > Input . Expression , MatchingInput - > Input . OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
FunctionStack . Push ( FunctionState ) ;
}
2014-03-14 14:13:41 -04:00
else
{
2014-10-23 21:38:06 -04:00
const TArray < FExpressionInput * > & ExpressionInputs = MaterialExpressionKey . Expression - > GetInputs ( ) ;
for ( int32 ExpressionInputIndex = 0 ; ExpressionInputIndex < ExpressionInputs . Num ( ) ; ExpressionInputIndex + + )
2014-03-14 14:13:41 -04:00
{
//retrieve the expression input and then start parsing its children
FExpressionInput * Input = ExpressionInputs [ ExpressionInputIndex ] ;
2014-10-23 21:38:06 -04:00
GetVisibleMaterialParametersFromExpression ( FMaterialExpressionKey ( Input - > Expression , Input - > OutputIndex ) , MaterialInstance , VisibleExpressions , FunctionStack ) ;
2014-03-14 14:13:41 -04:00
}
}
2014-10-23 21:38:06 -04:00
FMaterialExpressionKey TopExpressionKey = FunctionStack . Top ( ) - > ExpressionStack . Pop ( ) ;
check ( FunctionDepth = = FunctionStack . Num ( ) ) ;
//ensure that the top of the stack matches what we expect (the same as MaterialExpressionKey)
check ( MaterialExpressionKey = = TopExpressionKey ) ;
2014-03-14 14:13:41 -04:00
}
TSharedPtr < class IMaterialEditor > FMaterialEditorUtilities : : GetIMaterialEditorForObject ( const UObject * ObjectToFocusOn )
{
check ( ObjectToFocusOn ) ;
// Find the associated Material
UMaterial * Material = Cast < UMaterial > ( ObjectToFocusOn - > GetOuter ( ) ) ;
TSharedPtr < IMaterialEditor > MaterialEditor ;
if ( Material ! = NULL )
{
TSharedPtr < IToolkit > FoundAssetEditor = FToolkitManager : : Get ( ) . FindEditorForAsset ( Material ) ;
if ( FoundAssetEditor . IsValid ( ) )
{
MaterialEditor = StaticCastSharedPtr < IMaterialEditor > ( FoundAssetEditor ) ;
}
}
return MaterialEditor ;
}
void FMaterialEditorUtilities : : AddMaterialExpressionCategory ( FGraphActionMenuBuilder & ActionMenuBuilder , FString CategoryName , TArray < struct FMaterialExpression > * MaterialExpressions , bool bMaterialFunction )
{
// Get type of dragged pin
uint32 FromPinType = 0 ;
if ( ActionMenuBuilder . FromPin )
{
FromPinType = UMaterialGraphSchema : : GetMaterialValueType ( ActionMenuBuilder . FromPin ) ;
}
for ( int32 Index = 0 ; Index < MaterialExpressions - > Num ( ) ; + + Index )
{
const FMaterialExpression & MaterialExpression = ( * MaterialExpressions ) [ Index ] ;
if ( IsAllowedExpressionType ( MaterialExpression . MaterialClass , bMaterialFunction ) )
{
if ( ! ActionMenuBuilder . FromPin | | HasCompatibleConnection ( MaterialExpression . MaterialClass , FromPinType , ActionMenuBuilder . FromPin - > Direction , bMaterialFunction ) )
{
FFormatNamedArguments Arguments ;
Arguments . Add ( TEXT ( " Name " ) , FText : : FromString ( * MaterialExpression . Name ) ) ;
const FText ToolTip = FText : : Format ( LOCTEXT ( " NewMaterialExpressionTooltip " , " Adds a {Name} node here " ) , Arguments ) ;
TSharedPtr < FMaterialGraphSchemaAction_NewNode > NewNodeAction ( new FMaterialGraphSchemaAction_NewNode (
CategoryName ,
2014-04-23 18:30:37 -04:00
FText : : FromString ( MaterialExpression . Name ) ,
2014-03-14 14:13:41 -04:00
ToolTip . ToString ( ) , 0 ) ) ;
ActionMenuBuilder . AddAction ( NewNodeAction ) ;
NewNodeAction - > MaterialExpressionClass = MaterialExpression . MaterialClass ;
NewNodeAction - > Keywords = CastChecked < UMaterialExpression > ( MaterialExpression . MaterialClass - > GetDefaultObject ( ) ) - > GetKeywords ( ) ;
}
}
}
}
bool FMaterialEditorUtilities : : HasCompatibleConnection ( UClass * ExpressionClass , uint32 TestType , EEdGraphPinDirection TestDirection , bool bMaterialFunction )
{
if ( TestType ! = 0 )
{
UMaterialExpression * DefaultExpression = CastChecked < UMaterialExpression > ( ExpressionClass - > GetDefaultObject ( ) ) ;
if ( TestDirection = = EGPD_Output )
{
int32 NumInputs = DefaultExpression - > GetInputs ( ) . Num ( ) ;
for ( int32 Index = 0 ; Index < NumInputs ; + + Index )
{
uint32 InputType = DefaultExpression - > GetInputType ( Index ) ;
if ( CanConnectMaterialValueTypes ( InputType , TestType ) )
{
return true ;
}
}
}
else
{
int32 NumOutputs = DefaultExpression - > GetOutputs ( ) . Num ( ) ;
for ( int32 Index = 0 ; Index < NumOutputs ; + + Index )
{
uint32 OutputType = DefaultExpression - > GetOutputType ( Index ) ;
if ( CanConnectMaterialValueTypes ( TestType , OutputType ) )
{
return true ;
}
}
}
if ( bMaterialFunction )
{
// Specific test as Default object won't have texture input
if ( ExpressionClass = = UMaterialExpressionTextureSample : : StaticClass ( ) & & TestType & MCT_Texture & & TestDirection = = EGPD_Output )
{
return true ;
}
// Always allow creation of new inputs as they can take any type
else if ( ExpressionClass = = UMaterialExpressionFunctionInput : : StaticClass ( ) )
{
return true ;
}
// Allow creation of outputs for floats and material attributes
else if ( ExpressionClass = = UMaterialExpressionFunctionOutput : : StaticClass ( ) & & TestType & ( MCT_Float | MCT_MaterialAttributes ) )
{
return true ;
}
}
}
return false ;
}
# undef LOCTEXT_NAMESPACE