Behind the Scenes of the NBS Revit Add-in

Here is a guest post by Stephen Hamil of RIBA Enterprises, director of NBS, the national standard specification company in the UK, owned by the Royal Institute of British Architects.

They just released the new version of their Revit plug-in that integrates the Revit design model with the NBS specification model, technical guidance and National BIM Library objects.

Below, Chris and Calum from the NBS software development team give a little insight into some of the API functionality they used when developing this software:

Drag-and-drop Support from the National BIM Library

Drag-and-drop support from the National BIM Library

We make use of the IDropHandler interface from the API to allow us to drag drop from the National BIM Library NBL.

That enables us to overwrite the default behaviour of Revit when the user drops a family on a project file.

We start the process by making a call from the web browser to its owning user control:

  /// <summary>
  /// Method called from the web browser
  /// </summary>
  public override void ClickDrag(
    string downloadLink,
    string strFamilyName )
  {
    if( this.nbsUser.hasLoggedInNBL )
    {
      List<string> dragInfo = new List<string>() {
        downloadLink, strFamilyName };
 
      // Kick off the drag drop event which Revit 
      // will pick up and custom code will check 
      // if family already entered
 
      UIApplication.DoDragDrop( dragInfo,
        new dropHandler( this ) );
    }
    else
    {
      this.SignInToFloatPanel();
    }
  }

Controlling Revit from Modeless Dialogues

Controlling Revit from modeless dialogues

We use the Idling event to call into the Revit API from modeless dialogs to modify the database without causing damage.

We have a list of commands to run with an array of objects as their parameters and then run this chunk of code to process them in the Idling event handler:

  // If we have commands to process
 
  if( CommandsToProcess.Count > 0 )
  {
    try
    {
      UIDocument uiDoc = UIApp.ActiveUIDocument;
 
      // Get the first command in the list to process
 
      CommandToRun command = CommandsToProcess.First();
 
      // Get the delegate that we want to run
 
      Delegate FunctionDelegate = command.FunctionToRun;
 
      // Make sure we have the lastest UIDocument
 
      command.ListOfParameters.Insert( 0, uiDoc );
 
      // Get it's parameters
 
      object[] Parameters = command.ListOfParameters.ToArray();
 
      // Invoke our function
 
      FunctionDelegate.DynamicInvoke( Parameters );
    }
    catch( Exception ex )
    {
      ErrorLogger.LogError( "Error processing command: "
        + ex.ToString() );
    }
    finally
    {
      // Always Pop the first in the queue
 
      CommandsToProcess.RemoveAt( 0 );
    }
  }

Porting to 2014

We encountered a problem when developing the plugin to work with 2014, due to the Document class method get_Element changing to GetElement.

This was easily handled by the way we structure the plugin and have each version inheriting from the previous; we start off with a generic interface:

  public class RevitRibbon : IRevitRibbon

For Revit 2013 and 2014, we inherit the previous RevitRibbon class:

  public class RevitRibbon : Revit2012.RevitRibbon

  public class RevitRibbon : Revit2013.RevitRibbon

This allows us to simply override the one function calling the get_Element method, solving the problem without causing any damage to our existing implementations for Revit 2012 and 2013.

Docking Panel Prototype

For the Revit 2014 users, we did also look into replacing the modeless dialog by a docking panel, which is a really cool new feature.

Unfortunately, though, we ran out of time for this release. However, we’ll look at this again for version 2.1.

Here is a screen snapshot of it working in a prototype:

Docking window

Further Information

A lot of work was put into this and it looks pretty good, really linking the design model in Revit with the specification model in NBS.

Here is some further information on:

Thank you, Stephen, for providing this background information.