IFamilyLoadOptions not respected in python

IFamilyLoadOptions not respected in python

mike
Enthusiast Enthusiast
2,249 Views
5 Replies
Message 1 of 6

IFamilyLoadOptions not respected in python

mike
Enthusiast
Enthusiast

I am reloading families from disk based on a user selection, intending to allow easy updating to standard families.  I want the parameters to remain unchanged, retaining the values set by the user.  My implementation is below.  The parameters are reset to the values being loaded no matter what I do.  Apparently I am in over my head.  I'm using python and the most excellent pyrevit library to run it.  Thank you for your time.

 

from rpw.ui.forms import (Alert)
from Autodesk.Revit.DB import FamilySource, IFamilyLoadOptions
from rpw import ui, revit, DB, db
import clr
clr.AddReference('RevitAPI')
class FamilyOption(IFamilyLoadOptions):
    def OnFamilyFound(self, familyInUse, overwriteParameterValues): 
        overwriteParameterValues = False
        return True

    def OnSharedFamilyFound(
            self, sharedFamily, familyInUse, source, overwriteParameterValues):
        source = FamilySource.Family
        overwriteParameterValues = False
        return True

sel = ui.Selection()
newfam = clr.StrongBox[DB.Family]()
if ui.Selection():
    try:
        famdoc = revit.doc.EditFamily(sel[0].Symbol.Family)
        familypath = famdoc.PathName
         famdoc.Close(False)
    except Exception as e:
        print (e)
    if familypath:
        with db.Transaction("Reload Family"):
            revit.doc.LoadFamily(familypath,FamilyOption(),newfam)
            Alert ("Family updated from: {}".format(familypath))
    else:
        Alert ("No External file to reload")
else:
    Alert ("Nothing Selected")

 

0 Likes
Accepted solutions (1)
2,250 Views
5 Replies
Replies (5)
Message 2 of 6

jeremytammik
Autodesk
Autodesk

The IFamilyLoadOptions interface uses a C# `out` parameter to return the setting you require:

 

  out bool overwriteParameterValues

  

`out` parameters are not supported by Python:

  

 

Therefore, this naive translation of the IFamilyLoadOptions interface will not work as expected in Python.

 

I would suggest defining your IFamilyLoadOptions interface in C# instead.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 6

bhprest
Advocate
Advocate

Hey Jeremy.

 

I'm certainly no expert, but I believe that within IronPython, you can pass an instance of

 

clr.Reference[T]

 

to any C# method requiring an out parameter, where <T> is the Type expected back. Once the method returns, you can then use the TryGetValue() method to retrieve the value that was output.

 

I believe that I've used this within RevitPythonShell before, but a quick search through my personal library didn't yield any examples that I could share.

0 Likes
Message 4 of 6

jeremytammik
Autodesk
Autodesk

Well then somebody might want to check the IronPythonShell wrapper implementation for the methods used above and ensure that the arguments really are passed by reference. Where does this implementation come from?

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 5 of 6

mike
Enthusiast
Enthusiast

Good idea.  Python is more familiar but I got it to run from a button in pyrevit.  My users will never know.  Nor do they care.  Everything works great IF the family has a change.  If there has been no change, the parameters reset to whatever is in the external family document.  The user has no idea if there is a change or not.  How can abort the insert in that case or test if there is a change?  I'm sure there is something I'm missing here.

0 Likes
Message 6 of 6

tamas.deri
Advocate
Advocate
Accepted solution

It works this way:

 

class FamilyLoaderOptionsHandler(DB.IFamilyLoadOptions):
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
        overwriteParameterValues.Value = True
        return True


    def OnSharedFamilyFound(self, sharedFamily, familyInUse, source, overwriteParameterValues):
        source.Value = DB.FamilySource.Family
        overwriteParameterValues.Value = True
        return True

 

0 Likes