Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto-generate Zero Touch Node classes to cover all element generation methods in Revit API. #975

Open
ikeough opened this issue Apr 21, 2016 · 0 comments
Assignees

Comments

@ikeough
Copy link

ikeough commented Apr 21, 2016

The Idea

Implement tooling to auto-generate zero touch node classes to cover all element generation methods in the Revit 2017 API (and possibly more).

History

Two years ago, the Dynamo team had an internal project to attempt to wrap Revit API methods to make them work as nodes for Dynamo. This was when Dynamo's engine was written in F#. Initially, we tried doing this using .net reflection. But, the Revit API does not load correctly using reflection. Moreover, reflection gave us the names of methods and parameters, but did not give us any other helpful information which we would use to get descriptions for the node, the ports, etc. The RevitAPI.xml did give us this information however, so we wrote a python script which read types from this xml and emitted c# classes in individual .cs files.

A decision was made not to make this library public as it was a tight wrapping around the Revit API and the node names were not comprehensible to the user in the same way that Dynamo node names are. That is, they did not follow the static constructor pattern like Point.ByCoordinates(...), any they required that the user would need to know and understand specific Revit types, like CurveArrArray. It was deemed to big an effort at the time to create mappings between all of these types and names that were more Dynamo-like.

The original python script can be found here: https://github.com/DynamoDS/Dynamo/blob/e1944bcba7590f49e2860645a2d92f6d07f6fd97/tools/NodeGenerator/NodeGenerator.py.

Fast forward two years...

Reflecting over the Revit API still doesn't work. But a new effort to write c# tooling to use the RevitAPI.xml for auto-wrapping has begun here. The tools we've developed for Dynamo for Revit to do element binding, transaction management, etc. are much more sophisticated then what we had two years ago. The Element base class now contains a great deal of the logic for element binding, transaction management, etc. It is possible that an auto-generated library could use or extend this base class to make the auto-generated types as small as possible.

Benefits

Auto-generating Dynamo node classes to wrap the Revit API has several key benefits. First, we can rapidly expand the coverage of the Revit API that we expose as nodes to our Dynamo for Revit users. Second, an auto-generated node library would be fast to update when the Revit API is updated. Third RTF-compatible tests can be automatically generated. And finally, documentation for the node can be automatically generated by lifting the comments from the RevitAPI.xml file.

Challenges

For this type of auto-wrapping exercise there are several challenges which are detailed below. It is possible that a base class for our auto-generated types can exist which includes much of the functionality required when addressing these challenges, such that the auto-generated types need only tightly wrap the Revit API calls.

Element Binding

When an element is created, the element's id needs to be serialized and added to trace. This allows Dynamo to find that element in the Revit model on subsequent executions, so that that element does not need to be recreated. Element binding logic must be added to the auto-generated type's constructor. And must handle both the case where the element does not exist in Revit and is being created, and the case where the element is only being modified.

Document Modification Events

Dynamo for Revit listens for document modification events like when elements are added, modified, or deleted. Auto-generated types need to handle these three cases, and manage the serialized element ids in trace to keep Dynamo in sync with Revit. Most of this should be handled by Dynamo for Revit's DocumentManager.

Transaction Handling

Dynamo batches transactions to the extent that it is possible to do so. For example, if a node to the left of the graph requires that a transaction be started, then the transaction is opened and held open so that subsequent node executions can use the same transaction. Auto-generated types need to have the correct behavior with regards to transaction management, taking advantage of open transactions, and opening transactions where appropriate. Most of this should be handled by Dynamo for Revit's TransactionManager

Name Mapping

Dynamo uses static constructor for element creation with names which describe the required inputs, i.e. Wall.ByCurveAndHeight(...). As Revit API methods are not named in this way, a mapping will have to be defined in the type generator between the Revit API method and the design Dynamo-like naming. This mapping can be produced in a separate config file, so that the mapping can be edited by project stake-holders like @kronz, without having to edit the code.

Testing

Dynamo for Revit is tested using NUnit tests that are run with the Revit Test Framework. Auto-generated types would also need to generate unit tests which validate the basic conditions null/valid/invalid for all combinations on parameters.

Starting Small

We do not have to wrap the entire Revit API to start. A logical place to start would be methods in the Revit API which create and modify elements. Once those are stabilized, we can move to element properties, etc. The auto-generated types can go into their own library and be released early as beta functionality to gather community feedback.

Edge Cases

There will be edge cases. The first solution for these is to simply not generate node classes for the problematic types, and provide documentation somewhere listing these edge cases.

@ikeough ikeough self-assigned this Apr 21, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant