How to use Revit IUpdater

An interface named IUpdater is another DMU(Dynamic Model Update) methode. It is more flexible then Event Hadler, because we are more free is difining an event triger. The good thing is that we can trigger IUpdater when we make any element modification either by creating a new element or by modifying an existing geometry. Download a sample code from my GitHub page.

Read the previous article about Event Handlers where i explained how the __selfinit__  and togglestate functions work. The plan is to create an instance of the IUpdater class, register the updater, and set its triger.

First we need all neccessary imports. here they are:

# -*- coding: UTF-8 -*-
import os
from pyrevit import framework
from pyrevit import script
from pyrevit.framework import AppDomain
import Autodesk
from Autodesk.Revit.UI import *
from Autodesk.Revit.DB import *
import System
from System import Guid

This is a standart body of the IUpdater class:

class MyUpdater(IUpdater):

    def __init__(self, addinId):
        '''type UpdaterId, mix of Addin ID and updater GUID
           choose a different GUID for each updater !!! '''
        self.updaterID = UpdaterId(addinId,
            Guid("CBCBF6B2-4C06-42d4-97C1-D1B4EB593100"))

    def GetUpdaterId(self):
        return self.updaterID

    def GetUpdaterName(self):
        return 'MyUpdater'

    def GetAdditionalInformation(self):
        return 'MyUpdater (explanation, details, warnings)'

    def GetChangePriority(self):
        return ChangePriority.Structure

    def Execute(self, updaterData):
        up_doc = updaterData.GetDocument()   #document
        uidoc = __revit__.ActiveUIDocument
        #elems = updaterData.GetAddedElementIds()
        elems = updaterData.GetModifiedElementIds()
        # use a subtransaction in the current opened transaction
        if script.get_envvar(UPDATER_TEST):

            t = SubTransaction(up_doc)
            t.Start()
            try:
                if elems:
                    for h in elems:
                        id = up_doc.GetElement(h)
                        TaskDialog.Show('Element', 'Wall Changed '+str(h)+h)
                t.Commit()
            except:
                t.RollBack()

For different IUpdaters we need unique ID. Combine the Active addin ID and GUID of your application. Just create a random one:

Guid("CBCBF6B2-4C06-42d4-97C1-D1B4EB593100"))

Other properties are optional, but required for syntax. We are interested in the Execute method, where we write instructions for revit. Define the document and uidoc inside the Execute function, otherwise it will cause an error when running revit without an opened document.

up_doc = updaterData.GetDocument()   #document
uidoc = __revit__.ActiveUIDocument

You can collect items created or modified to make further manipulations:

elems = updaterData.GetAddedElementIds()
or
elems = updaterData.GetModifiedElementIds()

Then add a condition to move on only if the enviromnet variable is True(read Event Handler post)

if script.get_envvar(UPDATER_TEST)

Then we need to open SubTransaction to make changes to the document, write the instructions and commit the SubTransaction. The Rollback() methode is used if an error occurs.

Next, create an instance of IUpdater and register it with smartbutton __selfinit__ function. If statement is required to avoid multiple registrations:

def __selfinit__(script_cmp, ui_button_cmp, __rvt__):
    my_updater = MyUpdater(app.ActiveAddInId)
    if UpdaterRegistry.IsUpdaterRegistered(my_updater.GetUpdaterId()):
        UpdaterRegistry.UnregisterUpdater(my_updater.GetUpdaterId())
    UpdaterRegistry.RegisterUpdater(my_updater)

And add a trigger. For example, if you need to check the creation of elements, use GetChangeTypeElementAddition () or GetChangeTypeGeometry () to track modifications of existing elements. The UpdateRegistry methode requires an updater ID, element filter and triger type:

filter = ElementCategoryFilter(BuiltInCategory.OST_Walls)
UpdaterRegistry.AddTrigger(my_updater.GetUpdaterId(), filter,
Element.GetChangeTypeGeometry())
or
UpdaterRegistry.AddTrigger(my_updater.GetUpdaterId(), filter,
Element.GetChangeTypeElementAddition())

There are many options for using the IUpdater. In one of my projects to automate disign routine I used the GetChangeTypeElementAddition() methode to check when the Dimensions are being created and run an algorithm that moves the leaders in certain directions. Like these:

 

 

Post Comments(3)

...
Yevgeniy1 year, 11 months ago

Доброго дня! Аплодую Вашій роботі! Питання - чи можливо реалізувати IUpdater для скрипта Dynamo?

...
Yevgeniy1 year, 11 months ago

Доброго дня! Аплодую Вашій роботі! Питання - чи можливо реалізувати IUpdater для скрипта Dynamo?

...
Yevgeniy1 year, 11 months ago

Доброго дня! Аплодую Вашій роботі! Питання - чи можливо реалізувати IUpdater для скрипта Dynamo?