soc-2008-mxcurioni: implemented (without testing) StrokeShader, Stroke and MediumType...
[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                                 Py_DECREF(loc); /* PyList_Append increfs */
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                         Py_DECREF(seglist); /* PyList_Append increfs */
868                 }
869
870                 cache=psys->childcache;
871
872                 for(i = 0; i < psys->totchild; i++){
873                         path=cache[i];
874                         seglist = PyList_New( 0 );
875                         k = path->steps+1;
876                         for( j = 0; j < k ; j++){
877                                 loc = PyTuple_New(3);
878
879                                 PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)path->co[0]));
880                                 PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)path->co[1]));
881                                 PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)path->co[2]));
882
883                                 if ( PyList_Append(seglist,loc) < 0){
884                                         Py_DECREF(partlist);
885                                         Py_XDECREF(loc);
886                                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
887                                                         "Couldn't append item to PyList" );
888                                 }
889                                 Py_DECREF(loc);/* PyList_Append increfs */
890                                 path++;
891                         }
892
893                         if ( PyList_Append(partlist,seglist) < 0){
894                                 Py_DECREF(partlist);
895                                 Py_XDECREF(loc);
896                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
897                                                 "Couldn't append item to PyList" );     
898                         }
899                         Py_DECREF(seglist); /* PyList_Append increfs */
900                 }
901                 
902         } else {
903                 int init;
904                 partlist = PyList_New( 0 );
905                 if( !partlist )
906                         return EXPP_ReturnPyObjError( PyExc_MemoryError, "PyList() failed" );
907
908                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
909                         childexists = 1;
910
911                 for (i = 0; i < psys->totpart + psys->totchild; i++){
912                         if (childexists && (i < psys->totpart))
913                                 continue;
914
915                         state.time = cfra;
916                         if(psys_get_particle_state(ob,psys,i,&state,0)==0)
917                                 init = 0;
918                         else
919                                 init = 1;
920
921                         if (init){
922                                 if (!id)
923                                         loc = PyTuple_New(3);
924                                 else
925                                         loc = PyTuple_New(4);
926                                 PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.co[0]));
927                                 PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.co[1]));
928                                 PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.co[2]));
929                                 if (id)
930                                         PyTuple_SetItem(loc,3,PyInt_FromLong(i));
931
932                                 if ( PyList_Append(partlist,loc) < 0 ){
933                                         Py_DECREF(partlist);
934                                         Py_XDECREF(loc);
935                                         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
936                                                                 "Couldn't append item to PyList" );
937                                 }
938                                 Py_DECREF(loc);/* PyList_Append increfs */
939                         }
940                         else {
941                                 if ( all ){
942                                         if ( PyList_Append(partlist,Py_None) < 0 ){
943                                                 Py_DECREF(partlist);
944                                                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
945                                                                         "Couldn't append item to PyList" );
946                                         }
947                                         Py_DECREF(Py_None); /* PyList_Append increfs */
948                                 }
949                         }
950                 }
951         }
952         return partlist;
953 }
954
955 static PyObject *Part_GetRot( BPy_PartSys * self, PyObject * args ){
956         ParticleSystem *psys = 0L;
957         Object *ob = 0L;
958         PyObject *partlist = 0L;
959         PyObject* loc = 0L;
960         ParticleKey state;
961         int i;
962         int childexists = 0;
963         int all = 0;
964         int id = 0;
965
966         float cfra=bsystem_time(ob,(float)CFRA,0.0);
967
968         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
969                 return EXPP_ReturnPyObjError( PyExc_TypeError,
970                                 "expected one optional integer as argument" );
971
972         psys = self->psys;
973         ob = self->object;
974         
975         if (!ob || !psys)
976                 Py_RETURN_NONE;
977
978         if (psys->part->type != 2){
979                 partlist = PyList_New( 0 );
980
981                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
982                         childexists = 1;
983
984                 for (i = 0; i < psys->totpart + psys->totchild; i++){
985                         if (childexists && (i < psys->totpart))
986                                 continue;
987
988                         state.time = cfra;
989                         if(psys_get_particle_state(ob,psys,i,&state,0)==0){
990                                 if ( all ){
991                                         PyList_Append(partlist,Py_None);
992                                         Py_DECREF(Py_None); /* PyList_Append increfs */
993                                         continue;
994                                 } else {
995                                         continue;
996                                 }
997                         }
998                         if (!id)
999                                 loc = PyTuple_New(4);
1000                         else
1001                                 loc = PyTuple_New(5);
1002                         PyTuple_SetItem(loc,0,PyFloat_FromDouble((double)state.rot[0]));
1003                         PyTuple_SetItem(loc,1,PyFloat_FromDouble((double)state.rot[1]));
1004                         PyTuple_SetItem(loc,2,PyFloat_FromDouble((double)state.rot[2]));
1005                         PyTuple_SetItem(loc,3,PyFloat_FromDouble((double)state.rot[3]));
1006                         if (id)
1007                                 PyTuple_SetItem(loc,4,PyInt_FromLong(i));
1008                         PyList_Append(partlist,loc);
1009                         Py_DECREF(loc); /* PyList_Append increfs */
1010                 }
1011         }
1012         return partlist;
1013 }
1014
1015 static PyObject *Part_GetSize( BPy_PartSys * self, PyObject * args ){
1016         ParticleKey state;
1017         ParticleSystem *psys = 0L;
1018         ParticleData *data;
1019         Object *ob = 0L;
1020         PyObject *partlist,*tuple;
1021         PyObject* siz = 0L;
1022         float size;
1023         int i;
1024         int childexists = 0;
1025         int all = 0;
1026         int id = 0;
1027
1028         float cfra=bsystem_time(ob,(float)CFRA,0.0);
1029
1030         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
1031                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1032                                 "expected one optional integer as argument" );
1033
1034         data = self->psys->particles;
1035
1036         psys = self->psys;
1037         ob = self->object;
1038         
1039         if (!ob || !psys)
1040                 Py_RETURN_NONE;
1041
1042                 partlist = PyList_New( 0 );
1043
1044                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
1045                         childexists = 1;
1046
1047                 for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
1048                 if (psys->part->type != 2){
1049                         if (childexists && (i < psys->totpart))
1050                                 continue;
1051
1052                         if ( !all ){
1053                                 state.time = cfra;
1054                                 if(psys_get_particle_state(ob,psys,i,&state,0)==0)
1055                                         continue;
1056                         }
1057
1058                         if (i < psys->totpart){
1059                                 size = data->size;
1060                         } else {
1061                                 ChildParticle *cpa= &psys->child[i-psys->totpart];
1062                                 size = psys_get_child_size(psys,cpa,cfra,0);
1063                         }
1064                         if (id){
1065                                 tuple = PyTuple_New(2);
1066                                 PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)size));
1067                                 PyTuple_SetItem(tuple,1,PyInt_FromLong(i));
1068                                 PyList_Append(partlist,tuple);
1069                                 Py_DECREF(tuple);
1070                         } else {
1071                                 siz = PyFloat_FromDouble((double)size);
1072                                 PyList_Append(partlist,siz);
1073                                 Py_DECREF(siz);
1074                         }
1075                 }
1076         }
1077         return partlist;
1078 }
1079
1080
1081 static PyObject *Part_GetAge( BPy_PartSys * self, PyObject * args ){
1082         ParticleKey state;
1083         ParticleSystem *psys = 0L;
1084         ParticleData *data;
1085         Object *ob = 0L;
1086         PyObject *partlist,*tuple;
1087         PyObject* lif = 0L;
1088         float life;
1089         int i;
1090         int childexists = 0;
1091         int all = 0;
1092         int id = 0;
1093
1094         float cfra=bsystem_time(ob,(float)CFRA,0.0);
1095
1096         if( !PyArg_ParseTuple( args, "|ii", &all, &id ) )
1097                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1098                                 "expected one optional integer as argument" );
1099
1100         data = self->psys->particles;
1101
1102         psys = self->psys;
1103         ob = self->object;
1104         
1105         if (!ob || !psys)
1106                 Py_RETURN_NONE;
1107
1108                 partlist = PyList_New( 0 );
1109
1110                 if (psys->totchild > 0 && !(psys->part->draw & PART_DRAW_PARENT))
1111                         childexists = 1;
1112
1113                 for (i = 0; i < psys->totpart + psys->totchild; i++, data++){
1114                 if (psys->part->type != 2){
1115
1116                         if (childexists && (i < psys->totpart))
1117                                 continue;
1118
1119                         if ( !all ){
1120                                 state.time = cfra;
1121                                 if(psys_get_particle_state(ob,psys,i,&state,0)==0)
1122                                         continue;
1123                         }
1124
1125                         if (i < psys->totpart){
1126                                 life = (cfra-data->time)/data->lifetime;
1127                         } else {
1128                                 ChildParticle *cpa= &psys->child[i-psys->totpart];
1129                                 life = psys_get_child_time(psys,cpa,cfra);
1130                         }
1131                         if (id){
1132                                 tuple = PyTuple_New(2);
1133                                 PyTuple_SetItem(tuple,0,PyFloat_FromDouble((double)life));
1134                                 PyTuple_SetItem(tuple,1,PyInt_FromLong(i));
1135                                 PyList_Append(partlist,tuple);
1136                                 Py_DECREF(tuple);
1137                         } else {
1138                                 lif = PyFloat_FromDouble((double)life);
1139                                 PyList_Append(partlist,lif);
1140                                 Py_DECREF(lif);
1141                         }
1142                 }
1143         }
1144         return partlist;
1145 }
1146
1147
1148 static PyObject *Part_GetMat( BPy_PartSys * self, PyObject * args ){
1149         Material *ma;
1150         PyObject* mat = 0L;
1151         ma = give_current_material(self->object,self->psys->part->omat);
1152         if(!ma)
1153                 Py_RETURN_NONE;
1154
1155         mat = Material_CreatePyObject(ma);
1156         return mat;
1157 }
1158
1159
1160 /*****************************************************************************/
1161 /* Function:              Set/Get Seed                                       */
1162 /*****************************************************************************/
1163
1164 static int Part_setSeed( BPy_PartSys * self, PyObject * args )
1165 {
1166         return EXPP_setIValueRange( args, &self->psys->seed,
1167                         0, 255, 'i' );
1168 }
1169
1170 static PyObject *Part_getSeed( BPy_PartSys * self )
1171 {
1172         return PyInt_FromLong( (long)( self->psys->seed ) );
1173 }
1174
1175 static int Part_setType( BPy_PartSys * self, PyObject * args )
1176 {
1177         int res = EXPP_setIValueRange( args, &self->psys->part->type,
1178                         0, 2, 'h' );
1179
1180         psys_flush_settings( self->psys->part, PSYS_TYPE, 1 );
1181
1182         return res;
1183 }
1184
1185 static PyObject *Part_getType( BPy_PartSys * self )
1186 {
1187         return PyInt_FromLong( (short)( self->psys->part->type ) );
1188 }
1189
1190 static int Part_setResol( BPy_PartSys * self, PyObject * args )
1191 {
1192         int res = EXPP_setIValueRange( args, &self->psys->part->grid_res,
1193                         0, 100, 'i' );
1194
1195         psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
1196
1197         return res;
1198 }
1199
1200 static PyObject *Part_getResol( BPy_PartSys * self )
1201 {
1202         return PyInt_FromLong( ((int)( self->psys->part->grid_res )) );
1203 }
1204
1205 static int Part_setStart( BPy_PartSys * self, PyObject * args )
1206 {
1207         int res = EXPP_setFloatRange( args, &self->psys->part->sta,
1208                         0.0f, 100000.0f );
1209
1210         psys_flush_settings(self->psys->part,PSYS_INIT,1);
1211
1212         return res;
1213 }
1214
1215 static PyObject *Part_getStart( BPy_PartSys * self )
1216 {
1217         return PyFloat_FromDouble( (float)( self->psys->part->sta ) );
1218 }
1219
1220 static int Part_setEnd( BPy_PartSys * self, PyObject * args )
1221 {
1222         int res = EXPP_setFloatRange( args, &self->psys->part->end,
1223                         0.0f, 100000.0f );
1224
1225         psys_flush_settings(self->psys->part,PSYS_INIT,1);
1226
1227         return res;
1228 }
1229
1230 static PyObject *Part_getEnd( BPy_PartSys * self )
1231 {
1232         return PyFloat_FromDouble( (long)( self->psys->part->end ) );
1233 }
1234
1235 static int Part_setEditable( BPy_PartSys * self, PyObject * args )
1236 {
1237         int number;
1238
1239         if( !PyInt_Check( args ) ) {
1240                 char errstr[128];
1241                 sprintf ( errstr, "expected int argument" );
1242                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1243         }
1244
1245         number = PyInt_AS_LONG( args );
1246
1247         if(!number){
1248                 if(self->psys->edit)
1249                         PE_free_particle_edit(self->psys);
1250
1251                 self->psys->flag &= ~PSYS_EDITED;
1252                 self->psys->recalc |= PSYS_RECALC_HAIR;
1253
1254                 DAG_object_flush_update(G.scene, self->object, OB_RECALC_DATA);
1255         }
1256         else
1257         {
1258                 self->psys->flag |= PSYS_EDITED;
1259                 if(G.f & G_PARTICLEEDIT)
1260                         PE_create_particle_edit(self->object, self->psys);
1261         }
1262
1263         return 0;
1264 }
1265
1266 static PyObject *Part_getEditable( BPy_PartSys * self )
1267 {
1268         return PyInt_FromLong( ((long)( self->psys->flag & PSYS_EDITED )) > 0  );
1269 }
1270
1271 static int Part_setAmount( BPy_PartSys * self, PyObject * args )
1272 {
1273         int res = EXPP_setIValueRange( args, &self->psys->part->totpart,
1274                         0, 100000, 'i' );
1275
1276         psys_flush_settings( self->psys->part, PSYS_ALLOC, 1 );
1277
1278         return res;
1279 }
1280
1281 static PyObject *Part_getAmount( BPy_PartSys * self )
1282 {
1283         return PyInt_FromLong( ((int)( self->psys->part->totpart )) );
1284 }
1285
1286 static int Part_setMultiReact( BPy_PartSys * self, PyObject * args )
1287 {
1288         int number;
1289
1290         if( !PyInt_Check( args ) ) {
1291                 char errstr[128];
1292                 sprintf ( errstr, "expected int argument" );
1293                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1294         }
1295
1296         number = PyInt_AS_LONG( args );
1297
1298
1299         if (number){
1300                 self->psys->part->flag |= PART_REACT_MULTIPLE;
1301         }else{
1302                 self->psys->part->flag &= ~PART_REACT_MULTIPLE;
1303         }
1304
1305         Particle_Recalc(self,1);
1306
1307         return 0;
1308 }
1309
1310 static PyObject *Part_getMultiReact( BPy_PartSys * self )
1311 {
1312         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_REACT_MULTIPLE )) > 0 );
1313 }
1314
1315 static int Part_setReactShape( BPy_PartSys * self, PyObject * args )
1316 {
1317         int res = EXPP_setFloatRange( args, &self->psys->part->reactshape,
1318                         0.0f, 10.0f );
1319
1320         Particle_Recalc(self,1);
1321
1322         return res;
1323 }
1324
1325 static PyObject *Part_getReactShape( BPy_PartSys * self )
1326 {
1327         return PyFloat_FromDouble( ((double)( self->psys->part->reactshape )) );
1328 }
1329
1330 static int Part_setSegments( BPy_PartSys * self, PyObject * args )
1331 {
1332         int res = EXPP_setIValueRange( args, &self->psys->part->hair_step,
1333                         2, 50, 'h' );
1334
1335         Particle_Recalc(self,1);
1336
1337         return res;
1338 }
1339
1340 static PyObject *Part_getSegments( BPy_PartSys * self )
1341 {
1342         return PyInt_FromLong( ((long)( self->psys->part->hair_step )) );
1343 }
1344
1345 static int Part_setLife( BPy_PartSys * self, PyObject * args )
1346 {
1347         int res = EXPP_setFloatRange( args, &self->psys->part->lifetime,
1348                         1.0f, MAXFRAMEF );
1349
1350         Particle_Recalc(self,1);
1351
1352         return res;
1353 }
1354
1355 static PyObject *Part_getLife( BPy_PartSys * self )
1356 {
1357         return PyFloat_FromDouble( ((double)( self->psys->part->lifetime )) );
1358 }
1359
1360 static int Part_setRandLife( BPy_PartSys * self, PyObject * args )
1361 {
1362         int res = EXPP_setFloatRange( args, &self->psys->part->randlife,
1363                         0.0f, 2.0f );
1364
1365         Particle_Recalc(self,1);
1366
1367         return res;
1368 }
1369
1370 static PyObject *Part_getRandLife( BPy_PartSys * self )
1371 {
1372         return PyFloat_FromDouble( ((double)( self->psys->part->randlife )) );
1373 }
1374
1375 static int Part_set2d( BPy_PartSys * self, PyObject * args )
1376 {
1377         int number;
1378
1379         if( !PyInt_Check( args ) ) {
1380                 char errstr[128];
1381                 sprintf ( errstr, "expected int argument" );
1382                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1383         }
1384
1385         number = PyInt_AS_LONG( args );
1386
1387         if (number){
1388                 self->psys->part->flag |= PART_BOIDS_2D;
1389         }else{
1390                 self->psys->part->flag &= ~PART_BOIDS_2D;
1391         }
1392
1393         Particle_Recalc(self,1);
1394
1395         return 0;
1396 }
1397
1398 static PyObject *Part_get2d( BPy_PartSys * self )
1399 {
1400         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 );
1401 }
1402
1403 static int Part_setMaxVel( BPy_PartSys * self, PyObject * args )
1404 {
1405         int res = EXPP_setFloatRange( args, &self->psys->part->max_vel,
1406                         0.0f, 200.0f );
1407
1408         Particle_Recalc(self,1);
1409
1410         return res;
1411 }
1412
1413 static PyObject *Part_getMaxVel( BPy_PartSys * self )
1414 {
1415         return PyFloat_FromDouble( ((double)( self->psys->part->max_vel )) );
1416 }
1417
1418 static int Part_setAvVel( BPy_PartSys * self, PyObject * args )
1419 {
1420         int res = EXPP_setFloatRange( args, &self->psys->part->average_vel,
1421                         0.0f, 1.0f );
1422
1423         Particle_Recalc(self,1);
1424
1425         return res;
1426 }
1427
1428 static PyObject *Part_getAvVel( BPy_PartSys * self )
1429 {
1430         return PyFloat_FromDouble( ((double)( self->psys->part->average_vel )) );
1431 }
1432
1433 static int Part_setLatAcc( BPy_PartSys * self, PyObject * args )
1434 {
1435         int res = EXPP_setFloatRange( args, &self->psys->part->max_lat_acc,
1436                         0.0f, 1.0f );
1437
1438         Particle_Recalc(self,1);
1439
1440         return res;
1441 }
1442
1443 static PyObject *Part_getLatAcc( BPy_PartSys * self )
1444 {
1445         return PyFloat_FromDouble( ((double)( self->psys->part->max_lat_acc )) );
1446 }
1447
1448 static int Part_setMaxTan( BPy_PartSys * self, PyObject * args )
1449 {
1450         int res = EXPP_setFloatRange( args, &self->psys->part->max_tan_acc,
1451                         0.0f, 1.0f );
1452
1453         Particle_Recalc(self,1);
1454
1455         return res;
1456 }
1457
1458 static PyObject *Part_getMaxTan( BPy_PartSys * self )
1459 {
1460         return PyFloat_FromDouble( ((double)( self->psys->part->max_tan_acc )) );
1461 }
1462
1463 static int Part_setGroundZ( BPy_PartSys * self, PyObject * args )
1464 {
1465         int res = EXPP_setFloatRange( args, &self->psys->part->groundz,
1466                         -100.0f, 100.0f );
1467
1468         Particle_Recalc(self,1);
1469
1470         return res;
1471 }
1472
1473 static PyObject *Part_getGroundZ( BPy_PartSys * self )
1474 {
1475         return PyFloat_FromDouble( ((double)( self->psys->part->groundz )) );
1476 }
1477
1478 static int Part_setOb( BPy_PartSys * self, PyObject * args )
1479 {
1480         Object *obj;
1481         if( !BPy_Object_Check( args ) ) {
1482                 char errstr[128];
1483                 sprintf ( errstr, "expected object argument" );
1484                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1485         }
1486
1487         obj = Object_FromPyObject(args);
1488
1489         self->psys->keyed_ob = obj;
1490
1491         return 0;
1492 }
1493
1494 static PyObject *Part_getOb( BPy_PartSys * self )
1495 {
1496         Object * obj;
1497         obj = self->psys->keyed_ob;
1498         if (!obj)
1499                 Py_RETURN_NONE;
1500
1501         return Object_CreatePyObject( obj );
1502 }
1503
1504 static int Part_setRandEmission( BPy_PartSys * self, PyObject * args )
1505 {
1506         int number;
1507
1508         if( !PyInt_Check( args ) ) {
1509                 char errstr[128];
1510                 sprintf ( errstr, "expected int argument" );
1511                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1512         }
1513
1514         number = PyInt_AS_LONG( args );
1515
1516         if (number){
1517                 self->psys->part->flag |= PART_TRAND;
1518         }else{
1519                 self->psys->part->flag &= ~PART_TRAND;
1520         }
1521
1522         Particle_RecalcPsys_distr(self,1);
1523
1524         return 0;
1525 }
1526
1527 static PyObject *Part_getRandEmission( BPy_PartSys * self )
1528 {
1529         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_BOIDS_2D )) > 0 );
1530 }
1531
1532 static int Part_setParticleDist( BPy_PartSys * self, PyObject * args )
1533 {
1534         int number;
1535         char errstr[128];
1536
1537         if( !PyInt_Check( args ) ) {
1538                 sprintf ( errstr, "expected int argument" );
1539                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1540         }
1541
1542         number = PyInt_AS_LONG( args );
1543
1544         if (number < 0 || number > 3){
1545                 sprintf ( errstr, "expected int argument between 0 - 3" );
1546                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1547         }
1548
1549         self->psys->part->from = number;
1550
1551         Particle_RecalcPsys_distr(self,1);
1552
1553         return 0;
1554 }
1555
1556 static PyObject *Part_getParticleDist( BPy_PartSys * self )
1557 {
1558         return PyInt_FromLong( (long)( self->psys->part->from ) );
1559 }
1560
1561 static int Part_setEvenDist( BPy_PartSys * self, PyObject * args )
1562 {
1563         int number;
1564
1565         if( !PyInt_Check( args ) ) {
1566                 char errstr[128];
1567                 sprintf ( errstr, "expected int argument" );
1568                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1569         }
1570
1571         number = PyInt_AS_LONG( args );
1572
1573         if (number){
1574                 self->psys->part->flag |= PART_EDISTR;
1575         }else{
1576                 self->psys->part->flag &= ~PART_EDISTR;
1577         }
1578
1579         Particle_RecalcPsys_distr(self,1);
1580
1581         return 0;
1582 }
1583
1584 static PyObject *Part_getEvenDist( BPy_PartSys * self )
1585 {
1586         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_EDISTR )) > 0 );
1587 }
1588
1589 static int Part_setDist( BPy_PartSys * self, PyObject * args )
1590 {
1591         int number;
1592         char errstr[128];
1593
1594         if( !PyInt_Check( args ) ) {
1595                 sprintf ( errstr, "expected int argument" );
1596                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1597         }
1598
1599         number = PyInt_AS_LONG( args );
1600
1601         if (number < 0 || number > 2){
1602                 sprintf ( errstr, "expected int argument between 0 - 2" );
1603                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1604         }
1605
1606         self->psys->part->distr = number;
1607
1608         Particle_RecalcPsys_distr(self,1);
1609
1610         return 0;
1611 }
1612
1613 static PyObject *Part_getDist( BPy_PartSys * self )
1614 {
1615         return PyInt_FromLong( (long)( self->psys->part->distr ) );
1616 }
1617
1618 static int Part_setJitterAmount( BPy_PartSys * self, PyObject * args )
1619 {
1620         int res = EXPP_setFloatRange( args, &self->psys->part->jitfac,
1621                         0.0f, 2.0f );
1622
1623         Particle_RecalcPsys_distr(self,1);
1624
1625         return res;
1626 }
1627
1628 static PyObject *Part_getJitterAmount( BPy_PartSys * self )
1629 {
1630         return PyFloat_FromDouble( ((double)( self->psys->part->jitfac )) );
1631 }
1632
1633
1634
1635 static int Part_setPF( BPy_PartSys * self, PyObject * args )
1636 {
1637         int res = EXPP_setIValueRange( args, &self->psys->part->userjit,
1638                         0, 1000, 'i' );
1639
1640         Particle_RecalcPsys_distr(self,1);
1641
1642         return res;
1643 }
1644
1645 static PyObject *Part_getPF( BPy_PartSys * self )
1646 {
1647         return PyInt_FromLong( ((short)( self->psys->part->userjit )) );
1648 }
1649
1650 static int Part_setInvert( BPy_PartSys * self, PyObject * args )
1651 {
1652         int number;
1653
1654         if( !PyInt_Check( args ) ) {
1655                 char errstr[128];
1656                 sprintf ( errstr, "expected int argument" );
1657                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1658         }
1659
1660         number = PyInt_AS_LONG( args );
1661
1662         if (number){
1663                 self->psys->part->flag |= PART_GRID_INVERT;
1664         }else{
1665                 self->psys->part->flag &= ~PART_GRID_INVERT;
1666         }
1667
1668         Particle_RecalcPsys_distr(self,1);
1669
1670         return 0;
1671 }
1672
1673 static PyObject *Part_getInvert( BPy_PartSys * self )
1674 {
1675         return PyInt_FromLong( ((long)( self->psys->part->flag & PART_GRID_INVERT )) > 0 );
1676 }
1677
1678 static int Part_setTargetOb( BPy_PartSys * self, PyObject * args )
1679 {
1680         Object *obj;
1681         if( !BPy_Object_Check( args ) ) {
1682                 char errstr[128];
1683                 sprintf ( errstr, "expected object argument" );
1684                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1685         }
1686
1687         obj = Object_FromPyObject(args);
1688
1689         self->psys->target_ob = obj;
1690
1691         return 0;
1692 }
1693
1694 static PyObject *Part_getTargetOb( BPy_PartSys * self )
1695 {
1696         Object * obj;
1697         obj = self->psys->target_ob;
1698         if (!obj)
1699                 Py_RETURN_NONE;
1700
1701         return Object_CreatePyObject( obj );
1702 }
1703
1704
1705
1706 PyObject *Part_getDupOb( BPy_PartSys * self )
1707 {
1708         Object * obj;
1709         obj = self->psys->part->dup_ob;
1710         if (!obj)
1711                 Py_RETURN_NONE;
1712
1713         return Object_CreatePyObject( obj );
1714 }
1715
1716 static int Part_setTargetPsys( BPy_PartSys * self, PyObject * args ){
1717         int tottpsys;
1718         int res;
1719         Object *tob=0;
1720         ParticleSystem *psys = self->psys;
1721         Object *ob;
1722
1723         ob = self->object;
1724
1725         if(psys->target_ob)
1726                 tob=psys->target_ob;
1727         else
1728                 tob=ob;
1729
1730         tottpsys = BLI_countlist(&tob->particlesystem);
1731
1732         res = EXPP_setIValueRange( args, &self->psys->target_psys, 0, tottpsys, 'h' );
1733
1734         if((psys=psys_get_current(ob))){
1735                 if(psys->keyed_ob==ob || psys->target_ob==ob){
1736                         if(psys->keyed_ob==ob)
1737                                 psys->keyed_ob=NULL;
1738                         else
1739                                 psys->target_ob=NULL;
1740                 }
1741                 else{
1742                         DAG_scene_sort(G.scene);
1743                         DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
1744                 }
1745         }
1746
1747         return res;
1748 }
1749
1750 static PyObject *Part_getTargetPsys( BPy_PartSys * self ){
1751         return PyInt_FromLong( (short)( self->psys->target_psys ) );
1752 }
1753
1754 static int Part_setRenderObject( BPy_PartSys * self, PyObject * args )
1755 {
1756         int number,nr;
1757         ParticleSystem *psys = 0L;
1758
1759         if( !PyInt_Check( args ) ) {
1760                 char errstr[128];
1761                 sprintf ( errstr, "expected int argument" );
1762                 return EXPP_ReturnIntError( PyExc_TypeError, errstr );
1763         }
1764
1765         number = PyInt_AS_LONG( args );
1766
1767         if (number){
1768                 self->psys->part->draw |= PART_DRAW_EMITTER;
1769         }else{
1770                 self->psys->part->draw &= ~PART_DRAW_EMITTER;
1771         }
1772
1773         /* check need for dupliobjects */
1774         nr=0;
1775         for(psys=self->object->particlesystem.first; psys; psys=psys->next){
1776                 if(ELEM(psys->part->draw_as,PART_DRAW_OB,PART_DRAW_GR))
1777                         nr++;
1778         }
1779         if(nr)
1780                 self->object->transflag |= OB_DUPLIPARTS;
1781         else
1782                 self->object->transflag &= ~OB_DUPLIPARTS;
1783
1784         return 0;
1785 }
1786
1787 static PyObject *Part_getRenderObject( BPy_PartSys * self )
1788 {
1789         return PyInt_FromLong( ((long)( self->psys->part->draw & PART_DRAW_EMITTER )) > 0 );
1790 }
1791
1792 static int Part_setParticleDisp( BPy_PartSys * self, PyObject * args )
1793 {
1794         int res = EXPP_setIValueRange( args, &self->psys->part->disp,
1795                         0, 100, 'i' );
1796
1797         Particle_Recalc(self,0);
1798
1799
1800         return res;
1801 }
1802
1803 static PyObject *Part_getParticleDisp( BPy_PartSys * self )
1804 {
1805         return PyInt_FromLong( ((short)( self->psys->part->disp )) );
1806 }
1807
1808 static int Part_setStep( BPy_PartSys * self, PyObject * args )
1809 {
1810         int res = EXPP_setIValueRange( args, &self->psys->part->draw_step,
1811                         0, 7, 'i' );
1812
1813         Particle_Recalc(self,1);
1814
1815
1816         return res;
1817 }
1818
1819 static PyObject *Part_getStep( BPy_PartSys * self )
1820 {
1821         return PyInt_FromLong( ((short)( self->psys->part->draw_step )) );
1822 }
1823
1824 static int Part_setRenderStep( BPy_PartSys * self, PyObject * args )
1825 {
1826         int res = EXPP_setIValueRange( args, &self->psys->part->ren_step,
1827                         0, 7, 'i' );
1828
1829         /*Particle_Recalc(self,1);*/
1830
1831
1832         return res;
1833 }
1834
1835 static PyObject *Part_getRenderStep( BPy_PartSys * self )
1836 {
1837         return PyInt_FromLong( ((short)( self->psys->part->ren_step )) );
1838 }
1839
1840 static PyObject *Part_getDrawAs( BPy_PartSys * self )
1841 {
1842         return PyInt_FromLong( (long)( self->psys->part->draw_as ) );
1843 }