Set material blender python

Python — Set material to material slot

enter image description here

I am using the Blender Internal render engine. I have an material slot with no material assigned to it. How can I assign a material to a slot using python? This should work in edit mode as well. Basically I would like to assign materials to specific faces.

6 Answers 6

This code creates 10 materials and appends it to the active object (should be a mesh). The diffuse color of every material is random. The .material_index poperty is set to the new materials by index (even if the object has materials assigned before the operation).

import bpy from random import random ob = bpy.context.object me = ob.data mat_offset = len(me.materials) mat_count = 10 mats = [] for i in range(mat_count): mat = bpy.data.materials.new("Mat_%i" % i) mat.diffuse_color = random(), random(), random() me.materials.append(mat) # Can't assign materials in editmode bpy.ops.object.mode_set(mode='OBJECT') i = 0 for poly in me.polygons: if poly.select: poly.material_index = i % mat_count + mat_offset i += 1 

If you want to use UV mapped textures, you’ll also have to deal with me.uv_layers and me.uv_textures . It’s not enough to assign materials to faces, you also need to set the texture image for every face.

$\begingroup$ Updated my example to only assign new materials to selected polygons. Note that if there’s no material before the operation, unselected polygons will use the first material ( .material_index has a default of 0, which is automatically the first material). $\endgroup$

$\begingroup$ @CoDEmanX I want to go over all of my materials and select (or get indices of) faces to which that specific material has been applied to. I haven’t been able to find a good solution for doing that as of now. I would appreciate if you can take a look at my question here and see if you can offer a solution? $\endgroup$

import bpy D = bpy.data if len(D.objects['Cube'].material_slots) < 1: # if there is no slot then we append to create the slot and assign D.objects['Cube'].data.materials.append(D.materials['Material']) else: # we always want the material in slot[0] D.objects['Cube'].material_slots[0].material = D.materials['Material'] 

$\begingroup$ This doesn't work when I want to assign random faces a material in edit mode. $\endgroup$

Читайте также:  After with image css

$\begingroup$ @gandalf3 I already know how to do this on object level. I need to do it in edit mode though. This tut only does objects. $\endgroup$

$\begingroup$ @Vader Your question is assigning a material to a slot not assigning a material to faces. $\endgroup$

Abandon the approach of edit mode/non-edit mode and just focus on the datablock. Materials for faces are specified via material_index inside the datablock of a mesh type object.

Add a Suzanne mesh to the scene and try this code:

import bpy, random ob = bpy.data.objects.get("Suzanne") if ob != None: # Create a materials. mat_one = bpy.data.materials.get("mat_one") if mat_one == None: mat_one = bpy.data.materials.new("mat_one") mat_one.diffuse_color = (random.random(),random.random(),random.random()) mat_two = bpy.data.materials.get("mat_two") if mat_two == None: mat_two = bpy.data.materials.new("mat_two") mat_two.diffuse_color = (random.random(),random.random(),random.random()) # Add materials to slots. ob.data.materials.append(mat_one) ob.data.materials.append(mat_two) # Determine random count and poly count. rnd_face_count = 12 l = len(ob.data.polygons) # Note: By default all faces have a material index of 0. for i in range(rnd_face_count): # Generate a random face index. rnd_face_index = random.randint(0,(l-1)) ob.data.polygons[rnd_face_index].material_index = 1 

This is not the cleanest code but it shows one way to accomplish the task mentioned. If you run this code twice, however, you will discover that you are building up a list of new materials on the Suzanne object.

Источник

Set material blender python

This is how to create a new material, add a shader, create a new object and assign the material to the object in Blender using Python.

First, create a new material. The function takes a string as the name for the new material.

import bpy def newMaterial(id): mat = bpy.data.materials.get(id) if mat is None: mat = bpy.data.materials.new(name=id) mat.use_nodes = True if mat.node_tree: mat.node_tree.links.clear() mat.node_tree.nodes.clear() return mat 

Then add a shader to the material. Input the type of shader (i.e. diffuse, emission, glossy) and the rgb colour.

def newShader(id, type, r, g, b): mat = newMaterial(id) nodes = mat.node_tree.nodes links = mat.node_tree.links output = nodes.new(type='ShaderNodeOutputMaterial') if type == "diffuse": shader = nodes.new(type='ShaderNodeBsdfDiffuse') nodes["Diffuse BSDF"].inputs[0].default_value = (r, g, b, 1) elif type == "emission": shader = nodes.new(type='ShaderNodeEmission') nodes["Emission"].inputs[0].default_value = (r, g, b, 1) nodes["Emission"].inputs[1].default_value = 1 elif type == "glossy": shader = nodes.new(type='ShaderNodeBsdfGlossy') nodes["Glossy BSDF"].inputs[0].default_value = (r, g, b, 1) nodes["Glossy BSDF"].inputs[1].default_value = 0 links.new(shader.outputs[0], output.inputs[0]) return mat 

Then create the object, assign the material and call the function.

