1ad5938c17ee7906dc3833ebbe84d95999385e99
[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                 
301                 // FIXME, should be exposed via python. this avoids creating bones with no layers.
302                 editbone->layer= 1;
303                 
304                 //set object pointer
305                 ((BPy_EditBone*)value)->editbone = editbone;
306
307                 //fix the bone's head position if flags indicate that it is 'connected'
308                 if (editbone->flag & BONE_CONNECTED){
309                         if(!editbone->parent){
310                                 ((BPy_EditBone*)value)->editbone = NULL;
311                                 MEM_freeN(editbone);
312                                         return EXPP_intError(PyExc_AttributeError, "%s%s", 
313                                                         sBoneDictBadArgs,  "The 'connected' flag is set but the bone has no parent!");
314                         }else{
315                                 VECCOPY(editbone->head, editbone->parent->tail);
316                         }
317                 }
318
319                 //set in editbonelist
320                 BLI_addtail(&self->editbones, editbone);
321
322                 //set the new editbone in the mapping
323                 if(PyDict_SetItemString(self->editbonesMap, key_str, value) == -1){
324                         ((BPy_EditBone*)value)->editbone = NULL;
325                         BLI_freelinkN(&self->editbones, editbone);
326                         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
327                                         sBoneDictError,  "Unable to access dictionary!");
328                 }
329         }else {
330                 //they are trying to delete the bone using 'del'
331                 editbone_for_deletion = (BPy_EditBone*)PyDict_GetItem(self->editbonesMap, key);
332
333                 if (!editbone_for_deletion)
334                         return EXPP_intError(PyExc_KeyError, "%s%s%s%s", 
335                                         sBoneDictError,  "The key: ", key_str, " is not present in this dictionary!");
336
337                 /*first kill the datastruct then remove the item from the dict
338                 and wait for GC to pick it up.
339                 We have to delete the datastruct here because the tp_dealloc
340                 doesn't handle it*/
341                 
342                 /*this is ugly but you have to set the parent to NULL for else 
343                 editbones_to_armature will crash looking for this bone*/
344                 for (editbone = self->editbones.first; editbone; editbone = editbone->next){
345                         if (editbone->parent == editbone_for_deletion->editbone) {
346                                 editbone->parent = NULL;
347                                  /* remove the connected flag or else the 'root' ball
348                                   * doesn't get drawn */
349                                 editbone->flag &= ~BONE_CONNECTED;
350                         }
351                 }
352                 BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
353                 if(PyDict_DelItem(self->editbonesMap, key) == -1)
354                         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
355                                         sBoneDictError,  "Unable to access dictionary!");
356         }
357         return 0;
358 }
359 //------------------TYPE_OBJECT DEFINITION--------------------------
360 //Mapping Protocol
361 static PyMappingMethods BonesDict_MapMethods = {
362         (inquiry) BonesDict_len,                                        //mp_length
363         (binaryfunc)BonesDict_GetItem,          //mp_subscript
364         (objobjargproc)BonesDict_SetItem,       //mp_ass_subscript
365 };
366 //BonesDict TypeObject
367 PyTypeObject BonesDict_Type = {
368         PyObject_HEAD_INIT(NULL)                        //tp_head
369         0,                                                                                              //tp_internal
370         "BonesDict",                                                            //tp_name
371         sizeof(BPy_BonesDict),                                  //tp_basicsize
372         0,                                                                                              //tp_itemsize
373         (destructor)BonesDict_dealloc,          //tp_dealloc
374         0,                                                                                              //tp_print
375         0,                                                                                              //tp_getattr
376         0,                                                                                              //tp_setattr
377         0,                                                                                              //tp_compare
378         (reprfunc) BonesDict_repr,                              //tp_repr
379         0,                                                                                              //tp_as_number
380         0,                                                                                              //tp_as_sequence
381         &BonesDict_MapMethods,                          //tp_as_mapping
382         0,                                                                                              //tp_hash
383         0,                                                                                              //tp_call
384         0,                                                                                              //tp_str
385         0,                                                                                              //tp_getattro
386         0,                                                                                              //tp_setattro
387         0,                                                                                              //tp_as_buffer
388         Py_TPFLAGS_DEFAULT,                                     //tp_flags
389         BPy_BonesDict_doc,                                              //tp_doc
390         0,                                                                                              //tp_traverse
391         0,                                                                                              //tp_clear
392         0,                                                                                              //tp_richcompare
393         0,                                                                                              //tp_weaklistoffset
394         0,                                                                                              //tp_iter
395         0,                                                                                              //tp_iternext
396         BPy_BonesDict_methods,                          //tp_methods
397         0,                                                                                              //tp_members
398         0,                                                                                              //tp_getset
399         0,                                                                                              //tp_base
400         0,                                                                                              //tp_dict
401         0,                                                                                              //tp_descr_get
402         0,                                                                                              //tp_descr_set
403         0,                                                                                              //tp_dictoffset
404         0,                                                              //tp_init
405         0,                                                                                              //tp_alloc
406         0,                                                                                              //tp_new
407         0,                                                                                              //tp_free
408         0,                                                                                              //tp_is_gc
409         0,                                                                                              //tp_bases
410         0,                                                                                              //tp_mro
411         0,                                                                                              //tp_cache
412         0,                                                                                              //tp_subclasses
413         0,                                                                                              //tp_weaklist
414         0                                                                                               //tp_del
415 };
416 //-----------------------PyBonesDict_FromPyArmature
417 static PyObject *PyBonesDict_FromPyArmature(BPy_Armature *py_armature)
418 {
419         BPy_BonesDict *py_BonesDict = (BPy_BonesDict *)PyObject_NEW( BPy_BonesDict, &BonesDict_Type );
420         if (!py_BonesDict)
421                 goto RuntimeError;
422
423         py_BonesDict->bones = NULL;
424         py_BonesDict->editbones.first = py_BonesDict->editbones.last = NULL;
425
426         //create internal dictionaries
427         py_BonesDict->bonesMap = PyDict_New();
428         py_BonesDict->editbonesMap = PyDict_New();
429         if (!py_BonesDict->bonesMap || !py_BonesDict->editbonesMap)
430                 goto RuntimeError;
431
432         //set listbase pointer
433         py_BonesDict->bones = &py_armature->armature->bonebase;
434
435         //now that everything is setup - init the mappings
436         if (!BonesDict_InitBones(py_BonesDict))
437                 goto RuntimeError;
438         if (!BonesDict_InitEditBones(py_BonesDict))
439                 goto RuntimeError;
440
441         //set editmode flag
442         py_BonesDict->editmode_flag = 0; 
443
444         return (PyObject*)py_BonesDict;
445
446 RuntimeError:
447         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
448                 sBoneDictError, "Failed to create class");
449 }
450
451 //######################### Armature_Type #############################
452 /*This type represents a thin wrapper around bArmature data types
453 * internal to blender. It contains the psuedo-dictionary BonesDict
454 * as an assistant in manipulating it's own bone collection*/
455 //#################################################################
456
457 //------------------METHOD IMPLEMENTATION------------------------------
458 //------------------------Armature.makeEditable()
459 static PyObject *Armature_makeEditable(BPy_Armature *self)
460 {
461         if (self->armature->flag & ARM_EDITMODE)
462                 goto AttributeError;
463
464         make_boneList(&self->Bones->editbones, self->Bones->bones, NULL);
465         if (!BonesDict_InitEditBones(self->Bones))
466                 return NULL;
467         self->Bones->editmode_flag = 1;
468         return EXPP_incr_ret(Py_None);
469
470 AttributeError:
471         return EXPP_objError(PyExc_AttributeError, "%s%s", 
472                 sArmatureBadArgs, "The armature cannot be placed manually in editmode before you call makeEditable()!");
473 }
474
475 //------------------------Armature.update()
476 //This is a bit ugly because you need an object link to do this
477 static PyObject *Armature_update(BPy_Armature *self)
478 {
479         Object *obj = NULL;
480
481         for (obj = G.main->object.first; obj; obj = obj->id.next){
482                 if (obj->data == self->armature)
483                         break;
484         }
485         if (obj){
486                 editbones_to_armature (&self->Bones->editbones, obj);
487                 if (!BonesDict_InitBones(self->Bones))
488                         return NULL;
489                 self->Bones->editmode_flag = 0;
490                 BLI_freelistN(&self->Bones->editbones);
491         }else{
492                 goto AttributeError;
493
494         }
495         return EXPP_incr_ret(Py_None);
496
497 AttributeError:
498         return EXPP_objError(PyExc_AttributeError, "%s%s", 
499                 sArmatureBadArgs, "The armature must be linked to an object before you can save changes!");
500 }
501
502 //------------------------Armature.__copy__()
503 static PyObject *Armature_copy(BPy_Armature *self)
504 {
505         PyObject *py_armature = NULL;
506         bArmature *bl_armature;
507         bl_armature= copy_armature(self->armature);
508         bl_armature->id.us= 0;
509         py_armature= Armature_CreatePyObject( bl_armature );
510         return py_armature;
511 }
512
513 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
514 //------------------------Armature.autoIK (getter)
515 static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
516 {
517         if (self->armature->flag & ARM_AUTO_IK)
518                 return EXPP_incr_ret(Py_True);
519         else
520                 return EXPP_incr_ret(Py_False);
521 }
522 //------------------------Armature.autoIK (setter)
523 static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
524 {
525         if(value){
526                 if(PyBool_Check(value)){
527                         if (value == Py_True){
528                                 self->armature->flag |= ARM_AUTO_IK;
529                                 return 0;
530                         }else if (value == Py_False){
531                                 self->armature->flag &= ~ARM_AUTO_IK;
532                                 return 0;
533                         }
534                 }
535         }
536         goto AttributeError;
537
538 AttributeError:
539         return EXPP_intError(PyExc_AttributeError, "%s%s", 
540                 sArmatureBadArgs, "Expects True or False");
541 }
542 //------------------------Armature.layers (getter)
543 static PyObject *Armature_getLayers(BPy_Armature *self, void *closure)
544 {
545         int layers, bit = 0, val = 0;
546         PyObject *item = NULL, *laylist = PyList_New( 0 );
547
548         if( !laylist )
549                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
550                         "couldn't create pylist!" );
551
552         layers = self->armature->layer;
553
554         while( bit < 20 ) {
555                 val = 1 << bit;
556                 if( layers & val ) {
557                         item = Py_BuildValue( "i", bit + 1 );
558                         PyList_Append( laylist, item );
559                         Py_DECREF( item );
560                 }
561                 bit++;
562         }
563         return laylist;
564 }
565 //------------------------Armature.layer (setter)
566 static int Armature_setLayers(BPy_Armature *self, PyObject *value, void *closure)
567 {
568         if(value){
569                 if(PyList_Check(value)){
570                         int layers = 0, len_list = 0;
571                         int val;
572                         PyObject *item = NULL;
573
574                         len_list = PyList_Size(value);
575
576                         if( len_list == 0 )
577                                 return EXPP_ReturnIntError( PyExc_AttributeError,
578                                   "list can't be empty, at least one layer must be set" );
579
580                         while( len_list ) {
581                                 --len_list;
582                                 item = PyList_GetItem( value, len_list );
583                                 if( !PyInt_Check( item ) )
584                                         return EXPP_ReturnIntError( PyExc_AttributeError,
585                                                         "list must contain only integer numbers" );
586
587                                 val = ( int ) PyInt_AsLong( item );
588                                 if( val < 1 || val > 20 )
589                                         return EXPP_ReturnIntError( PyExc_AttributeError,
590                                                   "layer values must be in the range [1, 20]" );
591
592                                 layers |= 1 << ( val - 1 );
593                         }
594
595                         /* update any bases pointing to our object */
596                         self->armature->layer = (short)layers;
597
598                         return 0;
599                 }
600         }
601         goto AttributeError;
602
603 AttributeError:
604         return EXPP_ReturnIntError( PyExc_TypeError,
605                         "expected a list of integers" );
606 }
607
608 //------------------------Armature.mirrorEdit (getter)
609 static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
610 {
611         if (self->armature->flag & ARM_MIRROR_EDIT)
612                 return EXPP_incr_ret(Py_True);
613         else
614                 return EXPP_incr_ret(Py_False);
615 }
616 //------------------------Armature.mirrorEdit (setter)
617 static int Armature_setMirrorEdit(BPy_Armature *self, PyObject *value, void *closure)
618 {
619         if(value){
620                 if(PyBool_Check(value)){
621                         if (value == Py_True){
622                                 self->armature->flag |= ARM_MIRROR_EDIT;
623                                 return 0;
624                         }else if (value == Py_False){
625                                 self->armature->flag &= ~ARM_MIRROR_EDIT;
626                                 return 0;
627                         }
628                 }
629         }
630         goto AttributeError;
631
632 AttributeError:
633         return EXPP_intError(PyExc_AttributeError, "%s%s", 
634                 sArmatureBadArgs, "Expects True or False");
635 }
636 //------------------------Armature.drawType (getter)
637 static PyObject *Armature_getDrawType(BPy_Armature *self, void *closure)
638 {
639         if (self->armature->drawtype == ARM_OCTA){
640                 return EXPP_GetModuleConstant("Blender.Armature", "OCTAHEDRON") ;
641         }else if (self->armature->drawtype == ARM_LINE){
642                 return EXPP_GetModuleConstant("Blender.Armature", "STICK") ;
643         }else if (self->armature->drawtype == ARM_B_BONE){
644                 return EXPP_GetModuleConstant("Blender.Armature", "BBONE") ;
645         }else if (self->armature->drawtype == ARM_ENVELOPE){
646                 return EXPP_GetModuleConstant("Blender.Armature", "ENVELOPE") ;
647         }else{
648                 goto RuntimeError;
649         }
650
651 RuntimeError:
652         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
653                 sArmatureError, "drawType: ", "Internal failure!");
654 }
655 //------------------------Armature.drawType (setter)
656 static int Armature_setDrawType(BPy_Armature *self, PyObject *value, void *closure)
657 {
658         PyObject *val = NULL, *name = NULL;
659         long numeric_value;
660
661         if(value){
662                 if(BPy_Constant_Check(value)){
663                         name = PyDict_GetItemString(((BPy_constant*)value)->dict, "name");
664                         if (!STREQ2(PyString_AsString(name), "OCTAHEDRON", "STICK") &&
665                                 !STREQ2(PyString_AsString(name), "BBONE", "ENVELOPE"))
666                                 goto ValueError;
667                         val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
668                         if (PyInt_Check(val)){
669                                 numeric_value = PyInt_AS_LONG(val);
670                                 self->armature->drawtype = (int)numeric_value;
671                                 return 0;
672                         }
673                 }
674         }
675         goto AttributeError;
676
677 AttributeError:
678         return EXPP_intError(PyExc_AttributeError, "%s%s", 
679                 sArmatureBadArgs, "Expects module constant");
680
681 ValueError:
682         return EXPP_intError(PyExc_AttributeError, "%s%s", 
683                 sArmatureBadArgs, "Argument must be the constant OCTAHEDRON, STICK, BBONE, or ENVELOPE");
684 }
685 //------------------------Armature.ghostStep (getter)
686 static PyObject *Armature_getStep(BPy_Armature *self, void *closure)
687 {
688         return PyInt_FromLong((long)self->armature->ghostsize);
689 }
690 //------------------------Armature.ghostStep (setter)
691 static int Armature_setStep(BPy_Armature *self, PyObject *value, void *closure)
692 {
693         long numerical_value;
694
695         if(value){
696                 if(PyInt_Check(value)){
697                         numerical_value = PyInt_AS_LONG(value);
698                         if (numerical_value > 20.0f || numerical_value < 1.0f)
699                                 goto ValueError;
700                         self->armature->ghostsize = (short)numerical_value;
701                         return 0;
702                 }
703         }
704         goto AttributeError;
705
706 AttributeError:
707         return EXPP_intError(PyExc_AttributeError, "%s%s", 
708                 sArmatureBadArgs, "Expects Integer");
709
710 ValueError:
711         return EXPP_intError(PyExc_AttributeError, "%s%s", 
712                 sArmatureBadArgs, "Argument must fall within 1-20");
713 }
714 //------------------------Armature.ghost (getter)
715 static PyObject *Armature_getGhost(BPy_Armature *self, void *closure)
716 {
717         return PyInt_FromLong((long)self->armature->ghostep);
718 }
719 //------------------------Armature.ghost (setter)
720 static int Armature_setGhost(BPy_Armature *self, PyObject *value, void *closure)
721 {
722         long numerical_value;
723
724         if(value){
725                 if(PyInt_Check(value)){
726                         numerical_value = PyInt_AS_LONG(value);
727                         if (numerical_value > 30.0f || numerical_value < 0.0f)
728                                 goto ValueError;
729                         self->armature->ghostep = (short)numerical_value;
730                         return 0;
731                 }
732         }
733         goto AttributeError;
734
735 AttributeError:
736         return EXPP_intError(PyExc_AttributeError, "%s%s", 
737                 sArmatureBadArgs, "Expects Integer");
738
739 ValueError:
740         return EXPP_intError(PyExc_AttributeError, "%s%s", 
741                 sArmatureBadArgs, "Argument must fall within 0-30");
742 }
743 //------------------------Armature.drawNames (getter)
744 static PyObject *Armature_getDrawNames(BPy_Armature *self, void *closure)
745 {
746         if (self->armature->flag & ARM_DRAWNAMES)
747                 return EXPP_incr_ret(Py_True);
748         else
749                 return EXPP_incr_ret(Py_False);
750 }
751 //------------------------Armature.drawNames (setter)
752 static int Armature_setDrawNames(BPy_Armature *self, PyObject *value, void *closure)
753 {
754         if(value){
755                 if(PyBool_Check(value)){
756                         if (value == Py_True){
757                                 self->armature->flag |= ARM_DRAWNAMES;
758                                 return 0;
759                         }else if (value == Py_False){
760                                 self->armature->flag &= ~ARM_DRAWNAMES;
761                                 return 0;
762                         }
763                 }
764         }
765         goto AttributeError;
766
767 AttributeError:
768         return EXPP_intError(PyExc_AttributeError, "%s%s", 
769                 sArmatureBadArgs, "Expects True or False");
770 }
771 //------------------------Armature.drawAxes (getter)
772 static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
773 {
774         if (self->armature->flag & ARM_DRAWAXES)
775                 return EXPP_incr_ret(Py_True);
776         else
777                 return EXPP_incr_ret(Py_False);
778 }
779 //------------------------Armature.drawAxes (setter)
780 static int Armature_setDrawAxes(BPy_Armature *self, PyObject *value, void *closure)
781 {
782         if(value){
783                 if(PyBool_Check(value)){
784                         if (value == Py_True){
785                                 self->armature->flag |= ARM_DRAWAXES;
786                                 return 0;
787                         }else if (value == Py_False){
788                                 self->armature->flag &= ~ARM_DRAWAXES;
789                                 return 0;
790                         }
791                 }
792         }
793         goto AttributeError;
794
795 AttributeError:
796         return EXPP_intError(PyExc_AttributeError, "%s%s", 
797                 sArmatureBadArgs, "Expects True or False");
798 }
799 //------------------------Armature.delayDeform (getter)
800 static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
801 {
802         if (self->armature->flag & ARM_DELAYDEFORM)
803                 return EXPP_incr_ret(Py_True);
804         else
805                 return EXPP_incr_ret(Py_False);
806 }
807 //------------------------Armature.delayDeform (setter)
808 static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
809 {
810         if(value){
811                 if(PyBool_Check(value)){
812                         if (value == Py_True){
813                                 self->armature->flag |= ARM_DELAYDEFORM;
814                                 return 0;
815                         }else if (value == Py_False){
816                                 self->armature->flag &= ~ARM_DELAYDEFORM;
817                                 return 0;
818                         }
819                 }
820         }
821         goto AttributeError;
822
823 AttributeError:
824         return EXPP_intError(PyExc_AttributeError, "%s%s", 
825                 sArmatureBadArgs, "Expects True or False");
826 }
827 //------------------------Armature.restPosition (getter)
828 static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
829 {
830         if (self->armature->flag & ARM_RESTPOS)
831                 return EXPP_incr_ret(Py_True);
832         else
833                 return EXPP_incr_ret(Py_False);
834 }
835 //------------------------Armature.restPosition (setter)
836 static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
837 {
838         if(value){
839                 if(PyBool_Check(value)){
840                         if (value == Py_True){
841                                 self->armature->flag |= ARM_RESTPOS;
842                                 return 0;
843                         }else if (value == Py_False){
844                                 self->armature->flag &= ~ARM_RESTPOS;
845                                 return 0;
846                         }
847                 }
848         }
849         goto AttributeError;
850
851 AttributeError:
852         return EXPP_intError(PyExc_AttributeError, "%s%s", 
853                 sArmatureBadArgs, "Expects True or False");
854 }
855 //------------------------Armature.envelopes (getter)
856 static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
857 {
858         if (self->armature->deformflag & ARM_DEF_ENVELOPE)
859                 return EXPP_incr_ret(Py_True);
860         else
861                 return EXPP_incr_ret(Py_False);
862 }
863 //------------------------Armature.envelopes (setter)
864 static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
865 {
866         if(value){
867                 if(PyBool_Check(value)){
868                         if (value == Py_True){
869                                 self->armature->deformflag |= ARM_DEF_ENVELOPE;
870                                 return 0;
871                         }else if (value == Py_False){
872                                 self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
873                                 return 0;
874                         }
875                 }
876         }
877         goto AttributeError;
878
879 AttributeError:
880         return EXPP_intError(PyExc_AttributeError, "%s%s", 
881                 sArmatureBadArgs, "Expects True or False");
882 }
883 //------------------------Armature.vertexGroups (getter)
884 static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
885 {
886         if (self->armature->deformflag & ARM_DEF_VGROUP)
887                 return EXPP_incr_ret(Py_True);
888         else
889                 return EXPP_incr_ret(Py_False);
890 }
891 //------------------------Armature.vertexGroups (setter)
892 static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
893 {
894         if(value){
895                 if(PyBool_Check(value)){
896                         if (value == Py_True){
897                                 self->armature->deformflag |= ARM_DEF_VGROUP;
898                                 return 0;
899                         }else if (value == Py_False){
900                                 self->armature->deformflag &= ~ARM_DEF_VGROUP;
901                                 return 0;
902                         }
903                 }
904         }
905         goto AttributeError;
906
907 AttributeError:
908         return EXPP_intError(PyExc_AttributeError, "%s%s", 
909                 sArmatureBadArgs, "Expects True or False");
910 }
911
912 //------------------------Armature.bones (getter)
913 //Gets the name of the armature
914 static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
915 {
916     return EXPP_incr_ret((PyObject*)self->Bones);
917 }
918 //------------------------Armature.bones (setter)
919 //Sets the name of the armature
920 /*TODO*/
921 /*Copy Bones through x = y*/
922 static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
923 {
924         goto AttributeError;
925
926 AttributeError:
927         return EXPP_intError(PyExc_AttributeError, "%s%s", 
928                 sArmatureError, "You are not allowed to change the .Bones attribute");
929 }
930 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
931 //------------------------tp_doc
932 //The __doc__ string for this object
933 static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
934 //------------------------tp_methods
935 //This contains a list of all methods the object contains
936 static PyMethodDef BPy_Armature_methods[] = {
937         {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
938                 "() - Unlocks the ability to modify armature bones"},
939         {"update", (PyCFunction) Armature_update, METH_NOARGS, 
940                 "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
941         {"__copy__", (PyCFunction) Armature_copy, METH_NOARGS, 
942                 "() - Return a copy of the armature."},
943         {"copy", (PyCFunction) Armature_copy, METH_NOARGS, 
944                 "() - Return a copy of the armature."},
945         {NULL, NULL, 0, NULL}
946 };
947 //------------------------tp_getset
948 //This contains methods for attributes that require checking
949 static PyGetSetDef BPy_Armature_getset[] = {
950         GENERIC_LIB_GETSETATTR,
951         {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
952                 "The armature's Bone dictionary", NULL},
953         {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
954                 "Enable/Disable vertex group defined deformation", NULL},
955         {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
956                 "Enable/Disable bone envelope defined deformation", NULL},
957         {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
958                 "Show armature rest position - disables posing", NULL},
959         {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
960                 "Don't deform children when manipulating bones in pose mode", NULL},
961         {"drawAxes", (getter)Armature_getDrawAxes, (setter)Armature_setDrawAxes, 
962                 "Enable/Disable  drawing  the bone axes", NULL},
963         {"drawNames", (getter)Armature_getDrawNames, (setter)Armature_setDrawNames, 
964                 "Enable/Disable  drawing the bone names", NULL},
965         {"ghost", (getter)Armature_getGhost, (setter)Armature_setGhost, 
966                 "Draw a number of ghosts around the current frame for current Action", NULL},
967         {"ghostStep", (getter)Armature_getStep, (setter)Armature_setStep, 
968                 "The number of frames between ghost instances", NULL},
969         {"drawType", (getter)Armature_getDrawType, (setter)Armature_setDrawType, 
970                 "The type of drawing currently applied to the armature", NULL},
971         {"mirrorEdit", (getter)Armature_getMirrorEdit, (setter)Armature_setMirrorEdit, 
972                 "Enable/Disable X-axis mirrored editing", NULL},
973         {"autoIK", (getter)Armature_getAutoIK, (setter)Armature_setAutoIK, 
974                 "Adds temporal IK chains while grabbing bones", NULL},
975         {"layers", (getter)Armature_getLayers, (setter)Armature_setLayers, 
976                 "List of layers for the armature", NULL},
977         {NULL, NULL, NULL, NULL, NULL}
978 };
979 //------------------------tp_new
980 //This methods creates a new object (note it does not initialize it - only the building)
981 //This can be called through python by myObject.__new__() however, tp_init is not called
982 static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
983 {
984         BPy_Armature *py_armature = NULL;
985         bArmature *bl_armature;
986
987         bl_armature = add_armature("Armature");
988         if(bl_armature) {
989                 bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
990
991                 py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
992                 if (py_armature == NULL)
993                         goto RuntimeError;
994
995                 py_armature->armature = bl_armature;
996
997                 //create armature.bones
998                 py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
999                 if (!py_armature->Bones)
1000                         goto RuntimeError;
1001
1002         } else {
1003                 goto RuntimeError;
1004         }
1005         return (PyObject*)py_armature; 
1006
1007 RuntimeError:
1008         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1009                 sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
1010 }
1011 //------------------------tp_init
1012 //This methods does initialization of the new object
1013 //This method will get called in python by 'myObject(argument, keyword=value)'
1014 //tp_new will be automatically called before this
1015 static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
1016 {
1017         char buf[21];
1018         char *name = "myArmature";
1019         static char *kwlist[] = {"name", NULL};
1020
1021         if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
1022                 goto AttributeError;
1023         }
1024
1025         //rename the armature if a name is supplied
1026         if(!BLI_streq(name, "myArmature")){
1027                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
1028                 rename_id(&self->armature->id, buf);
1029         }
1030         return 0;
1031
1032 AttributeError:
1033         return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
1034                 sArmatureBadArgs, " __init__: ", "Expects string(name)");
1035 }
1036
1037
1038 /*****************************************************************************/
1039 /* Function:    Armature_compare                                                 */
1040 /* Description: This is a callback function for the BPy_Armature type. It        */
1041 /*              compares two Armature_Type objects. Only the "==" and "!="  */
1042 /*              comparisons are meaninful. Returns 0 for equality and -1 if  */
1043 /*              they don't point to the same Blender Object struct.      */
1044 /*              In Python it becomes 1 if they are equal, 0 otherwise.   */
1045 /*****************************************************************************/
1046 static int Armature_compare( BPy_Armature * a, BPy_Armature * b )
1047 {
1048         return ( a->armature == b->armature ) ? 0 : -1;
1049 }
1050
1051 //------------------------tp_repr
1052 //This is the string representation of the object
1053 static PyObject *Armature_repr(BPy_Armature *self)
1054 {
1055         return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
1056 }
1057 //------------------------tp_dealloc
1058 //This tells how to 'tear-down' our object when ref count hits 0
1059 ///tp_dealloc
1060 static void Armature_dealloc(BPy_Armature * self)
1061 {
1062         if (self->weaklist != NULL)
1063                 PyObject_ClearWeakRefs((PyObject *) self); /* this causes the weakref dealloc func to be called */
1064         
1065         Py_DECREF(self->Bones);
1066         PyObject_DEL( self );
1067 }
1068 //------------------TYPE_OBECT DEFINITION--------------------------
1069 PyTypeObject Armature_Type = {
1070         PyObject_HEAD_INIT(NULL)                //tp_head
1071         0,                                                              //tp_internal
1072         "Armature",                                             //tp_name
1073         sizeof(BPy_Armature),                   //tp_basicsize
1074         0,                                                              //tp_itemsize
1075         (destructor)Armature_dealloc,   //tp_dealloc
1076         0,                                                              //tp_print
1077         0,                                                              //tp_getattr
1078         0,                                                              //tp_setattr
1079         (cmpfunc) Armature_compare,             //tp_compare
1080         (reprfunc) Armature_repr,               //tp_repr
1081         0,                                                              //tp_as_number
1082         0,                                                              //tp_as_sequence
1083         0,                                                              //tp_as_mapping
1084         ( hashfunc ) GenericLib_hash,   //tp_hash
1085         0,                                                              //tp_call
1086         0,                                                              //tp_str
1087         0,                                                              //tp_getattro
1088         0,                                                              //tp_setattro
1089         0,                                                              //tp_as_buffer
1090         Py_TPFLAGS_DEFAULT| Py_TPFLAGS_HAVE_WEAKREFS,                           //tp_flags
1091         BPy_Armature_doc,                               //tp_doc
1092         0,                                                              //tp_traverse
1093         0,                                                              //tp_clear
1094         0,                                                              //tp_richcompare
1095         offsetof(BPy_Armature, weaklist),       //tp_weaklistoffset
1096         0,                                                              //tp_iter
1097         0,                                                              //tp_iternext
1098         BPy_Armature_methods,                   //tp_methods
1099         0,                                                              //tp_members
1100         BPy_Armature_getset,                    //tp_getset
1101         0,                                                              //tp_base
1102         0,                                                              //tp_dict
1103         0,                                                              //tp_descr_get
1104         0,                                                              //tp_descr_set
1105         0,                                                              //tp_dictoffset
1106         (initproc)Armature_init,                //tp_init
1107         0,                                                              //tp_alloc
1108         (newfunc)Armature_new,                  //tp_new
1109         0,                                                              //tp_free
1110         0,                                                              //tp_is_gc
1111         0,                                                              //tp_bases
1112         0,                                                              //tp_mro
1113         0,                                                              //tp_cache
1114         0,                                                              //tp_subclasses
1115         0,                                                              //tp_weaklist
1116         0                                                               //tp_del
1117 };
1118
1119 //-------------------MODULE METHODS IMPLEMENTATION------------------------
1120 //----------------Blender.Armature.Get()
1121 /* This function will return a Py_Armature when a single string is passed
1122 * or else it will return a {key:value} dictionary when mutliple strings are passed
1123 * or it will return a {key:value} dictionary of all armatures when nothing is passed */
1124 static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
1125 {
1126         PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
1127         char *name = "", buffer[24];
1128         int size = 0, i;
1129         void *data;
1130
1131         //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
1132         size = PySequence_Length(args);
1133         if (size == 1) {
1134                 seq = PySequence_GetItem(args, 0); //*new*
1135                 if (!seq)
1136                         goto RuntimeError;
1137                 if(!PyString_Check(seq)){
1138                         if (PySequence_Check(seq)) {
1139                                 size = PySequence_Length(seq);
1140                         } else {
1141                                 Py_DECREF(seq);
1142                                 goto AttributeError;
1143                         }
1144                 }
1145         } else {
1146                 seq = EXPP_incr_ret(args); //*take ownership*
1147         }
1148         //'seq' should be a list, empty tuple or string - check list for strings
1149         if(!PyString_Check(seq)){
1150                 for(i = 0; i < size; i++){
1151                         item = PySequence_GetItem(seq, i); //*new*
1152                         if (!item) {
1153                                 Py_DECREF(seq);
1154                                 goto RuntimeError;
1155                         }
1156                         if(!PyString_Check(item)){
1157                                 EXPP_decr2(item, seq);
1158                                 goto AttributeError;
1159                         }
1160                         Py_DECREF(item);
1161                 }
1162         }
1163
1164         //GET ARMATURES
1165         if(size != 1){
1166                 dict = PyDict_New(); //*new*
1167                 if(!dict){
1168                         Py_DECREF(seq);
1169                         goto RuntimeError;
1170                 }
1171                 if(size == 0){  //GET ALL ARMATURES
1172                         data = G.main->armature.first; //get the first data ID from the armature library
1173                         while (data){
1174                                 py_armature = Armature_CreatePyObject(data); //*new*
1175                                 sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
1176                                 if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
1177                                         EXPP_decr3(seq, dict, py_armature);
1178                                         goto RuntimeError;
1179                                 }
1180                                 Py_DECREF(py_armature);
1181                                 data = ((ID*)data)->next;
1182                         }
1183                         Py_DECREF(seq);
1184                 }else{  //GET ARMATURE LIST
1185                         for (i = 0; i < size; i++) {
1186                                 item = PySequence_GetItem(seq, i); //*new*
1187                                 name = PyString_AsString(item);
1188                                 Py_DECREF(item);
1189                                 data = find_id("AR", name); //get data from library
1190                                 if (data != NULL){
1191                                         py_armature = Armature_CreatePyObject(data); //*new*
1192                                         if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
1193                                                 EXPP_decr3(seq, dict, py_armature);
1194                                                 goto RuntimeError;
1195                                         }
1196                                         Py_DECREF(py_armature);
1197                                 }else{
1198                                         if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
1199                                                 EXPP_decr2(seq, dict);
1200                                                 goto RuntimeError;
1201                                         }
1202                                         Py_DECREF(Py_None);
1203                                 }
1204                         }
1205                         Py_DECREF(seq);
1206                 }
1207                 return dict;
1208         }else{  //GET SINGLE ARMATURE
1209                 if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
1210                         item = PySequence_GetItem(seq, 0); //*new*
1211                         name = PyString_AsString(item);
1212                         Py_DECREF(item);
1213                 }else{
1214                         name = PyString_AsString(seq);
1215                 }
1216                 Py_DECREF(seq);
1217                 data = find_id("AR", name); //get data from library
1218                 if (data != NULL){
1219                         return Armature_CreatePyObject(data); //*new*
1220                 }else{
1221                         char buffer[128];
1222                         PyOS_snprintf( buffer, sizeof(buffer),
1223                                                    "Armature \"%s\" not found", name);
1224                         return EXPP_ReturnPyObjError( PyExc_ValueError,
1225                                                                                   buffer );
1226                 }
1227         }
1228
1229 RuntimeError:
1230         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1231                 sModuleError, "Get(): ", "Internal Error Ocurred");
1232
1233 AttributeError:
1234         return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
1235                 sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
1236 }
1237
1238
1239 //----------------Blender.Armature.New()
1240 static PyObject *M_Armature_New(PyObject * self, PyObject * args)
1241 {
1242         char *name = "Armature";
1243         struct bArmature *armature;
1244         BPy_Armature *obj;
1245
1246         if( !PyArg_ParseTuple( args, "|s", &name ) )
1247                 return EXPP_ReturnPyObjError( PyExc_TypeError,
1248                                               "expected nothing or a string as argument" );
1249
1250         armature= add_armature(name);
1251         armature->id.us = 0;
1252         obj = (BPy_Armature *)Armature_CreatePyObject(armature); /*new*/
1253
1254         if( !obj )
1255                 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
1256                                        "PyObject_New() failed" );       
1257
1258         obj->armature = armature;
1259         return (PyObject *)obj;
1260 }
1261
1262
1263 //-------------------MODULE METHODS DEFINITION-----------------------------
1264
1265 static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
1266   returns None if not found.\n If 'name' is not specified, it returns a list of all \
1267   armatures in the\ncurrent scene.";
1268
1269 static char M_Armature_New_doc[] = "(name) - return a new armature object.";
1270
1271 struct PyMethodDef M_Armature_methods[] = {
1272         {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
1273         {"New", M_Armature_New, METH_VARARGS, M_Armature_New_doc},
1274         {NULL, NULL, 0, NULL}
1275 };
1276 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1277 //------------------------Armature_RebuildEditbones (internal)
1278 PyObject * Armature_RebuildEditbones(PyObject *pyarmature)
1279 {
1280         return Armature_makeEditable((BPy_Armature*)pyarmature);
1281 }
1282
1283 //------------------------Armature_RebuildBones (internal)
1284 PyObject *Armature_RebuildBones(PyObject *pyarmature)
1285 {
1286         return Armature_update((BPy_Armature*)pyarmature);
1287 }
1288
1289 /* internal func to remove weakref from weakref list */
1290 PyObject * arm_weakref_callback_weakref_dealloc(PyObject *self, PyObject *weakref)
1291 {
1292         char *list_name = ARM_WEAKREF_LIST_NAME;
1293         PyObject *maindict = NULL, *armlist = NULL;
1294         int i;
1295         
1296         maindict= PyModule_GetDict(PyImport_AddModule(  "__main__"));
1297         armlist = PyDict_GetItemString(maindict, list_name);
1298         if( !armlist){
1299                 printf("Oops - update_armature_weakrefs()\n");
1300                 Py_RETURN_NONE;
1301         }
1302         
1303         i = PySequence_Index(armlist, weakref);
1304         if (i==-1) {
1305                 printf("callback weakref internal error, weakref not in list\n\tthis should never happen.\n");
1306                 Py_RETURN_NONE;
1307         }
1308         PySequence_DelItem(armlist, i);
1309         Py_RETURN_NONE;
1310 }
1311
1312 /*-----------------(internal)
1313  * Converts a bArmature to a PyArmature */
1314
1315 PyObject *Armature_CreatePyObject(struct bArmature *armature)
1316 {
1317         BPy_Armature *py_armature = NULL;
1318         PyObject *maindict = NULL, *weakref = NULL;
1319         PyObject *armlist = NULL;  /* list of armature weak refs */
1320         char *list_name = ARM_WEAKREF_LIST_NAME;
1321         int i;
1322
1323         //put a weakreference in __main__
1324         maindict= PyModule_GetDict(PyImport_AddModule(  "__main__"));
1325
1326         armlist = PyDict_GetItemString(maindict, list_name);
1327         if(!armlist) {
1328                 printf("Oops - can't get the armature weakref list\n");
1329                 goto RuntimeError;
1330         }
1331
1332         /* see if we alredy have it */
1333         for (i=0; i< PyList_Size(armlist); i++) { 
1334                 py_armature = (BPy_Armature *)PyWeakref_GetObject(PyList_GET_ITEM(armlist, i));
1335                 if (BPy_Armature_Check(py_armature) && py_armature->armature == armature) {
1336                         Py_INCREF(py_armature);
1337                         /*printf("reusing armature\n");*/
1338                         return (PyObject *)py_armature;
1339                 }
1340         }
1341
1342         
1343         /*create armature type*/
1344         py_armature = PyObject_NEW( BPy_Armature, &Armature_Type );
1345         
1346         if (!py_armature){
1347                 printf("Oops - can't create py armature\n");
1348                 goto RuntimeError;
1349         }
1350
1351         py_armature->armature = armature;
1352         py_armature->weaklist = NULL; //init the weaklist
1353         
1354         //create armature.bones
1355         py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
1356         if (!py_armature->Bones){
1357                 printf("Oops - creating armature.bones\n");
1358                 goto RuntimeError;
1359         }
1360         
1361         weakref = PyWeakref_NewRef((PyObject*)py_armature, arm_weakref_callback_weakref_dealloc__pyfunc);
1362         if (PyList_Append(armlist, weakref) == -1){
1363                 printf("Oops - list-append failed\n");
1364                 goto RuntimeError;
1365         }
1366         Py_DECREF(weakref);
1367
1368         return (PyObject *) py_armature;
1369
1370 RuntimeError:
1371         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1372                 sModuleError, "Armature_CreatePyObject: ", "Internal Error Ocurred");
1373 }
1374 //-----------------(internal)
1375 //Converts a PyArmature to a bArmature
1376 struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
1377 {
1378         return (py_armature->armature);
1379 }
1380
1381 struct bArmature *Armature_FromPyObject( PyObject * py_obj )
1382 {
1383         return PyArmature_AsArmature((BPy_Armature*)py_obj);
1384 }
1385
1386 /* internal use only */
1387 static PyMethodDef bpy_arm_weakref_callback_weakref_dealloc[] = {
1388         {"arm_weakref_callback_weakref_dealloc", arm_weakref_callback_weakref_dealloc, METH_O, ""}
1389 };
1390
1391 //-------------------MODULE INITIALIZATION--------------------------------
1392 PyObject *Armature_Init(void)
1393 {
1394         PyObject *module, *dict;
1395
1396         //Initializes TypeObject.ob_type
1397         if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
1398                 PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0) {
1399                 return EXPP_incr_ret(Py_None);
1400         }
1401
1402         /* Weakref management - used for callbacks so we can
1403          * tell when a callback has been removed that a UI button referenced */
1404         arm_weakref_callback_weakref_dealloc__pyfunc = PyCFunction_New(bpy_arm_weakref_callback_weakref_dealloc, NULL);
1405         
1406         
1407         //Register the module
1408         module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
1409                 "The Blender Armature module"); 
1410
1411         //Add TYPEOBJECTS to the module
1412         PyModule_AddObject(module, "Armature", 
1413                 EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
1414         PyModule_AddObject(module, "Bone", 
1415                 EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
1416         PyModule_AddObject(module, "Editbone", 
1417                 EXPP_incr_ret((PyObject *)&EditBone_Type)); //*steals*
1418
1419         //Add CONSTANTS to the module
1420         PyModule_AddObject(module, "CONNECTED", 
1421                 PyConstant_NewInt("CONNECTED", BONE_CONNECTED));
1422         PyModule_AddObject(module, "HINGE", 
1423                 PyConstant_NewInt("HINGE", BONE_HINGE));
1424         PyModule_AddObject(module, "NO_DEFORM", 
1425                 PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM));
1426         PyModule_AddObject(module, "MULTIPLY", 
1427                 PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV));
1428         PyModule_AddObject(module, "HIDDEN_EDIT", 
1429                 PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A));
1430         PyModule_AddObject(module, "ROOT_SELECTED", 
1431                 PyConstant_NewInt("ROOT_SELECTED", BONE_ROOTSEL));
1432         PyModule_AddObject(module, "BONE_SELECTED", 
1433                 PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED));
1434         PyModule_AddObject(module, "TIP_SELECTED", 
1435                 PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL));
1436
1437         PyModule_AddObject(module, "OCTAHEDRON", 
1438                 PyConstant_NewInt("OCTAHEDRON", ARM_OCTA));
1439         PyModule_AddObject(module, "STICK", 
1440                 PyConstant_NewInt("STICK", ARM_LINE));
1441         PyModule_AddObject(module, "BBONE", 
1442                 PyConstant_NewInt("BBONE", ARM_B_BONE));
1443         PyModule_AddObject(module, "ENVELOPE", 
1444                 PyConstant_NewInt("ENVELOPE", ARM_ENVELOPE));
1445
1446         //Add SUBMODULES to the module
1447         dict = PyModule_GetDict( module ); //borrowed
1448         PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
1449
1450         return module;
1451 }