Little bit of testing code snuck in there.
[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                 bone->boneclass = 0;
457         }
458
459         pos = 0;
460         //place bones in their correct heirarchy
461         while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, 
462                 &pos, &key, &value)) {
463
464                 editbone = (BPy_EditBone*)value;
465                 bone = editbone->temp; //get bone pointer
466
467                 if (!STREQ(editbone->parent, "")){
468                         parent = EditBoneDict_CheckForKey((BPy_BonesDict*)self->Bones, editbone->parent);
469                         if(parent != NULL){
470
471                                 //parent found in dictionary
472                                 bone->parent = parent->temp;
473                                 BLI_addtail (&parent->temp->childbase, bone);
474                                 //Parenting calculations 
475                                 VecSubf (delta, parent->tail, parent->head);
476                                 vec_roll_to_mat3(delta, parent->roll, M_parentRest); //M_parentRest = parent matrix
477                                 VecSubf (delta, editbone->tail, editbone->head);
478                                 vec_roll_to_mat3(delta, editbone->roll, M_boneRest);  //M_boneRest = bone matrix
479                                 Mat3Inv(iM_parentRest, M_parentRest); //iM_parentRest = 1/parent matrix
480                                 //get head/tail
481                                 VecSubf (bone->head, editbone->head, parent->tail);
482                                 VecSubf (bone->tail, editbone->tail, parent->tail);
483                                 //put them in parentspace
484                                 Mat3MulVecfl(iM_parentRest, bone->head);
485                                 Mat3MulVecfl(iM_parentRest, bone->tail);
486
487                                 Py_DECREF(parent);
488                         }else{
489                                 //was not found - most likely parent was deleted
490                                 parent = NULL;
491                                 BLI_addtail (&self->armature->bonebase, bone);
492                         }
493                 }else{
494                         BLI_addtail (&self->armature->bonebase, bone);
495                 }
496         }
497         //fix rolls and generate matrices
498         PyArmature_FixRolls(&self->armature->bonebase, 
499                 ((BPy_BonesDict*)self->Bones)->editBoneDict);
500
501         //update linked objects
502         for(obj = G.main->object.first; obj; obj = obj->id.next) {
503                 if(obj->data == self->armature){
504                         armature_rebuild_pose(obj, self->armature);
505                 }
506         }
507         DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
508
509         //clear the editbone dictionary and set edit flag
510         PyDict_Clear(((BPy_BonesDict*)self->Bones)->editBoneDict);
511         ((BPy_BonesDict*)self->Bones)->editmode_flag = 0;
512
513         //rebuild py_bones
514         PyDict_Clear(((BPy_BonesDict*)self->Bones)->dict);
515         if (BonesDict_Init(((BPy_BonesDict*)self->Bones)->dict, 
516                 &self->armature->bonebase) == -1)
517                 return NULL; //error string already set
518
519         return EXPP_incr_ret(Py_None);
520 }
521 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
522 //------------------------Armature.autoIK (getter)
523 static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
524 {
525         if (self->armature->flag & ARM_AUTO_IK)
526                 return EXPP_incr_ret(Py_True);
527         else
528                 return EXPP_incr_ret(Py_False);
529 }
530 //------------------------Armature.autoIK (setter)
531 static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
532 {
533         if(value){
534                 if(PyBool_Check(value)){
535                         if (value == Py_True){
536                                 self->armature->flag |= ARM_AUTO_IK;
537                                 return 0;
538                         }else if (value == Py_False){
539                                 self->armature->flag &= ~ARM_AUTO_IK;
540                                 return 0;
541                         }
542                 }
543         }
544         goto AttributeError;
545
546 AttributeError:
547         return EXPP_intError(PyExc_AttributeError, "%s%s", 
548                 sArmatureBadArgs, "Expects True or False");
549 }
550 //------------------------Armature.mirrorEdit (getter)
551 static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
552 {
553         if (self->armature->flag & ARM_MIRROR_EDIT)
554                 Py_RETURN_TRUE;
555         else
556                 Py_RETURN_FALSE;
557 }
558 //------------------------Armature.mirrorEdit (setter)
559 static int Armature_setMirrorEdit(BPy_Armature *self, PyObject *value, void *closure)
560 {
561         if(value){
562                 if(PyBool_Check(value)){
563                         if (value == Py_True){
564                                 self->armature->flag |= ARM_MIRROR_EDIT;
565                                 return 0;
566                         }else if (value == Py_False){
567                                 self->armature->flag &= ~ARM_MIRROR_EDIT;
568                                 return 0;
569                         }
570                 }
571         }
572         goto AttributeError;
573
574 AttributeError:
575         return EXPP_intError(PyExc_AttributeError, "%s%s", 
576                 sArmatureBadArgs, "Expects True or False");
577 }
578 //------------------------Armature.drawType (getter)
579 static PyObject *Armature_getDrawType(BPy_Armature *self, void *closure)
580 {
581         if (self->armature->drawtype == ARM_OCTA){
582                 return EXPP_GetModuleConstant("Blender.Armature", "OCTAHEDRON") ;
583         }else if (self->armature->drawtype == ARM_LINE){
584                 return EXPP_GetModuleConstant("Blender.Armature", "STICK") ;
585         }else if (self->armature->drawtype == ARM_B_BONE){
586                 return EXPP_GetModuleConstant("Blender.Armature", "BBONE") ;
587         }else if (self->armature->drawtype == ARM_ENVELOPE){
588                 return EXPP_GetModuleConstant("Blender.Armature", "ENVELOPE") ;
589         }else{
590                 goto RuntimeError;
591         }
592
593 RuntimeError:
594         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
595                 sArmatureError, "drawType: ", "Internal failure!");
596 }
597 //------------------------Armature.drawType (setter)
598 static int Armature_setDrawType(BPy_Armature *self, PyObject *value, void *closure)
599 {
600         PyObject *val = NULL, *name = NULL;
601         long numeric_value;
602
603         if(value){
604                 if(BPy_Constant_Check(value)){
605                         name = PyDict_GetItemString(((BPy_constant*)value)->dict, "name");
606                         if (!STREQ2(PyString_AsString(name), "OCTAHEDRON", "STICK") &&
607                                 !STREQ2(PyString_AsString(name), "BBONE", "ENVELOPE"))
608                                 goto ValueError;
609                         val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
610                         if (PyInt_Check(val)){
611                                 numeric_value = PyInt_AS_LONG(val);
612                                 self->armature->drawtype = (int)numeric_value;
613                                 return 0;
614                         }
615                 }
616         }
617         goto AttributeError;
618
619 AttributeError:
620         return EXPP_intError(PyExc_AttributeError, "%s%s", 
621                 sArmatureBadArgs, "Expects module constant");
622
623 ValueError:
624         return EXPP_intError(PyExc_AttributeError, "%s%s", 
625                 sArmatureBadArgs, "Argument must be the constant OCTAHEDRON, STICK, BBONE, or ENVELOPE");
626 }
627 //------------------------Armature.ghostStep (getter)
628 static PyObject *Armature_getStep(BPy_Armature *self, void *closure)
629 {
630         return PyInt_FromLong((long)self->armature->ghostsize);
631 }
632 //------------------------Armature.ghostStep (setter)
633 static int Armature_setStep(BPy_Armature *self, PyObject *value, void *closure)
634 {
635         long numerical_value;
636
637         if(value){
638                 if(PyInt_Check(value)){
639                         numerical_value = PyInt_AS_LONG(value);
640                         if (numerical_value > 20.0f || numerical_value < 1.0f)
641                                 goto ValueError;
642                         self->armature->ghostsize = (short)numerical_value;
643                         return 0;
644                 }
645         }
646         goto AttributeError;
647
648 AttributeError:
649         return EXPP_intError(PyExc_AttributeError, "%s%s", 
650                 sArmatureBadArgs, "Expects Integer");
651
652 ValueError:
653         return EXPP_intError(PyExc_AttributeError, "%s%s", 
654                 sArmatureBadArgs, "Argument must fall within 1-20");
655 }
656 //------------------------Armature.ghost (getter)
657 static PyObject *Armature_getGhost(BPy_Armature *self, void *closure)
658 {
659         return PyInt_FromLong((long)self->armature->ghostep);
660 }
661 //------------------------Armature.ghost (setter)
662 static int Armature_setGhost(BPy_Armature *self, PyObject *value, void *closure)
663 {
664         long numerical_value;
665
666         if(value){
667                 if(PyInt_Check(value)){
668                         numerical_value = PyInt_AS_LONG(value);
669                         if (numerical_value > 30.0f || numerical_value < 0.0f)
670                                 goto ValueError;
671                         self->armature->ghostep = (short)numerical_value;
672                         return 0;
673                 }
674         }
675         goto AttributeError;
676
677 AttributeError:
678         return EXPP_intError(PyExc_AttributeError, "%s%s", 
679                 sArmatureBadArgs, "Expects Integer");
680
681 ValueError:
682         return EXPP_intError(PyExc_AttributeError, "%s%s", 
683                 sArmatureBadArgs, "Argument must fall within 0-30");
684 }
685 //------------------------Armature.drawNames (getter)
686 static PyObject *Armature_getDrawNames(BPy_Armature *self, void *closure)
687 {
688         if (self->armature->flag & ARM_DRAWNAMES)
689                 Py_RETURN_TRUE;
690         else
691                 Py_RETURN_FALSE;
692 }
693 //------------------------Armature.drawNames (setter)
694 static int Armature_setDrawNames(BPy_Armature *self, PyObject *value, void *closure)
695 {
696         if(value){
697                 if(PyBool_Check(value)){
698                         if (value == Py_True){
699                                 self->armature->flag |= ARM_DRAWNAMES;
700                                 return 0;
701                         }else if (value == Py_False){
702                                 self->armature->flag &= ~ARM_DRAWNAMES;
703                                 return 0;
704                         }
705                 }
706         }
707         goto AttributeError;
708
709 AttributeError:
710         return EXPP_intError(PyExc_AttributeError, "%s%s", 
711                 sArmatureBadArgs, "Expects True or False");
712 }
713 //------------------------Armature.drawAxes (getter)
714 static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
715 {
716         if (self->armature->flag & ARM_DRAWAXES)
717                 Py_RETURN_TRUE;
718         else
719                 Py_RETURN_FALSE;
720 }
721 //------------------------Armature.drawAxes (setter)
722 static int Armature_setDrawAxes(BPy_Armature *self, PyObject *value, void *closure)
723 {
724         if(value){
725                 if(PyBool_Check(value)){
726                         if (value == Py_True){
727                                 self->armature->flag |= ARM_DRAWAXES;
728                                 return 0;
729                         }else if (value == Py_False){
730                                 self->armature->flag &= ~ARM_DRAWAXES;
731                                 return 0;
732                         }
733                 }
734         }
735         goto AttributeError;
736
737 AttributeError:
738         return EXPP_intError(PyExc_AttributeError, "%s%s", 
739                 sArmatureBadArgs, "Expects True or False");
740 }
741 //------------------------Armature.delayDeform (getter)
742 static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
743 {
744         if (self->armature->flag & ARM_DELAYDEFORM)
745                 Py_RETURN_TRUE;
746         else
747                 Py_RETURN_FALSE;
748 }
749 //------------------------Armature.delayDeform (setter)
750 static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
751 {
752         if(value){
753                 if(PyBool_Check(value)){
754                         if (value == Py_True){
755                                 self->armature->flag |= ARM_DELAYDEFORM;
756                                 return 0;
757                         }else if (value == Py_False){
758                                 self->armature->flag &= ~ARM_DELAYDEFORM;
759                                 return 0;
760                         }
761                 }
762         }
763         goto AttributeError;
764
765 AttributeError:
766         return EXPP_intError(PyExc_AttributeError, "%s%s", 
767                 sArmatureBadArgs, "Expects True or False");
768 }
769 //------------------------Armature.restPosition (getter)
770 static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
771 {
772         if (self->armature->flag & ARM_RESTPOS)
773                 Py_RETURN_TRUE;
774         else
775                 Py_RETURN_FALSE;
776 }
777 //------------------------Armature.restPosition (setter)
778 static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
779 {
780         if(value){
781                 if(PyBool_Check(value)){
782                         if (value == Py_True){
783                                 self->armature->flag |= ARM_RESTPOS;
784                                 return 0;
785                         }else if (value == Py_False){
786                                 self->armature->flag &= ~ARM_RESTPOS;
787                                 return 0;
788                         }
789                 }
790         }
791         goto AttributeError;
792
793 AttributeError:
794         return EXPP_intError(PyExc_AttributeError, "%s%s", 
795                 sArmatureBadArgs, "Expects True or False");
796 }
797 //------------------------Armature.envelopes (getter)
798 static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
799 {
800         if (self->armature->deformflag & ARM_DEF_ENVELOPE)
801                 Py_RETURN_TRUE;
802         else
803                 Py_RETURN_FALSE;
804 }
805 //------------------------Armature.envelopes (setter)
806 static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
807 {
808         if(value){
809                 if(PyBool_Check(value)){
810                         if (value == Py_True){
811                                 self->armature->deformflag |= ARM_DEF_ENVELOPE;
812                                 return 0;
813                         }else if (value == Py_False){
814                                 self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
815                                 return 0;
816                         }
817                 }
818         }
819         goto AttributeError;
820
821 AttributeError:
822         return EXPP_intError(PyExc_AttributeError, "%s%s", 
823                 sArmatureBadArgs, "Expects True or False");
824 }
825 //------------------------Armature.vertexGroups (getter)
826 static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
827 {
828         if (self->armature->deformflag & ARM_DEF_VGROUP)
829                 Py_RETURN_TRUE;
830         else
831                 Py_RETURN_FALSE;
832 }
833 //------------------------Armature.vertexGroups (setter)
834 static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
835 {
836         if(value){
837                 if(PyBool_Check(value)){
838                         if (value == Py_True){
839                                 self->armature->deformflag |= ARM_DEF_VGROUP;
840                                 return 0;
841                         }else if (value == Py_False){
842                                 self->armature->deformflag &= ~ARM_DEF_VGROUP;
843                                 return 0;
844                         }
845                 }
846         }
847         goto AttributeError;
848
849 AttributeError:
850         return EXPP_intError(PyExc_AttributeError, "%s%s", 
851                 sArmatureBadArgs, "Expects True or False");
852 }
853 //------------------------Armature.name (getter)
854 //Gets the name of the armature
855 static PyObject *Armature_getName(BPy_Armature *self, void *closure)
856 {
857     return PyString_FromString(self->armature->id.name +2); //*new*
858 }
859 //------------------------Armature.name (setter)
860 //Sets the name of the armature
861 static int Armature_setName(BPy_Armature *self, PyObject *value, void *closure)
862 {
863         char buffer[24];
864         char *name = "";
865
866         if(value){
867                 if(PyString_Check(value)){
868                         name = PyString_AsString(value);
869                         PyOS_snprintf(buffer, sizeof(buffer), "%s", name);
870                         rename_id(&self->armature->id, buffer);
871                         return 0; 
872                 }
873         }
874         goto AttributeError;
875
876 AttributeError:
877         return EXPP_intError(PyExc_AttributeError, "%s%s", 
878                 sArmatureBadArgs, "Expects string");
879 }
880 //------------------------Armature.bones (getter)
881 //Gets the name of the armature
882 static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
883 {
884     return EXPP_incr_ret(self->Bones);
885 }
886 //------------------------Armature.bones (setter)
887 //Sets the name of the armature
888 /*TODO*/
889 /*Copy Bones through x = y*/
890 static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
891 {
892         goto AttributeError;
893
894 AttributeError:
895         return EXPP_intError(PyExc_AttributeError, "%s%s", 
896                 sArmatureError, "You are not allowed to change the .Bones attribute");
897 }
898 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
899 //------------------------tp_doc
900 //The __doc__ string for this object
901 static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
902
903 //------------------------tp_methods
904 //This contains a list of all methods the object contains
905 static PyMethodDef BPy_Armature_methods[] = {
906         {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
907                 "() - Unlocks the ability to modify armature bones"},
908         {"saveChanges", (PyCFunction) Armature_saveChanges, METH_NOARGS, 
909                 "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
910         {NULL}
911 };
912
913 //------------------------tp_getset
914 //This contains methods for attributes that require checking
915 static PyGetSetDef BPy_Armature_getset[] = {
916         {"name", (getter)Armature_getName, (setter)Armature_setName, 
917                 "The armature's name", NULL},
918         {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
919                 "The armature's Bone dictionary", NULL},
920         {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
921                 "Enable/Disable vertex group defined deformation", NULL},
922         {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
923                 "Enable/Disable bone envelope defined deformation", NULL},
924         {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
925                 "Show armature rest position - disables posing", NULL},
926         {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
927                 "Don't deform children when manipulating bones in pose mode", NULL},
928         {"drawAxes", (getter)Armature_getDrawAxes, (setter)Armature_setDrawAxes, 
929                 "Enable/Disable  drawing  the bone axes", NULL},
930         {"drawNames", (getter)Armature_getDrawNames, (setter)Armature_setDrawNames, 
931                 "Enable/Disable  drawing the bone names", NULL},
932         {"ghost", (getter)Armature_getGhost, (setter)Armature_setGhost, 
933                 "Draw a number of ghosts around the current frame for current Action", NULL},
934         {"ghostStep", (getter)Armature_getStep, (setter)Armature_setStep, 
935                 "The number of frames between ghost instances", NULL},
936         {"drawType", (getter)Armature_getDrawType, (setter)Armature_setDrawType, 
937                 "The type of drawing currently applied to the armature", NULL},
938         {"mirrorEdit", (getter)Armature_getMirrorEdit, (setter)Armature_setMirrorEdit, 
939                 "Enable/Disable X-axis mirrored editing", NULL},
940         {"autoIK", (getter)Armature_getAutoIK, (setter)Armature_setAutoIK, 
941                 "Adds temporal IK chains while grabbing bones", NULL},
942         {NULL}
943 };
944 //------------------------tp_new
945 //This methods creates a new object (note it does not initialize it - only the building)
946 //This can be called through python by myObject.__new__() however, tp_init is not called
947 static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
948 {
949         BPy_Armature *py_armature = NULL;
950         bArmature *bl_armature;
951         int success;
952
953         bl_armature = add_armature();
954         if(bl_armature) {
955                 bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
956
957                 py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
958                 if (py_armature == NULL)
959                         goto RuntimeError;
960
961                 py_armature->armature = bl_armature;
962
963                 py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL);
964                 if (py_armature->Bones == NULL)
965                         goto RuntimeError;
966
967                 success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &bl_armature->bonebase);
968                 if (success == -1)
969                         return NULL; //error string already set
970         } else {
971                 goto RuntimeError;
972         }
973         return (PyObject*)py_armature; 
974
975 RuntimeError:
976         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
977                 sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
978 }
979 //------------------------tp_init
980 //This methods does initialization of the new object
981 //This method will get called in python by 'myObject(argument, keyword=value)'
982 //tp_new will be automatically called before this
983 static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
984 {
985         char buf[21];
986         char *name = "myArmature";
987         static char *kwlist[] = {"name", NULL};
988
989         if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
990                 goto AttributeError;
991         }
992
993         //rename the armature if a name is supplied
994         if(!BLI_streq(name, "myArmature")){
995                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
996                 rename_id(&self->armature->id, buf);
997         }
998
999         return 0;
1000
1001 AttributeError:
1002         return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
1003                 sArmatureBadArgs, " __init__: ", "Expects string(name)");
1004 }
1005 //------------------------tp_richcompare
1006 //This method allows the object to use comparison operators
1007 //TODO: We need some armature comparisons
1008 static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op)
1009 {
1010         return EXPP_incr_ret(Py_None);
1011 }
1012
1013 //------------------------tp_repr
1014 //This is the string representation of the object
1015 static PyObject *Armature_repr(BPy_Armature *self)
1016 {
1017         return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
1018 }
1019
1020 //------------------------tp_dealloc
1021 //This tells how to 'tear-down' our object when ref count hits 0
1022 ///tp_dealloc
1023 static void Armature_dealloc(BPy_Armature * self)
1024 {
1025         Py_DECREF(self->Bones);
1026         ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
1027         return;
1028 }
1029 //------------------TYPE_OBECT DEFINITION--------------------------
1030 PyTypeObject Armature_Type = {
1031         PyObject_HEAD_INIT(NULL)                //tp_head
1032         0,                                                              //tp_internal
1033         "Armature",                                             //tp_name
1034         sizeof(BPy_Armature),                   //tp_basicsize
1035         0,                                                              //tp_itemsize
1036         (destructor)Armature_dealloc,   //tp_dealloc
1037         0,                                                              //tp_print
1038         0,                                                              //tp_getattr
1039         0,                                                              //tp_setattr
1040         0,                                                              //tp_compare
1041         (reprfunc) Armature_repr,               //tp_repr
1042         0,                                                              //tp_as_number
1043         0,                                                              //tp_as_sequence
1044         0,                                                              //tp_as_mapping
1045         0,                                                              //tp_hash
1046         0,                                                              //tp_call
1047         0,                                                              //tp_str
1048         0,                                                              //tp_getattro
1049         0,                                                              //tp_setattro
1050         0,                                                              //tp_as_buffer
1051         Py_TPFLAGS_DEFAULT,                             //tp_flags
1052         BPy_Armature_doc,                               //tp_doc
1053         0,                                                              //tp_traverse
1054         0,                                                              //tp_clear
1055         (richcmpfunc)Armature_richcmpr, //tp_richcompare
1056         0,                                                              //tp_weaklistoffset
1057         0,                                                              //tp_iter
1058         0,                                                              //tp_iternext
1059         BPy_Armature_methods,                   //tp_methods
1060         0,                                                              //tp_members
1061         BPy_Armature_getset,                    //tp_getset
1062         0,                                                              //tp_base
1063         0,                                                              //tp_dict
1064         0,                                                              //tp_descr_get
1065         0,                                                              //tp_descr_set
1066         0,                                                              //tp_dictoffset
1067         (initproc)Armature_init,                //tp_init
1068         0,                                                              //tp_alloc
1069         (newfunc)Armature_new,                  //tp_new
1070         0,                                                              //tp_free
1071         0,                                                              //tp_is_gc
1072         0,                                                              //tp_bases
1073         0,                                                              //tp_mro
1074         0,                                                              //tp_cache
1075         0,                                                              //tp_subclasses
1076         0,                                                              //tp_weaklist
1077         0                                                               //tp_del
1078 };
1079
1080 //-------------------MODULE METHODS IMPLEMENTATION------------------------
1081 //----------------Blender.Armature.Get()
1082 /* This function will return a Py_Armature when a single string is passed
1083 * or else it will return a {key:value} dictionary when mutliple strings are passed
1084 * or it will return a {key:value} dictionary of all armatures when nothing is passed*/
1085 static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
1086 {
1087         PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
1088         char *name = "", buffer[24];
1089         int size = 0, i;
1090         void *data;
1091
1092         //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
1093         size = PySequence_Length(args);
1094         if (size == 1) {
1095                 seq = PySequence_GetItem(args, 0); //*new*
1096                 if (seq == NULL)
1097                         goto RuntimeError;
1098                 if(!PyString_Check(seq)){
1099                         if (PySequence_Check(seq)) {
1100                                 size = PySequence_Length(seq);
1101                         } else {
1102                                 Py_DECREF(seq);
1103                                 goto AttributeError;
1104                         }
1105                 }
1106         } else {
1107                 seq = EXPP_incr_ret(args); //*take ownership*
1108         }
1109         //'seq' should be a list, empty tuple or string - check list for strings
1110         if(!PyString_Check(seq)){
1111                 for(i = 0; i < size; i++){
1112                         item = PySequence_GetItem(seq, i); //*new*
1113                         if (item == NULL) {
1114                                 Py_DECREF(seq);
1115                                 goto RuntimeError;
1116                         }
1117                         if(!PyString_Check(item)){
1118                                 EXPP_decr2(item, seq);
1119                                 goto AttributeError;
1120                         }
1121                         Py_DECREF(item);
1122                 }
1123         }
1124
1125         //GET ARMATURES
1126         if(size != 1){
1127                 dict = PyDict_New(); //*new*
1128                 if(dict == NULL){
1129                         Py_DECREF(seq);
1130                         goto RuntimeError;
1131                 }
1132                 if(size == 0){  //GET ALL ARMATURES
1133                         data = &(G.main->armature).first; //get the first data ID from the armature library
1134                         while (data){
1135                                 py_armature = PyArmature_FromArmature(data); //*new*
1136                                 sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
1137                                 if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
1138                                         EXPP_decr3(seq, dict, py_armature);
1139                                         goto RuntimeError;
1140                                 }
1141                                 data = ((ID*)data)->next;
1142                         }
1143                         Py_DECREF(seq);
1144                 }else{  //GET ARMATURE LIST
1145                         for (i = 0; i < size; i++) {
1146                                 item = PySequence_GetItem(seq, i); //*new*
1147                                 name = PyString_AsString(item);
1148                                 Py_DECREF(item);
1149                                 data = find_id("AR", name); //get data from library
1150                                 if (data != NULL){
1151                                         py_armature = PyArmature_FromArmature(data); //*new*
1152                                         if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
1153                                                 EXPP_decr3(seq, dict, py_armature);
1154                                                 goto RuntimeError;
1155                                         }
1156                                 }else{
1157                                         if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
1158                                                 EXPP_decr2(seq, dict);
1159                                                 goto RuntimeError;
1160                                         }
1161                                 }
1162                         }
1163                         Py_DECREF(seq);
1164                 }
1165                 return dict; //transfering ownership to caller
1166         }else{  //GET SINGLE ARMATURE
1167                 if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
1168                         item = PySequence_GetItem(seq, 0); //*new*
1169                         name = PyString_AsString(item);
1170                         Py_DECREF(item);
1171                 }else{
1172                         name = PyString_AsString(seq);
1173                 }
1174                 Py_DECREF(seq);
1175                 data = find_id("AR", name); //get data from library
1176                 if (data != NULL){
1177                         return PyArmature_FromArmature(data); //*new*
1178                 }else{
1179                         return EXPP_incr_ret(Py_None);
1180                 }
1181         }
1182
1183 RuntimeError:
1184         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1185                 sModuleError, "Get(): ", "Internal Error Ocurred");
1186
1187 AttributeError:
1188         return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
1189                 sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
1190 }
1191
1192 //-------------------MODULE METHODS DEFINITION-----------------------------
1193 static PyObject *M_Armature_Get( PyObject * self, PyObject * args );
1194
1195 static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
1196   returns None if not found.\n If 'name' is not specified, it returns a list of all \
1197   armatures in the\ncurrent scene.";
1198
1199 struct PyMethodDef M_Armature_methods[] = {
1200         {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
1201         {NULL}
1202 };
1203 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1204 //-----------------(internal)
1205 //Converts a bArmature to a PyArmature
1206 PyObject *PyArmature_FromArmature(struct bArmature *armature)
1207 {
1208         BPy_Armature *py_armature = NULL;
1209         int success;
1210
1211         py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
1212         if (py_armature == NULL)
1213                 goto RuntimeError;
1214
1215         py_armature->armature = armature;
1216
1217         py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); //*new*
1218         if (py_armature->Bones == NULL)
1219                 goto RuntimeError;
1220
1221         success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &armature->bonebase);
1222         if (success == -1)
1223                 return NULL; //error string already set
1224
1225         return (PyObject *) py_armature; 
1226
1227 RuntimeError:
1228         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1229                 sModuleError, "PyArmature_FromArmature: ", "Internal Error Ocurred");
1230 }
1231 //-----------------(internal)
1232 //Converts a PyArmature to a bArmature
1233 struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
1234 {
1235         return (py_armature->armature);
1236 }
1237 //-------------------MODULE INITIALIZATION--------------------------------
1238 PyObject *Armature_Init(void)
1239 {
1240         PyObject *module, *dict;
1241
1242         //Initializes TypeObject.ob_type
1243         if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
1244                 PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0){
1245                 return EXPP_incr_ret(Py_None);
1246         }
1247
1248         //Register the module
1249         module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
1250                 "The Blender Armature module"); 
1251
1252         //Add TYPEOBJECTS to the module
1253         PyModule_AddObject(module, "ArmatureType", 
1254                 EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
1255         PyModule_AddObject(module, "BoneType", 
1256                 EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
1257
1258         //Add CONSTANTS to the module
1259         PyModule_AddObject(module, "CONNECTED", 
1260                 EXPP_incr_ret(PyConstant_NewInt("CONNECTED", BONE_CONNECTED)));
1261         PyModule_AddObject(module, "HINGE", 
1262                 EXPP_incr_ret(PyConstant_NewInt("HINGE", BONE_HINGE)));
1263         PyModule_AddObject(module, "NO_DEFORM", 
1264                 EXPP_incr_ret(PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM)));
1265         PyModule_AddObject(module, "MULTIPLY", 
1266                 EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV)));
1267         PyModule_AddObject(module, "HIDDEN_EDIT", 
1268                 EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A)));
1269
1270         PyModule_AddObject(module, "BONESPACE", 
1271                 EXPP_incr_ret(PyConstant_NewString("BONESPACE", "bone_space")));
1272         PyModule_AddObject(module, "ARMATURESPACE", 
1273                 EXPP_incr_ret(PyConstant_NewString("ARMATURESPACE", "armature_space")));
1274         PyModule_AddObject(module, "WORLDSPACE", 
1275                 EXPP_incr_ret(PyConstant_NewString("WORLDSPACE", "world_space")));
1276
1277         PyModule_AddObject(module, "OCTAHEDRON", 
1278                 EXPP_incr_ret(PyConstant_NewInt("OCTAHEDRON", ARM_OCTA)));
1279         PyModule_AddObject(module, "STICK", 
1280                 EXPP_incr_ret(PyConstant_NewInt("STICK", ARM_LINE)));
1281         PyModule_AddObject(module, "BBONE", 
1282                 EXPP_incr_ret(PyConstant_NewInt("BBONE", ARM_B_BONE)));
1283         PyModule_AddObject(module, "ENVELOPE", 
1284                 EXPP_incr_ret(PyConstant_NewInt("ENVELOPE", ARM_ENVELOPE)));
1285
1286         //Add SUBMODULES to the module
1287         dict = PyModule_GetDict( module ); //borrowed
1288         PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
1289
1290         return module;
1291 }