5
$\begingroup$

I have run out of luck just copy/pasting other peoples code, and now I want to understand (at least somewhat) how to "do some things" to mesh objects. For example, I often do this to make various complicated meshes:

# make a custom purple mesh object
me = bpy.data.meshes.new('tim_the_mesh')
ob = bpy.data.objects.new('tim_the_object', me)

bpy.context.scene.objects.link(ob)

me.from_pydata(verts, [], faces)   # generated earlier

ob.active_material = purple
bpy.ops.object.shade_smooth()

# then, for some reason, I do this to make sure it remains selected
bpy.data.objects['tim_the_object'].select = False
bpy.data.objects['tim_the_object'].select = True

Now I want to make a matching purple sphere

ob2 = bpy.ops.mesh.primitive_uv_sphere_add(size=1, location=(3,3,3))
#ob2.active_material = purple  # Nope!
#me2 = ob2.data   # Nope!

bpy.ops.mesh.primitive_uv_sphere_add(size=1, location=(3,3,3))
ao = bpy.context.active_object
ao.name = "tim_the_sphere"
ao.location = (x,y,z)
#ao.active_material = purple  # Nope!
#bpy.ops.object.shade_smooth()  # Nope!

Each "Nope!" is something I thought might work, but without a decent grip on what is what.

Of course there is more than plenty of documentation all over the internet. But is there something concise, maybe even a block diagram, that will help me see how to "get at" the various properties easily within a script environment? It will be much easier for me if I can get a grip on how these things are accessed.

$\endgroup$
5
  • $\begingroup$ have you defined purple and x,y,z $\endgroup$
    – Chebhou
    May 27, 2015 at 11:39
  • $\begingroup$ do you need explanation of both scripts or only the second $\endgroup$
    – Chebhou
    May 27, 2015 at 11:58
  • $\begingroup$ related: blender.stackexchange.com/questions/8067/… and blender.stackexchange.com/questions/29134/… $\endgroup$
    – zeffii
    May 27, 2015 at 14:15
  • $\begingroup$ Thanks @zeffi, this is all really helpful! It's late here but I can't let this go. I can do many things to the first mesh at any time through the reference me, but to change some things later on (say another frame), the object must be reselected? (e.g through bpy.context.active_object and bpy.ops.mesh) I wonder if there is something deeper I can learn by asking why. $\endgroup$
    – uhoh
    May 27, 2015 at 16:35
  • $\begingroup$ Ask a new question, explain what you are trying to do, but take effort to reduce all code to something that we can copy and run $\endgroup$
    – zeffii
    May 27, 2015 at 17:16

2 Answers 2

7
$\begingroup$

it's simple in that case.

ob = bpy.ops.mesh.primitive_uv_sphere_add()
print(ob)
>>> {'FINISHED'}

The docs for mesh.primitive_uv_sphere_add don't explicitly mention a return type, and that's a first hint that it won't have a very useful return value.

There are 2 main ways to get object references. Either by:

# getting the reference by object name 
ob = bpy.data.objects['Sphere']

# or using the fact that calls to bpy.ops.mesh_xxxxx
# place new objects as the active_object.
bpy.ops.mesh.primitive_uv_sphere_add()
ob = bpy.context.active_object

unlike objects of type BlendDataObjects. These are found in bpy.data.

data.objects
data.meshes
data.materials
# etc

The new() method for those Objects does return an Object reference.

ob = bpy.data.objects.new('tim_the_object', me)

A good approach to learning the bpy is to use that print() statement on objects, or dir(). I'm fairly confident in my bpy-knowledge, but I still use those methods to understand the return values on occasion, and I use dir(whatever) constantly.

Hit control+space after typing this in the python console:

