soc-2008-mxcurioni: merged changes to revision 15705
[blender.git] / source / blender / python / api2_2x / Particle.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * This is a new part of Blender.
24  *
25  * Contributor(s): 
26  *    Original version: Jacques Guignot, Jean-Michel Soler
27  *    Rewrite :        Cedric Paille, Stephen Swaney, Joilnen Leite
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "Particle.h"
33 #include "gen_utils.h"
34 #include "BKE_object.h"
35 #include "BKE_main.h"
36 #include "BKE_particle.h"
37 #include "BKE_global.h"
38 #include "BKE_depsgraph.h"
39 #include "BKE_modifier.h"
40 #include "BKE_material.h"
41 #include "BKE_utildefines.h"
42 #include "BKE_pointcache.h"
43 #include "BKE_DerivedMesh.h"
44 #include "BIF_editparticle.h"
45 #include "BIF_space.h"
46 #include "blendef.h"
47 #include "DNA_modifier_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_material_types.h"
50 #include "BLI_blenlib.h"
51 #include "mydevice.h"
52 #include "Object.h"
53 #include "Material.h"
54
55 #include "MEM_guardedalloc.h"
56
57
58
59 /* Type Methods */
60 static PyObject *M_ParticleSys_New( PyObject * self, PyObject * args );
61 static PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args );
62
63 /* Particle Methods */
64 static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args );
65 static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args );
66 static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args );
67 static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args );
68 static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args );
69 static int Part_setSeed( BPy_PartSys * self, PyObject * args );
70 static PyObject *Part_getSeed( BPy_PartSys * self );
71 static int Part_setType( BPy_PartSys * self, PyObject * args );
72 static PyObject *Part_getType( BPy_PartSys * self );
73 static int Part_setResol( BPy_PartSys * self, PyObject * args );
74 static PyObject *Part_getResol( BPy_PartSys * self );
75 static int Part_setStart( BPy_PartSys * self, PyObject * args );
76 static PyObject *Part_getStart( BPy_PartSys * self );
77 static int Part_setEnd( BPy_PartSys * self, PyObject * args );
78 static PyObject *Part_getEnd( BPy_PartSys * self );
79 static int Part_setEditable( BPy_PartSys * self, PyObject * args );
80 static PyObject *Part_getEditable( BPy_PartSys * self );
81 static int Part_setAmount( BPy_PartSys * self, PyObject * args );
82 static PyObject *Part_getAmount( BPy_PartSys * self );
83 static int Part_setMultiReact( BPy_PartSys * self, PyObject * args );
84 static PyObject *Part_getMultiReact( BPy_PartSys * self );
85 static int Part_setReactShape( BPy_PartSys * self, PyObject * args );
86 static PyObject *Part_getReactShape( BPy_PartSys * self );
87 static int Part_setSegments( BPy_PartSys * self, PyObject * args );
88 static PyObject *Part_getSegments( BPy_PartSys * self );
89 static int Part_setLife( BPy_PartSys * self, PyObject * args );
90 static PyObject *Part_getLife( BPy_PartSys * self );
91 static int Part_setRandLife( BPy_PartSys * self, PyObject * args );
92 static PyObject *Part_getRandLife( BPy_PartSys * self );
93 static int Part_set2d( BPy_PartSys * self, PyObject * args );
94 static PyObject *Part_get2d( BPy_PartSys * self );
95 static int Part_setMaxVel( BPy_PartSys * self, PyObject * args );
96 static PyObject *Part_getMaxVel( BPy_PartSys * self );
97 static int Part_setAvVel( BPy_PartSys * self, PyObject * args );
98 static PyObject *Part_getAvVel( BPy_PartSys * self );
99 static int Part_setLatAcc( BPy_PartSys * self, PyObject * args );
100 static PyObject *Part_getLatAcc( BPy_PartSys * self );
101 static int Part_setMaxTan( BPy_PartSys * self, PyObject * args );
102 static PyObject *Part_getMaxTan( BPy_PartSys * self );
103 static int Part_setGroundZ( BPy_PartSys * self, PyObject * args );
104 static PyObject *Part_getGroundZ( BPy_PartSys * self );
105 static int Part_setOb( BPy_PartSys * self, PyObject * args );
106 static PyObject *Part_getOb( BPy_PartSys * self );
107 static PyObject *Part_getRandEmission( BPy_PartSys * self );
108 static int Part_setRandEmission( BPy_PartSys * self, PyObject * args );
109 static PyObject *Part_getRandEmission( BPy_PartSys * self );
110 static int Part_setParticleDist( BPy_PartSys * self, PyObject * args );
111 static PyObject *Part_getParticleDist( BPy_PartSys * self );
112 static int Part_setEvenDist( BPy_PartSys * self, PyObject * args );
113 static PyObject *Part_getEvenDist( BPy_PartSys * self );
114 static int Part_setDist( BPy_PartSys * self, PyObject * args );
115 static PyObject *Part_getDist( BPy_PartSys * self );
116 static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args );
117 static PyObject *Part_getParticleDisp( BPy_PartSys * self );
118 static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args );
119 static PyObject *Part_getJitterAmount( BPy_PartSys * self );
120 static int Part_setPF( BPy_PartSys * self, PyObject * args );
121 static PyObject *Part_getPF( BPy_PartSys * self );
122 static int Part_setInvert( BPy_PartSys * self, PyObject * args );
123 static PyObject *Part_getInvert( BPy_PartSys * self );
124 static int Part_setTargetOb( BPy_PartSys * self, PyObject * args );
125 static PyObject *Part_getTargetOb( BPy_PartSys * self );
126 static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args );
127 static PyObject *Part_getTargetPsys( BPy_PartSys * self );
128 static int Part_setRenderObject( BPy_PartSys * self, PyObject * args );
129 static PyObject *Part_getRenderObject( BPy_PartSys * self );
130 static int Part_setStep( BPy_PartSys * self, PyObject * args );
131 static PyObject *Part_getStep( BPy_PartSys * self );
132 static int Part_setRenderStep( BPy_PartSys * self, PyObject * args );
133 static PyObject *Part_getRenderStep( BPy_PartSys * self );
134 static PyObject *Part_getDupOb( BPy_PartSys * self );
135 static PyObject *Part_getDrawAs( BPy_PartSys * self );
136 static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args );
137
138 /*****************************************************************************/
139 /* Python Effect_Type callback function prototypes:                           */
140 /*****************************************************************************/
141 static PyObject *ParticleSys_repr( void );
142
143 /*****************************************************************************/
144 /* The following string definitions are used for documentation strings.      */
145 /* In Python these will be written to the console when doing a               */
146 /* Blender.Particle.__doc__                                                  */
147 /*****************************************************************************/
148 static char M_ParticleSys_doc[] = "The Blender Effect module\n\n\
149 This module provides access to **Object Data** in Blender.\n\
150 Functions :\n\
151         Get(name) : retreives particle system (as list)  with the given name\n";
152 static char M_ParticleSys_Get_doc[] = "xxx";
153 static char M_ParticleSys_New_doc[] = "xxx";
154
155 /*****************************************************************************/
156 /* Python BPy_ParticleSys methods table:                                     */
157 /*****************************************************************************/
158
159 static PyMethodDef BPy_ParticleSys_methods[] = {
160         {"freeEdit", ( PyCFunction ) Part_freeEdit,
161          METH_NOARGS, "() - Free from edit mode"},
162         {"getLoc", ( PyCFunction ) Part_GetLoc,
163          METH_VARARGS, "() - Get particles location"},
164         {"getRot", ( PyCFunction ) Part_GetRot,
165          METH_VARARGS, "() - Get particles rotations (list of 4 floats quaternion)"},
166         {"getMat", ( PyCFunction ) Part_GetMat,
167          METH_NOARGS, "() - Get particles material"},
168         {"getSize", ( PyCFunction ) Part_GetSize,
169          METH_VARARGS, "() - Get particles size in a list"},
170         {"getAge", ( PyCFunction ) Part_GetAge,
171          METH_VARARGS, "() - Get particles life in a list"},
172         {NULL, NULL, 0, NULL}
173 };
174
175 /*****************************************************************************/
176 /* Python BPy_ParticleSys attributes get/set structure:                           */
177 /*****************************************************************************/
178 static PyGetSetDef BPy_ParticleSys_getseters[] = {
179 /* Extras */
180         {"seed",
181          (getter)Part_getSeed, (setter)Part_setSeed,
182          "Set an offset in the random table",
183          NULL},
184  /* basics */
185         {"type",
186          (getter)Part_getType, (setter)Part_setType,
187          "Type of particle system ( Particle.TYPE[ 'HAIR' | 'REACTOR' | 'EMITTER' ] )",
188          NULL},
189         {"resolutionGrid",
190          (getter)Part_getResol, (setter)Part_setResol,
191          "The resolution of the particle grid",
192          NULL},
193         {"startFrame",
194          (getter)Part_getStart, (setter)Part_setStart,
195          "Frame # to start emitting particles",
196          NULL},
197         {"endFrame",
198          (getter)Part_getEnd, (setter)Part_setEnd,
199          "Frame # to stop emitting particles",
200          NULL},
201         {"editable",
202          (getter)Part_getEditable, (setter)Part_setEditable,
203          "Finalize hair to enable editing in particle mode",
204          NULL},
205     {"amount",
206          (getter)Part_getAmount, (setter)Part_setAmount,
207          "The total number of particles",
208          NULL},
209     {"multireact",
210          (getter)Part_getMultiReact, (setter)Part_setMultiReact,
211          "React multiple times ( Paricle.REACTON[ 'NEAR' | 'COLLISION' | 'DEATH' ] )",
212          NULL},
213     {"reactshape",
214          (getter)Part_getReactShape, (setter)Part_setReactShape,
215          "Power of reaction strength dependence on distance to target",
216          NULL},
217     {"hairSegments",
218          (getter)Part_getSegments, (setter)Part_setSegments,
219          "Amount of hair segments",
220          NULL},
221     {"lifetime",
222          (getter)Part_getLife, (setter)Part_setLife,
223          "Specify the life span of the particles",
224          NULL},
225     {"randlife",
226          (getter)Part_getRandLife, (setter)Part_setRandLife,
227          "Give the particle life a random variation",
228          NULL},
229      {"randemission",
230          (getter)Part_getRandEmission, (setter)Part_setRandEmission,
231          "Give the particle life a random variation",
232          NULL},
233      {"particleDistribution",
234          (getter)Part_getParticleDist, (setter)Part_setParticleDist,
235          "Where to emit particles from  Paricle.EMITFROM[ 'PARTICLE' | 'VOLUME' | 'FACES' | 'VERTS' ] )",
236          NULL},
237      {"evenDistribution",
238          (getter)Part_getEvenDist, (setter)Part_setEvenDist,
239          "Use even distribution from faces based on face areas or edge lengths",
240          NULL},
241      {"distribution",
242          (getter)Part_getDist, (setter)Part_setDist,
243          "How to distribute particles on selected element Paricle.DISTRIBUTION[ 'GRID' | 'RANDOM' | 'JITTERED' ] )",
244          NULL},
245      {"jitterAmount",
246          (getter)Part_getJitterAmount, (setter)Part_setJitterAmount,
247          "Amount of jitter applied to the sampling",
248          NULL},
249      {"pf",
250          (getter)Part_getPF, (setter)Part_setPF,
251          "Emission locations / face (0 = automatic)",
252          NULL},
253      {"invert",
254          (getter)Part_getInvert, (setter)Part_setInvert,
255          "Invert what is considered object and what is not.",
256          NULL},
257      {"targetObject",
258          (getter)Part_getTargetOb, (setter)Part_setTargetOb,
259          "The object that has the target particle system (empty if same object)",
260          NULL},
261      {"targetpsys",
262          (getter)Part_getTargetPsys, (setter)Part_setTargetPsys,
263          "The target particle system number in the object",
264          NULL},
265 /* Physics */
266     {"2d",
267          (getter)Part_get2d, (setter)Part_set2d,
268          "Constrain boids to a surface",
269          NULL},
270     {"maxvel",
271          (getter)Part_getMaxVel, (setter)Part_setMaxVel,
272          "Maximum velocity",
273          NULL},
274     {"avvel",
275          (getter)Part_getAvVel, (setter)Part_setAvVel,
276          "The usual speed % of max velocity",
277          NULL},
278     {"latacc",
279          (getter)Part_getLatAcc, (setter)Part_setLatAcc,
280          "Lateral acceleration % of max velocity",
281          NULL},
282     {"tanacc",
283          (getter)Part_getMaxTan, (setter)Part_setMaxTan,
284          "Tangential acceleration % of max velocity",
285          NULL},
286     {"groundz",
287          (getter)Part_getGroundZ, (setter)Part_setGroundZ,
288          "Default Z value",
289          NULL},
290      {"object",
291          (getter)Part_getOb, (setter)Part_setOb,
292          "Constrain boids to object's surface",
293          NULL},
294 /* Visualisation */
295      {"renderEmitter",
296          (getter)Part_getRenderObject, (setter)Part_setRenderObject,
297          "Render emitter object",
298          NULL},
299      {"displayPercentage",
300          (getter)Part_getParticleDisp, (setter)Part_setParticleDisp,
301          "Particle display percentage",
302          NULL},
303      {"hairDisplayStep",
304          (getter)Part_getStep, (setter)Part_setStep,
305          "How many steps paths are drawn with (power of 2)",
306          NULL},
307      {"hairRenderStep",
308          (getter)Part_getRenderStep, (setter)Part_setRenderStep,
309          "How many steps paths are rendered with (power of 2)",
310          NULL},
311      {"duplicateObject",
312          (getter)Part_getDupOb, NULL,
313          "Get the duplicate ob",
314          NULL},
315      {"drawAs",
316          (getter)Part_getDrawAs, NULL,
317          "Get draw type Particle.DRAWAS([ 'NONE' | 'OBJECT' | 'POINT' | ... ] )",
318          NULL},
319         {NULL,NULL,NULL,NULL,NULL}  /* Sentinel */
320 };
321
322 /*****************************************************************************/
323 /* Python method structure definition for Blender.Particle module:           */
324 /*****************************************************************************/
325 static struct PyMethodDef M_ParticleSys_methods[] = {
326         {"New", ( PyCFunction ) M_ParticleSys_New, METH_VARARGS, M_ParticleSys_New_doc},
327         {"Get", M_ParticleSys_Get, METH_VARARGS, M_ParticleSys_Get_doc},
328         {NULL, NULL, 0, NULL}
329 };
330
331 /*****************************************************************************/
332 /* Python ParticleSys_Type structure definition:                                  */
333 /*****************************************************************************/
334 PyTypeObject ParticleSys_Type = {
335         PyObject_HEAD_INIT( NULL )  /* required py macro */
336         0,                          /* ob_size */
337         /*  For printing, in format "<module>.<name>" */
338         "Blender ParticleSys",           /* char *tp_name; */
339         sizeof( BPy_PartSys ),       /* int tp_basicsize; */
340         0,                          /* tp_itemsize;  For allocation */
341
342         /* Methods to implement standard operations */
343
344         NULL,                                           /* destructor tp_dealloc; */
345         NULL,                       /* printfunc tp_print; */
346         NULL,                       /* getattrfunc tp_getattr; */
347         NULL,                       /* setattrfunc tp_setattr; */
348         NULL,                       /* cmpfunc tp_compare; */
349         ( reprfunc ) ParticleSys_repr,/* reprfunc tp_repr; */
350
351         /* Method suites for standard classes */
352
353         NULL,                       /* PyNumberMethods *tp_as_number; */
354         NULL,                       /* PySequenceMethods *tp_as_sequence; */
355         NULL,                       /* PyMappingMethods *tp_as_mapping; */
356
357         /* More standard operations (here for binary compatibility) */
358
359         NULL,                       /* hashfunc tp_hash; */
360         NULL,                       /* ternaryfunc tp_call; */
361         NULL,                       /* reprfunc tp_str; */
362         NULL,                       /* getattrofunc tp_getattro; */
363         NULL,                       /* setattrofunc tp_setattro; */
364
365         /* Functions to access object as input/output buffer */
366         NULL,                       /* PyBufferProcs *tp_as_buffer; */
367
368   /*** Flags to define presence of optional/expanded features ***/
369         Py_TPFLAGS_DEFAULT,         /* long tp_flags; */
370
371         NULL,                       /*  char *tp_doc;  Documentation string */
372   /*** Assigned meaning in release 2.0 ***/
373         /* call function for all accessible objects */
374         NULL,                       /* traverseproc tp_traverse; */
375
376         /* delete references to contained objects */
377         NULL,                       /* inquiry tp_clear; */
378
379   /***  Assigned meaning in release 2.1 ***/
380   /*** rich comparisons ***/
381         NULL,                       /* richcmpfunc tp_richcompare; */
382
383   /***  weak reference enabler ***/
384         0,                          /* long tp_weaklistoffset; */
385
386   /*** Added in release 2.2 ***/
387         /*   Iterators */
388         NULL,                       /* getiterfunc tp_iter; */
389         NULL,                       /* iternextfunc tp_iternext; */
390
391   /*** Attribute descriptor and subclassing stuff ***/
392         BPy_ParticleSys_methods,      /* struct PyMethodDef *tp_methods; */
393         NULL,                       /* struct PyMemberDef *tp_members; */
394         BPy_ParticleSys_getseters,  /* struct PyGetSetDef *tp_getset; */
395         NULL,                       /* struct _typeobject *tp_base; */
396         NULL,                       /* PyObject *tp_dict; */
397         NULL,                       /* descrgetfunc tp_descr_get; */
398         NULL,                       /* descrsetfunc tp_descr_set; */
399         0,                          /* long tp_dictoffset; */
400         NULL,                       /* initproc tp_init; */
401         NULL,                       /* allocfunc tp_alloc; */
402         NULL,                       /* newfunc tp_new; */
403         /*  Low-level free-memory routine */
404         NULL,                       /* freefunc tp_free;  */
405         /* For PyObject_IS_GC */
406         NULL,                       /* inquiry tp_is_gc;  */
407         NULL,                       /* PyObject *tp_bases; */
408         /* method resolution order */
409         NULL,                       /* PyObject *tp_mro;  */
410         NULL,                       /* PyObject *tp_cache; */
411         NULL,                       /* PyObject *tp_subclasses; */
412         NULL,                       /* PyObject *tp_weaklist; */
413         NULL
414 };
415
416 /*****************************************************************************/
417 /* Function:    PARTICLESYS_repr                                             */
418 /* Description: This is a callback function for the BPy_Effect type. It      */
419 /*              builds a meaninful string to represent effcte objects.       */
420 /*****************************************************************************/
421
422 static PyObject *ParticleSys_repr( void )
423 {
424         return PyString_FromString( "ParticleSys" );
425 }
426
427 /*****************************************************************************/
428 /* Function : P_sys_FromPyObject                                           */
429 /*****************************************************************************/
430
431 struct ParticleSystem *P_sys_FromPyObject( BPy_PartSys * py_obj )
432 {
433         BPy_PartSys *blen_obj;
434
435         blen_obj = ( BPy_PartSys * ) py_obj;
436         return ( blen_obj->psys );
437 }
438
439 /*****************************************************************************/
440 /* Function : ParticleSysCreatePyObject                                            */
441 /*****************************************************************************/
442 PyObject *ParticleSys_CreatePyObject( ParticleSystem * psystem, Object *ob )
443 {
444         BPy_PartSys *blen_object;
445
446         blen_object =
447                 ( BPy_PartSys * ) PyObject_NEW( BPy_PartSys, &ParticleSys_Type );
448
449         if( blen_object )
450                 blen_object->psys = (ParticleSystem *)psystem;
451
452         blen_object->object = ob;
453
454         return ( PyObject * ) blen_object;
455 }
456
457
458 PyObject *M_ParticleSys_New( PyObject * self, PyObject * args ){
459         ParticleSystem *psys = 0;
460         ParticleSystem *rpsys = 0;
461         ModifierData *md;
462         ParticleSystemModifierData *psmd;
463         Object *ob = NULL;
464         char *name = NULL;
465         ID *id;
466         int nr;
467
468         if( !PyArg_ParseTuple( args, "s", &name ) )
469                 return EXPP_ReturnPyObjError( PyExc_TypeError,
470                         "expected string argument" );
471
472         for( ob = G.main->object.first; ob; ob = ob->id.next )
473                 if( !strcmp( name, ob->id.name + 2 ) )
474                         break;
475
476         if( !ob )
477                 return EXPP_ReturnPyObjError( PyExc_AttributeError, 
478                         "object does not exist" );
479
480         id = (ID *)psys_new_settings("PSys", G.main);
481
482         psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
483         psys->pointcache = BKE_ptcache_add();
484         psys->flag |= PSYS_ENABLED;
485         BLI_addtail(&ob->particlesystem,psys);
486
487         md = modifier_new(eModifierType_ParticleSystem);
488         sprintf(md->name, "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
489         psmd = (ParticleSystemModifierData*) md;
490         psmd->psys=psys;
491         BLI_addtail(&ob->modifiers, md);
492
493         psys->part=(ParticleSettings*)id;
494         psys->totpart=0;
495         psys->flag=PSYS_ENABLED|PSYS_CURRENT;
496         psys->cfra=bsystem_time(ob,(float)G.scene->r.cfra+1,0.0);
497         rpsys = psys;
498
499         /* check need for dupliobjects */
500
501         nr=0;
502         for(psys=ob->particlesystem.first; psys; psys=psys->next){
503                 if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
504                         nr++;
505         }
506         if(nr)
507                 ob->transflag |= OB_DUPLIPARTS;
508         else
509                 ob->transflag &= ~OB_DUPLIPARTS;
510
511         BIF_undo_push("Browse Particle System");
512
513         DAG_scene_sort(G.scene);
514         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
515
516         return ParticleSys_CreatePyObject(rpsys,ob);
517 }
518
519
520 /* 
521
522 Get( name ) returns named particle sys or list of all
523 throws NameError if name not found
524
525 */
526
527 PyObject *M_ParticleSys_Get( PyObject * self, PyObject * args ) 
528 {
529         ParticleSettings *psys_iter;
530         char *name = NULL;
531 #if 0
532
533         ParticleSystem *blparticlesys = 0;
534         Object *ob;
535
536         PyObject *partsyslist,*current;
537 #endif
538         if( !PyArg_ParseTuple( args, "|s", &name ) )
539                 return EXPP_ReturnPyObjError( PyExc_TypeError,
540                                 "expected string argument" );
541
542         psys_iter = G.main->particle.first; /* initialize our iterator */
543
544         if( name ) {   /* find psys by name */
545
546                 PyObject *wanted_obj = NULL;
547         
548                 while( psys_iter && ! wanted_obj ){
549                         if( !strcmp( name, psys_iter->id.name + 2)){
550                                 printf("** found %s\n", psys_iter->id.name+2);
551                                 //wanted_obj = ParticleSys_CreatePyObject( psys_iter );
552                                 break;
553                         }
554                         psys_iter = psys_iter->id.next;
555                 }
556
557                 if( !wanted_obj){  /* requested object not found */
558                         char error_msg[64];
559                         PyOS_snprintf( error_msg, sizeof( error_msg ),
560                                                    "Particle System '%s' not found", name);
561                         return EXPP_ReturnPyObjError( PyExc_NameError, error_msg );
562                 }
563
564                 return wanted_obj;
565
566         }else {  /* no arg - return a list of bpy objs all P. systems */
567
568                 PyObject *pylist;
569                 int index = 0;
570
571                 pylist = PyList_New( BLI_countlist( &G.main->particle ));
572                 printf("** list is %d long\n", PyList_Size( pylist));
573                 if( ! pylist ){
574                         return EXPP_ReturnPyObjError( 
575                                 PyExc_MemoryError,
576                                 "could not create ParticleSystem list");
577                 }
578                 
579                 while( psys_iter ){
580 #if 0
581                         pyobj = ParticleSystem_CreatePyObject( psys_iter);
582                         if( !pyobj){
583                                 Py_DECREF( pylist );
584                                 return EXPP_ReturnPyObjError(
585                                         PyExc_MemoryError, 
586                                         "could not create ParticleSystem PyObject");
587                         }
588                         PyList_SET_ITEM( pylist, index, pyobj);
589 #endif
590                         printf("name is %s\n", psys_iter->id.name+2);
591                         psys_iter = psys_iter->id.next;
592                         index++;
593                 }
594
595                 return pylist;
596                         
597         }
598                         
599                 
600
601 #if 0
602
603         for( ob = G.main->particlesystem.first; ob; ob = ob->id.next )
604                 if( !strcmp( name, ob->id.name + 2 ) )
605                         break;
606
607         if( !ob )
608                 return EXPP_ReturnPyObjError( PyExc_AttributeError, 
609                                 "object does not exist" );
610
611         blparticlesys = ob->particlesystem.first;
612         
613
614         partsyslist = PyList_New( 0 );
615
616         if (!blparticlesys)
617                 return partsyslist;
618
619         current = ParticleSys_CreatePyObject( blparticlesys, ob );
620         PyList_Append(partsyslist,current);
621
622
623         while((blparticlesys = blparticlesys->next)){
624                 current = ParticleSys_CreatePyObject( blparticlesys, ob );
625                 PyList_Append(partsyslist,current);
626         }
627
628         return partsyslist;
629
630 #endif
631 }
632
633
634 /*****************************************************************************/
635 /* Function:              ParticleSys_Init                                   */
636 /*****************************************************************************/
637
638 /* create the Blender.Particle.Type constant dict */
639
640 static PyObject *Particle_TypeDict( void )
641 {
642         PyObject *Types = PyConstant_New(  );
643
644         if( Types ) {
645                 BPy_constant *c = ( BPy_constant * ) Types;
646
647                 PyConstant_Insert( c, "HAIR",
648                                  PyInt_FromLong( 2 ) );
649                 PyConstant_Insert( c, "REACTOR",
650                                  PyInt_FromLong( 1 ) );
651                 PyConstant_Insert( c, "EMITTER",
652                                  PyInt_FromLong( 0 ) );
653         }
654         return Types;
655 }
656
657 /* create the Blender.Particle.Distribution constant dict */
658
659 static PyObject *Particle_DistrDict( void )
660 {
661         PyObject *Distr = PyConstant_New(  );
662
663         if( Distr ) {
664                 BPy_constant *c = ( BPy_constant * ) Distr;
665
666                 PyConstant_Insert( c, "GRID",
667                                  PyInt_FromLong( 2 ) );
668                 PyConstant_Insert( c, "RANDOM",
669                                  PyInt_FromLong( 1 ) );
670                 PyConstant_Insert( c, "JITTERED",
671                                  PyInt_FromLong( 0 ) );
672         }
673         return Distr;
674 }
675
676 /* create the Blender.Particle.EmitFrom constant dict */
677
678 static PyObject *Particle_EmitFrom( void )
679 {
680         PyObject *EmitFrom = PyConstant_New(  );
681
682         if( EmitFrom ) {
683                 BPy_constant *c = ( BPy_constant * ) EmitFrom;
684
685                 PyConstant_Insert( c, "VERTS",
686                                  PyInt_FromLong( 0 ) );
687                 PyConstant_Insert( c, "FACES",
688                                  PyInt_FromLong( 1 ) );
689                 PyConstant_Insert( c, "VOLUME",
690                                  PyInt_FromLong( 2 ) );
691                 PyConstant_Insert( c, "PARTICLE",
692                                  PyInt_FromLong( 3 ) );
693         }
694         return EmitFrom;
695 }
696
697 /* create the Blender.Particle.Collision constant dict */
698
699 static PyObject *Particle_ReactOnDict( void )
700 {
701         PyObject *ReactOn = PyConstant_New(  );
702
703         if( ReactOn ) {
704                 BPy_constant *c = ( BPy_constant * ) ReactOn;
705
706                 PyConstant_Insert( c, "NEAR",
707                                  PyInt_FromLong( 2 ) );
708                 PyConstant_Insert( c, "COLLISION",
709                                  PyInt_FromLong( 1 ) );
710                 PyConstant_Insert( c, "DEATH",
711                                  PyInt_FromLong( 0 ) );
712         }
713         return ReactOn;
714 }
715
716 static PyObject *Particle_DrawAs( void )
717 {
718         PyObject *DrawAs = PyConstant_New(  );
719
720         if( DrawAs ) {
721                 BPy_constant *c = ( BPy_constant * ) DrawAs;
722
723                 PyConstant_Insert( c, "NONE",
724                                  PyInt_FromLong( 0 ) );
725                 PyConstant_Insert( c, "POINT",
726                                  PyInt_FromLong( 1 ) );
727                 PyConstant_Insert( c, "CIRCLE",
728                                  PyInt_FromLong( 2 ) );
729                 PyConstant_Insert( c, "CROSS",
730                                  PyInt_FromLong( 3 ) );
731                 PyConstant_Insert( c, "AXIS",
732                                  PyInt_FromLong( 4 ) );
733                 PyConstant_Insert( c, "LINE",
734                                  PyInt_FromLong( 5 ) );
735                 PyConstant_Insert( c, "PATH",
736                                  PyInt_FromLong( 6 ) );
737                 PyConstant_Insert( c, "OBJECT",
738                                  PyInt_FromLong( 7 ) );
739                 PyConstant_Insert( c, "GROUP",
740                                  PyInt_FromLong( 8 ) );
741                 PyConstant_Insert( c, "BILLBOARD",
742                                  PyInt_FromLong( 9 ) );
743         }
744         return DrawAs;
745 }
746
747 void Particle_Recalc(BPy_PartSys* self,int child){
748         psys_flush_settings(self->psys->part,0,child );
749 }
750
751 void Particle_RecalcPsys_distr(BPy_PartSys* self,int child){
752         psys_flush_settings(self->psys->part,PSYS_DISTR,child);
753 }
754
755 PyObject *ParticleSys_Init( void ){
756         PyObject *submodule;
757         PyObject *Types;
758         PyObject *React;
759         PyObject *EmitFrom;
760         PyObject *Dist;
761         PyObject *DrawAs;
762
763         if( PyType_Ready( &ParticleSys_Type ) < 0)
764                 return NULL;
765
766         Types = Particle_TypeDict ();
767         React = Particle_ReactOnDict();
768         EmitFrom = Particle_EmitFrom();
769         DrawAs = Particle_DrawAs();
770         Dist = Particle_DistrDict();
771
772         submodule = Py_InitModule3( "Blender.Particle", 
773                                                                 M_ParticleSys_methods, M_ParticleSys_doc );
774
775         if( Types )
776                 PyModule_AddObject( submodule, "TYPE", Types );
777         if( React )
778                 PyModule_AddObject( submodule, "REACTON", React );
779         if( EmitFrom )
780                 PyModule_AddObject( submodule, "EMITFROM", EmitFrom );
781         if( Dist )
782                 PyModule_AddObject( submodule, "DISTRIBUTION", Dist );
783         if( DrawAs )
784                 PyModule_AddObject( submodule, "DRAWAS", DrawAs );
785
786         return ( submodule );
787 }
788
789 static PyObject *Part_freeEdit( BPy_PartSys * self, PyObject * args ){
790
791         if(self->psys->flag & PSYS_EDITED){
792                 if(self->psys->edit)
793                         PE_free_particle_edit(self->psys);
794
795                 self->psys->flag &= ~PSYS_EDITED;
796                 self->psys->recalc |= PSYS_RECALC_HAIR;
797
798                 DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA);
799         }
800         Py_RETURN_NONE;
801 }
802
803 static PyObject *Part_GetLoc( BPy_PartSys * self, PyObject * args )
804 {
805         ParticleSystem *psys = 0L;
806         Object *ob = 0L;
807         PyObject *partlist,*seglist;
808         ParticleCacheKey **cache,*path;
809         PyObject* loc = 0L;
810         ParticleKey state;
811         DerivedMesh* dm;
812         float cfra;
813         int i,j,k;
814         float vm[4][4],wm[4][4];
815         int     childexists = 0;
816         int all = 0;
817         int id = 0;
818
819         cfra = bsystem_time(ob,(float)CFRA,0.0);
820
821         if( !PyArg_ParseTuple( args, "|ii", &all,&id ) )
822                 return EXPP_ReturnPyObjError( PyExc_TypeError,
823                                 "expected two optional integers as arguments" );
824
825         psys = self->psys;
826         ob = self->object;
827         
828         if (!ob || !psys)
829                 Py_RETURN_NONE;
830
831         G.rendering = 1;
832
833         /* Just to create a valid rendering context */
834         psys_render_set(ob,psys,vm,wm,0,0,0);
835
836         dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
837         dm->release(dm);
838
839         if ( !psys_check_enabled(ob,psys) ){
840                 G.rendering = 0;
841                 psys_render_restore(ob,psys);
842                 Particle_Recalc(self,1);
843                 Py_RETURN_NONE;
844         }
845
846         partlist = PyList_New( 0 );
847         if( !partlist ){
848                 PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
849                 goto error;
850         }
851
852         if (psys->part->type == PART_HAIR){
853                 cache = psys->pathcache;
854
855                 if ( ((self->psys->part->draw & PART_DRAW_PARENT) && (self->psys->part->childtype != 0)) || (self->psys->part->childtype == 0) ){
856
857                         for(i = 0; i < psys->totpart; i++){
858                                 seglist = PyList_New( 0 );
859                                 if (!seglist){
860                                         PyErr_SetString( PyExc_MemoryError,
861                                                         "PyList_New() failed" );
862                                         goto error;
863                                 }
864
865                                 path=cache[i];
866                                 k = path->steps+1;
867                                 for( j = 0; j < k ; j++, path++){
868                                         loc = Py_BuildValue("(fff)",(double)path->co[0],
869                                                         (double)path->co[1], (double)path->co[2]);
870
871                                         if (!loc){
872                                                 PyErr_SetString( PyExc_RuntimeError,
873                                                                 "Couldn't build tuple" );
874                                                 goto error;
875                                         }
876
877                                         if ( (PyList_Append(seglist,loc) < 0) ){
878                                                 PyErr_SetString( PyExc_RuntimeError,
879                                                                 "Couldn't append item to PyList" );
880                                                 goto error;
881                                         }
882                                         Py_DECREF(loc); /* PyList_Append increfs */
883                                         loc = NULL;
884                                 }
885
886                                 if ( PyList_Append(partlist,seglist) < 0 ){
887                                         PyErr_SetString( PyExc_RuntimeError,
888                                                         "Couldn't append item to PyList" );             
889                                         goto error;
890                                 }
891                                 Py_DECREF(seglist); /* PyList_Append increfs */
892                                 seglist = NULL;
893                         }
894                 }
895
896                 cache=psys->childcache;
897
898                 for(i = 0; i < psys->totchild; i++){
899                         seglist = PyList_New( 0 );
900                         if (!seglist){
901                                 PyErr_SetString( PyExc_MemoryError,
902                                                 "PyList_New() failed" );
903                                 goto error;
904                         }
905
906                         path=cache[i];
907                         k = path->steps+1;
908                         for( j = 0; j < k ; j++, path++ ){
909                                 loc = Py_BuildValue("(fff)",(double)path->co[0],
910                                                 (double)path->co[1], (double)path->co[2]);
911
912                                 if (!loc){
913                                         PyErr_SetString( PyExc_RuntimeError,
914                                                         "Couldn't build tuple" );
915                                         goto error;
916                                 }
917
918                                 if ( PyList_Append(seglist,loc) < 0){
919                                         PyErr_SetString( PyExc_RuntimeError,
920                                                         "Couldn't append item to PyList" );
921                                         goto error;
922                                 }
923                                 Py_DECREF(loc);/* PyList_Append increfs */
924                                 loc = NULL;
925                         }
926
927                         if ( PyList_Append(partlist,seglist) < 0){
928                                 PyErr_SetString( PyExc_RuntimeError,
929                                                 "Couldn't append item to PyList" );     
930                                 goto error;
931                         }
932                         Py_DECREF(seglist); /* PyList_Append increfs */
933                         seglist = NULL;
934                 }
935         } else {
936                 int init;
937                 char *fmt = NULL;
938
939                 if(id)
940                         fmt = "(fffi)";
941                 else
942                         fmt = "(fff)";
943
944                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
945                         childexists = 1;
946
947                 for (i = 0; i < psys->totpart + psys->totchild; i++){
948                         if (childexists && (i < psys->totpart))
949                                 continue;
950
951                         state.time = cfra;
952                         if(psys_get_particle_state(ob,psys,i,&state,0)==0)
953                                 init = 0;
954                         else
955                                 init = 1;
956
957                         if (init){
958                                 loc = Py_BuildValue(fmt,(double)state.co[0],
959                                                 (double)state.co[1], (double)state.co[2],i);
960                                 
961                                 if (!loc){
962                                         PyErr_SetString( PyExc_RuntimeError,
963                                                         "Couldn't build tuple" );
964                                         goto error;
965                                 }
966
967                                 if ( PyList_Append(partlist,loc) < 0 ){
968                                         PyErr_SetString( PyExc_RuntimeError,
969                                                         "Couldn't append item to PyList" );
970                                         goto error;
971                                 }
972                                 Py_DECREF(loc);
973                                 loc = NULL;
974                         } else {
975                                 if ( all && PyList_Append(partlist,Py_None) < 0 ){
976                                         PyErr_SetString( PyExc_RuntimeError,
977                                                         "Couldn't append item to PyList" );
978                                         goto error;
979                                 }
980                         }
981                 }
982         }
983
984         psys_render_restore(ob,psys);
985         G.rendering = 0;
986         Particle_Recalc(self,1);
987         return partlist;
988
989 error:
990         Py_XDECREF(partlist);
991         Py_XDECREF(seglist);
992         Py_XDECREF(loc);
993         psys_render_restore(ob,psys);
994         G.rendering = 0;
995         Particle_Recalc(self,1);
996         return NULL;
997 }
998
999 static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args )
1000 {
1001         ParticleSystem *psys = 0L;
1002         Object *ob = 0L;
1003         PyObject *partlist = 0L;
1004         PyObject* loc = 0L;
1005         ParticleKey state;
1006         DerivedMesh* dm;
1007         float vm[4][4],wm[4][4];
1008         int i;
1009         int childexists = 0;
1010         int all = 0;
1011         int id = 0;
1012     char *fmt = NULL;
1013
1014         float cfra=bsystem_time(ob,(float)CFRA,0.0);
1015
1016         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
1017                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1018                                 "expected two optional integers as arguments" );
1019
1020         psys = self->psys;
1021         ob = self->object;
1022         
1023         if (!ob || !psys)
1024                 Py_RETURN_NONE;
1025
1026         G.rendering = 1;
1027
1028         /* Just to create a valid rendering context */
1029         psys_render_set(ob,psys,vm,wm,0,0,0);
1030
1031         dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
1032         dm->release(dm);
1033
1034         if ( !psys_check_enabled(ob,psys) ){
1035                 G.rendering = 0;
1036                 psys_render_restore(ob,psys);
1037                 Particle_Recalc(self,1);
1038                 Py_RETURN_NONE;
1039         }
1040
1041         if (psys->part->type != PART_HAIR){
1042                 partlist = PyList_New( 0 );
1043
1044                 if( !partlist ){
1045                         PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
1046                         goto error;
1047                 }
1048
1049                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
1050                         childexists = 1;
1051
1052                 if(id)
1053                         fmt = "(ffffi)";
1054                 else
1055                         fmt = "(ffff)";
1056
1057                 for (i = 0; i < psys->totpart + psys->totchild; i++){
1058                         if (childexists && (i < psys->totpart))
1059                                 continue;
1060
1061                         state.time = cfra;
1062                         if(psys_get_particle_state(ob,psys,i,&state,0)==0){
1063                                 if ( all && PyList_Append(partlist,Py_None) < 0){
1064                                         PyErr_SetString( PyExc_RuntimeError,
1065                                                 "Couldn't append item to PyList" );
1066                                         goto error;
1067                                 }
1068                         } else {
1069                                 loc = Py_BuildValue(fmt,(double)state.rot[0], (double)state.rot[1],
1070                                                 (double)state.rot[2], (double)state.rot[3], i);
1071
1072                                 if (!loc){
1073                                         PyErr_SetString( PyExc_RuntimeError,
1074                                                         "Couldn't build tuple" );
1075                                         goto error;
1076                                 }
1077                                 if (PyList_Append(partlist,loc) < 0){
1078                                         PyErr_SetString ( PyExc_RuntimeError,
1079                                                         "Couldn't append item to PyList" );
1080                                         goto error;
1081                                 }
1082                                 Py_DECREF(loc); /* PyList_Append increfs */
1083                                 loc = NULL;
1084                         }
1085                 }
1086         } else {
1087                 partlist = EXPP_incr_ret( Py_None );
1088         }
1089
1090         psys_render_restore(ob,psys);
1091         G.rendering = 0;
1092         Particle_Recalc(self,1);
1093         return partlist;
1094
1095 error:
1096         Py_XDECREF(partlist);
1097         Py_XDECREF(loc);
1098         psys_render_restore(ob,psys);
1099         G.rendering = 0;
1100         Particle_Recalc(self,1);
1101         return NULL;
1102 }
1103
1104 static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args )
1105 {
1106         ParticleKey state;
1107         ParticleSystem *psys = 0L;
1108         ParticleData *data;
1109         Object *ob = 0L;
1110         PyObject *partlist,*tuple;
1111         DerivedMesh* dm;
1112         float vm[4][4],wm[4][4];
1113         float size;
1114         int i;
1115         int childexists = 0;
1116         int all = 0;
1117         int id = 0;
1118     char *fmt = NULL;
1119
1120         float cfra=bsystem_time(ob,(float)CFRA,0.0);
1121
1122         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
1123                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1124                                 "expected two optional integers as arguments" );
1125
1126         psys = self->psys;
1127         ob = self->object;
1128         
1129         if (!ob || !psys)
1130                 Py_RETURN_NONE;
1131
1132         G.rendering = 1;
1133
1134         /* Just to create a valid rendering context */
1135         psys_render_set(ob,psys,vm,wm,0,0,0);
1136
1137         dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
1138         dm->release(dm);
1139         data = self->psys->particles;
1140
1141         if ( !psys_check_enabled(ob,psys) ){
1142                 psys_render_restore(ob,psys);
1143                 G.rendering = 0;
1144                 Particle_Recalc(self,1);
1145                 Py_RETURN_NONE;
1146         }
1147
1148         partlist = PyList_New( 0 );
1149
1150         if( !partlist ){
1151                 PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
1152                 goto error;
1153         }
1154
1155         if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
1156                 childexists = 1;
1157
1158         if(id)
1159                 fmt = "(fi)";
1160         else
1161                 fmt = "f";
1162
1163         for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
1164                 if (psys->part->type != PART_HAIR){
1165                         if (childexists && (i < psys->totpart))
1166                                 continue;
1167
1168                         if ( !all ){
1169                                 state.time = cfra;
1170                                 if(psys_get_particle_state(ob,psys,i,&state,0)==0)
1171                                         continue;
1172                         }
1173
1174                         if (i < psys->totpart){
1175                                 size = data->size;
1176                         } else {
1177                                 ChildParticle *cpa= &psys->child[i-psys->totpart];
1178                                 size = psys_get_child_size(psys,cpa,cfra,0);
1179                         }
1180
1181                         tuple = Py_BuildValue(fmt,(double)size,i);
1182
1183                         if (!tuple){
1184                                 PyErr_SetString( PyExc_RuntimeError,
1185                                                 "Couldn't build tuple" );
1186                                 goto error;
1187                         }
1188
1189                         if (PyList_Append(partlist,tuple) < 0){
1190                                 PyErr_SetString( PyExc_RuntimeError,
1191                                                 "Couldn't append item to PyList" );
1192                                 goto error;
1193                         }
1194                         Py_DECREF(tuple);
1195                         tuple = NULL;
1196                 }
1197         }
1198
1199         psys_render_restore(ob,psys);
1200         G.rendering = 0;
1201         Particle_Recalc(self,1);
1202         return partlist;
1203
1204 error:
1205         Py_XDECREF(partlist);
1206         Py_XDECREF(tuple);
1207         psys_render_restore(ob,psys);
1208         G.rendering = 0;
1209         Particle_Recalc(self,1);
1210         return NULL;
1211 }
1212
1213
1214 static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args )
1215 {
1216         ParticleKey state;
1217         ParticleSystem *psys = 0L;
1218         ParticleData *data;
1219         Object *ob = 0L;
1220         PyObject *partlist,*tuple;
1221         DerivedMesh* dm;
1222         float vm[4][4],wm[4][4];
1223         float life;
1224         int i;
1225         int childexists = 0;
1226         int all = 0;
1227         int id = 0;
1228         char *fmt = NULL;
1229
1230         float cfra=bsystem_time(ob,(float)CFRA,0.0);
1231
1232         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
1233                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1234                                 "expected two optional integers as arguments" );
1235
1236         psys = self->psys;
1237         ob = self->object;
1238         
1239         if (!ob || !psys)
1240                 Py_RETURN_NONE;
1241
1242         G.rendering = 1;
1243
1244         /* Just to create a valid rendering context */
1245         psys_render_set(ob,psys,vm,wm,0,0,0);
1246
1247         dm = mesh_create_derived_render(ob,CD_MASK_BAREMESH|CD_MASK_MTFACE|CD_MASK_MCOL);
1248         dm->release(dm);
1249         data = self->psys->particles;
1250
1251         if ( !psys_check_enabled(ob,psys) ){
1252                 psys_render_restore(ob,psys);
1253                 G.rendering = 0;
1254                 Py_RETURN_NONE;
1255         }
1256
1257         partlist = PyList_New( 0 );
1258         if( !partlist ){
1259                 PyErr_SetString( PyExc_MemoryError, "PyList_New() failed" );
1260                 goto error;
1261         }
1262
1263         if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
1264                 childexists = 1;
1265
1266         if(id)
1267                 fmt = "(fi)";
1268         else
1269                 fmt = "f";
1270
1271         for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
1272                 if (psys->part->type != PART_HAIR){
1273
1274                         if (childexists && (i < psys->totpart))
1275                                 continue;
1276
1277                         if ( !all ){
1278                                 state.time = cfra;
1279                                 if(psys_get_particle_state(ob,psys,i,&state,0)==0)
1280                                         continue;
1281                         }
1282
1283                         if (i < psys->totpart){
1284                                 life = (cfra-data->time)/data->lifetime;
1285                         } else {
1286                                 ChildParticle *cpa= &psys->child[i-psys->totpart];
1287                                 life = psys_get_child_time(psys,cpa,cfra);
1288                         }
1289
1290                         tuple = Py_BuildValue(fmt,(double)life,i);
1291
1292                         if (!tuple){
1293                                 PyErr_SetString( PyExc_RuntimeError,
1294                                                 "Couldn't build tuple" );
1295                                 goto error;
1296                         }
1297
1298                         if (PyList_Append(partlist,tuple) < 0){
1299                                 PyErr_SetString( PyExc_RuntimeError,
1300                                                 "Couldn't append item to PyList" );
1301                                 goto error;
1302                         }
1303                         Py_DECREF(tuple);
1304                         tuple = NULL;
1305                 }
1306         }
1307
1308         psys_render_restore(ob,psys);
1309         G.rendering = 0;
1310         Particle_Recalc(self,1);
1311         return partlist;
1312
1313 error:
1314         Py_XDECREF(partlist);
1315         Py_XDECREF(tuple);
1316         psys_render_restore(ob,psys);
1317         G.rendering = 0;
1318         Particle_Recalc(self,1);
1319         return NULL;
1320 }
1321
1322
1323 static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ){
1324         Material *ma;
1325         PyObject* mat = 0L;
1326         ma = give_current_material(self->object,self->psys->part->omat);
1327         if(!ma)
1328                 Py_RETURN_NONE;
1329
1330         mat = Material_CreatePyObject(ma);
1331         return mat;
1332 }
1333
1334
1335 /*****************************************************************************/
1336 /* Function:              Set/Get Seed                                       */
1337 /*****************************************************************************/
1338
1339 static int Part_setSeed( BPy_PartSys * self, PyObject * args )
1340 {
1341         return EXPP_setIValueRange( args, &self->psys->seed,
1342                         0, 255, 'i' );
1343 }
1344
1345 static PyObject *Part_getSeed( BPy_PartSys * self )
1346 {
1347         return PyInt_FromLong( (long)( self->psys->seed ) );
1348 }
1349
1350 static int Part_setType( BPy_PartSys * self, PyObject * args )
1351 {
1352         int res = EXPP_setIValueRange( args, &self->psys->part->type,
1353                         0, 2, 'h' );
1354
1355         psys_flush_settings( self->psys->part, PSYS_TYPE, 1 );
1356
1357         return res;
1358 }
1359
1360 static PyObject *Part_getType( BPy_PartSys * self )
1361 {
1362         return PyInt_FromLong( (short)( self->psys->part->type ) );
1363 }
1364
1365 static int Part_setResol( BPy_PartSys * self, PyObject * args )
1366 {
1367         int res = EXPP_setIValueRange( args, &self->psys->part->grid_res,
1368                         0, 100, 'i' );
1369
1370         psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
1371
1372         return res;
1373 }
1374
1375 static PyObject *Part_getResol( BPy_PartSys * self )
1376 {
1377         return PyInt_FromLong( ((int)( self->psys->part->grid_res )) );
1378 }
1379
1380 static int Part_setStart( BPy_PartSys * self, PyObject * args )
1381 {
1382         int res = EXPP_setFloatRange( args, &self->psys->part->sta,
1383                         0.0f, 100000.0f );
1384
1385         psys_flush_settings(self->psys->part,PSYS_INIT,1);
1386
1387         return res;
1388 }
1389
1390 static PyObject *Part_getStart( BPy_PartSys * self )
1391 {
1392         return PyFloat_FromDouble( (float)( self->psys->part->sta ) );
1393 }
1394
1395 static int Part_setEnd( BPy_PartSys * self, PyObject * args )
1396 {
1397         int res = EXPP_setFloatRange( args, &self->psys->part->end,
1398                         0.0f, 100000.0f );
1399
1400         psys_flush_settings(self->psys->part,PSYS_INIT,1);
1401
1402         return res;
1403 }
1404
1405 static PyObject *Part_getEnd( BPy_PartSys * self )
1406 {
1407         return PyFloat_FromDouble( (long)( self->psys->part->end ) );
1408 }
1409
1410 static int Part_setEditable( BPy_PartSys * self, PyObject * args )
1411 {
1412         int number;
1413
1414         if( !PyInt_Check( args ) ) {
1415                 char errstr[128];
1416                 sprintf ( errstr, "expected int argument" );
1417                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1418         }
1419
1420         number = PyInt_AS_LONG( args );
1421
1422         if(!number){
1423                 if(self->psys->edit)
1424                         PE_free_particle_edit(self->psys);
1425
1426                 self->psys->flag &= ~PSYS_EDITED;
1427                 self->psys->recalc |= PSYS_RECALC_HAIR;
1428
1429                 DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA);
1430         }
1431         else
1432         {
1433                 self->psys->flag |= PSYS_EDITED;
1434                 if(G.f & G_PARTICLEEDIT)
1435                         PE_create_particle_edit(self->object, self->psys);
1436         }
1437
1438         return 0;
1439 }
1440
1441 static PyObject *Part_getEditable( BPy_PartSys * self )
1442 {
1443         return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0  );
1444 }
1445
1446 static int Part_setAmount( BPy_PartSys * self, PyObject * args )
1447 {
1448         int res = EXPP_setIValueRange( args, &self->psys->part->totpart,
1449                         0, 100000, 'i' );
1450
1451         psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
1452
1453         return res;
1454 }
1455
1456 static PyObject *Part_getAmount( BPy_PartSys * self )
1457 {
1458         return PyInt_FromLong( ((int)( self->psys->part->totpart )) );
1459 }
1460
1461 static int Part_setMultiReact( BPy_PartSys * self, PyObject * args )
1462 {
1463         int number;
1464
1465         if( !PyInt_Check( args ) ) {
1466                 char errstr[128];
1467                 sprintf ( errstr, "expected int argument" );
1468                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1469         }
1470
1471         number = PyInt_AS_LONG( args );
1472
1473
1474         if (number){
1475                 self->psys->part->flag |= PART_REACT_MULTIPLE;
1476         }else{
1477                 self->psys->part->flag &= ~PART_REACT_MULTIPLE;
1478         }
1479
1480         Particle_Recalc(self,1);
1481
1482         return 0;
1483 }
1484
1485 static PyObject *Part_getMultiReact( BPy_PartSys * self )
1486 {
1487         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 );
1488 }
1489
1490 static int Part_setReactShape( BPy_PartSys * self, PyObject * args )
1491 {
1492         int res = EXPP_setFloatRange( args, &self->psys->part->reactshape,
1493                         0.0f, 10.0f );
1494
1495         Particle_Recalc(self,1);
1496
1497         return res;
1498 }
1499
1500 static PyObject *Part_getReactShape( BPy_PartSys * self )
1501 {
1502         return PyFloat_FromDouble( ((double)( self->psys->part->reactshape )) );
1503 }
1504
1505 static int Part_setSegments( BPy_PartSys * self, PyObject * args )
1506 {
1507         int res = EXPP_setIValueRange( args, &self->psys->part->hair_step,
1508                         2, 50, 'h' );
1509
1510         Particle_Recalc(self,1);
1511
1512         return res;
1513 }
1514
1515 static PyObject *Part_getSegments( BPy_PartSys * self )
1516 {
1517         return PyInt_FromLong( ((long)( self->psys->part->hair_step )) );
1518 }
1519
1520 static int Part_setLife( BPy_PartSys * self, PyObject * args )
1521 {
1522         int res = EXPP_setFloatRange( args, &self->psys->part->lifetime,
1523                         1.0f, MAXFRAMEF );
1524
1525         Particle_Recalc(self,1);
1526
1527         return res;
1528 }
1529
1530 static PyObject *Part_getLife( BPy_PartSys * self )
1531 {
1532         return PyFloat_FromDouble( ((double)( self->psys->part->lifetime )) );
1533 }
1534
1535 static int Part_setRandLife( BPy_PartSys * self, PyObject * args )
1536 {
1537         int res = EXPP_setFloatRange( args, &self->psys->part->randlife,
1538                         0.0f, 2.0f );
1539
1540         Particle_Recalc(self,1);
1541
1542         return res;
1543 }
1544
1545 static PyObject *Part_getRandLife( BPy_PartSys * self )
1546 {
1547         return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) );
1548 }
1549
1550 static int Part_set2d( BPy_PartSys * self, PyObject * args )
1551 {
1552         int number;
1553
1554         if( !PyInt_Check( args ) )
1555                 return EXPP_ReturnIntError( PyExc_TypeError, "expected int argument" );
1556
1557         number = PyInt_AS_LONG( args );
1558
1559         if (number){
1560                 self->psys->part->flag |= PART_BOIDS_2D;
1561         }else{
1562                 self->psys->part->flag &= ~PART_BOIDS_2D;
1563         }
1564
1565         Particle_Recalc(self,1);
1566
1567         return 0;
1568 }
1569
1570 static PyObject *Part_get2d( BPy_PartSys * self )
1571 {
1572         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 );
1573 }
1574
1575 static int Part_setMaxVel( BPy_PartSys * self, PyObject * args )
1576 {
1577         int res = EXPP_setFloatRange( args, &self->psys->part->max_vel,
1578                         0.0f, 200.0f );
1579
1580         Particle_Recalc(self,1);
1581
1582         return res;
1583 }
1584
1585 static PyObject *Part_getMaxVel( BPy_PartSys * self )
1586 {
1587         return PyFloat_FromDouble( ((double)( self->psys->part->max_vel )) );
1588 }
1589
1590 static int Part_setAvVel( BPy_PartSys * self, PyObject * args )
1591 {
1592         int res = EXPP_setFloatRange( args, &self->psys->part->average_vel,
1593                         0.0f, 1.0f );
1594
1595         Particle_Recalc(self,1);
1596
1597         return res;
1598 }
1599
1600 static PyObject *Part_getAvVel( BPy_PartSys * self )
1601 {
1602         return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) );
1603 }
1604
1605 static int Part_setLatAcc( BPy_PartSys * self, PyObject * args )
1606 {
1607         int res = EXPP_setFloatRange( args, &self->psys->part->max_lat_acc,
1608                         0.0f, 1.0f );
1609
1610         Particle_Recalc(self,1);
1611
1612         return res;
1613 }
1614
1615 static PyObject *Part_getLatAcc( BPy_PartSys * self )
1616 {
1617         return PyFloat_FromDouble( ((double)( self->psys->part->max_lat_acc )) );
1618 }
1619
1620 static int Part_setMaxTan( BPy_PartSys * self, PyObject * args )
1621 {
1622         int res = EXPP_setFloatRange( args, &self->psys->part->max_tan_acc,
1623                         0.0f, 1.0f );
1624
1625         Particle_Recalc(self,1);
1626
1627         return res;
1628 }
1629
1630 static PyObject *Part_getMaxTan( BPy_PartSys * self )
1631 {
1632         return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) );
1633 }
1634
1635 static int Part_setGroundZ( BPy_PartSys * self, PyObject * args )
1636 {
1637         int res = EXPP_setFloatRange( args, &self->psys->part->groundz,
1638                         -100.0f, 100.0f );
1639
1640         Particle_Recalc(self,1);
1641
1642         return res;
1643 }
1644
1645 static PyObject *Part_getGroundZ( BPy_PartSys * self )
1646 {
1647         return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) );
1648 }
1649
1650 static int Part_setOb( BPy_PartSys * self, PyObject * args )
1651 {
1652         Object *obj;
1653         if( !BPy_Object_Check( args ) ) {
1654                 char errstr[128];
1655                 sprintf ( errstr, "expected object argument" );
1656                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1657         }
1658
1659         obj = Object_FromPyObject(args);
1660
1661         self->psys->keyed_ob = obj;
1662
1663         return 0;
1664 }
1665
1666 static PyObject *Part_getOb( BPy_PartSys * self )
1667 {
1668         Object * obj;
1669         obj = self->psys->keyed_ob;
1670         if (!obj)
1671                 Py_RETURN_NONE;
1672
1673         return Object_CreatePyObject( obj );
1674 }
1675
1676 static int Part_setRandEmission( BPy_PartSys * self, PyObject * args )
1677 {
1678         int number;
1679
1680         if( !PyInt_Check( args ) ) {
1681                 char errstr[128];
1682                 sprintf ( errstr, "expected int argument" );
1683                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1684         }
1685
1686         number = PyInt_AS_LONG( args );
1687
1688         if (number){
1689                 self->psys->part->flag |= PART_TRAND;
1690         }else{
1691                 self->psys->part->flag &= ~PART_TRAND;
1692         }
1693
1694         Particle_RecalcPsys_distr(self,1);
1695
1696         return 0;
1697 }
1698
1699 static PyObject *Part_getRandEmission( BPy_PartSys * self )
1700 {
1701         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_TRAND )) > 0 );
1702 }
1703
1704 static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
1705 {
1706         int number;
1707         char errstr[128];
1708
1709         if( !PyInt_Check( args ) ) {
1710                 sprintf ( errstr, "expected int argument" );
1711                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1712         }
1713
1714         number = PyInt_AS_LONG( args );
1715
1716         if (number < 0 || number > 3){
1717                 sprintf ( errstr, "expected int argument between 0 - 3" );
1718                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1719         }
1720
1721         self->psys->part->from = (short)number;
1722
1723         Particle_RecalcPsys_distr(self,1);
1724
1725         return 0;
1726 }
1727
1728 static PyObject *Part_getParticleDist( BPy_PartSys * self )
1729 {
1730         return PyInt_FromLong( (long)( self->psys->part->from ) );
1731 }
1732
1733 static int Part_setEvenDist( BPy_PartSys * self, PyObject * args )
1734 {
1735         int number;
1736
1737         if( !PyInt_Check( args ) ) {
1738                 char errstr[128];
1739                 sprintf ( errstr, "expected int argument" );
1740                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1741         }
1742
1743         number = PyInt_AS_LONG( args );
1744
1745         if (number){
1746                 self->psys->part->flag |= PART_EDISTR;
1747         }else{
1748                 self->psys->part->flag &= ~PART_EDISTR;
1749         }
1750
1751         Particle_RecalcPsys_distr(self,1);
1752
1753         return 0;
1754 }
1755
1756 static PyObject *Part_getEvenDist( BPy_PartSys * self )
1757 {
1758         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_EDISTR )) > 0 );
1759 }
1760
1761 static int Part_setDist( BPy_PartSys * self, PyObject * args )
1762 {
1763         int number;
1764         char errstr[128];
1765
1766         if( !PyInt_Check( args ) ) {
1767                 sprintf ( errstr, "expected int argument" );
1768                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1769         }
1770
1771         number = PyInt_AS_LONG( args );
1772
1773         if (number < 0 || number > 2){
1774                 sprintf ( errstr, "expected int argument between 0 - 2" );
1775                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1776         }
1777
1778         self->psys->part->distr = (short)number;
1779
1780         Particle_RecalcPsys_distr(self,1);
1781
1782         return 0;
1783 }
1784
1785 static PyObject *Part_getDist( BPy_PartSys * self )
1786 {
1787         return PyInt_FromLong( (long)( self->psys->part->distr ) );
1788 }
1789
1790 static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args )
1791 {
1792         int res = EXPP_setFloatRange( args, &self->psys->part->jitfac,
1793                         0.0f, 2.0f );
1794
1795         Particle_RecalcPsys_distr(self,1);
1796
1797         return res;
1798 }
1799
1800 static PyObject *Part_getJitterAmount( BPy_PartSys * self )
1801 {
1802         return PyFloat_FromDouble( ((double)( self->psys->part->jitfac )) );
1803 }
1804
1805
1806
1807 static int Part_setPF( BPy_PartSys * self, PyObject * args )
1808 {
1809         int res = EXPP_setIValueRange( args, &self->psys->part->userjit,
1810                         0, 1000, 'i' );
1811
1812         Particle_RecalcPsys_distr(self,1);
1813
1814         return res;
1815 }
1816
1817 static PyObject *Part_getPF( BPy_PartSys * self )
1818 {
1819         return PyInt_FromLong( ((short)( self->psys->part->userjit )) );
1820 }
1821
1822 static int Part_setInvert( BPy_PartSys * self, PyObject * args )
1823 {
1824         int number;
1825
1826         if( !PyInt_Check( args ) ) {
1827                 char errstr[128];
1828                 sprintf ( errstr, "expected int argument" );
1829                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1830         }
1831
1832         number = PyInt_AS_LONG( args );
1833
1834         if (number){
1835                 self->psys->part->flag |= PART_GRID_INVERT;
1836         }else{
1837                 self->psys->part->flag &= ~PART_GRID_INVERT;
1838         }
1839
1840         Particle_RecalcPsys_distr(self,1);
1841
1842         return 0;
1843 }
1844
1845 static PyObject *Part_getInvert( BPy_PartSys * self )
1846 {
1847         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_GRID_INVERT )) > 0 );
1848 }
1849
1850 static int Part_setTargetOb( BPy_PartSys * self, PyObject * args )
1851 {
1852         Object *obj;
1853         if( !BPy_Object_Check( args ) ) {
1854                 char errstr[128];
1855                 sprintf ( errstr, "expected object argument" );
1856                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1857         }
1858
1859         obj = Object_FromPyObject(args);
1860
1861         self->psys->target_ob = obj;
1862
1863         return 0;
1864 }
1865
1866 static PyObject *Part_getTargetOb( BPy_PartSys * self )
1867 {
1868         Object * obj;
1869         obj = self->psys->target_ob;
1870         if (!obj)
1871                 Py_RETURN_NONE;
1872
1873         return Object_CreatePyObject( obj );
1874 }
1875
1876
1877
1878 PyObject *Part_getDupOb( BPy_PartSys * self )
1879 {
1880         Object * obj;
1881         obj = self->psys->part->dup_ob;
1882         if (!obj)
1883                 Py_RETURN_NONE;
1884
1885         return Object_CreatePyObject( obj );
1886 }
1887
1888 static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){
1889         int tottpsys;
1890         int res;
1891         Object *tob=0;
1892         ParticleSystem *psys = self->psys;
1893         Object *ob;
1894
1895         ob = self->object;
1896
1897         if(psys->target_ob)
1898                 tob=psys->target_ob;
1899         else
1900                 tob=ob;
1901
1902         tottpsys = BLI_countlist(&tob->particlesystem);
1903
1904         res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' );
1905
1906         if( ( psys = psys_get_current(ob) ) ){
1907                 if(psys->keyed_ob==ob || psys->target_ob==ob){
1908                         if(psys->keyed_ob==ob)
1909                                 psys->keyed_ob=NULL;
1910                         else
1911                                 psys->target_ob=NULL;
1912                 }
1913                 else{
1914                         DAG_scene_sort(G.scene);
1915                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1916                 }
1917         }
1918
1919         return res;
1920 }
1921
1922 static PyObject *Part_getTargetPsys( BPy_PartSys * self ){
1923         return PyInt_FromLong( (short)( self->psys->target_psys ) );
1924 }
1925
1926 static int Part_setRenderObject( BPy_PartSys * self, PyObject * args )
1927 {
1928         int number,nr;
1929         ParticleSystem *psys = 0L;
1930
1931         if( !PyInt_Check( args ) ) {
1932                 char errstr[128];
1933                 sprintf ( errstr, "expected int argument" );
1934                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1935         }
1936
1937         number = PyInt_AS_LONG( args );
1938
1939         if (number){
1940                 self->psys->part->draw |= PART_DRAW_EMITTER;
1941         }else{
1942                 self->psys->part->draw &= ~PART_DRAW_EMITTER;
1943         }
1944
1945         /* check need for dupliobjects */
1946         nr=0;
1947         for(psys=self->object->particlesystem.first; psys; psys=psys->next){
1948                 if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
1949                         nr++;
1950         }
1951         if(nr)
1952                 self->object->transflag |= OB_DUPLIPARTS;
1953         else
1954                 self->object->transflag &= ~OB_DUPLIPARTS;
1955
1956         return 0;
1957 }
1958
1959 static PyObject *Part_getRenderObject( BPy_PartSys * self )
1960 {
1961         return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 0 );
1962 }
1963
1964 static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args )
1965 {
1966         int res = EXPP_setIValueRange( args, &self->psys->part->disp,
1967                         0, 100, 'i' );
1968
1969         Particle_Recalc(self,0);
1970
1971
1972         return res;
1973 }
1974
1975 static PyObject *Part_getParticleDisp( BPy_PartSys * self )
1976 {
1977         return PyInt_FromLong( ((short)( self->psys->part->disp )) );
1978 }
1979
1980 static int Part_setStep( BPy_PartSys * self, PyObject * args )
1981 {
1982         int res = EXPP_setIValueRange( args, &self->psys->part->draw_step,
1983                         0, 7, 'i' );
1984
1985         Particle_Recalc(self,1);
1986
1987
1988         return res;
1989 }
1990
1991 static PyObject *Part_getStep( BPy_PartSys * self )
1992 {
1993         return PyInt_FromLong( ((short)( self->psys->part->draw_step )) );
1994 }
1995
1996 static int Part_setRenderStep( BPy_PartSys * self, PyObject * args )
1997 {
1998         int res = EXPP_setIValueRange( args, &self->psys->part->ren_step,
1999                         0, 7, 'i' );
2000
2001         /*Particle_Recalc(self,1);*/
2002
2003
2004         return res;
2005 }
2006
2007 static PyObject *Part_getRenderStep( BPy_PartSys * self )
2008 {
2009         return PyInt_FromLong( ((short)( self->psys->part->ren_step )) );
2010 }
2011
2012 static PyObject *Part_getDrawAs( BPy_PartSys * self )
2013 {
2014         return PyInt_FromLong( (long)( self->psys->part->draw_as ) );
2015 }