Final merge of HEAD (bf-blender) into the orange branch.
[blender.git] / source / blender / python / api2_2x / Armature.c
index 1a1a9ea3498d8aaf32ced3b797796a315406ccb9..28ae3eadcc7ac04cb01e017bfb69b4eafb0442a8 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * $Id$
  *
  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  *
- * This is a new part of Blender.
- *
- * Contributor(s): Jordi Rovira i Bonet, Joseph Gilbert
- *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
- */
+*/
 
-#include "Armature.h" /*This must come first*/
+#include "Armature.h" //This must come first
 
 #include "BKE_main.h"
 #include "BKE_global.h"
 #include "BKE_armature.h"
 #include "BKE_library.h"
+#include "BKE_depsgraph.h"
+#include "BKE_utildefines.h"
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
 #include "MEM_guardedalloc.h"
 #include "NLA.h"
 #include "gen_utils.h"
 
-//---------------- Python API function prototypes for the Armature module---
-static PyObject *M_Armature_New( PyObject * self, PyObject * args );
-static PyObject *M_Armature_Get( PyObject * self, PyObject * args );
-
-//------------- Python API Doc Strings for the Armature module-----------
-static char M_Armature_doc[] = "The Blender Armature module\n\n\
-  This module provides control over **Armature Data** objects in Blender.\n";
-static char M_Armature_New_doc[] =
-       "(name) - return a new Armature datablock of \n\
-  optional name 'name'.";
-static char M_Armature_Get_doc[] =
-       "(name) - return the armature with the name 'name', \
-  returns None if not found.\n If 'name' is not specified, it returns a list of all armatures in the\ncurrent scene.";
-static char M_Armature_get_doc[] = "(name) - DEPRECATED. Use 'Get' instead. \
-  return the armature with the name 'name', returns None if not found.\n If 'name' is not specified, \
-  it returns a list of all armatures in the\ncurrent scene.";
-
-//------Python method structure definition for Blender.Armature module-----
-struct PyMethodDef M_Armature_methods[] = {
-       {"New", ( PyCFunction ) M_Armature_New, METH_VARARGS,
-        M_Armature_New_doc},
-       {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
-       {"get", M_Armature_Get, METH_VARARGS, M_Armature_get_doc},
-       {NULL, NULL, 0, NULL}
-};
-//--------Python BPy_Armature methods declarations----------------------------
-static PyObject *Armature_getName( BPy_Armature * self );
-static PyObject *Armature_getBones( BPy_Armature * self );
-static PyObject *Armature_addBone( BPy_Armature * self, PyObject * args );
-static PyObject *Armature_setName( BPy_Armature * self, PyObject * args );
-static PyObject *Armature_drawAxes( BPy_Armature * self, PyObject * args );
-static PyObject *Armature_drawNames( BPy_Armature * self, PyObject * args );
-//----------------Python BPy_Armature methods table---------------------------
-static PyMethodDef BPy_Armature_methods[] = {
-       {"getName", ( PyCFunction ) Armature_getName, METH_NOARGS,
-        "() - return Armature name"},
-       {"getBones", ( PyCFunction ) Armature_getBones, METH_NOARGS,
-        "() - return Armature root bones"},
-       {"setName", ( PyCFunction ) Armature_setName, METH_VARARGS,
-        "(str) - rename Armature"},
-       {"addBone", ( PyCFunction ) Armature_addBone, METH_VARARGS,
-        "(bone)-add bone"},
-       {"drawAxes", ( PyCFunction ) Armature_drawAxes, METH_VARARGS,
-        "will draw the axis of each bone in armature"},
-       {"drawNames", ( PyCFunction ) Armature_drawNames, METH_VARARGS,
-        "will draw the names of each bone in armature"},
-       {NULL, NULL, 0, NULL}
-};
-
-//----------------Python TypeArmature callback function prototypes-----------
-static void Armature_dealloc( BPy_Armature * armature );
-static PyObject *Armature_getAttr( BPy_Armature * armature, char *name );
-static int Armature_setAttr( BPy_Armature * armature, char *name,
-                            PyObject * v );
-static int Armature_compare( BPy_Armature * a1, BPy_Armature * a2 );
-static PyObject *Armature_repr( BPy_Armature * armature );
-static int doesBoneName_exist( char *name, bArmature * arm );
-
-//---------------- Python TypeArmature structure definition:-----------
-PyTypeObject Armature_Type = {
-       PyObject_HEAD_INIT( NULL ) 
-       0,      /* ob_size */
-       "Blender Armature",     /* tp_name */
-       sizeof( BPy_Armature ), /* tp_basicsize */
-       0,                      /* tp_itemsize */
-       /* methods */
-       ( destructor ) Armature_dealloc,        /* tp_dealloc */
-       0,                      /* tp_print */
-       ( getattrfunc ) Armature_getAttr,       /* tp_getattr */
-       ( setattrfunc ) Armature_setAttr,       /* tp_setattr */
-       ( cmpfunc ) Armature_compare,   /* tp_compare */
-       ( reprfunc ) Armature_repr,     /* tp_repr */
-       0,                      /* tp_as_number */
-       0,                      /* tp_as_sequence */
-       0,                      /* tp_as_mapping */
-       0,                      /* tp_as_hash */
-       0, 0, 0, 0, 0, 0,
-       0,                      /* tp_doc */
-       0, 0, 0, 0, 0, 0,
-       BPy_Armature_methods,   /* tp_methods */
-       0,                      /* tp_members */
-};
-//-------------------Blender Armature Module Init-----------------
-PyObject *Armature_Init( void )
+#include "DNA_object_types.h" //This must come before BIF_editarmature.h...
+#include "BIF_editarmature.h"
+
+//------------------EXTERNAL PROTOTYPES--------------------
+extern void free_editArmature(void);
+extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
+extern void editbones_to_armature (ListBase *list, Object *ob);
+
+//------------------------ERROR CODES---------------------------------
+//This is here just to make me happy and to have more consistant error strings :)
+static const char sBoneDictError[] = "ArmatureType.bones - Error: ";
+static const char sBoneDictBadArgs[] = "ArmatureType.bones - Bad Arguments: ";
+static const char sArmatureError[] = "ArmatureType - Error: ";
+static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: ";
+static const char sModuleError[] = "Blender.Armature - Error: ";
+static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
+
+//################## BonesDict_Type (internal) ########################
+/*This is an internal psuedo-dictionary type that allows for manipulation
+* of bones inside of an armature. It is a subobject of armature.
+* i.e. Armature.bones['key']*/
+//#####################################################################
+
+//------------------METHOD IMPLEMENTATIONS-----------------------------
+//------------------------Armature.bones.items()
+//Returns a list of key:value pairs like dict.items()
+PyObject* BonesDict_items(BPy_BonesDict *self)
 {
-       PyObject *submodule;
-       PyObject *dict;
-
-       Armature_Type.ob_type = &PyType_Type;
-
-       submodule = Py_InitModule3( "Blender.Armature",
-                                   M_Armature_methods, M_Armature_doc );
-
-       /* Add the Bone submodule to this module */
-       dict = PyModule_GetDict( submodule );
-       PyDict_SetItemString( dict, "Bone", Bone_Init(  ) );
-       PyDict_SetItemString( dict, "NLA", NLA_Init(  ) );
-
-       return ( submodule );
+       if (self->editmode_flag){
+               return PyDict_Items(self->editbonesMap); 
+       }else{
+               return PyDict_Items(self->bonesMap); 
+       }
 }
-
-//----------------------Blender Armature Module internal callbacks----
-
-//------------------append_childrenToList-----------------------------------
-static void append_childrenToList( Bone * parent, PyObject * listbones )
+//------------------------Armature.bones.keys()
+//Returns a list of keys like dict.keys()
+PyObject* BonesDict_keys(BPy_BonesDict *self)
 {
-       Bone *child = NULL;
-
-       //append children 
-       for( child = parent->childbase.first; child; child = child->next ) {
-               PyList_Append( listbones, Bone_CreatePyObject( child ) );
-               if( child->childbase.first ) {  //has children?
-                       append_childrenToList( child, listbones );
-               }
+       if (self->editmode_flag){
+               return PyDict_Keys(self->editbonesMap);
+       }else{
+               return PyDict_Keys(self->bonesMap);
        }
 }
-
-//------------------unique_BoneName----------------------------
-static void unique_BoneName( char *name, bArmature * arm )
+//------------------------Armature.bones.values()
+//Returns a list of values like dict.values()
+PyObject* BonesDict_values(BPy_BonesDict *self)
 {
-       char tempname[64];
-       int number;
-       char *dot;
-
-       if( doesBoneName_exist( name, arm ) ) {
-               /*      Strip off the suffix */
-               dot = strchr( name, '.' );
-               if( dot )
-                       *dot = 0;
-
-               for( number = 1; number <= 999; number++ ) {
-                       sprintf( tempname, "%s.%03d", name, number );
-                       if( !doesBoneName_exist( tempname, arm ) ) {
-                               strcpy( name, tempname );
-                               return;
-                       }
-               }
+       if (self->editmode_flag){
+               return PyDict_Values(self->editbonesMap);
+       }else{
+               return PyDict_Values(self->bonesMap);
        }
 }
-
-//------------------doesBoneName_exist----------------------------
-static int doesBoneName_exist( char *name, bArmature * arm )
-{
-       Bone *parent = NULL;
-       Bone *child = NULL;
-
-       for( parent = arm->bonebase.first; parent; parent = parent->next ) {
-               if( !strcmp( name, parent->name ) )
-                       return 1;
-               for( child = parent->childbase.first; child;
-                    child = child->next ) {
-                       if( !strcmp( name, child->name ) )
-                               return 1;
+//------------------ATTRIBUTE IMPLEMENTATION---------------------------
+//------------------TYPE_OBECT IMPLEMENTATION-----------------------
+//------------------------tp_doc
+//The __doc__ string for this object
+static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\
+designed to act as a Py_Bone dictionary.";
+
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_BonesDict_methods[] = {
+       {"items", (PyCFunction) BonesDict_items, METH_NOARGS, 
+               "() - Returns the key:value pairs from the dictionary"},
+       {"keys", (PyCFunction) BonesDict_keys, METH_NOARGS, 
+               "() - Returns the keys the dictionary"},
+       {"values", (PyCFunction) BonesDict_values, METH_NOARGS, 
+               "() - Returns the values from the dictionary"},
+       {NULL, NULL, 0, NULL}
+};
+//-----------------(internal)
+static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
+       Bone *bone = NULL;
+       PyObject *py_bone = NULL;
+
+       for (bone = bones->first; bone; bone = bone->next){
+               py_bone = PyBone_FromBone(bone);
+               if (!py_bone)
+                       return -1;
+
+               if(PyDict_SetItem(dictionary, 
+                       PyString_FromString(bone->name), py_bone) == -1){
+                       return -1;
                }
+               Py_DECREF(py_bone);
+               if (bone->childbase.first) 
+                       BoneMapping_Init(dictionary, &bone->childbase);
        }
        return 0;
 }
-
-//------------------testChildInChildbase--------------------------
-static int testChildInChildbase( Bone * bone, Bone * test )
-{
-       Bone *child;
-       for( child = bone->childbase.first; child; child = child->next ) {
-               if( child == test ) {
-                       return 1;
-               } else {
-                       if( child->childbase.first != NULL ) {
-                               if( testChildInChildbase( child, test ) ) {
-                                       return 1;
-                               }
-                       }
+//-----------------(internal)
+static int EditBoneMapping_Init(PyObject *dictionary, ListBase *editbones){
+       EditBone *editbone = NULL;
+       PyObject *py_editbone = NULL;
+
+       for (editbone = editbones->first; editbone; editbone = editbone->next){
+               py_editbone = PyEditBone_FromEditBone(editbone);
+               if (!py_editbone)
+                       return -1;
+
+               if(PyDict_SetItem(dictionary, 
+                       PyString_FromString(editbone->name), py_editbone) == -1){
+                       return -1;
                }
+               Py_DECREF(py_editbone);
        }
        return 0;
 }
-
-//------------------testBoneInArmature-----------------------------
-static int testBoneInArmature( bArmature * arm, Bone * test )
+//----------------- BonesDict_InitBones
+static int BonesDict_InitBones(BPy_BonesDict *self)
 {
-       Bone *root;
-       for( root = arm->bonebase.first; root; root = root->next ) {
-               if( root == test ) {
-                       return 1;
-               } else {
-                       if( root->childbase.first != NULL ) {
-                               if( testChildInChildbase( root, test ) ) {
-                                       return 1;
-                               }
-                       }
-               }
-       }
-       return 0;
+       PyDict_Clear(self->bonesMap);
+       if (BoneMapping_Init(self->bonesMap, self->bones) == -1)
+               return 0;
+       return 1;
+} 
+//----------------- BonesDict_InitEditBones
+static int BonesDict_InitEditBones(BPy_BonesDict *self)
+{
+       PyDict_Clear(self->editbonesMap);
+       if (EditBoneMapping_Init(self->editbonesMap, &self->editbones) == -1)
+               return 0;
+       return 1;
 }
-
-//-----------------testChildNameInChildbase--------------------------
-static Bone *testChildNameInChildbase( Bone * bone, char *name )
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *BonesDict_repr(BPy_BonesDict *self)
 {
-       Bone *child;
-       Bone *test;
-       for( child = bone->childbase.first; child; child = child->next ) {
-               if( BLI_streq( child->name, name ) ) {
-                       return child;
-               } else {
-                       if( child->childbase.first != NULL ) {
-                               test = testChildNameInChildbase( child, name );
-                               if( test )
-                                       return test;
-                       }
+       char str[4096];
+       PyObject *key, *value;
+       int pos = 0;
+       char *p = str;
+
+       p += sprintf(str, "[Bone Dict: {");
+
+       if (self->editmode_flag){
+               while (PyDict_Next(self->editbonesMap, &pos, &key, &value)) {
+                       p += sprintf(p, "%s : %s, ", PyString_AsString(key), 
+                               PyString_AsString(value->ob_type->tp_repr(value)));
+               }
+       }else{
+               while (PyDict_Next(self->bonesMap, &pos, &key, &value)) {
+                       p += sprintf(p, "%s : %s, ", PyString_AsString(key), 
+                               PyString_AsString(value->ob_type->tp_repr(value)));
                }
        }
-       return NULL;
+       p += sprintf(p, "}]\n");
+       return PyString_FromString(str);
 }
 
-//----------------testBoneNameInArmature----------------------------
-static Bone *testBoneNameInArmature( bArmature * arm, char *name )
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+static void BonesDict_dealloc(BPy_BonesDict * self)
 {
-       Bone *bone;
-       Bone *test;
-       for( bone = arm->bonebase.first; bone; bone = bone->next ) {
-               if( BLI_streq( bone->name, name ) ) {
-                       return bone;    //found it
-               } else {
-                       if( bone->childbase.first != NULL ) {
-                               test = testChildNameInChildbase( bone, name );
-                               if( test )
-                                       return test;
-                       }
+       Py_DECREF(self->bonesMap);
+       Py_DECREF(self->editbonesMap);
+       BLI_freelistN(&self->editbones); 
+       BonesDict_Type.tp_free(self);
+       return;
+}
+//------------------------mp_length
+//This gets the size of the dictionary
+int BonesDict_len(BPy_BonesDict *self)
+{
+       if (self->editmode_flag){
+               return BLI_countlist(&self->editbones);
+       }else{
+               return BLI_countlist(self->bones);
+       }
+}
+//-----------------------mp_subscript
+//This defines getting a bone from the dictionary - x = Bones['key']
+PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
+{ 
+       PyObject *value = NULL;
+
+       if (self->editmode_flag){
+               value = PyDict_GetItem(self->editbonesMap, key);
+       }else{
+               value = PyDict_GetItem(self->bonesMap, key);
+       }
+       if(value == NULL){  /* item not found in dict. throw exception */
+               char buffer[128];
+               char* key_str;
+               key_str = PyString_AsString( key );
+               if( !key_str ){  /* key not a py string */
+                       key_str = "";  /* use empty string for printing */
                }
+  
+               PyOS_snprintf( buffer, sizeof(buffer),
+                                          "bone %s not found", key_str);
+                       
+        return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
        }
-       return NULL;
+       return EXPP_incr_ret(value);
 }
-
-//-------------------BPy_Armature internal methods------------------
-
-//------------------dealloc-----------------------------------------
-static void Armature_dealloc( BPy_Armature * self )
+//-----------------------mp_ass_subscript
+//This does dict assignment - Bones['key'] = value
+int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
 {
-       PyObject_DEL( self );
-}
+       BPy_EditBone *editbone_for_deletion;
+       struct EditBone *editbone = NULL;
+       char *key_str = "";
+
+       if (self->editmode_flag){
+               //Get the key name
+               if(key && PyString_Check(key)){
+                       key_str = PyString_AsString(key);
+               }else{
+                       goto AttributeError;
+               }
+               //parse value for assignment
+               if (value && EditBoneObject_Check(value)){
+                       //create a new editbone
+                       editbone = MEM_callocN(sizeof(EditBone), "eBone");
+                       BLI_strncpy(editbone->name, key_str, 32);
+                       unique_editbone_name(editbone->name);
+                       editbone->dist = ((BPy_EditBone*)value)->dist;
+                       editbone->ease1 = ((BPy_EditBone*)value)->ease1;
+                       editbone->ease2 = ((BPy_EditBone*)value)->ease2;
+                       editbone->flag = ((BPy_EditBone*)value)->flag;
+                       editbone->parent = ((BPy_EditBone*)value)->parent;
+                       editbone->rad_head = ((BPy_EditBone*)value)->rad_head;
+                       editbone->rad_tail = ((BPy_EditBone*)value)->rad_tail;
+                       editbone->roll = ((BPy_EditBone*)value)->roll;
+                       editbone->segments = ((BPy_EditBone*)value)->segments;
+                       editbone->weight = ((BPy_EditBone*)value)->weight;
+                       editbone->xwidth = ((BPy_EditBone*)value)->xwidth;
+                       editbone->zwidth = ((BPy_EditBone*)value)->zwidth;
+                       VECCOPY(editbone->head, ((BPy_EditBone*)value)->head);
+                       VECCOPY(editbone->tail, ((BPy_EditBone*)value)->tail);
+
+                       //set object pointer
+                       ((BPy_EditBone*)value)->editbone = editbone;
+
+                       //fix the bone's head position if flags indicate that it is 'connected'
+                       if (editbone->flag & BONE_CONNECTED){
+                               if(!editbone->parent){
+                                       ((BPy_EditBone*)value)->editbone = NULL;
+                                       MEM_freeN(editbone);
+                                       goto AttributeError3;
+                               }else{
+                                       VECCOPY(editbone->head, editbone->parent->tail);
+                               }
+                       }
 
-//-----------------getattr--------------------------------------------
-static PyObject *Armature_getAttr( BPy_Armature * self, char *name )
-{
-       PyObject *attr = Py_None;
+                       //set in editbonelist
+                       BLI_addtail(&self->editbones, editbone);
 
-       if( strcmp( name, "name" ) == 0 )
-               attr = Armature_getName( self );
-       if( strcmp( name, "bones" ) == 0 )
-               attr = Armature_getBones( self );
-       else if( strcmp( name, "__members__" ) == 0 ) {
-               /* 2 entries */
-               attr = Py_BuildValue( "[s,s]", "name", "bones" );
+                       //set the new editbone in the mapping
+                       if(PyDict_SetItemString(self->editbonesMap, key_str, value) == -1){
+                               ((BPy_EditBone*)value)->editbone = NULL;
+                               BLI_freelinkN(&self->editbones, editbone);
+                               goto RuntimeError;
+                       }
+               }else if(!value){
+                       //they are trying to delete the bone using 'del'
+                       if(PyDict_GetItem(self->editbonesMap, key) != NULL){
+                               /*first kill the datastruct then remove the item from the dict
+                               and wait for GC to pick it up.
+                               We have to delete the datastruct here because the tp_dealloc
+                               doesn't handle it*/
+                               editbone_for_deletion = (BPy_EditBone*)PyDict_GetItem(self->editbonesMap, key);
+                               /*this is ugly but you have to set the parent to NULL for else 
+                               editbones_to_armature will crash looking for this bone*/
+                               for (editbone = self->editbones.first; editbone; editbone = editbone->next){
+                                       if (editbone->parent == editbone_for_deletion->editbone)
+                                               editbone->parent = NULL;
+                                           /*any parent's were connected to this we must remove the flag
+                                           or else the 'root' ball doesn't get draw*/
+                                           if (editbone->flag & BONE_CONNECTED)
+                                                       editbone->flag &= ~BONE_CONNECTED;
+                               }
+                               BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
+                               if(PyDict_DelItem(self->editbonesMap, key) == -1)
+                                       goto RuntimeError;
+                       }else{
+                               goto KeyError;
+                       }
+               }
+               return 0;
+       }else{
+               goto AttributeError2;
        }
 
-       if( !attr )
-               return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
-                                               "couldn't create PyObject" ) );
-
-       if( attr != Py_None )
-               return attr;    /* member attribute found, return it */
-
-       /* not an attribute, search the methods table */
-       return Py_FindMethod( BPy_Armature_methods, ( PyObject * ) self,
-                             name );
+KeyError:
+return EXPP_intError(PyExc_KeyError, "%s%s%s%s", 
+           sBoneDictError,  "The key: ", key_str, " is not present in this dictionary!");
+RuntimeError:
+       return EXPP_intError(PyExc_RuntimeError, "%s%s", 
+               sBoneDictError,  "Unable to access dictionary!");
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sBoneDictBadArgs,  "Expects EditboneType Object");
+AttributeError2:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sBoneDictBadArgs,  "You must call makeEditable() first");
+AttributeError3:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sBoneDictBadArgs,  "The 'connected' flag is set but the bone has no parent!");
 }
-
-//-----------------setattr--------------------------------------------
-static int
-Armature_setAttr( BPy_Armature * self, char *name, PyObject * value )
+//------------------TYPE_OBJECT DEFINITION--------------------------
+//Mapping Protocol
+static PyMappingMethods BonesDict_MapMethods = {
+       (inquiry) BonesDict_len,                                        //mp_length
+       (binaryfunc)BonesDict_GetItem,          //mp_subscript
+       (objobjargproc)BonesDict_SetItem,       //mp_ass_subscript
+};
+//BonesDict TypeObject
+PyTypeObject BonesDict_Type = {
+       PyObject_HEAD_INIT(NULL)                        //tp_head
+       0,                                                                                              //tp_internal
+       "BonesDict",                                                            //tp_name
+       sizeof(BPy_BonesDict),                                  //tp_basicsize
+       0,                                                                                              //tp_itemsize
+       (destructor)BonesDict_dealloc,          //tp_dealloc
+       0,                                                                                              //tp_print
+       0,                                                                                              //tp_getattr
+       0,                                                                                              //tp_setattr
+       0,                                                                                              //tp_compare
+       (reprfunc) BonesDict_repr,                              //tp_repr
+       0,                                                                                              //tp_as_number
+       0,                                                                                              //tp_as_sequence
+       &BonesDict_MapMethods,                          //tp_as_mapping
+       0,                                                                                              //tp_hash
+       0,                                                                                              //tp_call
+       0,                                                                                              //tp_str
+       0,                                                                                              //tp_getattro
+       0,                                                                                              //tp_setattro
+       0,                                                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                                     //tp_flags
+       BPy_BonesDict_doc,                                              //tp_doc
+       0,                                                                                              //tp_traverse
+       0,                                                                                              //tp_clear
+       0,                                                                                              //tp_richcompare
+       0,                                                                                              //tp_weaklistoffset
+       0,                                                                                              //tp_iter
+       0,                                                                                              //tp_iternext
+       BPy_BonesDict_methods,                          //tp_methods
+       0,                                                                                              //tp_members
+       0,                                                                                              //tp_getset
+       0,                                                                                              //tp_base
+       0,                                                                                              //tp_dict
+       0,                                                                                              //tp_descr_get
+       0,                                                                                              //tp_descr_set
+       0,                                                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                                                              //tp_alloc
+       0,                                                                                              //tp_new
+       0,                                                                                              //tp_free
+       0,                                                                                              //tp_is_gc
+       0,                                                                                              //tp_bases
+       0,                                                                                              //tp_mro
+       0,                                                                                              //tp_cache
+       0,                                                                                              //tp_subclasses
+       0,                                                                                              //tp_weaklist
+       0                                                                                               //tp_del
+};
+//-----------------------PyBonesDict_FromPyArmature
+static PyObject *PyBonesDict_FromPyArmature(BPy_Armature *py_armature)
 {
-       PyObject *valtuple;
-       PyObject *error = NULL;
+       BPy_BonesDict *py_BonesDict = NULL;
 
-       valtuple = Py_BuildValue( "(O)", value );       /*the set* functions expect a tuple */
+       //create py object
+       py_BonesDict = (BPy_BonesDict *)BonesDict_Type.tp_alloc(&BonesDict_Type, 0); 
+       if (!py_BonesDict)
+               goto RuntimeError;
 
-       if( !valtuple )
-               return EXPP_ReturnIntError( PyExc_MemoryError,
-                                           "ArmatureSetAttr: couldn't create tuple" );
+       //create internal dictionaries
+       py_BonesDict->bonesMap = PyDict_New();
+       py_BonesDict->editbonesMap = PyDict_New();
+       if (!py_BonesDict->bonesMap || !py_BonesDict->editbonesMap)
+               goto RuntimeError;
 
-       if( strcmp( name, "name" ) == 0 )
-               error = Armature_setName( self, valtuple );
-       else {                  /* Error */
-               Py_DECREF( valtuple );
+       //set listbase pointer
+       py_BonesDict->bones = &py_armature->armature->bonebase;
 
-               /* ... member with the given name was found */
-               return ( EXPP_ReturnIntError
-                        ( PyExc_KeyError, "attribute not found" ) );
-       }
+       //now that everything is setup - init the mappings
+       if (!BonesDict_InitBones(py_BonesDict))
+               goto RuntimeError;
+       if (!BonesDict_InitEditBones(py_BonesDict))
+               goto RuntimeError;
 
-       Py_DECREF( valtuple );
+       //set editmode flag
+       py_BonesDict->editmode_flag = 0; 
 
-       if( error != Py_None )
-               return -1;
+       return (PyObject*)py_BonesDict;
 
-       Py_DECREF( Py_None );   /* was incref'ed by the called Armature_set* function */
-       return 0;               /* normal exit */
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s", 
+               sBoneDictError, "Failed to create class");
 }
 
-//-----------------repr-----------------------------------------------
-static PyObject *Armature_repr( BPy_Armature * self )
-{
-       return PyString_FromFormat( "[Armature \"%s\"]",
-                                   self->armature->id.name + 2 );
-}
+//######################### Armature_Type #############################
+/*This type represents a thin wrapper around bArmature data types
+* internal to blender. It contains the psuedo-dictionary BonesDict
+* as an assistant in manipulating it's own bone collection*/
+//#################################################################
 
-//-----------------compare--------------------------------------------
-static int Armature_compare( BPy_Armature * a, BPy_Armature * b )
+//------------------METHOD IMPLEMENTATION------------------------------
+//------------------------Armature.makeEditable()
+static PyObject *Armature_makeEditable(BPy_Armature *self)
 {
-       bArmature *pa = a->armature, *pb = b->armature;
-       return ( pa == pb ) ? 0 : -1;
+       if (self->armature->flag & ARM_EDITMODE)
+               goto AttributeError;
+
+       make_boneList(&self->Bones->editbones, self->Bones->bones, NULL);
+       if (!BonesDict_InitEditBones(self->Bones))
+               return NULL;
+       self->Bones->editmode_flag = 1;
+       return EXPP_incr_ret(Py_None);
+
+AttributeError:
+       return EXPP_objError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "The armature cannot be placed manually in editmode before you call makeEditable()!");
 }
-
-//-----------------Armature_CreatePyObject----------------------------
-PyObject *Armature_CreatePyObject( struct bArmature * obj )
+//------------------------Armature.update()
+//This is a bit ugly because you need an object link to do this
+static PyObject *Armature_update(BPy_Armature *self)
 {
-       BPy_Armature *blen_armature;
+       Object *obj = NULL;
 
-       blen_armature =
-               ( BPy_Armature * ) PyObject_NEW( BPy_Armature,
-                                                &Armature_Type );
+       for (obj = G.main->object.first; obj; obj = obj->id.next){
+               if (obj->data == self->armature)
+                       break;
+       }
+       if (obj){
+               editbones_to_armature (&self->Bones->editbones, obj);
+               if (!BonesDict_InitBones(self->Bones))
+                       return NULL;
+               self->Bones->editmode_flag = 0;
+               BLI_freelistN(&self->Bones->editbones);
+       }else{
+               goto AttributeError;
 
-       if( blen_armature == NULL ) {
-               return ( NULL );
        }
-       blen_armature->armature = obj;
+       return EXPP_incr_ret(Py_None);
 
-       return ( ( PyObject * ) blen_armature );
+AttributeError:
+       return EXPP_objError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "The armature must be linked to an object before you can save changes!");
 }
-
-//-----------------Armature_CheckPyObject ----------------------------
-int Armature_CheckPyObject( PyObject * py_obj )
+//------------------ATTRIBUTE IMPLEMENTATION---------------------------
+//------------------------Armature.autoIK (getter)
+static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
 {
-       return ( py_obj->ob_type == &Armature_Type );
+       if (self->armature->flag & ARM_AUTO_IK)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
 }
-
-//-----------------Armature_FromPyObject -----------------------------
-struct bArmature *Armature_FromPyObject( PyObject * py_obj )
+//------------------------Armature.autoIK (setter)
+static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
 {
-       BPy_Armature *blen_obj;
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_AUTO_IK;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_AUTO_IK;
+                               return 0;
+                       }
+               }
+       }
+       goto AttributeError;
 
-       blen_obj = ( BPy_Armature * ) py_obj;
-       return ( blen_obj->armature );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
 }
-
-//-----------------Blender Module function prototypes-----------------
-
-//----------------Blender.Armature.New()------------------------------
-static PyObject *M_Armature_New( PyObject * self, PyObject * args )
+//------------------------Armature.layers (getter)
+static PyObject *Armature_getLayers(BPy_Armature *self, void *closure)
 {
-       char *name_str = "ArmatureData";
-       BPy_Armature *py_armature;      /* for Armature Data object wrapper in Python */
-       bArmature *bl_armature; /* for actual Armature Data we create in Blender */
-       char buf[21];
+       int layers, bit = 0, val = 0;
+       PyObject *item = NULL, *laylist = PyList_New( 0 );
 
-       if( !PyArg_ParseTuple( args, "|s", &name_str ) )
-               return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-                                               "expected string or empty argument" ) );
+       if( !laylist )
+               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                       "couldn't create pylist!" );
 
-       bl_armature = add_armature(  ); /* first create in Blender */
+       layers = self->armature->layer;
 
-       if( bl_armature ) {
-               /* return user count to zero because add_armature() inc'd it */
-               bl_armature->id.us = 0;
-               /* now create the wrapper obj in Python */
-               py_armature =
-                       ( BPy_Armature * ) PyObject_NEW( BPy_Armature,
-                                                        &Armature_Type );
-       } else {
-               return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                               "couldn't create Armature Data in Blender" ) );
+       while( bit < 20 ) {
+               val = 1 << bit;
+               if( layers & val ) {
+                       item = Py_BuildValue( "i", bit + 1 );
+                       PyList_Append( laylist, item );
+                       Py_DECREF( item );
+               }
+               bit++;
        }
