-NLA module added
[blender.git] / source / blender / python / api2_2x / NLA.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Joseph Gilbert
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 #include "NLA.h"
33 #include "Object.h"
34 #include <BKE_action.h>
35 #include <BKE_global.h>
36 #include <BKE_main.h>
37 #include "Types.h"
38
39 /*****************************************************************************/
40 /* Python API function prototypes for the NLA module.                    */
41 /*****************************************************************************/
42 static PyObject *M_NLA_NewAction (PyObject * self, PyObject * args);
43 static PyObject *M_NLA_CopyAction (PyObject * self, PyObject * args);
44 static PyObject *M_NLA_GetActions(PyObject* self);
45
46 /*****************************************************************************/
47 /* The following string definitions are used for documentation strings.          */
48 /* In Python these will be written to the console when doing a           */
49 /* Blender.Armature.NLA.__doc__                                  */
50 /*****************************************************************************/
51 char M_NLA_doc[] = "The Blender NLA module -This module provides control over  Armature keyframing in Blender.";
52 char M_NLA_NewAction_doc[] = "(name) - Create new action for linking to an object.";
53 char M_NLA_CopyAction_doc[] = "(name) - Copy action and return copy.";
54 char M_NLA_GetActions_doc[] = "(name) - Returns a dictionary of actions.";
55
56 /*****************************************************************************/
57 /* Python method structure definition for Blender.Armature.NLA module:                   */
58 /*****************************************************************************/
59 struct PyMethodDef M_NLA_methods[] = {
60   {"NewAction", (PyCFunction) M_NLA_NewAction, METH_VARARGS,
61           M_NLA_NewAction_doc},
62   {"CopyAction", (PyCFunction) M_NLA_CopyAction, METH_VARARGS,
63           M_NLA_CopyAction_doc},
64   {"GetActions", (PyCFunction) M_NLA_GetActions, METH_NOARGS,
65           M_NLA_GetActions_doc},
66   {NULL, NULL, 0, NULL}
67 };
68 /*****************************************************************************/
69 /* Python BPy_Action methods declarations:                                                                                                                                               */
70 /*****************************************************************************/
71 static PyObject *Action_getName (BPy_Action * self);
72 static PyObject *Action_setName (BPy_Action * self, PyObject * args);
73 static PyObject *Action_setActive (BPy_Action * self, PyObject * args);
74 static PyObject *Action_getChannelIpo(BPy_Action * self, PyObject * args);
75 static PyObject *Action_removeChannel(BPy_Action * self, PyObject * args);
76 static PyObject *Action_getAllChannelIpos(BPy_Action*self);
77
78 /*****************************************************************************/
79 /* Python BPy_Action methods table:                                      */
80 /*****************************************************************************/
81 static PyMethodDef BPy_Action_methods[] = {
82   /* name, method, flags, doc */
83   {"getName", (PyCFunction) Action_getName, METH_NOARGS,
84    "() - return Action name"},
85   {"setName", (PyCFunction) Action_setName, METH_VARARGS,
86    "(str) - rename Action"},
87   {"setActive", (PyCFunction) Action_setActive, METH_VARARGS,
88    "(str) -set this action as the active action for an object"},
89   {"getChannelIpo", (PyCFunction) Action_getChannelIpo, METH_VARARGS,
90    "(str) -get the Ipo from a named action channel in this action"},
91   {"removeChannel", (PyCFunction) Action_removeChannel, METH_VARARGS,
92    "(str) -remove the channel from the action"},
93   {"getAllChannelIpos", (PyCFunction)Action_getAllChannelIpos, METH_NOARGS,
94         "() - Return a dict of (name:ipo)-keys containing each channel in the object's action"},
95   {NULL, NULL, 0, NULL}
96 };
97
98 /*****************************************************************************/
99 /* Python TypeAction callback function prototypes:                               */
100 /*****************************************************************************/
101 static void Action_dealloc (BPy_Action * bone);
102 static PyObject *Action_getAttr (BPy_Action * bone, char *name);
103 static int Action_setAttr (BPy_Action * bone, char *name, PyObject * v);
104 static PyObject *Action_repr (BPy_Action * bone);
105
106 /*****************************************************************************/
107 /* Python TypeAction structure definition:                               */
108 /*****************************************************************************/
109 PyTypeObject Action_Type = {
110   PyObject_HEAD_INIT (NULL) 0,    /* ob_size */
111   "Blender Action",                                       /* tp_name */
112   sizeof (BPy_Action),                            /* tp_basicsize */
113   0,                                                                      /* tp_itemsize */
114   /* methods */
115   (destructor) Action_dealloc,            /* tp_dealloc */
116   0,                                                                     /* tp_print */
117   (getattrfunc) Action_getAttr,          /* tp_getattr */
118   (setattrfunc) Action_setAttr,          /* tp_setattr */
119   0,                                                         /* tp_compare */
120   (reprfunc) Action_repr,                            /* tp_repr */
121   0,                                                                     /* tp_as_number */
122   0,                                                                     /* tp_as_sequence */
123   0,                                                                     /* tp_as_mapping */
124   0,                                                                     /* tp_as_hash */
125   0, 0, 0, 0, 0, 0,
126   0,                                                                     /* tp_doc */
127   0, 0, 0, 0, 0, 0,
128   BPy_Action_methods,                        /* tp_methods */
129   0,                                                                     /* tp_members */
130 };
131
132 //-------------------------------------------------------------------------------------------------------------------------------
133 static PyObject *
134 M_NLA_NewAction (PyObject * self, PyObject * args)
135 {
136   char *name_str = "DefaultAction";
137   BPy_Action *py_action = NULL; /* for Action Data object wrapper in Python */
138   bAction *bl_action = NULL;            /* for actual Action Data we create in Blender */
139
140   if (!PyArg_ParseTuple (args, "|s", &name_str)){
141     EXPP_ReturnPyObjError (PyExc_AttributeError,
142                                    "expected string or nothing");
143         return NULL;
144   }
145
146   //Create new action globally
147  bl_action = alloc_libblock(&G.main->action, ID_AC, name_str);
148  bl_action->id.flag |= LIB_FAKEUSER;
149  bl_action->id.us++;
150
151   // now create the wrapper obj in Python
152   if (bl_action)                                
153     py_action = (BPy_Action *) PyObject_NEW (BPy_Action, &Action_Type);
154   else{
155     EXPP_ReturnPyObjError (PyExc_RuntimeError,
156                                    "couldn't create Action Data in Blender");
157         return NULL;
158   }
159
160   if (py_action == NULL){
161     EXPP_ReturnPyObjError (PyExc_MemoryError,
162                                    "couldn't create Action Data object");
163         return NULL;
164   }
165
166   py_action->action = bl_action;        // link Python action wrapper with Blender Action
167
168   Py_INCREF(py_action);
169   return (PyObject *) py_action;
170 }
171
172 static PyObject *
173 M_NLA_CopyAction(PyObject* self, PyObject * args)
174 {
175         BPy_Action *py_action = NULL;
176         bAction *copyAction = NULL;
177
178         if (!PyArg_ParseTuple (args, "O!", &Action_Type, &py_action)){
179                 EXPP_ReturnPyObjError (PyExc_AttributeError,
180                                    "expected python action type");
181                 return NULL;
182   }
183         copyAction =  copy_action(py_action->action);
184         return Action_CreatePyObject (copyAction);
185 }
186
187 static PyObject *
188 M_NLA_GetActions(PyObject* self)
189 {
190         PyObject *dict=PyDict_New ();
191         bAction *action = NULL;
192
193         for(action = G.main->action.first; action; action = action->id.next){
194         PyObject * py_action = Action_CreatePyObject (action);
195                 if (py_action) {
196                         // Insert dict entry using the bone name as key
197                         if (PyDict_SetItemString (dict, action->id.name + 2, py_action) !=0) {
198                                 Py_DECREF (py_action);
199                                 Py_DECREF ( dict );
200                                 
201                                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
202                                                 "NLA_GetActions: couldn't set dict item");
203                         }
204                         Py_DECREF (py_action);
205                 } else {
206                         Py_DECREF ( dict );
207                         return (PythonReturnErrorObject (PyExc_RuntimeError,
208                                 "NLA_GetActions: could not create Action object"));
209                 }
210         }       
211         return dict;
212 }
213
214 /*****************************************************************************/
215 /* Function:    NLA_Init                                                 */
216 /*****************************************************************************/
217 PyObject *
218 NLA_Init (void)
219 {
220   PyObject *submodule;
221
222   Action_Type.ob_type = &PyType_Type;
223
224   submodule = Py_InitModule3 ("Blender.Armature.NLA",
225                               M_NLA_methods, M_NLA_doc);
226
227   return (submodule);
228 }
229
230 //-------------------------------------------------------------------------------------------------------------------------------
231 static PyObject *
232 Action_getName (BPy_Action * self)
233 {
234   PyObject *attr = NULL;
235
236   if (!self->action)
237     (EXPP_ReturnPyObjError (PyExc_RuntimeError,
238                             "couldn't get attribute from a NULL action"));
239
240   attr = PyString_FromString (self->action->id.name+2);
241
242   if (attr)
243     return attr;
244
245   return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
246                                  "couldn't get Action.name attribute"));
247 }
248 //-------------------------------------------------------------------------------------------------------------------------------
249 static PyObject *
250 Action_setName (BPy_Action * self, PyObject * args)
251 {
252   char *name;
253
254   if (!self->action)
255     (EXPP_ReturnPyObjError (PyExc_RuntimeError,
256                             "couldn't get attribute from a NULL action"));
257
258   if (!PyArg_ParseTuple (args, "s", &name))
259     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
260                                    "expected string argument"));
261
262   //change name
263   strcpy(self->action->id.name+2, name);
264
265   Py_INCREF (Py_None);
266   return Py_None;
267 }
268
269 static PyObject *
270 Action_setActive(BPy_Action * self, PyObject * args)
271 {
272   BPy_Object *object;
273
274   if (!self->action)
275     (EXPP_ReturnPyObjError (PyExc_RuntimeError,
276                             "couldn't get attribute from a NULL action"));
277
278   if (!PyArg_ParseTuple (args, "O!", &Object_Type, &object))
279     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
280                                    "expected python object argument"));
281
282   if(object->object->type != OB_ARMATURE) {
283     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
284                                    "object not of type armature"));
285   }
286
287   //set the active action to object
288   object->object->action = self->action;
289
290   Py_INCREF (Py_None);
291   return Py_None;
292 }
293
294 static PyObject *
295 Action_getChannelIpo(BPy_Action * self, PyObject * args)
296 {
297         char *chanName;
298         bActionChannel *chan;
299
300         if(!PyArg_ParseTuple(args, "s", &chanName)){
301                 EXPP_ReturnPyObjError(PyExc_AttributeError, "string expected");
302                 return NULL;
303         }
304
305         chan = get_named_actionchannel(self->action,chanName);
306         if(chan == NULL){
307                 EXPP_ReturnPyObjError(PyExc_AttributeError, "no channel with that name...");
308                 return NULL;
309         }
310
311         //return IPO
312     return Ipo_CreatePyObject (chan->ipo);
313 }
314
315 static PyObject *
316 Action_removeChannel(BPy_Action * self, PyObject * args)
317 {
318         char *chanName;
319         bActionChannel *chan;
320
321         if(!PyArg_ParseTuple(args, "s", &chanName)){
322                 EXPP_ReturnPyObjError(PyExc_AttributeError, "string expected");
323                 return NULL;
324         }
325
326         chan = get_named_actionchannel(self->action,chanName);
327         if(chan == NULL){
328                 EXPP_ReturnPyObjError(PyExc_AttributeError, "no channel with that name...");
329                 return NULL;
330         }
331
332         //release ipo
333         if(chan->ipo)
334                 chan->ipo->id.us--;
335
336         //remove channel
337         BLI_freelinkN (&self->action->chanbase, chan);
338
339         Py_INCREF (Py_None);
340         return (Py_None);
341 }
342
343 static PyObject *Action_getAllChannelIpos (BPy_Action *self)
344 {
345         PyObject *dict=PyDict_New ();
346         bActionChannel *chan = NULL;
347
348         for(chan = self->action->chanbase.first; chan; chan = chan->next){
349         PyObject * ipo_attr = Ipo_CreatePyObject (chan->ipo);
350                 if (ipo_attr) {
351                         // Insert dict entry using the bone name as key
352                         if (PyDict_SetItemString (dict, chan->name, ipo_attr) !=0) {
353                                 Py_DECREF ( ipo_attr );
354                                 Py_DECREF ( dict );
355                                 
356                                 return EXPP_ReturnPyObjError (PyExc_RuntimeError,
357                                                 "Action_getAllChannelIpos: couldn't set dict item");
358                         }
359                         Py_DECREF (ipo_attr);
360                 } else {
361                         Py_DECREF ( dict );
362                         return (PythonReturnErrorObject (PyExc_RuntimeError,
363                                 "Action_getAllChannelIpos: could not create Ipo object"));
364                 }
365         }       
366         return dict;
367 }
368
369 //-------------------------------------------------------------------------------------------------------------------------------
370 static void
371 Action_dealloc (BPy_Action * self)
372 {
373     PyObject_DEL (self);
374 }
375 //-------------------------------------------------------------------------------------------------------------------------------
376 static PyObject *
377 Action_getAttr (BPy_Action * self, char *name)
378 {
379   PyObject *attr = Py_None;
380
381   if (strcmp (name, "name") == 0)
382     attr = Action_getName (self);
383   else if (strcmp (name, "__members__") == 0)  {
384       attr = Py_BuildValue ("[s]",
385                             "name");
386     }
387
388   if (!attr)
389     return (EXPP_ReturnPyObjError (PyExc_MemoryError,
390                                    "couldn't create PyObject"));
391
392   if (attr != Py_None)
393     return attr;                /* member attribute found, return it */
394
395   /* not an attribute, search the methods table */
396   return Py_FindMethod (BPy_Action_methods, (PyObject *) self, name);
397 }
398
399 //-------------------------------------------------------------------------------------------------------------------------------
400 static int
401 Action_setAttr (BPy_Action * self, char *name, PyObject * value)
402 {
403   PyObject *valtuple;
404   PyObject *error = NULL;
405
406   valtuple = Py_BuildValue ("(O)", value);      /* the set* functions expect a tuple */
407
408   if (!valtuple)
409     return EXPP_ReturnIntError (PyExc_MemoryError,
410                                 "ActionSetAttr: couldn't create tuple");
411
412   if (strcmp (name, "name") == 0)
413     error = Action_setName (self, valtuple);
414   else
415     {                           /* Error */
416       Py_DECREF (valtuple);
417
418       /* ... member with the given name was found */
419       return (EXPP_ReturnIntError (PyExc_KeyError, "attribute not found"));
420     }
421
422   Py_DECREF (valtuple);
423
424   if (error != Py_None)
425     return -1;
426
427   Py_DECREF (Py_None);          /* was incref'ed by the called Action_set* function */
428   return 0;                     /* normal exit */
429 }
430 //-------------------------------------------------------------------------------------------------------------------------------
431 static PyObject *
432 Action_repr (BPy_Action * self)
433 {
434   if (self->action)
435     return PyString_FromFormat ("[Action \"%s\"]", self->action->id.name + 2);
436   else
437     return PyString_FromString ("NULL");
438 }
439 //-------------------------------------------------------------------------------------------------------------------------------
440 PyObject *
441 Action_CreatePyObject (struct bAction * act)
442 {
443   BPy_Action *blen_action;
444
445   blen_action = (BPy_Action *) PyObject_NEW (BPy_Action, &Action_Type);
446
447   if (blen_action == NULL)
448     {
449       return (NULL);
450     }
451   blen_action->action   = act;
452   return ((PyObject *) blen_action);
453 }
454 //-------------------------------------------------------------------------------------------------------------------------------
455 int
456 Action_CheckPyObject (PyObject * py_obj)
457 {
458   return (py_obj->ob_type == &Action_Type);
459 }
460 //-------------------------------------------------------------------------------------------------------------------------------
461 struct bAction *
462 Action_FromPyObject (PyObject * py_obj)
463 {
464   BPy_Action *blen_obj;
465
466   blen_obj = (BPy_Action *) py_obj;
467   return (blen_obj->action);
468 }