This tutorial will guide you through the process of programming a new node that will be available as a plugin.
A node contains one or more input- and output slots. The most important method of a node is the Update(…) method which calculates the values of all the output slots when any of the inputs change.
Connections can be made between input and output slots where one output slot can be connected to any number of input slots. Note that one input slot can have only one connection. Not shown in the diagram but also important is that input slots have a member property which indicates this slot as an “active” slot meaning it activates a call of the Update(…) method of the node when the value of the slot has changed. So it is possible to create slots which are called “passive” meaning a change of their values does not update the outputs of the node owning the slot.
Now if two slots are connected a change of an output slot´s value triggers a call of the Update(…) method of all connected nodes.
As we know the modulus calculates the remainder of a division operation. Because this operation needs two arguments we know that our node will get two input slots and one for the result of the calculation. This formula shows what we want to do:
result = number % modulus The following steps must be performed before we can start:
Set up a new Library (.dll) project in your preferred C# editor. The Nodekit uses the the last part of the file name of the library as the new group name containing the nodes.
For example, the file name “part1.part2.dll” will cause that Nodekit names the new node group “part2”. Add the TagTool.Core.dll in the references of your project. You can find it in the installation folder of the Nodekit.
Now we can start to type our code for the node:
/* * Example of a simple node performing a mathematical operation * Created by Richard Radlherr */ using System; // It is important to import the TagTool core classes which defines // the BaseNode class using TagTool.Core; namespace TestNodeCollection.MyNodes { /** * The information attribute lets you set the name * and a description of the node you are intending to program. * * All nodes must be derived from the BaseNode class. */ [Information("Modulo", ToolTipText = "Calculates the modulus.")] public class MyClass : BaseNode { // declare neccessary input slots InputSlot number; InputSlot modulus; // declare neccessary output slots OutputSlot result; /** * Each node must have a standard constructor. */ public MyClass() { // this is the name of this instance of the modulo node. Name = "Modulo"; // Create the slot for the argument from which we calculate // the modulus. // The default value is zero // to be compatible to the most nodes from the Nodekit we use // the double datatype instead of an integer. // For the modulo calulation we use only the fixed part of the // number. number = new InputSlot(this, "Number", 0.0); // Let the slot update the node if its value changes. number.Active = true; // set a callback for parsing values - this enables a text // field for entering the value. number.ParseCallback = ParseDouble; // Similarly to the number input slot we set up the // modulus input slot. // Note that zero is not allowed in a modulo operation. modulus = new InputSlot(this, "Modulus", 1.0); modulus.Active = true; modulus.ParseCallback = ParseDouble; // create the slot containing the result of the calculation. result = new OutputSlot(this, "Result", typeof(double)); // set an initial value for the output. result.Value = 0.0; } /** * Parse callback for the numbers. */ private static Object ParseDouble(String description) { return Convert.ToDouble(description); } /** * The update method is where the work is done. */ public override void Update(Object sender) { // prevent from division by zero if((int)(double)modulus.Value > 0) { result.Value = (double) ((int)(double)number.Value % (int)(double)modulus.Value); } } /** * On initializatoin (called after loading the node) we have nothing * to do. */ public override void Initialize() { } /** * Expose each slot as property member of the class. *´The node attribute is necessary for creating the GUI * automatically * by traversing over the properties. */ [NodeAttribute(SlotType.Input, Show = true)] public InputSlot Number { get { return number; } } [NodeAttribute(SlotType.Input, Show = true)] public InputSlot Modulus { get { return modulus; } } [NodeAttribute(SlotType.Output, Show = true)] public OutputSlot Result { get { return result; } } } }
Now compile your project and put the resulting dynamic link library file into the “plugins” folder of your Nodekit installation. When started Nodekit will load all libraries containing additional Nodes from there.
Note that now a new group containing our new node appears in the menu on the left side of the editing panel:
By dragging the node into the editing pane an instance of the node is created. You can now try to enter some input values manually and look what happens. Then you could try to draw in some other nodes from the “Math” section and connect them (by dragging lines from output slots to input slots) to the Modulo node. Enter some values in the other nodes. For example: