Revit API: IUpdater 自动更新接口

前言

在做完特定操作之后,追加用户自定义的操作,这是否能通过 Revit API 实现呢?现实中,确实有很多这种需求,比如各种标准的检查。
答案是“Yes”,Revit API 提供了这个功能,通过 IUpdater 及其相关。

例子

代码大部分来自 Revit API 官方文档。
在这里插入图片描述
在绘制完左边这种墙类型的时候,自动将其转化成右边这种类型。
完成这个功能,需要:

  1. 实现你自己的 Updater
  2. 注册你的 Updater
  3. Updater 添加触发

实现你自己的 Updater

所有用户定义的 Updater 都继承自 Autodesk.Revit.DB.IUpdater,接口如下。主要逻辑写在 Execute 里面,它会被触发和执行。

namespace Autodesk.Revit.DB
{
    public interface IUpdater
    {
        void Execute(UpdaterData data);
        string GetAdditionalInformation();
        ChangePriority GetChangePriority();
        UpdaterId GetUpdaterId();
        string GetUpdaterName();
    }
}

这是自定义的 Updater,它的功能是当你创建墙的时候,把它替换成 Exterior - Brick on CMU 这种类型。当然,你也可以实现自己的逻辑,比如在更改墙的参数。

    public class WallUpdater : IUpdater
    {
        static AddInId m_appId;
        static UpdaterId m_updaterId;
        WallType m_wallType = null;

        // constructor takes the AddInId for the add-in associated with this updater
        public WallUpdater(AddInId id)
        {
            m_appId = id;
            m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
        }

        public void Execute(UpdaterData data)
        {
            Document doc = data.GetDocument();

            // Cache the wall type
            if (m_wallType == null)
            {
                FilteredElementCollector collector = new FilteredElementCollector(doc);
                collector.OfClass(typeof(WallType));
                var wallTypes = from element in collector
                                where
                                    element.Name == "Exterior - Brick on CMU"
                                select element;
                if (wallTypes.Count<Element>() > 0)
                {
                    m_wallType = wallTypes.Cast<WallType>().ElementAt<WallType>(0);
                }
            }

            if (m_wallType != null)
            {
                // Change the wall to the cached wall type.
                foreach (ElementId addedElemId in data.GetAddedElementIds())
                {
                    Wall wall = doc.GetElement(addedElemId) as Wall;
                    if (wall != null)
                    {
                        wall.WallType = m_wallType;
                    }
                }
            }
        }

        public string GetAdditionalInformation()
        {
            return "Wall type updater example: updates all newly created walls to a special wall";
        }

        public ChangePriority GetChangePriority()
        {
            return ChangePriority.FloorsRoofsStructuralWalls;
        }

        public UpdaterId GetUpdaterId()
        {
            return m_updaterId;
        }

        public string GetUpdaterName()
        {
            return "Wall Type Updater";
        }
    }

注册你的 Updater

注册用 IExternalCommand 或者 IExternalApplication 都可以。

WallUpdater updater = new WallUpdater(commandData.Application.ActiveAddInId);
UpdaterRegistry.RegisterUpdater(updater);

IExternalApplication 的好处是可以在 OnShutdown 接口里面把它取消掉:

        public Result OnShutdown(UIControlledApplication application)
        {
            WallUpdater updater = new WallUpdater(application.ActiveAddInId);
            UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
            return Result.Succeeded;
        }

为 Updater 添加触发

触发的接口在 Autodesk.Revit.DB.UpdaterRegistry,有三种类型,不同点在于使用的范围:

// 限定在某个 document 能通过 filter 的 elements,并且符合 change 这个类型的操作
public static void AddTrigger(UpdaterId id, Document document, ElementFilter filter, ChangeType change);
// 限定在能通过 filter 的 elements,并且符合 change 这个类型的操作
public static void AddTrigger(UpdaterId id, ElementFilter filter, ChangeType change);
// 限定在某个 document 的 elements,并且符合 change 这个类型的操作
public static void AddTrigger(UpdaterId id, Document document, ICollection<ElementId> elements, ChangeType change);

什么是 ChangeType,可能是添加构件、删除构件、几何形体发生变化、参数发生变化等:

namespace Autodesk.Revit.DB
{
    public class Element : IDisposable
    {
        public static ChangeType GetChangeTypeAny();
        public static ChangeType GetChangeTypeElementAddition();
        public static ChangeType GetChangeTypeElementDeletion();
        public static ChangeType GetChangeTypeGeometry();
        public static ChangeType GetChangeTypeParameter(ElementId parameterId);
        public static ChangeType GetChangeTypeParameter(Parameter param);
        // 其它接口
    }
}

在这个例子中的添加触发:

ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));
UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), wallFilter, Element.GetChangeTypeElementAddition());

完整例子代码

UpdaterCommand 或者 WallUpdaterApplication 都可以:

namespace RevitAddinTemp
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class UpdaterCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            // Register wall updater with Revit
            WallUpdater updater = new WallUpdater(commandData.Application.ActiveAddInId);
            UpdaterRegistry.RegisterUpdater(updater);

            // Change Scope = any Wall element
            ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));

            // Change type = element addition
            UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), wallFilter,
                                        Element.GetChangeTypeElementAddition());
            return Result.Succeeded;
        }
    }

    public class WallUpdaterApplication : Autodesk.Revit.UI.IExternalApplication
    {
        public Result OnStartup(UIControlledApplication application)
        {
            // Register wall updater with Revit
            WallUpdater updater = new WallUpdater(application.ActiveAddInId);
            UpdaterRegistry.RegisterUpdater(updater);

            // Change Scope = any Wall element
            ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));

            // Change type = element addition
            UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), wallFilter,
                                        Element.GetChangeTypeElementAddition());
            return Result.Succeeded;
        }

        public Result OnShutdown(UIControlledApplication application)
        {
            WallUpdater updater = new WallUpdater(application.ActiveAddInId);
            UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());
            return Result.Succeeded;
        }
    }

    public class WallUpdater : IUpdater
    {
        static AddInId m_appId;
        static UpdaterId m_updaterId;
        WallType m_wallType = null;

        // constructor takes the AddInId for the add-in associated with this updater
        public WallUpdater(AddInId id)
        {
            m_appId = id;
            m_updaterId = new UpdaterId(m_appId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
        }

        public void Execute(UpdaterData data)
        {
            Document doc = data.GetDocument();

            // Cache the wall type
            if (m_wallType == null)
            {
                FilteredElementCollector collector = new FilteredElementCollector(doc);
                collector.OfClass(typeof(WallType));
                var wallTypes = from element in collector
                                where
                                    element.Name == "Exterior - Brick on CMU"
                                select element;
                if (wallTypes.Count<Element>() > 0)
                {
                    m_wallType = wallTypes.Cast<WallType>().ElementAt<WallType>(0);
                }
            }

            if (m_wallType != null)
            {
                // Change the wall to the cached wall type.
                foreach (ElementId addedElemId in data.GetAddedElementIds())
                {
                    Wall wall = doc.GetElement(addedElemId) as Wall;
                    if (wall != null)
                    {
                        wall.WallType = m_wallType;
                    }
                }
            }
        }

        public string GetAdditionalInformation()
        {
            return "Wall type updater example: updates all newly created walls to a special wall";
        }

        public ChangePriority GetChangePriority()
        {
            return ChangePriority.FloorsRoofsStructuralWalls;
        }

        public UpdaterId GetUpdaterId()
        {
            return m_updaterId;
        }

        public string GetUpdaterName()
        {
            return "Wall Type Updater";
        }
    }

}
发布了72 篇原创文章 · 获赞 14 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览