+       return laylist;
+}
+//------------------------Armature.layer (setter)
+static int Armature_setLayers(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyList_Check(value)){
+                       int layers = 0, len_list = 0;
+                       int val;
+                       PyObject *item = NULL;
+
+                       len_list = PyList_Size(value);
+
+                       if( len_list == 0 )
+                               return EXPP_ReturnIntError( PyExc_AttributeError,
+                                 "list can't be empty, at least one layer must be set" );
+
+                       while( len_list ) {
+                               --len_list;
+                               item = PyList_GetItem( value, len_list );
+                               if( !PyInt_Check( item ) )
+                                       return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                       "list must contain only integer numbers" );
+
+                               val = ( int ) PyInt_AsLong( item );
+                               if( val < 1 || val > 20 )
+                                       return EXPP_ReturnIntError( PyExc_AttributeError,
+                                                 "layer values must be in the range [1, 20]" );
+
+                               layers |= 1 << ( val - 1 );
+                       }
 
-       if( py_armature == NULL )
-               return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
-                                               "couldn't create ArmaturePyObject" ) );
-
-       /* link Python armature wrapper with Blender Armature: */
-       py_armature->armature = bl_armature;
+                       /* update any bases pointing to our object */
+                       self->armature->layer = layers;
 
-       if( strcmp( name_str, "ArmatureData" ) == 0 )
-               return ( PyObject * ) py_armature;
-       else {                  /* user gave us a name for the armature, use it */
-               PyOS_snprintf( buf, sizeof( buf ), "%s", name_str );
-               rename_id( &bl_armature->id, buf );
+                       return 0;
+               }
        }
