2
$\begingroup$

I would like to add some nodes to the Texture Editor, I would like to edit their default values and then link them together. I have found something on here that was helpful but they deviated to the Shader Editor and I could not seem to make the same thing work for me.

I have added some nodes but I don't know how to link them. This is my attempt:

import bpy

texture = bpy.data.textures.new('Texture Name', 'IMAGE')
texture.use_nodes = True

inv_node = texture.node_tree.nodes.new(type= 'TextureNodeInvert')
inv_node.location = 400,400
inv_node.select = False 

disnoise_node = texture.node_tree.nodes.new(type= 'TextureNodeTexDistNoise')
disnoise_node.location = 800,400
disnoise_node.select = False
disnoise_node.inputs[2].default_value = 10

Ideally I want to add maybe only one node and be able to connect it to the output but I am not sure how to link added node to the output.

I would greatly appreciate someone pointing me towards some information.

$\endgroup$
2
$\begingroup$

Following example creates a new node group called NewGroup (based on How do I create a custom node group for the compositor?) for the Texture Node Tree, containing three Math nodes as well as one Distorted Noise node plugged together properly:

import bpy

# create a group
test_group = bpy.data.node_groups.new('NewGroup', 'TextureNodeTree')

# create group inputs
group_inputs = test_group.nodes.new('NodeGroupInput')
group_inputs.location = (-350,0)
test_group.inputs.new('NodeSocketFloat','in_to_greater')
test_group.inputs.new('NodeSocketFloat','in_to_less')

# create group outputs
group_outputs = test_group.nodes.new('NodeGroupOutput')
group_outputs.location = (500,0)
test_group.outputs.new('NodeSocketFloat','out_result')

# create three math nodes in a group
node_add = test_group.nodes.new('TextureNodeMath')  
node_add.operation = 'ADD'
node_add.location = (100,0)

node_greater = test_group.nodes.new('TextureNodeMath')
node_greater.operation = 'GREATER_THAN'
node_greater.label = 'greater'
node_greater.location = (-100,100)

node_less = test_group.nodes.new('TextureNodeMath')
node_less.operation = 'LESS_THAN'
node_less.label = 'less'
node_less.location = (-100,-100)

node_vorn = test_group.nodes.new('TextureNodeTexDistNoise')
node_vorn.inputs[2].default_value = 10 # Set scale to 10
node_vorn.location = (300,0)

# link nodes together
test_group.links.new(node_add.inputs[0], node_greater.outputs[0])
test_group.links.new(node_add.inputs[1], node_less.outputs[0])
test_group.links.new(node_vorn.inputs[3], node_add.outputs[0])

# link inputs
test_group.links.new(group_inputs.outputs['in_to_greater'], node_greater.inputs[0])
test_group.links.new(group_inputs.outputs['in_to_less'], node_less.inputs[0])

#link output
test_group.links.new(node_vorn.outputs[0], group_outputs.inputs['out_result'])

API link - List of all available node types.


Creating the links outside of the group is basically the same. Following Operator, creates a new Output node and the group node from above as well as linking both together properly:

enter image description here

import bpy

# Create texture group
def create_tex_group(context, operator, group_name):

    # Create a group
    test_group = bpy.data.node_groups.new(group_name, 'TextureNodeTree')

    # Create group inputs
    group_inputs = test_group.nodes.new('NodeGroupInput')
    group_inputs.location = (-350,0)
    test_group.inputs.new('NodeSocketFloat','in_to_greater')
    test_group.inputs.new('NodeSocketFloat','in_to_less')

    # Create group outputs
    group_outputs = test_group.nodes.new('NodeGroupOutput')
    group_outputs.location = (300,0)
    test_group.outputs.new('NodeSocketFloat','out_result')

    # Create three math nodes in a group
    node_add = test_group.nodes.new('TextureNodeMath')  
    node_add.operation = 'ADD'
    node_add.location = (100,0)

    node_greater = test_group.nodes.new('TextureNodeMath')
    node_greater.operation = 'GREATER_THAN'
    node_greater.label = 'greater'
    node_greater.location = (-100,100)

    node_less = test_group.nodes.new('TextureNodeMath')
    node_less.operation = 'LESS_THAN'
    node_less.label = 'less'
    node_less.location = (-100,-100)

    # Link nodes together
    test_group.links.new(node_add.inputs[0], node_greater.outputs[0])
    test_group.links.new(node_add.inputs[1], node_less.outputs[0])

    # Link inputs
    test_group.links.new(group_inputs.outputs['in_to_greater'], node_greater.inputs[0])
    test_group.links.new(group_inputs.outputs['in_to_less'], node_less.inputs[0])

    # link output
    test_group.links.new(node_add.outputs[0], group_outputs.inputs['out_result'])

    # return the group
    return test_group


