Packages are a way to code custom nodes for Serpens. These can then interact with other nodes inside the addon to provide new capabilities.
You can package these nodes to distribute them to others. If you want to do this for free or sell these packages is up to you.
A custom node can do anything that a Serpens node can. You can implement almost any functionality that you can achieve with python.
The hardest part here is to achieve a good balance between usability for non-python users and functionality.
The following pages provide insights into what functions you have available for creating your nodes, but it can be very useful to look at nodes that are included in Serpens to understand how we approach certain problems. For questions, you can also always ask in the discord server.
Development
You can use the file above to develop your packages. Create a new folder somewhere with the name of your package. Move this file into that folder.
Open the file and replace the serpens root path with the install path of serpens. Then run the script with python dev.py
This will copy all files and folders in your package folder to the serpens nodes folder. It will then keep track of changes in your files and update the copied versions accordingly.
What this allows you to do is to use git to track your changes separately from your serpens install.
When you’re have a complete release you can use python dev.py --build to create a zip file with your package.
The serpens file structure looks as follows:
The nodes can be found in the nodes folder. You can create new categories here, simply by adding a folder and adding an empty __init__.py file. Then create python files in these folders to create your addon. When a package is installed your zip file will be extracted into the nodes folder and merged with whatever already exists.
How Serpens works
Serpens 3.x creates add-ons in the following way: When the user adds a node or changes settings on the node, a function is called on that node. This function generates code in form of a single or multiline string. Parts of this string can be filled with data coming from properties on the node or inputs of the node.
Programs make the main flow of Serpens node trees. These can be Interface or Execute branches. These branches start from a trigger node. This could for example be a panel node. This panel node uses the code from its Interface outputs to fill in parts of its code. The nodes attached to those outputs do the same, meaning program branches are built from left to right, outputs use the code of their connected nodes.
Data sockets work the other way around. To go back to the panel node, the Hide input on that node has a default value. If a node is connected to it, it uses the value of the output of that node. This way data is built from right to left, inputs use the code of their connected nodes.
When settings on a node change, the code of the node is reevaluated. This evaluation function sets the code on the data outputs themselves. The nodes connected to these are then evaluated as well to update their code. This way the code gets updated all the way back to the trigger node. Nodes only trigger reevaluation of the connected nodes if their code actually changed. If a node is updated but didn’t change its code, no update is triggered.
When a trigger node like the panel is reevaluated and its code changes, this runs the code. The trigger node now has all the code immediately accessible, everything is cached because it is already updated when it reaches the trigger node.
This approach has the advantage that compiling the code is instant. It has disadvantages though as there is no general environment where the entire addon lives in. In some cases, this makes the development code different from the export code.
Nodes
When writing a node, you are mainly writing the evaluation function. This sets code on the data outputs and code on the node itself, including the main code, register, unregister, import, and imperative.
There are certain events you can respond to, like sockets getting added, connected, or updates from referenced nodes.
Sockets of the node handle everything regarding data conversion, connected nodes, and their values. This means you can concentrate on writing the functionality of the node itself and don’t need to worry about the internal workings of Serpens. This will only come into play if you’re writing more complex nodes.
See the next page for everything you can use to write a node.