+       goto AttributeError;
 
-       return ( PyObject * ) py_armature;
+AttributeError:
+       return EXPP_ReturnIntError( PyExc_TypeError,
+                       "expected a list of integers" );
 }
-
-//----------------Blender.Armature.Get()------------------------------
-static PyObject *M_Armature_Get( PyObject * self, PyObject * args )
+//------------------------Armature.mirrorEdit (getter)
+static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
 {
-       char *name = NULL;
-       bArmature *armature_iter;
-       BPy_Armature *wanted_armature;
-
-       if( !PyArg_ParseTuple( args, "|s", &name ) )
-               return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-                                               "expected string argument (or nothing)" ) );
-
-       armature_iter = G.main->armature.first;
-
-       /* Use the name to search for the armature requested. */
-
-       if( name ) {            /* (name) - Search armature by name */
-               wanted_armature = NULL;
-               while( ( armature_iter ) && ( wanted_armature == NULL ) ) {
-                       if( strcmp( name, armature_iter->id.name + 2 ) == 0 ) {
-                               wanted_armature =
-                                       ( BPy_Armature * )
-                                       PyObject_NEW( BPy_Armature,
-                                                     &Armature_Type );
-                               if( wanted_armature )
-                                       wanted_armature->armature =
-                                               armature_iter;
+       if (self->armature->flag & ARM_MIRROR_EDIT)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.mirrorEdit (setter)
+static int Armature_setMirrorEdit(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_MIRROR_EDIT;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_MIRROR_EDIT;
+                               return 0;
                        }
-                       armature_iter = armature_iter->id.next;
                }
+       }
+       goto AttributeError;
 
-               if( wanted_armature == NULL ) { /* Requested Armature doesn't exist */
-                       char error_msg[64];
-                       PyOS_snprintf( error_msg, sizeof( error_msg ),
-                                      "Armature \"%s\" not found", name );
-                       return ( EXPP_ReturnPyObjError
-                                ( PyExc_NameError, error_msg ) );
-               }
-               return ( PyObject * ) wanted_armature;
-       } else {
-               /* Return a list of with armatures in the scene */
-               int index = 0;
-               PyObject *armlist, *pyobj;
-
-               armlist = PyList_New( BLI_countlist( &( G.main->armature ) ) );
-
-               if( armlist == NULL )
-                       return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
-                                                       "couldn't create PyList" ) );
-
-               while( armature_iter ) {
-                       pyobj = Armature_CreatePyObject( armature_iter );
-
-                       if( !pyobj )
-                               return ( EXPP_ReturnPyObjError
-                                        ( PyExc_MemoryError,
-                                          "couldn't create PyString" ) );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.drawType (getter)
+static PyObject *Armature_getDrawType(BPy_Armature *self, void *closure)
+{
+       if (self->armature->drawtype == ARM_OCTA){
+               return EXPP_GetModuleConstant("Blender.Armature", "OCTAHEDRON") ;
+       }else if (self->armature->drawtype == ARM_LINE){
+               return EXPP_GetModuleConstant("Blender.Armature", "STICK") ;
+       }else if (self->armature->drawtype == ARM_B_BONE){
+               return EXPP_GetModuleConstant("Blender.Armature", "BBONE") ;
+       }else if (self->armature->drawtype == ARM_ENVELOPE){
+               return EXPP_GetModuleConstant("Blender.Armature", "ENVELOPE") ;
+       }else{
+               goto RuntimeError;
+       }
 
-                       PyList_SET_ITEM( armlist, index, pyobj );
-                       armature_iter = armature_iter->id.next;
-                       index++;
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
+               sArmatureError, "drawType: ", "Internal failure!");
+}
+//------------------------Armature.drawType (setter)
+static int Armature_setDrawType(BPy_Armature *self, PyObject *value, void *closure)
+{
+       PyObject *val = NULL, *name = NULL;
+       long numeric_value;
+
+       if(value){
+               if(BPy_Constant_Check(value)){
+                       name = PyDict_GetItemString(((BPy_constant*)value)->dict, "name");
+                       if (!STREQ2(PyString_AsString(name), "OCTAHEDRON", "STICK") &&
+                               !STREQ2(PyString_AsString(name), "BBONE", "ENVELOPE"))
+                               goto ValueError;
+                       val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
+                       if (PyInt_Check(val)){
+                               numeric_value = PyInt_AS_LONG(val);
+                               self->armature->drawtype = (int)numeric_value;
+                               return 0;
+                       }
                }
-               return ( armlist );
        }
-}
+       goto AttributeError;
 
