Sunday merger of orange branch with bf-blender
[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 "Armature.h" //This must come first
30
31 #include "BKE_main.h"
32 #include "BKE_global.h"
33 #include "BKE_armature.h"
34 #include "BKE_library.h"
35 #include "BKE_depsgraph.h"
36 #include "BKE_utildefines.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_arithb.h"
39 #include "MEM_guardedalloc.h"
40 #include "Bone.h"
41 #include "NLA.h"
42 #include "gen_utils.h"
43
44 #include "DNA_object_types.h" //This must come before BIF_editarmature.h...
45 #include "BIF_editarmature.h"
46
47 //------------------UNDECLARED EXTERNAL PROTOTYPES--------------------
48 //These are evil 'extern' declarations for functions with no anywhere
49 extern void free_editArmature(void);
50 extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
51 extern void editbones_to_armature (ListBase *list, Object *ob, bArmature *armature);
52
53 //------------------------ERROR CODES---------------------------------
54 //This is here just to make me happy and to have more consistant error strings :)
55 static const char sBoneDictError[] = "ArmatureType.bones - Error: ";
56 static const char sBoneDictBadArgs[] = "ArmatureType.bones - Bad Arguments: ";
57 static const char sArmatureError[] = "ArmatureType - Error: ";
58 static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: ";
59 static const char sModuleError[] = "Blender.Armature - Error: ";
60 static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
61
62 //################## BonesDict_Type (internal) ########################
63 /*This is an internal psuedo-dictionary type that allows for manipulation
64 * of bones inside of an armature. It is a subobject of armature.
65 * i.e. Armature.bones['key']*/
66 //#####################################################################
67
68 //------------------METHOD IMPLEMENTATIONS-----------------------------
69 //------------------------Armature.bones.items()
70 //Returns a list of key:value pairs like dict.items()
71 PyObject* BonesDict_items(BPy_BonesDict *self)
72 {
73         if (self->editmode_flag){
74                 return PyDict_Items(self->editBoneDict); 
75         }else{
76                 return PyDict_Items(self->dict); 
77         }
78 }
79 //------------------------Armature.bones.keys()
80 //Returns a list of keys like dict.keys()
81 PyObject* BonesDict_keys(BPy_BonesDict *self)
82 {
83         if (self->editmode_flag){
84                 return PyDict_Keys(self->editBoneDict);
85         }else{
86                 return PyDict_Keys(self->dict);
87         }
88 }
89 //------------------------Armature.bones.values()
90 //Returns a list of values like dict.values()
91 PyObject* BonesDict_values(BPy_BonesDict *self)
92 {
93         if (self->editmode_flag){
94                 return PyDict_Values(self->editBoneDict);
95         }else{
96                 return PyDict_Values(self->dict);
97         }
98 }
99 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
100 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
101 //------------------------tp_doc
102 //The __doc__ string for this object
103 static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\
104 designed to act as a Py_Bone dictionary.";
105
106 //------------------------tp_methods
107 //This contains a list of all methods the object contains
108 static PyMethodDef BPy_BonesDict_methods[] = {
109         {"items", (PyCFunction) BonesDict_items, METH_NOARGS, 
110                 "() - Returns the key:value pairs from the dictionary"},
111         {"keys", (PyCFunction) BonesDict_keys, METH_NOARGS, 
112                 "() - Returns the keys the dictionary"},
113         {"values", (PyCFunction) BonesDict_values, METH_NOARGS, 
114                 "() - Returns the values from the dictionary"},
115         {NULL}
116 };
117
118 //------------------------tp_new
119 //This methods creates a new object (note it does not initialize it - only the building)
120 static PyObject *BonesDict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
121 {
122         BPy_BonesDict *py_BonesDict = NULL;
123
124         py_BonesDict = (BPy_BonesDict*)type->tp_alloc(type, 0); 
125         if (!py_BonesDict)
126                 goto RuntimeError;
127
128         py_BonesDict->dict = PyDict_New();
129         if(!py_BonesDict->dict)
130                 goto RuntimeError;
131
132         py_BonesDict->editBoneDict = PyDict_New();
133         if (py_BonesDict->editBoneDict == NULL)
134                 goto RuntimeError;
135
136         py_BonesDict->editmode_flag = 0;
137
138         return (PyObject*)py_BonesDict;
139
140 RuntimeError:
141         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
142                 sBoneDictError, "Failed to create dictionary!");
143 }
144 //------------------------tp_repr
145 //This is the string representation of the object
146 static PyObject *BonesDict_repr(BPy_BonesDict *self)
147 {
148         char buffer[128], str[4096];
149         PyObject *key, *value;
150         int pos = 0;
151
152         BLI_strncpy(str,"",4096);
153         sprintf(buffer, "[Bone Dict: {");
154         strcat(str,buffer);
155         if (self->editmode_flag){
156                 while (PyDict_Next(self->editBoneDict, &pos, &key, &value)) {
157                         sprintf(buffer, "%s : %s, ", PyString_AsString(key), 
158                                 PyString_AsString(value->ob_type->tp_repr(value)));
159                         strcat(str,buffer);
160                 }
161         }else{
162                 while (PyDict_Next(self->dict, &pos, &key, &value)) {
163                         sprintf(buffer, "%s : %s, ", PyString_AsString(key), 
164                                 PyString_AsString(value->ob_type->tp_repr(value)));
165                         strcat(str,buffer);
166                 }
167         }
168         sprintf(buffer, "}]\n");
169         strcat(str,buffer);
170         return PyString_FromString(str);
171 }
172
173 //------------------------tp_dealloc
174 //This tells how to 'tear-down' our object when ref count hits 0
175 static void BonesDict_dealloc(BPy_BonesDict * self)
176 {
177         Py_DECREF(self->dict);
178         Py_DECREF(self->editBoneDict);
179         ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
180         return;
181 }
182 //------------------------mp_length
183 //This gets the size of the dictionary
184 int BonesDict_len(BPy_BonesDict *self)
185 {
186         if (self->editmode_flag){
187                 return PyDict_Size(self->editBoneDict);
188         }else{
189                 return PyDict_Size(self->dict);
190         }
191 }
192 //-----------------------mp_subscript
193 //This defines getting a bone from the dictionary - x = Bones['key']
194 PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
195
196         PyObject *value = NULL;
197
198         if (self->editmode_flag){
199                 value = PyDict_GetItem(self->editBoneDict, key);
200         }else{
201                 value = PyDict_GetItem(self->dict, key);
202         }
203         if(value == NULL){
204         return EXPP_incr_ret(Py_None);
205         }
206         return EXPP_incr_ret(value);
207 }
208 //-----------------------mp_ass_subscript
209 //This does dict assignment - Bones['key'] = value
210 int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
211 {
212         char *key_str = "", *name = "", *misc = "";
213         static char *kwlist[] = {"name", "misc", NULL};
214
215         //Get the key name
216         if(key && PyString_Check(key)){
217                 key_str = PyString_AsString(key);
218         }else{
219                 goto AttributeError;
220         }
221
222         //Parse the value for assignment
223         if(value && PyDict_Check(value)){
224                 if(!PyArg_ParseTupleAndKeywords(Py_BuildValue("()"), value, "|ss", kwlist, &name, &misc)){
225                         goto AttributeError;
226                 }
227         }else{
228                 goto AttributeError;
229         }
230         return 0;
231
232 AttributeError:
233         return EXPP_intError(PyExc_AttributeError, "%s%s", 
234                 sBoneDictBadArgs,  "Expects (optional) name='string', misc='string'");
235 }
236 //------------------TYPE_OBECT DEFINITION--------------------------
237 //Mapping Protocol
238 static PyMappingMethods BonesDict_MapMethods = {
239         (inquiry) BonesDict_len,                                        //mp_length
240         (binaryfunc)BonesDict_GetItem,          //mp_subscript
241         (objobjargproc)BonesDict_SetItem,       //mp_ass_subscript
242 };
243 //BonesDict TypeObject
244 PyTypeObject BonesDict_Type = {
245         PyObject_HEAD_INIT(NULL)                //tp_head
246         0,                                                                                              //tp_internal
247         "BonesDict",                                                            //tp_name
248         sizeof(BPy_BonesDict),                          //tp_basicsize
249         0,                                                                                              //tp_itemsize
250         (destructor)BonesDict_dealloc,  //tp_dealloc
251         0,                                                                                              //tp_print
252         0,                                                                                              //tp_getattr
253         0,                                                                                              //tp_setattr
254         0,                                                                                              //tp_compare
255         (reprfunc) BonesDict_repr,                      //tp_repr
256         0,                                                                                              //tp_as_number
257         0,                                                                                              //tp_as_sequence
258         &BonesDict_MapMethods,                  //tp_as_mapping
259         0,                                                                                              //tp_hash
260         0,                                                                                              //tp_call
261         0,                                                                                              //tp_str
262         0,                                                                                              //tp_getattro
263         0,                                                                                              //tp_setattro
264         0,                                                                                              //tp_as_buffer
265         Py_TPFLAGS_DEFAULT,                     //tp_flags
266         BPy_BonesDict_doc,                                      //tp_doc
267         0,                                                                                              //tp_traverse
268         0,                                                                                              //tp_clear
269         0,                                                                                              //tp_richcompare
270         0,                                                                                              //tp_weaklistoffset
271         0,                                                                                              //tp_iter
272         0,                                                                                              //tp_iternext
273         BPy_BonesDict_methods,                  //tp_methods
274         0,                                                                                              //tp_members
275         0,                                                                                              //tp_getset
276         0,                                                                                              //tp_base
277         0,                                                                                              //tp_dict
278         0,                                                                                              //tp_descr_get
279         0,                                                                                              //tp_descr_set
280         0,                                                                                              //tp_dictoffset
281         0,                                                                                              //tp_init
282         0,                                                                                              //tp_alloc
283         (newfunc)BonesDict_new,                 //tp_new
284         0,                                                                                              //tp_free
285         0,                                                                                              //tp_is_gc
286         0,                                                                                              //tp_bases
287         0,                                                                                              //tp_mro
288         0,                                                                                              //tp_cache
289         0,                                                                                              //tp_subclasses
290         0,                                                                                              //tp_weaklist
291         0                                                                                               //tp_del
292 };
293 //-----------------(internal)
294 static int BonesDict_Init(PyObject *dictionary, ListBase *bones){
295         Bone *bone = NULL;
296         PyObject *py_bone = NULL;
297
298         for (bone = bones->first; bone; bone = bone->next){
299                 py_bone = PyBone_FromBone(bone);
300                 if (py_bone == NULL)
301                         return -1;
302
303                 if(PyDict_SetItem(dictionary, PyString_FromString(bone->name), py_bone) == -1){
304                         goto RuntimeError;
305                 }
306                 if (bone->childbase.first) 
307                         BonesDict_Init(dictionary, &bone->childbase);
308         }
309         return 0;
310
311 RuntimeError:
312         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
313                 sBoneDictError, "Internal error trying to wrap blender bones!");
314 }
315
316 //######################### Armature_Type #############################
317 /*This type represents a thin wrapper around bArmature data types
318 * internal to blender. It contains the psuedo-dictionary BonesDict
319 * as an assistant in manipulating it's own bone collection*/
320 //#####################################################################
321
322 //------------------METHOD IMPLEMENTATION------------------------------
323 //This is a help function for Armature_makeEditable
324 static int PyArmature_InitEditBoneDict(PyObject *dictionary, ListBase *branch)
325 {
326         struct Bone *bone = NULL;
327         PyObject *args, *py_editBone = NULL, *py_bone = NULL;
328
329         for (bone = branch->first; bone; bone = bone->next){
330
331                 //create a new editbone based on the bone data
332                 py_bone = PyBone_FromBone(bone); //new
333                 if (py_bone == NULL)
334                         goto RuntimeError;
335
336                 args = Py_BuildValue("(O)",py_bone); //new
337
338                 py_editBone = EditBone_Type.tp_new(&EditBone_Type, args, NULL); //new
339                 if (py_editBone == NULL) 
340                         goto RuntimeError;
341
342                 //add the new editbone to the dictionary
343                 if (PyDict_SetItemString(dictionary, bone->name, py_editBone) == -1) 
344                         goto RuntimeError;
345
346                 if(bone->childbase.first){
347                         PyArmature_InitEditBoneDict(dictionary, &bone->childbase);
348                 }
349         }
350         return 0;
351
352 RuntimeError:
353         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
354                 sArmatureError, "Internal error trying to construct an edit armature!");
355
356 }
357 //------------------------Armature.makeEditable()
358 static PyObject *Armature_makeEditable(BPy_Armature *self)
359 {
360         if (PyArmature_InitEditBoneDict(((BPy_BonesDict*)self->Bones)->editBoneDict, 
361                 &self->armature->bonebase) == -1){
362                 return NULL;    //error already set
363         }
364         ((BPy_BonesDict*)self->Bones)->editmode_flag = 1;
365         return EXPP_incr_ret(Py_None);
366 }
367
368 static void PyArmature_FixRolls(ListBase *branch, PyObject *dictionary)
369 {
370         float premat[3][3],postmat[3][3];
371         float difmat[3][3],imat[3][3], delta[3];
372         BPy_EditBone *py_editBone = NULL;
373         struct Bone *bone = NULL;
374         int keyCheck = -1;
375
376         for (bone = branch->first; bone; bone = bone->next){
377
378                 where_is_armature_bone(bone, bone->parent);     //set bone_mat, arm_mat, length, etc.
379
380                 keyCheck = PySequence_Contains(dictionary, PyString_FromString(bone->name));
381                 if (keyCheck == 1){
382
383                         py_editBone = (BPy_EditBone*)PyDict_GetItem(dictionary, 
384                                 PyString_FromString(bone->name)); //borrowed
385                         VecSubf (delta, py_editBone->tail, py_editBone->head);
386                         vec_roll_to_mat3(delta, py_editBone->roll, premat); //pre-matrix
387                         Mat3CpyMat4(postmat, bone->arm_mat); //post-matrix
388                         Mat3Inv(imat, premat);
389                         Mat3MulMat3(difmat, imat, postmat);
390
391                         bone->roll = (float)-atan(difmat[2][0]/difmat[2][2]); //YEA!!
392                         if (difmat[0][0]<0.0){
393                                 bone->roll += (float)M_PI;
394                         }
395
396                         where_is_armature_bone(bone, bone->parent); //gotta do it again...
397                 }else if (keyCheck == 0){
398                         //oops we couldn't find it
399                 }else{
400                         //error
401                 }
402                 PyArmature_FixRolls (&bone->childbase, dictionary);
403         }
404 }
405 //------------------------(internal)EditBoneDict_CheckForKey
406 static BPy_EditBone *EditBoneDict_CheckForKey(BPy_BonesDict *dictionary, char *name)
407 {
408         BPy_EditBone *editbone; 
409         PyObject *value, *key;
410         int pos = 0;
411
412         while (PyDict_Next(dictionary->editBoneDict, &pos, &key, &value)) {
413                 editbone = (BPy_EditBone *)value;
414                 if (STREQ(editbone->name, name)){
415                         Py_INCREF(editbone);
416                         return editbone;
417                 }
418         }
419         return NULL;
420 }
421 //------------------------Armature.saveChanges()
422 static PyObject *Armature_saveChanges(BPy_Armature *self)
423 {
424         float M_boneRest[3][3], M_parentRest[3][3];
425         float iM_parentRest[3][3], delta[3];
426         BPy_EditBone *parent = NULL, *editbone = NULL;
427         struct Bone *bone = NULL;
428         struct Object *obj = NULL;
429         PyObject *key, *value;
430         int pos = 0;
431
432         //empty armature of old bones
433         free_bones(self->armature);
434
435         //create a new set based on the editbones
436         while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, &pos, &key, &value)) {
437
438                 editbone = (BPy_EditBone*)value;
439                 bone = MEM_callocN (sizeof(Bone), "bone");      
440                 editbone->temp = bone;  //save temp pointer
441
442                 strcpy (bone->name, editbone->name);
443                 memcpy (bone->head, editbone->head, sizeof(float)*3);
444                 memcpy (bone->tail, editbone->tail, sizeof(float)*3);
445                 bone->flag= editbone->flag;
446                 bone->roll = 0.0f; //is fixed later
447                 bone->weight = editbone->weight;
448                 bone->dist = editbone->dist;
449                 bone->xwidth = editbone->xwidth;
450                 bone->zwidth = editbone->zwidth;
451                 bone->ease1= editbone->ease1;
452                 bone->ease2= editbone->ease2;
453                 bone->rad_head= editbone->rad_head;
454                 bone->rad_tail= editbone->rad_tail;
455                 bone->segments= editbone->segments;
456         }
457
458         pos = 0;
459         //place bones in their correct heirarchy
460         while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, 
461                 &pos, &key, &value)) {
462
463                 editbone = (BPy_EditBone*)value;
464                 bone = editbone->temp; //get bone pointer
465
466                 if (!STREQ(editbone->parent, "")){
467                         parent = EditBoneDict_CheckForKey((BPy_BonesDict*)self->Bones, editbone->parent);
468                         if(parent != NULL){
469
470                                 //parent found in dictionary
471                                 bone->parent = parent->temp;
472                                 BLI_addtail (&parent->temp->childbase, bone);
473                                 //Parenting calculations 
474                                 VecSubf (delta, parent->tail, parent->head);
475                                 vec_roll_to_mat3(delta, parent->roll, M_parentRest); //M_parentRest = parent matrix
476                                 VecSubf (delta, editbone->tail, editbone->head);
477                                 vec_roll_to_mat3(delta, editbone->roll, M_boneRest);  //M_boneRest = bone matrix
478                                 Mat3Inv(iM_parentRest, M_parentRest); //iM_parentRest = 1/parent matrix
479                                 //get head/tail
480                                 VecSubf (bone->head, editbone->head, parent->tail);
481                                 VecSubf (bone->tail, editbone->tail, parent->tail);
482                                 //put them in parentspace
483                                 Mat3MulVecfl(iM_parentRest, bone->head);
484                                 Mat3MulVecfl(iM_parentRest, bone->tail);
485
486                                 Py_DECREF(parent);
487                         }else{
488                                 //was not found - most likely parent was deleted
489                                 parent = NULL;
490                                 BLI_addtail (&self->armature->bonebase, bone);
491                         }
492                 }else{
493                         BLI_addtail (&self->armature->bonebase, bone);
494                 }
495         }
496         //fix rolls and generate matrices
497         PyArmature_FixRolls(&self->armature->bonebase, 
498                 ((BPy_BonesDict*)self->Bones)->editBoneDict);
499
500         //update linked objects
501         for(obj = G.main->object.first; obj; obj = obj->id.next) {
502                 if(obj->data == self->armature){
503                         armature_rebuild_pose(obj, self->armature);
504                 }
505         }
506         DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
507
508         //clear the editbone dictionary and set edit flag
509         PyDict_Clear(((BPy_BonesDict*)self->Bones)->editBoneDict);
510         ((BPy_BonesDict*)self->Bones)->editmode_flag = 0;
511
512         //rebuild py_bones
513         PyDict_Clear(((BPy_BonesDict*)self->Bones)->dict);
514         if (BonesDict_Init(((BPy_BonesDict*)self->Bones)->dict, 
515                 &self->armature->bonebase) == -1)
516                 return NULL; //error string already set
517
518         return EXPP_incr_ret(Py_None);
519 }
520 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
521 //------------------------Armature.autoIK (getter)
522 static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
523 {
524         if (self->armature->flag & ARM_AUTO_IK)
525                 return EXPP_incr_ret(Py_True);
526         else
527                 return EXPP_incr_ret(Py_False);
528 }
529 //------------------------Armature.autoIK (setter)
530 static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
531 {
532         if(value){
533                 if(PyBool_Check(value)){
534                         if (value == Py_True){
535                                 self->armature->flag |= ARM_AUTO_IK;
536                                 return 0;
537                         }else if (value == Py_False){
538                                 self->armature->flag &= ~ARM_AUTO_IK;
539                                 return 0;
540                         }
541                 }
542         }
543         goto AttributeError;
544
545 AttributeError:
546         return EXPP_intError(PyExc_AttributeError, "%s%s", 
547                 sArmatureBadArgs, "Expects True or False");
548 }
549 //------------------------Armature.layers (getter)
550 static PyObject *Armature_getLayers(BPy_Armature *self, void *closure)
551 {
552         int layers, bit = 0, val = 0;
553         PyObject *item = NULL, *laylist = PyList_New( 0 );
554
555         if( !laylist )
556                 return EXPP_ReturnPyObjError( PyExc_MemoryError,
557                         "couldn't create pylist!" );
558
559         layers = self->armature->layer;
560
561         while( bit < 20 ) {
562                 val = 1 << bit;
563                 if( layers & val ) {
564                         item = Py_BuildValue( "i", bit + 1 );
565                         PyList_Append( laylist, item );
566                         Py_DECREF( item );
567                 }
568                 bit++;
569         }
570         return laylist;
571 }
572 //------------------------Armature.layer (setter)
573 static int Armature_setLayers(BPy_Armature *self, PyObject *value, void *closure)
574 {
575         if(value){
576                 if(PyList_Check(value)){
577                         int layers = 0, len_list = 0;
578                         int val;
579                         PyObject *item = NULL;
580
581                         len_list = PyList_Size(value);
582
583                         if( len_list == 0 )
584                                 return EXPP_ReturnIntError( PyExc_AttributeError,
585                                   "list can't be empty, at least one layer must be set" );
586
587                         while( len_list ) {
588                                 --len_list;
589                                 item = PyList_GetItem( value, len_list );
590                                 if( !PyInt_Check( item ) )
591                                         return EXPP_ReturnIntError( PyExc_AttributeError,
592                                                         "list must contain only integer numbers" );
593
594                                 val = ( int ) PyInt_AsLong( item );
595                                 if( val < 1 || val > 20 )
596                                         return EXPP_ReturnIntError( PyExc_AttributeError,
597                                                   "layer values must be in the range [1, 20]" );
598
599                                 layers |= 1 << ( val - 1 );
600                         }
601
602                         /* update any bases pointing to our object */
603                         self->armature->layer = layers;
604
605                         return 0;
606                 }
607         }
608         goto AttributeError;
609
610 AttributeError:
611         return EXPP_ReturnIntError( PyExc_TypeError,
612                         "expected a list of integers" );
613 }
614 //------------------------Armature.mirrorEdit (getter)
615 static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
616 {
617         if (self->armature->flag & ARM_MIRROR_EDIT)
618                 return EXPP_incr_ret(Py_True);
619         else
620                 return EXPP_incr_ret(Py_False);
621 }
622 //------------------------Armature.mirrorEdit (setter)
623 static int Armature_setMirrorEdit(BPy_Armature *self, PyObject *value, void *closure)
624 {
625         if(value){
626                 if(PyBool_Check(value)){
627                         if (value == Py_True){
628                                 self->armature->flag |= ARM_MIRROR_EDIT;
629                                 return 0;
630                         }else if (value == Py_False){
631                                 self->armature->flag &= ~ARM_MIRROR_EDIT;
632                                 return 0;
633                         }
634                 }
635         }
636         goto AttributeError;
637
638 AttributeError:
639         return EXPP_intError(PyExc_AttributeError, "%s%s", 
640                 sArmatureBadArgs, "Expects True or False");
641 }
642 //------------------------Armature.drawType (getter)
643 static PyObject *Armature_getDrawType(BPy_Armature *self, void *closure)
644 {
645         if (self->armature->drawtype == ARM_OCTA){
646                 return EXPP_GetModuleConstant("Blender.Armature", "OCTAHEDRON") ;
647         }else if (self->armature->drawtype == ARM_LINE){
648                 return EXPP_GetModuleConstant("Blender.Armature", "STICK") ;
649         }else if (self->armature->drawtype == ARM_B_BONE){
650                 return EXPP_GetModuleConstant("Blender.Armature", "BBONE") ;
651         }else if (self->armature->drawtype == ARM_ENVELOPE){
652                 return EXPP_GetModuleConstant("Blender.Armature", "ENVELOPE") ;
653         }else{
654                 goto RuntimeError;
655         }
656
657 RuntimeError:
658         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
659                 sArmatureError, "drawType: ", "Internal failure!");
660 }
661 //------------------------Armature.drawType (setter)
662 static int Armature_setDrawType(BPy_Armature *self, PyObject *value, void *closure)
663 {
664         PyObject *val = NULL, *name = NULL;
665         long numeric_value;
666
667         if(value){
668                 if(BPy_Constant_Check(value)){
669                         name = PyDict_GetItemString(((BPy_constant*)value)->dict, "name");
670                         if (!STREQ2(PyString_AsString(name), "OCTAHEDRON", "STICK") &&
671                                 !STREQ2(PyString_AsString(name), "BBONE", "ENVELOPE"))
672                                 goto ValueError;
673                         val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
674                         if (PyInt_Check(val)){
675                                 numeric_value = PyInt_AS_LONG(val);
676                                 self->armature->drawtype = (int)numeric_value;
677                                 return 0;
678                         }
679                 }
680         }
681         goto AttributeError;
682
683 AttributeError:
684         return EXPP_intError(PyExc_AttributeError, "%s%s", 
685                 sArmatureBadArgs, "Expects module constant");
686
687 ValueError:
688         return EXPP_intError(PyExc_AttributeError, "%s%s", 
689                 sArmatureBadArgs, "Argument must be the constant OCTAHEDRON, STICK, BBONE, or ENVELOPE");
690 }
691 //------------------------Armature.ghostStep (getter)
692 static PyObject *Armature_getStep(BPy_Armature *self, void *closure)
693 {
694         return PyInt_FromLong((long)self->armature->ghostsize);
695 }
696 //------------------------Armature.ghostStep (setter)
697 static int Armature_setStep(BPy_Armature *self, PyObject *value, void *closure)
698 {
699         long numerical_value;
700
701         if(value){
702                 if(PyInt_Check(value)){
703                         numerical_value = PyInt_AS_LONG(value);
704                         if (numerical_value > 20.0f || numerical_value < 1.0f)
705                                 goto ValueError;
706                         self->armature->ghostsize = (short)numerical_value;
707                         return 0;
708                 }
709         }
710         goto AttributeError;
711
712 AttributeError:
713         return EXPP_intError(PyExc_AttributeError, "%s%s", 
714                 sArmatureBadArgs, "Expects Integer");
715
716 ValueError:
717         return EXPP_intError(PyExc_AttributeError, "%s%s", 
718                 sArmatureBadArgs, "Argument must fall within 1-20");
719 }
720 //------------------------Armature.ghost (getter)
721 static PyObject *Armature_getGhost(BPy_Armature *self, void *closure)
722 {
723         return PyInt_FromLong((long)self->armature->ghostep);
724 }
725 //------------------------Armature.ghost (setter)
726 static int Armature_setGhost(BPy_Armature *self, PyObject *value, void *closure)
727 {
728         long numerical_value;
729
730         if(value){
731                 if(PyInt_Check(value)){
732                         numerical_value = PyInt_AS_LONG(value);
733                         if (numerical_value > 30.0f || numerical_value < 0.0f)
734                                 goto ValueError;
735                         self->armature->ghostep = (short)numerical_value;
736                         return 0;
737                 }
738         }
739         goto AttributeError;
740
741 AttributeError:
742         return EXPP_intError(PyExc_AttributeError, "%s%s", 
743                 sArmatureBadArgs, "Expects Integer");
744
745 ValueError:
746         return EXPP_intError(PyExc_AttributeError, "%s%s", 
747                 sArmatureBadArgs, "Argument must fall within 0-30");
748 }
749 //------------------------Armature.drawNames (getter)
750 static PyObject *Armature_getDrawNames(BPy_Armature *self, void *closure)
751 {
752         if (self->armature->flag & ARM_DRAWNAMES)
753                 return EXPP_incr_ret(Py_True);
754         else
755                 return EXPP_incr_ret(Py_False);
756 }
757 //------------------------Armature.drawNames (setter)
758 static int Armature_setDrawNames(BPy_Armature *self, PyObject *value, void *closure)
759 {
760         if(value){
761                 if(PyBool_Check(value)){
762                         if (value == Py_True){
763                                 self->armature->flag |= ARM_DRAWNAMES;
764                                 return 0;
765                         }else if (value == Py_False){
766                                 self->armature->flag &= ~ARM_DRAWNAMES;
767                                 return 0;
768                         }
769                 }
770         }
771         goto AttributeError;
772
773 AttributeError:
774         return EXPP_intError(PyExc_AttributeError, "%s%s", 
775                 sArmatureBadArgs, "Expects True or False");
776 }
777 //------------------------Armature.drawAxes (getter)
778 static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
779 {
780         if (self->armature->flag & ARM_DRAWAXES)
781                 return EXPP_incr_ret(Py_True);
782         else
783                 return EXPP_incr_ret(Py_False);
784 }
785 //------------------------Armature.drawAxes (setter)
786 static int Armature_setDrawAxes(BPy_Armature *self, PyObject *value, void *closure)
787 {
788         if(value){
789                 if(PyBool_Check(value)){
790                         if (value == Py_True){
791                                 self->armature->flag |= ARM_DRAWAXES;
792                                 return 0;
793                         }else if (value == Py_False){
794                                 self->armature->flag &= ~ARM_DRAWAXES;
795                                 return 0;
796                         }
797                 }
798         }
799         goto AttributeError;
800
801 AttributeError:
802         return EXPP_intError(PyExc_AttributeError, "%s%s", 
803                 sArmatureBadArgs, "Expects True or False");
804 }
805 //------------------------Armature.delayDeform (getter)
806 static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
807 {
808         if (self->armature->flag & ARM_DELAYDEFORM)
809                 return EXPP_incr_ret(Py_True);
810         else
811                 return EXPP_incr_ret(Py_False);
812 }
813 //------------------------Armature.delayDeform (setter)
814 static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
815 {
816         if(value){
817                 if(PyBool_Check(value)){
818                         if (value == Py_True){
819                                 self->armature->flag |= ARM_DELAYDEFORM;
820                                 return 0;
821                         }else if (value == Py_False){
822                                 self->armature->flag &= ~ARM_DELAYDEFORM;
823                                 return 0;
824                         }
825                 }
826         }
827         goto AttributeError;
828
829 AttributeError:
830         return EXPP_intError(PyExc_AttributeError, "%s%s", 
831                 sArmatureBadArgs, "Expects True or False");
832 }
833 //------------------------Armature.restPosition (getter)
834 static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
835 {
836         if (self->armature->flag & ARM_RESTPOS)
837                 return EXPP_incr_ret(Py_True);
838         else
839                 return EXPP_incr_ret(Py_False);
840 }
841 //------------------------Armature.restPosition (setter)
842 static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
843 {
844         if(value){
845                 if(PyBool_Check(value)){
846                         if (value == Py_True){
847                                 self->armature->flag |= ARM_RESTPOS;
848                                 return 0;
849                         }else if (value == Py_False){
850                                 self->armature->flag &= ~ARM_RESTPOS;
851                                 return 0;
852                         }
853                 }
854         }
855         goto AttributeError;
856
857 AttributeError:
858         return EXPP_intError(PyExc_AttributeError, "%s%s", 
859                 sArmatureBadArgs, "Expects True or False");
860 }
861 //------------------------Armature.envelopes (getter)
862 static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
863 {
864         if (self->armature->deformflag & ARM_DEF_ENVELOPE)
865                 return EXPP_incr_ret(Py_True);
866         else
867                 return EXPP_incr_ret(Py_False);
868 }
869 //------------------------Armature.envelopes (setter)
870 static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
871 {
872         if(value){
873                 if(PyBool_Check(value)){
874                         if (value == Py_True){
875                                 self->armature->deformflag |= ARM_DEF_ENVELOPE;
876                                 return 0;
877                         }else if (value == Py_False){
878                                 self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
879                                 return 0;
880                         }
881                 }
882         }
883         goto AttributeError;
884
885 AttributeError:
886         return EXPP_intError(PyExc_AttributeError, "%s%s", 
887                 sArmatureBadArgs, "Expects True or False");
888 }
889 //------------------------Armature.vertexGroups (getter)
890 static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
891 {
892         if (self->armature->deformflag & ARM_DEF_VGROUP)
893                 return EXPP_incr_ret(Py_True);
894         else
895                 return EXPP_incr_ret(Py_False);
896 }
897 //------------------------Armature.vertexGroups (setter)
898 static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
899 {
900         if(value){
901                 if(PyBool_Check(value)){
902                         if (value == Py_True){
903                                 self->armature->deformflag |= ARM_DEF_VGROUP;
904                                 return 0;
905                         }else if (value == Py_False){
906                                 self->armature->deformflag &= ~ARM_DEF_VGROUP;
907                                 return 0;
908                         }
909                 }
910         }
911         goto AttributeError;
912
913 AttributeError:
914         return EXPP_intError(PyExc_AttributeError, "%s%s", 
915                 sArmatureBadArgs, "Expects True or False");
916 }
917 //------------------------Armature.name (getter)
918 //Gets the name of the armature
919 static PyObject *Armature_getName(BPy_Armature *self, void *closure)
920 {
921     return PyString_FromString(self->armature->id.name +2); //*new*
922 }
923 //------------------------Armature.name (setter)
924 //Sets the name of the armature
925 static int Armature_setName(BPy_Armature *self, PyObject *value, void *closure)
926 {
927         char buffer[24];
928         char *name = "";
929
930         if(value){
931                 if(PyString_Check(value)){
932                         name = PyString_AsString(value);
933                         PyOS_snprintf(buffer, sizeof(buffer), "%s", name);
934                         rename_id(&self->armature->id, buffer);
935                         return 0; 
936                 }
937         }
938         goto AttributeError;
939
940 AttributeError:
941         return EXPP_intError(PyExc_AttributeError, "%s%s", 
942                 sArmatureBadArgs, "Expects string");
943 }
944 //------------------------Armature.bones (getter)
945 //Gets the name of the armature
946 static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
947 {
948     return EXPP_incr_ret(self->Bones);
949 }
950 //------------------------Armature.bones (setter)
951 //Sets the name of the armature
952 /*TODO*/
953 /*Copy Bones through x = y*/
954 static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
955 {
956         goto AttributeError;
957
958 AttributeError:
959         return EXPP_intError(PyExc_AttributeError, "%s%s", 
960                 sArmatureError, "You are not allowed to change the .Bones attribute");
961 }
962 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
963 //------------------------tp_doc
964 //The __doc__ string for this object
965 static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
966
967 //------------------------tp_methods
968 //This contains a list of all methods the object contains
969 static PyMethodDef BPy_Armature_methods[] = {
970         {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
971                 "() - Unlocks the ability to modify armature bones"},
972         {"saveChanges", (PyCFunction) Armature_saveChanges, METH_NOARGS, 
973                 "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
974         {NULL}
975 };
976
977 //------------------------tp_getset
978 //This contains methods for attributes that require checking
979 static PyGetSetDef BPy_Armature_getset[] = {
980         {"name", (getter)Armature_getName, (setter)Armature_setName, 
981                 "The armature's name", NULL},
982         {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
983                 "The armature's Bone dictionary", NULL},
984         {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
985                 "Enable/Disable vertex group defined deformation", NULL},
986         {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
987                 "Enable/Disable bone envelope defined deformation", NULL},
988         {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
989                 "Show armature rest position - disables posing", NULL},
990         {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
991                 "Don't deform children when manipulating bones in pose mode", NULL},
992         {"drawAxes", (getter)Armature_getDrawAxes, (setter)Armature_setDrawAxes, 
993                 "Enable/Disable  drawing  the bone axes", NULL},
994         {"drawNames", (getter)Armature_getDrawNames, (setter)Armature_setDrawNames, 
995                 "Enable/Disable  drawing the bone names", NULL},
996         {"ghost", (getter)Armature_getGhost, (setter)Armature_setGhost, 
997                 "Draw a number of ghosts around the current frame for current Action", NULL},
998         {"ghostStep", (getter)Armature_getStep, (setter)Armature_setStep, 
999                 "The number of frames between ghost instances", NULL},
1000         {"drawType", (getter)Armature_getDrawType, (setter)Armature_setDrawType, 
1001                 "The type of drawing currently applied to the armature", NULL},
1002         {"mirrorEdit", (getter)Armature_getMirrorEdit, (setter)Armature_setMirrorEdit, 
1003                 "Enable/Disable X-axis mirrored editing", NULL},
1004         {"autoIK", (getter)Armature_getAutoIK, (setter)Armature_setAutoIK, 
1005                 "Adds temporal IK chains while grabbing bones", NULL},
1006         {"layers", (getter)Armature_getLayers, (setter)Armature_setLayers, 
1007                 "List of layers for the armature", NULL},
1008         {NULL}
1009 };
1010 //------------------------tp_new
1011 //This methods creates a new object (note it does not initialize it - only the building)
1012 //This can be called through python by myObject.__new__() however, tp_init is not called
1013 static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1014 {
1015         BPy_Armature *py_armature = NULL;
1016         bArmature *bl_armature;
1017         int success;
1018
1019         bl_armature = add_armature();
1020         if(bl_armature) {
1021                 bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
1022
1023                 py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
1024                 if (py_armature == NULL)
1025                         goto RuntimeError;
1026
1027                 py_armature->armature = bl_armature;
1028
1029                 py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL);
1030                 if (py_armature->Bones == NULL)
1031                         goto RuntimeError;
1032
1033                 success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &bl_armature->bonebase);
1034                 if (success == -1)
1035                         return NULL; //error string already set
1036         } else {
1037                 goto RuntimeError;
1038         }
1039         return (PyObject*)py_armature; 
1040
1041 RuntimeError:
1042         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1043                 sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
1044 }
1045 //------------------------tp_init
1046 //This methods does initialization of the new object
1047 //This method will get called in python by 'myObject(argument, keyword=value)'
1048 //tp_new will be automatically called before this
1049 static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
1050 {
1051         char buf[21];
1052         char *name = "myArmature";
1053         static char *kwlist[] = {"name", NULL};
1054
1055         if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
1056                 goto AttributeError;
1057         }
1058
1059         //rename the armature if a name is supplied
1060         if(!BLI_streq(name, "myArmature")){
1061                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
1062                 rename_id(&self->armature->id, buf);
1063         }
1064
1065         return 0;
1066
1067 AttributeError:
1068         return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
1069                 sArmatureBadArgs, " __init__: ", "Expects string(name)");
1070 }
1071 //------------------------tp_richcompare
1072 //This method allows the object to use comparison operators
1073 //TODO: We need some armature comparisons
1074 static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op)
1075 {
1076         return EXPP_incr_ret(Py_None);
1077 }
1078
1079 //------------------------tp_repr
1080 //This is the string representation of the object
1081 static PyObject *Armature_repr(BPy_Armature *self)
1082 {
1083         return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
1084 }
1085
1086 //------------------------tp_dealloc
1087 //This tells how to 'tear-down' our object when ref count hits 0
1088 ///tp_dealloc
1089 static void Armature_dealloc(BPy_Armature * self)
1090 {
1091         Py_DECREF(self->Bones);
1092         ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
1093         return;
1094 }
1095 //------------------TYPE_OBECT DEFINITION--------------------------
1096 PyTypeObject Armature_Type = {
1097         PyObject_HEAD_INIT(NULL)                //tp_head
1098         0,                                                              //tp_internal
1099         "Armature",                                             //tp_name
1100         sizeof(BPy_Armature),                   //tp_basicsize
1101         0,                                                              //tp_itemsize
1102         (destructor)Armature_dealloc,   //tp_dealloc
1103         0,                                                              //tp_print
1104         0,                                                              //tp_getattr
1105         0,                                                              //tp_setattr
1106         0,                                                              //tp_compare
1107         (reprfunc) Armature_repr,               //tp_repr
1108         0,                                                              //tp_as_number
1109         0,                                                              //tp_as_sequence
1110         0,                                                              //tp_as_mapping
1111         0,                                                              //tp_hash
1112         0,                                                              //tp_call
1113         0,                                                              //tp_str
1114         0,                                                              //tp_getattro
1115         0,                                                              //tp_setattro
1116         0,                                                              //tp_as_buffer
1117         Py_TPFLAGS_DEFAULT,                             //tp_flags
1118         BPy_Armature_doc,                               //tp_doc
1119         0,                                                              //tp_traverse
1120         0,                                                              //tp_clear
1121         (richcmpfunc)Armature_richcmpr, //tp_richcompare
1122         0,                                                              //tp_weaklistoffset
1123         0,                                                              //tp_iter
1124         0,                                                              //tp_iternext
1125         BPy_Armature_methods,                   //tp_methods
1126         0,                                                              //tp_members
1127         BPy_Armature_getset,                    //tp_getset
1128         0,                                                              //tp_base
1129         0,                                                              //tp_dict
1130         0,                                                              //tp_descr_get
1131         0,                                                              //tp_descr_set
1132         0,                                                              //tp_dictoffset
1133         (initproc)Armature_init,                //tp_init
1134         0,                                                              //tp_alloc
1135         (newfunc)Armature_new,                  //tp_new
1136         0,                                                              //tp_free
1137         0,                                                              //tp_is_gc
1138         0,                                                              //tp_bases
1139         0,                                                              //tp_mro
1140         0,                                                              //tp_cache
1141         0,                                                              //tp_subclasses
1142         0,                                                              //tp_weaklist
1143         0                                                               //tp_del
1144 };
1145
1146 //-------------------MODULE METHODS IMPLEMENTATION------------------------
1147 //----------------Blender.Armature.Get()
1148 /* This function will return a Py_Armature when a single string is passed
1149 * or else it will return a {key:value} dictionary when mutliple strings are passed
1150 * or it will return a {key:value} dictionary of all armatures when nothing is passed*/
1151 static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
1152 {
1153         PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
1154         char *name = "", buffer[24];
1155         int size = 0, i;
1156         void *data;
1157
1158         //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
1159         size = PySequence_Length(args);
1160         if (size == 1) {
1161                 seq = PySequence_GetItem(args, 0); //*new*
1162                 if (seq == NULL)
1163                         goto RuntimeError;
1164                 if(!PyString_Check(seq)){
1165                         if (PySequence_Check(seq)) {
1166                                 size = PySequence_Length(seq);
1167                         } else {
1168                                 Py_DECREF(seq);
1169                                 goto AttributeError;
1170                         }
1171                 }
1172         } else {
1173                 seq = EXPP_incr_ret(args); //*take ownership*
1174         }
1175         //'seq' should be a list, empty tuple or string - check list for strings
1176         if(!PyString_Check(seq)){
1177                 for(i = 0; i < size; i++){
1178                         item = PySequence_GetItem(seq, i); //*new*
1179                         if (item == NULL) {
1180                                 Py_DECREF(seq);
1181                                 goto RuntimeError;
1182                         }
1183                         if(!PyString_Check(item)){
1184                                 EXPP_decr2(item, seq);
1185                                 goto AttributeError;
1186                         }
1187                         Py_DECREF(item);
1188                 }
1189         }
1190
1191         //GET ARMATURES
1192         if(size != 1){
1193                 dict = PyDict_New(); //*new*
1194                 if(dict == NULL){
1195                         Py_DECREF(seq);
1196                         goto RuntimeError;
1197                 }
1198                 if(size == 0){  //GET ALL ARMATURES
1199                         data = G.main->armature.first; //get the first data ID from the armature library
1200                         while (data){
1201                                 py_armature = PyArmature_FromArmature(data); //*new*
1202                                 sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
1203                                 if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
1204                                         EXPP_decr3(seq, dict, py_armature);
1205                                         goto RuntimeError;
1206                                 }
1207                                 data = ((ID*)data)->next;
1208                         }
1209                         Py_DECREF(seq);
1210                 }else{  //GET ARMATURE LIST
1211                         for (i = 0; i < size; i++) {
1212                                 item = PySequence_GetItem(seq, i); //*new*
1213                                 name = PyString_AsString(item);
1214                                 Py_DECREF(item);
1215                                 data = find_id("AR", name); //get data from library
1216                                 if (data != NULL){
1217                                         py_armature = PyArmature_FromArmature(data); //*new*
1218                                         if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
1219                                                 EXPP_decr3(seq, dict, py_armature);
1220                                                 goto RuntimeError;
1221                                         }
1222                                 }else{
1223                                         if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
1224                                                 EXPP_decr2(seq, dict);
1225                                                 goto RuntimeError;
1226                                         }
1227                                 }
1228                         }
1229                         Py_DECREF(seq);
1230                 }
1231                 return dict; //transfering ownership to caller
1232         }else{  //GET SINGLE ARMATURE
1233                 if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
1234                         item = PySequence_GetItem(seq, 0); //*new*
1235                         name = PyString_AsString(item);
1236                         Py_DECREF(item);
1237                 }else{
1238                         name = PyString_AsString(seq);
1239                 }
1240                 Py_DECREF(seq);
1241                 data = find_id("AR", name); //get data from library
1242                 if (data != NULL){
1243                         return PyArmature_FromArmature(data); //*new*
1244                 }else{
1245                         return EXPP_incr_ret(Py_None);
1246                 }
1247         }
1248
1249 RuntimeError:
1250         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1251                 sModuleError, "Get(): ", "Internal Error Ocurred");
1252
1253 AttributeError:
1254         return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
1255                 sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
1256 }
1257
1258 //-------------------MODULE METHODS DEFINITION-----------------------------
1259 static PyObject *M_Armature_Get( PyObject * self, PyObject * args );
1260
1261 static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
1262   returns None if not found.\n If 'name' is not specified, it returns a list of all \
1263   armatures in the\ncurrent scene.";
1264
1265 struct PyMethodDef M_Armature_methods[] = {
1266         {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
1267         {NULL}
1268 };
1269 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1270 //-----------------(internal)
1271 //Converts a bArmature to a PyArmature
1272 PyObject *PyArmature_FromArmature(struct bArmature *armature)
1273 {
1274         BPy_Armature *py_armature = NULL;
1275         int success;
1276
1277         py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
1278         if (py_armature == NULL)
1279                 goto RuntimeError;
1280
1281         py_armature->armature = armature;
1282
1283         py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); //*new*
1284         if (py_armature->Bones == NULL)
1285                 goto RuntimeError;
1286
1287         success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &armature->bonebase);
1288         if (success == -1)
1289                 return NULL; //error string already set
1290
1291         return (PyObject *) py_armature; 
1292
1293 RuntimeError:
1294         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1295                 sModuleError, "PyArmature_FromArmature: ", "Internal Error Ocurred");
1296 }
1297 //-----------------(internal)
1298 //Converts a PyArmature to a bArmature
1299 struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
1300 {
1301         return (py_armature->armature);
1302 }
1303 //-------------------MODULE INITIALIZATION--------------------------------
1304 PyObject *Armature_Init(void)
1305 {
1306         PyObject *module, *dict;
1307
1308         //Initializes TypeObject.ob_type
1309         if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
1310                 PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0){
1311                 return EXPP_incr_ret(Py_None);
1312         }
1313
1314         //Register the module
1315         module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
1316                 "The Blender Armature module"); 
1317
1318         //Add TYPEOBJECTS to the module
1319         PyModule_AddObject(module, "ArmatureType", 
1320                 EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
1321         PyModule_AddObject(module, "BoneType", 
1322                 EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
1323
1324         //Add CONSTANTS to the module
1325         PyModule_AddObject(module, "CONNECTED", 
1326                 EXPP_incr_ret(PyConstant_NewInt("CONNECTED", BONE_CONNECTED)));
1327         PyModule_AddObject(module, "HINGE", 
1328                 EXPP_incr_ret(PyConstant_NewInt("HINGE", BONE_HINGE)));
1329         PyModule_AddObject(module, "NO_DEFORM", 
1330                 EXPP_incr_ret(PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM)));
1331         PyModule_AddObject(module, "MULTIPLY", 
1332                 EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV)));
1333         PyModule_AddObject(module, "HIDDEN_EDIT", 
1334                 EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A)));
1335
1336         PyModule_AddObject(module, "BONESPACE", 
1337                 EXPP_incr_ret(PyConstant_NewString("BONESPACE", "bone_space")));
1338         PyModule_AddObject(module, "ARMATURESPACE", 
1339                 EXPP_incr_ret(PyConstant_NewString("ARMATURESPACE", "armature_space")));
1340         PyModule_AddObject(module, "WORLDSPACE", 
1341                 EXPP_incr_ret(PyConstant_NewString("WORLDSPACE", "world_space")));
1342
1343         PyModule_AddObject(module, "OCTAHEDRON", 
1344                 EXPP_incr_ret(PyConstant_NewInt("OCTAHEDRON", ARM_OCTA)));
1345         PyModule_AddObject(module, "STICK", 
1346                 EXPP_incr_ret(PyConstant_NewInt("STICK", ARM_LINE)));
1347         PyModule_AddObject(module, "BBONE", 
1348                 EXPP_incr_ret(PyConstant_NewInt("BBONE", ARM_B_BONE)));
1349         PyModule_AddObject(module, "ENVELOPE", 
1350                 EXPP_incr_ret(PyConstant_NewInt("ENVELOPE", ARM_ENVELOPE)));
1351
1352         //Add SUBMODULES to the module
1353         dict = PyModule_GetDict( module ); //borrowed
1354         PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
1355
1356         return module;
1357 }