* Module Curve updated:
[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 /*****************************************************************************/
36 /* Function:              M_Armature_New                                     */
37 /* Python equivalent:     Blender.Armature.New                               */
38 /*****************************************************************************/
39 static PyObject *M_Armature_New(PyObject *self, PyObject *args,
40                                 PyObject *keywords)
41 {
42   char        *type_str = "Armature";
43   char        *name_str = "ArmatureData";
44   static char *kwlist[] = {"type_str", "name_str", NULL};
45   C_Armature  *py_armature; /* for Armature Data object wrapper in Python */
46   bArmature   *bl_armature; /* for actual Armature Data we create in Blender */
47   char        buf[21];
48
49   printf ("In Armature_New()\n");
50
51   if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ss", kwlist,
52            &type_str, &name_str))
53     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
54            "expected string(s) or empty argument"));
55
56   bl_armature = add_armature(); /* first create in Blender */
57   if (bl_armature) /* now create the wrapper obj in Python */
58     py_armature = (C_Armature *)PyObject_NEW(C_Armature, &Armature_Type);
59   else
60     return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
61            "couldn't create Armature Data in Blender"));
62
63   if (py_armature == NULL)
64     return (EXPP_ReturnPyObjError (PyExc_MemoryError,
65            "couldn't create Armature Data object"));
66
67   /* link Python armature wrapper with Blender Armature: */
68   py_armature->armature = bl_armature;
69
70   if (strcmp(name_str, "ArmatureData") == 0)
71     return (PyObject *)py_armature;
72   else { /* user gave us a name for the armature, use it */
73     PyOS_snprintf(buf, sizeof(buf), "%s", name_str);
74     rename_id(&bl_armature->id, buf);
75   }
76
77   return (PyObject *)py_armature;
78 }
79
80 /*****************************************************************************/
81 /* Function:              M_Armature_Get                                     */
82 /* Python equivalent:     Blender.Armature.Get                               */
83 /*****************************************************************************/
84 static PyObject *M_Armature_Get(PyObject *self, PyObject *args)
85 {
86   char   *name = NULL;
87   bArmature   *armature_iter;
88   C_Armature *wanted_armature;
89
90   printf ("In Armature_Get()\n");
91   if (!PyArg_ParseTuple(args, "|s", &name))
92     return (EXPP_ReturnPyObjError (PyExc_TypeError,
93            "expected string argument (or nothing)"));  
94
95   armature_iter = G.main->armature.first;
96   
97         /* Use the name to search for the armature requested. */
98
99   if (name) { /* (name) - Search armature by name */
100     wanted_armature = NULL;
101     
102     while ((armature_iter) && (wanted_armature == NULL)) {
103       
104       if (strcmp (name, armature_iter->id.name+2) == 0) {
105   wanted_armature = (C_Armature *)PyObject_NEW(C_Armature, &Armature_Type);
106   if (wanted_armature) wanted_armature->armature = armature_iter;
107       }
108       
109       armature_iter = armature_iter->id.next;
110     }
111
112     if (wanted_armature == NULL) {/* Requested Armature doesn't exist */
113       char error_msg[64];
114       PyOS_snprintf(error_msg, sizeof(error_msg),
115         "Armature \"%s\" not found", name);
116       return (EXPP_ReturnPyObjError (PyExc_NameError, error_msg));
117     }
118
119     return (PyObject*)wanted_armature;
120   }
121   
122   else
123     {
124       /* Return a list of all armatures in the scene */
125       int index = 0;
126       PyObject *armlist, *pystr;
127
128       armlist = PyList_New (BLI_countlist (&(G.main->armature)));
129
130       if (armlist == NULL)
131         return (PythonReturnErrorObject (PyExc_MemoryError,
132                 "couldn't create PyList"));
133
134       while (armature_iter) {
135         pystr = PyString_FromString (armature_iter->id.name+2);
136
137         if (!pystr)
138           return (PythonReturnErrorObject (PyExc_MemoryError,
139                     "couldn't create PyString"));
140   
141         PyList_SET_ITEM (armlist, index, pystr);
142
143         armature_iter = armature_iter->id.next;
144         index++;
145       }
146
147       return (armlist);
148     }
149
150 }
151
152 /*****************************************************************************/
153 /* Function:              M_Armature_Init                                    */
154 /*****************************************************************************/
155 PyObject *M_Armature_Init (void)
156 {
157   PyObject  *submodule;
158   PyObject  *dict;
159
160   printf ("In M_Armature_Init()\n");
161
162   submodule = Py_InitModule3("Blender.Armature",
163                              M_Armature_methods, M_Armature_doc);
164
165   /* Add the Bone submodule to this module */
166   dict = PyModule_GetDict (submodule);
167   PyDict_SetItemString (dict, "Bone", M_Bone_Init());
168
169   return (submodule);
170 }
171
172 /*****************************************************************************/
173 /* Python C_Armature methods:                                                */
174 /*****************************************************************************/
175 static PyObject *Armature_getName(C_Armature *self)
176 {
177   PyObject *attr = PyString_FromString(self->armature->id.name+2);
178
179   if (attr) return attr;
180
181   return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
182          "couldn't get Armature.name attribute"));
183 }
184
185
186 /** Create and return a list of the root bones for this armature. */
187 static PyObject *Armature_getBones(C_Armature *self)
188 {
189   int totbones = 0;
190   PyObject *listbones = NULL;
191   Bone* current = NULL; 
192   int i;
193
194   /* Count the number of bones to create the list */
195   current = self->armature->bonebase.first;
196   for (;current; current=current->next) totbones++;
197
198   /* Create a list with a bone wrapper for each bone */
199   current = self->armature->bonebase.first;
200   listbones = PyList_New(totbones);
201   for (i=0; i<totbones; i++) {
202     /* Wrap and set to corresponding element of the list. */
203     PyList_SetItem(listbones, i, M_BoneCreatePyObject(current) );
204     current = current->next;
205   }
206
207   return listbones;
208 }
209
210
211 static PyObject *Armature_setName(C_Armature *self, PyObject *args)
212 {
213   char *name;
214   char buf[21];
215
216   if (!PyArg_ParseTuple(args, "s", &name))
217     return (EXPP_ReturnPyObjError (PyExc_AttributeError,
218            "expected string argument"));
219   
220   PyOS_snprintf(buf, sizeof(buf), "%s", name);
221
222   rename_id(&self->armature->id, buf);
223
224   Py_INCREF(Py_None);
225   return Py_None;
226 }
227
228 /*
229   static PyObject *Armature_setBones(C_Armature *self, PyObject *args)
230   {
231   // TODO: Implement me!
232   printf("ERROR: Armature_setBones NOT implemented yet!\n");
233   Py_INCREF(Py_None);
234   return Py_None;
235   
236   }
237 */
238
239 /*****************************************************************************/
240 /* Function:    ArmatureDeAlloc                                              */
241 /* Description: This is a callback function for the C_Armature type. It is   */
242 /*              the destructor function.                                     */
243 /*****************************************************************************/
244 static void ArmatureDeAlloc (C_Armature *self)
245 {
246   PyObject_DEL (self);
247 }
248
249 /*****************************************************************************/
250 /* Function:    ArmatureGetAttr                                              */
251 /* Description: This is a callback function for the C_Armature type. It is   */
252 /*              the function that accesses C_Armature member variables and   */
253 /*              methods.                                                     */
254 /*****************************************************************************/
255 static PyObject* ArmatureGetAttr (C_Armature *self, char *name)
256 {
257   PyObject *attr = Py_None;
258
259   if (strcmp(name, "name") == 0)
260     attr = Armature_getName(self);
261   if (strcmp(name, "bones") == 0)
262     attr = Armature_getBones(self);
263   else if (strcmp(name, "__members__") == 0) {
264     /* 2 entries */
265     attr = Py_BuildValue("[s,s]",
266        "name", "bones");
267   }
268
269   if (!attr)
270     return (EXPP_ReturnPyObjError (PyExc_MemoryError,
271            "couldn't create PyObject"));
272
273   if (attr != Py_None) return attr; /* member attribute found, return it */
274
275   /* not an attribute, search the methods table */
276   return Py_FindMethod(C_Armature_methods, (PyObject *)self, name);
277 }
278
279 /*****************************************************************************/
280 /* Function:    ArmatureSetAttr                                              */
281 /* Description: This is a callback function for the C_Armature type. It is   */
282 /*              the function that changes Armature Data members values. If   */
283 /*              this data is linked to a Blender Armature, it also gets      */
284 /*              updated.                                                     */
285 /*****************************************************************************/
286 static int ArmatureSetAttr (C_Armature *self, char *name, PyObject *value)
287 {
288   PyObject *valtuple; 
289   PyObject *error = NULL;
290
291   valtuple = Py_BuildValue("(N)", value); /*the set* functions expect a tuple*/
292
293   if (!valtuple)
294     return EXPP_ReturnIntError(PyExc_MemoryError,
295              "ArmatureSetAttr: couldn't create tuple");
296
297   if (strcmp (name, "name") == 0)
298     error = Armature_setName (self, valtuple);
299   /*  if (strcmp (name, "bones") == 0)
300       error = Armature_setBones (self, valtuple);*/
301   else { /* Error */
302     Py_DECREF(valtuple);
303   
304     /* ... member with the given name was found */
305     return (EXPP_ReturnIntError (PyExc_KeyError,
306          "attribute not found"));
307   }
308
309   Py_DECREF(valtuple);
310   
311   if (error != Py_None) return -1;
312
313   Py_DECREF(Py_None); /* was incref'ed by the called Armature_set* function */
314   return 0; /* normal exit */
315 }
316
317 /*****************************************************************************/
318 /* Function:    ArmaturePrint                                                */
319 /* Description: This is a callback function for the C_Armature type. It      */
320 /*              builds a meaninful string to 'print' armature objects.       */
321 /*****************************************************************************/
322 static int ArmaturePrint(C_Armature *self, FILE *fp, int flags)
323
324   fprintf(fp, "[Armature \"%s\"]", self->armature->id.name+2);
325   return 0;
326 }
327
328 /*****************************************************************************/
329 /* Function:    ArmatureRepr                                                 */
330 /* Description: This is a callback function for the C_Armature type. It      */
331 /*              builds a meaninful string to represent armature objects.     */
332 /*****************************************************************************/
333 static PyObject *ArmatureRepr (C_Armature *self)
334 {
335   return PyString_FromString(self->armature->id.name+2);
336 }
337
338 /*****************************************************************************/
339 /* Function:    ArmatureCmp                                                  */
340 /* Description: This is a callback function for the C_Armature type. It      */
341 /*              compares the two armatures: translate comparison to the      */
342 /*              C pointers.                                                  */
343 /*****************************************************************************/
344 static int ArmatureCmp (C_Armature *a, C_Armature *b)
345 {
346   if (a<b) return -1;
347   else if (a==b) return 0;
348   else return 1;
349 }
350
351
352 /*****************************************************************************/
353 /* Function:    M_ArmatureCreatePyObject                                     */
354 /* Description: This function will create a new BlenArmature from an         */
355 /*              existing Armature structure.                                 */
356 /*****************************************************************************/
357 PyObject* M_ArmatureCreatePyObject (struct bArmature *obj)
358 {
359   C_Armature    * blen_armature;
360
361   printf ("In M_ArmatureCreatePyObject\n");
362
363   blen_armature = (C_Armature*)PyObject_NEW (C_Armature, &Armature_Type);
364
365   if (blen_armature == NULL)
366     {
367       return (NULL);
368     }
369   blen_armature->armature = obj;
370   return ((PyObject*)blen_armature);
371 }
372
373 /*****************************************************************************/
374 /* Function:    M_ArmatureCheckPyObject                                      */
375 /* Description: This function returns true when the given PyObject is of the */
376 /*              type Armature. Otherwise it will return false.               */
377 /*****************************************************************************/
378 int M_ArmatureCheckPyObject (PyObject *py_obj)
379 {
380   return (py_obj->ob_type == &Armature_Type);
381 }
382
383 /*****************************************************************************/
384 /* Function:    M_ArmatureFromPyObject                                       */
385 /* Description: This function returns the Blender armature from the given    */
386 /*              PyObject.                                                    */
387 /*****************************************************************************/
388 struct bArmature* M_ArmatureFromPyObject (PyObject *py_obj)
389 {
390   C_Armature    * blen_obj;
391
392   blen_obj = (C_Armature*)py_obj;
393   return (blen_obj->armature);
394 }