I want to find some material with a specific node, can I get the arrangement of the nodes that material itself has in python?
I donât see anything in the Python API documentation that lets you search for a specific node, but I do see a function to get information on a parameter. If your node uses a specific parameter, you could search for it this way.
Here is the link to the page I found this on in case you want to look for any other useful functions:
https://dev.epicgames.com/documentation/en-us/unreal-engine/python-api/class/MaterialInterface?application_version=4.27#unreal.MaterialInterface
Alternatively, Iâm seeing some potential here:
https://dev.epicgames.com/documentation/en-us/unreal-engine/python-api/class/MaterialEditingLibrary?highlight=get%20materialexpression&application_version=4.27
None of these functions directly returns a specific material function, but you may still be able to get some results. For instance, I can see a method where you use the get_inputs_for_material_expression, and if it returns null, then your material does not contain the expression. However, it looks like this method requires an active material editor, so you would first have to code the material graph opening up.
I typed this earlier but accidentally hit deleteâŚgrrr (need undo epic!)
The ânodesâ arenât code, they are xml-bodies that represent calls/pure-functions that are compiled-down into native-code for the GPU. eg:
Summary
Begin Object Class=/Script/UnrealEd.MaterialGraphNode Name=âMaterialGraphNode_2â ExportPath=â/Script/UnrealEd.MaterialGraphNodeâ/Engine/Transient.M_Tower_Highlight:MaterialGraph_0.MaterialGraphNode_2ââ
Begin Object Class=/Script/Engine.MaterialExpressionMaterialFunctionCall Name=âMaterialExpressionMaterialFunctionCall_0â ExportPath=â/Script/Engine.MaterialExpressionMaterialFunctionCallâ/Engine/Transient.M_Tower_Highlight:MaterialGraph_0.MaterialGraphNode_2.MaterialExpressionMaterialFunctionCall_0ââ
End Object
Begin Object Name=âMaterialExpressionMaterialFunctionCall_0â ExportPath=â/Script/Engine.MaterialExpressionMaterialFunctionCallâ/Engine/Transient.M_Tower_Highlight:MaterialGraph_0.MaterialGraphNode_2.MaterialExpressionMaterialFunctionCall_0ââ
MaterialFunction=â/Script/Engine.MaterialFunctionâ/Game/Materials/MF_SDF_AA.MF_SDF_AAââ
FunctionInputs(0)=(ExpressionInputId=EE49EF2E4233F32F23DAC4BE05A2C7F4,Input=(Expression=â/Script/Engine.MaterialExpressionSaturateâMaterialExpressionSaturate_2ââ,InputName=âSDFâ))
FunctionInputs(1)=(ExpressionInputId=BA99EEC24C99C22AC1C416B825916021,Input=(Expression=â/Script/Engine.MaterialExpressionConstantâMaterialExpressionConstant_1ââ,InputName=âThresholdâ))
FunctionInputs(2)=(ExpressionInputId=84EBF17040B5F5EACDF3C09285B8BF1E,Input=(Expression=â/Script/Engine.MaterialExpressionConstantâMaterialExpressionConstant_0ââ,InputName=âWidthâ))
FunctionOutputs(0)=(ExpressionOutputId=05B634674CFD2FD433AD6B91D335B9D2,Output=(OutputName=âResultâ))
MaterialExpressionEditorX=624
MaterialExpressionEditorY=-144
MaterialExpressionGuid=DAB5391543A6E82EA3FA06AE9E0D5DBD
Material=â/Script/UnrealEd.PreviewMaterialâ/Engine/Transient.M_Tower_Highlightââ
Outputs(0)=(OutputName=âResultâ)
End Object
MaterialExpression=â/Script/Engine.MaterialExpressionMaterialFunctionCallâMaterialExpressionMaterialFunctionCall_0ââ
NodePosX=624
NodePosY=-144
NodeGuid=CDC5CBAA4303D558CE6BBC9E72E4E322
CustomProperties Pin (PinId=46C09AD34263C499942433BC0FA22933,PinName=âSDF (S)â,PinType.PinCategory=ârequiredâ,PinType.PinSubCategory=ââ,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_3 665EAC564615E86BDC1193AA6E0CE83C,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=2EA7A53C4F10B7D3105F22818203D9D7,PinName=âThreshold (S)â,PinType.PinCategory=âoptionalâ,PinType.PinSubCategory=ââ,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_18 09F36D974ED6EC93428D51A6DDCF88CC,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=C68337DC4CB271DDDC29DF9EEB62CE56,PinName=âWidth (S)â,PinType.PinCategory=âoptionalâ,PinType.PinSubCategory=ââ,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_17 6FFCBFDF40120A953B3F8AA41D10DE1B,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
CustomProperties Pin (PinId=99A016044FE8A71A1B0E1CBB3194C8A2,PinName=âResultâ,Direction=âEGPD_Outputâ,PinType.PinCategory=ââ,PinType.PinSubCategory=ââ,PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PinType.bSerializeAsSinglePrecisionFloat=False,LinkedTo=(MaterialGraphNode_Root_0 772CABB448415F9B449D42B86AC4C680,MaterialGraphNode_19 632A801E49332B28FF3E618F9A654D1F,),PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,)
End Object
Never tinkered with python, but if you can get the contents of the material/material-function you ought to be able just-search text against the name of the node you want.
Even opening the .uasset-file in Notepad++ gives you node-names:
Summary
line 57 is a function called STRATA_EFFECT (as in the literal name of the blue node I am calling) and Strata.On is a switch-node to toggle the function (hence it comes first):
it also puts a list of functions-used at least:
Engine/Functions/Engine_MaterialFunctions02/Utility/BreakOutFloat2Components øþ¨N
/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakOutFloat3Components $[ĂÂN
/Engine/Functions/Engine_MaterialFunctions02/Utility/BreakOutFloat4Components :äà 9G
/Engine/Functions/Engine_MaterialFunctions02/Utility/DebugFloat2Values cĂÂĽâG
You can attack it at that level at least.
Hi again @TumHardy!
I wanted to follow up on this again for you or anyone else who stumbles onto this thread. After needing to do the same thing, Iâve learned a lot.
To start off, I couldnât find a way to search for a specific material expression within a material. Maybe there is a way to do this, but I didnât see anything. Instead, you need to load the material and get all of the material expressions. I couldnât find a way to differentiate between material expressions of the same type, so the method I used was to get their input parameters and their values to check if it was the one I was looking for.
Now, this entire process is a lot of for loops with a large amount of inputs. I simplified this down as much as possible by only searching for a material once then saving it to an array if it contained the node I needed, so I only needed to find the material once when iterating over a bunch of meshes. I also made sure I was only getting the input names and values of the specific node type I was searching for, so I didnât need to get all of the input parameters of every material expression in the material.
In the end, this is what my setup looked like:
With this being the logic of my main python script that gets every material expression:
import unreal
if name == âmainâ:
# load the material
material = unreal.EditorAssetLibrary.load_asset(matpath)
it = unreal.ObjectIterator(unreal.MaterialExpression)
ocl_exp = []
# iterate over all loaded material expressions, append all that belong to material.
all_material_expressions = []
for material_expression in it:
if material_expression.get_outer() == material:
all_material_expressions.append(material_expression)
# print out all expressions we stored.
for material_expression in all_material_expressions:
ocl_exp.append(material_expression)