This project stands or falls on your contribution.

Besides lots of todos regarding the core system, hundreds of nodes want to be ported. Some of them being complex, but also many simple ones, which can be implemented quicker than you can say some phrase of medium length.

It's very easy to write your own nodes. Basically the only thing you need is a text editor. However, the best way to get your nodes into the VVVV.js repository on GitHub is to follow these steps:

  1. Fork the project's Git Repository on GitHub
  2. There's one .js file for each node category in the 'node' directory. Add your code to the corresponding file, or create a new one, if you start a new category.
  3. Adjust the meta data (see below)
  4. Create a dummy module and add it to the vvvv_js_modules directory, if necessary (see below)
  5. Commit your changes to your fork, and make a new issue at the GitHub page, to announce your node

The anatomy of a VVVV.js node

The following shows the Add (Value) node, which is located in the file vvvv.js/nodes/VVVV.Nodes.Value.js as an example.

VVVV.Nodes.AddValue = function(id, graph) {
  this.constructor(id, "Add (Value)", graph);
  
  this.meta = {
    authors: ['Matthias Zauner'],
    original_authors: ['VVVV Group'],
    credits: [],
    compatibility_issues: []
  };
  
  var input1In = this.addInputPin("Input 1", [0.0], this);
  var input2In = this.addInputPin("Input 2", [0.0], this);
  
  var outputOut = this.addOutputPin("Output", [0.0], this);

  this.evaluate = function() {
    if (input1In.pinIsChanged() || input2In.pinIsChanged()) {
      var maxSpreadSize = this.getMaxInputSliceCount();
      
      for (var i=0; i<maxSpreadSize; i++) {
        outputOut.setValue(i, parseFloat(input1In.getValue(i)) + parseFloat(input2In.getValue(i)));
      }
    }
    
  }

}
VVVV.Nodes.AddValue.prototype = new VVVV.Core.Node(); // quasi inheritance

The first few lines are pretty obvious: choose an object name prefixed by the VVVV.Nodes namespace. Call the "base class" constructor by supplying the nodename ("Add (Value)" in this example), and adjust the this.meta object.

The lines

var input1In = this.addInputPin("Input 1", [0.0], this);
var input2In this.addInputPin("Input 2", [0.0], this);
  
var outputOut = this.addOutputPin("Output", [0.0], this);
create in- and output pins. The first argument refers to the pin name, the second one is the default value. In VVVV.js, spreads are simply arrays, there's no explicit spread data structure. Note in the example above, that [0.0] means a default value of a one-sliced spread. You'll always have to supply an array here, even if the default value is just one slice.

Let's have a look at the evaluate function, which is called every frame.. There are three methods you'll need:

Pin changes

if (input1In.pinIsChanged() ...)
  ...
Using the pinIsChanged() method, you can find out, if an input pin has changed during the last frame, and therefore the node has to be evaluated. This helps you creating a clever path through your node, which saves ressources by only calculating, if really needed.

Maximum Input Slice Count

var maxSpreadSize = this.getMaxInputSliceCount();
gives you the maximum slice count of all input pins.

Reading input values

input1In.getValue(i);
returns the i-th slice of the input1In input pin. This method does an automatic modulo operation on the index, meaning that, if you call inputpin.getValue(10) on a pin with a spread of 8 slices, the 2nd slice will be returned.

Setting output values

outputOut.setValue(i, ...)
sets the i-th slice of an output pin. This will cause the pinIsChanged() method in other nodes, which are connected to this pin, to return true. There's no explicit setPinIsChanged() method as in pure VVVV. Also note, that here the index is not auto-moduloed.

Spread size

Find out the spread size of a single pin through
inputPin.values.length
As you can see, you can access the values property of a pin directly. However, writing directly into the values array will not set the changed flag for the pin.

Meta Data

Fill the meta object with correct values. This is needed to track you as an author, as well as to document known issues. Here's a sample:
this.meta = {
  authors: ['Your name', 'this other guy\'s name'],
  original_authors: ['The author of the original VVVV node, if any exists'],
  credits: ['papers', 'websites', 'books', 'libraries', 'and other sources used do develope the node'],
  compatibility_issues: ['issue1', 'issue2']
};
Note that the object properties are all arrays. Authors, original authors and credits should be pretty clear. The compatibility_issues property should contain issues, which describe the progress of node development, regarding the range of functionality of the original VVVV node. Use the following checklist, to find out what to put in here:

About Dummy Modules

There might be some VVVV.js nodes, that don't exist in pure VVVV (for example the whole Canvas category). To be able to create those nodes in VVVV, we use (dummy) modules.

If you write a node which doesn't have an original VVVV counterpart, create a module with the full nodename as filename (e.g. "BezierCurve (Canvas VVVVjs).v4p"), and place it into the vvvv_js_modules directory. Add the input and output pins, named just like in the javascript code. You can leave the module empty, or add some dummy behaviour. For example, the BezierCurve (Canvas VVVVjs) node, uses the original VVVV's BezierLine (GDI) node, to get at least some output for developing purposes.