-//--------------------------Python BPy_Armature methods---------------
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects module constant");
 
-//---------------------BPy_Armature.getName()-------------------------
-static PyObject *Armature_getName( BPy_Armature * self )
+ValueError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Argument must be the constant OCTAHEDRON, STICK, BBONE, or ENVELOPE");
+}
+//------------------------Armature.ghostStep (getter)
+static PyObject *Armature_getStep(BPy_Armature *self, void *closure)
+{
+       return PyInt_FromLong((long)self->armature->ghostsize);
+}
+//------------------------Armature.ghostStep (setter)
+static int Armature_setStep(BPy_Armature *self, PyObject *value, void *closure)
 {
-       PyObject *attr = PyString_FromString( self->armature->id.name + 2 );
+       long numerical_value;
+
+       if(value){
+               if(PyInt_Check(value)){
+                       numerical_value = PyInt_AS_LONG(value);
+                       if (numerical_value > 20.0f || numerical_value < 1.0f)
+                               goto ValueError;
+                       self->armature->ghostsize = (short)numerical_value;
+                       return 0;
+               }
+       }
+       goto AttributeError;
 
-       if( attr )
-               return attr;
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects Integer");
 
-       return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
-                                       "couldn't get Armature.name attribute" ) );
+ValueError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Argument must fall within 1-20");
 }
