Index: Particle.c =================================================================== --- Particle.c (revision 14348) +++ Particle.c (working copy) @@ -1,5 +1,5 @@ /* - * $Id: Particle.c 10279 2007-03-16 11:38:02Z campbellbarton $ + * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -25,250 +25,503 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot, Jean-Michel Soler + * Contributor(s): Jacques Guignot, Jean-Michel Soler, Ken Hughes, Cedric Paille * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ - -#include "Particle.h" /*This must come first */ - -#include "DNA_object_types.h" -#include "BKE_effect.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_main.h" -#include "BKE_object.h" +#include "BKE_depsgraph.h" +#include "BKE_modifier.h" +#include "BKE_material.h" +#include "BKE_utildefines.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 "gen_utils.h" +#include "mydevice.h" +#include "Object.h" +#include "Material.h" + +/* 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_ProtectCache( BPy_PartSYS * self, PyObject * args ); +static PyObject *Part_UnprotectCache( 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_setPaticleDist( BPy_PartSYS * self, PyObject * args ); +static PyObject *Part_getPaticleDist( 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_setEnable( BPy_PartSYS * self, PyObject * args ); +static PyObject *Part_getEnable( 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 ); + /*****************************************************************************/ -/* Python API function prototypes for the Particle module. */ +/* Python Effect_Type callback function prototypes: */ /*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ); -PyObject *M_Particle_Get( PyObject * self, PyObject * args ); +static PyObject *ParticleSYS_repr( void ); /*****************************************************************************/ -/* Python BPy_Particle methods declarations: */ +/* The following string definitions are used for documentation strings. */ +/* In Python these will be written to the console when doing a */ +/* Blender.Particle.__doc__ */ /*****************************************************************************/ -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 ); +static char M_ParticleSYS_doc[] = "The Blender Effect module\n\n\ +This module provides access to **Object Data** in Blender.\n\ +Functions :\n\ + 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 Particle_Type callback function prototypes: */ +/* Python BPy_ParticleSYS methods table: */ /*****************************************************************************/ -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 ); - +static PyMethodDef BPy_ParticleSYS_methods[] = { + {"freeEdit", ( PyCFunction ) Part_freeEdit, + METH_NOARGS, "() - Free from edit mode"}, + {"protectCache", ( PyCFunction ) Part_ProtectCache, + METH_NOARGS, "() - Protect the cache"}, + {"unprotectCache", ( PyCFunction ) Part_UnprotectCache, + METH_NOARGS, "() - Unprotect the cache"}, + {"getLoc", ( PyCFunction ) Part_GetLoc, + METH_NOARGS, "() - Get particles location"}, + {"getRot", ( PyCFunction ) Part_GetRot, + METH_NOARGS, "() - Get particles rotations (list of 4 floats quaternion)"}, + {"getMat", ( PyCFunction ) Part_GetMat, + METH_NOARGS, "() - Get particles material"}, + {"getSize", ( PyCFunction ) Part_GetSize, + METH_NOARGS, "() - Get particles size in a list"}, + {NULL, NULL, 0, NULL} +}; + /*****************************************************************************/ -/* Python BPy_Particle methods table: */ +/* Python BPy_ParticleSYS attributes get/set structure: */ /*****************************************************************************/ -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 "}, - - +static PyGetSetDef BPy_ParticleSYS_getseters[] = { +/* Extras */ + {"extra_seed", + (getter)Part_getSeed, (setter)Part_setSeed, + "Set an offset in the random table", + NULL}, + /* basics */ + {"basic_type", + (getter)Part_getType, (setter)Part_setType, + "Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] )", + NULL}, + {"basic_resolgrid", + (getter)Part_getType, (setter)Part_setType, + "The resolution of the particle grid", + NULL}, + {"basic_startframe", + (getter)Part_getStart, (setter)Part_setStart, + "Frame # to start emitting particles", + NULL}, + {"basic_endframe", + (getter)Part_getEnd, (setter)Part_setEnd, + "Frame # to stop emitting particles", + NULL}, + {"basic_editable", + (getter)Part_getEditable, (setter)Part_setEditable, + "Finalize hair to enable editing in particle mode", + NULL}, + {"basic_amount", + (getter)Part_getAmount, (setter)Part_setAmount, + "The total number of particles", + NULL}, + {"basic_multireact", + (getter)Part_getMultiReact, (setter)Part_setMultiReact, + "React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] )", + NULL}, + {"basic_reactshape", + (getter)Part_getReactShape, (setter)Part_setReactShape, + "Power of reaction strength dependence on distance to target", + NULL}, + {"basic_segments", + (getter)Part_getSegments, (setter)Part_setSegments, + "Amount of hair segments", + NULL}, + {"basic_lifetime", + (getter)Part_getLife, (setter)Part_setLife, + "Specify the life span of the particles", + NULL}, + {"basic_randlife", + (getter)Part_getRandLife, (setter)Part_setRandLife, + "Give the particle life a random variation", + NULL}, + {"basic_randemission", + (getter)Part_getRandEmission, (setter)Part_setRandEmission, + "Give the particle life a random variation", + NULL}, + {"basic_particledist", + (getter)Part_getPaticleDist, (setter)Part_setPaticleDist, + "Where to emit particles from Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )", + NULL}, + {"basic_evendist", + (getter)Part_getEvenDist, (setter)Part_setEvenDist, + "Use even distribution from faces based on face areas or edge lengths", + NULL}, + {"basic_distribution", + (getter)Part_getDist, (setter)Part_setDist, + "How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] )", + NULL}, + {"basic_jitteramount", + (getter)Part_getJitterAmount, (setter)Part_setJitterAmount, + "Amount of jitter applied to the sampling", + NULL}, + {"basic_pf", + (getter)Part_getPF, (setter)Part_setPF, + "Emission locations / face (0 = automatic)", + NULL}, + {"basic_invert", + (getter)Part_getInvert, (setter)Part_setInvert, + "Invert what is considered object and what is not.", + NULL}, + {"basic_targetobject", + (getter)Part_getTargetOb, (setter)Part_setTargetOb, + "The object that has the target particle system (empty if same object)", + NULL}, + {"basic_targetpsys", + (getter)Part_getTargetPsys, (setter)Part_setTargetPsys, + "The target particle system number in the object", + NULL}, + {"basic_enable", + (getter)Part_getEnable, (setter)Part_setEnable, + "Sets particle system to be calculated and shown", + NULL}, +/* Physics */ + {"phy_2d", + (getter)Part_get2d, (setter)Part_set2d, + "Constrain boids to a surface", + NULL}, + {"phy_maxvel", + (getter)Part_getMaxVel, (setter)Part_setMaxVel, + "Maximum velocity", + NULL}, + {"phy_avvel", + (getter)Part_getAvVel, (setter)Part_setAvVel, + "The usual speed % of max velocity", + NULL}, + {"phy_latacc", + (getter)Part_getLatAcc, (setter)Part_setLatAcc, + "Lateral acceleration % of max velocity", + NULL}, + {"phy_tanacc", + (getter)Part_getMaxTan, (setter)Part_setMaxTan, + "Tangential acceleration % of max velocity", + NULL}, + {"phy_groundz", + (getter)Part_getGroundZ, (setter)Part_setGroundZ, + "Default Z value", + NULL}, + {"phy_object", + (getter)Part_getOb, (setter)Part_setOb, + "Constrain boids to object's surface", + NULL}, +/* Visualisation */ + {"visu_emitter", + (getter)Part_getRenderObject, (setter)Part_setRenderObject, + "Render emitter object", + NULL}, + {"visu_display", + (getter)Part_getParticleDisp, (setter)Part_setParticleDisp, + "Particle display percentage", + NULL}, + {"visu_step", + (getter)Part_getStep, (setter)Part_setStep, + "How many steps paths are drawn with (power of 2)", + NULL}, + {"visu_renderstep", + (getter)Part_getRenderStep, (setter)Part_setRenderStep, + "How many steps paths are rendered with (power of 2)", + NULL}, + {"visu_dupob", + (getter)Part_getDupOb, NULL, + "Get the duplicate ob", + NULL}, + {"visu_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: */ +/*****************************************************************************/ +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} }; -/**************** prototypes ********************/ -PyObject *Particle_Init( void ); - - /*****************************************************************************/ -/* Python Particle_Type structure definition: */ +/* 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 */ -PyTypeObject Particle_Type = { - PyObject_HEAD_INIT( NULL ) - 0, - "Particle", - sizeof( BPy_Particle ), - 0, + /* Methods to implement standard operations */ - ( 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, + 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 }; + /*****************************************************************************/ -/* The following string definitions are used for documentation strings. */ -/* In Python these will be written to the console when doing a */ -/* Blender.Particle.__doc__ */ +/* Function: PARTICLESYS_repr */ +/* Description: This is a callback function for the BPy_Effect type. It */ +/* builds a meaninful string to represent effcte objects. */ /*****************************************************************************/ -char M_Particle_doc[] = "The Blender Particle 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"; +static PyObject *ParticleSYS_repr( void ) +{ + return PyString_FromString( "ParticleSYS" ); +} /*****************************************************************************/ -/* Python method structure definition for Blender.Particle module: */ +/* Function : P_sys_FromPyObject */ /*****************************************************************************/ -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}, - {NULL, NULL, 0, NULL} -}; +struct ParticleSystem *P_sys_FromPyObject( BPy_PartSYS * py_obj ) +{ + BPy_PartSYS *blen_obj; + blen_obj = ( BPy_PartSYS * ) py_obj; + return ( blen_obj->psys ); +} + /*****************************************************************************/ -/* 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 : P_sysCreatePyObject */ /*****************************************************************************/ -PyObject *M_Particle_New( PyObject * self, PyObject * args ) +PyObject *P_sysCreatePyObject( ParticleSystem * psystem, Object *ob ) { - BPy_Effect *pyeffect; - Effect *bleffect = 0; + 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"); + 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); + + id->us++; + 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 P_sysCreatePyObject(rpsys,ob); +} + +PyObject *M_ParticleSYS_Get( PyObject * self, PyObject * args ){ + ParticleSystem *blparticlesys = 0; Object *ob; char *name = NULL; + PyObject *partsyslist,*current; if( !PyArg_ParseTuple( args, "s", &name ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -282,759 +535,1139 @@ return EXPP_ReturnPyObjError( PyExc_AttributeError, "object does not exist" ); - if( ob->type != OB_MESH ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "object is not a mesh" ); + blparticlesys = ob->particlesystem.first; - pyeffect = ( BPy_Effect * ) PyObject_NEW( BPy_Effect, &Effect_Type ); - if( !pyeffect ) - return EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create Effect Data object" ); + partsyslist = PyList_New( 0 ); - bleffect = add_effect( EFF_PARTICLE ); - if( !bleffect ) { - Py_DECREF( pyeffect ); - return EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't create Effect Data in Blender" ); + if (!blparticlesys) + return partsyslist; + + current = P_sysCreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); + + while(blparticlesys = blparticlesys->next){ + current = P_sysCreatePyObject( blparticlesys, ob ); + PyList_Append(partsyslist,current); } - pyeffect->effect = (PartEff *)bleffect; - BLI_addtail( &ob->effect, bleffect ); - - return ( PyObject * ) pyeffect; + return partsyslist; } + /*****************************************************************************/ -/* Function: M_Particle_Get */ -/* Python equivalent: Blender.Effect.Particle.Get */ +/* Function: ParticleSYS_Init */ /*****************************************************************************/ -PyObject *M_Particle_Get( PyObject * self, PyObject * args ) -{ - /*arguments : string object name - int : position of effect in the obj's effect list */ - char *name = 0; - Object *object_iter; - Effect *eff; - BPy_Particle *wanted_eff; - int num, i; - if( !PyArg_ParseTuple( args, "si", &name, &num ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected string int argument" ) ); +/* create the Blender.Particle.Type constant dict */ - object_iter = G.main->object.first; - if( !object_iter ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "Scene contains no object" ); +static PyObject *Particle_TypeDict( void ) +{ + PyObject *Types = PyConstant_New( ); - while( object_iter ) { - if( strcmp( name, object_iter->id.name + 2 ) ) { - object_iter = object_iter->id.next; - continue; - } + if( Types ) { + BPy_constant *c = ( BPy_constant * ) Types; - if( object_iter->effect.first != NULL ) { - eff = object_iter->effect.first; - for( i = 0; i < num; i++ ) { - if( eff->type != EFF_PARTICLE ) - continue; - eff = eff->next; - if( !eff ) - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "Object" ) ); - } - wanted_eff = - ( BPy_Particle * ) PyObject_NEW( BPy_Particle, - &Particle_Type ); - wanted_eff->particle = eff; - return ( PyObject * ) wanted_eff; - } - object_iter = object_iter->id.next; + PyConstant_Insert( c, "HAIR", + PyInt_FromLong( 2 ) ); + PyConstant_Insert( c, "REACTOR", + PyInt_FromLong( 1 ) ); + PyConstant_Insert( c, "EMITTER", + PyInt_FromLong( 0 ) ); } - Py_INCREF( Py_None ); - return Py_None; + return Types; } -/*****************************************************************************/ -/* Function: Particle_Init */ -/*****************************************************************************/ -PyObject *Particle_Init( void ) +/* create the Blender.Particle.Distribution constant dict */ + +static PyObject *Particle_DistrDict( void ) { - PyObject *submodule; - - if( PyType_Ready( &Particle_Type) < 0) - return NULL; - - submodule = - Py_InitModule3( "Blender.Particle", M_Particle_methods, M_Particle_doc ); - return ( submodule ); + 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; } -/*****************************************************************************/ -/* Python BPy_Particle methods: */ -/*****************************************************************************/ +/* create the Blender.Particle.EmitFrom constant dict */ -PyObject *Particle_getSta( BPy_Particle * self ) +static PyObject *Particle_EmitFrom( void ) { + PyObject *EmitFrom = PyConstant_New( ); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->sta ); + 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( ); -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; + 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; } -PyObject *Particle_getEnd( BPy_Particle * self ) +static PyObject *Particle_DrawAs( void ) { + PyObject *DrawAs = PyConstant_New( ); - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->end ); + 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 ); +} - -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; +void Particle_RecalcPsys_distr(BPy_PartSYS* self,int child){ + psys_flush_settings(self->psys->part,PSYS_DISTR,child); } -PyObject *Particle_getLifetime( BPy_Particle * self ) -{ +PyObject *ParticleSYS_Init( void ){ + PyObject *submodule; + PyObject *Types; + PyObject *React; + PyObject *EmitFrom; + PyObject *Dist; + PyObject *DrawAs; - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->lifetime ); + if( PyType_Ready( &ParticleSYS_Type ) < 0) + return NULL; + + Types = Particle_TypeDict (); + React = Particle_ReactOnDict(); + EmitFrom = Particle_EmitFrom(); + DrawAs = Particle_DrawAs(); + Dist = Particle_DistrDict(); + + submodule = Py_InitModule3( "Blender.Particle", M_ParticleSYS_methods, 0 ); + + 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 ); } +static PyObject *Part_freeEdit( BPy_PartSYS * self, PyObject * args ){ + if(self->psys->flag & PSYS_EDITED){ + if(self->psys->edit) + PE_free_particle_edit(self->psys); -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 ); + self->psys->flag &= ~PSYS_EDITED; + self->psys->recalc |= PSYS_RECALC_HAIR; + + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); + } return Py_None; } +static PyObject *Part_ProtectCache( BPy_PartSYS * self, PyObject * args ){ + self->psys->flag |= PSYS_PROTECT_CACHE; + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + return Py_None; +} -PyObject *Particle_getNormfac( BPy_Particle * self ) -{ +static PyObject *Part_UnprotectCache( BPy_PartSYS * self, PyObject * args ){ + self->psys->flag &= ~PSYS_PROTECT_CACHE; + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + return Py_None; +} - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->normfac ); +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; + + if (!(self->psys->flag & PSYS_ENABLED)) + return Py_None; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + return Py_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" ); + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0) + init = 0; + else + init = 1; + + if (init){ + loc = PyTuple_New(3); + 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 ( PyList_Append(partlist,loc) < 0 ){ + Py_DECREF(partlist); + Py_XDECREF(loc); + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Couldn't append item to PyList" ); + } + } + else { + 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; + float cfra=bsystem_time(ob,(float)CFRA,0.0); + int i; -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; + + if (!(self->psys->flag & PSYS_ENABLED)) + return Py_None; + + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + return Py_None; + + if (psys->part->type != 2){ + partlist = PyList_New( 0 ); + + for (i = 0; i < psys->totpart + psys->totchild; i++){ + state.time = cfra; + if(psys_get_particle_state(ob,psys,i,&state,0)==0){ + PyList_Append(partlist,Py_None); + continue; + } + loc = PyTuple_New(4); + 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])); + PyList_Append(partlist,loc); + } + } + return partlist; } +static PyObject *Part_GetSize( BPy_PartSYS * self, PyObject * args ){ + ParticleSystem *psys = 0L; + ParticleData *data; + Object *ob = 0L; + PyObject *partlist; + PyObject* loc = 0L; + PyObject* siz = 0L; + float size; + float cfra=bsystem_time(ob,(float)CFRA,0.0); + int i; + data = self->psys->particles; -PyObject *Particle_getObfac( BPy_Particle * self ) -{ + if (!(self->psys->flag & PSYS_ENABLED)) + return Py_None; - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->obfac ); + psys = self->psys; + ob = self->object; + + if (!ob || !psys) + return Py_None; + + if (psys->part->type != 2){ + partlist = PyList_New( 0 ); + + for (i = 0; i < psys->totpart + psys->totchild; i++, data++){ + if (i < psys->totpart){ + size = data->size; + } else { + ChildParticle *cpa= &psys->child[i-psys->totpart]; + size = psys_get_child_size(psys,cpa,cfra,0); + } + siz = PyFloat_FromDouble((double)size); + PyList_Append(partlist,siz); + } + } + return partlist; } +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) + return Py_None; -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; + mat = Material_CreatePyObject(ma); + return mat; } +/*****************************************************************************/ +/* Function: Set/Get Seed */ +/*****************************************************************************/ -PyObject *Particle_getRandfac( BPy_Particle * self ) +static int Part_setSeed( BPy_PartSYS * self, PyObject * args ) { + return EXPP_setIValueRange( args, &self->psys->seed, + 0, 255, 'i' ); +} - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randfac ); +static PyObject *Part_getSeed( BPy_PartSYS * self ) +{ + return PyInt_FromLong( (long)( self->psys->seed ) ); } +static int Part_setType( BPy_PartSYS * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->type, + 0, 2, 'h' ); + psys_flush_settings( self->psys->part, PSYS_TYPE, 1 ); -PyObject *Particle_setRandfac( BPy_Particle * self, PyObject * args ) + return res; +} + +static PyObject *Part_getType( BPy_PartSYS * self ) { - 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; + return PyInt_FromLong( (short)( self->psys->part->type ) ); } +static int Part_setResol( BPy_PartSYS * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->grid_res, + 0, 100, 'i' ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); -PyObject *Particle_getTexfac( BPy_Particle * self ) + return res; +} + +static PyObject *Part_getResol( BPy_PartSYS * self ) { - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->texfac ); + 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); -PyObject *Particle_setTexfac( BPy_Particle * self, PyObject * args ) + return res; +} + +static PyObject *Part_getStart( BPy_PartSYS * self ) { - 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; + 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); -PyObject *Particle_getRandlife( BPy_Particle * self ) + return res; +} + +static PyObject *Part_getEnd( BPy_PartSYS * self ) { - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->randlife ); + 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 ); + } -PyObject *Particle_setRandlife( BPy_Particle * self, PyObject * args ) + 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); + } + + return 0; +} + +static PyObject *Part_getEditable( BPy_PartSYS * self ) { - 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; + return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0 ); } +static int Part_setAmount( BPy_PartSYS * self, PyObject * args ) +{ + int res = EXPP_setIValueRange( args, &self->psys->part->totpart, + 0, 100000, 'i' ); + psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 ); -PyObject *Particle_getNabla( BPy_Particle * self ) + return res; +} + +static PyObject *Part_getAmount( BPy_PartSYS * self ) { - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->nabla ); + 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 ); + } -PyObject *Particle_setNabla( BPy_Particle * self, PyObject * args ) + 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; +} + +static PyObject *Part_getMultiReact( BPy_PartSYS * self ) { - 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; + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 ); } +static int Part_setReactShape( BPy_PartSYS * self, PyObject * args ) +{ + int res = EXPP_setFloatRange( args, &self->psys->part->reactshape, + 0.0f, 10.0f ); + Particle_Recalc(self,1); -PyObject *Particle_getVectsize( BPy_Particle * self ) + return res; +} + +static PyObject *Part_getReactShape( BPy_PartSYS * self ) { - - PartEff *ptr = ( PartEff * ) self->particle; - return PyFloat_FromDouble( ptr->vectsize ); + 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); -PyObject *Particle_setVectsize( BPy_Particle * self, PyObject * args ) + return res; +} + +static PyObject *Part_getSegments( BPy_PartSYS * self ) { - 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; + return PyInt_FromLong( ((long)( self->psys->part->hair_step )) ); } - -PyObject *Particle_getTotpart( BPy_Particle * self ) +static int Part_setLife( BPy_PartSYS * self, PyObject * args ) { + int res = EXPP_setFloatRange( args, &self->psys->part->lifetime, + 1.0f, MAXFRAMEF ); - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totpart ); + 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 ); -PyObject *Particle_setTotpart( BPy_Particle * self, PyObject * args ) + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getRandLife( BPy_PartSYS * self ) { - 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; + return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) ); } - -PyObject *Particle_getTotkey( BPy_Particle * self ) +static int Part_set2d( BPy_PartSYS * self, PyObject * args ) { + int number; - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->totkey ); + 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 ); -PyObject *Particle_setTotkey( BPy_Particle * self, PyObject * args ) + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxVel( BPy_PartSYS * self ) { - 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; + 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); -PyObject *Particle_getSeed( BPy_Particle * self ) + return res; +} + +static PyObject *Part_getAvVel( BPy_PartSYS * self ) { + return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) ); +} - PartEff *ptr = ( PartEff * ) self->particle; - return PyInt_FromLong( ptr->seed ); +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 ); -PyObject *Particle_setSeed( BPy_Particle * self, PyObject * args ) + Particle_Recalc(self,1); + + return res; +} + +static PyObject *Part_getMaxTan( BPy_PartSYS * self ) { - 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; + return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) ); } -PyObject *Particle_getForce( BPy_Particle * self ) +static int Part_setGroundZ( BPy_PartSYS * self, PyObject * args ) { + int res = EXPP_setFloatRange( args, &self->psys->part->groundz, + -100.0f, 100.0f ); - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", ptr->force[0], ptr->force[1], - ptr->force[2] ); + Particle_Recalc(self,1); + + return res; } +static PyObject *Part_getGroundZ( BPy_PartSYS * self ) +{ + return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) ); +} -PyObject *Particle_setForce( BPy_Particle * self, PyObject * args ) +static int Part_setOb( BPy_PartSYS * 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; + 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; } -PyObject *Particle_getMult( BPy_Particle * self ) +static PyObject *Part_getOb( BPy_PartSYS * self ) { + Object * obj; + obj = self->psys->keyed_ob; + if (!obj) + return Py_None; - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mult[0], ptr->mult[1], ptr->mult[2], - ptr->mult[3] ); + return Object_CreatePyObject( obj ); } +static int Part_setRandEmission( BPy_PartSYS * self, PyObject * args ) +{ + int number; -PyObject *Particle_setMult( BPy_Particle * self, PyObject * args ) + 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 ) { - 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; + return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 ); } +static int Part_setPaticleDist( 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 ); -PyObject *Particle_getLife( BPy_Particle * self ) -{ + if (number < 0 || number > 3){ + sprintf ( errstr, "expected int argument between 0 - 3" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->life[0], ptr->life[1], ptr->life[2], - ptr->life[3] ); + self->psys->part->from = number; + + Particle_RecalcPsys_distr(self,1); + + return 0; } - -PyObject *Particle_setLife( BPy_Particle * self, PyObject * args ) +static PyObject *Part_getPaticleDist( BPy_PartSYS * self ) { - 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; + 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 ); + } -PyObject *Particle_getChild( BPy_Particle * self ) + 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 ); +} - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->child[0], ptr->child[1], ptr->child[2], - ptr->child[3] ); +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 ) ); +} -PyObject *Particle_setChild( BPy_Particle * self, PyObject * args ) +static int Part_setJitterAmount( BPy_PartSYS * 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; + 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 )) ); +} -PyObject *Particle_getMat( BPy_Particle * self ) + +static int Part_setPF( BPy_PartSYS * self, PyObject * args ) { + int res = EXPP_setIValueRange( args, &self->psys->part->userjit, + 0, 1000, 'i' ); - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f,f)", - ptr->mat[0], ptr->mat[1], ptr->mat[2], - ptr->mat[3] ); + Particle_RecalcPsys_distr(self,1); + + return res; } +static PyObject *Part_getPF( BPy_PartSYS * self ) +{ + return PyInt_FromLong( ((short)( self->psys->part->userjit )) ); +} -PyObject *Particle_setMat( BPy_Particle * self, PyObject * args ) +static int Part_setInvert( BPy_PartSYS * 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; + 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 ); +} -PyObject *Particle_getDefvec( BPy_Particle * self ) +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 ); + } - PartEff *ptr = ( PartEff * ) self->particle; - return Py_BuildValue( "(f,f,f)", - ptr->defvec[0], ptr->defvec[1], ptr->defvec[2] ); + 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) + return Py_None; -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; + return Object_CreatePyObject( obj ); } -/*****************************************************************************/ -/* Function: ParticleDeAlloc */ -/* Description: This is a callback function for the BPy_Particle type. It is */ -/* the destructor function. */ -/*****************************************************************************/ -void ParticleDeAlloc( BPy_Particle * self ) + +PyObject *Part_getDupOb( BPy_PartSYS * self ) { - PartEff *ptr = ( PartEff * ) self; - PyObject_DEL( ptr ); + Object * obj; + obj = self->psys->part->dup_ob; + if (!obj) + return Py_None; + + return Object_CreatePyObject( obj ); } -/*****************************************************************************/ -/* 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. */ -/*****************************************************************************/ +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; -PyObject *ParticleGetAttr( BPy_Particle * self, char *name ) -{ + if(psys->target_ob) + tob=psys->target_ob; + else + tob=ob; - 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 ); + tottpsys = BLI_countlist(&tob->particlesystem); + res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' ); - return Py_FindMethod( BPy_Particle_methods, ( PyObject * ) self, - name ); + 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; } -/*****************************************************************************/ -/* 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 PyObject *Part_getTargetPsys( BPy_PartSYS * self ){ + return PyInt_FromLong( (short)( self->psys->target_psys ) ); +} + +static int Part_setEnable( BPy_PartSYS * self, PyObject * args ) { + int number; - PyObject *valtuple; - PyObject *error = NULL; + if( !PyInt_Check( args ) ) { + char errstr[128]; + sprintf ( errstr, "expected int argument" ); + return EXPP_ReturnIntError( PyExc_TypeError, errstr ); + } - valtuple = Py_BuildValue( "(N)", value ); + number = PyInt_AS_LONG( args ); - if( !valtuple ) - return EXPP_ReturnIntError( PyExc_MemoryError, - "ParticleSetAttr: couldn't create PyTuple" ); + if (number){ + self->psys->flag |= PSYS_ENABLED; + }else{ + self->psys->flag &= ~PSYS_ENABLED; + } - 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 ); + DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA); - else { - Py_DECREF( valtuple ); + return 0; +} - if( ( strcmp( name, "Types" ) == 0 ) || - ( strcmp( name, "Modes" ) == 0 ) ) - return ( EXPP_ReturnIntError( PyExc_AttributeError, - "constant dictionary -- cannot be changed" ) ); +static PyObject *Part_getEnable( BPy_PartSYS * self ) +{ + return PyInt_FromLong( ((long)( self->psys->flag & PSYS_ENABLED )) > 0 ); +} - else - return ( EXPP_ReturnIntError( PyExc_KeyError, - "attribute not found" ) ); +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 ); } - Py_DECREF(valtuple); - if( error != Py_None ) - return -1; + number = PyInt_AS_LONG( args ); - Py_DECREF( Py_None ); + if (number){ + self->psys->part->draw |= PART_DRAW_EMITTER; + }else{ + self->psys->part->draw &= ~PART_DRAW_EMITTER; + } + + /* check need for dupliobjects */ + nr=0; + for(self->psys=self->object->particlesystem.first; self->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; } -/*****************************************************************************/ -/* 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; +static PyObject *Part_getRenderObject( BPy_PartSYS * self ) +{ + return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 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 int Part_setParticleDisp( BPy_PartSYS * self, PyObject * args ) { - return PyString_FromString( "Particle" ); + int res = EXPP_setIValueRange( args, &self->psys->part->disp, + 0, 100, 'i' ); + + Particle_Recalc(self,0); + + + return res; } -PyObject *ParticleCreatePyObject( struct Effect * particle ) +static PyObject *Part_getParticleDisp( BPy_PartSYS * self ) { - BPy_Particle *blen_object; + 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' ); - blen_object = - ( BPy_Particle * ) PyObject_NEW( BPy_Particle, - &Particle_Type ); + Particle_Recalc(self,1); - if( blen_object == NULL ) { - return ( NULL ); - } - blen_object->particle = particle; - return ( ( PyObject * ) blen_object ); + return res; } -int ParticleCheckPyObject( PyObject * py_obj ) +static PyObject *Part_getStep( BPy_PartSYS * self ) { - return ( py_obj->ob_type == &Particle_Type ); + return PyInt_FromLong( ((short)( self->psys->part->draw_step )) ); } - -struct Particle *ParticleFromPyObject( PyObject * py_obj ) +static int Part_setRenderStep( BPy_PartSYS * self, PyObject * args ) { - BPy_Particle *blen_obj; + int res = EXPP_setIValueRange( args, &self->psys->part->ren_step, + 0, 7, 'i' ); - blen_obj = ( BPy_Particle * ) py_obj; - return ( ( struct Particle * ) blen_obj->particle ); + /*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 ) ); +} Index: Particle.h =================================================================== --- Particle.h (revision 14348) +++ Particle.h (working copy) @@ -1,5 +1,5 @@ -/* - * $Id: Particle.h 5702 2005-11-04 20:34:38Z khughes $ +/* + * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * @@ -25,43 +25,31 @@ * * This is a new part of Blender. * - * Contributor(s): Jacques Guignot + * Contributor(s): Jacques Guignot, Cedric Paille * * ***** END GPL/BL DUAL 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; +} BPy_PartSYS; -#include "Effect.h" +PyObject *ParticleSYS_Init( void ); -/*****************************************************************************/ -/* 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 - - -#endif /* EXPP_PARTICLE_H */ +#endif /* EXPP_EFFECT_H */