Check this out, I defined another method based on Dimitar Venkov’s original “NewForm_background”, and it works for me(MultiSolidToOneFamily() can give each solid different material either):
def MultiSolidToOneFamily(s1, name1, cat1, isVoid1, mat1, subcat1):
enable_mat = False if mat1 is None else True
enable_subcat = False if subcat1 is None else True
TransactionManager.ForceCloseTransaction(t1)
famdoc = doc.Application.NewFamilyDocument(fam_path)
message = None
temp_path = System.IO.Path.GetTempPath()
sat_path = "%s%s.sat" % (temp_path, name1)
try:
vec1 = Vector.ByTwoPoints(BoundingBox.ByGeometry(s1).MinPoint, DynPoint.Origin())
for i in xrange(0,len(s1)):
if factor != 1:
s1[i] = s1[i].Scale(factor)
s1[i] = s1[i].Translate(vec1)
sat1 = Geometry.ExportToSAT(s1[i], sat_path)
view_fec = FilteredElementCollector(famdoc).OfClass(View)
view1 = None
for v in view_fec:
if str(v.ViewType) in acceptable_views and not v.IsTemplate:
view1 = v
break
t1.EnsureInTransaction(famdoc)
satId = famdoc.Import(sat1, satOpt, view1)
el1 = famdoc.GetElement(satId)
geom1 = el1.get_Geometry(opt1)
enum = geom1.GetEnumerator()
enum.MoveNext()
geom2 = enum.Current.GetInstanceGeometry()
enum2 = geom2.GetEnumerator()
enum2.MoveNext()
s1[i] = enum2.Current
famdoc.Delete(satId)
System.IO.File.Delete(sat_path)
except:
message = (traceback.format_exc(),"")
pass
if message is None:
try:
save_path = "%s%s.rfa" % (temp_path, name1)
try: #set the category
fam_cat = famdoc.Settings.Categories.get_Item(cat1.Name)
famdoc.OwnerFamily.FamilyCategory = fam_cat
except: pass
for i in xrange(0,len(s1)):
s2 = FreeFormElement.Create(famdoc,s1[i])
try:
mat_fec = FilteredElementCollector(famdoc).OfClass(Material)
for m in mat_fec:
if m.Name == mat1[i]:
fam_mat = m
break
mat_par = s2.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM).Set(fam_mat.Id)
except: pass
TransactionManager.ForceCloseTransaction(t1)
famdoc.SaveAs(save_path, SaveAsOpt)
family1 = famdoc.LoadFamily(doc, FamOpt1() )
famdoc.Close(False)
System.IO.File.Delete(save_path)
symbols = family1.GetFamilySymbolIds().GetEnumerator()
symbols.MoveNext()
symbol1 = doc.GetElement(symbols.Current)
t1.EnsureInTransaction(doc)
if not symbol1.IsActive: symbol1.Activate()
inst1 = doc.Create.NewFamilyInstance(origin, symbol1, str_typ)
ElementTransformUtils.MoveElement(doc,inst1.Id, vec1.Reverse().ToXyz() )
TransactionManager.ForceCloseTransaction(t1)
#set ToDSType() to True so that the second run of script won't override result of first run, based on what you prefer
return inst1.ToDSType(True), family1.ToDSType(False)
except:
message = (traceback.format_exc(),"")
return message
else : return message
And The OUT variable is set to this(I didn’t figure out how to use map(), and so I made some change )
if len(geom) == len(names) == len(category) == len(isVoid) == len(material) == len(subcat):
return1 = map(NewForm_background, geom, names, category, isVoid, material, subcat)
OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
elif len(geom) == len(names):
padded = PadLists([geom, category, isVoid, material,subcat])
p_category, p_isVoid, p_material, p_subcat = padded[1], padded[2], padded[3], padded[4]
return1 = map(NewForm_background, geom, names, p_category, p_isVoid, p_material, p_subcat)
OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
elif len(geom) > 1 and len(names) == 1:
OUT = MultiSolidToOneFamily(geom, names[0], category[0], isVoid[0], material, subcat[0])
else :
return1 = [("Make sure that each geometry\nobject has a unique family name.", "")]
OUT = output1([i[0] for i in return1]), output1([i[1] for i in return1])
satOpt.Dispose()
opt1.Dispose()
SaveAsOpt.Dispose()