def drawObject(): mat = newShader("Shader1", "diffuse", 1, 1, 1) bpy.ops.mesh.primitive_cube_add(size=2, align='WORLD', location=(0, 0, 0)) bpy.context.active_object.data.materials.append(mat) drawObject() 

I like working with awesome people on awesome projects.
Let me know what you’re working on. Drop me a line at

Источник

How to assign a material to a mesh object with python?

Creating Materials using python is easy and it has a lot of answers on StackExchange. Now what I want to ask is - If I want that the material should only be added if the object (on which material to be added) should be mesh or text, and material should not be added in case of curves or anything else and it should give a custom error message. Whenever the add test material button is pressed operator should only be executed if the object is mesh. Actually I want to specify in the script that this material to be added only if the object type is mesh. (Please have a look at the script)

import bpy class TEST_MATERIAL_OT_add_material(bpy.types.Operator): bl_idname = "test_material.add_material" bl_label = "Add Test Material" bl_description = "This button will add a material to your object" @classmethod def poll(cls, context): ob = context.active_object return ob is not None and ob.type=='MESH' def execute(self, context): ob = context.active_object if ob is None: self.report(, "No active object") return if ob.type != 'MESH': self.report(, "Object is not a mesh") return self.report(, "Object is a mesh, operator can run") self.create_material() return def create_material(self): # removes unwanted nodes for node in tree.nodes: tree.nodes.remove(node) test_shader_mat = bpy.data.materials.new("TestMat") mesh = bpy.context.object.data mesh.materials.clear() mesh.materials.append(test_shader_mat) bpy.context.object.active_material.use_nodes = True for mat in bpy.data.materials: if "TestMat" in mat.name: nodes = mat.node_tree.nodes for node in nodes: if node.type != 'OUTPUT_MATERIAL': # skip the material output node as we'll need it later nodes.remove(node) # Creating Node Group Test_Material group = bpy.data.node_groups.new(type="ShaderNodeTree", name="Test_Material") # Creating Group Input group.inputs.new("NodeSocketColor", "Diffuse Color") group.inputs.new("NodeSocketColor", "Glossy Color") group.inputs.new("NodeSocketFloat", "Mix Factor") group.inputs.new("NodeSocketFloat", "Glossyness") input_node = group.nodes.new("NodeGroupInput") input_node.location = (-800, 0) # Creating Group Output Node group.outputs.new("NodeSocketShader", "Diffuse Color") group.outputs.new("NodeSocketShader", "Glossy Color") group.outputs.new("NodeSocketShader", "Mix Output") output_node = group.nodes.new("NodeGroupOutput") output_node.location = (1500, 0) # Creating Diffuse Node diffuse_node = group.nodes.new(type='ShaderNodeBsdfDiffuse') diffuse_node.location = (150, 100) # Creating Glossy Node glossy_node = group.nodes.new(type='ShaderNodeBsdfGlossy') glossy_node.location = (300, 250) # Creating Mix Shader Node mix_shader_node = group.nodes.new(type='ShaderNodeMixShader') mix_shader_node.location = (450, 100) # Creating Links Between Nodes group.links.new(diffuse_node.outputs["BSDF"], mix_shader_node.inputs[1]) group.links.new(glossy_node.outputs["BSDF"], mix_shader_node.inputs[2]) group.links.new(input_node.outputs["Diffuse Color"], diffuse_node.inputs[0]) group.links.new(input_node.outputs["Glossy Color"], glossy_node.inputs[0]) group.links.new(input_node.outputs["Mix Factor"], mix_shader_node.inputs[0]) group.links.new(input_node.outputs["Glossyness"], glossy_node.inputs[1]) group.links.new(output_node.inputs["Diffuse Color"], diffuse_node.outputs[0]) group.links.new(output_node.inputs["Glossy Color"], glossy_node.outputs[0]) group.links.new(output_node.inputs["Mix Output"], mix_shader_node.outputs[0]) # Putting Node Group to the node editor tree = bpy.context.object.active_material.node_tree group_node = tree.nodes.new("ShaderNodeGroup") group_node.node_tree = group group_node.location = (-40, 300) group_node.use_custom_color = True group_node.color = (1, 0.341, 0.034) group_node.width = 250 shader_node_output_material_node = tree.nodes["Material Output"] links = tree.links links.new(group_node.outputs[0], shader_node_output_material_node.inputs[0]) class TEST_MATERIAL_PT_layout_panel(bpy.types.Panel): bl_label = "Test Material Node" bl_category = "Test Material" bl_space_type = "VIEW_3D" bl_region_type = "UI" def draw(self, context): layout = self.layout layout.operator("test_material.add_material", icon='IMPORT') classes = (TEST_MATERIAL_OT_add_material, TEST_MATERIAL_PT_layout_panel) def register(): for cls in classes: bpy.utils.register_class(cls) def unregister(): for cls in classes: bpy.utils.unregister_class(cls) if __name__ == "__main__": register() 

Источник

Оцените статью