== Action Editor - Copy and Paste Tools ==
[blender.git] / source / blender / python / api2_2x / Ipocurve.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Jacques Guignot, Nathan Letwory, Ken Hughes, Johnny Matthews
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include "Ipocurve.h" /*This must come first*/
34
35 #include "Object.h"
36 #include "BKE_global.h"
37 #include "BKE_main.h"
38 #include "BKE_depsgraph.h"
39 #include "BKE_ipo.h"
40 #include "BIF_space.h"
41 #include "BSE_editipo.h"
42 #include "MEM_guardedalloc.h"
43 #include "DNA_ipo_types.h"
44 #include "DNA_key_types.h"
45 #include "BezTriple.h"
46 #include "gen_utils.h"
47
48 /*****************************************************************************/
49 /* The following string definitions are used for documentation strings.      */
50 /* In Python these will be written to the console when doing a               */
51 /* Blender.IpoCurve.__doc__                                                  */
52 /*****************************************************************************/
53 char M_IpoCurve_doc[] = "";
54 char M_IpoCurve_New_doc[] = "";
55 char M_IpoCurve_Get_doc[] = "";
56
57 /*****************************************************************************/
58 /* Python method structure definition for Blender.IpoCurve module:           */
59 /*****************************************************************************/
60
61 struct PyMethodDef M_IpoCurve_methods[] = {
62         {NULL, NULL, 0, NULL}
63 };
64
65 /*****************************************************************************/
66 /* Python C_IpoCurve methods declarations:                                   */
67 /*****************************************************************************/
68 static PyObject *IpoCurve_getName( C_IpoCurve * self );
69 static PyObject *IpoCurve_Recalc( C_IpoCurve * self );
70 static PyObject *IpoCurve_append( C_IpoCurve * self, PyObject * value );
71 static PyObject *IpoCurve_addBezier( C_IpoCurve * self, PyObject * value );
72 static PyObject *IpoCurve_delBezier( C_IpoCurve * self, PyObject * args );
73 static PyObject *IpoCurve_setInterpolation( C_IpoCurve * self,
74                                             PyObject * value );
75 static PyObject *IpoCurve_getInterpolation( C_IpoCurve * self );
76 static PyObject *IpoCurve_newgetInterp( C_IpoCurve * self );
77 static int IpoCurve_newsetInterp( C_IpoCurve * self, PyObject * args );
78 static PyObject *IpoCurve_setExtrapolation( C_IpoCurve * self,
79                                             PyObject * value );
80 static PyObject *IpoCurve_getExtrapolation( C_IpoCurve * self );
81 static PyObject *IpoCurve_newgetExtend( C_IpoCurve * self );
82 static int IpoCurve_newsetExtend( C_IpoCurve * self, PyObject * args );
83 static PyObject *IpoCurve_getPoints( C_IpoCurve * self );
84 static PyObject *IpoCurve_evaluate( C_IpoCurve * self, PyObject * args );
85 static PyObject *IpoCurve_getDriver( C_IpoCurve * self );
86 static int IpoCurve_setDriver( C_IpoCurve * self, PyObject * args );
87 static PyObject *IpoCurve_getDriverObject( C_IpoCurve * self);
88 static int IpoCurve_setDriverObject( C_IpoCurve * self, PyObject * args );
89 static PyObject *IpoCurve_getDriverChannel( C_IpoCurve * self);
90 static int IpoCurve_setDriverChannel( C_IpoCurve * self, PyObject * args );
91 static PyObject *IpoCurve_getDriverExpression( C_IpoCurve * self);
92 static PyObject *IpoCurve_getFlag( C_IpoCurve * self, void *type);
93 static int IpoCurve_setFlag( C_IpoCurve * self, PyObject *value, void *type);
94
95 static int IpoCurve_setDriverExpression( C_IpoCurve * self, PyObject * args );
96 static PyObject *IpoCurve_getCurval( C_IpoCurve * self, PyObject * args );
97 static int IpoCurve_setCurval( C_IpoCurve * self, PyObject * key, 
98                 PyObject * value );
99
100 /*****************************************************************************/
101 /* Python C_IpoCurve methods table:                                          */
102 /*****************************************************************************/
103 static PyMethodDef C_IpoCurve_methods[] = {
104         /* name, method, flags, doc */
105         {"getName", ( PyCFunction ) IpoCurve_getName, METH_NOARGS,
106          "() - Return IpoCurve name"},
107         {"Recalc", ( PyCFunction ) IpoCurve_Recalc, METH_NOARGS,
108          "() - deprecated method.  use recalc() instead"},
109         {"recalc", ( PyCFunction ) IpoCurve_Recalc, METH_NOARGS,
110          "() - Recomputes the curve after changes"},
111         {"update", ( PyCFunction ) IpoCurve_Recalc, METH_NOARGS,
112          "() - deprecated method: use recalc method instead."},
113         {"append", ( PyCFunction ) IpoCurve_append, METH_O,
114          "(coordlist) -  Adds a Bezier point to a curve"},
115         {"addBezier", ( PyCFunction ) IpoCurve_addBezier, METH_O,
116          "() - deprecated method. use append() instead"},
117         {"delBezier", ( PyCFunction ) IpoCurve_delBezier, METH_VARARGS,
118          "() - deprecated method. use \"del icu[index]\" instead"},
119         {"setInterpolation", ( PyCFunction ) IpoCurve_setInterpolation,
120          METH_O, "(str) - Sets the interpolation type of the curve"},
121         {"getInterpolation", ( PyCFunction ) IpoCurve_getInterpolation,
122          METH_NOARGS, "() - Gets the interpolation type of the curve"},
123         {"setExtrapolation", ( PyCFunction ) IpoCurve_setExtrapolation,
124          METH_O, "(str) - Sets the extend mode of the curve"},
125         {"getExtrapolation", ( PyCFunction ) IpoCurve_getExtrapolation,
126          METH_NOARGS, "() - Gets the extend mode of the curve"},
127         {"getPoints", ( PyCFunction ) IpoCurve_getPoints, METH_NOARGS,
128          "() - Returns list of all bezTriples of the curve"},
129         {"evaluate", ( PyCFunction ) IpoCurve_evaluate, METH_VARARGS,
130          "(float) - Evaluate curve at given time"},
131         {NULL, NULL, 0, NULL}
132 };
133
134 /*
135  * IpoCurve methods
136  */
137
138 static PyGetSetDef C_IpoCurve_getseters[] = {
139         {"name",
140          (getter)IpoCurve_getName, (setter)NULL,
141          "the IpoCurve name",
142         NULL},
143         {"bezierPoints",
144          (getter)IpoCurve_getPoints, (setter)NULL,
145          "list of all bezTriples of the curve",
146         NULL},
147         {"driver",
148          (getter)IpoCurve_getDriver, (setter)IpoCurve_setDriver,
149          "The status of the driver 1-object, 2-py expression, 0-off",
150          NULL},
151         {"driverObject",
152          (getter)IpoCurve_getDriverObject, (setter)IpoCurve_setDriverObject,
153          "The object used to drive the IpoCurve",
154          NULL},
155         {"driverChannel",
156          (getter)IpoCurve_getDriverChannel, (setter)IpoCurve_setDriverChannel,
157          "The channel on the driver object used to drive the IpoCurve",
158          NULL},
159         {"driverExpression",
160          (getter)IpoCurve_getDriverExpression, (setter)IpoCurve_setDriverExpression,
161          "The python expression on the driver used to drive the IpoCurve",
162          NULL},
163         {"interpolation",
164          (getter)IpoCurve_newgetInterp, (setter)IpoCurve_newsetInterp,
165          "The interpolation mode of the curve",
166          NULL},
167         {"extend",
168          (getter)IpoCurve_newgetExtend, (setter)IpoCurve_newsetExtend,
169          "The extend mode of the curve",
170          NULL},
171         
172         {"sel",
173          (getter)IpoCurve_getFlag, (setter)IpoCurve_setFlag,
174          "the selection state of the curve",
175          (void *)IPO_SELECT},
176          
177          {NULL,NULL,NULL,NULL,NULL}
178 };
179
180 /*****************************************************************************/
181 /* Python IpoCurve_Type Mapping Methods table:                               */
182 /*****************************************************************************/
183
184 static PyMappingMethods IpoCurve_as_mapping = {
185         ( inquiry ) 0,  /* mp_length */
186         ( binaryfunc ) IpoCurve_getCurval,      /* mp_subscript */
187         ( objobjargproc ) IpoCurve_setCurval,   /* mp_ass_subscript */
188 };
189
190 /*****************************************************************************/
191 /* Python IpoCurve_Type callback function prototypes:                        */
192 /*****************************************************************************/
193 static int IpoCurve_compare( C_IpoCurve * a, C_IpoCurve * b );
194 static PyObject *IpoCurve_repr( C_IpoCurve * self );
195
196 /*****************************************************************************/
197 /* Python IpoCurve_Type structure definition:                                */
198 /*****************************************************************************/
199 PyTypeObject IpoCurve_Type = {
200         PyObject_HEAD_INIT( NULL )          /* required macro */ 
201         0,                                                                      /* ob_size */
202         "IpoCurve",                                                     /* tp_name */
203         sizeof( C_IpoCurve ),                           /* tp_basicsize */
204         0,                                                                      /* tp_itemsize */
205         /* methods */
206         NULL,                                                       /* tp_dealloc */
207         0,                                                                      /* tp_print */
208         ( getattrfunc ) NULL,               /* tp_getattr */
209         ( setattrfunc ) NULL,               /* tp_setattr */
210         ( cmpfunc ) IpoCurve_compare,           /* tp_compare */
211         ( reprfunc ) IpoCurve_repr,                     /* tp_repr */
212         /* Method suites for standard classes */
213
214         NULL,                               /* PyNumberMethods *tp_as_number; */
215         NULL,                               /* PySequenceMethods *tp_as_sequence; */
216         &IpoCurve_as_mapping,               /* PyMappingMethods *tp_as_mapping; */
217
218         /* More standard operations (here for binary compatibility) */
219
220         NULL,                                   /* hashfunc tp_hash; */
221         NULL,                                   /* ternaryfunc tp_call; */
222         NULL,                                   /* reprfunc tp_str; */
223         NULL,                                   /* getattrofunc tp_getattro; */
224         NULL,                                           /* setattrofunc tp_setattro; */
225
226         /* Functions to access object as input/output buffer */
227         NULL,                                   /* PyBufferProcs *tp_as_buffer; */
228
229   /*** Flags to define presence of optional/expanded features ***/
230         Py_TPFLAGS_DEFAULT,                     /* long tp_flags; */
231
232         NULL,                                   /*  char *tp_doc;  */
233   /*** Assigned meaning in release 2.0 ***/
234         /* call function for all accessible objects */
235         NULL,                                   /* traverseproc tp_traverse; */
236
237         /* delete references to contained objects */
238         NULL,                                   /* inquiry tp_clear; */
239
240   /***  Assigned meaning in release 2.1 ***/
241   /*** rich comparisons ***/
242         NULL,                                   /* richcmpfunc tp_richcompare; */
243
244   /***  weak reference enabler ***/
245         0,                                      /* long tp_weaklistoffset; */
246
247   /*** Added in release 2.2 ***/
248         /*   Iterators */
249         NULL,                                           /* getiterfunc tp_iter; */
250         NULL,                                   /* iternextfunc tp_iternext; */
251
252   /*** Attribute descriptor and subclassing stuff ***/
253         C_IpoCurve_methods,                     /* struct PyMethodDef *tp_methods; */
254         NULL,                                   /* struct PyMemberDef *tp_members; */
255         C_IpoCurve_getseters,                   /* struct PyGetSetDef *tp_getset; */
256         NULL,                                   /* struct _typeobject *tp_base; */
257         NULL,                                   /* PyObject *tp_dict; */
258         NULL,                                   /* descrgetfunc tp_descr_get; */
259         NULL,                                   /* descrsetfunc tp_descr_set; */
260         0,                                      /* long tp_dictoffset; */
261         NULL,                                   /* initproc tp_init; */
262         NULL,                                   /* allocfunc tp_alloc; */
263         NULL,                                   /* newfunc tp_new; */
264         /*  Low-level free-memory routine */
265         NULL,                                   /* freefunc tp_free;  */
266         /* For PyObject_IS_GC */
267         NULL,                                   /* inquiry tp_is_gc;  */
268         NULL,                                   /* PyObject *tp_bases; */
269         /* method resolution order */
270         NULL,                                   /* PyObject *tp_mro;  */
271         NULL,                                   /* PyObject *tp_cache; */
272         NULL,                                   /* PyObject *tp_subclasses; */
273         NULL,                                   /* PyObject *tp_weaklist; */
274         NULL
275 };
276
277 /*****************************************************************************/
278 /* local utility functions                                                   */
279 /*****************************************************************************/
280
281 /*
282  * Keys are handled differently than other Ipos, so go through contortions
283  * to find their names.
284  */
285
286 static char *get_key_curvename( IpoCurve *ipocurve )
287 {
288         Key *key_iter;
289         char *empty = "";
290
291         /* search for keys with an Ipo */
292
293         for( key_iter = G.main->key.first; key_iter; key_iter=key_iter->id.next) {
294                 if( key_iter->ipo ) {
295                         IpoCurve *icu = key_iter->ipo->curve.first;
296                         /* search curves for a match */
297                         while( icu ) {
298                                 if( icu == ipocurve ) {
299                                         KeyBlock *block = key_iter->block.first;
300                                         /* search for matching adrcode */
301                                         while( block ) {
302                                                 if( block->adrcode == ipocurve->adrcode )
303                                                         return block->name;
304                                                 block = block->next;
305                                         }
306                                 }
307                                 icu = icu->next;
308                         }
309                 }
310         }
311
312         /* shouldn't get here unless deleted in UI while BPy object alive */
313         return empty;
314 }
315
316 /*
317  * internal bpy func to get Ipo Curve Name, used by Ipo.c and
318  * KX_BlenderSceneConverter.cpp.
319  *
320  * We are returning a pointer to string constants so there are
321  * no issues with who owns pointers.
322  */
323
324 char *getIpoCurveName( IpoCurve * icu )
325 {
326         switch ( icu->blocktype ) {
327         case ID_MA:
328                 return getname_mat_ei( icu->adrcode );
329         case ID_WO:
330                 return getname_world_ei( icu->adrcode );
331         case ID_CA:
332                 return getname_cam_ei( icu->adrcode );
333         case ID_OB:
334                 return getname_ob_ei( icu->adrcode, 1 );
335                 /* solve: what if EffX/Y/Z are wanted? */
336         case ID_TE:
337                 return getname_tex_ei( icu->adrcode );
338         case ID_LA:
339                 return getname_la_ei( icu->adrcode );
340         case ID_PO:
341                 return getname_ac_ei( icu->adrcode );
342         case ID_CU:
343                 return getname_cu_ei( icu->adrcode );
344         case ID_KE:
345                 /* return "Key";        */
346                 /* ipo curves have no names... that was only meant for drawing the buttons... (ton) */
347                 return get_key_curvename( icu );
348         case ID_SEQ:
349                 return getname_seq_ei( icu->adrcode );
350         case ID_CO:
351                 return getname_co_ei( icu->adrcode );
352         }
353         return NULL;
354 }
355
356 /*
357  * delete a bezTriple from a curve
358  */
359
360 static void del_beztriple( IpoCurve *icu, int index )
361 {
362         int npoints = icu->totvert - 1;
363         BezTriple * tmp = icu->bezt;
364
365         /*
366          * if delete empties list, then delete it, otherwise copy the remaining
367          * points to a new list
368          */
369
370         if( !npoints ) {
371                 icu->bezt = NULL;
372         } else {
373                 icu->bezt =
374                         MEM_mallocN( sizeof( BezTriple ) * npoints, "bezt" );
375                 if( index > 0 )
376                         memmove( icu->bezt, tmp, index * sizeof( BezTriple ) );
377                 if( index < npoints )
378                         memmove( icu->bezt + index, tmp + index + 1,
379                                  ( npoints - index ) * sizeof( BezTriple ) );
380         }
381
382         /* free old list, adjust vertex count */
383         MEM_freeN( tmp );
384         icu->totvert--;
385
386         /* call calchandles_* instead of testhandles_*  */
387         /* I'm not sure this is a complete solution but since we do not */
388         /* deal with curve handles right now, it seems ok */
389         calchandles_ipocurve( icu );
390 }
391
392 /*****************************************************************************/
393 /* Python C_IpoCurve methods:                                                */
394 /*****************************************************************************/
395
396 static PyObject *IpoCurve_setInterpolation( C_IpoCurve * self,
397                                             PyObject * value )
398 {
399         char *interpolationtype = PyString_AsString(value);
400         short id;
401
402         if( !interpolationtype )
403                 return EXPP_ReturnPyObjError( PyExc_TypeError,
404                                 "expected string argument" );
405
406         if( !strcmp( interpolationtype, "Bezier" ) )
407                 id = IPO_BEZ;
408         else if( !strcmp( interpolationtype, "Constant" ) )
409                 id = IPO_CONST;
410         else if( !strcmp( interpolationtype, "Linear" ) )
411                 id = IPO_LIN;
412         else
413                 return EXPP_ReturnPyObjError( PyExc_TypeError,
414                                 "bad interpolation type" );
415
416         self->ipocurve->ipo = id;
417         Py_RETURN_NONE;
418 }
419
420 static PyObject *IpoCurve_getInterpolation( C_IpoCurve * self )
421 {
422         char *str = 0;
423         IpoCurve *icu = self->ipocurve;
424
425         switch( icu->ipo ) {
426         case IPO_BEZ:
427                 str = "Bezier";
428                 break;
429         case IPO_CONST:
430                 str = "Constant";
431                 break;
432         case IPO_LIN:
433                 str = "Linear";
434                 break;
435         default:
436                 return EXPP_ReturnPyObjError( PyExc_TypeError,
437                                 "unknown interpolation type" );
438         }
439
440         return PyString_FromString( str );
441 }
442
443 static PyObject * IpoCurve_setExtrapolation( C_IpoCurve * self,
444                 PyObject * value )
445 {
446         char *extrapolationtype = PyString_AsString(value);
447         short id;
448
449         if( !extrapolationtype )
450                 return EXPP_ReturnPyObjError( PyExc_TypeError,
451                                 "expected string argument" );
452
453         if( !strcmp( extrapolationtype, "Constant" ) )
454                 id = 0;
455         else if( !strcmp( extrapolationtype, "Extrapolation" ) )
456                 id = 1;
457         else if( !strcmp( extrapolationtype, "Cyclic" ) )
458                 id = 2;
459         else if( !strcmp( extrapolationtype, "Cyclic_extrapolation" ) )
460                 id = 3;
461         else
462                 return EXPP_ReturnPyObjError( PyExc_TypeError,
463                                 "bad interpolation type" );
464
465         self->ipocurve->extrap = id;
466         Py_RETURN_NONE;
467 }
468
469 static PyObject *IpoCurve_getExtrapolation( C_IpoCurve * self )
470 {
471         char *str;
472         IpoCurve *icu = self->ipocurve;
473
474         switch( icu->extrap ) {
475         case 0:
476                 str = "Constant";
477                 break;
478         case 1:
479                 str = "Extrapolation";
480                 break;
481         case 2:
482                 str = "Cyclic";
483                 break;
484         case 3:
485                 str = "Cyclic_extrapolation";
486                 break;
487         default:
488                 return EXPP_ReturnPyObjError( PyExc_TypeError,
489                                 "bad extrapolation type" );
490         }
491
492         return PyString_FromString( str );
493 }
494
495 /*
496  * append a new BezTriple to curve
497  */
498
499 static PyObject *IpoCurve_append( C_IpoCurve * self, PyObject * value )
500 {
501         float x, y;
502         IpoCurve *icu = self->ipocurve;
503
504         /* if args is a already a beztriple, tack onto end of list */
505         if( BPy_BezTriple_Check ( value ) ) {
506                 BPy_BezTriple *bobj = (BPy_BezTriple *)value;
507
508                 BezTriple *newb = MEM_callocN( (icu->totvert+1)*sizeof(BezTriple),
509                                 "BPyBeztriple" );
510                 if( icu->bezt ) {
511                         memcpy( newb, icu->bezt, ( icu->totvert )*sizeof( BezTriple ) );
512                         MEM_freeN( icu->bezt );
513                 }
514                 icu->bezt = newb;
515                 memcpy( &icu->bezt[icu->totvert], bobj->beztriple,
516                                 sizeof( BezTriple ) );
517                 icu->totvert++;
518                 calchandles_ipocurve( icu );
519         
520         /* otherwise try to get two floats and add to list */
521         } else {
522                 PyObject *xobj, *yobj;
523                 xobj = PyNumber_Float( PyTuple_GetItem( value, 0 ) );
524                 yobj = PyNumber_Float( PyTuple_GetItem( value, 1 ) );
525
526                 if( !xobj || !yobj )
527                         return EXPP_ReturnPyObjError( PyExc_TypeError,
528                                 "expected tuple of floats" );
529
530                 x = (float)PyFloat_AsDouble( xobj );
531                 Py_DECREF( xobj );
532                 y = (float)PyFloat_AsDouble( yobj );
533                 Py_DECREF( yobj );
534                 insert_vert_icu( icu, x, y);
535         }
536
537         Py_RETURN_NONE;
538 }
539
540 /*
541    Function:  IpoCurve_delBezier
542    Bpy:       Blender.Ipocurve.delBezier(0)
543
544    Delete an BezTriple from an IPO curve.
545    example:
546        ipo = Blender.Ipo.Get('ObIpo')
547        cu = ipo.getCurve('LocX')
548        cu.delBezier(0)
549 */
550
551 static PyObject *IpoCurve_delBezier( C_IpoCurve * self, PyObject * args )
552 {
553         int index;
554
555         if( !PyArg_ParseTuple( args, "i", &index ) )
556                 return EXPP_ReturnPyObjError( PyExc_TypeError,
557                                 "expected int argument" );
558
559         /* if index is negative, count from end of list */
560         if( index < 0 )
561                 index += self->ipocurve->totvert;
562         /* check range of index */
563         if( index < 0 || index > self->ipocurve->totvert - 1 )
564                 return EXPP_ReturnPyObjError( PyExc_IndexError,
565                                 "index outside of list" );
566
567         del_beztriple( self->ipocurve, index );
568
569         Py_RETURN_NONE;
570 }
571
572 static PyObject *IpoCurve_Recalc( C_IpoCurve * self )
573 {
574         IpoCurve *icu = self->ipocurve;
575
576         /* testhandles_ipocurve (icu); */
577         /* call calchandles_* instead of testhandles_*  */
578         /* I'm not sure this is a complete solution but since we do not */
579         /* deal with curve handles right now, it seems ok */
580         calchandles_ipocurve( icu );
581         sort_time_ipocurve( icu );
582
583         Py_INCREF( Py_None );
584         return Py_None;
585 }
586
587 static PyObject *IpoCurve_getName( C_IpoCurve * self )
588 {
589         switch ( self->ipocurve->blocktype ) {
590         case ID_OB:
591                 return PyString_FromString( getname_ob_ei( self->ipocurve->adrcode, 1 ) );      /* solve: what if EffX/Y/Z are wanted? */
592         case ID_TE:
593                 return PyString_FromString( getname_tex_ei
594                                             ( self->ipocurve->adrcode ) );
595         case ID_LA:
596                 return PyString_FromString( getname_la_ei
597                                             ( self->ipocurve->adrcode ) );
598         case ID_MA:
599                 return PyString_FromString( getname_mat_ei
600                                             ( self->ipocurve->adrcode ) );
601         case ID_CA:
602                 return PyString_FromString( getname_cam_ei
603                                             ( self->ipocurve->adrcode ) );
604         case ID_WO:
605                 return PyString_FromString( getname_world_ei
606                                             ( self->ipocurve->adrcode ) );
607         case ID_PO:
608                 return PyString_FromString( getname_ac_ei
609                                             ( self->ipocurve->adrcode ) );
610         case ID_CU:
611                 return PyString_FromString( getname_cu_ei
612                                             ( self->ipocurve->adrcode ) );
613         case ID_KE:
614                 return PyString_FromString( get_key_curvename( self->ipocurve ) );
615         case ID_SEQ:
616                 return PyString_FromString( getname_seq_ei
617                                             ( self->ipocurve->adrcode ) );
618         case ID_CO:
619                 return PyString_FromString( getname_co_ei
620                                             ( self->ipocurve->adrcode ) );
621         default:
622                 return EXPP_ReturnPyObjError( PyExc_TypeError,
623                                 "This function doesn't support this ipocurve type yet" );
624         }
625 }
626
627 static PyObject *IpoCurve_getPoints( C_IpoCurve * self )
628 {
629         BezTriple *bezt;
630         PyObject *po;
631         int i;
632         PyObject *list = PyList_New( self->ipocurve->totvert );
633
634         if( !list )
635                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
636                                 "PyList_New() failed" );
637
638         for( bezt = self->ipocurve->bezt, i = 0;
639                         i < self->ipocurve->totvert; i++, bezt++ ) {
640                 po = BezTriple_CreatePyObject( bezt );
641                 if( !po ) {
642                         Py_DECREF( list );
643                         return NULL; /* This is okay since the error is alredy set */
644                 }
645                 PyList_SET_ITEM( list, i, po );
646         }
647         return list;
648 }
649
650 /*****************************************************************************/
651 /* Function:    IpoCurve_compare                                                 */
652 /* Description: This compares 2 python types, == or != only.                         */
653 /*****************************************************************************/
654 static int IpoCurve_compare( C_IpoCurve * a, C_IpoCurve * b )
655 {
656         return ( a->ipocurve == b->ipocurve ) ? 0 : -1;
657 }
658
659 /*****************************************************************************/
660 /* Function:    IpoCurve_repr                                                */
661 /* Description: This is a callback function for the C_IpoCurve type. It      */
662 /*              builds a meaningful string to represent ipocurve objects.    */
663 /*****************************************************************************/
664 static PyObject *IpoCurve_repr( C_IpoCurve * self )
665 {
666         return PyString_FromFormat( "[IpoCurve \"%s\"]",
667                         getIpoCurveName( self->ipocurve ) );
668 }
669
670 /* Three Python IpoCurve_Type helper functions needed by the Object module: */
671
672 /*****************************************************************************/
673 /* Function:    IpoCurve_CreatePyObject                                     */
674 /* Description: This function will create a new C_IpoCurve from an existing  */
675 /*              Blender ipo structure.                                       */
676 /*****************************************************************************/
677 PyObject *IpoCurve_CreatePyObject( IpoCurve * icu )
678 {
679         C_IpoCurve *pyipo;
680
681         pyipo = ( C_IpoCurve * ) PyObject_NEW( C_IpoCurve, &IpoCurve_Type );
682
683         if( !pyipo )
684                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
685                                               "couldn't create C_IpoCurve object" );
686
687         pyipo->ipocurve = icu;
688
689         return ( PyObject * ) pyipo;
690 }
691
692 /*****************************************************************************/
693 /* Function:    IpoCurve_FromPyObject                                       */
694 /* Description: This function returns the Blender ipo from the given         */
695 /*              PyObject.                                                    */
696 /*****************************************************************************/
697 IpoCurve *IpoCurve_FromPyObject( PyObject * pyobj )
698 {
699         return ( ( C_IpoCurve * ) pyobj )->ipocurve;
700 }
701
702 /*
703  * get the value of an Ipocurve at a particular time
704  */
705
706 static PyObject *IpoCurve_getCurval( C_IpoCurve * self, PyObject * args )
707 {
708         float time;
709         PyObject *pyfloat = PyNumber_Float( args );
710
711         if( !pyfloat )
712                 return EXPP_ReturnPyObjError( PyExc_TypeError,
713                                 "expected float argument" );
714         time = ( float )PyFloat_AS_DOUBLE( pyfloat );
715         Py_DECREF( pyfloat );
716
717         return PyFloat_FromDouble( ( double ) eval_icu( self->ipocurve, time ) );
718 }
719
720 /*
721  * set the value of an Ipocurve at a particular time
722  */
723
724 static int IpoCurve_setCurval( C_IpoCurve * self, PyObject * key, 
725                 PyObject * value )
726 {
727         float time, curval;
728         PyObject *pyfloat;
729
730         /* make sure time, curval are both floats */
731
732         pyfloat = PyNumber_Float( key );
733         if( !pyfloat )
734                 return EXPP_ReturnIntError( PyExc_TypeError,
735                                 "expected float key" );
736         time = ( float )PyFloat_AS_DOUBLE( pyfloat );
737         Py_DECREF( pyfloat );
738
739         pyfloat = PyNumber_Float( value );
740         if( !pyfloat )
741                 return EXPP_ReturnIntError( PyExc_TypeError,
742                                 "expected float argument" );
743         curval = ( float )PyFloat_AS_DOUBLE( pyfloat );
744         Py_DECREF( pyfloat );
745
746         /* insert a key at the specified time */
747
748         insert_vert_icu( self->ipocurve, time, curval );
749         allspace(REMAKEIPO, 0);
750         return 0;
751 }
752
753 /***************************************************************************/
754 /* Function:      IpoCurve_evaluate( time )                                */
755 /* Description:   Evaluates IPO curve at the given time.                   */
756 /***************************************************************************/
757
758 static PyObject *IpoCurve_evaluate( C_IpoCurve * self, PyObject * args )
759 {
760         float time = 0;
761         double eval = 0;
762
763         /* expecting float */
764         if( !PyArg_ParseTuple( args, "f", &time ) )
765                 return ( EXPP_ReturnPyObjError
766                          ( PyExc_TypeError, "expected float argument" ) );
767
768         eval = ( double ) eval_icu( self->ipocurve, time );
769
770         return PyFloat_FromDouble( eval );
771
772 }
773
774 static PyObject *IpoCurve_getDriver( C_IpoCurve * self )
775 {
776         if( !self->ipocurve->driver )
777                 return PyInt_FromLong( 0 );     
778         else {
779                 if (self->ipocurve->driver->type == IPO_DRIVER_TYPE_NORMAL)
780                         return PyInt_FromLong( 1 );
781                 if (self->ipocurve->driver->type == IPO_DRIVER_TYPE_PYTHON)
782                         return PyInt_FromLong( 2 );
783         }
784         return EXPP_ReturnPyObjError( PyExc_RuntimeError,
785                         "unknown driver type, internal error" );
786         
787 }
788
789 /*
790         sets the driver to
791         0: disabled
792         1: enabled (object)
793         2: enabled (python expression)
794 */
795 static int IpoCurve_setDriver( C_IpoCurve * self, PyObject * args )
796 {
797         IpoCurve *ipo = self->ipocurve;
798         int type;
799         if( !PyInt_Check( args ) )
800                 return EXPP_ReturnIntError( PyExc_TypeError,
801                                 "expected int argument 0 or 1 " );
802         
803         type = PyInt_AS_LONG( args );
804         
805         if (type < 0 || type > 2)
806                 return EXPP_ReturnIntError( PyExc_ValueError,
807                                 "expected int argument 0, 1 or 2" );
808         
809         if (type==0) { /* disable driver */
810                 if( ipo->driver ) {
811                         MEM_freeN( ipo->driver );
812                         ipo->driver = NULL;                     
813                 }
814         } else {
815                 if( !ipo->driver ) { /*add driver if its not there */
816                         ipo->driver = MEM_callocN( sizeof(IpoDriver), "ipo driver" );
817                         ipo->driver->blocktype = ID_OB;
818                         ipo->driver->adrcode = OB_LOC_X;
819                 }
820                 
821                 if (type==1 && ipo->driver->type != IPO_DRIVER_TYPE_NORMAL) {
822                         ipo->driver->type = IPO_DRIVER_TYPE_NORMAL;
823                         ipo->driver->ob = NULL;
824                         ipo->driver->flag &= ~IPO_DRIVER_FLAG_INVALID;
825                         
826                 } else if (type==2 && ipo->driver->type != IPO_DRIVER_TYPE_PYTHON) {
827                         ipo->driver->type = IPO_DRIVER_TYPE_PYTHON;
828                         /* we should probably set ipo->driver->ob, but theres no way to do it properly */
829                         ipo->driver->ob = NULL;
830                 }
831         }
832         
833         return 0;
834 }
835
836 static PyObject *IpoCurve_getDriverObject( C_IpoCurve * self )
837 {
838         IpoCurve *ipo = self->ipocurve;
839         
840         if( ipo->driver )
841                 return Object_CreatePyObject( ipo->driver->ob );
842
843         Py_RETURN_NONE;
844 }
845
846 static int IpoCurve_setDriverObject( C_IpoCurve * self, PyObject * arg )
847 {
848         IpoCurve *ipo = self->ipocurve;
849
850         if( !ipo->driver )
851                 return EXPP_ReturnIntError( PyExc_RuntimeError,
852                                               "This IpoCurve does not have an active driver" );
853
854         if(!BPy_Object_Check(arg) )
855                 return EXPP_ReturnIntError( PyExc_RuntimeError,
856                                               "expected an object argument" );
857         ipo->driver->ob = ((BPy_Object *)arg)->object;
858
859         DAG_scene_sort(G.scene);        
860         
861         return 0;
862 }
863
864 static PyObject *IpoCurve_getDriverChannel( C_IpoCurve * self )
865 {
866         if( !self->ipocurve->driver )
867                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
868                                               "This IpoCurve does not have an active driver" );
869
870         return PyInt_FromLong( self->ipocurve->driver->adrcode );       
871 }
872
873 static int IpoCurve_setDriverChannel( C_IpoCurve * self, PyObject * args )
874 {
875         IpoCurve *ipo = self->ipocurve;
876         short param;
877
878         if( !ipo->driver )
879                 return EXPP_ReturnIntError( PyExc_RuntimeError,
880                                 "This IpoCurve does not have an active driver" );
881
882         if( !PyInt_Check( args ) )
883                 return EXPP_ReturnIntError( PyExc_TypeError,
884                                 "expected int argument" );
885
886         param  = (short)PyInt_AS_LONG ( args );
887         if( ( param >= OB_LOC_X && param <= OB_LOC_Z )
888                         || ( param >= OB_ROT_X && param <= OB_ROT_Z )
889                         || ( param >= OB_SIZE_X && param <= OB_SIZE_Z ) ) {
890                 ipo->driver->adrcode = (short)PyInt_AS_LONG ( args );
891                 return 0;
892         }
893
894         return EXPP_ReturnIntError( PyExc_ValueError, "invalid int argument" );
895 }
896
897 static PyObject *IpoCurve_getDriverExpression( C_IpoCurve * self )
898 {
899         IpoCurve *ipo = self->ipocurve;
900         
901         if( ipo->driver && ipo->driver->type == IPO_DRIVER_TYPE_PYTHON )
902                 return PyString_FromString( ipo->driver->name );
903
904         Py_RETURN_NONE;
905 }
906
907 static int IpoCurve_setDriverExpression( C_IpoCurve * self, PyObject * arg )
908 {
909         IpoCurve *ipo = self->ipocurve;
910         char *exp; /* python expression */
911         
912         if( !ipo->driver )
913                 return EXPP_ReturnIntError( PyExc_RuntimeError,
914                         "This IpoCurve does not have an active driver" );
915
916         if (ipo->driver->type != IPO_DRIVER_TYPE_PYTHON)
917                 return EXPP_ReturnIntError( PyExc_RuntimeError,
918                         "This IpoCurve is not a python expression set the driver attribute to 2" );
919         
920         if(!PyString_Check(arg) )
921                 return EXPP_ReturnIntError( PyExc_RuntimeError,
922                                               "expected a string argument" );
923         
924         exp = PyString_AsString(arg);
925         if (strlen(exp)>127)
926                 return EXPP_ReturnIntError( PyExc_ValueError,
927                                               "string is too long, use 127 characters or less" );
928
929         strcpy(ipo->driver->name, exp);
930         return 0;
931 }
932
933 static PyObject *M_IpoCurve_ExtendDict( void )
934 {
935         PyObject *EM = PyConstant_New(  );
936
937         if( EM ) {
938                 BPy_constant *d = ( BPy_constant * ) EM;
939
940                 PyConstant_Insert( d, "CONST", PyInt_FromLong( IPO_HORIZ ) );
941                 PyConstant_Insert( d, "EXTRAP", PyInt_FromLong( IPO_DIR ) );
942                 PyConstant_Insert( d, "CYCLIC", PyInt_FromLong( IPO_CYCL ) );
943                 PyConstant_Insert( d, "CYCLIC_EXTRAP", PyInt_FromLong( IPO_CYCLX ) );
944         }
945         return EM;
946 }
947
948 static PyObject *M_IpoCurve_InterpDict( void )
949 {
950         PyObject *IM = PyConstant_New(  );
951
952         if( IM ) {
953                 BPy_constant *d = ( BPy_constant * ) IM;
954
955                 PyConstant_Insert( d, "CONST", PyInt_FromLong( IPO_CONST ) );
956                 PyConstant_Insert( d, "LINEAR", PyInt_FromLong( IPO_LIN ) );
957                 PyConstant_Insert( d, "BEZIER", PyInt_FromLong( IPO_BEZ ) );
958         }
959         return IM;
960 }
961
962 /*****************************************************************************/
963 /* Function:              IpoCurve_Init                                      */
964 /*****************************************************************************/
965 PyObject *IpoCurve_Init( void )
966 {
967         PyObject *submodule;
968         PyObject *ExtendTypes = M_IpoCurve_ExtendDict( );
969         PyObject *InterpTypes = M_IpoCurve_InterpDict( );
970
971         if( PyType_Ready( &IpoCurve_Type ) < 0)
972                 return NULL;
973
974         submodule =
975                 Py_InitModule3( "Blender.IpoCurve", M_IpoCurve_methods,
976                                 M_IpoCurve_doc );
977
978         PyModule_AddIntConstant( submodule, "LOC_X", OB_LOC_X );
979         PyModule_AddIntConstant( submodule, "LOC_Y", OB_LOC_Y );
980         PyModule_AddIntConstant( submodule, "LOC_Z", OB_LOC_Z );        
981         PyModule_AddIntConstant( submodule, "ROT_X", OB_ROT_X );
982         PyModule_AddIntConstant( submodule, "ROT_Y", OB_ROT_Y );
983         PyModule_AddIntConstant( submodule, "ROT_Z", OB_ROT_Z );        
984         PyModule_AddIntConstant( submodule, "SIZE_X", OB_SIZE_X );
985         PyModule_AddIntConstant( submodule, "SIZE_Y", OB_SIZE_Y );
986         PyModule_AddIntConstant( submodule, "SIZE_Z", OB_SIZE_Z );      
987
988         if( ExtendTypes )
989                 PyModule_AddObject( submodule, "ExtendTypes", ExtendTypes );
990         if( InterpTypes )
991                 PyModule_AddObject( submodule, "InterpTypes", InterpTypes );
992
993         return submodule;
994 }
995
996 /*
997  */
998
999 static PyObject *IpoCurve_newgetInterp( C_IpoCurve * self )
1000 {
1001         return PyInt_FromLong( self->ipocurve->ipo );   
1002 }
1003
1004 static int IpoCurve_newsetInterp( C_IpoCurve * self, PyObject * value )
1005 {
1006         return EXPP_setIValueRange( value, &self->ipocurve->ipo,
1007                         IPO_CONST, IPO_BEZ, 'h' );
1008 }
1009
1010 static PyObject *IpoCurve_newgetExtend( C_IpoCurve * self )
1011 {
1012         return PyInt_FromLong( self->ipocurve->extrap );        
1013 }
1014
1015 static int IpoCurve_newsetExtend( C_IpoCurve * self, PyObject * value )
1016 {
1017         return EXPP_setIValueRange( value, &self->ipocurve->extrap,
1018                         IPO_HORIZ, IPO_CYCLX, 'h' );
1019 }
1020
1021 static PyObject *IpoCurve_getFlag( C_IpoCurve * self, void *type )
1022 {
1023         if (self->ipocurve->flag & (int)type)
1024                 Py_RETURN_TRUE;
1025         else
1026                 Py_RETURN_FALSE;
1027 }
1028
1029 static int IpoCurve_setFlag( C_IpoCurve * self, PyObject *value, void *type )
1030 {
1031         int param = PyObject_IsTrue( value );
1032         if( param == -1 )
1033                 return EXPP_ReturnIntError( PyExc_TypeError,
1034                                 "expected True/False or 0/1" );
1035         
1036         if (param)
1037                 self->ipocurve->flag |= (int)type;
1038         else
1039                 self->ipocurve->flag &= ~(int)type;
1040         
1041         return 0;
1042 }
1043
1044
1045 /* #####DEPRECATED###### */
1046
1047 static PyObject *IpoCurve_addBezier( C_IpoCurve * self, PyObject * value )
1048 {
1049         float x, y;
1050         int npoints;
1051         IpoCurve *icu;
1052         BezTriple *bzt, *tmp;
1053         static char name[10] = "mlml";
1054         if( !PyArg_ParseTuple( value, "ff", &x, &y ) )
1055                 return ( EXPP_ReturnPyObjError
1056                          ( PyExc_TypeError, "expected a tuple of 2 floats" ) );
1057
1058         icu = self->ipocurve;
1059         npoints = icu->totvert;
1060         tmp = icu->bezt;
1061         icu->bezt = MEM_mallocN( sizeof( BezTriple ) * ( npoints + 1 ), name );
1062         if( tmp ) {
1063                 memmove( icu->bezt, tmp, sizeof( BezTriple ) * npoints );
1064                 MEM_freeN( tmp );
1065         }
1066         memmove( icu->bezt + npoints, icu->bezt, sizeof( BezTriple ) );
1067         icu->totvert++;
1068         bzt = icu->bezt + npoints;
1069         bzt->vec[0][0] = x - 1;
1070         bzt->vec[1][0] = x;
1071         bzt->vec[2][0] = x + 1;
1072         bzt->vec[0][1] = y - 1;
1073         bzt->vec[1][1] = y;
1074         bzt->vec[2][1] = y + 1;
1075         /* set handle type to Auto */
1076         bzt->h1 = HD_AUTO;
1077         bzt->h2 = HD_AUTO;
1078
1079         Py_RETURN_NONE;
1080 }