Writing Your First Autodesk Revit Model Review Plug-In

Similar documents
CALCULATOR APPLICATION

Now find the button component in the tool box. [if toolbox isn't present click VIEW on the top and click toolbox]

You can call the project anything you like I will be calling this one project slide show.

To start we will be using visual studio Start a new C# windows form application project and name it motivational quotes viewer

Start Visual Studio, start a new Windows Form project under the C# language, name the project BalloonPop MooICT and click OK.

IBSDK Quick Start Tutorial for C# 2010

CSIS 1624 CLASS TEST 6

The Open Core Interface SDK has to be installed on your development computer. The SDK can be downloaded at:

First start a new Windows Form Application from C# and name it Interest Calculator. We need 3 text boxes. 4 labels. 1 button

Click on the empty form and apply the following options to the properties Windows.

We are going to use some graphics and found a nice little batman running GIF, off course you can use any image you want for the project.

Form Properties Window

if (say==0) { k.commandtext = "Insert into kullanici(k_adi,sifre) values('" + textbox3.text + "','" + textbox4.text + "')"; k.

Start Visual Studio and create a new windows form application under C# programming language. Call this project YouTube Alarm Clock.

Object oriented lab /second year / review/lecturer: yasmin maki

This is the empty form we will be working with in this game. Look under the properties window and find the following and change them.

Mastering the Visual LISP Integrated Development Environment

Answer on Question# Programming, C#

Start Visual Studio, create a new project called Helicopter Game and press OK

// Precondition: None // Postcondition: The address' name has been set to the // specified value set;

Conventions in this tutorial

Huw Talliss Data Structures and Variables. Variables

Inheriting Windows Forms with Visual C#.NET

Visual Basic/C# Programming (330)

} } public void getir() { DataTable dt = vt.dtgetir("select* from stok order by stokadi");

// Program 2 - Extra Credit // CIS // Spring // Due: 3/11/2015. // By: Andrew L. Wright. //Edited by : Ben Spalding

Create your own Meme Maker in C#

Eyes of the Dragon - XNA Part 37 Map Editor Revisited

// Specify SEF file to load. oschema = (edischema) oedidoc.loadschema(spath + sseffilename, SchemaTypeIDConstants. Schema_Standard_Exchange_Format);

Lesson 1: The Basic Plug-in

Main Game Code. //ok honestly im not sure, if i guess its a class ment for this page called methodtimer that //either uses the timer or set to timer..

Mainly three tables namely Teacher, Student and Class for small database of a school. are used. The snapshots of all three tables are shown below.

Hands-On Lab. Lab: Client Object Model. Lab version: Last updated: 2/23/2011

Representing Recursive Relationships Using REP++ TreeView

Using Template Bookmarks for Automating Microsoft Word Reports

Sub To Srt Converter. This is the source code of this program. It is made in C# with.net 2.0.

Experiment 5 : Creating a Windows application to interface with 7-Segment LED display

C:\homeworks\PenAttention_v13_src\PenAttention_v13_src\PenAttention4\PenAttention\PenAttention.cs 1 using System; 2 using System.Diagnostics; 3 using

In-Class Worksheet #4

UNIT-3. Prepared by R.VINODINI 1

Class Test 4. Question 1. Use notepad to create a console application that displays a stick figure. See figure 1. Question 2

How to create an Add-In extension.dll file and make it available from Robot pull down menu. (language C#)

CSC 415 ONLINE PHOTOALBUM: THE SEQUEL ASP.NET VERSION

Visual Basic/C# Programming (330)

NI USB-TC01 Thermocouple Measurement Device

Developing for Mobile Devices Lab (Part 1 of 2)

Getting Started with Autodesk Vault Programming

XNA 4.0 RPG Tutorials. Part 11b. Game Editors

Chapter 8 Advanced GUI Features

Eyes of the Dragon - XNA Part 33 Non-Player Character Conversations

XNA 4.0 RPG Tutorials. Part 24. Level Editor Continued

Classes in C# namespace classtest { public class myclass { public myclass() { } } }

Chapter 12. Tool Strips, Status Strips, and Splitters

ArcGIS Pro Extensibility - Building and Deploying Addins with the new DotNet SDK

create database ABCD use ABCD create table bolumler ( bolumkodu int primary key, bolumadi varchar(20) )

// Specify SEF file to load. edischema oschema = oedidoc.loadschema(spath + sseffilename, SchemaTypeIDConstants. Schema_Standard_Exchange_Format);

Hands-On Lab (MBL04) Lab Manual Incorporating COM Objects into Your.NET Compact Framework 2.0 Application

Chapter 6 Dialogs. Creating a Dialog Style Form

private string sconnection = ConfigurationManager.ConnectionStrings["Development"].ConnectionString

Quick Guide for the ServoWorks.NET API 2010/7/13

Tutorial 5 Completing the Inventory Application Introducing Programming

string spath; string sedifile = "277_005010X228.X12"; string sseffile = "277_005010X228.SemRef.EVAL0.SEF";

LISTING PROGRAM. //Find the maximum and minimum values in the array int maxvalue = integers[0]; //start with first element int minvalue = integers[0];

Appendix A Programkod

Creating SDK plugins

EL-USB-RT API Guide V1.0

C# winforms gridview

Using the vrealize Orchestrator Operations Client. vrealize Orchestrator 7.5

II. Programming Technologies

User Filter State. Chapter 11. Overview of User Filter State. The PDSAUserFilterState Class

LAMPIRAN A : LISTING PROGRAM

namespace csharp_gen277x214 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

Getting Started With AutoCAD Civil 3D.Net Programming

Using Visual Studio 2017

FDSc in ICT. Building a Program in C#

The first program we write will display a picture on a Windows screen, with buttons to make the picture appear and disappear.

TARGETPROCESS PLUGIN DEVELOPMENT GUIDE

Advanced Customization. Charles Macleod, Steve Van Esch

Your Company Name. Tel: Fax: Microsoft Visual Studio C# Project Source Code Output

Visual Studio.NET.NET Framework. Web Services Web Forms Windows Forms. Data and XML classes. Framework Base Classes. Common Language Runtime

namespace Gen837X222A1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

APARAT DE MASURA. Descrierea programului

1 de :02

เว บแอพล เคช น. private void Back_Click(object sender, EventArgs e) { this.webbrowser2.goback(); }

The Gracefulness of the Merging Graph N ** C 4 with Dotnet Framework

private string sconnection = ConfigurationManager.ConnectionStrings["Development"].ConnectionString

Contents Getting Started... 3 About Scribe Online and Connectors... 3 Scribe Online Services... 3 CDK Components... 3 Audience... 4 Prerequisites...

emkt Browserless Coding For C#.Net and Excel

This is the start of the server code

2.3 Add GDS Google Map to Visual Studio Toolbox and create a simple map project

Tutorial 6 Enhancing the Inventory Application Introducing Variables, Memory Concepts and Arithmetic

How to create a simple ASP.NET page to create/search data on baan using baan logic from the BOBS client sample.

HIDING PACKET SEND THROUGH MULTIPLE TRANSMISSION LINE BY VIRTUALLY IN AD HOC

ListBox. Class ListBoxTest. Allows users to add and remove items from ListBox Uses event handlers to add to, remove from, and clear list

User-Defined Controls

Tutorial 19 - Microwave Oven Application Building Your Own Classes and Objects

Lecture 8 Building an MDI Application

Savoy ActiveX Control User Guide

Activating AspxCodeGen 4.0

Introduction. Create a New Project. Create the Main Form. Assignment 1 Lights Out! in C# GUI Programming 10 points

Transcription:

Writing Your First Autodesk Revit Model Review Plug-In R. Robert Bell Sparling CP5880 The Revit Model Review plug-in is a great tool for checking a Revit model for matching the standards your company has created. Even better, the tool can fix issues that are found with the click of a button. However, the provided set of tests is basic and may not cover all the types of model standards your company believes are important. Fortunately, there is an API to create additional tests as plug-ins to the Model Review plug-in. This class will present step-by-step instructions for creating a plugin that you can use to improve collaboration in your Revit projects. Learning Objectives At the end of this class, you will be able to: Locate the API documentation Create the appropriate class module Implement the interface methods Deploy the plug-in About the Speaker Robert is the design technology manager for Sparling, a specialty electrical engineering and technology consulting firm in the United States, headquartered in Seattle, Washington. He provides strategic direction, technical oversight, and high-level support for the Sparling enterprise design and production technology systems. He is instrumental in positioning Sparling as an industry and client leader in leveraging technology in virtual building and design. Robert has been writing code for customizing AutoCAD since the release of AutoCAD v2.5. rbell@sparling.com

Introduction The Model Review add-in provides a great way to check a model for issues without manually or visually inspecting the model. The add-in not only checks the model, but can also correct some of the issues it exposes. The developer of the tool also provided an API to create additional plug-ins for the Model Review add-in. This makes it possible to expand the functionality of the add-in to meet the needs of your company. This handout supplements the video recording of this class. Locate the API documentation The API documentation consists for a PDF and a sample Visual Studio project. Both are located in the following folder for Revit 2012 installations: Folder Location 64-bit operating systems %ProgramFiles(x86)%\Autodesk\Autodesk Revit Model Review 2012\Plugin-Source 32-bit operating systems %ProgramFiles%\Autodesk\Autodesk Revit Model Review 2012\Plugin-Source Developing_ModelReview_Plugins.pdf After an introduction, the PDF, titled "Developing Plug-in Checks for Autodesk Revit Model Review", provides an overview of the methods that can be implemented in the plug-in by an interface to the Model Review add-in. It goes on to describe the procedure for creating a new Model Review plug-in. There is an explanation of the filtering mechanism used by the Model review add-in which the plug-in can initialize. The structure of the data passed between the addin and the plug-in is documented in a table. Finally, the methods in the interface are described. Sample Visual Studio Project The sample project (located in a subfolder named SamplePlugin in the folder noted above) will not run without modification in Revit 2012. It was written for earlier versions of Revit and was not updated for Revit 2012. Therefore the target framework is incorrect, references need to be corrected, and the transaction model has changed. Therefore, this class is presented to provide a working plug-in for Revit 2012. Create the appropriate class module The "Developing Plug-in Checks" documentation outlines the procedure for creating a new Model Review plug-in and is as follows: Procedure 1. Create a new Visual Studio Class Library Project 2

2. Add a reference to the RevitAPI.dll, located in Revit's Program folder. a. A reference to RevitAPIUI.dll is not required, but needed if you plan on using the Revit UI. 3. Add a reference to ModelReviewPlugins.dll, located in the main Autodesk Revit Model Review folder. 4. Create a class to implement the check 5. Add the IPluginCheck interface to the class 6. Implement the methods of the interface (see below) 7. Build the project 8. Copy the resulting DLL to either the Plugins subfolder located in the main Autodesk Revit Model Review folder or in an alternate folder as specified in the add-in interface. After completing the procedure with a successful build, the new plug-in will be available in the add-in Manage interface's menu under Check> Add> Plugins. Implement the interface methods There are five methods in the IPluginCheck interface. Two are required to be implemented. The other three add functionality and therefore are often implemented. Initialize public void Initialize(ICheckData data) This is a required method. The method initializes information about the check. Note that a PluginGUID should be provided and you should not replicate an existing GUID in a new plug-in. Configure public void Configure(System.Windows.Forms.IWin32Window window, ICheckData data) This is an optional method. Use it to gather configuration information from the user when the check needs to support user configuration. GetReportVariables public List<ReportVariable> GetReportVariables() This is an optional method. This method allows you to create variables that will be used in the report. The add-in's configuration tool uses this method. RunCheck public void RunCheck(ICheckData data) This is a required method. It performs the check, determines if the checks passes or fails, and provides supporting data. There is a typical process that should be followed by the code implementing this method: 1. Retrieve configuration data 2. Retrieve a list of objects (the filtering mechanism can reduce the number of objects) 3. Determine pass or fail 3

4. Build a report 5. Build a results tree 6. Store results CorrectCheck public void CorrectCheck(System.Windows.Forms.IWin32Window window, ICheckData data) This is an optional method. It is called when the user clicks on the Correct button. It should change the Revit model so that the bad objects are corrected and the objects would now pass a check. Note that this correction is running in a modeless application so it is mandatory to use transactions. Also, never store objects directly, instead store object IDs. Finally, never assume the object exists; always check for a valid object. After the correction is complete the plug-in check is automatically run so there is no need to reset the results in this method. Deploy the plug-in Check files that use a plug-in still need to be added to the Model Review check file list. This is done by using the add-in Manage interface's menu, Profile> Edit> Standards> Add. This edits a file in the main Autodesk Revit Model Review folder called ModelReview.config, which is an XML-based file. This folder is read-only to normal users so either Revit needs to be run as an Administrator to use the interface to add the check file, or the file needs to be externally edited and replaced using administrative privileges. Note that the location of the plugin DLL does not need to be in the main Autodesk Revit Model Review folder structure when an alternate location is specified in the Manage interface so the plugin could be located in a separate folder where the user has modify rights. But this still does not alleviate the read-only issue with the configuration file. Conclusion This working project, along with the API documentation, should give you the confidence to develop your own plug-ins to expand the functionality of Autodesk's Revit Model Review add-in. 4

Code Samples Main.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using BIMreviewPlugins; using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Architecture; using Autodesk.Revit.DB.Structure; using Autodesk.Revit.DB.Mechanical; using Autodesk.Revit.DB.Electrical; using Autodesk.Revit.DB.Plumbing; namespace Sparling_Model_Review_Plug_In public class Reference_Planes_On_Specified_Workset: IPluginCheck #region Declarations private string _worksetname; private int _worksetid; private IList<Workset> _worksets; #endregion #region PrivateMethods private string buildbadelementtable (List<ReferencePlaneResult> badelements) // make an HTML table for the report StringBuilder sb = new StringBuilder(); sb.appendline("<table border='1'>"); sb.appendline(string.format( "<tr><th>0</th><th>1</th><th>2</th></tr>", CommonResources.String_ID, CommonResources.String_Type, CommonResources.String_Problem)); for (int i = 0; i < badelements.count; i++) string prob = string.format( "0 " + CommonResources.String_Is + " 1 " + CommonResources.String_AndNot + " 2", CommonResources.String_Workset, badelements[i].worksetname, _worksetname); sb.appendformat( "<tr><td>0</td><td>1</td><td>2</td></tr>", badelements[i].id, CommonResources.String_ReferencePlane, prob); sb.appendline("</table>"); return sb.tostring(); private TreeNode buildelementtree(list<referenceplaneresult> badelements, ICheckData data) TreeNode node = new TreeNode(CommonResources.String_ReferencePlanes); foreach (ReferencePlaneResult e in badelements) TreeNode elementnode = new TreeNode(string.Format( "0 (1=2)", e.name, CommonResources.String_ID, e.id.tostring())); 5

// use the Tag to store whatever data you want // (recommend the ID or UniqueID for an element) // this will be used later for highlighting, etc. elementnode.tag = e.id; node.nodes.add(elementnode); return node; private IList<Workset> getworksets (ICheckData data) FilteredWorksetCollector worksetscollector = new FilteredWorksetCollector(data.RevitDocument); worksetscollector.ofkind(worksetkind.userworkset); IList<Workset> worksets = worksetscollector.toworksets(); return worksets; private WorksetId getworksetid (string wsname) WorksetId wsid = null; foreach (Workset workset in _worksets) if (workset.name == wsname) wsid = workset.id; _worksetid = workset.id.integervalue; return wsid; private string getworksetname (int chkid) string wsname = string.empty; foreach (Workset workset in _worksets) if (workset.id.integervalue == chkid) wsname = workset.name; return wsname; #endregion #region IPluginCheck Members public void Initialize(ICheckData data) // set up basic check information data.filter = CheckInfo.FilterType.Elements; data.filtersubtypes = new string[1] CommonResources.String_RevitReferencePlane; data.isconfigurable = true; data.correctable = true; data.supportsfamilydocuments = false; // generate your own GUID and place it here data.pluginguid = "90AE4CA5-9FDE-4837-BA68-420F07A0768E"; // initialize configuration data in case someone runs it without configuration if (data.configdata == null) data.configdata = CommonResources.String_SharedLevelsGrids; _worksetname = data.configdata; // fail/pass messages data.failmessage = "<B>%CheckName%: %CheckResult%</B><BR/><BR/><P>" + CommonResources.String_ThereWere + " NumberOfBadElements " + CommonResources.String_SomePlanesFail + "</P>BadElementTable"; data.passmessage = "<B>%CheckName%: %CheckResult%</B><BR/><BR/><P>" + CommonResources.String_AllPlanesOK +"</P>"; 6

public void Configure(System.Windows.Forms.IWin32Window window, ICheckData data) // get previous configuration data if (data.configdata!= null) _worksetname = data.configdata; SpecifyWorksetForm cfgform = new SpecifyWorksetForm(); cfgform.selectedworkset = _worksetname; if (cfgform.showdialog(window) == DialogResult.OK) // store configuration as string to be persisted in the check file data.configdata = cfgform.selectedworkset; _worksetname = data.configdata; public List<ReportVariable> GetReportVariables() // fill in the report variables, if any List<ReportVariable> vars = new List<ReportVariable>(); vars.add( new ReportVariable( ReportVariable.VariableTypeEnum.Value, "NumberOfBadElements" ) ); vars.add( new ReportVariable( ReportVariable.VariableTypeEnum.Table, "BadElementTable" ) ); return vars; public void RunCheck(ICheckData data) // unpack the config data _worksetname = data.configdata; // get workset ID of target workset _worksets = getworksets(data); WorksetId wsid = getworksetid(_worksetname); // create a structure to store the bad results List<ReferencePlaneResult> badelements = new List<ReferencePlaneResult>(); // check only when target workset is found if (wsid!= null) // the filterdata contains the objects to check (if appropriate) if (data.filterdata!= null) foreach (object obj in data.filterdata) ReferencePlane myref = obj as ReferencePlane; if (myref!= null) // test the reference plane Parameter wsval = myref.get_parameter("workset"); if (wsval == null) continue; if (wsval.asinteger()!= wsid.integervalue) ReferencePlaneResult result = new ReferencePlaneResult(myRef); result.worksetname = getworksetname(wsval.asinteger()); badelements.add(result); else MessageBox.Show(CommonResources.String_The + " " + _worksetname + " " + CommonResources.String_WorksetNotFound, CommonResources.String_UnneededCheckTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); data.result = CheckInfo.ResultType.Passed; 7

// check status if (badelements.count == 0) data.result = CheckInfo.ResultType.Passed; else data.result = CheckInfo.ResultType.Failed; // store the bad result to be returned later for correction data.resultdata = badelements; // build the replaceable tokens for the report data.reporttokens = new Dictionary<string, string>(); data.reporttokens.add("numberofbadelements", badelements.count.tostring()); data.reporttokens.add("badelementtable", buildbadelementtable(badelements)); // populate the node tree data.resultstree = buildelementtree(badelements, data); public void CorrectCheck(System.Windows.Forms.IWin32Window window, ICheckData data) // go thru each of the reference planes List<ReferencePlaneResult> warnings = data.resultdata as List<ReferencePlaneResult>; if (warnings == null) return; // we need to do this in a transaction Transaction trans = new Transaction(data.RevitDocument); trans.start("fixreferenceplaneworkset"); foreach (ReferencePlaneResult result in warnings) // get the element Autodesk.Revit.DB.ElementId eid = new Autodesk.Revit.DB.ElementId(result.Id); Element e = data.revitdocument.get_element(eid); if (e!= null) // get the parameter Parameter p = e.get_parameter("workset"); if (p!= null) p.set(_worksetid); trans.commit(); #endregion ReferencePlaneResult.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Sparling_Model_Review_Plug_In /// <summary> /// Simple class to represent a failed reference plane result /// </summary> class ReferencePlaneResult public string Name; public int Id; public string WorksetName; public ReferencePlaneResult(Autodesk.Revit.DB.Element e) Name = e.name; Id = e.id.integervalue; 8

SpecifyWorksetForm.cs using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Sparling_Model_Review_Plug_In public partial class SpecifyWorksetForm : Form private string _selectedworkset; public string SelectedWorkset get return _selectedworkset; set _selectedworkset = value; public SpecifyWorksetForm() InitializeComponent(); private bool ValidateInput() if (inpworksetname.text.trim() == string.empty) MessageBox.Show(this, CommonResources.String_SpecifyWorkset, CommonResources.String_SpecifyWorksetTitle); inpworksetname.focus(); return false; return true; private void SpecifyWorksetForm_Load(object sender, EventArgs e) this.text = CommonResources.String_SpecifyWorksetTitle; label1.text = CommonResources.String_SpecifyWorksetLabel; inpok.text = CommonResources.String_OK; inpcancel.text = CommonResources.String_Cancel; inpworksetname.text = _selectedworkset; private void inpok_click(object sender, EventArgs e) if (ValidateInput() == true) _selectedworkset = inpworksetname.text.trim(); this.dialogresult = DialogResult.OK; this.close(); CommonResources String_AllPlanesOK All reference planes met the criteria of this check. String_AndNot and not String_Cancel Cancel String_ID ID String_Is is String_OK OK String_Problem Problem String_ReferencePlane Reference Plane String_ReferencePlanes Reference Planes String_RevitReferencePlane ReferencePlane String_SelectWorkset Select Workset String_SharedLevelsGrids Shared Levels and Grids String_SomePlanesFail reference planes which did not meet the criteria of this check. 9

String_SpecifyWorkset You must specify a workset name. String_SpecifyWorksetLabel Specify the Workset that Reference Planes should be on: String_SpecifyWorksetTitle Specify Workset String_The The String_ThereWere There were String_Type Type String_UnneededCheckTitle Unneeded Check String_Workset Workset String_WorksetNotFound workset cannot be found. Form Image 10