resolve some compiler warnings with intel c/c++ compiler
[blender-staging.git] / source / blender / python / api2_2x / Armature.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24 */
25
26 #include <stddef.h>
27
28 #include "Armature.h" //This must come first
29
30 #include "BKE_main.h"
31 #include "BKE_global.h"
32 #include "BKE_armature.h"
33 #include "BKE_library.h"
34 #include "BKE_depsgraph.h"
35 #include "BKE_utildefines.h"
36 #include "BLI_blenlib.h"
37 #include "BLI_arithb.h"
38 #include "MEM_guardedalloc.h"
39 #include "Bone.h"
40 #include "NLA.h"
41 #include "gen_utils.h"
42 #include "gen_library.h"
43
44 #include "DNA_object_types.h" //This must come before BIF_editarmature.h...
45 #include "BIF_editarmature.h"
46
47 //------------------EXTERNAL PROTOTYPES--------------------
48 extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
49 extern void editbones_to_armature (ListBase *list, Object *ob);
50
51 //------------------------ERROR CODES---------------------------------
52 //This is here just to make me happy and to have more consistant error strings :)
53 static const char sBoneDictError[] = "ArmatureType.bones - Error: ";
54 static const char sBoneDictBadArgs[] = "ArmatureType.bones - Bad Arguments: ";
55 static const char sArmatureError[] = "ArmatureType - Error: ";
56 static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: ";
57 static const char sModuleError[] = "Blender.Armature - Error: ";
58 static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
59
60 static PyObject * arm_weakref_callback_weakref_dealloc(PyObject *self, PyObject *weakref);
61 /* python callable */
62 static PyObject * arm_weakref_callback_weakref_dealloc__pyfunc;
63
64 //################## BonesDict_Type (internal) ########################
65 /*This is an internal psuedo-dictionary type that allows for manipulation
66 * of bones inside of an armature. It is a subobject of armature.
67 * i.e. Armature.bones['key']*/
68 //#####################################################################
69
70 //------------------METHOD IMPLEMENTATIONS-----------------------------
71 //------------------------Armature.bones.items()
72 //Returns a list of key:value pairs like dict.items()
73 static PyObject* BonesDict_items(BPy_BonesDict *self)
74 {
75         if (self->editmode_flag){
76                 return PyDict_Items(self->editbonesMap); 
77         }else{
78                 return PyDict_Items(self->bonesMap); 
79         }
80 }
81 //------------------------Armature.bones.keys()
82 //Returns a list of keys like dict.keys()
83 static PyObject* BonesDict_keys(BPy_BonesDict *self)
84 {
85         if (self->editmode_flag){
86                 return PyDict_Keys(self->editbonesMap);
87         }else{
88                 return PyDict_Keys(self->bonesMap);
89         }
90 }
91 //------------------------Armature.bones.values()
92 //Returns a list of values like dict.values()
93 static PyObject* BonesDict_values(BPy_BonesDict *self)
94 {
95         if (self->editmode_flag){
96                 return PyDict_Values(self->editbonesMap);
97         }else{
98                 return PyDict_Values(self->bonesMap);
99         }
100 }
101 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
102 //------------------TYPE_OBECT IMPLEMENTATION-----------------------
103 //------------------------tp_doc
104 //The __doc__ string for this object
105 static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\
106 designed to act as a Py_Bone dictionary.";
107
108 //------------------------tp_methods
109 //This contains a list of all methods the object contains
110 static PyMethodDef BPy_BonesDict_methods[] = {
111         {"items", (PyCFunction) BonesDict_items, METH_NOARGS, 
112                 "() - Returns the key:value pairs from the dictionary"},
113         {"keys", (PyCFunction) BonesDict_keys, METH_NOARGS, 
114                 "() - Returns the keys the dictionary"},
115         {"values", (PyCFunction) BonesDict_values, METH_NOARGS, 
116                 "() - Returns the values from the dictionary"},
117         {NULL, NULL, 0, NULL}
118 };
119 //-----------------(internal)
120 static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
121         Bone *bone = NULL;
122         PyObject *py_bone = NULL;
123
124         for (bone = bones->first; bone; bone = bone->next){
125                 py_bone = PyBone_FromBone(bone);
126                 if (!py_bone)
127                         return -1;
128                 
129                 if(PyDict_SetItemString(dictionary, bone->name, py_bone) == -1) {
130                         /* unlikely but possible */
131                         Py_DECREF(py_bone);
132                         return -1;
133                 }
134                 
135                 Py_DECREF(py_bone);
136                 if (bone->childbase.first) 
137                         BoneMapping_Init(dictionary, &bone->childbase);
138         }
139         return 0;
140 }
141 //-----------------(internal)
142 static int EditBoneMapping_Init(PyObject *dictionary, ListBase *editbones){
143         EditBone *editbone = NULL;
144         PyObject *py_editbone = NULL;
145
146         for (editbone = editbones->first; editbone; editbone = editbone->next){
147                 py_editbone = PyEditBone_FromEditBone(editbone);
148                 if (!py_editbone)
149                         return -1;
150                 
151                 if(PyDict_SetItemString(dictionary, editbone->name, py_editbone) == -1) {
152                         Py_DECREF(py_editbone);
153                         return -1;
154                 }
155                 Py_DECREF(py_editbone);
156         }
157         return 0;
158 }
159 //----------------- BonesDict_InitBones
160 static int BonesDict_InitBones(BPy_BonesDict *self)
161 {
162         PyDict_Clear(self->bonesMap);
163         if (BoneMapping_Init(self->bonesMap, self->bones) == -1)
164                 return 0;
165         return 1;
166
167 //----------------- BonesDict_InitEditBones
168 static int BonesDict_InitEditBones(BPy_BonesDict *self)
169 {
170         PyDict_Clear(self->editbonesMap);
171         if (EditBoneMapping_Init(self->editbonesMap, &self->editbones) == -1)
172                 return 0;
173         return 1;
174 }
175 //------------------------tp_repr
176 //This is the string representation of the object
177 static PyObject *BonesDict_repr(BPy_BonesDict *self)
178 {
179         char str[2048];
180         PyObject *key, *value;
181         Py_ssize_t pos = 0;
182         char *p = str;
183         char *keys, *vals;
184
185         p += sprintf(str, "[Bone Dict: {");
186
187         if (self->editmode_flag){
188                 while (PyDict_Next(self->editbonesMap, &pos, &key, &value)) {
189                         keys = PyString_AsString(key);
190                         vals = PyString_AsString(value->ob_type->tp_repr(value));
191                         if( strlen(str) + strlen(keys) + strlen(vals) < sizeof(str)-20 )
192                                 p += sprintf(p, "%s : %s, ", keys, vals );
193                         else {
194                                 p += sprintf(p, "...." );
195                                 break;
196                         }
197                 }
198         }else{
199                 while (PyDict_Next(self->bonesMap, &pos, &key, &value)) {
200                         keys = PyString_AsString(key);
201                         vals = PyString_AsString(value->ob_type->tp_repr(value));
202                         if( strlen(str) + strlen(keys) + strlen(vals) < sizeof(str)-20 )
203                                 p += sprintf(p, "%s : %s, ", keys, vals );
204                         else {
205                                 p += sprintf(p, "...." );
206                                 break;
207                         }
208                 }
209         }
210         sprintf(p, "}]");
211         return PyString_FromString(str);
212 }
213
214 //------------------------tp_dealloc
215 //This tells how to 'tear-down' our object when ref count hits 0
216 static void BonesDict_dealloc(BPy_BonesDict * self)
217 {
218         Py_DECREF(self->bonesMap);
219         Py_DECREF(self->editbonesMap);
220         BLI_freelistN(&self->editbones); 
221         PyObject_DEL( self );
222         return;
223 }
224 //------------------------mp_length
225 //This gets the size of the dictionary
226 static int BonesDict_len(BPy_BonesDict *self)
227 {
228         if (self->editmode_flag){
229                 return BLI_countlist(&self->editbones);
230         }else{
231                 return BLI_countlist(self->bones);
232         }
233 }
234 //-----------------------mp_subscript
235 //This defines getting a bone from the dictionary - x = Bones['key']
236 static PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
237
238         PyObject *value = NULL;
239
240         if (self->editmode_flag){
241                 value = PyDict_GetItem(self->editbonesMap, key);
242         }else{
243                 value = PyDict_GetItem(self->bonesMap, key);
244         }
245         if(value == NULL){  /* item not found in dict. throw exception */
246                 char* key_str = PyString_AsString( key );
247                 if (key_str) {
248                         return EXPP_ReturnPyObjError(PyExc_KeyError, "bone key must be a string" );
249                 } else {
250                         char buffer[128];
251                         PyOS_snprintf( buffer, sizeof(buffer), "bone %s not found", key_str);
252                         return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
253                 }
254         }
255         return EXPP_incr_ret(value);
256 }
257 //-----------------------mp_ass_subscript
258 //This does dict assignment - Bones['key'] = value
259 static int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
260 {
261         BPy_EditBone *editbone_for_deletion;
262         struct EditBone *editbone = NULL;
263         char *key_str = PyString_AsString(key);
264
265         if (!self->editmode_flag)
266                 return EXPP_intError(PyExc_AttributeError, "%s%s", 
267                                 sBoneDictBadArgs,  "You must call makeEditable() first");
268         
269         if (!key_str)
270                 return EXPP_intError(PyExc_AttributeError, "%s%s", 
271                                 sBoneDictBadArgs,  "The key must be the name of an editbone");
272         
273         if (value && !EditBoneObject_Check(value))
274                 return EXPP_intError(PyExc_AttributeError, "%s%s",
275                                 sBoneDictBadArgs,  "Can only assign editbones as values");
276         
277         //parse value for assignment
278         if (value){ /* we know this must be an editbone from the above check */
279                 //create a new editbone
280                 editbone = MEM_callocN(sizeof(EditBone), "eBone");
281                 BLI_strncpy(editbone->name, key_str, 32);
282                 unique_editbone_name(NULL, editbone->name);
283                 editbone->dist = ((BPy_EditBone*)value)->dist;
284                 editbone->ease1 = ((BPy_EditBone*)value)->ease1;
285                 editbone->ease2 = ((BPy_EditBone*)value)->ease2;
286                 editbone->flag = ((BPy_EditBone*)value)->flag;
287                 editbone->parent = ((BPy_EditBone*)value)->parent;
288                 editbone->rad_head = ((BPy_EditBone*)value)->rad_head;
289                 editbone->rad_tail = ((BPy_EditBone*)value)->rad_tail;
290                 editbone->roll = ((BPy_EditBone*)value)->roll;
291                 editbone->segments = ((BPy_EditBone*)value)->segments;
292                 editbone->weight = ((BPy_EditBone*)value)->weight;
293                 editbone->xwidth = ((BPy_EditBone*)value)->xwidth;
294                 editbone->zwidth = ((BPy_EditBone*)value)->zwidth;
295                 VECCOPY(editbone->head, ((BPy_EditBone*)value)->head);
296                 VECCOPY(editbone->tail, ((BPy_EditBone*)value)->tail);
297                 editbone->layer= ((BPy_EditBone*)value)->layer;
298                 
299                 //set object pointer
300                 ((BPy_EditBone*)value)->editbone = editbone;
301
302                 //fix the bone's head position if flags indicate that it is 'connected'
303                 if (editbone->flag & BONE_CONNECTED){
304                         if(!editbone->parent){
305                                 ((BPy_EditBone*)value)->editbone = NULL;
306                                 MEM_freeN(editbone);
307                                         return EXPP_intError(PyExc_AttributeError, "%s%s", 
308                                                         sBoneDictBadArgs,  "The 'connected' flag is set but the bone has no parent!");
309                         }else{
310                                 VECCOPY(editbone->head, editbone->parent->tail);
311                         }
312                 }
313
314                 //set in editbonelist
315                 BLI_addtail(&self->editbones, editbone);
316
317                 //set the new editbone in the mapping
318                 if(PyDict_SetItemString(self->editbonesMap, key_str, value) == -1){
319                         ((BPy_EditBone*)value)->editbone = NULL;
320                         BLI_freelinkN(&self->editbones, editbone);
321                         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
322                                         sBoneDictError,  "Unable to access dictionary!");
323                 }
324         }else {
325                 //they are trying to delete the bone using 'del'
326                 editbone_for_deletion = (BPy_EditBone*)PyDict_GetItem(self->editbonesMap, key);
327
328                 if (!editbone_for_deletion)
329                         return EXPP_intError(PyExc_KeyError, "%s%s%s%s", 
330                                         sBoneDictError,  "The key: ", key_str, " is not present in this dictionary!");
331
332                 /*first kill the datastruct then remove the item from the dict
333                 and wait for GC to pick it up.
334                 We have to delete the datastruct here because the tp_dealloc
335                 doesn't handle it*/
336                 
337                 /*this is ugly but you have to set the parent to NULL for else 
338                 editbones_to_armature will crash looking for this bone*/
339                 for (editbone = self->editbones.first; editbone; editbone = editbone->next){
340                         if (editbone->parent == editbone_for_deletion->editbone) {
341                                 editbone->parent = NULL;
342                                  /* remove the connected flag or else the 'root' ball
343                                   * doesn't get drawn */
344                                 editbone->flag &= ~BONE_CONNECTED;
345                         }
346                 }
347                 BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
348                 if(PyDict_DelItem(self->editbonesMap, key) == -1)
349                         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
350                                         sBoneDictError,  "Unable to access dictionary!");
351         }
352         return 0;
353 }
354 //------------------TYPE_OBJECT DEFINITION--------------------------
355 //Mapping Protocol
356 static PyMappingMethods BonesDict_MapMethods = {
357         (inquiry) BonesDict_len,                                        //mp_length
358         (binaryfunc)BonesDict_GetItem,          //mp_subscript
359         (objobjargproc)BonesDict_SetItem,       //mp_ass_subscript
360 };
361 //BonesDict TypeObject
362 PyTypeObject BonesDict_Type = {
363         PyObject_HEAD_INIT(NULL)                        //tp_head
364         0,                                                                                              //tp_internal
365         "BonesDict",                                                            //tp_name
366         sizeof(BPy_BonesDict),                                  //tp_basicsize
367         0,                                                                                              //tp_itemsize
368         (destructor)BonesDict_dealloc,          //tp_dealloc
369         0,                                                                                              //tp_print
370         0,                                                                                              //tp_getattr
371         0,                                                                                              //tp_setattr
372         0,                                                                                              //tp_compare
373         (reprfunc) BonesDict_repr,                              //tp_repr
374         0,                                                                                              //tp_as_number
375         0,                                                                                              //tp_as_sequence
376         &BonesDict_MapMethods,                          //tp_as_mapping
377         0,                                                                                              //tp_hash
378         0,                                                                                              //tp_call
379         0,                                                                                              //tp_str
380         0,                                                                                              //tp_getattro
381         0,                                                                                              //tp_setattro
382         0,                                                                                              //tp_as_buffer
383         Py_TPFLAGS_DEFAULT,                                     //tp_flags
384         BPy_BonesDict_doc,                                              //tp_doc
385         0,                                                                                              //tp_traverse
386         0,                                                                                              //tp_clear
387         0,                                                                                              //tp_richcompare
388         0,                                                                                              //tp_weaklistoffset
389         0,                                                                                              //tp_iter
390         0,                                                                                              //tp_iternext
391         BPy_BonesDict_methods,                          //tp_methods
392         0,                                                                                              //tp_members
393         0,                                                                                              //tp_getset
394         0,                                                                                              //tp_base
395         0,                                                                                              //tp_dict
396         0,                                                                                              //tp_descr_get
397         0,                                                                                              //tp_descr_set
398         0,                                                                                              //tp_dictoffset
399         0,                                                              //tp_init
400         0,                                                                                              //tp_alloc
401         0,                                                                                              //tp_new
402         0,                                                                                              //tp_free
403         0,                                                                                              //tp_is_gc
404         0,                                                                                              //tp_bases
405         0,                                                                                              //tp_mro
406         0,                                                                                              //tp_cache
407         0,                                                                                              //tp_subclasses
408         0,                                                                                              //tp_weaklist
409         0                                                                                               //tp_del
410 };
411 //-----------------------PyBonesDict_FromPyArmature
412 static PyObject *PyBonesDict_FromPyArmature(BPy_Armature *py_armature)
413 {
414         BPy_BonesDict *py_BonesDict = (BPy_BonesDict *)PyObject_NEW( BPy_BonesDict, &BonesDict_Type );
415         if (!py_BonesDict)
416                 goto RuntimeError;
417
418         py_BonesDict->bones = NULL;
419         py_BonesDict->editbones.first = py_BonesDict->editbones.last = NULL;
420
421         //create internal dictionaries
422         py_BonesDict->bonesMap = PyDict_New();
423         py_BonesDict->editbonesMap = PyDict_New();
424         if (!py_BonesDict->bonesMap || !py_BonesDict->editbonesMap)
425                 goto RuntimeError;
426
427         //set listbase pointer
428         py_BonesDict->bones = &py_armature->armature->bonebase;
429
430         //now that everything is setup - init the mappings
431         if (!BonesDict_InitBones(py_BonesDict))
432                 goto RuntimeError;
433         if (!BonesDict_InitEditBones(py_BonesDict))
434                 goto RuntimeError;
435
436         //set editmode flag
437         py_BonesDict->editmode_flag = 0; 
438
439         return (PyObject*)py_BonesDict;
440
441 RuntimeError:
442         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
443                 sBoneDictError, "Failed to create class");
444 }
445
446 //######################### Armature_Type #############################
447 /*This type represents a thin wrapper around bArmature data types
448 * internal to blender. It contains the psuedo-dictionary BonesDict
449 * as an assistant in manipulating it's own bone collection*/
450 //#################################################################
451
452 //------------------METHOD IMPLEMENTATION------------------------------
453 //------------------------Armature.makeEditable()
454 static PyObject *Armature_makeEditable(BPy_Armature *self)
455 {
456         if (self->armature->flag & ARM_EDITMODE)
457                 goto AttributeError;
458
459         make_boneList(&self->Bones->editbones, self->Bones->bones, NULL);
460         if (!BonesDict_InitEditBones(self->Bones))
461                 return NULL;
462         self->Bones->editmode_flag = 1;
463         return EXPP_incr_ret(Py_None);
464
465 AttributeError:
466         return EXPP_objError(PyExc_AttributeError, "%s%s", 
467                 sArmatureBadArgs, "The armature cannot be placed manually in editmode before you call makeEditable()!");
468 }
469
470 //------------------------Armature.update()
471 //This is a bit ugly because you need an object link to do this
472 static PyObject *Armature_update(BPy_Armature *self)
473 {
474         Object *obj = NULL;
475
476         for (obj = G.main->object.first; obj; obj = obj->id.next){
477                 if (obj->data == self->armature)
478                         break;
479         }
480         if (obj){
481                 editbones_to_armature (&self->Bones->editbones, obj);
482                 if (!BonesDict_InitBones(self->Bones))
483                         return NULL;
484                 self->Bones->editmode_flag = 0;
485                 BLI_freelistN(&self->Bones->editbones);
486         }else{
487                 goto AttributeError;
488
489         }
490         return EXPP_incr_ret(Py_None);
491
492 AttributeError:
493         return EXPP_objError(PyExc_AttributeError, "%s%s", 
494                 sArmatureBadArgs, "The armature must be linked to an object before you can save changes!");
495 }
496
497 //------------------------Armature.__copy__()
498 static PyObject *Armature_copy(BPy_Armature *self)
499 {
500         PyObject *py_armature = NULL;
501         bArmature *bl_armature;
502         bl_armature= copy_armature(self->armature);
503         bl_armature->id.us= 0;
504         py_armature= Armature_CreatePyObject( bl_armature );
505         return py_armature;
506 }
507
508 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
509 //------------------------Armature.autoIK (getter)
510 static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
511 {
512         if (self->armature->flag & ARM_AUTO_IK)
513                 return EXPP_incr_ret(Py_True);
514         else
515                 return EXPP_incr_ret(Py_False);
516 }
517 //------------------------Armature.autoIK (setter)
518 static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
519 {
520         if(value){
521                 if(PyBool_Check(value)){
522                         if (value == Py_True){
523                                 self->armature->flag |= ARM_AUTO_IK;
524                                 return 0;
525                         }else if (value == Py_False){
526                                 self->armature->flag &= ~ARM_AUTO_IK;
527                                 return 0;
528                         }
529                 }
530         }
531         goto AttributeError;
532
533 AttributeError:
534         return EXPP_intError(PyExc_AttributeError, "%s%s", 
535                 sArmatureBadArgs, "Expects True or False");
536 }
537 //------------------------Armature.layers (getter)
538 static PyObject *Armature_getLayers(BPy_Armature *self, void *closure)
539 {
540         int layers, bit = 0, val = 0;
541         PyObject *item = NULL, *laylist = PyList_New( 0 );
542
543         if( !laylist )
544                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
545                         "couldn't create pylist!" );
546
547         layers = self->armature->layer;
548
549         while( bit < 20 ) {
550                 val = 1 << bit;
551                 if( layers & val ) {
552                         item = Py_BuildValue( "i", bit + 1 );
553                         PyList_Append( laylist, item );
554                         Py_DECREF( item );
555                 }
556                 bit++;
557         }
558         return laylist;
559 }
560 //------------------------Armature.layer (setter)
561 static int Armature_setLayers(BPy_Armature *self, PyObject *value, void *closure)
562 {
563         if(value){
564                 if(PyList_Check(value)){
565                         int layers = 0, len_list = 0;
566                         int val;
567                         PyObject *item = NULL;
568
569                         len_list = PyList_Size(value);
570
571                         if( len_list == 0 )
572                                 return EXPP_ReturnIntError( PyExc_AttributeError,
573                                   "list can't be empty, at least one layer must be set" );
574
575                         while( len_list ) {
576                                 --len_list;
577                                 item = PyList_GetItem( value, len_list );
578                                 if( !PyInt_Check( item ) )
579                                         return EXPP_ReturnIntError( PyExc_AttributeError,
580                                                         "list must contain only integer numbers" );
581
582                                 val = ( int ) PyInt_AsLong( item );
583                                 if( val < 1 || val > 20 )
584                                         return EXPP_ReturnIntError( PyExc_AttributeError,
585                                                   "layer values must be in the range [1, 20]" );
586
587                                 layers |= 1 << ( val - 1 );
588                         }
589
590                         /* update any bases pointing to our object */
591                         self->armature->layer = (short)layers;
592
593                         return 0;
594                 }
595         }
596         goto AttributeError;
597
598 AttributeError:
599         return EXPP_ReturnIntError( PyExc_TypeError,
600                         "expected a list of integers" );
601 }
602
603 //------------------------Armature.mirrorEdit (getter)
604 static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
605 {
606         if (self->armature->flag & ARM_MIRROR_EDIT)
607                 return EXPP_incr_ret(Py_True);
608         else
609                 return EXPP_incr_ret(Py_False);
610 }
611 //------------------------Armature.mirrorEdit (setter)
612 static int Armature_setMirrorEdit(BPy_Armature *self, PyObject *value, void *closure)
613 {
614         if(value){
615                 if(PyBool_Check(value)){
616                         if (value == Py_True){
617                                 self->armature->flag |= ARM_MIRROR_EDIT;
618                                 return 0;
619                         }else if (value == Py_False){
620                                 self->armature->flag &= ~ARM_MIRROR_EDIT;
621                                 return 0;
622                         }
623                 }
624         }
625         goto AttributeError;
626
627 AttributeError:
628         return EXPP_intError(PyExc_AttributeError, "%s%s", 
629                 sArmatureBadArgs, "Expects True or False");
630 }
631 //------------------------Armature.drawType (getter)
632 static PyObject *Armature_getDrawType(BPy_Armature *self, void *closure)
633 {
634         if (self->armature->drawtype == ARM_OCTA){
635                 return EXPP_GetModuleConstant("Blender.Armature", "OCTAHEDRON") ;
636         }else if (self->armature->drawtype == ARM_LINE){
637                 return EXPP_GetModuleConstant("Blender.Armature", "STICK") ;
638         }else if (self->armature->drawtype == ARM_B_BONE){
639                 return EXPP_GetModuleConstant("Blender.Armature", "BBONE") ;
640         }else if (self->armature->drawtype == ARM_ENVELOPE){
641                 return EXPP_GetModuleConstant("Blender.Armature", "ENVELOPE") ;
642         }else{
643                 goto RuntimeError;
644         }
645
646 RuntimeError:
647         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
648                 sArmatureError, "drawType: ", "Internal failure!");
649 }
650 //------------------------Armature.drawType (setter)
651 static int Armature_setDrawType(BPy_Armature *self, PyObject *value, void *closure)
652 {
653         PyObject *val = NULL, *name = NULL;
654         long numeric_value;
655
656         if(value){
657                 if(BPy_Constant_Check(value)){
658                         name = PyDict_GetItemString(((BPy_constant*)value)->dict, "name");
659                         if (!STREQ2(PyString_AsString(name), "OCTAHEDRON", "STICK") &&
660                                 !STREQ2(PyString_AsString(name), "BBONE", "ENVELOPE"))
661                                 goto ValueError;
662                         val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
663                         if (PyInt_Check(val)){
664                                 numeric_value = PyInt_AS_LONG(val);
665                                 self->armature->drawtype = (int)numeric_value;
666                                 return 0;
667                         }
668                 }
669         }
670         goto AttributeError;
671
672 AttributeError:
673         return EXPP_intError(PyExc_AttributeError, "%s%s", 
674                 sArmatureBadArgs, "Expects module constant");
675
676 ValueError:
677         return EXPP_intError(PyExc_AttributeError, "%s%s", 
678                 sArmatureBadArgs, "Argument must be the constant OCTAHEDRON, STICK, BBONE, or ENVELOPE");
679 }
680 //------------------------Armature.ghostStep (getter)
681 static PyObject *Armature_getStep(BPy_Armature *self, void *closure)
682 {
683         return PyInt_FromLong((long)self->armature->ghostsize);
684 }
685 //------------------------Armature.ghostStep (setter)
686 static int Armature_setStep(BPy_Armature *self, PyObject *value, void *closure)
687 {
688         long numerical_value;
689
690         if(value){
691                 if(PyInt_Check(value)){
692                         numerical_value = PyInt_AS_LONG(value);
693                         if (numerical_value > 20.0f || numerical_value < 1.0f)
694                                 goto ValueError;
695                         self->armature->ghostsize = (short)numerical_value;
696                         return 0;
697                 }
698         }
699         goto AttributeError;
700
701 AttributeError:
702         return EXPP_intError(PyExc_AttributeError, "%s%s", 
703                 sArmatureBadArgs, "Expects Integer");
704
705 ValueError:
706         return EXPP_intError(PyExc_AttributeError, "%s%s", 
707                 sArmatureBadArgs, "Argument must fall within 1-20");
708 }
709 //------------------------Armature.ghost (getter)
710 static PyObject *Armature_getGhost(BPy_Armature *self, void *closure)
711 {
712         return PyInt_FromLong((long)self->armature->ghostep);
713 }
714 //------------------------Armature.ghost (setter)
715 static int Armature_setGhost(BPy_Armature *self, PyObject *value, void *closure)
716 {
717         long numerical_value;
718
719         if(value){
720                 if(PyInt_Check(value)){
721                         numerical_value = PyInt_AS_LONG(value);
722                         if (numerical_value > 30.0f || numerical_value < 0.0f)
723                                 goto ValueError;
724                         self->armature->ghostep = (short)numerical_value;
725                         return 0;
726                 }
727         }
728         goto AttributeError;
729
730 AttributeError:
731         return EXPP_intError(PyExc_AttributeError, "%s%s", 
732                 sArmatureBadArgs, "Expects Integer");
733
734 ValueError:
735         return EXPP_intError(PyExc_AttributeError, "%s%s", 
736                 sArmatureBadArgs, "Argument must fall within 0-30");
737 }
738 //------------------------Armature.drawNames (getter)
739 static PyObject *Armature_getDrawNames(BPy_Armature *self, void *closure)
740 {
741         if (self->armature->flag & ARM_DRAWNAMES)
742                 return EXPP_incr_ret(Py_True);
743         else
744                 return EXPP_incr_ret(Py_False);
745 }
746 //------------------------Armature.drawNames (setter)
747 static int Armature_setDrawNames(BPy_Armature *self, PyObject *value, void *closure)
748 {
749         if(value){
750                 if(PyBool_Check(value)){
751                         if (value == Py_True){
752                                 self->armature->flag |= ARM_DRAWNAMES;
753                                 return 0;
754                         }else if (value == Py_False){
755                                 self->armature->flag &= ~ARM_DRAWNAMES;
756                                 return 0;
757                         }
758                 }
759         }
760         goto AttributeError;
761
762 AttributeError:
763         return EXPP_intError(PyExc_AttributeError, "%s%s", 
764                 sArmatureBadArgs, "Expects True or False");
765 }
766 //------------------------Armature.drawAxes (getter)
767 static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
768 {
769         if (self->armature->flag & ARM_DRAWAXES)
770                 return EXPP_incr_ret(Py_True);
771         else
772                 return EXPP_incr_ret(Py_False);
773 }
774 //------------------------Armature.drawAxes (setter)
775 static int Armature_setDrawAxes(BPy_Armature *self, PyObject *value, void *closure)
776 {
777         if(value){
778                 if(PyBool_Check(value)){
779                         if (value == Py_True){
780                                 self->armature->flag |= ARM_DRAWAXES;
781                                 return 0;
782                         }else if (value == Py_False){
783                                 self->armature->flag &= ~ARM_DRAWAXES;
784                                 return 0;
785                         }
786                 }
787         }
788         goto AttributeError;
789
790 AttributeError:
791         return EXPP_intError(PyExc_AttributeError, "%s%s", 
792                 sArmatureBadArgs, "Expects True or False");
793 }
794 //------------------------Armature.delayDeform (getter)
795 static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
796 {
797         if (self->armature->flag & ARM_DELAYDEFORM)
798                 return EXPP_incr_ret(Py_True);
799         else
800                 return EXPP_incr_ret(Py_False);
801 }
802 //------------------------Armature.delayDeform (setter)
803 static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
804 {
805         if(value){
806                 if(PyBool_Check(value)){
807                         if (value == Py_True){
808                                 self->armature->flag |= ARM_DELAYDEFORM;
809                                 return 0;
810                         }else if (value == Py_False){
811                                 self->armature->flag &= ~ARM_DELAYDEFORM;
812                                 return 0;
813                         }
814                 }
815         }
816         goto AttributeError;
817
818 AttributeError:
819         return EXPP_intError(PyExc_AttributeError, "%s%s", 
820                 sArmatureBadArgs, "Expects True or False");
821 }
822 //------------------------Armature.restPosition (getter)
823 static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
824 {
825         if (self->armature->flag & ARM_RESTPOS)
826                 return EXPP_incr_ret(Py_True);
827         else
828                 return EXPP_incr_ret(Py_False);
829 }
830 //------------------------Armature.restPosition (setter)
831 static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
832 {
833         if(value){
834                 if(PyBool_Check(value)){
835                         if (value == Py_True){
836                                 self->armature->flag |= ARM_RESTPOS;
837                                 return 0;
838                         }else if (value == Py_False){
839                                 self->armature->flag &= ~ARM_RESTPOS;
840                                 return 0;
841                         }
842                 }
843         }
844         goto AttributeError;
845
846 AttributeError:
847         return EXPP_intError(PyExc_AttributeError, "%s%s", 
848                 sArmatureBadArgs, "Expects True or False");
849 }
850 //------------------------Armature.envelopes (getter)
851 static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
852 {
853         if (self->armature->deformflag & ARM_DEF_ENVELOPE)
854                 return EXPP_incr_ret(Py_True);
855         else
856                 return EXPP_incr_ret(Py_False);
857 }
858 //------------------------Armature.envelopes (setter)
859 static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
860 {
861         if(value){
862                 if(PyBool_Check(value)){
863                         if (value == Py_True){
864                                 self->armature->deformflag |= ARM_DEF_ENVELOPE;
865                                 return 0;
866                         }else if (value == Py_False){
867                                 self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
868                                 return 0;
869                         }
870                 }
871         }
872         goto AttributeError;
873
874 AttributeError:
875         return EXPP_intError(PyExc_AttributeError, "%s%s", 
876                 sArmatureBadArgs, "Expects True or False");
877 }
878 //------------------------Armature.vertexGroups (getter)
879 static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
880 {
881         if (self->armature->deformflag & ARM_DEF_VGROUP)
882                 Py_RETURN_TRUE;
883         else
884                 Py_RETURN_FALSE;
885 }
886 //------------------------Armature.vertexGroups (setter)
887 static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
888 {
889         if(value){
890                 if(PyBool_Check(value)){
891                         if (value == Py_True){
892                                 self->armature->deformflag |= ARM_DEF_VGROUP;
893                                 return 0;
894                         }else if (value == Py_False){
895                                 self->armature->deformflag &= ~ARM_DEF_VGROUP;
896                                 return 0;
897                         }
898                 }
899         }
900         goto AttributeError;
901
902 AttributeError:
903         return EXPP_intError(PyExc_AttributeError, "%s%s", 
904                 sArmatureBadArgs, "Expects True or False");
905 }
906
907 //------------------------Armature.bones (getter)
908 //Gets the name of the armature
909 static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
910 {
911     return EXPP_incr_ret((PyObject*)self->Bones);
912 }
913 //------------------------Armature.bones (setter)
914 //Sets the name of the armature
915 /*TODO*/
916 /*Copy Bones through x = y*/
917 static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
918 {
919         goto AttributeError;
920
921 AttributeError:
922         return EXPP_intError(PyExc_AttributeError, "%s%s", 
923                 sArmatureError, "You are not allowed to change the .Bones attribute");
924 }
925
926 //------------------------Bone.layerMask (get)
927 static PyObject *Armature_getLayerMask(BPy_Armature *self)
928 {
929         /* do this extra stuff because the short's bits can be negative values */
930         unsigned short laymask = 0;
931         laymask |= self->armature->layer;
932         return PyInt_FromLong((int)laymask);
933 }
934 //------------------------Bone.layerMask (set)
935 static int Armature_setLayerMask(BPy_Armature *self, PyObject *value)
936 {
937         int laymask;
938         if (!PyInt_Check(value)) {
939                 return EXPP_ReturnIntError( PyExc_AttributeError,
940                                                                         "expected an integer (bitmask) as argument" );
941         }
942         
943         laymask = PyInt_AsLong(value);
944
945         if (laymask <= 0 || laymask > (1<<16) - 1)
946                 return EXPP_ReturnIntError( PyExc_AttributeError,
947                                                                         "bitmask must have from 1 up to 16 bits set");
948
949         self->armature->layer = 0;
950         self->armature->layer |= laymask;
951
952         return 0;
953 }
954
955 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
956 //------------------------tp_doc
957 //The __doc__ string for this object
958 static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
959 //------------------------tp_methods
960 //This contains a list of all methods the object contains
961 static PyMethodDef BPy_Armature_methods[] = {
962         {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
963                 "() - Unlocks the ability to modify armature bones"},
964         {"update", (PyCFunction) Armature_update, METH_NOARGS, 
965                 "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
966         {"__copy__", (PyCFunction) Armature_copy, METH_NOARGS, 
967                 "() - Return a copy of the armature."},
968         {"copy", (PyCFunction) Armature_copy, METH_NOARGS, 
969                 "() - Return a copy of the armature."},
970         {NULL, NULL, 0, NULL}
971 };
972 //------------------------tp_getset
973 //This contains methods for attributes that require checking
974 static PyGetSetDef BPy_Armature_getset[] = {
975         GENERIC_LIB_GETSETATTR,
976         {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
977                 "The armature's Bone dictionary", NULL},
978         {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
979                 "Enable/Disable vertex group defined deformation", NULL},
980         {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
981                 "Enable/Disable bone envelope defined deformation", NULL},
982         {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
983                 "Show armature rest position - disables posing", NULL},
984         {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
985                 "Don't deform children when manipulating bones in pose mode", NULL},
986         {"drawAxes", (getter)Armature_getDrawAxes, (setter)Armature_setDrawAxes, 
987                 "Enable/Disable  drawing  the bone axes", NULL},
988         {"drawNames", (getter)Armature_getDrawNames, (setter)Armature_setDrawNames, 
989                 "Enable/Disable  drawing the bone names", NULL},
990         {"ghost", (getter)Armature_getGhost, (setter)Armature_setGhost, 
991                 "Draw a number of ghosts around the current frame for current Action", NULL},
992         {"ghostStep", (getter)Armature_getStep, (setter)Armature_setStep, 
993                 "The number of frames between ghost instances", NULL},
994         {"drawType", (getter)Armature_getDrawType, (setter)Armature_setDrawType, 
995                 "The type of drawing currently applied to the armature", NULL},
996         {"mirrorEdit", (getter)Armature_getMirrorEdit, (setter)Armature_setMirrorEdit, 
997                 "Enable/Disable X-axis mirrored editing", NULL},
998         {"autoIK", (getter)Armature_getAutoIK, (setter)Armature_setAutoIK, 
999                 "Adds temporal IK chains while grabbing bones", NULL},
1000         {"layers", (getter)Armature_getLayers, (setter)Armature_setLayers, 
1001                 "List of layers for the armature", NULL},
1002         {"layerMask", (getter)Armature_getLayerMask, (setter)Armature_setLayerMask, 
1003                 "Layer bitmask", NULL },
1004         {NULL, NULL, NULL, NULL, NULL}
1005 };
1006 //------------------------tp_new
1007 //This methods creates a new object (note it does not initialize it - only the building)
1008 //This can be called through python by myObject.__new__() however, tp_init is not called
1009 static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1010 {
1011         BPy_Armature *py_armature = NULL;
1012         bArmature *bl_armature;
1013
1014         bl_armature = add_armature("Armature");
1015         if(bl_armature) {
1016                 bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
1017
1018                 py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
1019                 if (py_armature == NULL)
1020                         goto RuntimeError;
1021
1022                 py_armature->armature = bl_armature;
1023
1024                 //create armature.bones
1025                 py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
1026                 if (!py_armature->Bones)
1027                         goto RuntimeError;
1028
1029         } else {
1030                 goto RuntimeError;
1031         }
1032         return (PyObject*)py_armature; 
1033
1034 RuntimeError:
1035         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1036                 sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
1037 }
1038 //------------------------tp_init
1039 //This methods does initialization of the new object
1040 //This method will get called in python by 'myObject(argument, keyword=value)'
1041 //tp_new will be automatically called before this
1042 static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
1043 {
1044         char buf[21];
1045         char *name = "myArmature";
1046         static char *kwlist[] = {"name", NULL};
1047
1048         if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
1049                 goto AttributeError;
1050         }
1051
1052         //rename the armature if a name is supplied
1053         if(!BLI_streq(name, "myArmature")){
1054                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
1055                 rename_id(&self->armature->id, buf);
1056         }
1057         return 0;
1058
1059 AttributeError:
1060         return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
1061                 sArmatureBadArgs, " __init__: ", "Expects string(name)");
1062 }
1063
1064
1065 /*****************************************************************************/
1066 /* Function:    Armature_compare                                                 */
1067 /* Description: This is a callback function for the BPy_Armature type. It        */
1068 /*              compares two Armature_Type objects. Only the "==" and "!="  */
1069 /*              comparisons are meaninful. Returns 0 for equality and -1 if  */
1070 /*              they don't point to the same Blender Object struct.      */
1071 /*              In Python it becomes 1 if they are equal, 0 otherwise.   */
1072 /*****************************************************************************/
1073 static int Armature_compare( BPy_Armature * a, BPy_Armature * b )
1074 {
1075         return ( a->armature == b->armature ) ? 0 : -1;
1076 }
1077
1078 //------------------------tp_repr
1079 //This is the string representation of the object
1080 static PyObject *Armature_repr(BPy_Armature *self)
1081 {
1082         return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
1083 }
1084 //------------------------tp_dealloc
1085 //This tells how to 'tear-down' our object when ref count hits 0
1086 ///tp_dealloc
1087 static void Armature_dealloc(BPy_Armature * self)
1088 {
1089         if (self->weaklist != NULL)
1090                 PyObject_ClearWeakRefs((PyObject *) self); /* this causes the weakref dealloc func to be called */
1091         
1092         Py_DECREF(self->Bones);
1093         PyObject_DEL( self );
1094 }
1095 //------------------TYPE_OBECT DEFINITION--------------------------
1096 PyTypeObject Armature_Type = {
1097         PyObject_HEAD_INIT(NULL)                //tp_head
1098         0,                                                              //tp_internal
1099         "Armature",                                             //tp_name
1100         sizeof(BPy_Armature),                   //tp_basicsize
1101         0,                                                              //tp_itemsize
1102         (destructor)Armature_dealloc,   //tp_dealloc
1103         0,                                                              //tp_print
1104         0,                                                              //tp_getattr
1105         0,                                                              //tp_setattr
1106         (cmpfunc) Armature_compare,             //tp_compare
1107         (reprfunc) Armature_repr,               //tp_repr
1108         0,                                                              //tp_as_number
1109         0,                                                              //tp_as_sequence
1110         0,                                                              //tp_as_mapping
1111         ( hashfunc ) GenericLib_hash,   //tp_hash
1112         0,                                                              //tp_call
1113         0,                                                              //tp_str
1114         0,                                                              //tp_getattro
1115         0,                                                              //tp_setattro
1116         0,                                                              //tp_as_buffer
1117         Py_TPFLAGS_DEFAULT| Py_TPFLAGS_HAVE_WEAKREFS,                           //tp_flags
1118         BPy_Armature_doc,                               //tp_doc
1119         0,                                                              //tp_traverse
1120         0,                                                              //tp_clear
1121         0,                                                              //tp_richcompare
1122         offsetof(BPy_Armature, weaklist),       //tp_weaklistoffset
1123         0,                                                              //tp_iter
1124         0,                                                              //tp_iternext
1125         BPy_Armature_methods,                   //tp_methods
1126         0,                                                              //tp_members
1127         BPy_Armature_getset,                    //tp_getset
1128         0,                                                              //tp_base
1129         0,                                                              //tp_dict
1130         0,                                                              //tp_descr_get
1131         0,                                                              //tp_descr_set
1132         0,                                                              //tp_dictoffset
1133         (initproc)Armature_init,                //tp_init
1134         0,                                                              //tp_alloc
1135         (newfunc)Armature_new,                  //tp_new
1136         0,                                                              //tp_free
1137         0,                                                              //tp_is_gc
1138         0,                                                              //tp_bases
1139         0,                                                              //tp_mro
1140         0,                                                              //tp_cache
1141         0,                                                              //tp_subclasses
1142         0,                                                              //tp_weaklist
1143         0                                                               //tp_del
1144 };
1145
1146 //-------------------MODULE METHODS IMPLEMENTATION------------------------
1147 //----------------Blender.Armature.Get()
1148 /* This function will return a Py_Armature when a single string is passed
1149 * or else it will return a {key:value} dictionary when mutliple strings are passed
1150 * or it will return a {key:value} dictionary of all armatures when nothing is passed */
1151 static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
1152 {
1153         PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
1154         char *name = "", buffer[24];
1155         int size = 0, i;
1156         void *data;
1157
1158         //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
1159         size = PySequence_Length(args);
1160         if (size == 1) {
1161                 seq = PySequence_GetItem(args, 0); //*new*
1162                 if (!seq)
1163                         goto RuntimeError;
1164                 if(!PyString_Check(seq)){
1165                         if (PySequence_Check(seq)) {
1166                                 size = PySequence_Length(seq);
1167                         } else {
1168                                 Py_DECREF(seq);
1169                                 goto AttributeError;
1170                         }
1171                 }
1172         } else {
1173                 seq = EXPP_incr_ret(args); //*take ownership*
1174         }
1175         //'seq' should be a list, empty tuple or string - check list for strings
1176         if(!PyString_Check(seq)){
1177                 for(i = 0; i < size; i++){
1178                         item = PySequence_GetItem(seq, i); //*new*
1179                         if (!item) {
1180                                 Py_DECREF(seq);
1181                                 goto RuntimeError;
1182                         }
1183                         if(!PyString_Check(item)){
1184                                 EXPP_decr2(item, seq);
1185                                 goto AttributeError;
1186                         }
1187                         Py_DECREF(item);
1188                 }
1189         }
1190
1191         //GET ARMATURES
1192         if(size != 1){
1193                 dict = PyDict_New(); //*new*
1194                 if(!dict){
1195                         Py_DECREF(seq);
1196                         goto RuntimeError;
1197                 }
1198                 if(size == 0){  //GET ALL ARMATURES
1199                         data = G.main->armature.first; //get the first data ID from the armature library
1200                         while (data){
1201                                 py_armature = Armature_CreatePyObject(data); //*new*
1202                                 if (!py_armature) {
1203                                         EXPP_decr2(seq, dict);
1204                                         return NULL; /* error is set from Armature_CreatePyObject */
1205                                 }
1206                                 sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
1207                                 if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
1208                                         EXPP_decr3(seq, dict, py_armature);
1209                                         goto RuntimeError;
1210                                 }
1211                                 Py_DECREF(py_armature);
1212                                 data = ((ID*)data)->next;
1213                         }
1214                         Py_DECREF(seq);
1215                 }else{  //GET ARMATURE LIST
1216                         for (i = 0; i < size; i++) {
1217                                 item = PySequence_GetItem(seq, i); //*new*
1218                                 name = PyString_AsString(item);
1219                                 Py_DECREF(item);
1220                                 data = find_id("AR", name); //get data from library
1221                                 if (data != NULL){
1222                                         py_armature = Armature_CreatePyObject(data); //*new*
1223                                         if (!py_armature) {
1224                                                 EXPP_decr2(seq, dict);
1225                                                 return NULL; /* error is set from Armature_CreatePyObject */
1226                                         }
1227                                         
1228                                         if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
1229                                                 EXPP_decr3(seq, dict, py_armature);
1230                                                 goto RuntimeError;
1231                                         }
1232                                         Py_DECREF(py_armature);
1233                                 }else{
1234                                         if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
1235                                                 EXPP_decr2(seq, dict);
1236                                                 goto RuntimeError;
1237                                         }
1238                                         Py_DECREF(Py_None);
1239                                 }
1240                         }
1241                         Py_DECREF(seq);
1242                 }
1243                 return dict;
1244         }else{  //GET SINGLE ARMATURE
1245                 if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
1246                         item = PySequence_GetItem(seq, 0); //*new*
1247                         name = PyString_AsString(item);
1248                         Py_DECREF(item);
1249                 }else{
1250                         name = PyString_AsString(seq);
1251                 }
1252                 Py_DECREF(seq);
1253                 data = find_id("AR", name); //get data from library
1254                 if (data != NULL){
1255                         return Armature_CreatePyObject(data); //*new*
1256                 }else{
1257                         char buffer[128];
1258                         PyOS_snprintf( buffer, sizeof(buffer),
1259                                                    "Armature \"%s\" not found", name);
1260                         return EXPP_ReturnPyObjError( PyExc_ValueError,
1261                                                                                   buffer );
1262                 }
1263         }
1264
1265 RuntimeError:
1266         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1267                 sModuleError, "Get(): ", "Internal Error Ocurred");
1268
1269 AttributeError:
1270         return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
1271                 sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
1272 }
1273
1274
1275 //----------------Blender.Armature.New()
1276 static PyObject *M_Armature_New(PyObject * self, PyObject * args)
1277 {
1278         char *name = "Armature";
1279         struct bArmature *armature;
1280         BPy_Armature *obj;
1281
1282         if( !PyArg_ParseTuple( args, "|s", &name ) )
1283                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1284                                               "expected nothing or a string as argument" );
1285
1286         armature= add_armature(name);
1287         armature->id.us = 0;
1288         obj = (BPy_Armature *)Armature_CreatePyObject(armature); /*new*/
1289
1290         if( !obj )
1291                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1292                                        "PyObject_New() failed" );       
1293
1294         obj->armature = armature;
1295         return (PyObject *)obj;
1296 }
1297
1298
1299 //-------------------MODULE METHODS DEFINITION-----------------------------
1300
1301 static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
1302   returns None if not found.\n If 'name' is not specified, it returns a list of all \
1303   armatures in the\ncurrent scene.";
1304
1305 static char M_Armature_New_doc[] = "(name) - return a new armature object.";
1306
1307 struct PyMethodDef M_Armature_methods[] = {
1308         {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
1309         {"New", M_Armature_New, METH_VARARGS, M_Armature_New_doc},
1310         {NULL, NULL, 0, NULL}
1311 };
1312 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1313 //------------------------Armature_RebuildEditbones (internal)
1314 PyObject * Armature_RebuildEditbones(PyObject *pyarmature)
1315 {
1316         return Armature_makeEditable((BPy_Armature*)pyarmature);
1317 }
1318
1319 //------------------------Armature_RebuildBones (internal)
1320 PyObject *Armature_RebuildBones(PyObject *pyarmature)
1321 {
1322         return Armature_update((BPy_Armature*)pyarmature);
1323 }
1324
1325 /* internal func to remove weakref from weakref list */
1326 static PyObject * arm_weakref_callback_weakref_dealloc(PyObject *self, PyObject *weakref)
1327 {
1328         char *list_name = ARM_WEAKREF_LIST_NAME;
1329         PyObject *maindict = NULL, *armlist = NULL;
1330         int i;
1331         
1332         maindict= PyModule_GetDict(PyImport_AddModule(  "__main__"));
1333         armlist = PyDict_GetItemString(maindict, list_name);
1334         if( !armlist){
1335                 printf("Oops - update_armature_weakrefs()\n");
1336                 Py_RETURN_NONE;
1337         }
1338         
1339         i = PySequence_Index(armlist, weakref);
1340         if (i==-1) {
1341                 printf("callback weakref internal error, weakref not in list\n\tthis should never happen.\n");
1342                 Py_RETURN_NONE;
1343         }
1344         PySequence_DelItem(armlist, i);
1345         Py_RETURN_NONE;
1346 }
1347
1348 /*-----------------(internal)
1349  * Converts a bArmature to a PyArmature */
1350
1351 PyObject *Armature_CreatePyObject(struct bArmature *armature)
1352 {
1353         BPy_Armature *py_armature = NULL;
1354         PyObject *maindict = NULL, *weakref = NULL;
1355         PyObject *armlist = NULL;  /* list of armature weak refs */
1356         char *list_name = ARM_WEAKREF_LIST_NAME;
1357         int i;
1358
1359         //put a weakreference in __main__
1360         maindict= PyModule_GetDict(PyImport_AddModule(  "__main__"));
1361
1362         armlist = PyDict_GetItemString(maindict, list_name);
1363         if(!armlist) {
1364                 printf("Oops - can't get the armature weakref list\n");
1365                 goto RuntimeError;
1366         }
1367
1368         /* see if we alredy have it */
1369         for (i=0; i< PyList_Size(armlist); i++) { 
1370                 py_armature = (BPy_Armature *)PyWeakref_GetObject(PyList_GET_ITEM(armlist, i));
1371                 if (BPy_Armature_Check(py_armature) && py_armature->armature == armature) {
1372                         Py_INCREF(py_armature);
1373                         /*printf("reusing armature\n");*/
1374                         return (PyObject *)py_armature;
1375                 }
1376         }
1377
1378         
1379         /*create armature type*/
1380         py_armature = PyObject_NEW( BPy_Armature, &Armature_Type );
1381         
1382         if (!py_armature){
1383                 printf("Oops - can't create py armature\n");
1384                 goto RuntimeError;
1385         }
1386
1387         py_armature->armature = armature;
1388         py_armature->weaklist = NULL; //init the weaklist
1389         
1390         //create armature.bones
1391         py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
1392         if (!py_armature->Bones){
1393                 printf("Oops - creating armature.bones\n");
1394                 goto RuntimeError;
1395         }
1396         
1397         weakref = PyWeakref_NewRef((PyObject*)py_armature, arm_weakref_callback_weakref_dealloc__pyfunc);
1398         if (PyList_Append(armlist, weakref) == -1){
1399                 printf("Oops - list-append failed\n");
1400                 goto RuntimeError;
1401         }
1402         Py_DECREF(weakref);
1403
1404         return (PyObject *) py_armature;
1405
1406 RuntimeError:
1407         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1408                 sModuleError, "Armature_CreatePyObject: ", "Internal Error Ocurred");
1409 }
1410 //-----------------(internal)
1411 //Converts a PyArmature to a bArmature
1412 struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
1413 {
1414         return (py_armature->armature);
1415 }
1416
1417 struct bArmature *Armature_FromPyObject( PyObject * py_obj )
1418 {
1419         return PyArmature_AsArmature((BPy_Armature*)py_obj);
1420 }
1421
1422 /* internal use only */
1423 static PyMethodDef bpy_arm_weakref_callback_weakref_dealloc[] = {
1424         {"arm_weakref_callback_weakref_dealloc", arm_weakref_callback_weakref_dealloc, METH_O, ""}
1425 };
1426
1427 //-------------------MODULE INITIALIZATION--------------------------------
1428 PyObject *Armature_Init(void)
1429 {
1430         PyObject *module, *dict;
1431
1432         //Initializes TypeObject.ob_type
1433         if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
1434                 PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0) {
1435                 return EXPP_incr_ret(Py_None);
1436         }
1437
1438         /* Weakref management - used for callbacks so we can
1439          * tell when a callback has been removed that a UI button referenced */
1440         arm_weakref_callback_weakref_dealloc__pyfunc = PyCFunction_New(bpy_arm_weakref_callback_weakref_dealloc, NULL);
1441         
1442         
1443         //Register the module
1444         module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
1445                 "The Blender Armature module"); 
1446
1447         //Add TYPEOBJECTS to the module
1448         PyModule_AddObject(module, "Armature", 
1449                 EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
1450         PyModule_AddObject(module, "Bone", 
1451                 EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
1452         PyModule_AddObject(module, "Editbone", 
1453                 EXPP_incr_ret((PyObject *)&EditBone_Type)); //*steals*
1454
1455         //Add CONSTANTS to the module
1456         PyModule_AddObject(module, "CONNECTED", 
1457                 PyConstant_NewInt("CONNECTED", BONE_CONNECTED));
1458         PyModule_AddObject(module, "HINGE", 
1459                 PyConstant_NewInt("HINGE", BONE_HINGE));
1460         PyModule_AddObject(module, "NO_DEFORM", 
1461                 PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM));
1462         PyModule_AddObject(module, "MULTIPLY", 
1463                 PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV));
1464         PyModule_AddObject(module, "HIDDEN_EDIT", 
1465                 PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A));
1466         PyModule_AddObject(module, "ROOT_SELECTED", 
1467                 PyConstant_NewInt("ROOT_SELECTED", BONE_ROOTSEL));
1468         PyModule_AddObject(module, "BONE_SELECTED", 
1469                 PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED));
1470         PyModule_AddObject(module, "TIP_SELECTED", 
1471                 PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL));
1472         PyModule_AddObject(module, "LOCKED_EDIT", 
1473                 PyConstant_NewInt("LOCKED_EDIT", BONE_EDITMODE_LOCKED));
1474
1475         PyModule_AddObject(module, "OCTAHEDRON", 
1476                 PyConstant_NewInt("OCTAHEDRON", ARM_OCTA));
1477         PyModule_AddObject(module, "STICK", 
1478                 PyConstant_NewInt("STICK", ARM_LINE));
1479         PyModule_AddObject(module, "BBONE", 
1480                 PyConstant_NewInt("BBONE", ARM_B_BONE));
1481         PyModule_AddObject(module, "ENVELOPE", 
1482                 PyConstant_NewInt("ENVELOPE", ARM_ENVELOPE));
1483
1484         //Add SUBMODULES to the module
1485         dict = PyModule_GetDict( module ); //borrowed
1486         PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
1487
1488         return module;
1489 }