# Operator
class NODE_OT_texGroup(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "node.simple_operator"
    bl_label = "Add Group (Operator)"

    @classmethod
    def poll(cls, context):
        space = context.space_data
        return space.tree_type == 'TextureNodeTree'

    def execute(self, context):
        tree_id = context.space_data.id
        nodes_list = tree_id.node_tree.nodes

        # Create Output Node
        out = nodes_list.new('TextureNodeOutput')
        out.location = (200,100)

        # Create Grup
        custom_node_name = "my_node"
        my_group = create_tex_group(self, context, custom_node_name)
        grp_node = nodes_list.new('TextureNodeGroup')
        grp_node.node_tree = bpy.data.node_groups[my_group.name]
        grp_node.location = (0,0)

        # Link Group to Output
        tree_id.node_tree.links.new(grp_node.outputs[0], out.inputs[0])

        return {'FINISHED'}


# Panel
class NODE_PT_customPanel(bpy.types.Panel):
    bl_idname = "NODE_PT_customPanel"
    bl_space_type = 'NODE_EDITOR'
    bl_label = "Custom Panel"
    bl_region_type = "UI"
    bl_category = "Custom Category"

    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        layout.operator(NODE_OT_texGroup.bl_idname)
        layout.separator()


# Register
def register():
    bpy.utils.register_class(NODE_OT_texGroup)
    bpy.utils.register_class(NODE_PT_customPanel)


def unregister():
    bpy.utils.unregister_class(NODE_OT_texGroup)
    bpy.utils.unregister_class(NODE_PT_customPanel)


if __name__ == "__main__":
    register()

In order to use the generated node texture from above directly in the Compositor, you have to create a new Texture node and assign the texture to its slot:

enter image description here

# Operator
class NODE_OT_texGroup(bpy.types.Operator):
    """Operator to generate a texture and add it to the Compositor"""
    bl_idname = "node.simple_operator"
    bl_label = "Add Texture (Operator)"

    @classmethod
    def poll(cls, context):
        space = context.space_data
        #return space.tree_type == 'TextureNodeTree'
        #return space.type == 'NODE_EDITOR'
        return space.tree_type == 'CompositorNodeTree'


    def execute(self, context):

        # ---------------------------------------------------------
        # Generate the texture
        # ---------------------------------------------------------

        # Create the texture
        my_texture = bpy.data.textures.new('TextureName', 'IMAGE')

        # Enable use nodes
        my_texture.use_nodes = True

        # Get the tree
        tex_tree = my_texture.node_tree

        # Clear default nodes
        for node in tex_tree.nodes:
            tex_tree.nodes.remove(node)

        # Create Output Node
        out = tex_tree.nodes.new('TextureNodeOutput')
        out.location = (200,100)

        # Create Group
        custom_node_name = "my_node"
        my_group = create_tex_group(self, context, custom_node_name)
        grp_node = tex_tree.nodes.new('TextureNodeGroup')
        grp_node.node_tree = bpy.data.node_groups[my_group.name]
        grp_node.location = (0,0)

        # Link Group to Output
        tex_tree.links.new(grp_node.outputs[0], out.inputs[0])

        # ---------------------------------------------------------
        # Compositor
        # ---------------------------------------------------------

        # Enable use nodes in the compositor
        context.scene.use_nodes = True

        # Get the tree
        comp_tree = context.scene.node_tree

        # Clear default nodes
        for node in comp_tree.nodes:
            comp_tree.nodes.remove(node)

        # Create the texture node
        comp_node_texture = comp_tree.nodes.new('CompositorNodeTexture')

        # Assign the newly created texture
        comp_node_texture.texture = my_texture

        # create output node
        comp_node_out = comp_tree.nodes.new('CompositorNodeComposite')   
        comp_node_out.location = 400,0

        # link nodes
        links = comp_tree.links
        link = links.new(comp_node_texture.outputs[0], comp_node_out.inputs[0])

        return {'FINISHED'}
$\endgroup$
  • $\begingroup$ Hey thanks again Brockmann!.. So, I have to change the window to the Texture Editor, then change to brush space, then Add a new material, then click use nodes before that button works.. Ideally, I would like to be inside the Compositor, click the button and the group has been added to a new texture which then can be used in the Compositor.. How can I add these Parameters?.. $\endgroup$ – Darkfall Sep 15 at 19:12
  • 1
    $\begingroup$ Remove the poll method of the operator and instead of using the tree_id (current texture), create a new texture via textures.new and find its id to get the tree @Darkfall $\endgroup$ – brockmann Sep 15 at 19:39
  • $\begingroup$ I have deleted the poll method but I am not sure what I need to change next. Do you mean, Everything that is tree_id needs to be changed to textures.new ? I am sorry I do not understand, Most of this is still over my head. @brockmann $\endgroup$ – Darkfall Sep 15 at 21:12
  • 1
    $\begingroup$ Edited the operator @Darkfall $\endgroup$ – brockmann Sep 16 at 10:32
  • 1
    $\begingroup$ Glad I could help @Darkfall $\endgroup$ – brockmann Sep 16 at 10:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.