-
-//---------------------BPy_Armature.getBones()------------------------
-static PyObject *Armature_getBones( BPy_Armature * self )
+//------------------------Armature.ghost (getter)
+static PyObject *Armature_getGhost(BPy_Armature *self, void *closure)
 {
+       return PyInt_FromLong((long)self->armature->ghostep);
+}
+//------------------------Armature.ghost (setter)
+static int Armature_setGhost(BPy_Armature *self, PyObject *value, void *closure)
+{
+       long numerical_value;
+
+       if(value){
+               if(PyInt_Check(value)){
+                       numerical_value = PyInt_AS_LONG(value);
+                       if (numerical_value > 30.0f || numerical_value < 0.0f)
+                               goto ValueError;
+                       self->armature->ghostep = (short)numerical_value;
+                       return 0;
+               }
+       }
+       goto AttributeError;
 
-       PyObject *listbones = NULL;
-       Bone *parent = NULL;
-
-       listbones = PyList_New( 0 );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects Integer");
 
-       //append root bones
-       for( parent = self->armature->bonebase.first; parent;
-            parent = parent->next ) {
-               PyList_Append( listbones, Bone_CreatePyObject( parent ) );
-               if( parent->childbase.first ) { //has children?
-                       append_childrenToList( parent, listbones );
+ValueError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Argument must fall within 0-30");
+}
+//------------------------Armature.drawNames (getter)
+static PyObject *Armature_getDrawNames(BPy_Armature *self, void *closure)
+{
+       if (self->armature->flag & ARM_DRAWNAMES)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.drawNames (setter)
+static int Armature_setDrawNames(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_DRAWNAMES;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_DRAWNAMES;
+                               return 0;
+                       }
                }
        }
+       goto AttributeError;
 
-       return listbones;
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
 }
