Final merge of HEAD (bf-blender) into the orange branch.
[blender.git] / source / blender / python / api2_2x / Armature.c
index 0abd4e8d777c094fedb3bbab6feba89197401487..28ae3eadcc7ac04cb01e017bfb69b4eafb0442a8 100644 (file)
@@ -1,4 +1,5 @@
-/* 
+/*
+ * $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
- *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
- */
+*/
 
-#include "Armature.h"
+#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 "Bone.h"
+#include "NLA.h"
+#include "gen_utils.h"
+
+#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)
+{
+       if (self->editmode_flag){
+               return PyDict_Items(self->editbonesMap); 
+       }else{
+               return PyDict_Items(self->bonesMap); 
+       }
+}
+//------------------------Armature.bones.keys()
+//Returns a list of keys like dict.keys()
+PyObject* BonesDict_keys(BPy_BonesDict *self)
+{
+       if (self->editmode_flag){
+               return PyDict_Keys(self->editbonesMap);
+       }else{
+               return PyDict_Keys(self->bonesMap);
+       }
+}
+//------------------------Armature.bones.values()
+//Returns a list of values like dict.values()
+PyObject* BonesDict_values(BPy_BonesDict *self)
+{
+       if (self->editmode_flag){
+               return PyDict_Values(self->editbonesMap);
+       }else{
+               return PyDict_Values(self->bonesMap);
+       }
+}
+//------------------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;
+}
+//-----------------(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;
+}
+//----------------- BonesDict_InitBones
+static int BonesDict_InitBones(BPy_BonesDict *self)
+{
+       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;
+}
+//------------------------tp_repr
+//This is the string representation of the object
+static PyObject *BonesDict_repr(BPy_BonesDict *self)
+{
+       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)));
+               }
+       }
+       p += sprintf(p, "}]\n");
+       return PyString_FromString(str);
+}
 
-/*****************************************************************************/
-/* Function:              M_Armature_New                                     */
-/* Python equivalent:     Blender.Armature.New                               */
-/*****************************************************************************/
-static PyObject *M_Armature_New(PyObject *self, PyObject *args,
-                                PyObject *keywords)
-{
-  char        *type_str = "Armature";
-  char        *name_str = "ArmatureData";
-  static char *kwlist[] = {"type_str", "name_str", NULL};
-  C_Armature  *py_armature; /* for Armature Data object wrapper in Python */
-  bArmature   *bl_armature; /* for actual Armature Data we create in Blender */
-  char        buf[21];
-
-  printf ("In Armature_New()\n");
-
-  if (!PyArg_ParseTupleAndKeywords(args, keywords, "|ss", kwlist,
-           &type_str, &name_str))
-    return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-           "expected string(s) or empty argument"));
-
-  bl_armature = add_armature(); /* first create in Blender */
-  if (bl_armature) /* now create the wrapper obj in Python */
-    py_armature = (C_Armature *)PyObject_NEW(C_Armature, &Armature_Type);
-  else
-    return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
-           "couldn't create Armature Data in Blender"));
-
-  if (py_armature == NULL)
-    return (EXPP_ReturnPyObjError (PyExc_MemoryError,
-           "couldn't create Armature Data object"));
-
-  /* link Python armature wrapper with Blender Armature: */
-  py_armature->armature = bl_armature;
-
-  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 (PyObject *)py_armature;
-}
-
-/*****************************************************************************/
-/* Function:              M_Armature_Get                                     */
-/* Python equivalent:     Blender.Armature.Get                               */
-/*****************************************************************************/
-static PyObject *M_Armature_Get(PyObject *self, PyObject *args)
-{
-  char   *name = NULL;
-  bArmature   *armature_iter;
-  C_Armature *wanted_armature;
-
-  printf ("In Armature_Get()\n");
-  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 = (C_Armature *)PyObject_NEW(C_Armature, &Armature_Type);
-  if (wanted_armature) wanted_armature->armature = armature_iter;
-      }
-      
-      armature_iter = armature_iter->id.next;
-    }
-
-    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;
-  }
+//------------------------tp_dealloc
+//This tells how to 'tear-down' our object when ref count hits 0
+static void BonesDict_dealloc(BPy_BonesDict * self)
+{
+       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 */
+               }
   
