There are a few uninstancer scripts and plugins around, but I stumbled upon a bit of python that Peter Shipkov (developer of the
SOuP toolset) which works great. Here's a link to the page:
http://soup-dev.websitetoolbox.com/post/Uninstancer-5887571
Here's the bit of code just in case the link or web site is somehow taken down at some point:
# save the code below in file named uninstancer.py
# select at least one instancer node in the maya scene and run the next command:
# import imp; uninstancer = imp.load_source('uninstancer','/path/to/uninstancer.py'); uninstancer.uninstancer().main()
import maya.cmds as mc
import maya.OpenMaya as om
import maya.OpenMayaFX as omfx
class uninstancer():
def main(self):
li = []
l = mc.ls(sl=True) or []
for n in l:
if mc.nodeType(n) != "instancer": continue
li.append(n)
if len(li) == 0: raise Exception('Select at least one instancer node.')
l = []
m = om.MMatrix()
dp = om.MDagPath()
dpa = om.MDagPathArray()
sa = om.MScriptUtil()
sa.createFromList([0.0, 0.0, 0.0], 3)
sp = sa.asDoublePtr()
sf = int(mc.playbackOptions(q=True, min=True))-1
ef = int(mc.playbackOptions(q=True, max=True))+2
for i in range(sf, ef):
mc.currentTime(i)
for inst in li:
g = inst+"_objects"
if i == sf:
if mc.objExists(g) == True: mc.delete(g)
mc.createNode("transform", n=g)
l.append(g)
sl = om.MSelectionList()
sl.add(inst)
sl.getDagPath(0, dp)
fni = omfx.MFnInstancer(dp)
for j in range(fni.particleCount()):
fni.instancesForParticle(j, dpa, m)
for k in range(dpa.length()):
n = inst+"_"+str(j)+"_"+dpa[k].partialPathName()
if mc.objExists(n) == False:
n2 = mc.duplicate(dpa[k].partialPathName())[0]
n = mc.rename(n2, n)
if mc.listRelatives(n, p=True) != g:
n = mc.parent(n, g)[0]
mc.setKeyframe(n+".v", t=i-1, v=False)
tm = om.MTransformationMatrix(m)
t = tm.getTranslation(om.MSpace.kWorld)
mc.setAttr(n+".t", t[0], t[1], t[2])
mc.setKeyframe(n+".t")
r = tm.eulerRotation().asVector()
mc.setAttr(n+".r", r[0]*57.2957795, r[1]*57.2957795, r[2]*57.2957795)
mc.setKeyframe(n+".r")
tm.getScale(sp, om.MSpace.kWorld)
sx = om.MScriptUtil().getDoubleArrayItem(sp, 0)
sy = om.MScriptUtil().getDoubleArrayItem(sp, 1)
sz = om.MScriptUtil().getDoubleArrayItem(sp, 2)
s = om.MTransformationMatrix(dpa[k].inclusiveMatrix()).getScale(sp, om.MSpace.kWorld)
sx2 = om.MScriptUtil().getDoubleArrayItem(sp, 0)
sy2 = om.MScriptUtil().getDoubleArrayItem(sp, 1)
sz2 = om.MScriptUtil().getDoubleArrayItem(sp, 2)
mc.setAttr(n+".s", sx*sx2, sy*sy2, sz*sz2)
mc.setKeyframe(n+".s")
mc.setAttr(n+".v", True)
mc.setKeyframe(n+".v")
mc.setKeyframe(n+".v", t=i+1, v=False)
return l
"This code will create animated individual copies of the base instanced objects. It supports point clouds with varying number of points - for instance - dying or newly created particles, or meshes with changning number of points over time.
Looking now at it before posting - i think it will not not accommodate for the case where the base objects have non-zeroed out TR channels."