* adds deformation properties to armatureType
[blender.git] / source / blender / python / api2_2x / Armature.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * ***** END GPL/BL DUAL LICENSE BLOCK *****
27 */
28
29 #include "Armature.h" //This must come first
30
31 #include "BKE_main.h"
32 #include "BKE_global.h"
33 #include "BKE_armature.h"
34 #include "BKE_library.h"
35 #include "BKE_depsgraph.h"
36 #include "BKE_utildefines.h"
37 #include "BLI_blenlib.h"
38 #include "BLI_arithb.h"
39 #include "MEM_guardedalloc.h"
40 #include "Bone.h"
41 #include "NLA.h"
42 #include "gen_utils.h"
43
44 #include "DNA_object_types.h" //This must come before BIF_editarmature.h...
45 #include "BIF_editarmature.h"
46
47 //------------------UNDECLARED EXTERNAL PROTOTYPES--------------------
48 //These are evil 'extern' declarations for functions with no anywhere
49 extern void free_editArmature(void);
50 extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
51 extern void editbones_to_armature (ListBase *list, Object *ob, bArmature *armature);
52
53 //------------------------ERROR CODES---------------------------------
54 //This is here just to make me happy and to have more consistant error strings :)
55 static const char sBoneDictError[] = "ArmatureType.bones - Error: ";
56 static const char sBoneDictBadArgs[] = "ArmatureType.bones - Bad Arguments: ";
57 static const char sArmatureError[] = "ArmatureType - Error: ";
58 static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: ";
59 static const char sModuleError[] = "Blender.Armature - Error: ";
60 static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
61
62 //################## BonesDict_Type (internal) ########################
63 /*This is an internal psuedo-dictionary type that allows for manipulation
64 * of bones inside of an armature. It is a subobject of armature.
65 * i.e. Armature.bones['key']*/
66 //#####################################################################
67
68 //------------------METHOD IMPLEMENTATIONS-----------------------------
69 //------------------------Armature.bones.items()
70 //Returns a list of key:value pairs like dict.items()
71 PyObject* BonesDict_items(BPy_BonesDict *self)
72 {
73         if (self->editmode_flag){
74                 return PyDict_Items(self->editBoneDict); 
75         }else{
76                 return PyDict_Items(self->dict); 
77         }
78 }
79 //------------------------Armature.bones.keys()
80 //Returns a list of keys like dict.keys()
81 PyObject* BonesDict_keys(BPy_BonesDict *self)
82 {
83         if (self->editmode_flag){
84                 return PyDict_Keys(self->editBoneDict);
85         }else{
86                 return PyDict_Keys(self->dict);
87         }
88 }
89 //------------------------Armature.bones.values()
90 //Returns a list of values like dict.values()
91 PyObject* BonesDict_values(BPy_BonesDict *self)
92 {
93         if (self->editmode_flag){
94                 return PyDict_Values(self->editBoneDict);
95         }else{
96                 return PyDict_Values(self->dict);
97         }
98 }
99 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
100 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
101 //------------------------tp_doc
102 //The __doc__ string for this object
103 static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\
104 designed to act as a Py_Bone dictionary.";
105
106 //------------------------tp_methods
107 //This contains a list of all methods the object contains
108 static PyMethodDef BPy_BonesDict_methods[] = {
109         {"items", (PyCFunction) BonesDict_items, METH_NOARGS, 
110                 "() - Returns the key:value pairs from the dictionary"},
111         {"keys", (PyCFunction) BonesDict_keys, METH_NOARGS, 
112                 "() - Returns the keys the dictionary"},
113         {"values", (PyCFunction) BonesDict_values, METH_NOARGS, 
114                 "() - Returns the values from the dictionary"},
115         {NULL}
116 };
117
118 //------------------------tp_new
119 //This methods creates a new object (note it does not initialize it - only the building)
120 static PyObject *BonesDict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
121 {
122         BPy_BonesDict *py_BonesDict = NULL;
123
124         py_BonesDict = (BPy_BonesDict*)type->tp_alloc(type, 0); 
125         if (!py_BonesDict)
126                 goto RuntimeError;
127
128         py_BonesDict->dict = PyDict_New();
129         if(!py_BonesDict->dict)
130                 goto RuntimeError;
131
132         py_BonesDict->editBoneDict = PyDict_New();
133         if (py_BonesDict->editBoneDict == NULL)
134                 goto RuntimeError;
135
136         py_BonesDict->editmode_flag = 0;
137
138         return (PyObject*)py_BonesDict;
139
140 RuntimeError:
141         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
142                 sBoneDictError, "Failed to create dictionary!");
143 }
144 //------------------------tp_repr
145 //This is the string representation of the object
146 static PyObject *BonesDict_repr(BPy_BonesDict *self)
147 {
148         char buffer[128], str[4096];
149         PyObject *key, *value;
150         int pos = 0;
151
152         BLI_strncpy(str,"",4096);
153         sprintf(buffer, "[Bone Dict: {");
154         strcat(str,buffer);
155         if (self->editmode_flag){
156                 while (PyDict_Next(self->editBoneDict, &pos, &key, &value)) {
157                         sprintf(buffer, "%s : %s, ", PyString_AsString(key), 
158                                 PyString_AsString(value->ob_type->tp_repr(value)));
159                         strcat(str,buffer);
160                 }
161         }else{
162                 while (PyDict_Next(self->dict, &pos, &key, &value)) {
163                         sprintf(buffer, "%s : %s, ", PyString_AsString(key), 
164                                 PyString_AsString(value->ob_type->tp_repr(value)));
165                         strcat(str,buffer);
166                 }
167         }
168         sprintf(buffer, "}]\n");
169         strcat(str,buffer);
170         return PyString_FromString(str);
171 }
172
173 //------------------------tp_dealloc
174 //This tells how to 'tear-down' our object when ref count hits 0
175 static void BonesDict_dealloc(BPy_BonesDict * self)
176 {
177         Py_DECREF(self->dict);
178         Py_DECREF(self->editBoneDict);
179         ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
180         return;
181 }
182 //------------------------mp_length
183 //This gets the size of the dictionary
184 int BonesDict_len(BPy_BonesDict *self)
185 {
186         if (self->editmode_flag){
187                 return PyDict_Size(self->editBoneDict);
188         }else{
189                 return PyDict_Size(self->dict);
190         }
191 }
192 //-----------------------mp_subscript
193 //This defines getting a bone from the dictionary - x = Bones['key']
194 PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
195
196         PyObject *value = NULL;
197
198         if (self->editmode_flag){
199                 value = PyDict_GetItem(self->editBoneDict, key);
200         }else{
201                 value = PyDict_GetItem(self->dict, key);
202         }
203         if(value == NULL){
204         return EXPP_incr_ret(Py_None);
205         }
206         return EXPP_incr_ret(value);
207 }
208 //-----------------------mp_ass_subscript
209 //This does dict assignment - Bones['key'] = value
210 int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
211 {
212         char *key_str = "", *name = "", *misc = "";
213         static char *kwlist[] = {"name", "misc", NULL};
214
215         //Get the key name
216         if(key && PyString_Check(key)){
217                 key_str = PyString_AsString(key);
218         }else{
219                 goto AttributeError;
220         }
221
222         //Parse the value for assignment
223         if(value && PyDict_Check(value)){
224                 if(!PyArg_ParseTupleAndKeywords(Py_BuildValue("()"), value, "|ss", kwlist, &name, &misc)){
225                         goto AttributeError;
226                 }
227         }else{
228                 goto AttributeError;
229         }
230         return 0;
231
232 AttributeError:
233         return EXPP_intError(PyExc_AttributeError, "%s%s", 
234                 sBoneDictBadArgs,  "Expects (optional) name='string', misc='string'");
235 }
236 //------------------TYPE_OBECT DEFINITION--------------------------
237 //Mapping Protocol
238 static PyMappingMethods BonesDict_MapMethods = {
239         (inquiry) BonesDict_len,                                        //mp_length
240         (binaryfunc)BonesDict_GetItem,          //mp_subscript
241         (objobjargproc)BonesDict_SetItem,       //mp_ass_subscript
242 };
243 //BonesDict TypeObject
244 PyTypeObject BonesDict_Type = {
245         PyObject_HEAD_INIT(NULL)                //tp_head
246         0,                                                                                              //tp_internal
247         "BonesDict",                                                            //tp_name
248         sizeof(BPy_BonesDict),                          //tp_basicsize
249         0,                                                                                              //tp_itemsize
250         (destructor)BonesDict_dealloc,  //tp_dealloc
251         0,                                                                                              //tp_print
252         0,                                                                                              //tp_getattr
253         0,                                                                                              //tp_setattr
254         0,                                                                                              //tp_compare
255         (reprfunc) BonesDict_repr,                      //tp_repr
256         0,                                                                                              //tp_as_number
257         0,                                                                                              //tp_as_sequence
258         &BonesDict_MapMethods,                  //tp_as_mapping
259         0,                                                                                              //tp_hash
260         0,                                                                                              //tp_call
261         0,                                                                                              //tp_str
262         0,                                                                                              //tp_getattro
263         0,                                                                                              //tp_setattro
264         0,                                                                                              //tp_as_buffer
265         Py_TPFLAGS_DEFAULT,                     //tp_flags
266         BPy_BonesDict_doc,                                      //tp_doc
267         0,                                                                                              //tp_traverse
268         0,                                                                                              //tp_clear
269         0,                                                                                              //tp_richcompare
270         0,                                                                                              //tp_weaklistoffset
271         0,                                                                                              //tp_iter
272         0,                                                                                              //tp_iternext
273         BPy_BonesDict_methods,                  //tp_methods
274         0,                                                                                              //tp_members
275         0,                                                                                              //tp_getset
276         0,                                                                                              //tp_base
277         0,                                                                                              //tp_dict
278         0,                                                                                              //tp_descr_get
279         0,                                                                                              //tp_descr_set
280         0,                                                                                              //tp_dictoffset
281         0,                                                                                              //tp_init
282         0,                                                                                              //tp_alloc
283         (newfunc)BonesDict_new,                 //tp_new
284         0,                                                                                              //tp_free
285         0,                                                                                              //tp_is_gc
286         0,                                                                                              //tp_bases
287         0,                                                                                              //tp_mro
288         0,                                                                                              //tp_cache
289         0,                                                                                              //tp_subclasses
290         0,                                                                                              //tp_weaklist
291         0                                                                                               //tp_del
292 };
293 //-----------------(internal)
294 static int BonesDict_Init(PyObject *dictionary, ListBase *bones){
295         Bone *bone = NULL;
296         PyObject *py_bone = NULL;
297
298         for (bone = bones->first; bone; bone = bone->next){
299                 py_bone = PyBone_FromBone(bone);
300                 if (py_bone == NULL)
301                         return -1;
302
303                 if(PyDict_SetItem(dictionary, PyString_FromString(bone->name), py_bone) == -1){
304                         goto RuntimeError;
305                 }
306                 if (bone->childbase.first) 
307                         BonesDict_Init(dictionary, &bone->childbase);
308         }
309         return 0;
310
311 RuntimeError:
312         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
313                 sBoneDictError, "Internal error trying to wrap blender bones!");
314 }
315
316 //######################### Armature_Type #############################
317 /*This type represents a thin wrapper around bArmature data types
318 * internal to blender. It contains the psuedo-dictionary BonesDict
319 * as an assistant in manipulating it's own bone collection*/
320 //#####################################################################
321
322 //------------------METHOD IMPLEMENTATION------------------------------
323 //This is a help function for Armature_makeEditable
324 static int PyArmature_InitEditBoneDict(PyObject *dictionary, ListBase *branch)
325 {
326         struct Bone *bone = NULL;
327         PyObject *args, *py_editBone = NULL, *py_bone = NULL;
328
329         for (bone = branch->first; bone; bone = bone->next){
330
331                 //create a new editbone based on the bone data
332                 py_bone = PyBone_FromBone(bone); //new
333                 if (py_bone == NULL)
334                         goto RuntimeError;
335
336                 args = Py_BuildValue("(O)",py_bone); //new
337
338                 py_editBone = EditBone_Type.tp_new(&EditBone_Type, args, NULL); //new
339                 if (py_editBone == NULL) 
340                         goto RuntimeError;
341
342                 //add the new editbone to the dictionary
343                 if (PyDict_SetItemString(dictionary, bone->name, py_editBone) == -1) 
344                         goto RuntimeError;
345
346                 if(bone->childbase.first){
347                         PyArmature_InitEditBoneDict(dictionary, &bone->childbase);
348                 }
349         }
350         return 0;
351
352 RuntimeError:
353         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
354                 sArmatureError, "Internal error trying to construct an edit armature!");
355
356 }
357 //------------------------Armature.makeEditable()
358 static PyObject *Armature_makeEditable(BPy_Armature *self)
359 {
360         if (PyArmature_InitEditBoneDict(((BPy_BonesDict*)self->Bones)->editBoneDict, 
361                 &self->armature->bonebase) == -1){
362                 return NULL;    //error already set
363         }
364         ((BPy_BonesDict*)self->Bones)->editmode_flag = 1;
365         return EXPP_incr_ret(Py_None);
366 }
367
368 static void PyArmature_FixRolls(ListBase *branch, PyObject *dictionary)
369 {
370         float premat[3][3],postmat[3][3];
371         float difmat[3][3],imat[3][3], delta[3];
372         BPy_EditBone *py_editBone = NULL;
373         struct Bone *bone = NULL;
374         int keyCheck = -1;
375
376         for (bone = branch->first; bone; bone = bone->next){
377
378                 where_is_armature_bone(bone, bone->parent);     //set bone_mat, arm_mat, length, etc.
379
380                 keyCheck = PySequence_Contains(dictionary, PyString_FromString(bone->name));
381                 if (keyCheck == 1){
382
383                         py_editBone = (BPy_EditBone*)PyDict_GetItem(dictionary, 
384                                 PyString_FromString(bone->name)); //borrowed
385                         VecSubf (delta, py_editBone->tail, py_editBone->head);
386                         vec_roll_to_mat3(delta, py_editBone->roll, premat); //pre-matrix
387                         Mat3CpyMat4(postmat, bone->arm_mat); //post-matrix
388                         Mat3Inv(imat, premat);
389                         Mat3MulMat3(difmat, imat, postmat);
390
391                         bone->roll = (float)-atan(difmat[2][0]/difmat[2][2]); //YEA!!
392                         if (difmat[0][0]<0.0){
393                                 bone->roll += (float)M_PI;
394                         }
395
396                         where_is_armature_bone(bone, bone->parent); //gotta do it again...
397                 }else if (keyCheck == 0){
398                         //oops we couldn't find it
399                 }else{
400                         //error
401                 }
402                 PyArmature_FixRolls (&bone->childbase, dictionary);
403         }
404 }
405 //------------------------(internal)EditBoneDict_CheckForKey
406 static BPy_EditBone *EditBoneDict_CheckForKey(BPy_BonesDict *dictionary, char *name)
407 {
408         BPy_EditBone *editbone; 
409         PyObject *value, *key;
410         int pos = 0;
411
412         while (PyDict_Next(dictionary->editBoneDict, &pos, &key, &value)) {
413                 editbone = (BPy_EditBone *)value;
414                 if (STREQ(editbone->name, name)){
415                         Py_INCREF(editbone);
416                         return editbone;
417                 }
418         }
419         return NULL;
420 }
421 //------------------------Armature.saveChanges()
422 static PyObject *Armature_saveChanges(BPy_Armature *self)
423 {
424         float M_boneRest[3][3], M_parentRest[3][3];
425         float iM_parentRest[3][3], delta[3];
426         BPy_EditBone *parent = NULL, *editbone = NULL;
427         struct Bone *bone = NULL;
428         struct Object *obj = NULL;
429         PyObject *key, *value;
430         int pos = 0;
431
432         //empty armature of old bones
433         free_bones(self->armature);
434
435         //create a new set based on the editbones
436         while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, &pos, &key, &value)) {
437
438                 editbone = (BPy_EditBone*)value;
439                 bone = MEM_callocN (sizeof(Bone), "bone");      
440                 editbone->temp = bone;  //save temp pointer
441
442                 strcpy (bone->name, editbone->name);
443                 memcpy (bone->head, editbone->head, sizeof(float)*3);
444                 memcpy (bone->tail, editbone->tail, sizeof(float)*3);
445                 bone->flag= editbone->flag;
446                 bone->roll = 0.0f; //is fixed later
447                 bone->weight = editbone->weight;
448                 bone->dist = editbone->dist;
449                 bone->xwidth = editbone->xwidth;
450                 bone->zwidth = editbone->zwidth;
451                 bone->ease1= editbone->ease1;
452                 bone->ease2= editbone->ease2;
453                 bone->rad_head= editbone->rad_head;
454                 bone->rad_tail= editbone->rad_tail;
455                 bone->segments= editbone->segments;
456                 bone->boneclass = 0;
457         }
458
459         pos = 0;
460         //place bones in their correct heirarchy
461         while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, 
462                 &pos, &key, &value)) {
463
464                 editbone = (BPy_EditBone*)value;
465                 bone = editbone->temp; //get bone pointer
466
467                 if (!STREQ(editbone->parent, "")){
468                         parent = EditBoneDict_CheckForKey((BPy_BonesDict*)self->Bones, editbone->parent);
469                         if(parent != NULL){
470
471                                 //parent found in dictionary
472                                 bone->parent = parent->temp;
473                                 BLI_addtail (&parent->temp->childbase, bone);
474                                 //Parenting calculations 
475                                 VecSubf (delta, parent->tail, parent->head);
476                                 vec_roll_to_mat3(delta, parent->roll, M_parentRest); //M_parentRest = parent matrix
477                                 VecSubf (delta, editbone->tail, editbone->head);
478                                 vec_roll_to_mat3(delta, editbone->roll, M_boneRest);  //M_boneRest = bone matrix
479                                 Mat3Inv(iM_parentRest, M_parentRest); //iM_parentRest = 1/parent matrix
480                                 //get head/tail
481                                 VecSubf (bone->head, editbone->head, parent->tail);
482                                 VecSubf (bone->tail, editbone->tail, parent->tail);
483                                 //put them in parentspace
484                                 Mat3MulVecfl(iM_parentRest, bone->head);
485                                 Mat3MulVecfl(iM_parentRest, bone->tail);
486
487                                 Py_DECREF(parent);
488                         }else{
489                                 //was not found - most likely parent was deleted
490                                 parent = NULL;
491                                 BLI_addtail (&self->armature->bonebase, bone);
492                         }
493                 }else{
494                         BLI_addtail (&self->armature->bonebase, bone);
495                 }
496         }
497         //fix rolls and generate matrices
498         PyArmature_FixRolls(&self->armature->bonebase, 
499                 ((BPy_BonesDict*)self->Bones)->editBoneDict);
500
501         //update linked objects
502         for(obj = G.main->object.first; obj; obj = obj->id.next) {
503                 if(obj->data == self->armature){
504                         armature_rebuild_pose(obj, self->armature);
505                 }
506         }
507         DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
508
509         //clear the editbone dictionary and set edit flag
510         PyDict_Clear(((BPy_BonesDict*)self->Bones)->editBoneDict);
511         ((BPy_BonesDict*)self->Bones)->editmode_flag = 0;
512
513         //rebuild py_bones
514         PyDict_Clear(((BPy_BonesDict*)self->Bones)->dict);
515         if (BonesDict_Init(((BPy_BonesDict*)self->Bones)->dict, 
516                 &self->armature->bonebase) == -1)
517                 return NULL; //error string already set
518
519         return EXPP_incr_ret(Py_None);
520 }
521 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
522 //------------------------Armature.delayDeform (getter)
523 static PyObject *Armature_getDelayDeform(BPy_Armature *self, void *closure)
524 {
525         if (self->armature->flag & ARM_DELAYDEFORM)
526                 Py_RETURN_TRUE;
527         else
528                 Py_RETURN_FALSE;
529 }
530 //------------------------Armature.delayDeform (setter)
531 static int Armature_setDelayDeform(BPy_Armature *self, PyObject *value, void *closure)
532 {
533         if(value){
534                 if(PyBool_Check(value)){
535                         if (value == Py_True){
536                                 self->armature->flag |= ARM_DELAYDEFORM;
537                                 return 0;
538                         }else if (value == Py_False){
539                                 self->armature->flag &= ~ARM_DELAYDEFORM;
540                                 return 0;
541                         }
542                 }
543         }
544         goto AttributeError;
545
546 AttributeError:
547         return EXPP_intError(PyExc_AttributeError, "%s%s", 
548                 sArmatureBadArgs, "Expects True or False");
549 }
550 //------------------------Armature.restPosition (getter)
551 static PyObject *Armature_getRestPosition(BPy_Armature *self, void *closure)
552 {
553         if (self->armature->flag & ARM_RESTPOS)
554                 Py_RETURN_TRUE;
555         else
556                 Py_RETURN_FALSE;
557 }
558 //------------------------Armature.restPosition (setter)
559 static int Armature_setRestPosition(BPy_Armature *self, PyObject *value, void *closure)
560 {
561         if(value){
562                 if(PyBool_Check(value)){
563                         if (value == Py_True){
564                                 self->armature->flag |= ARM_RESTPOS;
565                                 return 0;
566                         }else if (value == Py_False){
567                                 self->armature->flag &= ~ARM_RESTPOS;
568                                 return 0;
569                         }
570                 }
571         }
572         goto AttributeError;
573
574 AttributeError:
575         return EXPP_intError(PyExc_AttributeError, "%s%s", 
576                 sArmatureBadArgs, "Expects True or False");
577 }
578 //------------------------Armature.envelopes (getter)
579 static PyObject *Armature_getEnvelopes(BPy_Armature *self, void *closure)
580 {
581         if (self->armature->deformflag & ARM_DEF_ENVELOPE)
582                 Py_RETURN_TRUE;
583         else
584                 Py_RETURN_FALSE;
585 }
586 //------------------------Armature.envelopes (setter)
587 static int Armature_setEnvelopes(BPy_Armature *self, PyObject *value, void *closure)
588 {
589         if(value){
590                 if(PyBool_Check(value)){
591                         if (value == Py_True){
592                                 self->armature->deformflag |= ARM_DEF_ENVELOPE;
593                                 return 0;
594                         }else if (value == Py_False){
595                                 self->armature->deformflag &= ~ARM_DEF_ENVELOPE;
596                                 return 0;
597                         }
598                 }
599         }
600         goto AttributeError;
601
602 AttributeError:
603         return EXPP_intError(PyExc_AttributeError, "%s%s", 
604                 sArmatureBadArgs, "Expects True or False");
605 }
606 //------------------------Armature.vertexGroups (getter)
607 static PyObject *Armature_getVertexGroups(BPy_Armature *self, void *closure)
608 {
609         if (self->armature->deformflag & ARM_DEF_VGROUP)
610                 Py_RETURN_TRUE;
611         else
612                 Py_RETURN_FALSE;
613 }
614 //------------------------Armature.vertexGroups (setter)
615 static int Armature_setVertexGroups(BPy_Armature *self, PyObject *value, void *closure)
616 {
617         if(value){
618                 if(PyBool_Check(value)){
619                         if (value == Py_True){
620                                 self->armature->deformflag |= ARM_DEF_VGROUP;
621                                 return 0;
622                         }else if (value == Py_False){
623                                 self->armature->deformflag &= ~ARM_DEF_VGROUP;
624                                 return 0;
625                         }
626                 }
627         }
628         goto AttributeError;
629
630 AttributeError:
631         return EXPP_intError(PyExc_AttributeError, "%s%s", 
632                 sArmatureBadArgs, "Expects True or False");
633 }
634 //------------------------Armature.name (getter)
635 //Gets the name of the armature
636 static PyObject *Armature_getName(BPy_Armature *self, void *closure)
637 {
638     return PyString_FromString(self->armature->id.name +2); //*new*
639 }
640 //------------------------Armature.name (setter)
641 //Sets the name of the armature
642 static int Armature_setName(BPy_Armature *self, PyObject *value, void *closure)
643 {
644         char buffer[24];
645         char *name = "";
646
647         if(value){
648                 if(PyString_Check(value)){
649                         name = PyString_AsString(value);
650                         PyOS_snprintf(buffer, sizeof(buffer), "%s", name);
651                         rename_id(&self->armature->id, buffer);
652                         return 0; 
653                 }
654         }
655         goto AttributeError;
656
657 AttributeError:
658         return EXPP_intError(PyExc_AttributeError, "%s%s", 
659                 sArmatureBadArgs, "Expects string");
660 }
661 //------------------------Armature.bones (getter)
662 //Gets the name of the armature
663 static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
664 {
665     return EXPP_incr_ret(self->Bones);
666 }
667 //------------------------Armature.bones (setter)
668 //Sets the name of the armature
669 /*TODO*/
670 /*Copy Bones through x = y*/
671 static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure)
672 {
673         goto AttributeError;
674
675 AttributeError:
676         return EXPP_intError(PyExc_AttributeError, "%s%s", 
677                 sArmatureError, "You are not allowed to change the .Bones attribute");
678 }
679 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
680 //------------------------tp_doc
681 //The __doc__ string for this object
682 static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
683
684 //------------------------tp_methods
685 //This contains a list of all methods the object contains
686 static PyMethodDef BPy_Armature_methods[] = {
687         {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, 
688                 "() - Unlocks the ability to modify armature bones"},
689         {"saveChanges", (PyCFunction) Armature_saveChanges, METH_NOARGS, 
690                 "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
691         {NULL}
692 };
693
694 //------------------------tp_getset
695 //This contains methods for attributes that require checking
696 static PyGetSetDef BPy_Armature_getset[] = {
697         {"name", (getter)Armature_getName, (setter)Armature_setName, 
698                 "The armature's name", NULL},
699         {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, 
700                 "The armature's Bone dictionary", NULL},
701         {"vertexGroups", (getter)Armature_getVertexGroups, (setter)Armature_setVertexGroups, 
702                 "Enable/Disable vertex group defined deformation", NULL},
703         {"envelopes", (getter)Armature_getEnvelopes, (setter)Armature_setEnvelopes, 
704                 "Enable/Disable bone envelope defined deformation", NULL},
705         {"restPosition", (getter)Armature_getRestPosition, (setter)Armature_setRestPosition, 
706                 "Show armature rest position - disables posing", NULL},
707         {"delayDeform", (getter)Armature_getDelayDeform, (setter)Armature_setDelayDeform, 
708                 "Don't deform children when manipulating bones in pose mode", NULL},
709         {NULL}
710 };
711 //------------------------tp_new
712 //This methods creates a new object (note it does not initialize it - only the building)
713 //This can be called through python by myObject.__new__() however, tp_init is not called
714 static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
715 {
716         BPy_Armature *py_armature = NULL;
717         bArmature *bl_armature;
718         int success;
719
720         bl_armature = add_armature();
721         if(bl_armature) {
722                 bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it 
723
724                 py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new*
725                 if (py_armature == NULL)
726                         goto RuntimeError;
727
728                 py_armature->armature = bl_armature;
729
730                 py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL);
731                 if (py_armature->Bones == NULL)
732                         goto RuntimeError;
733
734                 success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &bl_armature->bonebase);
735                 if (success == -1)
736                         return NULL; //error string already set
737         } else {
738                 goto RuntimeError;
739         }
740         return (PyObject*)py_armature; 
741
742 RuntimeError:
743         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
744                 sArmatureError, " __new__: ", "couldn't create Armature Data in Blender");
745 }
746 //------------------------tp_init
747 //This methods does initialization of the new object
748 //This method will get called in python by 'myObject(argument, keyword=value)'
749 //tp_new will be automatically called before this
750 static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
751 {
752         char buf[21];
753         char *name = "myArmature";
754         static char *kwlist[] = {"name", NULL};
755
756         if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){
757                 goto AttributeError;
758         }
759
760         //rename the armature if a name is supplied
761         if(!BLI_streq(name, "myArmature")){
762                 PyOS_snprintf(buf, sizeof(buf), "%s", name);
763                 rename_id(&self->armature->id, buf);
764         }
765
766         return 0;
767
768 AttributeError:
769         return EXPP_intError(PyExc_AttributeError, "%s%s%s", 
770                 sArmatureBadArgs, " __init__: ", "Expects string(name)");
771 }
772 //------------------------tp_richcompare
773 //This method allows the object to use comparison operators
774 //TODO: We need some armature comparisons
775 static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op)
776 {
777         return EXPP_incr_ret(Py_None);
778 }
779
780 //------------------------tp_repr
781 //This is the string representation of the object
782 static PyObject *Armature_repr(BPy_Armature *self)
783 {
784         return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
785 }
786
787 //------------------------tp_dealloc
788 //This tells how to 'tear-down' our object when ref count hits 0
789 ///tp_dealloc
790 static void Armature_dealloc(BPy_Armature * self)
791 {
792         Py_DECREF(self->Bones);
793         ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
794         return;
795 }
796 //------------------TYPE_OBECT DEFINITION--------------------------
797 PyTypeObject Armature_Type = {
798         PyObject_HEAD_INIT(NULL)                //tp_head
799         0,                                                              //tp_internal
800         "Armature",                                             //tp_name
801         sizeof(BPy_Armature),                   //tp_basicsize
802         0,                                                              //tp_itemsize
803         (destructor)Armature_dealloc,   //tp_dealloc
804         0,                                                              //tp_print
805         0,                                                              //tp_getattr
806         0,                                                              //tp_setattr
807         0,                                                              //tp_compare
808         (reprfunc) Armature_repr,               //tp_repr
809         0,                                                              //tp_as_number
810         0,                                                              //tp_as_sequence
811         0,                                                              //tp_as_mapping
812         0,                                                              //tp_hash
813         0,                                                              //tp_call
814         0,                                                              //tp_str
815         0,                                                              //tp_getattro
816         0,                                                              //tp_setattro
817         0,                                                              //tp_as_buffer
818         Py_TPFLAGS_DEFAULT,                             //tp_flags
819         BPy_Armature_doc,                               //tp_doc
820         0,                                                              //tp_traverse
821         0,                                                              //tp_clear
822         (richcmpfunc)Armature_richcmpr, //tp_richcompare
823         0,                                                              //tp_weaklistoffset
824         0,                                                              //tp_iter
825         0,                                                              //tp_iternext
826         BPy_Armature_methods,                   //tp_methods
827         0,                                                              //tp_members
828         BPy_Armature_getset,                    //tp_getset
829         0,                                                              //tp_base
830         0,                                                              //tp_dict
831         0,                                                              //tp_descr_get
832         0,                                                              //tp_descr_set
833         0,                                                              //tp_dictoffset
834         (initproc)Armature_init,                //tp_init
835         0,                                                              //tp_alloc
836         (newfunc)Armature_new,                  //tp_new
837         0,                                                              //tp_free
838         0,                                                              //tp_is_gc
839         0,                                                              //tp_bases
840         0,                                                              //tp_mro
841         0,                                                              //tp_cache
842         0,                                                              //tp_subclasses
843         0,                                                              //tp_weaklist
844         0                                                               //tp_del
845 };
846
847 //-------------------MODULE METHODS IMPLEMENTATION------------------------
848 //----------------Blender.Armature.Get()
849 /* This function will return a Py_Armature when a single string is passed
850 * or else it will return a {key:value} dictionary when mutliple strings are passed
851 * or it will return a {key:value} dictionary of all armatures when nothing is passed*/
852 static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
853 {
854         PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL;
855         char *name = "", buffer[24];
856         int size = 0, i;
857         void *data;
858
859         //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable
860         size = PySequence_Length(args);
861         if (size == 1) {
862                 seq = PySequence_GetItem(args, 0); //*new*
863                 if (seq == NULL)
864                         goto RuntimeError;
865                 if(!PyString_Check(seq)){
866                         if (PySequence_Check(seq)) {
867                                 size = PySequence_Length(seq);
868                         } else {
869                                 Py_DECREF(seq);
870                                 goto AttributeError;
871                         }
872                 }
873         } else {
874                 seq = EXPP_incr_ret(args); //*take ownership*
875         }
876         //'seq' should be a list, empty tuple or string - check list for strings
877         if(!PyString_Check(seq)){
878                 for(i = 0; i < size; i++){
879                         item = PySequence_GetItem(seq, i); //*new*
880                         if (item == NULL) {
881                                 Py_DECREF(seq);
882                                 goto RuntimeError;
883                         }
884                         if(!PyString_Check(item)){
885                                 EXPP_decr2(item, seq);
886                                 goto AttributeError;
887                         }
888                         Py_DECREF(item);
889                 }
890         }
891
892         //GET ARMATURES
893         if(size != 1){
894                 dict = PyDict_New(); //*new*
895                 if(dict == NULL){
896                         Py_DECREF(seq);
897                         goto RuntimeError;
898                 }
899                 if(size == 0){  //GET ALL ARMATURES
900                         data = &(G.main->armature).first; //get the first data ID from the armature library
901                         while (data){
902                                 py_armature = PyArmature_FromArmature(data); //*new*
903                                 sprintf(buffer, "%s", ((bArmature*)data)->id.name +2);
904                                 if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary
905                                         EXPP_decr3(seq, dict, py_armature);
906                                         goto RuntimeError;
907                                 }
908                                 data = ((ID*)data)->next;
909                         }
910                         Py_DECREF(seq);
911                 }else{  //GET ARMATURE LIST
912                         for (i = 0; i < size; i++) {
913                                 item = PySequence_GetItem(seq, i); //*new*
914                                 name = PyString_AsString(item);
915                                 Py_DECREF(item);
916                                 data = find_id("AR", name); //get data from library
917                                 if (data != NULL){
918                                         py_armature = PyArmature_FromArmature(data); //*new*
919                                         if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary
920                                                 EXPP_decr3(seq, dict, py_armature);
921                                                 goto RuntimeError;
922                                         }
923                                 }else{
924                                         if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
925                                                 EXPP_decr2(seq, dict);
926                                                 goto RuntimeError;
927                                         }
928                                 }
929                         }
930                         Py_DECREF(seq);
931                 }
932                 return dict; //transfering ownership to caller
933         }else{  //GET SINGLE ARMATURE
934                 if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
935                         item = PySequence_GetItem(seq, 0); //*new*
936                         name = PyString_AsString(item);
937                         Py_DECREF(item);
938                 }else{
939                         name = PyString_AsString(seq);
940                 }
941                 Py_DECREF(seq);
942                 data = find_id("AR", name); //get data from library
943                 if (data != NULL){
944                         return PyArmature_FromArmature(data); //*new*
945                 }else{
946                         return EXPP_incr_ret(Py_None);
947                 }
948         }
949
950 RuntimeError:
951         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
952                 sModuleError, "Get(): ", "Internal Error Ocurred");
953
954 AttributeError:
955         return EXPP_objError(PyExc_AttributeError, "%s%s%s", 
956                 sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence");
957 }
958
959 //-------------------MODULE METHODS DEFINITION-----------------------------
960 static PyObject *M_Armature_Get( PyObject * self, PyObject * args );
961
962 static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \
963   returns None if not found.\n If 'name' is not specified, it returns a list of all \
964   armatures in the\ncurrent scene.";
965
966 struct PyMethodDef M_Armature_methods[] = {
967         {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc},
968         {NULL}
969 };
970 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
971 //-----------------(internal)
972 //Converts a bArmature to a PyArmature
973 PyObject *PyArmature_FromArmature(struct bArmature *armature)
974 {
975         BPy_Armature *py_armature = NULL;
976         int success;
977
978         py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
979         if (py_armature == NULL)
980                 goto RuntimeError;
981
982         py_armature->armature = armature;
983
984         py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); //*new*
985         if (py_armature->Bones == NULL)
986                 goto RuntimeError;
987
988         success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &armature->bonebase);
989         if (success == -1)
990                 return NULL; //error string already set
991
992         return (PyObject *) py_armature; 
993
994 RuntimeError:
995         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
996                 sModuleError, "PyArmature_FromArmature: ", "Internal Error Ocurred");
997 }
998 //-----------------(internal)
999 //Converts a PyArmature to a bArmature
1000 struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature)
1001 {
1002         return (py_armature->armature);
1003 }
1004 //-------------------MODULE INITIALIZATION--------------------------------
1005 PyObject *Armature_Init(void)
1006 {
1007         PyObject *module, *dict;
1008
1009         //Initializes TypeObject.ob_type
1010         if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || 
1011                 PyType_Ready(&EditBone_Type) < 0 ||     PyType_Ready(&Bone_Type) < 0){
1012                 return EXPP_incr_ret(Py_None);
1013         }
1014
1015         //Register the module
1016         module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
1017                 "The Blender Armature module"); 
1018
1019         //Add TYPEOBJECTS to the module
1020         PyModule_AddObject(module, "ArmatureType", 
1021                 EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
1022         PyModule_AddObject(module, "BoneType", 
1023                 EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
1024
1025         //Add CONSTANTS to the module
1026         PyModule_AddObject(module, "CONNECTED", 
1027                 EXPP_incr_ret(PyConstant_NewInt("CONNECTED", BONE_CONNECTED)));
1028         PyModule_AddObject(module, "HINGE", 
1029                 EXPP_incr_ret(PyConstant_NewInt("HINGE", BONE_HINGE)));
1030         PyModule_AddObject(module, "NO_DEFORM", 
1031                 EXPP_incr_ret(PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM)));
1032         PyModule_AddObject(module, "MULTIPLY", 
1033                 EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV)));
1034         PyModule_AddObject(module, "HIDDEN_EDIT", 
1035                 EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A)));
1036
1037         PyModule_AddObject(module, "BONESPACE", 
1038                 EXPP_incr_ret(PyConstant_NewString("BONESPACE", "bone_space")));
1039         PyModule_AddObject(module, "ARMATURESPACE", 
1040                 EXPP_incr_ret(PyConstant_NewString("ARMATURESPACE", "armature_space")));
1041         PyModule_AddObject(module, "WORLDSPACE", 
1042                 EXPP_incr_ret(PyConstant_NewString("WORLDSPACE", "world_space")));
1043
1044         //Add SUBMODULES to the module
1045         dict = PyModule_GetDict( module ); //borrowed
1046         PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module
1047
1048         return module;
1049 }