A node class is like a function or method. It takes some input, processes it, and produces some output.
When you write a node class using Vuo's API, the node class consists of:
Vuo currently provides an API for the C programming language. (Node classes can also reference code in C++, Objective-C, and any other language that exports C symbols; see Developing a Library Module and Managing Dependencies.) Support for other programming languages is planned.
The easiest way to start developing a node class is with one of the example Qt projects for a node class, which are provided with the Vuo SDK.
test.vuoize.cto your node class file name.
test.vuoize.cto your node class file name.
test.vuoize.c, in the Module Metadata call, change "Vuoize Text" to the title that you want to appear on the node.
Your node class should now be listed in your Node Library. You can now add it to a composition and see it perform the task defined in its nodeEvent() function.
The next step is to modify the nodeEvent() function so that your node actually does something interesting. To learn how, read on.
To implement a node class, you need to:
When you implement a node class, the first thing you have to decide is the class name. Every node class has two names: a class name (like vuo.math.add.integer) and a title (like Add). In the Vuo Editor, you can see the difference between titles and class names by switching between the "Titles" view and the "Class names" view of the Node Library. After a node has been added to a composition, its title can be changed, but its class name always stays the same. When you create a node class, the file name is the node class name. For example, the node class with name vuo.math.add.integer is implemented in a file called
Here's an example of metadata for a node class:
The Module Metadata macro takes a JSON-formatted argument. The argument includes the default title for nodes of this node class, a description to help users understand how to use the node class, an array of keywords used when searching the Node Library, and a version number to help users upgrade and manage their node classes.
Node classes are not the only files in Vuo that can define module details. You'll see this in Developing a Port Type and Developing a Library Module. The title, description, keywords, and version can be defined in other types of files as well.
But some module details are specific to node classes. The module details above include whether the node class is an interface, which affects how the node is rendered in a composition.
For more information, see the documentation for Module Metadata.
When you implement a node class, you have to implement certain functions that define what happens when a node receives an event. You implement different functions depending on whether the node class is stateless or stateful.
A stateless node class (like Add) is simpler. It just has input ports and output ports; given the same input, a stateless node always produces the same output. A stateful node class (like Count) additionally keeps track of its state. It can remember its progress, and it can fire events when something happens in the background.
For a stateless node class, you just need to implement one function: nodeEvent. The nodeEvent function is called each time a node of your node class receives an event through any input port. (If the same event is received through multiple input ports, the nodeEvent function is called just one time.) Its arguments represent input and output ports of the node.
As a simple example, here's the nodeEvent function for the vuo.math.subtract.integer node class:
The above nodeEvent function has a VuoInputData parameter for each input port and a VuoOutputData parameter for each output port. (The refresh port and done port are added to each node automatically.) Both VuoInputData and VuoOutputData define data-and-event ports. The parameter name (a, b, or difference) is the port name that appears on the node.
The second argument of VuoInputData defines details about the input port in JSON format. In this case, it specifies the default value for the input port when a node is first added to a composition.
The body of nodeEvent defines what happens when a node receives an event. In this case, it subtracts the two input port values and sets the output port value. Notice that
difference is a pointer to the VuoOutputData type (VuoInteger).
For a stateful node class, there are several functions to implement.
You also need to implement the nodeInstanceInit function and the nodeInstanceFini function to set up and clean up the node's state. The nodeInstanceInit function is called when the composition starts or when the node is added to a running composition. The nodeInstanceFini function is called when the composition stops or when the node is removed from a running composition.
As an example, let's look at a simplified version of the vuo.math.count.real node class. Its only input port is increment. Here are the functions for that node class:
The state of the node is called instance data. It's created by nodeInstanceInit and passed, via VuoInstanceData parameters, to nodeInstanceEvent and nodeInstanceFini. Notice that the return type of nodeInstanceInit and the type passed to each VuoInstanceData call must match. Currently, it needs to be a pointer type; support for non-pointer types is planned. Unlike the type passed to VuoInputData or VuoOutputData, the type passed to VuoInstanceData doesn't have to be a port type. For example, it can be a struct type defined in your node class. The name of the VuoInstanceData parameter (
countState) isn't important; you can choose any name. Notice that
countState is a pointer to the VuoInstanceData type (
Besides the instance data, another difference between this example and the stateless example above is the VuoInputEvent parameter of nodeInstanceEvent. The VuoInputEvent macro can represent either an event-only port or the event part of a data-and-event port. In this case, it's the latter. We can see this because the second argument of VuoInputEvent is the name of the corresponding VuoInputData parameter (and the port name that appears on the node). The first argument of VuoInputEvent says whether the port has an event wall, an event door, or (as in this case) neither. The value of
incrementEvent is true if the node has just received an event through its increment port.
The body of nodeInstanceEvent defines what happens when the node receives an event. In this case, it increments the count if the event came in through the increment port, then outputs the count.
The Vuo Compiler assumes that data passed between nodes is immutable.
If a node function receives a heap type (pointer) as input, it should not modify that heap data. For example, this is incorrect:
Instead, node functions should make a copy of the heap data, then modify that copy. For example:
Also, if a stateful node function sends heap data via an output port, it should not keep a reference to that heap data and modify it after the node function returns.
See Managing Memory for more information.
In addition to the Vuo API functions, your node class can define additional functions. Be sure to add a unique prefix to these function names to avoid naming conflicts with other node classes. Although the Vuo compiler renames the nodeEvent function and other API functions to avoid naming conflicts, it doesn't rename your custom functions.
If you want to share functions between multiple node classes, or use C++ or Objective-C functions in a node class, see Developing a Library Module.
A node class should not define any global variables.
Also see the source code for Vuo's built-in node classes, which can serve as examples to help you write your own node classes.
Before you can install your node class, you need to use the Vuo Compiler to compile it to a
If you're using the example Qt project for creating a node class, then you can just build the Qt project (Build > Build All).
Otherwise, you need to use the
vuo-compile command-line tool that comes with the Vuo SDK. To learn how to use
vuo-compile, see the Vuo Manual, run
vuo-compile --help, or look at the
vuo-compile command in the example Qt project.
The final step is to place your compiled node class in the correct folder, so that it will show up in the Vuo Editor's Node Library and be detected by the Vuo framework and the Vuo command-line tools. You can place it in either
~/Library/Application Support/Vuo/Modules/ or
/Library/Application Support/Vuo/Modules/. For more information about these folders, see the Vuo Manual.
If you're using the example Qt project for creating a node class, then when you build the project, the compiled node class is automatically placed in
Otherwise, you need to manually move the compiled node class (
.vuonode) file to one of these folders.
After that, the next time you start the Vuo Editor, the node class should show up in the Vuo Editor's Node Library. You can also see a list of all installed node classes by running
If you're having trouble compiling or installing a node class, try running
vuo-compile --verbose. This lists the paths that Vuo is using to compile a node class and find installed node classes.
If your node class is not showing up in the Vuo Editor's Node Library:
.vuonode) file is in
Please do not begin your node class's name with "vuo". This is reserved for node classes distributed by Team Vuo / Kosada. Please use your own company or personal name for your node classes so that Vuo users can appreciate your work (and not be confused).
Built-in Vuo nodes follow a set of naming conventions. If you develop node classes to share with other Vuo users, we encourage you to follow these conventions, too, to make your node classes easier to use.
In addition to these general rules, there are some special kinds of node classes that all have similar names:
In the Vuo Editor, when the user attempts to connect a cable between ports of different types (for example, VuoInteger to VuoReal), the connection is bridged by a type-converter node (for example, Convert Integer to Real) if one is available. This type-converter node is rendered in a special collapsed form and is attached to the input port to which it's connected. Currently, only certain built-in nodes may be used as type converters. Support is planned to allow any node with a single data-and-event input port and a single data-and-event output port of a different type to be used as a type converter. The Vuo Renderer decides when a node should be rendered as a collapsed, attached type converter, based on its connections to other nodes.
|Name, version, and behavior information to be defined by node classes, port types, and library modules. |
|Macros to help with debugging. |
|Parameter decorations to be used by node classes. |
|Node Methods: Stateless|
|Event handler method to be implemented by node classes. |
|Node Methods: Stateful|
|Setup, event handler, and teardown methods to be implemented by stateful node classes. |