Custom node trees questions

I’ve been hacking away at a custom node editor, based on the custom nodes template in blender, and i’m having some minor questions.

  1. How to deal with versioning?

It’s great for a prototype sofar, however, however there are times where i expand an existing node (one of my nodes, not an existing blender one), and add an output socket or rename it with a better name. Now for any new instances i add to the graph it’ll get all the latest outputs and names, however any nodes already existing in a .blend will not be updated. I’m perfectly happy, deleting the node and re-creating it, however for any end users this is hardly a great UI experience. How do i go about updating those automatically?

  1. Previews on the node

I tried to use layout.template_preview but couldn’t get it to work, when i did get it to show all nodes were displaying the same image or flickering like it was having a seizure or something. I’m pretty sure i’m doing something wrong, but an example or some insight here would be appreciated.

  1. Node wranger.

I’m so used to ctrl-shift clicking to get a preview of a node in the shader editor, nodewrangler naturally doesn’t know about my tree or know how to make a preview are there any hooks i can hook into or am i just doomed having to duplicate that functionality completely?

  1. Color ramp, and curves UI.

I can’t seem to easily re-use the color ramp and curves UI, I can by making a dummy shader graph, instance a shader node that has the UI in it and then draw it in the drawbuttons of my UI but that seems like a rather terrible hack.

  1. Background image for the node tree?

It be nice to preview things right in the editor, but I’m unsure how, NodeTree doesn’t seem to have a background image prop nor any callbacks for drawing things?

  1. Socket settings.

I’m using all custom socket types, and it can’t seem to change things like ‘step’

import bpy
from bpy.types import NodeTree, Node, NodeSocket

class Float1Socket(NodeSocket):
    '''float1 socket type'''
    bl_idname = 'Float1SocketType'
    bl_label = "float1 Node Socket"

    def prop_update(self, context):
        self.id_data.update()

    value: bpy.props.FloatProperty(default = 0.0, description="", update=prop_update)
    
    def draw(self, context, layout, node, text):
        if self.is_output or self.is_linked:
            layout.label(text=text)
        else:
            layout.prop(self, "value", text=text)

    def draw_color(self, context, node):
        return (0.8, 0.8, 0.8, 1.0)

later on using it

        self.inputs.new('Float1SocketType', "Sides")
        self.inputs["Sides"].step = 100

The UI seems to completely ignore this and give me a step of 3

paging @jacqueslucke / @Secrop :slight_smile:

For versioning I normally add a hidden version number to the node tree graph and have a load_post handler that checks the version and perform the actual upgrades that are needed.

The previews on the nodes are doable, so might be in how you setup your code. I can think that the flickering happens when you calculate the previews during drawing? But that is just a guess.

It is best that add-ons run without the need for other add-ons to be present. I can see the benefit of having some special cases like the node wrangler, but still the specific add-ons are becoming coupled.

Background images are currently not supported. If you want something you could look at custom draw handlers.

About the Float1Socket, it seems that step is not actually defined or is it?

Ow just a tip. Asking many questions in a single post is not always the best as the answers might get scattered around, or when the post gets long it gets unclear what is answered and what not. Especially when the questions are on its own.

In the LuxCore addon, I have functions that check the inputs/outputs of nodes and add/remove them if necessary: https://github.com/LuxCoreRender/BlendLuxCore/blob/master/utils/compatibility.py#L61
Like @JeroenBakker I call these functions in a load_post handler, but I also run them before each render, because users can link or append node trees into a file after it was loaded, and these linked/appended node trees are then out of date.

As far as I know, it’s not possible for Python addons to make new instances of these.
Some, like the V-Ray addon, create helper textures as a workaround, with names starting with a dot (".") which hides them from the user in search dropdowns etc.
There are a lot of addon developers that would be very grateful if someone would make it possible to instantiate color ramps and curves from Python.

  1. IMO, it should be handled by the nodetree addon… it’s a bit difficult to generalize this with custom nodetrees…
  2. I’d like to have a draw_preview function with a gpu context as a parameter, but i’m open to any other sugestions.
  3. Making the Node Wrangler a bit more dynamic would be nice. Think we must turn it part of the Node Editor, instead of using it as an Addon (at least most of it).
  4. I’m slowly working on that, thought both are also referenced in other parts of blender that i’m not familiared with.
  5. A bit similar to (2), i think?!, but instead of nodes we could have it for nodetrees.
  6. Another thing I’m slowly working on… as in (4), any help/ideas/sugestions are welcome.

I hope you don’t mind if I add some of my own questions here:

  • Is it possible to make delete and reconnect (Ctrl+X) work with custom nodes?
  • Is it possible to make muting of nodes (M) work with custom nodes?

Both questions are related… Delete&Reconnect makes the same effect as Muting in the temporary nodetree that’s created for evaluation (#localized). This is something each custom NT must know how to deal with.
We could, however, create some kind of interface to simplify both into a simple definition/method. :slight_smile:
Normally a node has more inputs than outputs…we can peek the first linked input to be jumped, but it’s up to the nodetree…
Defining a proper usage principle is necessary!

Does this mean it’s already possible?
I have tried in the past to make a custom test node with one input and one output socket, both of the same socket type, but I couldn’t get muting or reconnecting to work.
(I guess maybe I can implement reconnecting in the free() method of the node?)

No, :cry:
A bit the same problem with the NodeWrangler… too much hardcoded stuff. (you need to code everything in the addon).
I’d prefer a nice event system in the Node Editor (for now we are limited to update(context)), and some operators that could be called in default, in case we don’t override them…

I found a workaround to have “delete and reconnect” functionality: https://github.com/LuxCoreRender/BlendLuxCore/commit/cac14d2617bdf8467fd236fe3b69c7a75511f40f
(note: allowed_inputs is a socket attribute added by my addon, not a standard feature of NodeSocket class)

The only weird thing for end users is that the behaviour of [Del] and [Ctrl+X] is swapped ([Del] deletes with reconnect, [Ctrl+X] only deletes without reconnect).

I don’t have a solution to your problem, but I do have a question. I’ve been trying for so goddamn long over the past few days to get a simple custom node working, but I can’t seem to affect the output of it all. Can you show me the rest of your code so I can see how you did it? There’s surprisingly little documentation of this stuff online.

I’m unclear on what you’re asking

I can’t seem to affect the output of it

what is it? what are you trying to archive? Are you trying to make your own custom node tree? or perhaps trying to extend cycles/eeve with a custom node?

I’m trying to make a custom node that I can connect to the rest of my material, but I don’t know how to set the output of the node.

@Secrop perhaps we could include a few new templates showing off the new custom shader/compositor nodes?

I already ask @ETFO for more specifications about his node in BE… I could give a better answer and a better example if I knew what his node is supposed to do.

regardless of @EFTO’s issue, i think its a good idea to have some examples for custom nodes in the template list? I mean for my custom node tree, the template helped me more than anything i googled up.

2 Likes

Yes, you’re right! I need to write some templates, and also the documentation… I’m still making some tests to make registration/menus easier for custom nodes/nodetrees. Final Docs and templates should come after the changes (if accepted).

It’s just meant to take a float input between 0 and 1 and output another random float value between 0 and 1. I already have the code setup to facilitate the transformation of the input value to the output value (it’s only four lines long).

That’s exactly what I’m looking for! I just need the template.

There’s some samples attached to T61655 that may help.

1 Like