-
-//---------------------BPy_Armature.addBone()-------------------------
-static PyObject *Armature_addBone( BPy_Armature * self, PyObject * args )
+//------------------------Armature.drawAxes (getter)
+static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
 {
-       BPy_Bone *py_bone = NULL;
-       float M_boneObjectspace[4][4];
-       float iM_parentRest[4][4];
-       Bone *blen_bone;
-       char *parent_str = "";
-       Bone *parent;
+       if (self->armature->flag & ARM_DRAWAXES)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.drawAxes (setter)
+static int Armature_setDrawAxes(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_DRAWAXES;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_DRAWAXES;
+                               return 0;
+                       }
+               }
+       }
+       goto AttributeError;
 
-       if( !PyArg_ParseTuple( args, "O!", &Bone_Type, &py_bone ) )
-               return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-                                               "expected bone object argument (or nothing)" ) );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.delayDeform (getter)
+static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
+{
+       if (self->armature->flag & ARM_DELAYDEFORM)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.delayDeform (setter)
+static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_DELAYDEFORM;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_DELAYDEFORM;
+                               return 0;
+                       }
+               }
+       }
+       goto AttributeError;
 
-       if( py_bone->bone != NULL )
-               return EXPP_ReturnPyObjError( PyExc_TypeError,
-                                             "this bone has already been linked to an armature" );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.restPosition (getter)
+static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
+{
+       if (self->armature->flag & ARM_RESTPOS)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.restPosition (setter)
+static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->flag |= ARM_RESTPOS;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->flag &= ~ARM_RESTPOS;
+                               return 0;
+                       }
+               }
+       }
+       goto AttributeError;
 
-       //check to see if we can parent this bone if it will be attempted 
-        //otherwise exit
-       if( !BLI_streq( py_bone->parent, parent_str ) ) {       //parenting being attempted
-               //get parent if exists in this armature
-               parent = testBoneNameInArmature( self->armature,
-                                                py_bone->parent );
-               if( !parent ) { //could find the parent's name
-                       return ( EXPP_ReturnPyObjError( PyExc_TypeError,
-                                                       "cannot find parent's name in armature - check to see if name of parent is correct" ) );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.envelopes (getter)
+static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
+{
+       if (self->armature->deformflag & ARM_DEF_ENVELOPE)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.envelopes (setter)
+static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->deformflag |= ARM_DEF_ENVELOPE;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
+                               return 0;
+                       }
                }
-       } else {                //no parent for this bone
-               parent = NULL;
        }
+       goto AttributeError;
 
