/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * This is a new part of Blender. * * Contributor(s): * Original version: Jacques Guignot, Jean-Michel Soler * Rewrite : Cedric Paille, Stephen Swaney, Joilnen Leite * * ***** END GPL LICENSE BLOCK ***** */ #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" #include "MEM_guardedalloc.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_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 ); /*****************************************************************************/ /* The following string definitions are used for documentation strings. */ /* In Python these will be written to the console when doing a */ /* Blender.Particle.__doc__ */ /*****************************************************************************/ 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 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: */ /*****************************************************************************/ 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: PARTICLESYS_repr */ /* Description: This is a callback function for the BPy_Effect type. It */ /* builds a meaninful string to represent effcte objects. */ /*****************************************************************************/ static PyObject *ParticleSys_repr( void ) { return PyString_FromString( "ParticleSys" ); } /*****************************************************************************/ /* Function : P_sys_FromPyObject */ /*****************************************************************************/ struct ParticleSystem *P_sys_FromPyObject( BPy_PartSys * py_obj ) { BPy_PartSys *blen_obj; blen_obj = ( BPy_PartSys * ) py_obj; return ( blen_obj->psys ); } /*****************************************************************************/ /* Function : ParticleSysCreatePyObject */ /*****************************************************************************/ 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; 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; PyObject *Types; PyObject *React; PyObject *EmitFrom; PyObject *Dist; PyObject *DrawAs; 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, 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 ); } 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); 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 = 0L; 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, 1); 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" ); } Py_DECREF(loc); /* PyList_Append increfs */ path++; } if ( PyList_Append(partlist,seglist) < 0 ){ Py_DECREF(seglist); Py_DECREF(partlist); return EXPP_ReturnPyObjError( PyExc_RuntimeError, "Couldn't append item to PyList" ); } Py_DECREF(seglist); /* PyList_Append increfs */ } 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" ); } Py_DECREF(loc);/* PyList_Append increfs */ path++; } if ( PyList_Append(partlist,seglist) < 0){ Py_DECREF(partlist); Py_XDECREF(loc); return EXPP_ReturnPyObjError( PyExc_RuntimeError, "Couldn't append item to PyList" ); } Py_DECREF(seglist); /* PyList_Append increfs */ } } 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" ); } Py_DECREF(loc);/* PyList_Append increfs */ } else { if ( all ){ if ( PyList_Append(partlist,Py_None) < 0 ){ Py_DECREF(partlist); return EXPP_ReturnPyObjError( PyExc_RuntimeError, "Couldn't append item to PyList" ); } Py_DECREF(Py_None); /* PyList_Append increfs */ } } } } return partlist; } static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){ ParticleSystem *psys = 0L; Object *ob = 0L; PyObject *partlist = 0L; 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); Py_DECREF(Py_None); /* PyList_Append increfs */ 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); Py_DECREF(loc); /* PyList_Append increfs */ } } 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); Py_DECREF(tuple); } else { siz = PyFloat_FromDouble((double)size); PyList_Append(partlist,siz); Py_DECREF(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; 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){ 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); Py_DECREF(tuple); } else { lif = PyFloat_FromDouble((double)life); PyList_Append(partlist,lif); Py_DECREF(lif); } } } 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) Py_RETURN_NONE; mat = Material_CreatePyObject(ma); return mat; } /*****************************************************************************/ /* Function: Set/Get Seed */ /*****************************************************************************/ static int Part_setSeed( BPy_PartSys * self, PyObject * args ) { return EXPP_setIValueRange( args, &self->psys->seed, 0, 255, 'i' ); } 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 ); return res; } static PyObject *Part_getType( BPy_PartSys * self ) { 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 ); return res; } 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 ); } 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 ) { 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 ); return res; } 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 ); } 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 ) { 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); 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 ) ); }