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