-  else
-    {
-      /* Return a list of with armatures in the scene */
-      int index = 0;
-      PyObject *armlist, *pyobj;
+               PyOS_snprintf( buffer, sizeof(buffer),
+                                          "bone %s not found", key_str);
+                       
+        return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
+       }
+       return EXPP_incr_ret(value);
+}
+//-----------------------mp_ass_subscript
+//This does dict assignment - Bones['key'] = value
+int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
+{
+       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);
+                               }
+                       }
+
+                       //set in editbonelist
+                       BLI_addtail(&self->editbones, editbone);
+
+                       //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;
+       }
+
+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!");
+}
+//------------------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)
+{
+       BPy_BonesDict *py_BonesDict = NULL;
 
-      armlist = PyList_New (BLI_countlist (&(G.main->armature)));
+       //create py object
+       py_BonesDict = (BPy_BonesDict *)BonesDict_Type.tp_alloc(&BonesDict_Type, 0); 
+       if (!py_BonesDict)
+               goto RuntimeError;
 
-      if (armlist == NULL)
-        return (PythonReturnErrorObject (PyExc_MemoryError,
-                "couldn't create PyList"));
+       //create internal dictionaries
+       py_BonesDict->bonesMap = PyDict_New();
+       py_BonesDict->editbonesMap = PyDict_New();
+       if (!py_BonesDict->bonesMap || !py_BonesDict->editbonesMap)
+               goto RuntimeError;
 
-      while (armature_iter) {
-        pyobj = M_ArmatureCreatePyObject (armature_iter);
+       //set listbase pointer
+       py_BonesDict->bones = &py_armature->armature->bonebase;
 
-        if (!pyobj)
-          return (PythonReturnErrorObject (PyExc_MemoryError,
-                    "couldn't create PyString"));
-  
-        PyList_SET_ITEM (armlist, index, pyobj);
+       //now that everything is setup - init the mappings
+       if (!BonesDict_InitBones(py_BonesDict))
+               goto RuntimeError;
+       if (!BonesDict_InitEditBones(py_BonesDict))
+               goto RuntimeError;
 
-        armature_iter = armature_iter->id.next;
-        index++;
-      }
+       //set editmode flag
+       py_BonesDict->editmode_flag = 0; 
 
-      return (armlist);
-    }
+       return (PyObject*)py_BonesDict;
 
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s", 
+               sBoneDictError, "Failed to create class");
 }
 
-/*****************************************************************************/
-/* Function:              M_Armature_Init                                    */
-/*****************************************************************************/
-PyObject *M_Armature_Init (void)
-{
-  PyObject  *submodule;
-  PyObject  *dict;
-
-  printf ("In M_Armature_Init()\n");
+//######################### 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*/
+//#################################################################
 
-  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", M_Bone_Init());
-
-  return (submodule);
+//------------------METHOD IMPLEMENTATION------------------------------
+//------------------------Armature.makeEditable()
+static PyObject *Armature_makeEditable(BPy_Armature *self)
+{
+       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()!");
 }
-
-/*****************************************************************************/
-/* Python C_Armature methods:                                                */
-/*****************************************************************************/
-static PyObject *Armature_getName(C_Armature *self)
+//------------------------Armature.update()
+//This is a bit ugly because you need an object link to do this
+static PyObject *Armature_update(BPy_Armature *self)
 {
-  PyObject *attr = PyString_FromString(self->armature->id.name+2);
-
-  if (attr) return attr;
-
-  return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
-         "couldn't get Armature.name attribute"));
+       Object *obj = NULL;
+
+       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;
+
+       }
+       return EXPP_incr_ret(Py_None);
+
+AttributeError:
+       return EXPP_objError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "The armature must be linked to an object before you can save changes!");
 }
-
-
-/** Create and return a list of the root bones for this armature. */
-static PyObject *Armature_getBones(C_Armature *self)
+//------------------ATTRIBUTE IMPLEMENTATION---------------------------
+//------------------------Armature.autoIK (getter)
+static PyObject *Armature_getAutoIK(BPy_Armature *self, void *closure)
 {
-  int totbones = 0;
-  PyObject *listbones = NULL;
-  Bone* current = NULL; 
-  int i;
-
-  /* Count the number of bones to create the list */
-  current = self->armature->bonebase.first;
-  for (;current; current=current->next) totbones++;
-
-  /* Create a list with a bone wrapper for each bone */
-  current = self->armature->bonebase.first;
-  listbones = PyList_New(totbones);
-  for (i=0; i<totbones; i++) {
-    /* Wrap and set to corresponding element of the list. */
-    PyList_SetItem(listbones, i, M_BoneCreatePyObject(current) );
-    current = current->next;
-  }
-
-  return listbones;
+       if (self->armature->flag & ARM_AUTO_IK)
+               return EXPP_incr_ret(Py_True);
+       else
+               return EXPP_incr_ret(Py_False);
 }
