0
$\begingroup$

I'm upgrading my procedural addon with the ability to add individual procedural groups into other materials. I've figured out how to make buttons on the side menu that do it, but it's less than ideal.

Ideally I'd like to have it as a new category in the Add menu.

I found this question, which got me closer to the goal, then this question, led me to figure out the way bpy copies node groups.

Essentially, it references the Properties field, not the name of the group. Three name fields and it uses the Properties to copy?!

Don't know why it needs to do it that way, but now I can at least direct my code there knowing which one I'm doing.

Then I found this question, which got me to the point I'm at now, where the modules work if I run them directly.

It was a tad premature to accept my own answer to the problem, because as I've been trying to fold it into my addon, I'm now getting this error: group_script.py", line 73, in execute File "/home/maker/Downloads/blender-2.93.6-linux-x64/2.93/scripts/modules/bpy/ops.py", line 132, in __call__ ret = _op_call(self.idname_py(), None, kw) TypeError: Converting py args to operator properties: : keyword "type" unrecognized I haven't seen this particular error before. It was working until I tried to get my __init__ script to run this script.

The only thing I've changed in the __init__ script is adding a button for this script. And I haven't changed anything in this one since I posted the answer.

What's happening currently is that the nodegroup copy script works perfectly if I execute it alone, but if I try to run it from the init script, it seems to just forget that the type function is a thing.

class WM_OT_Lips(Operator):
    bl_label = "Load Lips"
    bl_idname = "wm.lips"
    bl_options = {'REGISTER', 'INTERNAL'}
    
    
    @classmethod
    def poll(cls, context):
        return True
    
    def execute(self, context):
        # this line calls the nodegroup from the existing material and places it in the current nodetree
        bpy.ops.node.add_node(type='ShaderNodeGroup', settings=[{"name":"node_tree", "value":"bpy.data.node_groups['Lips']"}])
        currNode = context.active_node # this selects the new nodegroup
        location = Vector((0,500)) # this line sets the destination of the new node
        currNode.location = (location) # this line moves the new node to the set location
        return {'FINISHED'}

Update

So I've been poking around randomly and I found that running my __init__ file changes something. Before I ran the init file the autocomplete looked like this:

>>> bpy.ops.node.add_node(
add_node()
bpy.ops.node.add_node(type="", use_transform=False, settings=[])
Add a node to the active tree

After I run it, the autocomplete looks like this:

>>> bpy.ops.node.add_node(
add_node()
bpy.ops.node.add_node()
(undocumented operator)

I have NO IDEA why it would do this.

Update

I've been picking at my _init_ script and trying parts of it individually, and I've finally isolated the part of it that's making problems. It's the group that's supposed to append the materials and subscripts. It's functionally the same as the one I use for the main skin, but that one doesn't mess with any core functions.

Can anyone tell me what's wrong with this?

class NODE_OT_add_group(Operator):
    bl_label = "Individual Textures"
    bl_idname = "node.add_node"
    
        
    def execute(self, context):
        if not bpy.data.materials.get("Skin"): 
            bpy.ops.wm.append(
            filepath="Skin.blend",
            directory=srcFile + skinmat,
            filename="Skin",
            set_fake=True)
        
        if not bpy.data.texts.get("group_script.py"):
            bpy.ops.wm.append(
            filepath="Skin.blend",
            directory=srcFile + skinscript,
            filename="group_script.py",
            set_fake=True)
        
        text_group= bpy.data.texts['group_script.py']
        context_c = context.copy()
        context_c['edit_text'] = text_group
        bpy.ops.text.run_script(context_c)
        return {'FINISHED'}

I'm on the verge of pulling my hair out trying to figure out how and/or why this section of code would even effect the node map functions.

$\endgroup$

1 Answer 1

0
$\begingroup$

After yet more digging, and looking into tangential questions, I found this gem, which led me to the solution. I'll post the whole operator group, this just goes on a button.

class WM_OT_Lips(Operator):
    bl_label = "Load Lips"
    bl_idname = "wm.lips"
    bl_options = {'REGISTER', 'INTERNAL'}
    
    
    @classmethod
    def poll(cls, context):
        return True
    
    def execute(self, context):
        # this line calls the nodegroup from the existing material and places it in the current nodetree
        bpy.ops.node.add_node(type='ShaderNodeGroup', settings=[{"name":"node_tree", "value":"bpy.data.node_groups['Lips']"}])
        currNode = context.active_node # this selects the new nodegroup
        location = Vector((0,500)) # this line sets the destination of the new node
        currNode.location = (location) # this line moves the new node to the set location
        return {'FINISHED'}

This is a pretty simple function, and I'd still like to have it on the Add menu, but this will do the job.

Updated Final Answer

As it turns out, the problem of my __init__ script removing the Add function from Blender was literally semantic.

class NODE_OT_add_group(Operator):
    bl_label = "Individual Textures"
    bl_idname = "node.add_node"

Was actually replacing the default add_node function! I didn't know that could even be done, and it never gave an error message so there was nothing stopping it. I found this while I was looking into the register function to see if it had a dangling participle of sorts.

Anyway, the solution was to just replace all the adds in the section to copy.

class NODE_OT_copy_group(Operator):
    bl_label = "Individual Textures"
    bl_idname = "node.copy_node"

And so on.

$\endgroup$

You must log in to answer this question.

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