2
$\begingroup$

I'm new to blender. I've just got 2 days of experience with it now. I've got a lot of programming experience, but I have not programmed in python before.

I want to render animations for bunch of audio files I have.

I thought I could copy the python-code blender logs, into a script. This seemed to work, I've got some bars which respond to the audio by using the GUI and copying the python coe it logs. I changed the code so I can dynamically set the number of bars, etc.

All went well until I tried to apply a material.

I've worked the problem down to minimal example, just 4 lines:

On an empty stage I create a plane and assign a (new) material to it.

First draw the plane: bpy.ops.mesh.primitive_plane_add(radius=8, view_align=False, enter_editmode=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))

This also works from the console, a plane is created.

bpy.context.space_data.context = 'MATERIAL'

This fails on the console:

AttributeError: 'SpaceConsole' object has no attribute 'context'

But it seems to be the command to switch the GUI panel, which (to me) would not make much sense when running from a script. So I believe I can safely ignore this.

bpy.ops.material.new()

Seems to work, but not sure what it did. On the console it just returns "{'FINISHED'}".

Now comes the part where it goes really wrong:

bpy.context.object.active_material.diffuse_color = (0, 0, 0)

AttributeError: 'NoneType' object has no attribute 'diffuse_color'

The exact command Blender logs when using the GUI, doesn't work from the console.

I'm trying to get a grasp on what the commands are doing, and more specifically doing to what.

I tried

mat = bpy.ops.material.new()
bpy.context.object.active_material = mat

But that returned

TypeError: bpy_struct: item.attr = val: Object.active_material expected a Material type, not set So, the return value of material.new() probably is not the material just created, but some status message instead. I wonder where the material went.

After creating the plane, it is selected in the GUI, does that make it the context I'm working in? So material.new() is a new material for the plane? And is the context after material.new() still the plane, or is the context now the material?

EDIT: I was very close to fixing the code with

mat = bpy.ops.material.new()
bpy.context.object.active_material = mat

It should have been

mat = bpy.data.materials.new("foo")
bpy.context.object.data.materials.append(mat)

This (only) gets my code issue fixed.

I wonder if there is a similar way to get a reference to the plane, other than using the somewhat magical bpy.context.object? It probably requires crating the plane via bpy.data instead of bpy.ops. But that's not trivial. And adding it to the scene.

And it does not answer the question whether copying the blender log to a script is something we should do. It seems the python code blender logs, needs considerable rework before it can be used in a script.

$\endgroup$
  • $\begingroup$ Suggest reading blender.org/api/blender_python_api_2_77_release/… , wiki.blender.org/index.php/Dev:Py/Scripts/Cookbook/… The info log shows operator calls based on the context that you are setting in the UI, eg the context object you selected, a button pressed in the Properties Area. Many simple operations can be replaced with low level API calls. Most bpy.data collections (eg bpy.data.objects) have a new() method, and are pretty consistent in usage. Autocomplete in the console is a good way to play around. $\endgroup$ – batFINGER Mar 22 '16 at 4:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.