-
-
-static PyObject *Armature_setName(C_Armature *self, PyObject *args)
+//------------------------Armature.autoIK (setter)
+static int Armature_setAutoIK(BPy_Armature *self, PyObject *value, void *closure)
+{
+       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;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.layers (getter)
+static PyObject *Armature_getLayers(BPy_Armature *self, void *closure)
+{
+       int layers, bit = 0, val = 0;
+       PyObject *item = NULL, *laylist = PyList_New( 0 );
+
+       if( !laylist )
+               return EXPP_ReturnPyObjError( PyExc_MemoryError,
+                       "couldn't create pylist!" );
+
+       layers = self->armature->layer;
+
+       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 );
+                       }
+
+                       /* update any bases pointing to our object */
+                       self->armature->layer = layers;
+
+                       return 0;
+               }
+       }
+       goto AttributeError;
+
+AttributeError:
+       return EXPP_ReturnIntError( PyExc_TypeError,
+                       "expected a list of integers" );
+}
+//------------------------Armature.mirrorEdit (getter)
+static PyObject *Armature_getMirrorEdit(BPy_Armature *self, void *closure)
+{
+       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;
+                       }
+               }
+       }
+       goto AttributeError;
+
+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;
+       }
+
+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;
+                       }
+               }
+       }
+       goto AttributeError;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects module constant");
+
+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)
+{
+       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;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects Integer");
+
+ValueError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Argument must fall within 1-20");
+}
+//------------------------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;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects Integer");
+
+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;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+               sArmatureBadArgs, "Expects True or False");
+}
+//------------------------Armature.drawAxes (getter)
+static PyObject *Armature_getDrawAxes(BPy_Armature *self, void *closure)
+{
+       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;
+
+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)
 {
-  char *name;
-  char buf[21];
+       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;
+
+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;
+
+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;
+                       }
+               }
+       }
+       goto AttributeError;
+
+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;
+
+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;
+
+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 (!PyArg_ParseTuple(args, "s", &name))
-    return (EXPP_ReturnPyObjError (PyExc_AttributeError,
-           "expected string argument"));
-  
-  PyOS_snprintf(buf, sizeof(buf), "%s", name);
+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;
 
-  rename_id(&self->armature->id, buf);
+       bl_armature = add_armature();
+       if(bl_armature) {
+               bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
 
-  Py_INCREF(Py_None);
-  return Py_None;
-}
+               py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
+               if (py_armature == NULL)
+                       goto RuntimeError;
 
-/*
-  static PyObject *Armature_setBones(C_Armature *self, PyObject *args)
-  {
-  // TODO: Implement me!
-  printf("ERROR: Armature_setBones NOT implemented yet!\n");
-  Py_INCREF(Py_None);
-  return Py_None;
-  
-  }
-*/
+               py_armature->armature = bl_armature;
 
-/*****************************************************************************/
-/* Function:    ArmatureDeAlloc                                              */
-/* Description: This is a callback function for the C_Armature type. It is   */
-/*              the destructor function.                                     */
-/*****************************************************************************/
-static void ArmatureDeAlloc (C_Armature *self)
-{
-  PyObject_DEL (self);
-}
-
-/*****************************************************************************/
-/* Function:    ArmatureGetAttr                                              */
-/* Description: This is a callback function for the C_Armature type. It is   */
-/*              the function that accesses C_Armature member variables and   */
-/*              methods.                                                     */
-/*****************************************************************************/
-static PyObject* ArmatureGetAttr (C_Armature *self, char *name)
-{
-  PyObject *attr = Py_None;
-
-  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");
-  }
-
-  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(C_Armature_methods, (PyObject *)self, name);
-}
-
-/*****************************************************************************/
-/* Function:    ArmatureSetAttr                                              */
-/* Description: This is a callback function for the C_Armature type. It is   */
-/*              the function that changes Armature Data members values. If   */
-/*              this data is linked to a Blender Armature, it also gets      */
-/*              updated.                                                     */
-/*****************************************************************************/
-static int ArmatureSetAttr (C_Armature *self, char *name, PyObject *value)
-{
-  PyObject *valtuple; 
-  PyObject *error = NULL;
-
-  valtuple = Py_BuildValue("(O)", value); /*the set* functions expect a tuple*/
-
-  if (!valtuple)
-    return EXPP_ReturnIntError(PyExc_MemoryError,
-             "ArmatureSetAttr: couldn't create tuple");
-
-  if (strcmp (name, "name") == 0)
-    error = Armature_setName (self, valtuple);
-  /*  if (strcmp (name, "bones") == 0)
-      error = Armature_setBones (self, valtuple);*/
-  else { /* Error */
-    Py_DECREF(valtuple);
-  
-    /* ... member with the given name was found */
-    return (EXPP_ReturnIntError (PyExc_KeyError,
-         "attribute not found"));
-  }
+               //create armature.bones
+               py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+               if (!py_armature->Bones)
+                       goto RuntimeError;
 
-  Py_DECREF(valtuple);
-  
-  if (error != Py_None) return -1;
+       } else {
+               goto RuntimeError;
+       }
+       return (PyObject*)py_armature; 
 