-       //create a bone struct
-       blen_bone = ( Bone * ) MEM_callocN( sizeof( Bone ), "DefaultBone" );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.vertexGroups (getter)
+static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
+{
+       if (self->armature->deformflag & ARM_DEF_VGROUP)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
+}
+//------------------------Armature.vertexGroups (setter)
+static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
+{
+       if(value){
+               if(PyBool_Check(value)){
+                       if (value == Py_True){
+                               self->armature->deformflag |= ARM_DEF_VGROUP;
+                               return 0;
+                       }else if (value == Py_False){
+                               self->armature->deformflag &= ~ARM_DEF_VGROUP;
+                               return 0;
+                       }
+               }
+       }
+       goto AttributeError;
 
-       //set the bone struct pointer
-       py_bone->bone = blen_bone;
-       //update the bonestruct data from py data
-       if( !updateBoneData( py_bone, parent ) )
-               return EXPP_ReturnPyObjError( PyExc_AttributeError,
-                                             "bone struct empty" );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.name (getter)
+//Gets the name of the armature
+static PyObject *Armature_getName(BPy_Armature *self, void *closure)
+{
+    return PyString_FromString(self->armature->id.name +2); //*new*
+}
+//------------------------Armature.name (setter)
+//Sets the name of the armature
+static int Armature_setName(BPy_Armature *self, PyObject *value, void *closure)
+{
+       char buffer[24];
+       char *name = "";
+
+       if(value){
+               if(PyString_Check(value)){
+                       name = PyString_AsString(value);
+                       PyOS_snprintf(buffer, sizeof(buffer), "%s", name);
+                       rename_id(&self->armature->id, buffer);
+                       return 0; 
+               }
+       }
+       goto AttributeError;
 
-       //make sure the name is unique for this armature
-       unique_BoneName( py_bone->bone->name, self->armature );
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects string");
+}
+//------------------------Armature.bones (getter)
+//Gets the name of the armature
+static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
+{
+    return EXPP_incr_ret((PyObject*)self->Bones);
+}
+//------------------------Armature.bones (setter)
+//Sets the name of the armature
+/*TODO*/
+/*Copy Bones through x = y*/
+static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
+{
+       goto AttributeError;
 
-       //if bone has a parent....      
-       if( py_bone->bone->parent ) {
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureError, "You are not allowed to change the .Bones attribute");
+}
+//------------------TYPE_OBECT IMPLEMENTATION--------------------------
+//------------------------tp_doc
+//The __doc__ string for this object
+static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_Armature_methods[] = {
+       {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
+               "() - Unlocks the ability to modify armature bones"},
+       {"update", (PyCFunction) Armature_update, METH_NOARGS, 
+               "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
+       {NULL, NULL, 0, NULL}
+};
+//------------------------tp_getset
+//This contains methods for attributes that require checking
+static PyGetSetDef BPy_Armature_getset[] = {
+       {"name", (getter)Armature_getName, (setter)Armature_setName, 
+               "The armature's name", NULL},
+       {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
+               "The armature's Bone dictionary", NULL},
+       {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
+               "Enable/Disable vertex group defined deformation", NULL},
+       {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
+               "Enable/Disable bone envelope defined deformation", NULL},
+       {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
+               "Show armature rest position - disables posing", NULL},
+       {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
+               "Don't deform children when manipulating bones in pose mode", NULL},
+       {"drawAxes", (getter)Armature_getDrawAxes, (setter)Armature_setDrawAxes, 
+               "Enable/Disable  drawing  the bone axes", NULL},
+       {"drawNames", (getter)Armature_getDrawNames, (setter)Armature_setDrawNames, 
+               "Enable/Disable  drawing the bone names", NULL},
+       {"ghost", (getter)Armature_getGhost, (setter)Armature_setGhost, 
+               "Draw a number of ghosts around the current frame for current Action", NULL},
+       {"ghostStep", (getter)Armature_getStep, (setter)Armature_setStep, 
+               "The number of frames between ghost instances", NULL},
+       {"drawType", (getter)Armature_getDrawType, (setter)Armature_setDrawType, 
+               "The type of drawing currently applied to the armature", NULL},
+       {"mirrorEdit", (getter)Armature_getMirrorEdit, (setter)Armature_setMirrorEdit, 
+               "Enable/Disable X-axis mirrored editing", NULL},
+       {"autoIK", (getter)Armature_getAutoIK, (setter)Armature_setAutoIK, 
+               "Adds temporal IK chains while grabbing bones", NULL},
+       {"layers", (getter)Armature_getLayers, (setter)Armature_setLayers, 
+               "List of layers for the armature", NULL},
+       {NULL}
+};
+//------------------------tp_new
+//This methods creates a new object (note it does not initialize it - only the building)
+//This can be called through python by myObject.__new__() however, tp_init is not called
+static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+       BPy_Armature *py_armature = NULL;
+       bArmature *bl_armature;
 
-               //then check to see if parent has been added to the armature - bone loop test
-               if( !testBoneInArmature
-                   ( self->armature, py_bone->bone->parent ) )
-                       return ( EXPP_ReturnPyObjError
-                                ( PyExc_TypeError,
-                                  "cannot parent to a bone not yet added to armature!" ) );
+       bl_armature = add_armature();
+       if(bl_armature) {
+               bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
 
-               //add to parent's childbase
-               BLI_addtail( &py_bone->bone->parent->childbase,
-                            py_bone->bone );
+               py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
+               if (py_armature == NULL)
+                       goto RuntimeError;
 
-               //get the worldspace coords for the parent
-               get_objectspace_bone_matrix( py_bone->bone->parent,
-                                            M_boneObjectspace, 0, 0 );
+               py_armature->armature = bl_armature;
 
-               // Invert the parent rest matrix
-               Mat4Invert( iM_parentRest, M_boneObjectspace );
+               //create armature.bones
+               py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+               if (!py_armature->Bones)
+                       goto RuntimeError;
 
-               //transformation of local bone
-               Mat4MulVecfl( iM_parentRest, py_bone->bone->tail );
-               Mat4MulVecfl( iM_parentRest, py_bone->bone->head );
+       } else {
+               goto RuntimeError;
+       }
+       return (PyObject*)py_armature; 
 
-       } else                  //no parent....
-               BLI_addtail( &self->armature->bonebase, py_bone->bone );
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
+               sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
+}
+//------------------------tp_init
+//This methods does initialization of the new object
+//This method will get called in python by 'myObject(argument, keyword=value)'
+//tp_new will be automatically called before this
+static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
+{
+       char buf[21];
+       char *name = "myArmature";
+       static char *kwlist[] = {"name", NULL};
 
-       //rebuild_bone_parent_matrix(py_bone->bone);
+       if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
+               goto AttributeError;
+       }
 
-       //precalc_bonelist_irestmats( &self->armature->bonebase );
-       //precalc_armature_posemats( self->armature );
-       //precalc_bone_defmat( py_bone->bone );
+       //rename the armature if a name is supplied
+       if(!BLI_streq(name, "myArmature")){
+               PyOS_snprintf(buf, sizeof(buf), "%s", name);
+               rename_id(&self->armature->id, buf);
+       }
+       return 0;
 
-       Py_INCREF( Py_None );
-       return Py_None;
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
+               sArmatureBadArgs, " __init__: ", "Expects string(name)");
 }
-
-//---------------------BPy_Armature.setName()-------------------------
-static PyObject *Armature_setName( BPy_Armature * self, PyObject * args )
+//------------------------tp_richcompare
+//This method allows the object to use comparison operators
+//TODO: We need some armature comparisons
+static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op)
 {
-       char *name;
-       char buf[21];
+       return EXPP_incr_ret(Py_None);
+}
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *Armature_repr(BPy_Armature *self)
+{
+       return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
+}
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+///tp_dealloc
+static void Armature_dealloc(BPy_Armature * self)
+{
+       Py_DECREF(self->Bones);
+       Armature_Type.tp_free(self);
+       return;
+}
+//------------------TYPE_OBECT DEFINITION--------------------------
+PyTypeObject Armature_Type = {
+       PyObject_HEAD_INIT(NULL)                //tp_head
+       0,                                                              //tp_internal
+       "Armature",                                             //tp_name
+       sizeof(BPy_Armature),                   //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Armature_dealloc,   //tp_dealloc
+       0,                                                              //tp_print
+       0,                                                              //tp_getattr
+       0,                                                              //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Armature_repr,               //tp_repr
+       0,                                                              //tp_as_number
+       0,                                                              //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       BPy_Armature_doc,                               //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Armature_richcmpr, //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       BPy_Armature_methods,                   //tp_methods
+       0,                                                              //tp_members
+       BPy_Armature_getset,                    //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       (initproc)Armature_init,                //tp_init
+       0,                                                              //tp_alloc
+       (newfunc)Armature_new,                  //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
+};
 
