Zero Touch Plugin Development in Dynamo

Download as pdf or txt
Download as pdf or txt
You are on page 1of 3
At a glance
Powered by AI
The key takeaways are that custom nodes can be developed in C# using static methods and classes, and that objects need to be constructed via static constructors with the By prefix. Documentation, tooltips and search functionality can be added.

The process involves referencing necessary DLLs, adding namespaces, and exposing static methods as nodes. The node will appear in the Dynamo menu in the category matching the namespace. Platform target and preferences need to be set correctly in Visual Studio.

To return multiple values, you need to add the MultiReturn attribute containing output port names. The function then returns a dictionary with the returned values mapped to the keys matching the attribute names.

Zero Touch Plugin Development

hlp edited this page 14 days ago 24 revisions


Pages 30

0.6.3 Upgrade to 0.7 version


Autobuild
Coding Standards
Concepts, Definitions and Terminology
Daylight Analysis for Dynamo
Documentation on CBNLanguageComparisonTests
Dynamo Wiki
FAQ: Developing with Dynamo
Generating the MSI Installer
Getting Started with Dynamo Development
Home
How To Create Your Own Nodes
HowTo Write Error Messages
HowTo: Load icon for method button
HowTo: Load icon for class button
Show 15 more pages

This page outlines the process of developing a custom Dynamo node in C# using the "Zero Touch" interface
An example Visual Studio 2012 project can be found here:https://github.com/hlp/ZeroTouchEssentials
Note 1: Make sure your Visual Studio project's "Platform target" is set to "Any CPU" or x64, and "Prefer 32-bit" is un-checked.
Note 2: If you are creating Geometry objects in your ZeroTouch nodes, see a VERY IMPORTANT note at the bottom.

Basics
In most cases, C# static methods and Classes can be imported without modification. If your library only needs to call functions, and not construct new objects,
this can be achieved very easily with static methods. When Dynamo loads your DLL, it will strip off the namespace of your classes, and expose all static
methods as nodes. For instance, we can create a node that takes a single number and multiplies it by 2 as follows:
namespace ZeroTouchExample
{
public class ZeroTouchExample
{
public static double MultByTwo(double inputNumber)
{
return inputNumber * 2.0;
}
}
}

A node will appear in the Dynamo menu called "MultByTwo" in the "ZeroTouchExample" category. It will have one input, called "inputNumber".

Returning multiple values


Accepting multiple inputs into a node is easy: just specify multiple parameters to your C# function. Returning multiple values from a node requires slightly more
work. First step is to reference "ProtoInterface.dll" in your project, found in the Dynamo install location, and add "using Autodesk.DesignScript.Runtime;" to the
top of your C# script. The second step is to add the "MultiReturn" attribute to your function. It should contain an array of strings, containing the names of the
output ports. Your function should then return a Dictionary containing the returned values. The keys to your dictionary should match the parameter names in
your attribute. For example:
using Autodesk.DesignScript.Runtime;
namespace ZeroTouchExample
{
public class ZeroTouchExample
{
[MultiReturn(new[] { "add", "mult" })]
public static Dictionary<string, object> ReturnMultiExample(double a, double b)
{
return new Dictionary<string, object>
{
{ "add", (a + b) },
{ "mult", (a * b) }
};
}
}
}

This creates a new node that outputs two doubles, "add" and "mult" containing the addition and multiplication of the two input numbers.

Objects
Dynamo doesn't have a "new" keyword, so objects need to be constructed via static constructors. Dynamo uses the "By" prefix to indicate a static method is a
constructor, and while this it is optional, using "By" will help your library better fit into the existing Dynamo style.
namespace ZeroTouchExample
{
public class MyLine
{
private double _x1;
private double _y1;
private double _x2;
private double _y2;
public static MyLine ByStartPointEndPoint(double x1, double y1, double x2, double y2)
{
_x1 = x1;
_y1 = y1;
_x2 = x2;
_y2 = y2;
}
public double Length()
{
return Math.sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
}
}
}

Using Dynamo geometry types


