11
$\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$
17
$\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$
12
$\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$
  • $\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$ – Sibbs Gambling Dec 27 '16 at 2:46
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$
  • 1
    $\begingroup$ mat = materials.get(materials.new(mat_name).name) $\endgroup$ – JuhaW Jan 28 '17 at 23:10
  • $\begingroup$ cool if that works :) $\endgroup$ – zeffii Jan 29 '17 at 15:46

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.