-       if( !PyArg_ParseTuple( args, "s", &name ) )
-               return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-                                               "expected string argument" ) );
+//-------------------MODULE METHODS IMPLEMENTATION------------------------
+//----------------Blender.Armature.Get()
+/* This function will return a Py_Armature when a single string is passed
+* or else it will return a {key:value} dictionary when mutliple strings are passed
+* or it will return a {key:value} dictionary of all armatures when nothing is passed*/
+static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
+{
+       PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
+       char *name = "", buffer[24];
+       int size = 0, i;
+       void *data;
+
+       //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
+       size = PySequence_Length(args);
+       if (size == 1) {
+               seq = PySequence_GetItem(args, 0); //*new*
+               if (!seq)
+                       goto RuntimeError;
+               if(!PyString_Check(seq)){
+                       if (PySequence_Check(seq)) {
+                               size = PySequence_Length(seq);
+                       } else {
+                               Py_DECREF(seq);
+                               goto AttributeError;
+                       }
+               }
+       } else {
+               seq = EXPP_incr_ret(args); //*take ownership*
+       }
+       //'seq' should be a list, empty tuple or string - check list for strings
+       if(!PyString_Check(seq)){
+               for(i = 0; i < size; i++){
+                       item = PySequence_GetItem(seq, i); //*new*
+                       if (!item) {
+                               Py_DECREF(seq);
+                               goto RuntimeError;
+                       }
+                       if(!PyString_Check(item)){
+                               EXPP_decr2(item, seq);
+                               goto AttributeError;
+                       }
+                       Py_DECREF(item);
+               }
+       }
 
-       PyOS_snprintf( buf, sizeof( buf ), "%s", name );
+       //GET ARMATURES
+       if(size != 1){
+               dict = PyDict_New(); //*new*
+               if(!dict){
+                       Py_DECREF(seq);
+                       goto RuntimeError;
+               }
+               if(size == 0){  //GET ALL ARMATURES
+                       data = G.main->armature.first; //get the first data ID from the armature library
+                       while (data){
+                               py_armature = PyArmature_FromArmature(data); //*new*
+                               sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
+                               if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
+                                       EXPP_decr3(seq, dict, py_armature);
+                                       goto RuntimeError;
+                               }
+                               Py_DECREF(py_armature);
+                               data = ((ID*)data)->next;
+                       }
+                       Py_DECREF(seq);
+               }else{  //GET ARMATURE LIST
+                       for (i = 0; i < size; i++) {
+                               item = PySequence_GetItem(seq, i); //*new*
+                               name = PyString_AsString(item);
+                               Py_DECREF(item);
+                               data = find_id("AR", name); //get data from library
+                               if (data != NULL){
+                                       py_armature = PyArmature_FromArmature(data); //*new*
+                                       if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
+                                               EXPP_decr3(seq, dict, py_armature);
+                                               goto RuntimeError;
+                                       }
+                                       Py_DECREF(py_armature);
+                               }else{
+                                       if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
+                                               EXPP_decr2(seq, dict);
+                                               goto RuntimeError;
+                                       }
+                                       Py_DECREF(Py_None);
+                               }
+                       }
+                       Py_DECREF(seq);
+               }
+               return dict;
+       }else{  //GET SINGLE ARMATURE
+               if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
+                       item = PySequence_GetItem(seq, 0); //*new*
+                       name = PyString_AsString(item);
+                       Py_DECREF(item);
+               }else{
+                       name = PyString_AsString(seq);
+               }
+               Py_DECREF(seq);
+               data = find_id("AR", name); //get data from library
+               if (data != NULL){
+                       return PyArmature_FromArmature(data); //*new*
+               }else{
+                       return EXPP_incr_ret(Py_None);
+               }
+       }
 
-       rename_id( &self->armature->id, buf );
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
+               sModuleError, "Get(): ", "Internal Error Ocurred");
 
-       Py_INCREF( Py_None );
-       return Py_None;
+AttributeError:
+       return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
+               sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
 }
 
-//---------------------BPy_Armature.drawAxes()------------------------
-static PyObject *Armature_drawAxes( BPy_Armature * self, PyObject * args )
+//-------------------MODULE METHODS DEFINITION-----------------------------
+static PyObject *M_Armature_Get( PyObject * self, PyObject * args );
+
+static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
+  returns None if not found.\n If 'name' is not specified, it returns a list of all \
+  armatures in the\ncurrent scene.";
+
+struct PyMethodDef M_Armature_methods[] = {
+       {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
+       {NULL, NULL, 0, NULL}
+};
+//------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
+//-----------------(internal)
+//Converts a bArmature to a PyArmature
+PyObject *PyArmature_FromArmature(struct bArmature *armature)
 {
-       int toggle;
+       BPy_Armature *py_armature = NULL;
 
-       if( !PyArg_ParseTuple( args, "i", &toggle ) )
-               return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-                                               "expected 1 or 0 as integer" ) );
+       //create armature type
+       py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
+       if (!py_armature)
+               goto RuntimeError;
+       py_armature->armature = armature;
 
-       if( toggle )
-               self->armature->flag |= ARM_DRAWAXES;
-       else
-               self->armature->flag &= ~ARM_DRAWAXES;
+       //create armature.bones
+       py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+       if (!py_armature->Bones)
+               goto RuntimeError;
 
-       Py_INCREF( Py_None );
-       return Py_None;
-}
+       return (PyObject *) py_armature; 
 
-//---------------------BPy_Armature.drawNames()-------------------------
-static PyObject *Armature_drawNames( BPy_Armature * self, PyObject * args )
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
+               sModuleError, "PyArmature_FromArmature: ", "Internal Error Ocurred");
+}
+//-----------------(internal)
+//Converts a PyArmature to a bArmature
+struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
 {
-       int toggle;
-
-       if( !PyArg_ParseTuple( args, "i", &toggle ) )
-               return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
-                                               "expected 1 or 0 as integer" ) );
+       return (py_armature->armature);
+}
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Armature_Init(void)
+{
+       PyObject *module, *dict;
 
-       if( toggle )
-               self->armature->flag |= ARM_DRAWNAMES;
-       else
-               self->armature->flag &= ~ARM_DRAWNAMES;
+       //Initializes TypeObject.ob_type
+       if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
+               PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0) {
+               return EXPP_incr_ret(Py_None);
+       }
 
-       Py_INCREF( Py_None );
-       return Py_None;
+       //Register the module
+       module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
+               "The Blender Armature module"); 
+
+       //Add TYPEOBJECTS to the module
+       PyModule_AddObject(module, "Armature", 
+               EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
+       PyModule_AddObject(module, "Bone", 
+               EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
+       PyModule_AddObject(module, "Editbone", 
+               EXPP_incr_ret((PyObject *)&EditBone_Type)); //*steals*
+
+       //Add CONSTANTS to the module
+       PyModule_AddObject(module, "CONNECTED", 
+               EXPP_incr_ret(PyConstant_NewInt("CONNECTED", BONE_CONNECTED)));
+       PyModule_AddObject(module, "HINGE", 
+               EXPP_incr_ret(PyConstant_NewInt("HINGE", BONE_HINGE)));
+       PyModule_AddObject(module, "NO_DEFORM", 
+               EXPP_incr_ret(PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM)));
+       PyModule_AddObject(module, "MULTIPLY", 
+               EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV)));
+       PyModule_AddObject(module, "HIDDEN_EDIT", 
+               EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A)));
+       PyModule_AddObject(module, "ROOT_SELECTED", 
+               EXPP_incr_ret(PyConstant_NewInt("ROOT_SELECTED", BONE_ROOTSEL)));
+       PyModule_AddObject(module, "BONE_SELECTED", 
+               EXPP_incr_ret(PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED)));
+       PyModule_AddObject(module, "TIP_SELECTED", 
+               EXPP_incr_ret(PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL)));
+
+       PyModule_AddObject(module, "OCTAHEDRON", 
+               EXPP_incr_ret(PyConstant_NewInt("OCTAHEDRON", ARM_OCTA)));
+       PyModule_AddObject(module, "STICK", 
+               EXPP_incr_ret(PyConstant_NewInt("STICK", ARM_LINE)));
+       PyModule_AddObject(module, "BBONE", 
+               EXPP_incr_ret(PyConstant_NewInt("BBONE", ARM_B_BONE)));
+       PyModule_AddObject(module, "ENVELOPE", 
+               EXPP_incr_ret(PyConstant_NewInt("ENVELOPE", ARM_ENVELOPE)));
+
+       //Add SUBMODULES to the module
+       dict = PyModule_GetDict( module ); //borrowed
+       PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
+
+       return module;
 }