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$

1 Answer 1

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$
7
  • $\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
    Commented Sep 15, 2019 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
    Commented Sep 15, 2019 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
    Commented Sep 15, 2019 at 21:12
  • 1
    $\begingroup$ Edited the operator @Darkfall $\endgroup$
    – brockmann
    Commented Sep 16, 2019 at 10:32
  • 1
    $\begingroup$ Glad I could help @Darkfall $\endgroup$
    – brockmann
    Commented Sep 16, 2019 at 10:47

You must log in to answer this question.

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