Recently I tried to make particle objects real in the new Blender particle system but couldn’t. It doesn’t seem to be supported yet, so until it is, I made a little Python script to do just that.
(EDIT: Just to clarify: There’s a “Convert” button in the modifier tab for each particle system, which works for converting hair, for example. But it doesn’t work for duplicated objects, i.e. when visualization type is “Object” or “Group”.)
EDIT: It is now fixed in svn, and there’s also CTRL+SHIFT+A which already works, see my post further down.
The script converts duplicated particle objects of particle systems which visualization type is set to “Object”, to real objects. Those converted objects are either linked duplicates of the original object, or they get their own data, as user choice. I also wanted to support the visualization type “Group”, but access to the grouped particle objects doesn’t seem to be supported yet by Blender Python.
The script looks for particle systems on the active object only. After the operation the converted objects are selected and also part of a group for easy access.
Here’s the script. Put it in your Blender scripts or custom scripts folder and access it from the scripts window under “Object” or from the Object/Scripts menu entry in the 3D view menu header, menu entry “Make Particle Objects Real”.
[EDIT] Version 0.2
Made script work also for 3D Text and Surface objects, prevented crash with Empty objects.
Limitations:
-
Right now only the first particle system gets operated on. Might be due to a bug in the Python API which I’ll be investigating and reporting if needed.
[EDIT] Might be my mistake. I found that for baked particle systems it works fine, so it seems that’s the solution. -
Surface objects get duplicated as Curve objects, I found no way around that. Any modifiers on the original object therefore can’t be copied to the new duplicated objects, because their type doesn’t match.
object-make-partobs-real.py version 0.2
#!BPY
"""
Name: 'Make Particle Objects Real'
Blender: 247svn
Group: 'Object'
Tooltip: 'Convert particle objects to real objects'
"""
__author__= "Sanne"
__url__= ["blenderartists.org"]
__version__= "0.2"
__bpydoc__= """
"""
# --------------------------------------------------------------------------
# Make Particle Objects Real v0.2 by Sanne
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
import Blender
def copyObject(ob, data, scn):
if hasattr(data, "copy"):
newob = scn.objects.new(data.copy())
else:
# text data doesn't have copy() method
if type(data) == Blender.Types.Text3dType:
txt = Blender.Text3d.New()
txt.setText(data.getText())
newob = scn.objects.new(txt)
else:
newob = 0
return newob
def makereal(ob, parts, scn, makelinks):
""" Make particle objects real """
for part in parts:
if part.type != Blender.Particle.TYPE.EMITTER:
continue
if part.drawAs == Blender.Particle.DRAWAS.OBJECT:
dupob = part.duplicateObject
if dupob.type == "Empty":
Blender.Draw.PupMenu("Unsupported object type %t | Can't convert Empty objects.")
print "No or wrong selection
Can't convert Empty objects."
return
elif dupob.type == "Surf":
Blender.Draw.PupMenu("Attention! %t | Surface object will be duplicated as curve objects. Modifiers can't be copied.")
print "Attention
Surface object will be duplicated as curve objects.
Modifiers can't be copied."
dupdata = dupob.getData(mesh=True)
# get location, rotation and sizes of all particle objects
plocs = part.getLoc()
prots = part.getRot()
psizes = part.getSize()
grp = Blender.Group.New()
# using part.amount sometimes gives list index out of range error
# BUG?: all part.getLoc() except from the first particle system are empty,
# so for now only objects of the first system are getting duplicated by the script
numparts = len(plocs)
for i in range(numparts):
if makelinks:
newob = scn.objects.new(dupdata)
else:
newob = copyObject(dupob, dupdata, scn)
if newob:
newob.loc = [x + y for x, y in zip(plocs[i], dupob.loc)]
newob.size = (psizes[i], psizes[i], psizes[i])
newob.rot = Blender.Mathutils.Quaternion(prots[i]).toEuler()
# Object data of a surface object is curve data, so scn.objects.new() generates
# a curve object out of surface object data. A newly made surface object via
# deprecated Blender.Object.New() can't be linked to curve data, getting:
# "AttributeError: The 'link' object is incompatible with the base object"
# Deaktivating copying modifiers for surface objects (can't be copied to curve duplicates)
if dupob.type != "Surf":
newob.modifiers = dupob.modifiers
grp.objects.link(newob)
elif part.drawAs == Blender.Particle.DRAWAS.GROUP:
# no access to the group name yet
pass
ob.sel = False
def main():
"""GUI function"""
scn = Blender.Scene.GetCurrent()
ob = scn.objects.active
if not ob:
Blender.Draw.PupMenu("No or wrong selection %t | Please select an object.")
print "No or wrong selection
Please select an object."
return
parts = ob.getParticleSystems()
if len(parts) == 0:
Blender.Draw.PupMenu("No or wrong selection %t | Active object has no particle system.")
print "No or wrong selection
Active object has no particle system."
return
# Can't delete/unlink particle system with Python (yet?)
#PREF_KEEPPARTSYS = Blender.Draw.Create(1)
PREF_MAKELINKS = Blender.Draw.Create(1)
# list for popup content
block = []
# inputs: title, button, min/max values, tooltip
#block.append(("Keep Particles ", PREF_KEEPPARTSYS, "Keep particle system"))
block.append(("Use Linked Data ", PREF_MAKELINKS, "Use linked data for newly generated objects"))
if not Blender.Draw.PupBlock("Make Particle Objects Real", block):
return
makereal(ob, parts, scn, PREF_MAKELINKS.val)
Blender.Window.RedrawAll()
# ------------------------
if __name__ == "__main__":
main()