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