-  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%s", 
+               sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
 }
-
-/*****************************************************************************/
-/* Function:    ArmaturePrint                                                */
-/* Description: This is a callback function for the C_Armature type. It      */
-/*              builds a meaninful string to 'print' armature objects.       */
-/*****************************************************************************/
-static int ArmaturePrint(C_Armature *self, FILE *fp, int flags)
-{ 
-  fprintf(fp, "[Armature \"%s\"]", self->armature->id.name+2);
-  return 0;
+//------------------------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};
+
+       if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
+               goto AttributeError;
+       }
+
+       //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;
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
+               sArmatureBadArgs, " __init__: ", "Expects string(name)");
 }
-
-/*****************************************************************************/
-/* Function:    ArmatureRepr                                                 */
-/* Description: This is a callback function for the C_Armature type. It      */
-/*              builds a meaninful string to represent armature objects.     */
-/*****************************************************************************/
-static PyObject *ArmatureRepr (C_Armature *self)
+//------------------------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)
 {
-  return PyString_FromString(self->armature->id.name+2);
+       return EXPP_incr_ret(Py_None);
 }
-
-/*****************************************************************************/
-/* Function:    ArmatureCmp                                                  */
-/* Description: This is a callback function for the C_Armature type. It      */
-/*              compares the two armatures: translate comparison to the      */
-/*              C pointers.                                                  */
-/*****************************************************************************/
-static int ArmatureCmp (C_Armature *a, C_Armature *b)
+//------------------------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
+};
+
+//-------------------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)
 {
-  bArmature *pa = a->armature, *pb = b->armature;
-  return (pa == pb) ? 0:-1;
+       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);
+               }
+       }
+
+       //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);
+               }
+       }
+
+RuntimeError:
+       return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
+               sModuleError, "Get(): ", "Internal Error Ocurred");
+
+AttributeError:
+       return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
+               sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
 }
 
-/*****************************************************************************/
-/* Function:    M_ArmatureCreatePyObject                                     */
-/* Description: This function will create a new BlenArmature from an         */
-/*              existing Armature structure.                                 */
-/*****************************************************************************/
-PyObject* M_ArmatureCreatePyObject (struct bArmature *obj)
+//-------------------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)
 {
-  C_Armature    * blen_armature;
+       BPy_Armature *py_armature = NULL;
 
-  printf ("In M_ArmatureCreatePyObject\n");
+       //create armature type
+       py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
+       if (!py_armature)
+               goto RuntimeError;
+       py_armature->armature = armature;
 
-  blen_armature = (C_Armature*)PyObject_NEW (C_Armature, &Armature_Type);
+       //create armature.bones
+       py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+       if (!py_armature->Bones)
+               goto RuntimeError;
 
-  if (blen_armature == NULL)
-    {
-      return (NULL);
-    }
-  blen_armature->armature = obj;
-  return ((PyObject*)blen_armature);
-}
+       return (PyObject *) py_armature; 
 
-/*****************************************************************************/
-/* Function:    M_ArmatureCheckPyObject                                      */
-/* Description: This function returns true when the given PyObject is of the */
-/*              type Armature. Otherwise it will return false.               */
-/*****************************************************************************/
-int M_ArmatureCheckPyObject (PyObject *py_obj)
+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)
 {
-  return (py_obj->ob_type == &Armature_Type);
+       return (py_armature->armature);
 }
-
-/*****************************************************************************/
-/* Function:    M_ArmatureFromPyObject                                       */
-/* Description: This function returns the Blender armature from the given    */
-/*              PyObject.                                                    */
-/*****************************************************************************/
-struct bArmature* M_ArmatureFromPyObject (PyObject *py_obj)
+//-------------------MODULE INITIALIZATION--------------------------------
+PyObject *Armature_Init(void)
 {
-  C_Armature    * blen_obj;
-
-  blen_obj = (C_Armature*)py_obj;
-  return (blen_obj->armature);
+       PyObject *module, *dict;
+
+       //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);
+       }
+
+       //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;
 }