#!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\nCan'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\nSurface object will be duplicated as curve objects.\nModifiers 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\nPlease 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\nActive 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()
