Marco,
The code below will achieve your goal, I believe.
#PROTO_Material Creation / Management v2 (Color and Surface Pattern control)
# by David Dória
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
#Inputs
names = IN[0]
cols = IN[1]
surfPatFor = IN[2]
surfPatForCl = IN[3]
surfPatBkg = IN[4]
surfPatBkgCl = IN[5]
#New materials OUT list
newMaterials = []
#Overwritten materials OUT list
ovwMaterials = []
def ToRevitColor(dynamoColor):
return Color(dynamoColor.Red, dynamoColor.Green, dynamoColor.Blue)
#Avoid instance input problem
if isinstance(names, list):
names = names
else: names = [names]
if isinstance(cols, list):
cols = cols
else: cols = [cols]
if isinstance(surfPatFor, list):
surfPatFor = surfPatFor
else: surfPatFor = [surfPatFor]
if isinstance(surfPatForCl, list):
surfPatForCl = surfPatForCl
else: surfPatForCl = [surfPatForCl]
if isinstance(surfPatBkg, list):
surfPatBkg = surfPatBkg
else: surfPatBkg = [surfPatBkg]
if isinstance(surfPatBkgCl, list):
surfPatBkgCl = surfPatBkgCl
else: surfPatBkgCl = [surfPatBkgCl]
#Get Pattern Id
#Iterate through the input names list
for n, cl,spfor,spforC, spBkg, spBkgC in zip(names,cols,surfPatFor,surfPatForCl,surfPatBkg,surfPatBkgCl):
#Check if the material with the specified name already exists
if Material.IsNameUnique(doc,n):
#If name is unique, create material
TransactionManager.Instance.EnsureInTransaction(doc)
new_mat_id = Material.Create(doc, n)
new_mat = doc.GetElement(new_mat_id)
new_mat.Color = ToRevitColor(cl)
new_mat.SurfaceForegroundPatternId = FillPatternElement.GetFillPatternElementByName(doc, FillPatternTarget.Drafting,spfor).Id
new_mat.SurfaceForegroundPatternColor = ToRevitColor(spforC)
new_mat.SurfaceBackgroundPatternId = FillPatternElement.GetFillPatternElementByName(doc, FillPatternTarget.Drafting,spBkg).Id
new_mat.SurfaceBackgroundPatternColor = ToRevitColor(spBkgC)
TransactionManager.Instance.TransactionTaskDone()
newMaterials.append(n)
else:
#If it already exists, collect it and modify it
TransactionManager.Instance.EnsureInTransaction(doc)
namePar = ParameterValueProvider(ElementId(BuiltInParameter.MATERIAL_NAME))
fRule = FilterStringRule(namePar,FilterStringEquals(),n, True)
filter = ElementParameterFilter(fRule)
exist_mat = FilteredElementCollector(doc).OfClass(Material).WherePasses(filter).ToElements()
#Iteration is necessary because the output of exist_mat is invariably a list
for em in exist_mat:
#Modify the Material Properties and Parameters
em.Color = ToRevitColor(cl)
em.SurfaceForegroundPatternId = FillPatternElement.GetFillPatternElementByName(doc, FillPatternTarget.Drafting,spfor).Id
em.SurfaceForegroundPatternColor = ToRevitColor(spforC)
em.SurfaceBackgroundPatternId = FillPatternElement.GetFillPatternElementByName(doc, FillPatternTarget.Drafting,spBkg).Id
em.SurfaceBackgroundPatternColor = ToRevitColor(spBkgC)
ovwMaterials.append(n)
TransactionManager.Instance.TransactionTaskDone()
OUT = newMaterials, ovwMaterials
Be aware that this is based on the Revit 2019 Materials, which have Foreground and Background surface patterns. If using an older version of Revit, replace the SurfaceForegroundPatternColor
and the SurfaceForegroundPatternId
with SurfacePatternColor
and SurfacePatternId
Also, I suggest adding another input to control the Drafting or Model variable of the GetFillPatternElementByName(doc, FillPatternTarget.Drafting/Model,name)
function, to facilitate the control via a external Database with different types of Fill Patterns.
Best,
David Dória