Oh, I have seen Sorcar, too. I think I snatched their code for my Make Node Group operator, since it is GPL and it works. I have learned a lot from both Sorcar and Sverchok.
I ran into a similar issue when parsing node groups- I had a situation where I didn’t know which instance of a node tree I was in, since the nodes inside the groups are shared. I realized the way to know which one was which: to keep track of the unique path from the ENTRY of the tree until the specific node. So, I wrote a function to traverse IN to group nodes and back OUT, and I developed a system to keep track of the ins and outs. It kept track of every node and socket with a “signature”, which looked like ((tree path), (node name), (socket name)). The tree path is the names of currently edited tree, and the group nodes the node is in (in order, as they may be nested). That way, every instance of every node is uniquely identified. Because it used the names, it was also hashable, so I could add it to a Python set
, which was useful on many occasions.
It may seem odd to do things this way, but there are two facts you should know! 1) I am not nearly as clever as the fellas who do dynamic programming or use OOP design patterns, and 2) my addon is more than anything about sorting the hierarchy. I’m making a “Rigging Nodes” addon and so it matters very much which order the nodes are executed in. It will also be useful to be able to edit the data after it is taken from the tree. Finally, I wish to separate execution from representation, so that in the future I can use the same execution system with e.g. a text-based markup language instead of a node tree.
Anyhow, after I read the tree from Blender, I use the data in the node tree to create my own set of “node container” classes for execution. The N.C.'s hold all the data from the nodes, including the “signature” and their connections. Each one is a unique instance, not a linked copy like the nodes inside of group nodes. So, I can give each one its own execution data and keep track of which have been executed, and I can keep a link to the Object or Bone the node created. At this point I can also add new N.C.'s to the tree if needed, for example, to represent data inferred from the context ( e.g. data conversion between different socket types that are incorrectly connected), or to expand nodes that may represent multiple objects (eventually I want to make “chain” nodes that represent a number of bones), etc… In the future I can probably use this “expansion” idea to deal with node groups more efficiently.
One of the nicest things about this system is that it helps me to locate and deal with cycles in the graph, by marking certain kinds of connections as “hierarchy connections”, rather than mere data connections. The data connections are ignored when sorting the graph, so later nodes can affect earlier nodes. I needed to do this because Blender actually allows this in its depagraph. A bone can have a driver than affects its own parent bone! This was a really vexing problem before I figured this out.
It isn’t quite the same as the problem you described, but I think it may be a solution, since it sidesteps the question of “which tree am I editing?”. Well, you need to know the base tree, in order to trace the lines all the way through the tree from the beginning to the end. But once you have a reference to the root nodes in the base tree, you can find every node in the tree including all of the groups, in order, and with a uniquely identifiable “signature”. Then you don’t need to know where you are at all, since you know where you’ve been!
I don’t know if that is helpful, but I wrote it in the hopes that it is interesting, since I think I solved the problem in a very different way. I have a feeling Sverchok does group nodes more efficiently, but probably doesn’t place as much emphasis on hierarchy and execution order. Thanks again for the reply and for the help.