more housekeeping. move static declarations and definititions out of .h files.
[blender.git] / source / blender / python / api2_2x / Armature.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): Jordi Rovira i Bonet
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #include "Armature.h"
33 #include "Bone.h"
34
35 #include <stdio.h>
36
37 #include <BKE_main.h>
38 #include <BKE_global.h>
39 #include <BKE_object.h>
40 #include <BKE_armature.h>
41 #include <BKE_library.h>
42 #include <BLI_blenlib.h>
43
44 #include "constant.h"
45 #include "gen_utils.h"
46 #include "modules.h"
47
48 /*****************************************************************************/
49 /* Python API function prototypes for the Armature module.                   */
50 /*****************************************************************************/
51 static PyObject *M_Armature_New (PyObject * self, PyObject * args,
52                                  PyObject * keywords);
53 static PyObject *M_Armature_Get (PyObject * self, PyObject * args);
54 PyObject *Armature_Init (void);
55
56 /*****************************************************************************/
57 /* The following string definitions are used for documentation strings.      */
58 /* In Python these will be written to the console when doing a               */
59 /* Blender.Armature.__doc__                                                  */
60 /*****************************************************************************/
61 char M_Armature_doc[] = "The Blender Armature module\n\n\
62 This module provides control over **Armature Data** objects in Blender.\n";
63
64 char M_Armature_New_doc[] = "(name) - return a new Armature datablock of \n\
65           optional name 'name'.";
66
67 char M_Armature_Get_doc[] =
68   "(name) - return the armature with the name 'name', \
69 returns None if not found.\n If 'name' is not specified, \
70 it returns a list of all armatures in the\ncurrent scene.";
71
72 char M_Armature_get_doc[] = "(name) - DEPRECATED. Use 'Get' instead. \
73 return the armature with the name 'name', \
74 returns None if not found.\n If 'name' is not specified, \
75 it returns a list of all armatures in the\ncurrent scene.";
76
77 /*****************************************************************************/
78 /* Python method structure definition for Blender.Armature module:           */
79 /*****************************************************************************/
80 struct PyMethodDef M_Armature_methods[] = {
81   {"New", (PyCFunction) M_Armature_New, METH_VARARGS | METH_KEYWORDS,
82    M_Armature_New_doc},
83   {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
84   {"get", M_Armature_Get, METH_VARARGS, M_Armature_get_doc},
85   {NULL, NULL, 0, NULL}
86 };
87
88 /*****************************************************************************/
89 /* Python BPy_Armature methods declarations:                                 */
90 /*****************************************************************************/
91 static PyObject *Armature_getName (BPy_Armature * self);
92 static PyObject *Armature_getBones (BPy_Armature * self);
93 static PyObject *Armature_setName (BPy_Armature * self, PyObject * args);
94 /* static PyObject *Armature_setBones(BPy_Armature *self, PyObject *args); */
95
96 /*****************************************************************************/
97 /* Python BPy_Armature methods table:                                        */
98 /*****************************************************************************/
99 static PyMethodDef BPy_Armature_methods[] = {
100   /* name, method, flags, doc */
101   {"getName", (PyCFunction) Armature_getName, METH_NOARGS,
102    "() - return Armature name"},
103   {"getBones", (PyCFunction) Armature_getBones, METH_NOARGS,
104    "() - return Armature root bones"},
105   {"setName", (PyCFunction) Armature_setName, METH_VARARGS,
106    "(str) - rename Armature"},
107   /*  {"setBones", (PyCFunction)Armature_setBones, METH_VARARGS,
108      "(list of bones) - replace the whole bone list of the armature"},
109    */
110   {NULL, NULL, 0, NULL}
111 };
112
113 /*****************************************************************************/
114 /* Python TypeArmature callback function prototypes:                         */
115 /*****************************************************************************/
116 static void Armature_dealloc (BPy_Armature * armature);
117 static PyObject *Armature_getAttr (BPy_Armature * armature, char *name);
118 static int Armature_setAttr (BPy_Armature * armature, char *name,
119                              PyObject * v);
120 static int Armature_compare (BPy_Armature * a1, BPy_Armature * a2);
121 static PyObject *Armature_repr (BPy_Armature * armature);
122
123 /*****************************************************************************/
124 /* Python TypeArmature structure definition:                                 */
125 /*****************************************************************************/
126 PyTypeObject Armature_Type = {
127   PyObject_HEAD_INIT (NULL) 0,  /* ob_size */
128   "Blender Armature",           /* tp_name */
129   sizeof (BPy_Armature),        /* tp_basicsize */
130   0,                            /* tp_itemsize */
131   /* methods */
132   (destructor) Armature_dealloc,        /* tp_dealloc */
133   0,                            /* tp_print */
134   (getattrfunc) Armature_getAttr,       /* tp_getattr */
135   (setattrfunc) Armature_setAttr,       /* tp_setattr */
136   (cmpfunc) Armature_compare,   /* tp_compare */
137   (reprfunc) Armature_repr,     /* tp_repr */
138   0,                            /* tp_as_number */
139   0,                            /* tp_as_sequence */
140   0,                            /* tp_as_mapping */
141   0,                            /* tp_as_hash */
142   0, 0, 0, 0, 0, 0,
143   0,                            /* tp_doc */
144   0, 0, 0, 0, 0, 0,
145   BPy_Armature_methods,         /* tp_methods */
146   0,                            /* tp_members */
147 };
148
149
150 /*****************************************************************************/
151 /* Function:              M_Armature_New                                     */
152 /* Python equivalent:     Blender.Armature.New                               */
153 /*****************************************************************************/
154 static PyObject *
155 M_Armature_New (PyObject * self, PyObject * args, PyObject * keywords)
156 {
157   char *type_str = "Armature";
158   char *name_str = "ArmatureData";
159   static char *kwlist[] = { "type_str", "name_str", NULL };
160   BPy_Armature *py_armature;    /* for Armature Data object wrapper in Python */
161   bArmature *bl_armature;       /* for actual Armature Data we create in Blender */
162   char buf[21];
163
164   if (!PyArg_ParseTupleAndKeywords (args, keywords, "|ss", kwlist,
165                                     &type_str, &name_str))
166     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
167                                    "expected string(s) or empty argument"));
168
169   bl_armature = add_armature ();        /* first create in Blender */
170   if (bl_armature)
171     {
172       /* return user count to zero because add_armature() inc'd it */
173       bl_armature->id.us = 0;
174       /* now create the wrapper obj in Python */
175       py_armature =
176         (BPy_Armature *) PyObject_NEW (BPy_Armature, &Armature_Type);
177     }
178   else
179     return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
180                                    "couldn't create Armature Data in Blender"));
181
182   if (py_armature == NULL)
183     return (EXPP_ReturnPyObjError (PyExc_MemoryError,
184                                    "couldn't create Armature Data object"));
185
186   /* link Python armature wrapper with Blender Armature: */
187   py_armature->armature = bl_armature;
188
189   if (strcmp (name_str, "ArmatureData") == 0)
190     return (PyObject *) py_armature;
191   else
192     {                           /* user gave us a name for the armature, use it */
193       PyOS_snprintf (buf, sizeof (buf), "%s", name_str);
194       rename_id (&bl_armature->id, buf);
195     }
196
197   return (PyObject *) py_armature;
198 }
199
200 /*****************************************************************************/
201 /* Function:              M_Armature_Get                                     */
202 /* Python equivalent:     Blender.Armature.Get                               */
203 /*****************************************************************************/
204 static PyObject *
205 M_Armature_Get (PyObject * self, PyObject * args)
206 {
207   char *name = NULL;
208   bArmature *armature_iter;
209   BPy_Armature *wanted_armature;
210
211   if (!PyArg_ParseTuple (args, "|s", &name))
212     return (EXPP_ReturnPyObjError (PyExc_TypeError,
213                                    "expected string argument (or nothing)"));
214
215   armature_iter = G.main->armature.first;
216
217   /* Use the name to search for the armature requested. */
218
219   if (name)
220     {                           /* (name) - Search armature by name */
221       wanted_armature = NULL;
222
223       while ((armature_iter) && (wanted_armature == NULL))
224         {
225
226           if (strcmp (name, armature_iter->id.name + 2) == 0)
227             {
228               wanted_armature =
229                 (BPy_Armature *) PyObject_NEW (BPy_Armature, &Armature_Type);
230               if (wanted_armature)
231                 wanted_armature->armature = armature_iter;
232             }
233
234           armature_iter = armature_iter->id.next;
235         }
236
237       if (wanted_armature == NULL)
238         {                       /* Requested Armature doesn't exist */
239           char error_msg[64];
240           PyOS_snprintf (error_msg, sizeof (error_msg),
241                          "Armature \"%s\" not found", name);
242           return (EXPP_ReturnPyObjError (PyExc_NameError, error_msg));
243         }
244
245       return (PyObject *) wanted_armature;
246     }
247
248   else
249     {
250       /* Return a list of with armatures in the scene */
251       int index = 0;
252       PyObject *armlist, *pyobj;
253
254       armlist = PyList_New (BLI_countlist (&(G.main->armature)));
255
256       if (armlist == NULL)
257         return (PythonReturnErrorObject (PyExc_MemoryError,
258                                          "couldn't create PyList"));
259
260       while (armature_iter)
261         {
262           pyobj = Armature_CreatePyObject (armature_iter);
263
264           if (!pyobj)
265             return (PythonReturnErrorObject (PyExc_MemoryError,
266                                              "couldn't create PyString"));
267
268           PyList_SET_ITEM (armlist, index, pyobj);
269
270           armature_iter = armature_iter->id.next;
271           index++;
272         }
273
274       return (armlist);
275     }
276
277 }
278
279 /*****************************************************************************/
280 /* Function:              Armature_Init                                      */
281 /*****************************************************************************/
282 PyObject *
283 Armature_Init (void)
284 {
285   PyObject *submodule;
286   PyObject *dict;
287
288   Armature_Type.ob_type = &PyType_Type;
289
290   submodule = Py_InitModule3 ("Blender.Armature",
291                               M_Armature_methods, M_Armature_doc);
292
293   /* Add the Bone submodule to this module */
294   dict = PyModule_GetDict (submodule);
295   PyDict_SetItemString (dict, "Bone", Bone_Init ());
296
297   return (submodule);
298 }
299
300 /*****************************************************************************/
301 /* Python BPy_Armature methods:                                              */
302 /*****************************************************************************/
303 static PyObject *
304 Armature_getName (BPy_Armature * self)
305 {
306   PyObject *attr = PyString_FromString (self->armature->id.name + 2);
307
308   if (attr)
309     return attr;
310
311   return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
312                                  "couldn't get Armature.name attribute"));
313 }
314
315
316 /** Create and return a list of the root bones for this armature. */
317 static PyObject *
318 Armature_getBones (BPy_Armature * self)
319 {
320   int totbones = 0;
321   PyObject *listbones = NULL;
322   Bone *current = NULL;
323   int i;
324
325   /* Count the number of bones to create the list */
326   current = self->armature->bonebase.first;
327   for (; current; current = current->next)
328     totbones++;
329
330   /* Create a list with a bone wrapper for each bone */
331   current = self->armature->bonebase.first;
332   listbones = PyList_New (totbones);
333   for (i = 0; i < totbones; i++)
334     {
335       /* Wrap and set to corresponding element of the list. */
336       PyList_SetItem (listbones, i, Bone_CreatePyObject (current));
337       current = current->next;
338     }
339
340   return listbones;
341 }
342
343
344 static PyObject *
345 Armature_setName (BPy_Armature * self, PyObject * args)
346 {
347   char *name;
348   char buf[21];
349
350   if (!PyArg_ParseTuple (args, "s", &name))
351     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
352                                    "expected string argument"));
353
354   PyOS_snprintf (buf, sizeof (buf), "%s", name);
355
356   rename_id (&self->armature->id, buf);
357
358   Py_INCREF (Py_None);
359   return Py_None;
360 }
361
362
363 #if 0
364 static PyObject *
365 Armature_setBones (BPy_Armature * self, PyObject * args)
366 {
367   /*  TODO: Implement me! */
368   printf ("ERROR: Armature_setBones NOT implemented yet!\n");
369   Py_INCREF (Py_None);
370   return Py_None;
371
372 }
373 #endif
374
375 /*****************************************************************************/
376 /* Function:    Armature_dealloc                                             */
377 /* Description: This is a callback function for the BPy_Armature type. It is */
378 /*              the destructor function.                                     */
379 /*****************************************************************************/
380 static void
381 Armature_dealloc (BPy_Armature * self)
382 {
383   PyObject_DEL (self);
384 }
385
386 /*****************************************************************************/
387 /* Function:    Armature_getAttr                                             */
388 /* Description: This is a callback function for the BPy_Armature type. It is */
389 /*              the function that accesses BPy_Armature member variables and */
390 /*              methods.                                                     */
391 /*****************************************************************************/
392 static PyObject *
393 Armature_getAttr (BPy_Armature * self, char *name)
394 {
395   PyObject *attr = Py_None;
396
397   if (strcmp (name, "name") == 0)
398     attr = Armature_getName (self);
399   if (strcmp (name, "bones") == 0)
400     attr = Armature_getBones (self);
401   else if (strcmp (name, "__members__") == 0)
402     {
403       /* 2 entries */
404       attr = Py_BuildValue ("[s,s]", "name", "bones");
405     }
406
407   if (!attr)
408     return (EXPP_ReturnPyObjError (PyExc_MemoryError,
409                                    "couldn't create PyObject"));
410
411   if (attr != Py_None)
412     return attr;                /* member attribute found, return it */
413
414   /* not an attribute, search the methods table */
415   return Py_FindMethod (BPy_Armature_methods, (PyObject *) self, name);
416 }
417
418 /*****************************************************************************/
419 /* Function:    Armature_setAttr                                             */
420 /* Description: This is a callback function for the BPy_Armature type. It is */
421 /*              the function that changes Armature Data members values. If   */
422 /*              this data is linked to a Blender Armature, it also gets      */
423 /*              updated.                                                     */
424 /*****************************************************************************/
425 static int
426 Armature_setAttr (BPy_Armature * self, char *name, PyObject * value)
427 {
428   PyObject *valtuple;
429   PyObject *error = NULL;
430
431   valtuple = Py_BuildValue ("(O)", value);      /*the set* functions expect a tuple */
432
433   if (!valtuple)
434     return EXPP_ReturnIntError (PyExc_MemoryError,
435                                 "ArmatureSetAttr: couldn't create tuple");
436
437   if (strcmp (name, "name") == 0)
438     error = Armature_setName (self, valtuple);
439   /*  if (strcmp (name, "bones") == 0)
440      error = Armature_setBones (self, valtuple); */
441   else
442     {                           /* Error */
443       Py_DECREF (valtuple);
444
445       /* ... member with the given name was found */
446       return (EXPP_ReturnIntError (PyExc_KeyError, "attribute not found"));
447     }
448
449   Py_DECREF (valtuple);
450
451   if (error != Py_None)
452     return -1;
453
454   Py_DECREF (Py_None);          /* was incref'ed by the called Armature_set* function */
455   return 0;                     /* normal exit */
456 }
457
458 /*****************************************************************************/
459 /* Function:    Armature_repr                                                */
460 /* Description: This is a callback function for the BPy_Armature type. It    */
461 /*              builds a meaninful string to represent armature objects.     */
462 /*****************************************************************************/
463 static PyObject *
464 Armature_repr (BPy_Armature * self)
465 {
466   return PyString_FromFormat ("[Armature \"%s\"]",
467                               self->armature->id.name + 2);
468 }
469
470 /*****************************************************************************/
471 /* Function:    Armature_compare                                             */
472 /* Description: This is a callback function for the BPy_Armature type. It    */
473 /*              compares the two armatures: translate comparison to the      */
474 /*              C pointers.                                                  */
475 /*****************************************************************************/
476 static int
477 Armature_compare (BPy_Armature * a, BPy_Armature * b)
478 {
479   bArmature *pa = a->armature, *pb = b->armature;
480   return (pa == pb) ? 0 : -1;
481 }
482
483 /*****************************************************************************/
484 /* Function:    Armature_CreatePyObject                                      */
485 /* Description: This function will create a new BlenArmature from an         */
486 /*              existing Armature structure.                                 */
487 /*****************************************************************************/
488 PyObject *
489 Armature_CreatePyObject (struct bArmature * obj)
490 {
491   BPy_Armature *blen_armature;
492
493   blen_armature =
494     (BPy_Armature *) PyObject_NEW (BPy_Armature, &Armature_Type);
495
496   if (blen_armature == NULL)
497     {
498       return (NULL);
499     }
500   blen_armature->armature = obj;
501   return ((PyObject *) blen_armature);
502 }
503
504 /*****************************************************************************/
505 /* Function:    Armature_CheckPyObject                                       */
506 /* Description: This function returns true when the given PyObject is of the */
507 /*              type Armature. Otherwise it will return false.               */
508 /*****************************************************************************/
509 int
510 Armature_CheckPyObject (PyObject * py_obj)
511 {
512   return (py_obj->ob_type == &Armature_Type);
513 }
514
515 /*****************************************************************************/
516 /* Function:    Armature_FromPyObject                                        */
517 /* Description: This function returns the Blender armature from the given    */
518 /*              PyObject.                                                    */
519 /*****************************************************************************/
520 struct bArmature *
521 Armature_FromPyObject (PyObject * py_obj)
522 {
523   BPy_Armature *blen_obj;
524
525   blen_obj = (BPy_Armature *) py_obj;
526   return (blen_obj->armature);
527 }