diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index 4fc68d138e0..6fce0864189 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -96,6 +96,7 @@ struct ID; /*keep me up here */ #include "Window.h" #include "World.h" #include "Types.h" +#include "Particle.h" /**********************************************************/ /* Python API function prototypes for the Blender module. */ @@ -1074,6 +1075,7 @@ void M_Blender_Init(void) PyDict_SetItemString(dict, "Node", Node_Init()); PyDict_SetItemString(dict, "Noise", Noise_Init()); PyDict_SetItemString(dict, "Object", Object_Init()); + PyDict_SetItemString(dict, "Particle", ParticleSys_Init()); PyDict_SetItemString(dict, "Group", Group_Init()); PyDict_SetItemString(dict, "Registry", Registry_Init()); PyDict_SetItemString(dict, "Scene", Scene_Init()); diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 4d8caf5a55e..0883cd1896b 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -27,7 +27,7 @@ * * Contributor(s): Michel Selten, Willian Germano, Jacques Guignot, * Joseph Gilbert, Stephen Swaney, Bala Gi, Campbell Barton, Johnny Matthews, - * Ken Hughes, Alex Mole, Jean-Michel Soler + * Ken Hughes, Alex Mole, Jean-Michel Soler, Cedric Paille * * ***** END GPL LICENSE BLOCK ***** */ @@ -117,6 +117,7 @@ struct rctf; #include "EXPP_interface.h" #include "BIF_editkey.h" #include "IDProp.h" +#include "Particle.h" /* Defines for insertIpoKey */ @@ -336,6 +337,9 @@ struct PyMethodDef M_Object_methods[] = { static int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */ static int setupPI(Object* ob); +static PyObject *Object_getParticleSys( BPy_Object * self ); +/* fixme Object_newParticleSys( self, default-partsys-name ) */ +static PyObject *Object_newParticleSys( BPy_Object * self ); static PyObject *Object_buildParts( BPy_Object * self ); static PyObject *Object_clearIpo( BPy_Object * self ); static PyObject *Object_clrParent( BPy_Object * self, PyObject * args ); @@ -465,6 +469,10 @@ static PyObject *Object_upAxis(BPy_Object * self); /*****************************************************************************/ static PyMethodDef BPy_Object_methods[] = { /* name, method, flags, doc */ + {"getParticleSystems", ( PyCFunction ) Object_getParticleSys, METH_NOARGS, + "Return a list of particle systems"}, + {"newParticleSystem", ( PyCFunction ) Object_newParticleSys, METH_NOARGS, + "Create and link a new particle system"}, {"buildParts", ( PyCFunction ) Object_buildParts, METH_NOARGS, "Recalcs particle system (if any), (depricated, will always return an empty list in version 2.46)"}, {"getIpo", ( PyCFunction ) Object_getIpo, METH_NOARGS, @@ -1026,6 +1034,78 @@ static PyObject *M_Object_Duplicate( PyObject * self_unused, /* Python BPy_Object methods: */ /*****************************************************************************/ +PyObject *Object_getParticleSys( BPy_Object * self ){ + ParticleSystem *blparticlesys = 0; + Object *ob = self->object; + PyObject *partsyslist,*current; + + blparticlesys = ob->particlesystem.first; + + partsyslist = PyList_New( 0 ); + + if (!blparticlesys) + return partsyslist; + + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + + while(blparticlesys = blparticlesys->next){ + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + } + + return partsyslist; +} + +PyObject *Object_newParticleSys( BPy_Object * self ){ + ParticleSystem *psys = 0; + ParticleSystem *rpsys = 0; + ModifierData *md; + ParticleSystemModifierData *psmd; + Object *ob = self->object; + char *name = NULL; + ID *id; + int nr; + + id = (ID *)psys_new_settings("PSys", G.main); + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; + BLI_addtail(&ob->particlesystem,psys); + + md = modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + psmd = (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&ob->modifiers, md); + + psys->part=(ParticleSettings*)id; + psys->totpart=0; + psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0); + rpsys = psys; + + /* check need for dupliobjects */ + + nr=0; + for(psys=ob->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + ob->transflag |= OB_DUPLIPARTS; + else + ob->transflag &= ~OB_DUPLIPARTS; + + BIF_undo_push("Browse Particle System"); + + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + return ParticleSys_CreatePyObject(rpsys,ob); +} + static PyObject *Object_buildParts( BPy_Object * self ) { /* This is now handles by modifiers */ diff --git a/source/blender/python/api2_2x/Particle.c b/source/blender/python/api2_2x/Particle.c index 1de0360cd77..8e449638977 100644 --- a/source/blender/python/api2_2x/Particle.c +++ b/source/blender/python/api2_2x/Particle.c @@ -22,941 +22,1813 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot, Jean-Michel Soler + * Contributor(s): + * Original version: Jacques Guignot, Jean-Michel Soler + * Rewrite : Cedric Paille, Stephen Swaney, Joilnen Leite * * ***** END GPL LICENSE BLOCK ***** */ -#include "Particle.h" /*This must come first */ - -#include "DNA_object_types.h" -#include "BKE_effect.h" -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_object.h" -#include "BLI_blenlib.h" +#include "Particle.h" #include "gen_utils.h" +#include "BKE_object.h" +#include "BKE_main.h" +#include "BKE_particle.h" +#include "BKE_global.h" +#include "BKE_depsgraph.h" +#include "BKE_modifier.h" +#include "BKE_material.h" +#include "BKE_utildefines.h" +#include "BKE_pointcache.h" +#include "BIF_editparticle.h" +#include "BIF_space.h" +#include "blendef.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "DNA_material_types.h" +#include "BLI_blenlib.h" +#include "mydevice.h" +#include "Object.h" +#include "Material.h" -/*****************************************************************************/ -/* Python API function prototypes for the Particle module. */ -/*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ); -PyObject *M_Particle_Get( PyObject * self, PyObject * args ); - -/*****************************************************************************/ -/* Python BPy_Particle methods declarations: */ -/*****************************************************************************/ -PyObject *Effect_getType( BPy_Effect * self ); -PyObject *Effect_setType( BPy_Effect * self, PyObject * args ); -PyObject *Effect_getFlag( BPy_Effect * self ); -PyObject *Effect_setFlag( BPy_Effect * self, PyObject * args ); -PyObject *Particle_getSta( BPy_Particle * self ); -PyObject *Particle_setSta( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getEnd( BPy_Particle * self ); -PyObject *Particle_setEnd( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getLifetime( BPy_Particle * self ); -PyObject *Particle_setLifetime( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getNormfac( BPy_Particle * self ); -PyObject *Particle_setNormfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getObfac( BPy_Particle * self ); -PyObject *Particle_setObfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getRandfac( BPy_Particle * self ); -PyObject *Particle_setRandfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTexfac( BPy_Particle * self ); -PyObject *Particle_setTexfac( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getRandlife( BPy_Particle * self ); -PyObject *Particle_setRandlife( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getNabla( BPy_Particle * self ); -PyObject *Particle_setNabla( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getVectsize( BPy_Particle * self ); -PyObject *Particle_setVectsize( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTotpart( BPy_Particle * self ); -PyObject *Particle_setTotpart( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getTotkey( BPy_Particle * self ); -PyObject *Particle_setTotkey( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getSeed( BPy_Particle * self ); -PyObject *Particle_setSeed( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getForce( BPy_Particle * self ); -PyObject *Particle_setForce( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getMult( BPy_Particle * self ); -PyObject *Particle_setMult( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getLife( BPy_Particle * self ); -PyObject *Particle_setLife( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getMat( BPy_Particle * self ); -PyObject *Particle_setMat( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getChild( BPy_Particle * self ); -PyObject *Particle_setChild( BPy_Particle * self, PyObject * a ); -PyObject *Particle_getDefvec( BPy_Particle * self ); -PyObject *Particle_setDefvec( BPy_Particle * self, PyObject * a ); - -/*****************************************************************************/ -/* Python Particle_Type callback function prototypes: */ -/*****************************************************************************/ -void ParticleDeAlloc( BPy_Particle * msh ); -//int ParticlePrint (BPy_Particle *msh, FILE *fp, int flags); -int ParticleSetAttr( BPy_Particle * msh, char *name, PyObject * v ); -PyObject *ParticleGetAttr( BPy_Particle * msh, char *name ); -PyObject *ParticleRepr( void ); -PyObject *ParticleCreatePyObject( struct Effect *particle ); -int ParticleCheckPyObject( PyObject * py_obj ); -struct Particle *ParticleFromPyObject( PyObject * py_obj ); - - -/*****************************************************************************/ -/* Python BPy_Particle methods table: */ -/*****************************************************************************/ -static PyMethodDef BPy_Particle_methods[] = { - {"getType", ( PyCFunction ) Effect_getType, - METH_NOARGS, "() - Return Effect type"}, - {"setType", ( PyCFunction ) Effect_setType, - METH_VARARGS, "() - Set Effect type"}, - {"getFlag", ( PyCFunction ) Effect_getFlag, - METH_NOARGS, "() - Return Effect flag"}, - {"setFlag", ( PyCFunction ) Effect_setFlag, - METH_VARARGS, "() - Set Effect flag"}, - {"getStartTime", ( PyCFunction ) Particle_getSta, - METH_NOARGS, "()-Return particle start time"}, - {"setStartTime", ( PyCFunction ) Particle_setSta, METH_VARARGS, - "()- Sets particle start time"}, - {"getEndTime", ( PyCFunction ) Particle_getEnd, - METH_NOARGS, "()-Return particle end time"}, - {"setEndTime", ( PyCFunction ) Particle_setEnd, METH_VARARGS, - "()- Sets particle end time"}, - {"getLifetime", ( PyCFunction ) Particle_getLifetime, - METH_NOARGS, "()-Return particle life time"}, - {"setLifetime", ( PyCFunction ) Particle_setLifetime, METH_VARARGS, - "()- Sets particle life time "}, - {"getNormfac", ( PyCFunction ) Particle_getNormfac, - METH_NOARGS, "()-Return particle life time"}, - {"setNormfac", ( PyCFunction ) Particle_setNormfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getObfac", ( PyCFunction ) Particle_getObfac, - METH_NOARGS, "()-Return particle life time"}, - {"setObfac", ( PyCFunction ) Particle_setObfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getRandfac", ( PyCFunction ) Particle_getRandfac, - METH_NOARGS, "()-Return particle life time"}, - {"setRandfac", ( PyCFunction ) Particle_setRandfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getTexfac", ( PyCFunction ) Particle_getTexfac, - METH_NOARGS, "()-Return particle life time"}, - {"setTexfac", ( PyCFunction ) Particle_setTexfac, METH_VARARGS, - "()- Sets particle life time "}, - {"getRandlife", ( PyCFunction ) Particle_getRandlife, - METH_NOARGS, "()-Return particle life time"}, - {"setRandlife", ( PyCFunction ) Particle_setRandlife, METH_VARARGS, - "()- Sets particle life time "}, - {"getNabla", ( PyCFunction ) Particle_getNabla, - METH_NOARGS, "()-Return particle life time"}, - {"setNabla", ( PyCFunction ) Particle_setNabla, METH_VARARGS, - "()- Sets particle life time "}, - {"getVectsize", ( PyCFunction ) Particle_getVectsize, - METH_NOARGS, "()-Return particle life time"}, - {"setVectsize", ( PyCFunction ) Particle_setVectsize, METH_VARARGS, - "()- Sets particle life time "}, - {"getTotpart", ( PyCFunction ) Particle_getTotpart, - METH_NOARGS, "()-Return particle life time"}, - {"setTotpart", ( PyCFunction ) Particle_setTotpart, METH_VARARGS, - "()- Sets particle life time "}, - {"getTotkey", ( PyCFunction ) Particle_getTotkey, - METH_NOARGS, "()-Return particle life time"}, - {"setTotkey", ( PyCFunction ) Particle_setTotkey, METH_VARARGS, - "()- Sets particle life time "}, - {"getSeed", ( PyCFunction ) Particle_getSeed, - METH_NOARGS, "()-Return particle life time"}, - {"setSeed", ( PyCFunction ) Particle_setSeed, METH_VARARGS, - "()- Sets particle life time "}, - {"getForce", ( PyCFunction ) Particle_getForce, - METH_NOARGS, "()-Return particle life time"}, - {"setForce", ( PyCFunction ) Particle_setForce, METH_VARARGS, - "()- Sets particle life time "}, - {"getMult", ( PyCFunction ) Particle_getMult, - METH_NOARGS, "()-Return particle life time"}, - {"setMult", ( PyCFunction ) Particle_setMult, METH_VARARGS, - "()- Sets particle life time "}, - {"getLife", ( PyCFunction ) Particle_getLife, - METH_NOARGS, "()-Return particle life time"}, - {"setLife", ( PyCFunction ) Particle_setLife, METH_VARARGS, - "()- Sets particle life time "}, - {"getMat", ( PyCFunction ) Particle_getMat, - METH_NOARGS, "()-Return particle life time"}, - {"setMat", ( PyCFunction ) Particle_setMat, METH_VARARGS, - "()- Sets particle life time "}, - {"getChild", ( PyCFunction ) Particle_getChild, - METH_NOARGS, "()-Return particle life time"}, - {"setChild", ( PyCFunction ) Particle_setChild, METH_VARARGS, - "()- Sets particle life time "}, - {"getDefvec", ( PyCFunction ) Particle_getDefvec, - METH_NOARGS, "()-Return particle life time"}, - {"setDefvec", ( PyCFunction ) Particle_setDefvec, METH_VARARGS, - "()- Sets particle life time "}, - - - {NULL, NULL, 0, NULL} -}; - -/**************** prototypes ********************/ -PyObject *Particle_Init( void ); +#include "MEM_guardedalloc.h" -/*****************************************************************************/ -/* Python Particle_Type structure definition: */ -/*****************************************************************************/ -PyTypeObject Particle_Type = { - PyObject_HEAD_INIT( NULL ) - 0, - "Particle", - sizeof( BPy_Particle ), - 0, +/* Type Methods */ +static PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ); +static PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ); + +/* Particle Methods */ +static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ); +static int Part_setSeed( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getSeed( BPy_PartSys * self ); +static int Part_setType( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getType( BPy_PartSys * self ); +static int Part_setResol( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getResol( BPy_PartSys * self ); +static int Part_setStart( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStart( BPy_PartSys * self ); +static int Part_setEnd( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEnd( BPy_PartSys * self ); +static int Part_setEditable( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEditable( BPy_PartSys * self ); +static int Part_setAmount( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getAmount( BPy_PartSys * self ); +static int Part_setMultiReact( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMultiReact( BPy_PartSys * self ); +static int Part_setReactShape( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getReactShape( BPy_PartSys * self ); +static int Part_setSegments( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getSegments( BPy_PartSys * self ); +static int Part_setLife( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getLife( BPy_PartSys * self ); +static int Part_setRandLife( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRandLife( BPy_PartSys * self ); +static int Part_set2d( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_get2d( BPy_PartSys * self ); +static int Part_setMaxVel( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMaxVel( BPy_PartSys * self ); +static int Part_setAvVel( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getAvVel( BPy_PartSys * self ); +static int Part_setLatAcc( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getLatAcc( BPy_PartSys * self ); +static int Part_setMaxTan( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getMaxTan( BPy_PartSys * self ); +static int Part_setGroundZ( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getGroundZ( BPy_PartSys * self ); +static int Part_setOb( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getOb( BPy_PartSys * self ); +static PyObject *Part_getRandEmission( BPy_PartSys * self ); +static int Part_setRandEmission( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRandEmission( BPy_PartSys * self ); +static int Part_setParticleDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getParticleDist( BPy_PartSys * self ); +static int Part_setEvenDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getEvenDist( BPy_PartSys * self ); +static int Part_setDist( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getDist( BPy_PartSys * self ); +static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getParticleDisp( BPy_PartSys * self ); +static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getJitterAmount( BPy_PartSys * self ); +static int Part_setPF( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getPF( BPy_PartSys * self ); +static int Part_setInvert( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getInvert( BPy_PartSys * self ); +static int Part_setTargetOb( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getTargetOb( BPy_PartSys * self ); +static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getTargetPsys( BPy_PartSys * self ); +static int Part_setRenderObject( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRenderObject( BPy_PartSys * self ); +static int Part_setStep( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getStep( BPy_PartSys * self ); +static int Part_setRenderStep( BPy_PartSys * self, PyObject * args ); +static PyObject *Part_getRenderStep( BPy_PartSys * self ); +static PyObject *Part_getDupOb( BPy_PartSys * self ); +static PyObject *Part_getDrawAs( BPy_PartSys * self ); +static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ); + +/*****************************************************************************/ +/* Python Effect_Type callback function prototypes: */ +/*****************************************************************************/ +static PyObject *ParticleSys_repr( void ); - ( destructor ) ParticleDeAlloc, - 0, - ( getattrfunc ) ParticleGetAttr, - ( setattrfunc ) ParticleSetAttr, - 0, - ( reprfunc ) ParticleRepr, - 0, - 0, - 0, - 0, - 0, 0, 0, 0, 0, 0, - 0, - 0, 0, 0, 0, 0, 0, - BPy_Particle_methods, - 0, -}; /*****************************************************************************/ /* The following string definitions are used for documentation strings. */ /* In Python these will be written to the console when doing a */ /* Blender.Particle.__doc__ */ /*****************************************************************************/ -char M_Particle_doc[] = "The Blender Particle module\n\n\ +static char M_ParticleSys_doc[] = "The Blender Effect module\n\n\ This module provides access to **Object Data** in Blender.\n\ Functions :\n\ - New(object mesh's name) : creates a new part object and adds it to the given mesh object \n\ - Get(name) : retreives a particle with the given name (mandatory)\n\ - get(name) : same as Get. Kept for compatibility reasons.\n"; -char M_Particle_New_doc[] = "New(name) : creates a new part object and adds it to the given mesh object\n"; -char M_Particle_Get_doc[] = "xxx"; + Get(name) : retreives particle system (as list) with the given name\n"; +static char M_ParticleSys_Get_doc[] = "xxx"; +static char M_ParticleSys_New_doc[] = "xxx"; +/*****************************************************************************/ +/* Python BPy_ParticleSys methods table: */ +/*****************************************************************************/ + +static PyMethodDef BPy_ParticleSys_methods[] = { + {"freeEdit", ( PyCFunction ) Part_freeEdit, + METH_NOARGS, "() - Free from edit mode"}, + {"getLoc", ( PyCFunction ) Part_GetLoc, + METH_VARARGS, "() - Get particles location"}, + {"getRot", ( PyCFunction ) Part_GetRot, + METH_VARARGS, "() - Get particles rotations (list of 4 floats quaternion)"}, + {"getMat", ( PyCFunction ) Part_GetMat, + METH_NOARGS, "() - Get particles material"}, + {"getSize", ( PyCFunction ) Part_GetSize, + METH_VARARGS, "() - Get particles size in a list"}, + {"getAge", ( PyCFunction ) Part_GetAge, + METH_VARARGS, "() - Get particles life in a list"}, + {NULL, NULL, 0, NULL} +}; + +/*****************************************************************************/ +/* Python BPy_ParticleSys attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef BPy_ParticleSys_getseters[] = { +/* Extras */ + {"seed", + (getter)Part_getSeed, (setter)Part_setSeed, + "Set an offset in the random table", + NULL}, + /* basics */ + {"type", + (getter)Part_getType, (setter)Part_setType, + "Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] )", + NULL}, + {"resolutionGrid", + (getter)Part_getResol, (setter)Part_setResol, + "The resolution of the particle grid", + NULL}, + {"startFrame", + (getter)Part_getStart, (setter)Part_setStart, + "Frame # to start emitting particles", + NULL}, + {"endFrame", + (getter)Part_getEnd, (setter)Part_setEnd, + "Frame # to stop emitting particles", + NULL}, + {"editable", + (getter)Part_getEditable, (setter)Part_setEditable, + "Finalize hair to enable editing in particle mode", + NULL}, + {"amount", + (getter)Part_getAmount, (setter)Part_setAmount, + "The total number of particles", + NULL}, + {"multireact", + (getter)Part_getMultiReact, (setter)Part_setMultiReact, + "React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] )", + NULL}, + {"reactshape", + (getter)Part_getReactShape, (setter)Part_setReactShape, + "Power of reaction strength dependence on distance to target", + NULL}, + {"hairSegments", + (getter)Part_getSegments, (setter)Part_setSegments, + "Amount of hair segments", + NULL}, + {"lifetime", + (getter)Part_getLife, (setter)Part_setLife, + "Specify the life span of the particles", + NULL}, + {"randlife", + (getter)Part_getRandLife, (setter)Part_setRandLife, + "Give the particle life a random variation", + NULL}, + {"randemission", + (getter)Part_getRandEmission, (setter)Part_setRandEmission, + "Give the particle life a random variation", + NULL}, + {"particleDistribution", + (getter)Part_getParticleDist, (setter)Part_setParticleDist, + "Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )", + NULL}, + {"evenDistribution", + (getter)Part_getEvenDist, (setter)Part_setEvenDist, + "Use even distribution from faces based on face areas or edge lengths", + NULL}, + {"distribution", + (getter)Part_getDist, (setter)Part_setDist, + "How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] )", + NULL}, + {"jitterAmount", + (getter)Part_getJitterAmount, (setter)Part_setJitterAmount, + "Amount of jitter applied to the sampling", + NULL}, + {"pf", + (getter)Part_getPF, (setter)Part_setPF, + "Emission locations / face (0 = automatic)", + NULL}, + {"invert", + (getter)Part_getInvert, (setter)Part_setInvert, + "Invert what is considered object and what is not.", + NULL}, + {"targetObject", + (getter)Part_getTargetOb, (setter)Part_setTargetOb, + "The object that has the target particle system (empty if same object)", + NULL}, + {"targetpsys", + (getter)Part_getTargetPsys, (setter)Part_setTargetPsys, + "The target particle system number in the object", + NULL}, +/* Physics */ + {"2d", + (getter)Part_get2d, (setter)Part_set2d, + "Constrain boids to a surface", + NULL}, + {"maxvel", + (getter)Part_getMaxVel, (setter)Part_setMaxVel, + "Maximum velocity", + NULL}, + {"avvel", + (getter)Part_getAvVel, (setter)Part_setAvVel, + "The usual speed % of max velocity", + NULL}, + {"latacc", + (getter)Part_getLatAcc, (setter)Part_setLatAcc, + "Lateral acceleration % of max velocity", + NULL}, + {"tanacc", + (getter)Part_getMaxTan, (setter)Part_setMaxTan, + "Tangential acceleration % of max velocity", + NULL}, + {"groundz", + (getter)Part_getGroundZ, (setter)Part_setGroundZ, + "Default Z value", + NULL}, + {"object", + (getter)Part_getOb, (setter)Part_setOb, + "Constrain boids to object's surface", + NULL}, +/* Visualisation */ + {"renderEmitter", + (getter)Part_getRenderObject, (setter)Part_setRenderObject, + "Render emitter object", + NULL}, + {"displayPercentage", + (getter)Part_getParticleDisp, (setter)Part_setParticleDisp, + "Particle display percentage", + NULL}, + {"hairDisplayStep", + (getter)Part_getStep, (setter)Part_setStep, + "How many steps paths are drawn with (power of 2)", + NULL}, + {"hairRenderStep", + (getter)Part_getRenderStep, (setter)Part_setRenderStep, + "How many steps paths are rendered with (power of 2)", + NULL}, + {"duplicateObject", + (getter)Part_getDupOb, NULL, + "Get the duplicate ob", + NULL}, + {"drawAs", + (getter)Part_getDrawAs, NULL, + "Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )", + NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; /*****************************************************************************/ /* Python method structure definition for Blender.Particle module: */ /*****************************************************************************/ -struct PyMethodDef M_Particle_methods[] = { - {"New", ( PyCFunction ) M_Particle_New, METH_VARARGS, M_Particle_New_doc}, - {"Get", M_Particle_Get, METH_VARARGS, M_Particle_Get_doc}, - {"get", M_Particle_Get, METH_VARARGS, M_Particle_Get_doc}, +static struct PyMethodDef M_ParticleSys_methods[] = { + {"New", ( PyCFunction ) M_ParticleSys_New, METH_VARARGS, M_ParticleSys_New_doc}, + {"Get", M_ParticleSys_Get, METH_VARARGS, M_ParticleSys_Get_doc}, {NULL, NULL, 0, NULL} }; +/*****************************************************************************/ +/* Python ParticleSys_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject ParticleSys_Type = { + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ + /* For printing, in format "." */ + "Blender ParticleSys", /* char *tp_name; */ + sizeof( BPy_PartSys ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + NULL, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* cmpfunc tp_compare; */ + ( reprfunc ) ParticleSys_repr,/* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + BPy_ParticleSys_methods, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + BPy_ParticleSys_getseters, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; /*****************************************************************************/ -/* Function: M_Particle_New */ -/* Python equivalent: Blender.Effect.Particle.New */ -/* Description : Create a particle effect and add a link */ -/* to the given mesh-type Object */ -/* Data : String mesh object name */ -/* Return : pyobject particle */ +/* Function: PARTICLESYS_repr */ +/* Description: This is a callback function for the BPy_Effect type. It */ +/* builds a meaninful string to represent effcte objects. */ /*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ) + +static PyObject *ParticleSys_repr( void ) { - printf("warning, static particles api removed\n"); - Py_INCREF( Py_None ); - return Py_None; + return PyString_FromString( "ParticleSys" ); } /*****************************************************************************/ -/* Function: M_Particle_Get */ -/* Python equivalent: Blender.Effect.Particle.Get */ +/* Function : P_sys_FromPyObject */ /*****************************************************************************/ -PyObject *M_Particle_Get( PyObject * self, PyObject * args ) + +struct ParticleSystem *P_sys_FromPyObject( BPy_PartSys * py_obj ) { - printf("warning, static particles api removed\n"); - Py_INCREF( Py_None ); - return Py_None; + BPy_PartSys *blen_obj; + + blen_obj = ( BPy_PartSys * ) py_obj; + return ( blen_obj->psys ); } /*****************************************************************************/ -/* Function: Particle_Init */ +/* Function : ParticleSysCreatePyObject */ /*****************************************************************************/ -PyObject *Particle_Init( void ) +PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob ) { + BPy_PartSys *blen_object; + + blen_object = + ( BPy_PartSys * ) PyObject_NEW( BPy_PartSys, &ParticleSys_Type ); + + if( blen_object ) + blen_object->psys = (ParticleSystem *)psystem; + + blen_object->object = ob; + + return ( PyObject * ) blen_object; +} + + +PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ){ + ParticleSystem *psys = 0; + ParticleSystem *rpsys = 0; + ModifierData *md; + ParticleSystemModifierData *psmd; + Object *ob = NULL; + char *name = NULL; + ID *id; + int nr; + + if( !PyArg_ParseTuple( args, "s", &name ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + for( ob = G.main->object.first; ob; ob = ob->id.next ) + if( !strcmp( name, ob->id.name + 2 ) ) + break; + + if( !ob ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "object does not exist" ); + + id = (ID *)psys_new_settings("PSys", G.main); + + psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; + BLI_addtail(&ob->particlesystem,psys); + + md = modifier_new(eModifierType_ParticleSystem); + sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem)); + psmd = (ParticleSystemModifierData*) md; + psmd->psys=psys; + BLI_addtail(&ob->modifiers, md); + + psys->part=(ParticleSettings*)id; + psys->totpart=0; + psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0); + rpsys = psys; + + /* check need for dupliobjects */ + + nr=0; + for(psys=ob->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + ob->transflag |= OB_DUPLIPARTS; + else + ob->transflag &= ~OB_DUPLIPARTS; + + BIF_undo_push("Browse Particle System"); + + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + return ParticleSys_CreatePyObject(rpsys,ob); +} + + +/* + +Get( name ) returns named particle sys or list of all +throws NameError if name not found + +*/ + +PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) +{ + ParticleSettings *psys_iter; + char *name = NULL; +#if 0 + + ParticleSystem *blparticlesys = 0; + Object *ob; + + PyObject *partsyslist,*current; +#endif + if( !PyArg_ParseTuple( args, "|s", &name ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected string argument" ); + + psys_iter = G.main->particle.first; /* initialize our iterator */ + + if( name ) { /* find psys by name */ + + PyObject *wanted_obj = NULL; + + while( psys_iter && ! wanted_obj ){ + if( !strcmp( name, psys_iter->id.name + 2)){ + printf("** found %s\n", psys_iter->id.name+2); + //wanted_obj = ParticleSys_CreatePyObject( psys_iter ); + break; + } + psys_iter = psys_iter->id.next; + } + + if( !wanted_obj){ /* requested object not found */ + char error_msg[64]; + PyOS_snprintf( error_msg, sizeof( error_msg ), + "Particle System '%s' not found", name); + return EXPP_ReturnPyObjError( PyExc_NameError, error_msg ); + } + + return wanted_obj; + + }else { /* no arg - return a list of bpy objs all P. systems */ + + PyObject *pylist; + PyObject *pyobj; + int index = 0; + + pylist = PyList_New( BLI_countlist( &G.main->particle )); + printf("** list is %d long\n", PyList_Size( pylist)); + if( ! pylist ){ + return EXPP_ReturnPyObjError( + PyExc_MemoryError, + "could not create ParticleSystem list"); + } + + while( psys_iter ){ +#if 0 + pyobj = ParticleSystem_CreatePyObject( psys_iter); + if( !pyobj){ + Py_DECREF( pylist ); + return EXPP_ReturnPyObjError( + PyExc_MemoryError, + "could not create ParticleSystem PyObject"); + } + PyList_SET_ITEM( pylist, index, pyobj); +#endif + printf("name is %s\n", psys_iter->id.name+2); + psys_iter = psys_iter->id.next; + index++; + } + + return pylist; + + } + + + +#if 0 + + for( ob = G.main->particlesystem.first; ob; ob = ob->id.next ) + if( !strcmp( name, ob->id.name + 2 ) ) + break; + + if( !ob ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "object does not exist" ); + + blparticlesys = ob->particlesystem.first; + + + partsyslist = PyList_New( 0 ); + + if (!blparticlesys) + return partsyslist; + + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + + + while((blparticlesys = blparticlesys->next)){ + current = ParticleSys_CreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + } + + return partsyslist; + +#endif +} + + +/*****************************************************************************/ +/* Function: ParticleSys_Init */ +/*****************************************************************************/ + +/* create the Blender.Particle.Type constant dict */ + +static PyObject *Particle_TypeDict( void ) +{ + PyObject *Types = PyConstant_New( ); + + if( Types ) { + BPy_constant *c = ( BPy_constant * ) Types; + + PyConstant_Insert( c, "HAIR", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "REACTOR", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "EMITTER", + PyInt_FromLong( 0 ) ); + } + return Types; +} + +/* create the Blender.Particle.Distribution constant dict */ + +static PyObject *Particle_DistrDict( void ) +{ + PyObject *Distr = PyConstant_New( ); + + if( Distr ) { + BPy_constant *c = ( BPy_constant * ) Distr; + + PyConstant_Insert( c, "GRID", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "RANDOM", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "JITTERED", + PyInt_FromLong( 0 ) ); + } + return Distr; +} + +/* create the Blender.Particle.EmitFrom constant dict */ + +static PyObject *Particle_EmitFrom( void ) +{ + PyObject *EmitFrom = PyConstant_New( ); + + if( EmitFrom ) { + BPy_constant *c = ( BPy_constant * ) EmitFrom; + + PyConstant_Insert( c, "VERTS", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( c, "FACES", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "VOLUME", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "PARTICLE", + PyInt_FromLong( 3 ) ); + } + return EmitFrom; +} + +/* create the Blender.Particle.Collision constant dict */ + +static PyObject *Particle_ReactOnDict( void ) +{ + PyObject *ReactOn = PyConstant_New( ); + + if( ReactOn ) { + BPy_constant *c = ( BPy_constant * ) ReactOn; + + PyConstant_Insert( c, "NEAR", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "COLLISION", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "DEATH", + PyInt_FromLong( 0 ) ); + } + return ReactOn; +} + +static PyObject *Particle_DrawAs( void ) +{ + PyObject *DrawAs = PyConstant_New( ); + + if( DrawAs ) { + BPy_constant *c = ( BPy_constant * ) DrawAs; + + PyConstant_Insert( c, "NONE", + PyInt_FromLong( 0 ) ); + PyConstant_Insert( c, "POINT", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "CIRCLE", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "CROSS", + PyInt_FromLong( 3 ) ); + PyConstant_Insert( c, "AXIS", + PyInt_FromLong( 4 ) ); + PyConstant_Insert( c, "LINE", + PyInt_FromLong( 5 ) ); + PyConstant_Insert( c, "PATH", + PyInt_FromLong( 6 ) ); + PyConstant_Insert( c, "OBJECT", + PyInt_FromLong( 7 ) ); + PyConstant_Insert( c, "GROUP", + PyInt_FromLong( 8 ) ); + PyConstant_Insert( c, "BILLBOARD", + PyInt_FromLong( 9 ) ); + } + return DrawAs; +} + +void Particle_Recalc(BPy_PartSys* self,int child){ + psys_flush_settings(self->psys->part,0,child ); +} + +void Particle_RecalcPsys_distr(BPy_PartSys* self,int child){ + psys_flush_settings(self->psys->part,PSYS_DISTR,child); +} + +PyObject *ParticleSys_Init( void ){ PyObject *submodule; - - if( PyType_Ready( &Particle_Type) < 0) + PyObject *Types; + PyObject *React; + PyObject *EmitFrom; + PyObject *Dist; + PyObject *DrawAs; + + if( PyType_Ready( &ParticleSys_Type ) < 0) return NULL; - - submodule = - Py_InitModule3( "Blender.Particle", M_Particle_methods, M_Particle_doc ); + + Types = Particle_TypeDict (); + React = Particle_ReactOnDict(); + EmitFrom = Particle_EmitFrom(); + DrawAs = Particle_DrawAs(); + Dist = Particle_DistrDict(); + + submodule = Py_InitModule3( "Blender.Particle", + M_ParticleSys_methods, M_ParticleSys_doc ); + + if( Types ) + PyModule_AddObject( submodule, "TYPE", Types ); + if( React ) + PyModule_AddObject( submodule, "REACTON", React ); + if( EmitFrom ) + PyModule_AddObject( submodule, "EMITFROM", EmitFrom ); + if( Dist ) + PyModule_AddObject( submodule, "DISTRIBUTION", Dist ); + if( DrawAs ) + PyModule_AddObject( submodule, "DRAWAS", DrawAs ); + return ( submodule ); } -/*****************************************************************************/ -/* Python BPy_Particle methods: */ -/*****************************************************************************/ +static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ){ -PyObject *Particle_getSta( BPy_Particle * self ) -{ + if(self->psys->flag & PSYS_EDITED){ + if(self->psys->edit) + PE_free_particle_edit(self->psys); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->sta ); + self->psys->flag &= ~PSYS_EDITED; + self->psys->recalc |= PSYS_RECALC_HAIR; + + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); + } + Py_RETURN_NONE; +} + +static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args ){ + ParticleSystem *psys = 0L; + Object *ob = 0L; + PyObject *partlist,*seglist; + PyObject* loc; + ParticleCacheKey **cache,*path; + ParticleKey state; + float cfra=bsystem_time(ob,(float)CFRA,0.0); + int i,j,k; + int childexists = 0; + int all = 0; + int id = 0; + + if( !PyArg_ParseTuple( args, "|ii", &all,&id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + if (psys->part->type == 2){ + cache=psys->pathcache; + + /* little hack to calculate hair steps in render mode */ + psys->renderdata = (void*)(int)1; + + psys_cache_paths(ob, psys, cfra, 0); + + psys->renderdata = NULL; + + partlist = PyList_New( 0 ); + if( !partlist ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" ); + + for(i = 0; i < psys->totpart; i++){ + path=cache[i]; + seglist = PyList_New( 0 ); + k = path->steps+1; + for( j = 0; j < k ; j++){ + loc = PyTuple_New(3); + + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2])); + + if ( (PyList_Append(seglist,loc) < 0) ){ + Py_DECREF(seglist); + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + + path++; + } + + if ( PyList_Append(partlist,seglist) < 0 ){ + Py_DECREF(seglist); + Py_DECREF(partlist); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + + cache=psys->childcache; + + for(i = 0; i < psys->totchild; i++){ + path=cache[i]; + seglist = PyList_New( 0 ); + k = path->steps+1; + for( j = 0; j < k ; j++){ + loc = PyTuple_New(3); + + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2])); + + if ( PyList_Append(seglist,loc) < 0){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + + path++; + } + + if ( PyList_Append(partlist,seglist) < 0){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + + } else { + int init; + partlist = PyList_New( 0 ); + if( !partlist ) + return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + if (childexists && (i < psys->totpart)) + continue; + + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + init = 0; + else + init = 1; + + if (init){ + if (!id) + loc = PyTuple_New(3); + else + loc = PyTuple_New(4); + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.co[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.co[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.co[2])); + if (id) + PyTuple_SetItem(loc,3,PyInt_FromLong(i)); + + if ( PyList_Append(partlist,loc) < 0 ){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + else { + if ( all ){ + if ( PyList_Append(partlist,Py_None) < 0 ){ + Py_DECREF(partlist); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + } + } + } + return partlist; +} + +static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){ + ParticleSystem *psys = 0L; + Object *ob = 0L; + PyObject *partlist; + PyObject* loc = 0L; + ParticleKey state; + int i; + int childexists = 0; + int all = 0; + int id = 0; + + float cfra=bsystem_time(ob,(float)CFRA,0.0); + + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + if (psys->part->type != 2){ + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + if (childexists && (i < psys->totpart)) + continue; + + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0){ + if ( all ){ + PyList_Append(partlist,Py_None); + continue; + } else { + continue; + } + } + if (!id) + loc = PyTuple_New(4); + else + loc = PyTuple_New(5); + PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.rot[0])); + PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.rot[1])); + PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.rot[2])); + PyTuple_SetItem(loc,3,PyFloat_FromDouble((double)state.rot[3])); + if (id) + PyTuple_SetItem(loc,4,PyInt_FromLong(i)); + PyList_Append(partlist,loc); + } + } + return partlist; +} + +static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){ + ParticleKey state; + ParticleSystem *psys = 0L; + ParticleData *data; + Object *ob = 0L; + PyObject *partlist,*tuple; + PyObject* siz = 0L; + float size; + int i; + int childexists = 0; + int all = 0; + int id = 0; + + float cfra=bsystem_time(ob,(float)CFRA,0.0); + + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); + + data = self->psys->particles; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++, data++){ + if (psys->part->type != 2){ + if (childexists && (i < psys->totpart)) + continue; + + if ( !all ){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + continue; + } + + if (i < psys->totpart){ + size = data->size; + } else { + ChildParticle *cpa= &psys->child[i-psys->totpart]; + size = psys_get_child_size(psys,cpa,cfra,0); + } + if (id){ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)size)); + PyTuple_SetItem(tuple,1,PyInt_FromLong(i)); + PyList_Append(partlist,tuple); + } else { + siz = PyFloat_FromDouble((double)size); + PyList_Append(partlist,siz); + } + } + } + return partlist; } +static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){ + ParticleKey state; + ParticleSystem *psys = 0L; + ParticleData *data; + Object *ob = 0L; + PyObject *partlist,*tuple; + PyObject* lif = 0L; + float life; + int i; + int childexists = 0; + int all = 0; + int id = 0; -PyObject *Particle_setSta( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->sta = val; - Py_INCREF( Py_None ); - return Py_None; -} + float cfra=bsystem_time(ob,(float)CFRA,0.0); -PyObject *Particle_getEnd( BPy_Particle * self ) -{ + if( !PyArg_ParseTuple( args, "|ii", &all, &id ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected one optional integer as argument" ); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->end ); + data = self->psys->particles; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + Py_RETURN_NONE; + + partlist = PyList_New( 0 ); + + if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT)) + childexists = 1; + + for (i = 0; i < psys->totpart + psys->totchild; i++, data++){ + if (psys->part->type != 2){ + + if (childexists && (i < psys->totpart)) + continue; + + if ( !all ){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + continue; + } + + if (i < psys->totpart){ + life = (cfra-data->time)/data->lifetime; + } else { + ChildParticle *cpa= &psys->child[i-psys->totpart]; + life = psys_get_child_time(psys,cpa,cfra); + } + if (id){ + tuple = PyTuple_New(2); + PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)life)); + PyTuple_SetItem(tuple,1,PyInt_FromLong(i)); + PyList_Append(partlist,tuple); + } else { + lif = PyFloat_FromDouble((double)life); + PyList_Append(partlist,lif); + } + } + } + return partlist; } - -PyObject *Particle_setEnd( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->end = val; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getLifetime( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->lifetime ); -} - - - -PyObject *Particle_setLifetime( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->lifetime = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getNormfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->normfac ); -} - - - -PyObject *Particle_setNormfac( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->normfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getObfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->obfac ); -} - - - -PyObject *Particle_setObfac( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->obfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getRandfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randfac ); -} - - - -PyObject *Particle_setRandfac( BPy_Particle * self, PyObject * args ) -{ - float val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->randfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getTexfac( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->texfac ); -} - - - -PyObject *Particle_setTexfac( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->texfac = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getRandlife( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randlife ); -} - - - -PyObject *Particle_setRandlife( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->randlife = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getNabla( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->nabla ); -} - - - -PyObject *Particle_setNabla( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->nabla = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getVectsize( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->vectsize ); -} - - - -PyObject *Particle_setVectsize( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val = 0; - if( !PyArg_ParseTuple( args, "f", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - ptr->vectsize = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getTotpart( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totpart ); -} - - - -PyObject *Particle_setTotpart( BPy_Particle * self, PyObject * args ) -{ - int val = 0; - PartEff *ptr = ( PartEff * ) self->particle; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->totpart = val; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getTotkey( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totkey ); -} - - - -PyObject *Particle_setTotkey( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - int val = 0; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->totkey = val; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getSeed( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->seed ); -} - - - -PyObject *Particle_setSeed( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - int val = 0; - if( !PyArg_ParseTuple( args, "i", &val ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected int argument" ) ); - ptr->seed = val; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getForce( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", ptr->force[0], ptr->force[1], - ptr->force[2] ); -} - - -PyObject *Particle_setForce( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[3]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - /* - if (!PyArg_ParseTuple(args, "fff", val,val+1,val+2 )) - return(EXPP_ReturnPyObjError(PyExc_AttributeError,\ - "expected three float arguments")); - */ - ptr->force[0] = val[0]; - ptr->force[1] = val[1]; - ptr->force[2] = val[2]; - Py_INCREF( Py_None ); - return Py_None; -} - -PyObject *Particle_getMult( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mult[0], ptr->mult[1], ptr->mult[2], - ptr->mult[3] ); -} - - -PyObject *Particle_setMult( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->mult[0] = val[0]; - ptr->mult[1] = val[1]; - ptr->mult[2] = val[2]; - ptr->mult[3] = val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - - -PyObject *Particle_getLife( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->life[0], ptr->life[1], ptr->life[2], - ptr->life[3] ); -} - - -PyObject *Particle_setLife( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->life[0] = val[0]; - ptr->life[1] = val[1]; - ptr->life[2] = val[2]; - ptr->life[3] = val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getChild( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->child[0], ptr->child[1], ptr->child[2], - ptr->child[3] ); -} - - -PyObject *Particle_setChild( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->child[0] = (short)val[0]; - ptr->child[1] = (short)val[1]; - ptr->child[2] = (short)val[2]; - ptr->child[3] = (short)val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - - -PyObject *Particle_getMat( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mat[0], ptr->mat[1], ptr->mat[2], - ptr->mat[3] ); -} - - -PyObject *Particle_setMat( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[4]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - val[3] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 3 ) ); - ptr->mat[0] = (short)val[0]; - ptr->mat[1] = (short)val[1]; - ptr->mat[2] = (short)val[2]; - ptr->mat[3] = (short)val[3]; - Py_INCREF( Py_None ); - return Py_None; -} - - -PyObject *Particle_getDefvec( BPy_Particle * self ) -{ - - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", - ptr->defvec[0], ptr->defvec[1], ptr->defvec[2] ); -} - - -PyObject *Particle_setDefvec( BPy_Particle * self, PyObject * args ) -{ - PartEff *ptr = ( PartEff * ) self->particle; - float val[3]; - if( PyTuple_Size( args ) == 1 ) - args = PyTuple_GetItem( args, 0 ); - val[0] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 0 ) ); - val[1] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 1 ) ); - val[2] = (float)PyFloat_AsDouble( PyTuple_GetItem( args, 2 ) ); - ptr->defvec[0] = val[0]; - ptr->defvec[1] = val[1]; - ptr->defvec[2] = val[2]; - Py_INCREF( Py_None ); - return Py_None; +static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ){ + Material *ma; + PyObject* mat = 0L; + ma = give_current_material(self->object,self->psys->part->omat); + if(!ma) + Py_RETURN_NONE; + + mat = Material_CreatePyObject(ma); + return mat; } /*****************************************************************************/ -/* Function: ParticleDeAlloc */ -/* Description: This is a callback function for the BPy_Particle type. It is */ -/* the destructor function. */ +/* Function: Set/Get Seed */ /*****************************************************************************/ -void ParticleDeAlloc( BPy_Particle * self ) + +static int Part_setSeed( BPy_PartSys * self, PyObject * args ) { - PartEff *ptr = ( PartEff * ) self; - PyObject_DEL( ptr ); + return EXPP_setIValueRange( args, &self->psys->seed, + 0, 255, 'i' ); } -/*****************************************************************************/ -/* Function: ParticleGetAttr */ -/* Description: This is a callback function for the BPy_Particle type. It is */ -/* the function that accesses BPy_Particle "member variables" */ -/* and methods. */ -/*****************************************************************************/ - - -PyObject *ParticleGetAttr( BPy_Particle * self, char *name ) +static PyObject *Part_getSeed( BPy_PartSys * self ) { - - if( strcmp( name, "seed" ) == 0 ) - return Particle_getSeed( self ); - else if( strcmp( name, "nabla" ) == 0 ) - return Particle_getNabla( self ); - else if( strcmp( name, "sta" ) == 0 ) - return Particle_getSta( self ); - else if( strcmp( name, "end" ) == 0 ) - return Particle_getEnd( self ); - else if( strcmp( name, "lifetime" ) == 0 ) - return Particle_getLifetime( self ); - else if( strcmp( name, "normfac" ) == 0 ) - return Particle_getNormfac( self ); - else if( strcmp( name, "obfac" ) == 0 ) - return Particle_getObfac( self ); - else if( strcmp( name, "randfac" ) == 0 ) - return Particle_getRandfac( self ); - else if( strcmp( name, "texfac" ) == 0 ) - return Particle_getTexfac( self ); - else if( strcmp( name, "randlife" ) == 0 ) - return Particle_getRandlife( self ); - else if( strcmp( name, "vectsize" ) == 0 ) - return Particle_getVectsize( self ); - else if( strcmp( name, "totpart" ) == 0 ) - return Particle_getTotpart( self ); - else if( strcmp( name, "force" ) == 0 ) - return Particle_getForce( self ); - else if( strcmp( name, "mult" ) == 0 ) - return Particle_getMult( self ); - else if( strcmp( name, "life" ) == 0 ) - return Particle_getLife( self ); - else if( strcmp( name, "child" ) == 0 ) - return Particle_getChild( self ); - else if( strcmp( name, "mat" ) == 0 ) - return Particle_getMat( self ); - else if( strcmp( name, "defvec" ) == 0 ) - return Particle_getDefvec( self ); - - - return Py_FindMethod( BPy_Particle_methods, ( PyObject * ) self, - name ); + return PyInt_FromLong( (long)( self->psys->seed ) ); } -/*****************************************************************************/ -/* Function: ParticleSetAttr */ -/* Description: This is a callback function for the BPy_Particle type. */ -/* It is the function that sets Particle Data attributes */ -/* (member vars) */ -/*****************************************************************************/ -int ParticleSetAttr( BPy_Particle * self, char *name, PyObject * value ) +static int Part_setType( BPy_PartSys * self, PyObject * args ) { + int res = EXPP_setIValueRange( args, &self->psys->part->type, + 0, 2, 'h' ); - PyObject *valtuple; - PyObject *error = NULL; + psys_flush_settings( self->psys->part, PSYS_TYPE, 1 ); - valtuple = Py_BuildValue( "(N)", value ); + return res; +} - if( !valtuple ) - return EXPP_ReturnIntError( PyExc_MemoryError, - "ParticleSetAttr: couldn't create PyTuple" ); +static PyObject *Part_getType( BPy_PartSys * self ) +{ + return PyInt_FromLong( (short)( self->psys->part->type ) ); +} - if( strcmp( name, "seed" ) == 0 ) - error = Particle_setSeed( self, valtuple ); - else if( strcmp( name, "nabla" ) == 0 ) - error = Particle_setNabla( self, valtuple ); - else if( strcmp( name, "sta" ) == 0 ) - error = Particle_setSta( self, valtuple ); - else if( strcmp( name, "end" ) == 0 ) - error = Particle_setEnd( self, valtuple ); - else if( strcmp( name, "lifetime" ) == 0 ) - error = Particle_setLifetime( self, valtuple ); - else if( strcmp( name, "normfac" ) == 0 ) - error = Particle_setNormfac( self, valtuple ); - else if( strcmp( name, "obfac" ) == 0 ) - error = Particle_setObfac( self, valtuple ); - else if( strcmp( name, "randfac" ) == 0 ) - error = Particle_setRandfac( self, valtuple ); - else if( strcmp( name, "texfac" ) == 0 ) - error = Particle_setTexfac( self, valtuple ); - else if( strcmp( name, "randlife" ) == 0 ) - error = Particle_setRandlife( self, valtuple ); - else if( strcmp( name, "nabla" ) == 0 ) - error = Particle_setNabla( self, valtuple ); - else if( strcmp( name, "vectsize" ) == 0 ) - error = Particle_setVectsize( self, valtuple ); - else if( strcmp( name, "totpart" ) == 0 ) - error = Particle_setTotpart( self, valtuple ); - else if( strcmp( name, "seed" ) == 0 ) - error = Particle_setSeed( self, valtuple ); - else if( strcmp( name, "force" ) == 0 ) - error = Particle_setForce( self, valtuple ); - else if( strcmp( name, "mult" ) == 0 ) - error = Particle_setMult( self, valtuple ); - else if( strcmp( name, "life" ) == 0 ) - error = Particle_setLife( self, valtuple ); - else if( strcmp( name, "child" ) == 0 ) - error = Particle_setChild( self, valtuple ); - else if( strcmp( name, "mat" ) == 0 ) - error = Particle_setMat( self, valtuple ); - else if( strcmp( name, "defvec" ) == 0 ) - error = Particle_setDefvec( self, valtuple ); +static int Part_setResol( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->grid_res, + 0, 100, 'i' ); - else { - Py_DECREF( valtuple ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); - if( ( strcmp( name, "Types" ) == 0 ) || - ( strcmp( name, "Modes" ) == 0 ) ) - return ( EXPP_ReturnIntError( PyExc_AttributeError, - "constant dictionary -- cannot be changed" ) ); + return res; +} - else - return ( EXPP_ReturnIntError( PyExc_KeyError, - "attribute not found" ) ); +static PyObject *Part_getResol( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((int)( self->psys->part->grid_res )) ); +} + +static int Part_setStart( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->sta, + 0.0f, 100000.0f ); + + psys_flush_settings(self->psys->part,PSYS_INIT,1); + + return res; +} + +static PyObject *Part_getStart( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( (float)( self->psys->part->sta ) ); +} + +static int Part_setEnd( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->end, + 0.0f, 100000.0f ); + + psys_flush_settings(self->psys->part,PSYS_INIT,1); + + return res; +} + +static PyObject *Part_getEnd( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( (long)( self->psys->part->end ) ); +} + +static int Part_setEditable( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - Py_DECREF(valtuple); - if( error != Py_None ) - return -1; + number = PyInt_AS_LONG( args ); + + if(!number){ + if(self->psys->edit) + PE_free_particle_edit(self->psys); + + self->psys->flag &= ~PSYS_EDITED; + self->psys->recalc |= PSYS_RECALC_HAIR; + + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); + } + else + { + self->psys->flag |= PSYS_EDITED; + if(G.f & G_PARTICLEEDIT) + PE_create_particle_edit(self->object, self->psys); + } - Py_DECREF( Py_None ); return 0; } -/*****************************************************************************/ -/* Function: ParticlePrint */ -/* Description: This is a callback function for the BPy_Particle type. It */ -/* particles a meaninful string to 'print' particle objects. */ -/*****************************************************************************/ -/* -int ParticlePrint(BPy_Particle *self, FILE *fp, int flags) -{ - printf("Hi, I'm a particle!"); - return 0; -} -*/ -/*****************************************************************************/ -/* Function: ParticleRepr */ -/* Description: This is a callback function for the BPy_Particle type. It */ -/* particles a meaninful string to represent particle objects. */ -/*****************************************************************************/ -PyObject *ParticleRepr( void ) +static PyObject *Part_getEditable( BPy_PartSys * self ) { - return PyString_FromString( "Particle" ); + return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0 ); } -PyObject *ParticleCreatePyObject( struct Effect * particle ) +static int Part_setAmount( BPy_PartSys * self, PyObject * args ) { - BPy_Particle *blen_object; + int res = EXPP_setIValueRange( args, &self->psys->part->totpart, + 0, 100000, 'i' ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); - blen_object = - ( BPy_Particle * ) PyObject_NEW( BPy_Particle, - &Particle_Type ); + return res; +} - if( blen_object == NULL ) { - return ( NULL ); +static PyObject *Part_getAmount( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((int)( self->psys->part->totpart )) ); +} + +static int Part_setMultiReact( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); } - blen_object->particle = particle; - return ( ( PyObject * ) blen_object ); + number = PyInt_AS_LONG( args ); + + + if (number){ + self->psys->part->flag |= PART_REACT_MULTIPLE; + }else{ + self->psys->part->flag &= ~PART_REACT_MULTIPLE; + } + + Particle_Recalc(self,1); + + return 0; } -int ParticleCheckPyObject( PyObject * py_obj ) +static PyObject *Part_getMultiReact( BPy_PartSys * self ) { - return ( py_obj->ob_type == &Particle_Type ); + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 ); } - -struct Particle *ParticleFromPyObject( PyObject * py_obj ) +static int Part_setReactShape( BPy_PartSys * self, PyObject * args ) { - BPy_Particle *blen_obj; + int res = EXPP_setFloatRange( args, &self->psys->part->reactshape, + 0.0f, 10.0f ); - blen_obj = ( BPy_Particle * ) py_obj; - return ( ( struct Particle * ) blen_obj->particle ); + Particle_Recalc(self,1); + return res; +} + +static PyObject *Part_getReactShape( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->reactshape )) ); +} + +static int Part_setSegments( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->hair_step, + 2, 50, 'h' ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getSegments( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->hair_step )) ); +} + +static int Part_setLife( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->lifetime, + 1.0f, MAXFRAMEF ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getLife( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->lifetime )) ); +} + +static int Part_setRandLife( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->randlife, + 0.0f, 2.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getRandLife( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) ); +} + +static int Part_set2d( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_BOIDS_2D; + }else{ + self->psys->part->flag &= ~PART_BOIDS_2D; + } + + Particle_Recalc(self,1); + + return 0; +} + +static PyObject *Part_get2d( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 ); +} + +static int Part_setMaxVel( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_vel, + 0.0f, 200.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxVel( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_vel )) ); +} + +static int Part_setAvVel( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->average_vel, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getAvVel( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) ); +} + +static int Part_setLatAcc( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_lat_acc, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getLatAcc( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_lat_acc )) ); +} + +static int Part_setMaxTan( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->max_tan_acc, + 0.0f, 1.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxTan( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) ); +} + +static int Part_setGroundZ( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->groundz, + -100.0f, 100.0f ); + + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getGroundZ( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) ); +} + +static int Part_setOb( BPy_PartSys * self, PyObject * args ) +{ + Object *obj; + if( !BPy_Object_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected object argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + obj = Object_FromPyObject(args); + + self->psys->keyed_ob = obj; + + return 0; +} + +static PyObject *Part_getOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->keyed_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + +static int Part_setRandEmission( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_TRAND; + }else{ + self->psys->part->flag &= ~PART_TRAND; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getRandEmission( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 ); +} + +static int Part_setParticleDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + char errstr[128]; + + if( !PyInt_Check( args ) ) { + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number < 0 || number > 3){ + sprintf ( errstr, "expected int argument between 0 - 3" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + self->psys->part->from = number; + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getParticleDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->from ) ); +} + +static int Part_setEvenDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_EDISTR; + }else{ + self->psys->part->flag &= ~PART_EDISTR; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getEvenDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_EDISTR )) > 0 ); +} + +static int Part_setDist( BPy_PartSys * self, PyObject * args ) +{ + int number; + char errstr[128]; + + if( !PyInt_Check( args ) ) { + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number < 0 || number > 2){ + sprintf ( errstr, "expected int argument between 0 - 2" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + self->psys->part->distr = number; + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getDist( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->distr ) ); +} + +static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->jitfac, + 0.0f, 2.0f ); + + Particle_RecalcPsys_distr(self,1); + + return res; +} + +static PyObject *Part_getJitterAmount( BPy_PartSys * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->jitfac )) ); +} + + + +static int Part_setPF( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->userjit, + 0, 1000, 'i' ); + + Particle_RecalcPsys_distr(self,1); + + return res; +} + +static PyObject *Part_getPF( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->userjit )) ); +} + +static int Part_setInvert( BPy_PartSys * self, PyObject * args ) +{ + int number; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->flag |= PART_GRID_INVERT; + }else{ + self->psys->part->flag &= ~PART_GRID_INVERT; + } + + Particle_RecalcPsys_distr(self,1); + + return 0; +} + +static PyObject *Part_getInvert( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_GRID_INVERT )) > 0 ); +} + +static int Part_setTargetOb( BPy_PartSys * self, PyObject * args ) +{ + Object *obj; + if( !BPy_Object_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected object argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + obj = Object_FromPyObject(args); + + self->psys->target_ob = obj; + + return 0; +} + +static PyObject *Part_getTargetOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->target_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + + + +PyObject *Part_getDupOb( BPy_PartSys * self ) +{ + Object * obj; + obj = self->psys->part->dup_ob; + if (!obj) + Py_RETURN_NONE; + + return Object_CreatePyObject( obj ); +} + +static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){ + int tottpsys; + int res; + Object *tob=0; + ParticleSystem *psys = self->psys; + Object *ob; + + ob = self->object; + + if(psys->target_ob) + tob=psys->target_ob; + else + tob=ob; + + tottpsys = BLI_countlist(&tob->particlesystem); + + res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' ); + + if((psys=psys_get_current(ob))){ + if(psys->keyed_ob==ob || psys->target_ob==ob){ + if(psys->keyed_ob==ob) + psys->keyed_ob=NULL; + else + psys->target_ob=NULL; + } + else{ + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } + } + + return res; +} + +static PyObject *Part_getTargetPsys( BPy_PartSys * self ){ + return PyInt_FromLong( (short)( self->psys->target_psys ) ); +} + +static int Part_setRenderObject( BPy_PartSys * self, PyObject * args ) +{ + int number,nr; + ParticleSystem *psys = 0L; + + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } + + number = PyInt_AS_LONG( args ); + + if (number){ + self->psys->part->draw |= PART_DRAW_EMITTER; + }else{ + self->psys->part->draw &= ~PART_DRAW_EMITTER; + } + + /* check need for dupliobjects */ + nr=0; + for(psys=self->object->particlesystem.first; psys; psys=psys->next){ + if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR)) + nr++; + } + if(nr) + self->object->transflag |= OB_DUPLIPARTS; + else + self->object->transflag &= ~OB_DUPLIPARTS; + + return 0; +} + +static PyObject *Part_getRenderObject( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 0 ); +} + +static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->disp, + 0, 100, 'i' ); + + Particle_Recalc(self,0); + + + return res; +} + +static PyObject *Part_getParticleDisp( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->disp )) ); +} + +static int Part_setStep( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->draw_step, + 0, 7, 'i' ); + + Particle_Recalc(self,1); + + + return res; +} + +static PyObject *Part_getStep( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->draw_step )) ); +} + +static int Part_setRenderStep( BPy_PartSys * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->ren_step, + 0, 7, 'i' ); + + /*Particle_Recalc(self,1);*/ + + + return res; +} + +static PyObject *Part_getRenderStep( BPy_PartSys * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->ren_step )) ); +} + +static PyObject *Part_getDrawAs( BPy_PartSys * self ) +{ + return PyInt_FromLong( (long)( self->psys->part->draw_as ) ); } diff --git a/source/blender/python/api2_2x/Particle.h b/source/blender/python/api2_2x/Particle.h index 13e6fadaaa0..416e3a99bea 100644 --- a/source/blender/python/api2_2x/Particle.h +++ b/source/blender/python/api2_2x/Particle.h @@ -22,43 +22,32 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot + * Contributor(s): Jacques Guignot, Cedric Paille * * ***** END GPL LICENSE BLOCK ***** - */ +*/ -#ifndef EXPP_PARTICLE_H -#define EXPP_PARTICLE_H +#ifndef EXPP_PARTICLESYS_H +#define EXPP_PARTICLESYS_H #include -#include "DNA_effect_types.h" +#include "DNA_particle_types.h" +#include "DNA_object_types.h" -extern PyTypeObject Particle_Type; +extern PyTypeObject ParticleSys_Type; -#define BPy_Particle_Check(v) ((v)->ob_type==&Particle_Type) +#define BPy_ParticleSys_Check(v) \ + ((v)->ob_type == &ParticleSys_Type) /* for type checking */ -/* Python BPy_Particle structure definition */ +/* Python BPy_Effect structure definition */ typedef struct { PyObject_HEAD /* required py macro */ - Effect * particle; -} BPy_Particle; + ParticleSystem *psys; + Object *object; /* fixeme: if this points back to the parent object,it is wrong */ +} BPy_PartSys; -#include "Effect.h" - -/*****************************************************************************/ -/* Python Particle_Type callback function prototypes: */ -/*****************************************************************************/ -#if 0 -void ParticleDeAlloc( BPy_Particle * msh ); -//int ParticlePrint (BPy_Particle *msh, FILE *fp, int flags); -int ParticleSetAttr( BPy_Particle * msh, char *name, PyObject * v ); -PyObject *ParticleGetAttr( BPy_Particle * msh, char *name ); -PyObject *ParticleRepr( void ); -PyObject *ParticleCreatePyObject( struct Effect *particle ); -int ParticleCheckPyObject( PyObject * py_obj ); -struct Particle *ParticleFromPyObject( PyObject * py_obj ); -#endif +PyObject *ParticleSys_Init( void ); +PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob ); - -#endif /* EXPP_PARTICLE_H */ +#endif /* EXPP_EFFECT_H */ diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py index a630c47229e..ec1d42bce43 100644 --- a/source/blender/python/api2_2x/doc/API_intro.py +++ b/source/blender/python/api2_2x/doc/API_intro.py @@ -29,7 +29,7 @@ The Blender Python API Reference - L{Group} (*) - L{Image} (*) - L{Ipo} (*) - - L{IpoCurve} (*) + - L{IpoCurve} (*) - L{Key} (*) - L{Lamp} - L{Lattice} (*) @@ -46,6 +46,7 @@ The Blender Python API Reference - L{Pose} (*) - L{Constraint} (*) - L{ActionStrips} (*) + - L{Particle} - L{Registry} - L{Scene} (*) - L{Radio} diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py index a3238f2615e..521be3b0cea 100644 --- a/source/blender/python/api2_2x/doc/Object.py +++ b/source/blender/python/api2_2x/doc/Object.py @@ -641,7 +641,16 @@ class Object: @ivar upAxis: Up axis. Return string 'Y' | 'Y' | 'Z' (readonly) @type upAxis: string """ - + def getParticleSystems(): + """ + Return a list of particle systems linked to this object (see Blender.Particle). + """ + + def newParticleSystem(): + """ + Link a new particle system (see Blender.Particle). + """ + def buildParts(): """ Recomputes the particle system. This method only applies to an Object of diff --git a/source/blender/python/api2_2x/doc/Particle.py b/source/blender/python/api2_2x/doc/Particle.py new file mode 100644 index 00000000000..192ecd5355b --- /dev/null +++ b/source/blender/python/api2_2x/doc/Particle.py @@ -0,0 +1,367 @@ +# Blender.Object module and the Object PyType object + +""" +The Blender.Particle submodule + + +Particle +======== + +This module provides access to the B{Particle} in Blender. + +@type TYPE: readonly dictionary +@var TYPE: Constant dict used for with L{Particle.TYPE} + - HAIR: set particle system to hair mode. + - REACTOR: set particle system to reactor mode. + - EMITTER: set particle system to emitter mode. +@type DISTRIBUTION: readonly dictionary +@var DISTRIBUTION: Constant dict used for with L{Particle.DISTRIBUTION} + - GRID: set grid distribution. + - RANDOM: set random distribution. + - JITTERED: set jittered distribution. +@type EMITFROM: readonly dictionary +@var EMITFROM: Constant dict used for with L{Particle.EMITFROM} + - VERTS: set particles emit from vertices + - FACES: set particles emit from faces + - VOLUME: set particles emit from volume + - PARTICLE: set particles emit from particles +@type REACTON: readonly dictionary +@var REACTON: Constant dict used for with L{Particle.REACTON} + - NEAR: react on near + - COLLISION: react on collision + - DEATH: react on death +@type DRAWAS: readonly dictionary +@var DRAWAS: Constant dict used for with L{Particle.DRAWAS} + - NONE: Don't draw + - POINT: Draw as point + - CIRCLE: Draw as circles + - CROSS: Draw as crosses + - AXIS: Draw as axis + - LINE: Draw as lines + - PATH: Draw pathes + - OBJECT: Draw object + - GROUP: Draw goup + - BILLBOARD: Draw as billboard +""" + +class Particle: + """ + The Particle object + =================== + This object gives access to paticles data. + + @ivar seed: Set an offset in the random table. + @type seed: int + @ivar type: Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] ). + @type type: int + @ivar resolutionGrid: The resolution of the particle grid. + @type resolutionGrid: int + @ivar startFrame: Frame # to start emitting particles. + @type startFrame: float + @ivar endFrame: Frame # to stop emitting particles. + @type endFrame: float + @ivar editable: Finalize hair to enable editing in particle mode. + @type editable: int + @ivar amount: The total number of particles. + @type amount: int + @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ). + @type multireact: int + @ivar reactshape: Power of reaction strength dependence on distance to target. + @type reactshape: float + @ivar hairSegments: Amount of hair segments. + @type hairSegments: int + @ivar lifetime: Specify the life span of the particles. + @type lifetime: float + @ivar randlife: Give the particle life a random variation. + @type randlife: float + @ivar randemission: Give the particle life a random variation + @type randemission: int + @ivar particleDistribution: Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] ) + @type particleDistribution: int + @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths. + @type evenDistribution: int + @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ). + @type distribution: int + @ivar jitterAmount: Amount of jitter applied to the sampling. + @type jitterAmount: float + @ivar pf: Emission locations / face (0 = automatic). + @type pf:int + @ivar invert: Invert what is considered object and what is not. + @type invert: int + @ivar targetObject: The object that has the target particle system (empty if same object). + @type targetObject: Blender object + @ivar targetpsys: The target particle system number in the object. + @type targetpsys: int + @ivar 2d: Constrain boids to a surface. + @type 2d: float + @ivar maxvel: Maximum velocity. + @type maxvel: float + @ivar avvel: The usual speed % of max velocity. + @type avvel: float + @ivar latacc: Lateral acceleration % of max velocity + @type latacc: float + @ivar tanacc: Tangential acceleration % of max velocity + @type tanacc: float + @ivar groundz: Default Z value. + @type groundz: float + @ivar object: Constrain boids to object's surface. + @type object: Blender Object + @ivar renderEmitter: Render emitter object. + @type renderEmitter: int + @ivar displayPercentage: Particle display percentage. + @type displayPercentage: int + @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode. + @type hairDisplayStep: int + @ivar hairRenderStep: How many steps paths are rendered with (power of 2) in render mode." + @type hairRenderStep: int + @ivar duplicateObject: Get the duplicate object. + @type duplicateObject: Blender Object + @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). + @type drawAs: int + """ + + def freeEdit(): + """ + Free edit mode. + @return: None + """ + + def getLoc(all=0,id=0): + """ + Get the particles locations. + A list of tuple is returned in particle mode. + A list of list of tuple is returned in hair mode. + The tuple is a vector list of 3 or 4 floats in world space (x,y,z, optionnaly the particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None). + @type id: int + @param id: add the particle id in the end of the vector tuple + @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors + @return: list of vectors or list of list of vectors (hair mode) + """ + def getRot(all=0,id=0): + """ + Get the particles rotations as quaternion. + A list of tuple is returned in particle mode. + The tuple is a vector list of 4 or 5 floats (x,y,z,w, optionnaly the id of the particle). + + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of tuple of 4 or 5 elements (if id is not zero) + @return: list of 4-tuples + """ + + def getMat(): + """ + Get the particles material. + @rtype: Blender Material + @return: The marterial assigned to particles + """ + + def getSize(all=0,id=0): + """ + Get the particles size. + A list of float or list of tuple (particle's size,particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """ + + def getAge(all=0,id=0): + """ + Get the particles age. + A list of float or list of tuple (particle's age,particle's id). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """ +# Blender.Object module and the Object PyType object + +""" +The Blender.Particle submodule + + +Particle +======== + +This module provides access to the B{Particle} in Blender. + +@type TYPE: readonly dictionary +@var TYPE: Constant dict used for with L{Particle.TYPE} + - HAIR: set particle system to hair mode. + - REACTOR: set particle system to reactor mode. + - EMITTER: set particle system to emitter mode. +@type DISTRIBUTION: readonly dictionary +@var DISTRIBUTION: Constant dict used for with L{Particle.DISTRIBUTION} + - GRID: set grid distribution. + - RANDOM: set random distribution. + - JITTERED: set jittered distribution. +@type EMITFROM: readonly dictionary +@var EMITFROM: Constant dict used for with L{Particle.EMITFROM} + - VERTS: set particles emit from vertices + - FACES: set particles emit from faces + - VOLUME: set particles emit from volume + - PARTICLE: set particles emit from particles +@type REACTON: readonly dictionary +@var REACTON: Constant dict used for with L{Particle.REACTON} + - NEAR: react on near + - COLLISION: react on collision + - DEATH: react on death +@type DRAWAS: readonly dictionary +@var DRAWAS: Constant dict used for with L{Particle.DRAWAS} + - NONE: Don't draw + - POINT: Draw as point + - CIRCLE: Draw as circles + - CROSS: Draw as crosses + - AXIS: Draw as axis + - LINE: Draw as lines + - PATH: Draw pathes + - OBJECT: Draw object + - GROUP: Draw goup + - BILLBOARD: Draw as billboard +""" + +def Get(name): + """ + Get the particle system of the object "name". + @type name: string + @return: The particle system of the object. + """ +def New(name): + """ + Assign a new particle system to the object "name". + @type name: string + @return: The newly created particle system. + """ + +class Particle: + """ + The Particle object + =================== + This object gives access to paticles data. + + @ivar seed: Set an offset in the random table. + @type seed: int + @ivar type: Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] ). + @type type: int + @ivar resolutionGrid: The resolution of the particle grid. + @type resolutionGrid: int + @ivar startFrame: Frame # to start emitting particles. + @type startFrame: float + @ivar endFrame: Frame # to stop emitting particles. + @type endFrame: float + @ivar editable: Finalize hair to enable editing in particle mode. + @type editable: int + @ivar amount: The total number of particles. + @type amount: int + @ivar multireact: React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] ). + @type multireact: int + @ivar reactshape: Power of reaction strength dependence on distance to target. + @type reactshape: float + @ivar hairSegments: Amount of hair segments. + @type hairSegments: int + @ivar lifetime: Specify the life span of the particles. + @type lifetime: float + @ivar randlife: Give the particle life a random variation. + @type randlife: float + @ivar randemission: Give the particle life a random variation + @type randemission: int + @ivar particleDistribution: Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] ) + @type particleDistribution: int + @ivar evenDistribution: Use even distribution from faces based on face areas or edge lengths. + @type evenDistribution: int + @ivar distribution: How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] ). + @type distribution: int + @ivar jitterAmount: Amount of jitter applied to the sampling. + @type jitterAmount: float + @ivar pf: Emission locations / face (0 = automatic). + @type pf:int + @ivar invert: Invert what is considered object and what is not. + @type invert: int + @ivar targetObject: The object that has the target particle system (empty if same object). + @type targetObject: Blender object + @ivar targetpsys: The target particle system number in the object. + @type targetpsys: int + @ivar 2d: Constrain boids to a surface. + @type 2d: float + @ivar maxvel: Maximum velocity. + @type maxvel: float + @ivar avvel: The usual speed % of max velocity. + @type avvel: float + @ivar latacc: Lateral acceleration % of max velocity + @type latacc: float + @ivar tanacc: Tangential acceleration % of max velocity + @type tanacc: float + @ivar groundz: Default Z value. + @type groundz: float + @ivar object: Constrain boids to object's surface. + @type object: Blender Object + @ivar renderEmitter: Render emitter object. + @type renderEmitter: int + @ivar displayPercentage: Particle display percentage. + @type displayPercentage: int + @ivar hairDisplayStep: How many steps paths are drawn with (power of 2) in visu mode. + @type hairDisplayStep: int + @ivar hairRenderStep: How many steps paths are rendered with (power of 2) in render mode." + @type hairRenderStep: int + @ivar duplicateObject: Get the duplicate object. + @type duplicateObject: Blender Object + @ivar drawAs: Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ]). + @type drawAs: int + """ + def freeEdit(): + """ + Free edit mode. + @return: None + """ + + def getLoc(all=0,id=0): + """ + Get the particles locations. + A list of tuple is returned in particle mode. + A list of list of tuple is returned in hair mode. + The tuple is a vector list of 3 floats in world space. + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died)particles exported as None). + @type id: int + @param id: add the particle id in the end of the vector tuple + @rtype: list of vectors (tuple of 3 floats and optionnaly the id) or list of list of vectors + @return: list of vectors or list of list of vectors (hair mode) + """ + def getRot(all=0,id=0): + """ + Get the particles rotations as quaternion. + A list of tuple is returned in particle mode. + The tuple is a vector list of 4 floats (quaternion). + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of tuple of 4 or 5 elements (if id is not zero) + @return: list of 4-tuples + """ + def getMat(): + """ + Get the particles material. + @rtype: Blender Material + @return: The marterial assigned to particles + """ + def getSize(all=0,id=0): + """ + Get the particles size. + A list of float. + @type all: int + @param all: if not 0 export all particles (uninitialized (unborn or died) particles exported as None). + @type id: int + @param id: add the particle id in the return tuple + @rtype: list of floats + @return: list of floats or list of tuples if id is not zero (size,id). + """