Adding new Node

This page documents the essentials to make your own node for sverchok. We make several assumptions about your Python knowledge - an affinity for Python is a prerequisite. If you suck at Python, you will have a bad time trying to write nodes for sverchok (– a hard truth).

Tip

If you don’t know Python my advice to you is to read first all the shorter nodes, and take notes about parts you don’t understand. As you read more, the notes you took on previous nodes will be about techniques that re-occur in other nodes. Once you notice some repetition of the techniques you can class them, and start to associate the code with a procedure. Humans learn by extracting patterns from the chaos, but you have to see enough new material to let your brain do the pattern matching.

Also do any of the free python courses, and quit and move on from easy ones to harder ones.

To create a node:

Creation of new node can be split into next steps.

  1. Make a scripted node to test the idea.

  2. Show your node to us in an issue or create branch or fork of master in github. If it is a huge complex job we can make you collaborator.

  3. Create a file with the node code according this page in appropriate folder ..sverchok/nodes/whatever_existing_category/your_file.py

  4. Add node’s bl_idname to sverchok/index.md file in an appropriate category.

  5. Make a pull request.

This page will describe from which pats the code of a new node should consist using simple example of a node. The whole code of the node can be downloaded from the link below.

Simple node code template.

Note

This documentation describe node structure which is used in most nodes in Sverchok. However there are other experimental approaches too. In the future more advanced approach may be born because current approach has certain disadvantages.

License

Use next strings in the top of the node file:

# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE

Imports

import bpy
from mathutils import Vector
from bpy.props import FloatProperty
from sverchok.node_tree import SverchCustomTreeNode
from sverchok.data_structure import updateNode
  • You need to import bpy because we use always use bpy.types.Node and often use bpy.props

  • The Sverchok imports are needed for the availability of common Sverchok functions.

    • The updateNode is the function we add to a property to trigger updates when a slider is adjusted.

    • SverchCustomTreeNode’s definition can be found in node_tree.py, it adds a poll and several utility functions to the node class.

  • You are free to import any other useful module in that section.

Node Class

class SvScaleVectorNode(SverchCustomTreeNode, bpy.types.Node):
    """
    Triggers: vector multiple scale
    Tooltip: This node multiply vector and some value

    Merely for illustration of node creation workflow
    """
    bl_idname = 'SvScaleVectorNode'  # should be add to `sverchok/index.md` file
    bl_label = 'Name shown in menu'
    bl_icon = 'GREASEPENCIL'
Class name

A small (but significant) implementation detail of Sverchok is that name of the Node class should be identical to the bl_idname of the node class. This simplified a few things for development. This class name should start with a prefix Sv and contain only alphanumeric characters. Something like SvMyFirstNode would be fine. If you want to automatically make the node available upon startup then this classname must be added to the index.md file in the correct category.

Docstring

Triggers: This should be very short (two or three words, not much more) to be used in Ctrl-Space search menu.

Tooltip: Longer description to be present as a tooltip in UI.

More detailed description with technical information or historical notes goes after empty line. This is not shown anywhere in the UI.

bl_idname

This is the unique identifier for a node type, like a post code for a home.

bl_label

This is the name as it will appear in menus and on the node’s header when it’s first added to a node tree. Keep this short.

bl_icon

This is used to display a node icon in the shift+A menu. There’s also a sv_icon implemented for custom icons (but for a different topic)

value: FloatProperty(name="My value", default=2, update=updateNode)

def draw_buttons(self, context, layout):
    layout.prop(self, "value")
Properties

Each node can have properties which can be displayed in the its UI and used in its code. Read more about properties.

def draw_buttons

This is where we add any custom UI (sliders/buttons/enumerators), this is like the draw function of a panel. This function can be called many times a second so avoid doing intense computation inside it. This function is for nothing other than drawing the current state of the node, it isn’t for updating node properties. More information in the Blender documentation.

def sv_init(self, context):
    self.inputs.new('SvVerticesSocket', "Vertices")
    self.outputs.new('SvVerticesSocket', "Vertices")
def sv_init

This function is used to setup the initial state of a node. This is where you add the default sockets and their properties. This is where we tell a socket to appear as a slider. To better get an idea of what it’s used for do a search for this function in the Sverchok repository.

def process(self):
    # read input value
    input_vertices = self.inputs["Vertices"].sv_get(default=[])

    # vectorization code
    output_vertices = []
    for in_vert_list in input_vertices:  # object level
        out_vert_list = []

        for v in in_vert_list:  # value level

            # perform the node function
            out_vert_list.append((Vector(v) * self.value)[:])

        output_vertices.append(out_vert_list)

    # wright output value
    self.outputs["Vertices"].sv_set(output_vertices)
def process

This function is called whenever the node is told to update. It’s where we get the content of the input sockets, and set the output of the output sockets. This function is sometimes big..and sometimes merely a few lines - you should look at existing nodes to get a feel for what to put in there.

First line of the process method read data from the input socket with name Vertices. If the socket is not connected the input data will be an empty list. Expecting format of vertices is next:

[[[x, y, z],   <- object 1, vector 1
  [x, y, z]],  <- object 1, vector 2

 [[x, y, z],   <- object 2, vector 1
  [x, y, z]]]  <- object 2, vector 2

To understand the Sverchok data structure read this tutorial.

Next step is unroll the vertices data structure, perform operation on single vertices and wrap the result back. Last string assign the result to output socket.

Register node class

def register():
    bpy.utils.register_class(SvScaleVectorNode)


def unregister():
    bpy.utils.unregister_class(SvScaleVectorNode)

All node classes should be registered so Blender could be able to use them. register function is called when the add-on is enabled, unregister when you hit f8 (or execute script.reload in Python console editor) or disable Sverchok.

Warning

Fixing existing nodes is not the same as create new ones. Existing node can be used in some layouts and new changes should not break them. It’s possible to add new logic to an existing node but don’t do next:

  1. Change bl_idname of a node

  2. Remove or rename sockets (use labels for socket renaming)

  3. Adding new socket in between existing sockets. We prefer that you add sockets behind the last existing socket for either self.inputs or self.outputs. This is the rule only if access to sockets is made by their indexes.

  4. There are other reserved property names see the bpy.types.Node baseclass in Blender docs and Sverchok’s custom node mixin class. (this is true and when new node is created)