24
$\begingroup$

I have edited a script that creates some nodes, but the only problem is, it always created a new material. I want it to either add the nodes on the existing material, or a pre-defined material. Here is the script base I am using.

http://blenderscripting.blogspot.com.es/2013/06/automatic-colour-ramped-shader-from.html

Thanks for the help in advance! :D

$\endgroup$
0

4 Answers 4

31
$\begingroup$

You can get the material node tree from bpy.data.materials['MyMaterial'].node_tree

Then add the nodes with node_tree.nodes.new()

For example, to add a diffuse shader node to MyMaterial and create MyMaterial if it doesn't exist:

import bpy
mat_name = "MyMaterial"
# Test if material exists
# If it does not exist, create it:
mat = (bpy.data.materials.get(mat_name) or 
       bpy.data.materials.new(mat_name))

# Enable 'Use nodes':
mat.use_nodes = True
nodes = mat.node_tree.nodes

# Add a diffuse shader and set its location:    
node = nodes.new('ShaderNodeBsdfDiffuse')
node.location = (100,100)
$\endgroup$
2
24
$\begingroup$

The answer provided is only partially helpful. Or it is outdated in 2.7

Yes you have to add the nodes (use_nodes = True). However the default material is the Diffuse BSDF. So if you want to use this, fine, you're done. But to change the shader being used:

  1. Remove the shader in place (Diffuse BSDF, otherwise the second element in the material.node_tree.nodes.values() list. This is sort of optional, as it can also stay in place, but it's just not tidy and confusing to leave it there.
  2. Create a new shader node. e.g. material.node_tree.nodes.new('ShaderNodeEmission')
  3. Update the link to the Material Output node. material.node_tree.links.new(mat.inputs[0], node.outputs[0])

Here an example I made I use quite often: a Mesh Light

    def create_light():
        """
        Add a mesh light for cycles
        """

        # Add new plane
        bpy.ops.mesh.primitive_plane_add(location=(15, -5, 5))
        plane = bpy.context.active_object
        plane.name = 'Light Plane'
        plane.scale = mathutils.Vector((4, 4, 4))
        # tilt
        plane.rotation_euler.rotate_axis('Y', radians(40))

        # Create a new material
        material = bpy.data.materials.new(name="Plane Light Emission Shader")
        material.use_nodes = True

        # Remove default
        material.node_tree.nodes.remove(material.node_tree.nodes.get('Diffuse BSDF'))
        material_output = material.node_tree.nodes.get('Material Output')
        emission = material.node_tree.nodes.new('ShaderNodeEmission')
        emission.inputs['Strength'].default_value = 5.0

        # link emission shader to material
        material.node_tree.links.new(material_output.inputs[0], emission.outputs[0])

        # set activer material to your new material
        plane.active_material = material
$\endgroup$
2
  • 1
    $\begingroup$ Your this code snippet is very helpful Sir. Thank you so much! Took me a while to figure out that link. Then I remember I saw your answer before. $\endgroup$ Commented Dec 27, 2016 at 2:46
  • $\begingroup$ Color can be set analog to Strength: emission.inputs['Color'].default_value = (0,1,0,1) # green RGBA $\endgroup$
    – jakob.j
    Commented Dec 26, 2019 at 12:55
3
$\begingroup$

now at first you have principled BSDF. a variation with a diffuse node on active object

import bpy

# Create a new material
material = bpy.data.materials.new(name="Diffuse")
material.use_nodes = True

# Remove default
material.node_tree.nodes.remove(material.node_tree.nodes.get('Principled BSDF')) #title of the existing node when materials.new
material_output = material.node_tree.nodes.get('Material Output')
diffuse = material.node_tree.nodes.new('ShaderNodeBsdfDiffuse')    #name of diffuse BSDF when added with shift+A


diffuse.inputs['Color'].default_value = (1, 0, 1, 1) #last value alpha

# link diffuse shader to material
material.node_tree.links.new(material_output.inputs[0], diffuse.outputs[0])

# set activer material to your new material
bpy.context.object.active_material = material
$\endgroup$
1
$\begingroup$

Another way to do this is. It picks up a material if it exists, else creates a new one with that name.

import bpy

mat_name = "MyMaterial"
materials = bpy.data.materials

# if .get returns None, the assignment comes from the right of the 'or'
mat = materials.get(mat_name) or materials.new(mat_name)   # *** see comment
mat.use_nodes = True
nodes = mat.node_tree.nodes

# Add a diffuse shader and set its location:    
node = nodes.new('ShaderNodeBsdfDiffuse')
node.location = (100,100)

I expected this to work, but it doesn't.

mat = materials.get(mat_name, materials.new(mat_name))
$\endgroup$
2
  • 1
    $\begingroup$ mat = materials.get(materials.new(mat_name).name) $\endgroup$
    – JuhaW
    Commented Jan 28, 2017 at 23:10
  • $\begingroup$ cool if that works :) $\endgroup$
    – zeffii
    Commented Jan 29, 2017 at 15:46

You must log in to answer this question.

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