>>> bpy.ops.mesh.primitive_uv_sphere_add(   

It will return a lot of information about the function signature, and that works for most functions. But not all functions have elaborate docstrings to tell us the return values (then you use print() )

active_material

your code

ao.active_material = purple  # Nope!
bpy.ops.object.shade_smooth()  # Nope!

assumes that purple is a reference to a material, if that failed, then the next line will also fail.

# this assumes you have a material, called 'purple'
ao.active_material = bpy.data.materials['purple']
bpy.ops.object.shade_smooth()  # probably works with an active object.

this does work:

import bpy

bpy.ops.mesh.primitive_uv_sphere_add(size=1, location=(3,3,3))
ao = bpy.context.active_object
ao.active_material = bpy.data.materials['purple']
bpy.ops.object.shade_smooth()
$\endgroup$
2
  • $\begingroup$ Super! Thanks for your time @zeffi. From your profile I see that you have a blog that I wish I had found sooner!! Wow, don't hesitate to include the link in your answers! $\endgroup$
    – uhoh
    May 27, 2015 at 14:21
  • $\begingroup$ uhoh, I think people who search for bpy stuff will find that blog sooner or later :). Here we try to keep information on this site, and avoid linking offshore (unless they are official blender docs) . Thanks for your encouragement. $\endgroup$
    – zeffii
    May 27, 2015 at 14:40
3
$\begingroup$

First what is a :

  • Mesh: mesh is a data-block that contains collection of points ( Vertices ) and their relations ( edges , faces ) and other properties related to them as ( Vertex groups , vertex color, UV maps, material index )
  • Object: is more general data-block which could be contains mesh or curve, empty, armature, .... and this is the important part of the object( it is the type of the object ), it also includes other properties like Location, rotation, size, modifiers, constraints, materials,particle systems.... ( what to note is that the mesh is only a part of the object )

let's go through the first code line by line :

me = bpy.data.meshes.new('tim_the_mesh')

this will create an empty mesh ( has no points in it ) with the name tim_the_mesh and me will be our reference to this mesh( when we need to call it we use me )

ob = bpy.data.objects.new('tim_the_object', me)

this will create a new object ( of type mesh ) that contains our mesh me and our reference to this object is ob

if we stop here our object will not show up in any of the scenes (Viewport, Outliner) and that is because we have not linked this object to any scene yet ( blender doesn't know where does this object belong to ) and for this we use the next line to link the object to the active scene ( the current scene )

bpy.context.scene.objects.link(ob)

Now we have created a mesh put it in an object and linked our object to the scene ( the object will be visible now in the scene ) but the problem is that our object has no geometry ( vertices , edges and faces ) now we will fill our mesh with a prepared data ( generated by other code parts ) in he next line

 me.from_pydata(verts, [], faces)

after giving our object a shape we want to give it a good look for that we assign a material to this object since the object is new it has no active material (or any material ) and using the next line we set the material of the object to be purple ( purple is material defined earlier in this code )

 ob.active_material = purple

and the next line is simply giving the object a smooth look by enabling the smooth shading

 bpy.ops.object.shade_smooth()

if you note in the last line we haven't referenced ob and that's because the function shade_smooth() will be applied to the active object which is our object ( because it has been just created )


for the second code :

  bpy.ops.mesh.primitive_uv_sphere_add(size=1, location=(3,3,3))

this line will take care of creating a mesh, generate its geometry, put in an object, link it to the current scene and move it to the position ( 3,3,3) so it replaces the 4 lines of the first script

ao = bpy.context.active_object

we want to get a reference to our new object to manipulate it later, and since our object has just been created it is the active object and we simply reference that as ao

 ao.name = "tim_the_sphere"

we have just changed the name of our object to tim_the_sphere

ao.location = (x,y,z)

now we changed the location of the object to be at (x, y, z)

and the rest is the same as above :

ao.active_material = purple  #assign a material
bpy.ops.object.shade_smooth()  # set smooth shading

Now how do I know that this object has a property called location or anything else this can be done by :

1- Locking through the API DOCs: just search for the type of the object you want know about and you'll get a page containing all properties like this one for the Object type

2- Using the console select your object and type C.object. and hit Ctrl+Space then you will get a list of all properties avialable for this object

enter image description here

3- From the properties panel hover over any property and you'll get the python reference for this property

enter image description here

$\endgroup$
2
  • $\begingroup$ This is great @Chebhou! There is plenty of help here, I really appreciate you taking the time to generate a thorough review of what I'm doing. Someday, there will be a blender mesh cheat-sheet like this one for python $\endgroup$
    – uhoh
    May 27, 2015 at 14:18
  • $\begingroup$ oh @uhoh regarding cheatsheet, that might be pretty easy to do, but hard to do well $\endgroup$
    – zeffii
    May 27, 2015 at 14:45

You must log in to answer this question.

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