7
$\begingroup$

I've done a fair amount of custom PyNode tree scripting for Sverchok, but one thing remains a bit nebulous and i'm hoping someone can shed some light.

The Material node trees have this Group feature which turns the background green and enables an operator on the header to call bpy.ops.node.tree_path_parent() to go to the parent node tree.

enter image description here

The poll / execute code for bpy.ops.node.tree_path_parent() is (...full code link)

@classmethod
def poll(cls, context):
    space = context.space_data
    # needs active node editor and a tree
    return (space.type == 'NODE_EDITOR' and len(space.path) > 1)

def execute(self, context):
    space = context.space_data
    space.path.pop()
    return {'FINISHED'}

For a NodeGroup of ShaderNodeTree space.path becomes a collection of 2 paths.

<bpy_collection[2], SpaceNodeEditorPath>
--- <bpy_struct, ShaderNodeTree("Shader Nodetree")>
--- <bpy_struct, ShaderNodeTree("NodeGroup")>

My simple attempt at declaring a NodeCustomGroup has some superficial success. My question is how / where can I set the space.path so there's something to .pop(), -- somewhere in the init of the custom node?

excerpt full code here:

class SvGroupNodeExp(bpy.types.NodeCustomGroup, SverchCustomTreeNode):
    bl_idname = 'SvGroupNodeExp'
    bl_label = 'Group Exp'
    bl_icon = 'OUTLINER_OB_EMPTY'

    group_name = StringProperty()

    def init(self, context):

        self.node_tree = bpy.data.node_groups.new('nooobgroup', 'SverchCustomTreeType')
        self.group_name = self.node_tree.name
        # self.node_tree.parent = self
        # space = context.space_data
        nodes = self.node_tree.nodes

        inputnode = nodes.new('SvGroupInputsNode')
        outputnode = nodes.new('SvGroupOutputsNode')
        inputnode.location = (-300, 0)
        outputnode.location = (300, 0)
$\endgroup$
5
  • $\begingroup$ Wouldn't you do that in bpy.ops.node.group_edit()? $\endgroup$
    – sambler
    Jul 26, 2016 at 8:11
  • $\begingroup$ maybe i'm not reading this right, but perhaps group_edit() is limited to standard node trees? -- i've implemented an operator to switch active node tree, and am tempted to also implement a back_to_parent operator.. $\endgroup$
    – zeffii
    Jul 26, 2016 at 9:12
  • 2
    $\begingroup$ None of the standard group operators work in custom node trees, we need to implement our own create/edit/ungroup operators. That would be the place to add/pop to space.path. Not sure we can use the existing menu entries but we can use the same shortcuts to run the custom operators. $\endgroup$
    – sambler
    Jul 26, 2016 at 13:36
  • $\begingroup$ Thanks @sambler this confirms my suspicion.. pitty it's not so elegant to replace an operator in the node tree header.. $\endgroup$
    – zeffii
    Jul 26, 2016 at 15:37
  • $\begingroup$ see object_nodes ../group_nodes.py by PyNodes' creator for a Python implementation of group_nodes $\endgroup$
    – zeffii
    Jul 29, 2016 at 13:45

1 Answer 1

5
$\begingroup$

I'm not sure how useful this is to people (see a sverchok branch which implements this). I'll provide this as answer to my question, because that's what it does -- whether or not this allows for a functional custom node_tree group implementation is still up in the air.


It seems the way to get the node.tree_path_parent to poll True is to repopulate the context.space_data.path with the parent tree at index 0 and the new group node (a tree under the hood) at index 1.

def group_make(self, new_group_name):
    self.node_tree = bpy.data.node_groups.new(new_group_name, 'SverchCustomTreeType')
    self.group_name = self.node_tree.name

    nodes = self.node_tree.nodes
    inputnode = nodes.new('SvGroupInputsNode')
    outputnode = nodes.new('SvGroupOutputsNode')
    inputnode.location = (-300, 0)
    outputnode.location = (300, 0)
    return self.node_tree

class SvGroupEdit(bpy.types.Operator):
    bl_idname = "node.sv_group_edit"
    bl_label = "edits an sv group"

    group_name = StringProperty()

    def execute(self, context):
        node = context.node
        ng = bpy.data.node_groups

        group_node = ng.get(self.group_name)
        if not group_node:
            group_node = group_make(node, new_group_name=self.group_name)

        bpy.ops.node.sv_switch_layout(layout_name=self.group_name)
        # context.space_data.node_tree = ng[self.group_name]  # does the same

        # by switching, space_data is now different
        parent_tree_name = node.id_data.name
        path = context.space_data.path
        path.clear()
        path.append(ng[parent_tree_name]) # below the green opacity layer
        path.append(ng[self.group_name])  # top level

        return {"FINISHED"}

However, when hitting the back button (tree_path_parent) the active node_tree isn't set. Why? I suspect it's due to using .clear() instead of .pop() and some loss of information. This means we need to roll our own version of tree_path_parent, to switch the node_tree and then set the context.space_data.node_tree to the desired parent tree.

Something like:

class SvTreePathParent(bpy.types.Operator):
    '''Go to parent node tree'''
    bl_idname = "node.sv_tree_path_parent"
    bl_label = "Parent Sv Node Tree"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        space = context.space_data
        return space.type == 'NODE_EDITOR' and len(space.path) > 1

    def execute(self, context):
        space = context.space_data
        space.path.pop()
        context.space_data.node_tree = space.path[0].node_tree
        return {'FINISHED'}

Bottom left in the screenshot i prepended the operator button for node.sv_tree_path_parent.

enter image description here

$\endgroup$
1
  • $\begingroup$ have there been any improvements to the Custom Node Group since this was posted? $\endgroup$
    – VSB
    Jan 16 at 14:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .