733b825121528c7d9cf3cc522f5c07a4cf451192
[blender.git] / source / blender / python / api2_2x / Bone.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  * Contributor(s): Joseph Gilbert
27  *
28  * ***** END GPL/BL DUAL LICENSE BLOCK *****
29 */
30
31 #include "Bone.h"
32 #include "vector.h"
33 #include "matrix.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_arithb.h"
37 #include "BKE_utildefines.h"
38 #include "gen_utils.h"
39 #include "BKE_armature.h"
40 #include "Mathutils.h"
41 #include "BKE_library.h"
42
43 //these must come in this order
44 #include "DNA_object_types.h" //1
45 #include "BIF_editarmature.h"   //2
46
47 //------------------------ERROR CODES---------------------------------
48 //This is here just to make me happy and to have more consistant error strings :)
49 static const char sEditBoneError[] = "EditBone - Error: ";
50 // static const char sEditBoneBadArgs[] = "EditBone - Bad Arguments: ";
51 static const char sBoneError[] = "Bone - Error: ";
52 // static const char sBoneBadArgs[] = "Bone - Bad Arguments: ";
53
54 //----------------------(internal)
55 //gets the bone->roll (which is a localspace roll) and puts it in parentspace
56 //(which is the 'roll' value the user sees)
57 static double boneRoll_ToArmatureSpace(struct Bone *bone)
58 {
59         float head[3], tail[3], delta[3];
60         float premat[3][3], postmat[3][3];
61         float imat[3][3], difmat[3][3];
62         double roll = 0.0f;
63
64         VECCOPY(head, bone->arm_head);
65         VECCOPY(tail, bone->arm_tail);          
66         VECSUB (delta, tail, head);                     
67         vec_roll_to_mat3(delta, 0.0f, postmat); 
68         Mat3CpyMat4(premat, bone->arm_mat);             
69         Mat3Inv(imat, postmat);                                 
70         Mat3MulMat3(difmat, imat, premat);      
71
72         roll = atan2(difmat[2][0], difmat[2][2]); 
73         if (difmat[0][0] < 0.0){
74                 roll += M_PI;
75         }
76         return roll; //result is in radians
77 }
78
79 //################## EditBone_Type ########################
80 /*This type is a wrapper for a tempory bone. This is an 'unparented' bone
81 *object. The armature->bonebase will be calculated from these temporary
82 *python tracked objects.*/
83 //####################################################
84
85 //------------------METHOD IMPLEMENTATIONS-----------------------------
86 //-------------------------EditBone.hasParent()
87 static PyObject *EditBone_hasParent(BPy_EditBone *self)
88 {
89         if (self->editbone){
90                 if (self->editbone->parent)
91                         Py_RETURN_TRUE;
92                 else
93                         Py_RETURN_FALSE;
94         }else{
95                 goto AttributeError;
96         }
97
98 AttributeError:
99         return EXPP_objError(PyExc_AttributeError, "%s%s%s",
100                 sEditBoneError, ".hasParent: ", "EditBone must be added to the armature first");
101 }
102 //-------------------------EditBone.clearParent()
103 static PyObject *EditBone_clearParent(BPy_EditBone *self)
104 {
105         if (self->editbone){
106                 if (self->editbone->parent)
107                         self->editbone->parent = NULL;
108                 Py_RETURN_NONE;
109         }else{
110                 goto AttributeError;
111         }
112
113 AttributeError:
114         return EXPP_objError(PyExc_AttributeError, "%s%s%s",
115                 sEditBoneError, ".clearParent: ", "EditBone must be added to the armature first");
116 }
117 //------------------ATTRIBUTE IMPLEMENTATION---------------------------
118 //------------------------EditBone.name (get)
119 static PyObject *EditBone_getName(BPy_EditBone *self, void *closure)
120 {
121         if (self->editbone)
122                 return PyString_FromString(self->editbone->name);
123         else
124                 return PyString_FromString(self->name);
125 }
126 //------------------------EditBone.name (set)
127 //check for char[] overflow here...
128 static int EditBone_setName(BPy_EditBone *self, PyObject *value, void *closure)
129 {  
130         char *name = "";
131
132         if (!PyArg_Parse(value, "s", &name))
133                 goto AttributeError;
134
135         if (self->editbone)
136         BLI_strncpy(self->editbone->name, name, 32);
137         else
138                 BLI_strncpy(self->name, name, 32);
139         return 0;
140
141 AttributeError:
142         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
143                 sEditBoneError, ".name: ", "expects a string");
144 }
145 //------------------------EditBone.roll (get)
146 static PyObject *EditBone_getRoll(BPy_EditBone *self, void *closure)
147 {
148         if (self->editbone){
149                 return PyFloat_FromDouble((self->editbone->roll * (180/Py_PI)));
150         }else{
151                 return PyFloat_FromDouble((self->roll * (180/Py_PI)));
152         }
153 }
154 //------------------------EditBone.roll (set)
155 static int EditBone_setRoll(BPy_EditBone *self, PyObject *value, void *closure)
156 {  
157         float roll = 0.0f;
158
159         if (!PyArg_Parse(value, "f", &roll))
160                 goto AttributeError;
161
162         if (self->editbone){
163                 self->editbone->roll = (float)(roll * (Py_PI/180));
164         }else{
165                 self->roll = (float)(roll * (Py_PI/180));
166         }
167         return 0;
168
169 AttributeError:
170         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
171                 sEditBoneError, ".roll: ", "expects a float");
172 }
173 //------------------------EditBone.head (get)
174 static PyObject *EditBone_getHead(BPy_EditBone *self, void *closure)
175 {
176         if (self->editbone){
177                 return newVectorObject(self->editbone->head, 3, Py_WRAP);
178         }else{
179                 return newVectorObject(self->head, 3, Py_NEW);
180         }
181 }
182 //------------------------EditBone.head (set)
183 static int EditBone_setHead(BPy_EditBone *self, PyObject *value, void *closure)
184 {  
185         VectorObject *vec = NULL;
186         int x;
187
188         if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
189                 goto AttributeError;
190         if (vec->size != 3)
191                 goto AttributeError2;
192
193         if (self->editbone){
194                 for (x = 0; x < 3; x++){
195                         self->editbone->head[x] = vec->vec[x];
196                 }
197         }else{
198                 for (x = 0; x < 3; x++){
199                         self->head[x] = vec->vec[x];
200                 }
201         }
202         return 0;
203
204 AttributeError:
205         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
206                 sEditBoneError, ".head: ", "expects a Vector Object");
207
208 AttributeError2:
209         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
210                 sEditBoneError, ".head: ", "Vector Object needs to be (x,y,z)");
211 }
212 //------------------------EditBone.tail (get)
213 static PyObject *EditBone_getTail(BPy_EditBone *self, void *closure)
214 {
215         if (self->editbone){
216                 return newVectorObject(self->editbone->tail, 3, Py_WRAP);
217         }else{
218                 return newVectorObject(self->tail, 3, Py_NEW);
219         }
220 }
221 //------------------------EditBone.tail (set)
222 static int EditBone_setTail(BPy_EditBone *self, PyObject *value, void *closure)
223 {  
224         VectorObject *vec = NULL;
225         int x;
226
227         if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
228                 goto AttributeError;
229         if (vec->size != 3)
230                 goto AttributeError2;
231
232         if (self->editbone){
233                 for (x = 0; x < 3; x++){
234                         self->editbone->tail[x] = vec->vec[x];
235                 }
236         }else{
237                 for (x = 0; x < 3; x++){
238                         self->tail[x] = vec->vec[x];
239                 }
240         }
241         return 0;
242
243 AttributeError:
244         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
245                 sEditBoneError, ".tail: ", "expects a Vector Object");
246
247 AttributeError2:
248         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
249                 sEditBoneError, ".tail: ", "Vector Object needs to be (x,y,z)");
250 }
251 //------------------------EditBone.weight (get)
252 static PyObject *EditBone_getWeight(BPy_EditBone *self, void *closure)
253 {
254         if (self->editbone)
255                 return PyFloat_FromDouble(self->editbone->weight);
256         else
257                 return PyFloat_FromDouble(self->weight);
258 }
259 //------------------------EditBone.weight (set)
260 static int EditBone_setWeight(BPy_EditBone *self, PyObject *value, void *closure)
261 {  
262         float weight;
263
264         if (!PyArg_Parse(value, "f", &weight))
265                 goto AttributeError;
266         CLAMP(weight, 0.0f, 1000.0f);
267
268         if (self->editbone)
269                 self->editbone->weight = weight;
270         else
271                 self->weight = weight;
272         return 0;
273
274 AttributeError:
275         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
276                 sEditBoneError, ".weight: ", "expects a float");
277 }
278 //------------------------EditBone.deform_dist (get)
279 static PyObject *EditBone_getDeform_dist(BPy_EditBone *self, void *closure)
280 {
281         if (self->editbone)
282                 return PyFloat_FromDouble(self->editbone->dist);
283         else
284                 return PyFloat_FromDouble(self->dist);
285 }
286 //------------------------EditBone.deform_dist (set)
287 static int EditBone_setDeform_dist(BPy_EditBone *self, PyObject *value, void *closure)
288 {  
289         float deform;
290
291         if (!PyArg_Parse(value, "f", &deform))
292                 goto AttributeError;
293         CLAMP(deform, 0.0f, 1000.0f);
294
295         if (self->editbone)
296                 self->editbone->dist = deform;
297         else
298                 self->dist = deform;
299         return 0;
300
301 AttributeError:
302         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
303                 sEditBoneError, ".deform_dist: ", "expects a float");
304 }
305 //------------------------EditBone.subdivisions (get)
306 static PyObject *EditBone_getSubdivisions(BPy_EditBone *self, void *closure)
307 {
308         if (self->editbone)
309                 return PyInt_FromLong(self->editbone->segments);
310         else
311                 return PyInt_FromLong(self->segments);
312 }
313 //------------------------EditBone.subdivisions (set)
314 static int EditBone_setSubdivisions(BPy_EditBone *self, PyObject *value, void *closure)
315 {  
316         int segs;
317
318         if (!PyArg_Parse(value, "i", &segs))
319                 goto AttributeError;
320         CLAMP(segs, 1, 32);
321
322         if (self->editbone)
323                 self->editbone->segments = (short)segs;
324         else
325                 self->segments = (short)segs;
326         return 0;
327
328 AttributeError:
329         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
330                 sEditBoneError, ".subdivisions: ", "expects a integer");
331 }
332 //------------------------EditBone.options (get)
333 static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
334 {
335         PyObject *list = NULL;
336
337         list = PyList_New(0);
338         if (!list)
339                 goto RuntimeError;
340
341         if(self->editbone){
342                 if(self->editbone->flag & BONE_CONNECTED)
343                         if (PyList_Append(list, 
344                                 EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
345                                 goto RuntimeError;
346                 if(self->editbone->flag & BONE_HINGE)
347                         if (PyList_Append(list, 
348                                 EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
349                                 goto RuntimeError;
350                 if(self->editbone->flag & BONE_NO_DEFORM)
351                         if (PyList_Append(list, 
352                                 EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
353                                 goto RuntimeError;
354                 if(self->editbone->flag & BONE_MULT_VG_ENV)
355                         if (PyList_Append(list, 
356                                 EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
357                                 goto RuntimeError;
358                 if(self->editbone->flag & BONE_HIDDEN_A)
359                         if (PyList_Append(list, 
360                                 EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
361                                 goto RuntimeError;
362                 if(self->editbone->flag & BONE_ROOTSEL)
363                         if (PyList_Append(list, 
364                                 EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
365                                 goto RuntimeError;
366                 if(self->editbone->flag & BONE_SELECTED)
367                         if (PyList_Append(list, 
368                                 EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
369                                 goto RuntimeError;
370                 if(self->editbone->flag & BONE_TIPSEL)
371                         if (PyList_Append(list, 
372                                 EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
373                                 goto RuntimeError;
374         }else{
375                 if(self->flag & BONE_CONNECTED)
376                         if (PyList_Append(list, 
377                                 EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
378                                 goto RuntimeError;
379                 if(self->flag & BONE_HINGE)
380                         if (PyList_Append(list, 
381                                 EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
382                                 goto RuntimeError;
383                 if(self->flag & BONE_NO_DEFORM)
384                         if (PyList_Append(list, 
385                                 EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
386                                 goto RuntimeError;
387                 if(self->flag & BONE_MULT_VG_ENV)
388                         if (PyList_Append(list, 
389                                 EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
390                                 goto RuntimeError;
391                 if(self->flag & BONE_HIDDEN_A)
392                         if (PyList_Append(list, 
393                                 EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
394                                 goto RuntimeError;
395                 if(self->flag & BONE_ROOTSEL)
396                         if (PyList_Append(list, 
397                                 EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
398                                 goto RuntimeError;
399                 if(self->flag & BONE_SELECTED)
400                         if (PyList_Append(list, 
401                                 EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
402                                 goto RuntimeError;
403                 if(self->flag & BONE_TIPSEL)
404                         if (PyList_Append(list, 
405                                 EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
406                                 goto RuntimeError;
407         }
408
409         return list;
410
411 RuntimeError:
412         Py_XDECREF( list );
413         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
414                 sEditBoneError, ".options: ", "Internal failure!");
415 }
416 //----------------------(internal) EditBone_CheckValidConstant
417 static int EditBone_CheckValidConstant(PyObject *constant)
418 {
419         PyObject *name = NULL;
420
421         if (constant){
422                 if (BPy_Constant_Check(constant)){
423                         name = PyDict_GetItemString(((BPy_constant*)constant)->dict, "name");
424                         if (!name) 
425                                 return 0;
426                         if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
427                                 !STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED")      &&
428                                 !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
429                                 return 0;
430                         else
431                                 return 1;
432                 }else{
433                         return 0;
434                 }
435         }else{
436                 return 0;
437         }
438 }
439
440 //------------------------EditBone.options (set)
441 static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closure)
442 {  
443         int length, numeric_value, new_flag = 0, x;
444         PyObject *val = NULL, *index = NULL;
445
446         if (PyList_Check(value)){
447                 length = PyList_Size(value);
448                 for (x = 0; x < length; x++){
449                         index = PyList_GetItem(value, x);
450                         if (!EditBone_CheckValidConstant(index))
451                                 goto AttributeError2;
452                         val = PyDict_GetItemString(((BPy_constant*)index)->dict, "value");
453                         if (PyInt_Check(val)){
454                                 numeric_value = (int)PyInt_AS_LONG(val);
455                                 new_flag |= numeric_value;
456                         }else{
457                                 goto AttributeError2;
458                         }
459                 }
460
461                 //set the options
462                 if(self->editbone){
463                         //make sure the 'connected' property is set up correctly
464                         if (new_flag & BONE_CONNECTED) {
465                                 if(!self->editbone->parent)
466                                         goto AttributeError3;
467                                 else
468                                         VECCOPY(self->editbone->head, self->editbone->parent->tail);
469                         }
470                         self->editbone->flag = new_flag;
471                 }else{
472                         self->flag = new_flag;
473                 }
474                 return 0;
475         }else if (BPy_Constant_Check(value)){
476                 if (!EditBone_CheckValidConstant(value))
477                         goto AttributeError2;
478                 val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
479                 if (PyInt_Check(val)){
480                         numeric_value = (int)PyInt_AS_LONG(val);
481
482                         if(self->editbone){
483                                 //make sure the 'connected' property is set up correctly
484                                 if (numeric_value & BONE_CONNECTED) {
485                                         if(!self->editbone->parent)
486                                                 goto AttributeError3;
487                                         else
488                                                 VECCOPY(self->editbone->head, self->editbone->parent->tail);
489                                 }
490                                 self->editbone->flag = numeric_value;
491                         }else{
492                                 self->flag = numeric_value;
493                         }
494                         return 0;
495                 }else{
496                         goto AttributeError2;
497                 }
498         }else{
499                 goto AttributeError1;
500         }
501
502 AttributeError1:
503         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
504                 sEditBoneError, ".options: ", "Expects a constant or list of constants");
505 AttributeError2:
506         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
507                 sEditBoneError, ".options: ", "Please use a constant defined in the Armature module");
508 AttributeError3:
509         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
510                 sEditBoneError, ".options: ", "You can't connect to parent because no parent is set");
511 }
512 //------------------------EditBone.parent (get)
513 static PyObject *EditBone_getParent(BPy_EditBone *self, void *closure)
514 {
515         if (self->editbone){
516                 if (self->editbone->parent)
517                         return PyEditBone_FromEditBone(self->editbone->parent);
518                 else
519                         Py_RETURN_NONE;
520         }else{
521                 Py_RETURN_NONE; //not in the list yet can't have a parent
522         }
523 }
524 //------------------------EditBone.parent (set)
525 static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure)
526 {  
527         BPy_EditBone *parent = NULL;
528
529         if (!PyArg_Parse(value, "O!", &EditBone_Type, &parent))
530                 goto AttributeError;
531
532         if (!parent->editbone)
533                 goto AttributeError2;
534
535         if (self->editbone){
536         self->editbone->parent = parent->editbone;
537         }else{
538                 self->parent = parent->editbone;
539         }
540         return 0;
541
542 AttributeError:
543         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
544                 sEditBoneError, ".parent: ", "expects a EditBone Object");
545 AttributeError2:
546         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
547                 sEditBoneError, ".parent: ", "This object is not in the armature's bone list!");
548 }
549 //------------------------EditBone.matrix (get)
550 static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
551 {
552         float boneMatrix[3][3];
553         float   axis[3];
554
555         if (self->editbone){
556                 VECSUB(axis, self->editbone->tail, self->editbone->head);
557                 vec_roll_to_mat3(axis, self->editbone->roll, boneMatrix);
558         }else{
559                 VECSUB(axis, self->tail, self->head);
560                 vec_roll_to_mat3(axis, self->roll, boneMatrix);
561         }
562
563     return newMatrixObject((float*)boneMatrix, 3, 3, Py_NEW);
564 }
565 //------------------------EditBone.matrix (set)
566 static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
567 {  
568         PyObject *matrix;
569         float roll, length, vec[3], axis[3], mat3[3][3];
570
571         if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
572                 goto AttributeError;
573
574         //make sure we have the right sizes
575         if (((MatrixObject*)matrix)->rowSize != 3 && ((MatrixObject*)matrix)->colSize != 3){
576                 if(((MatrixObject*)matrix)->rowSize != 4 && ((MatrixObject*)matrix)->colSize != 4){
577                         goto AttributeError;
578                 }
579         }
580                 
581         /*vec will be a normalized directional vector
582         * together with the length of the old bone vec*length = the new vector*/
583         /*The default rotation is 0,1,0 on the Y axis (see mat3_to_vec_roll)*/
584         if (((MatrixObject*)matrix)->rowSize == 4){
585                 Mat3CpyMat4(mat3, ((float (*)[4])*((MatrixObject*)matrix)->matrix));
586         }else{
587                 Mat3CpyMat3(mat3, ((float (*)[3])*((MatrixObject*)matrix)->matrix));
588         }
589         mat3_to_vec_roll(mat3, vec, &roll);
590
591         //if a 4x4 matrix was passed we'll translate the vector otherwise not
592         if (self->editbone){
593                 self->editbone->roll = roll;
594                 VecSubf(axis, self->editbone->tail, self->editbone->head);
595                 length =  VecLength(axis);
596                 VecMulf(vec, length);
597                 if (((MatrixObject*)matrix)->rowSize == 4)
598                         VecCopyf(self->editbone->head, ((MatrixObject*)matrix)->matrix[3]);
599                 VecAddf(self->editbone->tail, self->editbone->head, vec);
600                 return 0;
601         }else{
602                 self->roll = roll;
603                 VecSubf(axis, self->tail, self->head);
604                 length =  VecLength(axis);
605                 VecMulf(vec, length);
606                 if (((MatrixObject*)matrix)->rowSize == 4)
607                         VecCopyf(self->head, ((MatrixObject*)matrix)->matrix[3]);
608                 VecAddf(self->tail, self->head, vec);
609                 return 0;
610         }
611
612 AttributeError:
613         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
614                 sEditBoneError, ".matrix: ", "expects a 3x3 or 4x4 Matrix Object");
615 }
616 //------------------------Bone.length (get)
617 static PyObject *EditBone_getLength(BPy_EditBone *self, void *closure)
618 {
619         float delta[3];
620         double dot = 0.0f;
621         int x;
622
623         if (self->editbone){
624                 VECSUB(delta, self->editbone->tail, self->editbone->head);
625                 for(x = 0; x < 3; x++){
626                         dot += (delta[x] * delta[x]);
627                 }
628                 return PyFloat_FromDouble(sqrt(dot));
629         }else{
630                 VECSUB(delta, self->tail, self->head);
631                 for(x = 0; x < 3; x++){
632                         dot += (delta[x] * delta[x]);
633                 }
634                 return PyFloat_FromDouble(sqrt(dot));
635         }
636 }
637 //------------------------Bone.length (set)
638 static int EditBone_setLength(BPy_EditBone *self, PyObject *value, void *closure)
639 {  
640         printf("Sorry this isn't implemented yet.... :/");
641         return 1;
642 }
643
644
645 //------------------------Bone.headRadius (get)
646 static PyObject *EditBone_getHeadRadius(BPy_EditBone *self, void *closure)
647 {
648         if (self->editbone)
649                 if (self->editbone->parent && self->editbone->flag & BONE_CONNECTED)
650                         return PyFloat_FromDouble(self->editbone->parent->rad_tail);
651                 else
652                         return PyFloat_FromDouble(self->editbone->rad_head);
653         else
654                 if (self->parent && self->flag & BONE_CONNECTED)
655                         return PyFloat_FromDouble(self->parent->rad_tail);
656                 else
657                         return PyFloat_FromDouble(self->rad_head);
658 }
659 //------------------------Bone.headRadius (set)
660 static int EditBone_setHeadRadius(BPy_EditBone *self, PyObject *value, void *closure)
661 {  
662         float radius;
663         if (!PyArg_Parse(value, "f", &radius))
664                 goto AttributeError;
665         CLAMP(radius, 0.0f, 10000.0f);
666
667         if (self->editbone)
668                 if (self->editbone->parent && self->editbone->flag & BONE_CONNECTED)
669                         self->editbone->parent->rad_tail= radius;
670                 else
671                         self->editbone->rad_head= radius;
672         else
673                 if (self->parent && self->flag & BONE_CONNECTED)
674                         self->parent->rad_tail= radius;
675                 else
676                         self->rad_head= radius;
677         return 0;
678
679 AttributeError:
680         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
681                 sEditBoneError, ".headRadius: ", "expects a float");
682 }
683
684
685 //------------------------Bone.tailRadius (get)
686 static PyObject *EditBone_getTailRadius(BPy_EditBone *self, void *closure)
687 {
688         if (self->editbone)
689                 return PyFloat_FromDouble(self->editbone->rad_tail);
690         else
691                 return PyFloat_FromDouble(self->rad_tail);
692 }
693 //------------------------Bone.tailRadius (set)
694 static int EditBone_setTailRadius(BPy_EditBone *self, PyObject *value, void *closure)
695 {  
696         float radius;
697         if (!PyArg_Parse(value, "f", &radius))
698                 goto AttributeError;
699         CLAMP(radius, 0.0f, 10000.0f);
700
701         if (self->editbone)
702                 self->editbone->rad_tail = radius;
703         else
704                 self->rad_tail = radius;
705         return 0;
706
707 AttributeError:
708         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
709                 sEditBoneError, ".tailRadius: ", "expects a float");
710 }
711
712
713 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
714 //------------------------tp_methods
715 //This contains a list of all methods the object contains
716 static PyMethodDef BPy_EditBone_methods[] = {
717         {"hasParent", (PyCFunction) EditBone_hasParent, METH_NOARGS, 
718                 "() - True/False - Bone has a parent"},
719         {"clearParent", (PyCFunction) EditBone_clearParent, METH_NOARGS, 
720                 "() - sets the parent to None"},
721         {NULL, NULL, 0, NULL}
722 };
723 ///------------------------tp_getset
724 //This contains methods for attributes that require checking
725 static PyGetSetDef BPy_EditBone_getset[] = {
726         {"name", (getter)EditBone_getName, (setter)EditBone_setName, 
727                 "The name of the bone", NULL},
728         {"roll", (getter)EditBone_getRoll, (setter)EditBone_setRoll, 
729                 "The roll (or rotation around the axis) of the bone", NULL},
730         {"head", (getter)EditBone_getHead, (setter)EditBone_setHead, 
731                 "The start point of the bone", NULL},
732         {"tail", (getter)EditBone_getTail, (setter)EditBone_setTail, 
733                 "The end point of the bone", NULL},
734         {"matrix", (getter)EditBone_getMatrix, (setter)EditBone_setMatrix, 
735                 "The matrix of the bone", NULL},
736         {"weight", (getter)EditBone_getWeight, (setter)EditBone_setWeight, 
737                 "The weight of the bone in relation to a parented mesh", NULL},
738         {"deformDist", (getter)EditBone_getDeform_dist, (setter)EditBone_setDeform_dist, 
739                 "The distance at which deformation has effect", NULL},
740         {"subdivisions", (getter)EditBone_getSubdivisions, (setter)EditBone_setSubdivisions, 
741                 "The number of subdivisions (for B-Bones)", NULL},
742         {"options", (getter)EditBone_getOptions, (setter)EditBone_setOptions, 
743                 "The options effective on this bone", NULL},
744         {"parent", (getter)EditBone_getParent, (setter)EditBone_setParent, 
745                 "The parent bone of this bone", NULL},
746         {"length", (getter)EditBone_getLength, (setter)EditBone_setLength, 
747                 "The length of this bone", NULL},
748         {"tailRadius", (getter)EditBone_getTailRadius, (setter)EditBone_setTailRadius, 
749                 "Set the radius of this bones tip", NULL},
750         {"headRadius", (getter)EditBone_getHeadRadius, (setter)EditBone_setHeadRadius, 
751                 "Set the radius of this bones head", NULL},
752         {NULL, NULL, NULL, NULL,NULL}
753 };
754
755 //------------------------tp_repr
756 //This is the string representation of the object
757 static PyObject *EditBone_repr(BPy_EditBone *self)
758 {
759         if (self->editbone)
760                 return PyString_FromFormat( "[EditBone \"%s\"]", self->editbone->name ); 
761         else
762                 return PyString_FromFormat( "[EditBone \"%s\"]", self->name ); 
763 }
764
765 static int EditBone_compare( BPy_EditBone * a, BPy_EditBone * b )
766 {
767         /* if they are not wrapped, then they cant be the same */
768         if (a->editbone==NULL && b->editbone==NULL) return -1;
769         return ( a->editbone == b->editbone ) ? 0 : -1;
770 }
771
772
773 //------------------------tp_doc
774 //The __doc__ string for this object
775 static char BPy_EditBone_doc[] = "This is an internal subobject of armature\
776 designed to act as a wrapper for an 'edit bone'.";
777
778 //------------------------tp_new
779 //This methods creates a new object (note it does not initialize it - only the building)
780 static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
781 {
782         char *name = "myEditBone";
783         BPy_EditBone *py_editBone = NULL;
784         float head[3], tail[3];
785
786         py_editBone = (BPy_EditBone*)type->tp_alloc(type, 0); //new
787         if (py_editBone == NULL)
788                 goto RuntimeError;
789
790         //this pointer will be set when this bone is placed in ListBase
791         //otherwise this will act as a py_object
792         py_editBone->editbone = NULL;
793
794         unique_editbone_name(NULL, name);
795         BLI_strncpy(py_editBone->name, name, 32);
796         py_editBone->parent = NULL;
797         py_editBone->weight= 1.0f;
798         py_editBone->dist= 0.25f;
799         py_editBone->xwidth= 0.1f;
800         py_editBone->zwidth= 0.1f;
801         py_editBone->ease1= 1.0f;
802         py_editBone->ease2= 1.0f;
803         py_editBone->rad_head= 0.10f;
804         py_editBone->rad_tail= 0.05f;
805         py_editBone->segments= 1;
806         py_editBone->flag = 0;
807         py_editBone->roll = 0.0f;
808
809         head[0] = head[1] = head[2] = 0.0f;
810         tail[1] = tail[2] = 0.0f;
811         tail[0] = 1.0f;
812         VECCOPY(py_editBone->head, head);
813         VECCOPY(py_editBone->tail, tail);
814
815         return (PyObject*)py_editBone;
816
817 RuntimeError:
818         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
819                 sEditBoneError, " __new__: ", "Internal Error");
820 }
821 //------------------------tp_dealloc
822 //This tells how to 'tear-down' our object when ref count hits 0
823 //the struct EditBone pointer will be handled by the BPy_BonesDict class
824 static void EditBone_dealloc(BPy_EditBone * self)
825 {
826         EditBone_Type.tp_free(self);
827         return;
828 }
829 //------------------TYPE_OBECT DEFINITION--------------------------
830 PyTypeObject EditBone_Type = {
831         PyObject_HEAD_INIT(NULL)       //tp_head
832         0,                                                                                      //tp_internal
833         "EditBone",                                                             //tp_name
834         sizeof(BPy_EditBone),                           //tp_basicsize
835         0,                                                                                      //tp_itemsize
836         (destructor)EditBone_dealloc,           //tp_dealloc
837         0,                                                                                      //tp_print
838         0,                                                                                      //tp_getattr
839         0,                                                                                      //tp_setattr
840         (cmpfunc)EditBone_compare,                                      //tp_compare
841         (reprfunc)EditBone_repr,                        //tp_repr
842         0,                                                                                      //tp_as_number
843         0,                                                                                      //tp_as_sequence
844         0,                                                                                      //tp_as_mapping
845         0,                                                                                      //tp_hash
846         0,                                                                                      //tp_call
847         0,                                                                                      //tp_str
848         0,                                                                                      //tp_getattro
849         0,                                                                                      //tp_setattro
850         0,                                                                                      //tp_as_buffer
851         Py_TPFLAGS_DEFAULT,                             //tp_flags
852         BPy_EditBone_doc,                                       //tp_doc
853         0,                                                                                      //tp_traverse
854         0,                                                                                      //tp_clear
855         0,                                                                                      //tp_richcompare
856         0,                                                                                      //tp_weaklistoffset
857         0,                                                                                      //tp_iter
858         0,                                                                                      //tp_iternext
859         BPy_EditBone_methods,                           //tp_methods
860         0,                                                                                      //tp_members
861         BPy_EditBone_getset,                            //tp_getset
862         0,                                                                                      //tp_base
863         0,                                                                                      //tp_dict
864         0,                                                                                      //tp_descr_get
865         0,                                                                                      //tp_descr_set
866         0,                                                                                      //tp_dictoffset
867         0,                                                                                      //tp_init
868         0,                                                                                      //tp_alloc
869         (newfunc)EditBone_new,                  //tp_new
870         0,                                                                                      //tp_free
871         0,                                                                                      //tp_is_gc
872         0,                                                                                      //tp_bases
873         0,                                                                                      //tp_mro
874         0,                                                                                      //tp_cache
875         0,                                                                                      //tp_subclasses
876         0,                                                                                      //tp_weaklist
877         0                                                                                       //tp_del
878 };
879
880 //------------------METHOD IMPLEMENTATIONS--------------------------------
881 //------------------------(internal) PyBone_ChildrenAsList
882 static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){
883         Bone *bone = NULL;
884         PyObject *py_bone = NULL;
885
886         for (bone = bones->first; bone; bone = bone->next){
887                 py_bone = PyBone_FromBone(bone);
888                 if (py_bone == NULL)
889                         return 0;
890                 
891                 if(PyList_Append(list, py_bone) == -1){
892                         return 0;
893                 }
894                 Py_DECREF(py_bone);
895                 if (bone->childbase.first) 
896                         if (!PyBone_ChildrenAsList(list, &bone->childbase))
897                                 return 0;
898         }
899         return 1;
900 }
901 //-------------------------Bone.hasParent()
902 static PyObject *Bone_hasParent(BPy_Bone *self)
903 {
904         if (self->bone->parent)
905                 Py_RETURN_TRUE;
906         else
907                 Py_RETURN_FALSE;
908 }
909 //-------------------------Bone.hasChildren()
910 static PyObject *Bone_hasChildren(BPy_Bone *self)
911 {
912         if (self->bone->childbase.first)
913                 Py_RETURN_TRUE;
914         else
915                 Py_RETURN_FALSE;
916 }
917 //-------------------------Bone.getAllChildren()
918 static PyObject *Bone_getAllChildren(BPy_Bone *self)
919 {
920         PyObject *list = PyList_New(0);
921         if (!self->bone->childbase.first) {
922                 /* do nothing */
923         } else if (!PyBone_ChildrenAsList(list, &self->bone->childbase)) {
924                 Py_XDECREF(list);
925                 EXPP_objError(PyExc_RuntimeError, "%s%s", 
926                                 sBoneError, "Internal error trying to wrap blender bones!");
927         }
928         return list;
929 }
930
931 //------------------ATTRIBUTE IMPLEMENTATIONS-----------------------------
932 //------------------------Bone.name (get)
933 static PyObject *Bone_getName(BPy_Bone *self, void *closure)
934 {
935         return PyString_FromString(self->bone->name);
936 }
937 //------------------------Bone.name (set)
938 //check for char[] overflow here...
939 static int Bone_setName(BPy_Bone *self, PyObject *value, void *closure)
940 {  
941   return EXPP_intError(PyExc_ValueError, "%s%s", 
942                 sBoneError, "You must first call .makeEditable() to edit the armature");
943 }
944 //------------------------Bone.roll (get)
945 static PyObject *Bone_getRoll(BPy_Bone *self, void *closure)
946 {       
947         return Py_BuildValue("{s:f, s:f}", 
948                 "BONESPACE", self->bone->roll * (180/Py_PI),
949                 "ARMATURESPACE", boneRoll_ToArmatureSpace(self->bone) * (180/Py_PI));
950 }
951 //------------------------Bone.roll (set)
952 static int Bone_setRoll(BPy_Bone *self, PyObject *value, void *closure)
953 {  
954   return EXPP_intError(PyExc_ValueError, "%s%s", 
955                 sBoneError, "You must first call .makeEditable() to edit the armature");
956 }
957 //------------------------Bone.head (get)
958 static PyObject *Bone_getHead(BPy_Bone *self, void *closure)
959 {
960         PyObject *val1 = newVectorObject(self->bone->head, 3, Py_WRAP);
961         PyObject *val2 = newVectorObject(self->bone->arm_head, 3, Py_WRAP);
962         PyObject *ret = Py_BuildValue(
963                         "{s:O, s:O}", "BONESPACE", val1, "ARMATURESPACE", val2);
964         
965         Py_DECREF(val1);
966         Py_DECREF(val2);
967         return ret;
968 }
969 //------------------------Bone.head (set)
970 static int Bone_setHead(BPy_Bone *self, PyObject *value, void *closure)
971 {  
972   return EXPP_intError(PyExc_ValueError, "%s%s", 
973                 sBoneError, "You must first call .makeEditable() to edit the armature");
974 }
975 //------------------------Bone.tail (get)
976 static PyObject *Bone_getTail(BPy_Bone *self, void *closure)
977 {
978         PyObject *val1 = newVectorObject(self->bone->tail, 3, Py_WRAP);
979         PyObject *val2 = newVectorObject(self->bone->arm_tail, 3, Py_WRAP);
980         PyObject *ret = Py_BuildValue("{s:O, s:O}", 
981                 "BONESPACE", val1, "ARMATURESPACE", val2);
982         
983         Py_DECREF(val1);
984         Py_DECREF(val2);
985         return ret;
986 }
987 //------------------------Bone.tail (set)
988 static int Bone_setTail(BPy_Bone *self, PyObject *value, void *closure)
989 {  
990   return EXPP_intError(PyExc_ValueError, "%s%s", 
991                 sBoneError, "You must first call .makeEditable() to edit the armature");
992 }
993 //------------------------Bone.weight (get)
994 static PyObject *Bone_getWeight(BPy_Bone *self, void *closure)
995 {
996         return PyFloat_FromDouble(self->bone->weight);
997 }
998 //------------------------Bone.weight (set)
999 static int Bone_setWeight(BPy_Bone *self, PyObject *value, void *closure)
1000 {  
1001   return EXPP_intError(PyExc_ValueError, "%s%s", 
1002                 sBoneError, "You must first call .makeEditable() to edit the armature");
1003 }
1004 //------------------------Bone.deform_dist (get)
1005 static PyObject *Bone_getDeform_dist(BPy_Bone *self, void *closure)
1006 {
1007     return PyFloat_FromDouble(self->bone->dist);
1008 }
1009 //------------------------Bone.deform_dist (set)
1010 static int Bone_setDeform_dist(BPy_Bone *self, PyObject *value, void *closure)
1011 {  
1012   return EXPP_intError(PyExc_ValueError, "%s%s", 
1013                 sBoneError, "You must first call .makeEditable() to edit the armature");
1014 }
1015 //------------------------Bone.subdivisions (get)
1016 static PyObject *Bone_getSubdivisions(BPy_Bone *self, void *closure)
1017 {
1018     return PyInt_FromLong(self->bone->segments);
1019 }
1020 //------------------------Bone.subdivisions (set)
1021 static int Bone_setSubdivisions(BPy_Bone *self, PyObject *value, void *closure)
1022 {  
1023   return EXPP_intError(PyExc_ValueError, "%s%s", 
1024                 sBoneError, "You must first call .makeEditable() to edit the armature");
1025 }
1026 //------------------------Bone.connected (get)
1027 static PyObject *Bone_getOptions(BPy_Bone *self, void *closure)
1028 {
1029         PyObject *list = NULL;
1030
1031         list = PyList_New(0);
1032         if (list == NULL)
1033                 goto RuntimeError;
1034
1035         if(self->bone->flag & BONE_CONNECTED)
1036                 if (PyList_Append(list, 
1037                         EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
1038                         goto RuntimeError;
1039         if(self->bone->flag & BONE_HINGE)
1040                 if (PyList_Append(list, 
1041                         EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
1042                         goto RuntimeError;
1043         if(self->bone->flag & BONE_NO_DEFORM)
1044                 if (PyList_Append(list, 
1045                         EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
1046                         goto RuntimeError;
1047         if(self->bone->flag & BONE_MULT_VG_ENV)
1048                 if (PyList_Append(list, 
1049                         EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
1050                         goto RuntimeError;
1051         if(self->bone->flag & BONE_HIDDEN_A)
1052                 if (PyList_Append(list, 
1053                         EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
1054                         goto RuntimeError;
1055         if(self->bone->flag & BONE_ROOTSEL)
1056                 if (PyList_Append(list, 
1057                         EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
1058                         goto RuntimeError;
1059         if(self->bone->flag & BONE_SELECTED)
1060                 if (PyList_Append(list, 
1061                         EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
1062                         goto RuntimeError;
1063         if(self->bone->flag & BONE_TIPSEL)
1064                 if (PyList_Append(list, 
1065                         EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
1066                         goto RuntimeError;
1067
1068         return list;
1069         
1070 RuntimeError:
1071         Py_XDECREF(list);
1072         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1073                 sBoneError, "getOptions(): ", "Internal failure!");
1074 }
1075 //------------------------Bone.connected (set)
1076 static int Bone_setOptions(BPy_Bone *self, PyObject *value, void *closure)
1077 {  
1078   return EXPP_intError(PyExc_ValueError, "%s%s", 
1079                 sBoneError, "You must first call .makeEditable() to edit the armature");
1080 }
1081 //------------------------Bone.parent (get)
1082 static PyObject *Bone_getParent(BPy_Bone *self, void *closure)
1083 {
1084         if (self->bone->parent)
1085                 return PyBone_FromBone(self->bone->parent);
1086         else
1087                 Py_RETURN_NONE;
1088 }
1089 //------------------------Bone.parent (set)
1090 static int Bone_setParent(BPy_Bone *self, PyObject *value, void *closure)
1091 {  
1092   return EXPP_intError(PyExc_ValueError, "%s%s", 
1093                 sBoneError, "You must first call .makeEditable() to edit the armature");
1094 }
1095 //------------------------Bone.children (get)
1096 static PyObject *Bone_getChildren(BPy_Bone *self, void *closure)
1097 {
1098         PyObject *list = PyList_New(0);
1099         Bone *bone = NULL;
1100         PyObject *py_bone = NULL;
1101
1102         if (self->bone->childbase.first){
1103                 for (bone = self->bone->childbase.first; bone; bone = bone->next){
1104                         py_bone = PyBone_FromBone(bone);
1105                         if (py_bone == NULL)
1106                                 goto RuntimeError;
1107                         if (PyList_Append(list, py_bone) == -1)
1108                                 goto RuntimeError;
1109                         Py_DECREF(py_bone);
1110                 }
1111         }
1112         return list;
1113         
1114 RuntimeError:
1115         Py_XDECREF(list);
1116         Py_XDECREF(py_bone);
1117         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
1118                 sBoneError, "Internal error trying to wrap blender bones!");
1119 }
1120 //------------------------Bone.children (set)
1121 static int Bone_setChildren(BPy_Bone *self, PyObject *value, void *closure)
1122 {  
1123   return EXPP_intError(PyExc_ValueError, "%s%s", 
1124                 sBoneError, "You must first call .makeEditable() to edit the armature");
1125 }
1126 //------------------------Bone.matrix (get)
1127 static PyObject *Bone_getMatrix(BPy_Bone *self, void *closure)
1128 {
1129         PyObject *val1 = newMatrixObject((float*)self->bone->bone_mat, 3,3, Py_WRAP);
1130         PyObject *val2 = newMatrixObject((float*)self->bone->arm_mat, 4,4, Py_WRAP);
1131         PyObject *ret = Py_BuildValue("{s:O, s:O}", 
1132                 "BONESPACE", val1, "ARMATURESPACE", val2);
1133         Py_DECREF(val1);
1134         Py_DECREF(val2);
1135         return ret;
1136     
1137     
1138 }
1139 //------------------------Bone.matrix (set)
1140 static int Bone_setMatrix(BPy_Bone *self, PyObject *value, void *closure)
1141 {  
1142   return EXPP_intError(PyExc_ValueError, "%s%s", 
1143                 sBoneError, "You must first call .makeEditable() to edit the armature");
1144 }
1145 //------------------------Bone.length (get)
1146 static PyObject *Bone_getLength(BPy_Bone *self, void *closure)
1147 {
1148     return PyFloat_FromDouble(self->bone->length);
1149 }
1150 //------------------------Bone.length (set)
1151 static int Bone_setLength(BPy_Bone *self, PyObject *value, void *closure)
1152 {  
1153   return EXPP_intError(PyExc_ValueError, "%s%s", 
1154                 sBoneError, "You must first call .makeEditable() to edit the armature");
1155 }
1156
1157 //------------------------Bone.headRadius (get)
1158 static PyObject *Bone_getHeadRadius(BPy_Bone *self, void *closure)
1159 {
1160
1161         if (self->bone->parent && self->bone->flag & BONE_CONNECTED)
1162                 return PyFloat_FromDouble(self->bone->parent->rad_tail);
1163         else
1164                 return PyFloat_FromDouble(self->bone->rad_head);
1165 }
1166 //------------------------Bone.headRadius (set)
1167 static int Bone_setHeadRadius(BPy_Bone *self, PyObject *value, void *closure)
1168 {  
1169         float radius;
1170         if (!PyArg_Parse(value, "f", &radius))
1171                 goto AttributeError;
1172         CLAMP(radius, 0.0f, 10000.0f);
1173
1174         if (self->bone->parent && self->bone->flag & BONE_CONNECTED)
1175                 self->bone->parent->rad_tail= radius;
1176         else
1177                 self->bone->rad_head= radius;
1178         return 0;
1179
1180 AttributeError:
1181         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
1182                 sEditBoneError, ".headRadius: ", "expects a float");
1183 }
1184
1185 //------------------------Bone.tailRadius (get)
1186 static PyObject *Bone_getTailRadius(BPy_Bone *self, void *closure)
1187 {
1188         return PyFloat_FromDouble(self->bone->rad_tail);
1189 }
1190
1191 //------------------------Bone.headRadius (set)
1192 static int Bone_setTailRadius(BPy_Bone *self, PyObject *value, void *closure)
1193 {  
1194         float radius;
1195         if (!PyArg_Parse(value, "f", &radius))
1196                 goto AttributeError;
1197         CLAMP(radius, 0.0f, 10000.0f);
1198         self->bone->rad_tail= radius;
1199         return 0;
1200
1201 AttributeError:
1202         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
1203                 sEditBoneError, ".headRadius: ", "expects a float");
1204 }
1205
1206 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
1207 //------------------------tp_methods
1208 //This contains a list of all methods the object contains
1209 static PyMethodDef BPy_Bone_methods[] = {
1210         {"hasParent", (PyCFunction) Bone_hasParent, METH_NOARGS, 
1211                 "() - True/False - Bone has a parent"},
1212         {"hasChildren", (PyCFunction) Bone_hasChildren, METH_NOARGS, 
1213                 "() - True/False - Bone has 1 or more children"},
1214         {"getAllChildren", (PyCFunction) Bone_getAllChildren, METH_NOARGS, 
1215                 "() - All the children for this bone - including children's children"},
1216         {NULL, NULL, 0, NULL}
1217 };
1218 //------------------------tp_getset
1219 //This contains methods for attributes that require checking
1220 static PyGetSetDef BPy_Bone_getset[] = {
1221         {"name", (getter)Bone_getName, (setter)Bone_setName, 
1222                 "The name of the bone", NULL},
1223         {"roll", (getter)Bone_getRoll, (setter)Bone_setRoll, 
1224                 "The roll (or rotation around the axis) of the bone", NULL},
1225         {"head", (getter)Bone_getHead, (setter)Bone_setHead, 
1226                 "The start point of the bone", NULL},
1227         {"tail", (getter)Bone_getTail, (setter)Bone_setTail, 
1228                 "The end point of the bone", NULL},
1229         {"matrix", (getter)Bone_getMatrix, (setter)Bone_setMatrix, 
1230                 "The matrix of the bone", NULL},
1231         {"weight", (getter)Bone_getWeight, (setter)Bone_setWeight, 
1232                 "The weight of the bone in relation to a parented mesh", NULL},
1233         {"deform_dist", (getter)Bone_getDeform_dist, (setter)Bone_setDeform_dist, 
1234                 "The distance at which deformation has effect", NULL},
1235         {"subdivisions", (getter)Bone_getSubdivisions, (setter)Bone_setSubdivisions, 
1236                 "The number of subdivisions (for B-Bones)", NULL},
1237         {"options", (getter)Bone_getOptions, (setter)Bone_setOptions, 
1238                 "The options effective on this bone", NULL},
1239         {"parent", (getter)Bone_getParent, (setter)Bone_setParent, 
1240                 "The parent bone of this bone", NULL},
1241         {"children", (getter)Bone_getChildren, (setter)Bone_setChildren, 
1242                 "The child bones of this bone", NULL},
1243         {"length", (getter)Bone_getLength, (setter)Bone_setLength, 
1244                 "The length of this bone", NULL},
1245         {"tailRadius", (getter)Bone_getTailRadius, (setter)Bone_setTailRadius, 
1246                 "Set the radius of this bones tip", NULL},
1247         {"headRadius", (getter)Bone_getHeadRadius, (setter)Bone_setHeadRadius, 
1248                 "Set the radius of this bones head", NULL},
1249         {NULL, NULL, NULL, NULL,NULL}
1250 };
1251 //------------------------tp_repr
1252 //This is the string representation of the object
1253 static PyObject *Bone_repr(BPy_Bone *self)
1254 {
1255         return PyString_FromFormat( "[Bone \"%s\"]", self->bone->name ); 
1256 }
1257 static int Bone_compare( BPy_Bone * a, BPy_Bone * b )
1258 {
1259         return ( a->bone == b->bone ) ? 0 : -1;
1260 }
1261 //------------------------tp_dealloc
1262 //This tells how to 'tear-down' our object when ref count hits 0
1263 static void Bone_dealloc(BPy_Bone * self)
1264 {
1265         Bone_Type.tp_free(self);
1266         return;
1267 }
1268 //------------------------tp_doc
1269 //The __doc__ string for this object
1270 static char BPy_Bone_doc[] = "This object wraps a Blender Boneobject.\n\
1271                                           This object is a subobject of the Armature object.";
1272
1273 //------------------TYPE_OBECT DEFINITION--------------------------
1274 PyTypeObject Bone_Type = {
1275         PyObject_HEAD_INIT(NULL)   //tp_head
1276         0,                                                                              //tp_internal
1277         "Bone",                                                                 //tp_name
1278         sizeof(BPy_Bone),                                               //tp_basicsize
1279         0,                                                                              //tp_itemsize
1280         (destructor)Bone_dealloc,                               //tp_dealloc
1281         0,                                                                              //tp_print
1282         0,                                                                              //tp_getattr
1283         0,                                                                              //tp_setattr
1284         (cmpfunc) Bone_compare,                                 //tp_compare
1285         (reprfunc) Bone_repr,                                   //tp_repr
1286         0,                                                                              //tp_as_number
1287         0,                                                                              //tp_as_sequence
1288         0,                                                                              //tp_as_mapping
1289         0,                                                                              //tp_hash
1290         0,                                                                              //tp_call
1291         0,                                                                              //tp_str
1292         0,                                                                              //tp_getattro
1293         0,                                                                              //tp_setattro
1294         0,                                                                              //tp_as_buffer
1295         Py_TPFLAGS_DEFAULT,         //tp_flags
1296         BPy_Bone_doc,                                   //tp_doc
1297         0,                                                                              //tp_traverse
1298         0,                                                                              //tp_clear
1299         0,                                                                              //tp_richcompare
1300         0,                                                                              //tp_weaklistoffset
1301         0,                                                                              //tp_iter
1302         0,                                                                              //tp_iternext
1303         BPy_Bone_methods,                               //tp_methods
1304         0,                                                                              //tp_members
1305         BPy_Bone_getset,                                //tp_getset
1306         0,                                                                              //tp_base
1307         0,                                                                              //tp_dict
1308         0,                                                                              //tp_descr_get
1309         0,                                                                              //tp_descr_set
1310         0,                                                                              //tp_dictoffset
1311         0,                                                                              //tp_init
1312         0,                                                                              //tp_alloc
1313         0,                                                                              //tp_new
1314         0,                                                                              //tp_free
1315         0,                                                                              //tp_is_gc
1316         0,                                                                              //tp_bases
1317         0,                                                                              //tp_mro
1318         0,                                                                              //tp_cache
1319         0,                                                                              //tp_subclasses
1320         0,                                                                              //tp_weaklist
1321         0                                                                               //tp_del
1322 };
1323 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1324 //-----------------(internal)
1325 //Converts a struct EditBone to a BPy_EditBone
1326 PyObject *PyEditBone_FromEditBone(struct EditBone *editbone)
1327 {
1328         BPy_EditBone *py_editbone = NULL;
1329
1330         py_editbone = (BPy_EditBone*)EditBone_Type.tp_alloc(&EditBone_Type, 0); //*new*
1331         if (!py_editbone)
1332                 goto RuntimeError;
1333
1334         py_editbone->editbone = editbone;
1335
1336         return (PyObject *) py_editbone;
1337
1338 RuntimeError:
1339         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1340                 sEditBoneError, "PyEditBone_FromEditBone: ", "Internal Error Ocurred");
1341 }
1342 //-----------------(internal)
1343 //Converts a struct Bone to a BPy_Bone
1344 PyObject *PyBone_FromBone(struct Bone *bone)
1345 {
1346         BPy_Bone *py_Bone = ( BPy_Bone * ) PyObject_NEW( BPy_Bone, &Bone_Type );
1347         
1348         py_Bone->bone = bone;
1349
1350         return (PyObject *) py_Bone;
1351 }
1352 //-----------------(internal)
1353 //Converts a PyBone to a bBone
1354 struct Bone *PyBone_AsBone(BPy_Bone *py_Bone)
1355 {
1356         return (py_Bone->bone);
1357 }