0
$\begingroup$

I would like to apply custom colors to script-generated objects (mostly cubes). The setup I have is something like:

import bpy

# function that takes as input an object and color parameters,
# and applies the color (r,g,b) to object obj
colorCube(obj, r, g, b):
    # apply color defined by r, g, b to obj
    
obj1 = bpy.ops.mesh.primitive_cube_add(location=(0,0,0), scale=(1,1,1)) 
obj2 = bpy.ops.mesh.primitive_cube_add(location=(2,2,2), scale=(1,1,1))
obj3 = bpy.ops.mesh.primitive_cube_add(location=(4,4,4), scale=(1,1,1))
obj4 = bpy.ops.mesh.primitive_cube_add(location=(6,6,6), scale=(1,1,1))
obj5 = bpy.ops.mesh.primitive_cube_add(location=(8,8,8), scale=(1,1,1))

# color obj4 in red
colorCube(obj4, 255, 0, 0)

How do I go about defining colorCube()?

What I have so far is the following function that I scavenged from the web.

def createMat(object, r, g, b):    
    newMat = bpy.data.materials.new(name = 'Material')
    object.data.materials.append(newMat)
    newMat.use_nodes = True
    nodes = newMat.node_tree.nodes
    material_output = nodes.get("Material Output")
    node_emission = nodes.new(type='ShaderNodeBsdfDiffuse')
    node_emission.inputs[0].default_value = (r/255,g/255,b/255,1) 
    links = newMat.node_tree.links
    newLink = links.new(node_emission.outputs[0], material_output.inputs[0])

I call it after the object I want to color. For example:

import bpy

def createMat(object, r, g, b):    
    newMat = bpy.data.materials.new(name = 'Material')
    object.data.materials.append(newMat)
    newMat.use_nodes = True
    nodes = newMat.node_tree.nodes
    material_output = nodes.get("Material Output")
    node_emission = nodes.new(type='ShaderNodeBsdfDiffuse')
    node_emission.inputs[0].default_value = (r/255,g/255,b/255,1) 
    links = newMat.node_tree.links
    newLink = links.new(node_emission.outputs[0], material_output.inputs[0])
    
obj1 = bpy.ops.mesh.primitive_cube_add(location=(0,0,0), scale=(1,1,1)) 
obj2 = bpy.ops.mesh.primitive_cube_add(location=(2,2,2), scale=(1,1,1))
obj3 = bpy.ops.mesh.primitive_cube_add(location=(4,4,4), scale=(1,1,1))
obj4 = bpy.ops.mesh.primitive_cube_add(location=(6,6,6), scale=(1,1,1))
# color obj4 in red
actObj = bpy.context.active_object
createMat(actObj, 255, 0, 0)
obj5 = bpy.ops.mesh.primitive_cube_add(location=(8,8,8), scale=(1,1,1))

However, from my understanding, this function applies material to the last created object only -- or the active object. I need a function that colors the cubes I want after I have finished adding all the blocks to the scene.

Any thoughts?

$\endgroup$

2 Answers 2

0
$\begingroup$

Assign material to a mesh object

import bpy, math

cubes = []
x = 0

# create 5 cubes and append to a list
for r in range(5):
    bpy.ops.mesh.primitive_cube_add(location=(x, x, x), scale=(1,1,1))
    cubes.append(bpy.context.object)
    x += 2

def to_blender_color(c):    # gamma correction
    c = min(max(0, c), 255) / 255
    return c / 12.92 if c < 0.04045 else math.pow((c + 0.055) / 1.055, 2.4)

# function to create a material that not assign to any object
def create_simple_mat(r, g, b, gamma_correction = True):
    newMat = bpy.data.materials.new(name = 'Material')
    newMat.use_nodes = True
    nodes = newMat.node_tree.nodes
    material_output = nodes.get("Material Output")
    node_emission = nodes.new(type='ShaderNodeBsdfDiffuse')
    if gamma_correction:
        node_emission.inputs[0].default_value = (
            to_blender_color(r),
            to_blender_color(g),
            to_blender_color(b),
            1
        )
    else:
        node_emission.inputs[0].default_value = (r/255,g/255,b/255,1)
    links = newMat.node_tree.links
    newLink = links.new(node_emission.outputs[0], material_output.inputs[0])
    return newMat

mat = create_simple_mat(255, 0, 0)

# assign material to object
obj = cubes[3]
if obj.type == "MESH":
    obj.data.materials.append(mat)
    obj.active_material_index = len(obj.data.materials) - 1

Access a object by name

import bpy

obj = bpy.data.objects["my_object"]
$\endgroup$
2
  • $\begingroup$ @Minoush82 is rather quiet! $\endgroup$
    – james_t
    May 7, 2022 at 15:51
  • $\begingroup$ This helped me solve the issue :-) Actually I was waiting to finish my whole script before coming back here :-) $\endgroup$
    – user135638
    May 9, 2022 at 7:41
0
$\begingroup$

all you have to do is loop through the objects you created, assigning the material to each in turn:

for obj in bpy.context.editable_objects:
        if 'Cube' in obj.name:
            createMat(obj, 255, 0, 0)
$\endgroup$
1
  • $\begingroup$ Thanks, help very much appreciated! $\endgroup$
    – user135638
    May 9, 2022 at 7:42

You must log in to answer this question.