Dynamo libraries can also use native Dynamo geometry types as inputs, and create new geometry as outputs. The first step is to reference both
"ProtoGeometry.dll" and "ProtoInterface.dll" in your project, and include "using Autodesk.DesignScript.Interfaces;" and "using
Autodesk.DesignScript.Geometry;" in the top of your C# file. Dynamo geometry objects are then used like any other passed object to your functions. For
example, we can clean up our MyLine example above by using Dynamo's native geometry types:
using Autodesk.DesignScript.Interfaces;
using Autodesk.DesignScript.Geometry;
namespace ZeroTouchExample
{
public class MyLine
{
private Autodesk.DesignScript.Geometry.Point _p1;
private Autodesk.DesignScript.Geometry.Point _p2;
public static MyLine ByStartPointEndPoint(Autodesk.DesignScript.Geometry.Point p1, Autodesk.DesignScript.Geometry.Point p2)
{
_p1 = p1;
_p2 = p2;
}
public double Length()
{
return Math.sqrt(Math.Pow(_p2.X- _p1.X, 2) + Math.Pow(_p2.Y - _p1.Y, 2));
}
}
}

Documentation, Tooltips, and Search


It's best practice to add documentation to your Dynamo nodes. This is done through XML documentation tags. The main documentation for your node should be
in the <summary>...</summary> XML tags. This will appear as a tooltip over your node in the left search side bar. Documentation on specific input parameters
should appear in the <param name="inputName">...</param> XML tag.
Control over how your node appears in the Dynamo search results is similarly controlled through the <search>...</search> XML documentation tag. This tag
should contain a comma-separated list of search terms that, if matched, will cause your node to appear in search results.
To get Dynamo to pickup the tags you must enable XML documentation generation through visual studio, this setting is in the Build tab of the project settings.
We can add documentation an search to our original example as follows:
namespace ZeroTouchExample
{
public class ZeroTouchExample
{
/// <summary>
/// This is an example node demonstrating how to use the Zero Touch import mechanism.
/// It returns the input number multiplied by 2.
/// </summary>
/// <param name="inputNumber">Number that will get multiplied by 2</param>
/// <search>
/// example, multiply, math
/// </search>
public static double MultByTwo(double inputNumber)
{
return inputNumber * 2.0;
}
}
}

Migrations
As you publish newer versions of your library, you may want to change the names of ZeroTouch nodes. It is possible to specify these name changes in a
migrations file so that graphs built on previous versions of your library don't break when you create an update.
Migration files should be named in the following format: BaseDLLName.Migrations.xml. For instance ProtoGeometry.dll, Dynamo's core geometry library, has a
migration file named ProtoGeometry.Migrations.xml. The file needs to be located in the same directory as the base dll.
The migrations file should be valid XML. The file should contain one "migrations" element, containing several "priorNameHint" elements. Each prior name
element should have one "oldName" element, and one "newName" element. Old name should contain the complete name, including namespace, of the
previous method name. newName should contain the new name, also including complete namespace. See ProtoGeometry.Migrations.xml for a template
migrations file.
Note that in its current state, the migrations file gives hints to Dynamo about up how to handle missing nodes in a DLL, but doesn't specify in absolute terms a
mapping between versions. So, for instance, if you "depreciate" a node name, then begin re-using the name in a subsequent version, the migration will likely fail.

Dispose / using Statement


If you are using the Dynamo geometry library in your C# plugins, you'll need to manually manage the geometry resources created in your functions which are
not returned out of your functions. Any resources returned out of your functions will be managed by the Dynamo engine. The are two ways to do this, a
"using" statement, or manual Dispose() calls. The using statement is documented here.

IF YOU DO NOT IMPLEMENT THIS YOU WILL PUT BOTH DYNAMO AND REVIT INTO AN UNDEFINED STATE CAUSING BOTH TO MYSTERIOUSLY
CRASH!!!
Here are two examples:
With using
using (Point p1 = new Point.ByCoordinates(0, 0, 0))
{
using (Point p2 = new Point.ByCoordinates(10, 10, 0))
{
return Line.ByStartPointEndPoint(p1, p2);
}
}

With Dispose
Point p1 = new Point.ByCoordinates(0, 0, 0);
Point p2 = new Point.ByCoordinates(10, 10, 0);
Line l = Line.ByStartPointEndPoint(p1, p2);
p1.Dispose();
p2.Dispose();
return l;

You might also like