1
$\begingroup$

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\\"


#ERR1
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.ops.object.transform_apply(scale=True)

#ERR2           
            bpy.context.object.active_material.name = "gold"
            activeObject = bpy.context.active_object #Set active object to variable
$\endgroup$
1
$\begingroup$

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")
bpy.ops.mesh.primitive_blah_add()
blah = 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)

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

ob.data.transform(S)

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

Related

Python performance with Blender operators

| improve this answer | |
$\endgroup$
  • $\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 Aug 6 '19 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 Aug 7 '19 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 Aug 7 '19 at 15:58

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.