Thursday, May 30, 2013

New Feature: StartupScript in RevitPythonShell

Here is a new hidden feature in recent versions of the RevitPythonShell: You can specify a script to start when Revit starts. The script is called during the IExternalApplication.OnStartup event when all the Revit plugins get to do their initialization.

This feature is still not quite official yet, but I have been using it for various purposes internally and think it works quite nicely. There are some changes between the code I have locally and what you probably have installed - I will point these out below.

To specify a StartupScript for RevitPythonShell, add a tag called StartupScript to the RevitPythonShell.xml file at the same level as the Commands, Variables, SearchPaths and InitScript tags. This tag has a single attribute src that specifies the path to the script to run.

You can find the RevitPythonShell.xml file in the folder %APPDATA%\RevitPythonShell2013.

This feature is also present in deployed RpsAddins!

Example:

<?xml version="1.0" encoding="UTF-8"?>
<RevitPythonShell>
  <StartupScript src="c:\path-to-your-script\your-awesome-startup-script.py"/>
  <Commands>
    <Command name="Hello World" src="C:\...\helloworld.py" group="Examples"/>
    <!-- ... -->

NOTE:

If you are not building from source, then the attribute to use in the StartupScript tag is still source. I changed it to src for consistency with the Command tag. Future versions of RevitPythonShell (especially the 2014 line) will use src as described in this post!

There is currently no GUI for changing the StartupScript. Also, this is somewhat of a specialist feature: You probably don't want to use it except for some very special cases.

So... what can you do with a startup script? So far, I have used it for two projects...

In the first project, I load a web server and hook it up to the Idling event so that I can provide an HTTP interface to Revit. My day job involves extracting an abstract model of simulation relevant aspects of a building from Revit, much like gbXML and being able to do that from outside Revit gives me some flexibility.

In the second project, I was automating a solar study: For each window in an elaborate model, I traced rays from a grid on the window to the sun from the SunAndShadowSettings to determine the percentage of direct sunlight a window gets - for every 15 minutes in a whole year! Since the model was big, with a lot of neighboring buildings modeled as mass objects, ray tracing (using the FindReferencesByDirectionWithContext method) gets very slow. Simulating a single day takes about 20 minutes. And simulating the whole year just broke down with Revit crashing. So... I decided to do each day separatly, and just start Revit after each day - the startup script would check the __vars__[START_DAY] variable to get the current day to simulate and on successful simulation, increment that day (this is where the writeable __vars__ feature was born) and quit Revit. Then I wrapped that up in a simple script that just started looped 365 times, starting Revit and waiting for it to finish.

Side note: quitting Revit is not that easy. Or really easy, whichever way you want to view it. I ended up using this code to force the process to die:

from System.Diagnostics import Process
p = Process.GetCurrentProcess()
p.Kill()

No comments:

Post a Comment