My script is not functioning as I would like. I am appending a material from a file and the material is not adding to the material list.

Second I am trying to change the generated ellipsoid to a different material. I believe this code is simply changing the name and not changing to the saved material.

I can get around the first error by manually going to append and finding the file in my downloads.

Thank you for any support. S

import bpy

mat = 'Gold'

path = "C:/Users/ME/Downloads/78-gold.blend\\Material\\"

bpy.ops.wm.append(filename = mat, directory = path)

import numpy as np
loc_scale = 0.05
anisotropy = 10

for k in range(10):
    for j in range(10):
        for i in range(4):
            context = bpy.context
            scene = context.scene
            # add a sphere
            offsetx,offsety, offsetz = [0.5 , 0.5, 0.5] - np.random.random(3)

            bpy.ops.mesh.primitive_uv_sphere_add(location=(2 - k + offsetx, 2- j + offsety, -.5+ i + offsetz), rotation=( .1 - .2*np.random.random(), .1-.2*np.random.random(), .1-.2*np.random.random()))
            sphere = scene.objects.active
            # scale to (rx, ry, rz) of ellipsoid
            sphere.scale = (loc_scale, loc_scale, anisotropy*loc_scale)
            #apply scale

            bpy.context.object.active_material.name = "gold"
            activeObject = bpy.context.active_object #Set active object to variable

1 Answer 1


Set the active material not the name

The line

bpy.context.object.active_material.name = "Gold"

sets only the name of the material on the object to "Gold", not the material to the "Gold" material. Do something like this

ob.active_material = bpy.data.materials.get("Gold")

Please Note: blender is case sensitive, the material in file is either named "gold" or "Gold", there is a mix of both in your question.

Using the link / append operator adds a new material to the file. If there is another material already in blend of same name, the naming convention will append numbers to it, meaning above will only ever link the first material named "Gold" from file.

Simple API methods to link append rather than the op

How to Link/Append a data-block using the Python API?

# Append material named "Gold"
filepath = "C:/Users/ME/Downloads/78-gold.blend"
with bpy.data.libraries.load(filepath, link=False) as (data_from, data_to):
    data_to.materials = ["Gold"]
    #data_to.materials = data_from.materials #  append all materials from blend

Copy an object (and optionally its data)

Second lastly rather than call the add sphere operator 400 times, can call it once outside loop then copy and link to our collection

collection = bpy.data.collections.get("Blahs") or bpy.data.collections.new("Blahs")
blah = context.object
for i in range(copies):
    copy = blah.copy()
    copy.data = copy.data.copy() # a copy of data (mesh) also

Apply transforms directly to mesh

and lastly rather than the transform apply scale operator

from mathutils import Matrix
# don't set ob.scale = scale do
S = Matrix.Diagonal(scale).to_4x4() # a 4 x 4 scaling matrix


Changes suggested will reduce operator calls from 801 to 1, could get rid of add primitive operator, but nuffnuff one is ok.. lol.


Python performance with Blender operators

  • $\begingroup$ I am encountering an error with: ## collection = bpy.data.collections.get("Blahs") console says collections is not an attribute of data $\endgroup$
    – Matthew.MC
    Commented Aug 6, 2019 at 18:25
  • $\begingroup$ After some blender updates and changing the code I am still struggling with your suggestions see last line below copies = 10 collection = bpy.data.collections.get('Sphere') bpy.ops.mesh.primitive_uv_sphere_add() blah = bpy.context.object for i in range(copies): copy = blah.copy() copy.data = copy.data.copy() # a copy of data (mesh) also collection.objects.link(copy) collection is a noneType and has no attribute objects $\endgroup$
    – Matthew.MC
    Commented Aug 7, 2019 at 15:39
  • $\begingroup$ Try collection = context.collection Should have elaborated. With 2.8 we link objects to a collection, and then to a scene. For something like this make a collection .. named "Spheres" for example. collection = bpy.data.collections.new("Spheres") and link it to the scene collection with scene.collection.children.link(collection). Can get the collection with bpy.data.collections.get("Spheres") if it is None create it. $\endgroup$
    – batFINGER
    Commented Aug 7, 2019 at 15:58

You must log in to answer this question.

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