Add particle system without using bpy.ops?

Hi All,

What I am trying to do is create a plane and add a particle system to the plane.

Once again, bpy.ops is my enemy. It works fine in top down scripting, but when I try to use it in an operator, the context comes from the caller of the operator, in my case this happens to be an Empty.

This code works fine in top-down processing. Paste it into a code window and run it.


import bpy

bpy.ops.mesh.primitive_plane_add(location=(0,0,0))
temp_ob = bpy.context.object  #bpy.data.objects.get("Plane")
# Add a particle system.
bpy.ops.object.particle_system_add()    
psys = temp_ob.particle_systems[-1]
pset = psys.settings

But inside an operator, bpy.context.object is not the object that primitive_plane_add creates. My alternate solution is to fetch by the default name of ‘Plane’. This is rather shaky ground, however, because if I already have an object named ‘Plane’ I will get an object named ‘Plane.000’ instead and thus end up in the same boat of an object that is wrong or None for further processing.

What would be incredibly useful would be if primitive_plane_add could be extended to support a passed name value upon execution. Then I could at least know what the name of the newly created object was and fetch that directly.

Now the only reason I am fussing with primitive_plane_add is because particle_system_add seems to be the only way to add a particle system to an active selected mesh.

Does anyone know of a way to add a particle system to a mesh without using bpy.ops.particle_system_add?

What would be incredibly useful would be if particle_system_add could be extended to support a passed name value upon execution.

Here is another approach, just adding a particle system modifier.


my_ps = ob.modifiers.new("myPS",'PARTICLE_SYSTEM')

Now that I have a particle system in a variable I still need a way to add a particle system slot. This is the missing ingredient…

you can use an override to add a particle system to a non-selected, not active object:

>>> o={'active_object': D.objects['Cube.002'], 'object': D.objects['Cube.002'], 'window': C.window, 'region': C.region, 'scene': C.scene}
>>> bpy.ops.object.particle_system_add(o)

(region should actually be the 3d view’s region, but doesn’t seem to matter, even without window/region/scene the particle system is still created)

but anyway, adding a modifier seems to implicitly create a particle system + settings just fine:

p=C.object.modifiers.new("psys name", 'PARTICLE_SYSTEM')

>>> p.particle_system.settings.name
'ParticleSettings.005'

Thanks, passing a constructed context worked!

The API documentation need updated to reflect the fact that you can pass an optional parameter.
http://www.blender.org/documentation/blender_python_api_2_65_release/bpy.ops.object.html?highlight=particle_system_add#bpy.ops.object.particle_system_add

If you view the docs, there is no such information.

it does:
http://www.blender.org/documentation/blender_python_api_2_65_9/bpy.ops.html#overriding-context

every operator allows this

It would be nice if the link I posted actually linked back to the link you posted. Not everyone is going to understand that a function call is actually an operator. I certainly did not. But I guess you learn something new everyday!

well it says bpy.ops.*, ops = operators

True, but even as an experienced scripter I did not make the connection, let alone newbies. I thought I was calling functions.