Fix for bug #5250: inaccurate conversion between edit and pose mode bones.
[blender-staging.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                         return EXPP_incr_ret(Py_True);
92                 else
93                         return EXPP_incr_ret(Py_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                 return EXPP_incr_ret(Py_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 EXPP_incr_ret(list);
410
411 RuntimeError:
412         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
413                 sEditBoneError, ".options: ", "Internal failure!");
414 }
415 //----------------------(internal) EditBone_CheckValidConstant
416 static int EditBone_CheckValidConstant(PyObject *constant)
417 {
418         PyObject *name = NULL;
419
420         if (constant){
421                 if (BPy_Constant_Check(constant)){
422                         name = PyDict_GetItemString(((BPy_constant*)constant)->dict, "name");
423                         if (!name) 
424                                 return 0;
425                         if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
426                                 !STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED")      &&
427                                 !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
428                                 return 0;
429                         else
430                                 return 1;
431                 }else{
432                         return 0;
433                 }
434         }else{
435                 return 0;
436         }
437 }
438
439 //------------------------EditBone.options (set)
440 static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closure)
441 {  
442         int length, numeric_value, new_flag = 0, x;
443         PyObject *val = NULL, *index = NULL;
444
445         if (PyList_Check(value)){
446                 length = PyList_Size(value);
447                 for (x = 0; x < length; x++){
448                         index = PyList_GetItem(value, x);
449                         if (!EditBone_CheckValidConstant(index))
450                                 goto AttributeError2;
451                         val = PyDict_GetItemString(((BPy_constant*)index)->dict, "value");
452                         if (PyInt_Check(val)){
453                                 numeric_value = (int)PyInt_AS_LONG(val);
454                                 new_flag |= numeric_value;
455                         }else{
456                                 goto AttributeError2;
457                         }
458                 }
459
460                 //set the options
461                 if(self->editbone){
462                         //make sure the 'connected' property is set up correctly
463                         if (new_flag & BONE_CONNECTED) {
464                                 if(!self->editbone->parent)
465                                         goto AttributeError3;
466                                 else
467                                         VECCOPY(self->editbone->head, self->editbone->parent->tail);
468                         }
469                         self->editbone->flag = new_flag;
470                 }else{
471                         self->flag = new_flag;
472                 }
473                 return 0;
474         }else if (BPy_Constant_Check(value)){
475                 if (!EditBone_CheckValidConstant(value))
476                         goto AttributeError2;
477                 val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
478                 if (PyInt_Check(val)){
479                         numeric_value = (int)PyInt_AS_LONG(val);
480
481                         if(self->editbone){
482                                 //make sure the 'connected' property is set up correctly
483                                 if (numeric_value & BONE_CONNECTED) {
484                                         if(!self->editbone->parent)
485                                                 goto AttributeError3;
486                                         else
487                                                 VECCOPY(self->editbone->head, self->editbone->parent->tail);
488                                 }
489                                 self->editbone->flag = numeric_value;
490                         }else{
491                                 self->flag = numeric_value;
492                         }
493                         return 0;
494                 }else{
495                         goto AttributeError2;
496                 }
497         }else{
498                 goto AttributeError1;
499         }
500
501 AttributeError1:
502         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
503                 sEditBoneError, ".options: ", "Expects a constant or list of constants");
504 AttributeError2:
505         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
506                 sEditBoneError, ".options: ", "Please use a constant defined in the Armature module");
507 AttributeError3:
508         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
509                 sEditBoneError, ".options: ", "You can't connect to parent because no parent is set");
510 }
511 //------------------------EditBone.parent (get)
512 static PyObject *EditBone_getParent(BPy_EditBone *self, void *closure)
513 {
514         if (self->editbone){
515                 if (self->editbone->parent)
516                         return PyEditBone_FromEditBone(self->editbone->parent);
517                 else
518                         return EXPP_incr_ret(Py_None);
519         }else{
520                 return EXPP_incr_ret(Py_None); //not in the list yet can't have a parent
521         }
522 }
523 //------------------------EditBone.parent (set)
524 static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure)
525 {  
526         BPy_EditBone *parent = NULL;
527
528         if (!PyArg_Parse(value, "O!", &EditBone_Type, &parent))
529                 goto AttributeError;
530
531         if (!parent->editbone)
532                 goto AttributeError2;
533
534         if (self->editbone){
535         self->editbone->parent = parent->editbone;
536         }else{
537                 self->parent = parent->editbone;
538         }
539         return 0;
540
541 AttributeError:
542         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
543                 sEditBoneError, ".parent: ", "expects a EditBone Object");
544 AttributeError2:
545         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
546                 sEditBoneError, ".parent: ", "This object is not in the armature's bone list!");
547 }
548 //------------------------EditBone.matrix (get)
549 static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
550 {
551         float boneMatrix[3][3];
552         float   axis[3];
553
554         if (self->editbone){
555                 VECSUB(axis, self->editbone->tail, self->editbone->head);
556                 vec_roll_to_mat3(axis, self->editbone->roll, boneMatrix);
557         }else{
558                 VECSUB(axis, self->tail, self->head);
559                 vec_roll_to_mat3(axis, self->roll, boneMatrix);
560         }
561
562     return newMatrixObject((float*)boneMatrix, 3, 3, Py_NEW);
563 }
564 //------------------------EditBone.matrix (set)
565 static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
566 {  
567         PyObject *matrix;
568         float roll, length, vec[3], axis[3], mat3[3][3];
569
570         if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
571                 goto AttributeError;
572
573         //make sure we have the right sizes
574         if (((MatrixObject*)matrix)->rowSize != 3 && ((MatrixObject*)matrix)->colSize != 3){
575                 if(((MatrixObject*)matrix)->rowSize != 4 && ((MatrixObject*)matrix)->colSize != 4){
576                         goto AttributeError;
577                 }
578         }
579                 
580         /*vec will be a normalized directional vector
581         * together with the length of the old bone vec*length = the new vector*/
582         /*The default rotation is 0,1,0 on the Y axis (see mat3_to_vec_roll)*/
583         if (((MatrixObject*)matrix)->rowSize == 4){
584                 Mat3CpyMat4(mat3, ((float (*)[4])*((MatrixObject*)matrix)->matrix));
585         }else{
586                 Mat3CpyMat3(mat3, ((float (*)[3])*((MatrixObject*)matrix)->matrix));
587         }
588         mat3_to_vec_roll(mat3, vec, &roll);
589
590         //if a 4x4 matrix was passed we'll translate the vector otherwise not
591         if (self->editbone){
592                 self->editbone->roll = roll;
593                 VecSubf(axis, self->editbone->tail, self->editbone->head);
594                 length =  VecLength(axis);
595                 VecMulf(vec, length);
596                 if (((MatrixObject*)matrix)->rowSize == 4)
597                         VecCopyf(self->editbone->head, ((MatrixObject*)matrix)->matrix[3]);
598                 VecAddf(self->editbone->tail, self->editbone->head, vec);
599                 return 0;
600         }else{
601                 self->roll = roll;
602                 VecSubf(axis, self->tail, self->head);
603                 length =  VecLength(axis);
604                 VecMulf(vec, length);
605                 if (((MatrixObject*)matrix)->rowSize == 4)
606                         VecCopyf(self->head, ((MatrixObject*)matrix)->matrix[3]);
607                 VecAddf(self->tail, self->head, vec);
608                 return 0;
609         }
610
611 AttributeError:
612         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
613                 sEditBoneError, ".matrix: ", "expects a 3x3 or 4x4 Matrix Object");
614 }
615 //------------------------Bone.length (get)
616 static PyObject *EditBone_getLength(BPy_EditBone *self, void *closure)
617 {
618         float delta[3];
619         double dot = 0.0f;
620         int x;
621
622         if (self->editbone){
623                 VECSUB(delta, self->editbone->tail, self->editbone->head);
624                 for(x = 0; x < 3; x++){
625                         dot += (delta[x] * delta[x]);
626                 }
627                 return PyFloat_FromDouble(sqrt(dot));
628         }else{
629                 VECSUB(delta, self->tail, self->head);
630                 for(x = 0; x < 3; x++){
631                         dot += (delta[x] * delta[x]);
632                 }
633                 return PyFloat_FromDouble(sqrt(dot));
634         }
635 }
636 //------------------------Bone.length (set)
637 static int EditBone_setLength(BPy_EditBone *self, PyObject *value, void *closure)
638 {  
639         printf("Sorry this isn't implemented yet.... :/");
640         return 1;
641 }
642
643
644 //------------------------Bone.headRadius (get)
645 static PyObject *EditBone_getHeadRadius(BPy_EditBone *self, void *closure)
646 {
647         if (self->editbone)
648                 if (self->editbone->parent && self->editbone->flag & BONE_CONNECTED)
649                         return PyFloat_FromDouble(self->editbone->parent->rad_tail);
650                 else
651                         return PyFloat_FromDouble(self->editbone->rad_head);
652         else
653                 if (self->parent && self->flag & BONE_CONNECTED)
654                         return PyFloat_FromDouble(self->parent->rad_tail);
655                 else
656                         return PyFloat_FromDouble(self->rad_head);
657 }
658 //------------------------Bone.headRadius (set)
659 static int EditBone_setHeadRadius(BPy_EditBone *self, PyObject *value, void *closure)
660 {  
661         float radius;
662         if (!PyArg_Parse(value, "f", &radius))
663                 goto AttributeError;
664         CLAMP(radius, 0.0f, 10000.0f);
665
666         if (self->editbone)
667                 if (self->editbone->parent && self->editbone->flag & BONE_CONNECTED)
668                         self->editbone->parent->rad_tail= radius;
669                 else
670                         self->editbone->rad_head= radius;
671         else
672                 if (self->parent && self->flag & BONE_CONNECTED)
673                         self->parent->rad_tail= radius;
674                 else
675                         self->rad_head= radius;
676         return 0;
677
678 AttributeError:
679         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
680                 sEditBoneError, ".headRadius: ", "expects a float");
681 }
682
683
684 //------------------------Bone.tailRadius (get)
685 static PyObject *EditBone_getTailRadius(BPy_EditBone *self, void *closure)
686 {
687         if (self->editbone)
688                 return PyFloat_FromDouble(self->editbone->rad_tail);
689         else
690                 return PyFloat_FromDouble(self->rad_tail);
691 }
692 //------------------------Bone.tailRadius (set)
693 static int EditBone_setTailRadius(BPy_EditBone *self, PyObject *value, void *closure)
694 {  
695         float radius;
696         if (!PyArg_Parse(value, "f", &radius))
697                 goto AttributeError;
698         CLAMP(radius, 0.0f, 10000.0f);
699
700         if (self->editbone)
701                 self->editbone->rad_tail = radius;
702         else
703                 self->rad_tail = radius;
704         return 0;
705
706 AttributeError:
707         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
708                 sEditBoneError, ".tailRadius: ", "expects a float");
709 }
710
711
712 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
713 //------------------------tp_methods
714 //This contains a list of all methods the object contains
715 static PyMethodDef BPy_EditBone_methods[] = {
716         {"hasParent", (PyCFunction) EditBone_hasParent, METH_NOARGS, 
717                 "() - True/False - Bone has a parent"},
718         {"clearParent", (PyCFunction) EditBone_clearParent, METH_NOARGS, 
719                 "() - sets the parent to None"},
720         {NULL, NULL, 0, NULL}
721 };
722 ///------------------------tp_getset
723 //This contains methods for attributes that require checking
724 static PyGetSetDef BPy_EditBone_getset[] = {
725         {"name", (getter)EditBone_getName, (setter)EditBone_setName, 
726                 "The name of the bone", NULL},
727         {"roll", (getter)EditBone_getRoll, (setter)EditBone_setRoll, 
728                 "The roll (or rotation around the axis) of the bone", NULL},
729         {"head", (getter)EditBone_getHead, (setter)EditBone_setHead, 
730                 "The start point of the bone", NULL},
731         {"tail", (getter)EditBone_getTail, (setter)EditBone_setTail, 
732                 "The end point of the bone", NULL},
733         {"matrix", (getter)EditBone_getMatrix, (setter)EditBone_setMatrix, 
734                 "The matrix of the bone", NULL},
735         {"weight", (getter)EditBone_getWeight, (setter)EditBone_setWeight, 
736                 "The weight of the bone in relation to a parented mesh", NULL},
737         {"deformDist", (getter)EditBone_getDeform_dist, (setter)EditBone_setDeform_dist, 
738                 "The distance at which deformation has effect", NULL},
739         {"subdivisions", (getter)EditBone_getSubdivisions, (setter)EditBone_setSubdivisions, 
740                 "The number of subdivisions (for B-Bones)", NULL},
741         {"options", (getter)EditBone_getOptions, (setter)EditBone_setOptions, 
742                 "The options effective on this bone", NULL},
743         {"parent", (getter)EditBone_getParent, (setter)EditBone_setParent, 
744                 "The parent bone of this bone", NULL},
745         {"length", (getter)EditBone_getLength, (setter)EditBone_setLength, 
746                 "The length of this bone", NULL},
747         {"tailRadius", (getter)EditBone_getTailRadius, (setter)EditBone_setTailRadius, 
748                 "Set the radius of this bones tip", NULL},
749         {"headRadius", (getter)EditBone_getHeadRadius, (setter)EditBone_setHeadRadius, 
750                 "Set the radius of this bones head", NULL},
751         {NULL, NULL, NULL, NULL,NULL}
752 };
753
754 //------------------------tp_repr
755 //This is the string representation of the object
756 static PyObject *EditBone_repr(BPy_EditBone *self)
757 {
758         if (self->editbone)
759                 return PyString_FromFormat( "[EditBone \"%s\"]", self->editbone->name ); 
760         else
761                 return PyString_FromFormat( "[EditBone \"%s\"]", self->name ); 
762 }
763
764 //------------------------tp_doc
765 //The __doc__ string for this object
766 static char BPy_EditBone_doc[] = "This is an internal subobject of armature\
767 designed to act as a wrapper for an 'edit bone'.";
768
769 //------------------------tp_new
770 //This methods creates a new object (note it does not initialize it - only the building)
771 static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
772 {
773         char *name = "myEditBone";
774         BPy_EditBone *py_editBone = NULL;
775         float head[3], tail[3];
776
777         py_editBone = (BPy_EditBone*)type->tp_alloc(type, 0); //new
778         if (py_editBone == NULL)
779                 goto RuntimeError;
780
781         //this pointer will be set when this bone is placed in ListBase
782         //otherwise this will act as a py_object
783         py_editBone->editbone = NULL;
784
785         unique_editbone_name(name);
786         BLI_strncpy(py_editBone->name, name, 32);
787         py_editBone->parent = NULL;
788         py_editBone->weight= 1.0f;
789         py_editBone->dist= 0.25f;
790         py_editBone->xwidth= 0.1f;
791         py_editBone->zwidth= 0.1f;
792         py_editBone->ease1= 1.0f;
793         py_editBone->ease2= 1.0f;
794         py_editBone->rad_head= 0.10f;
795         py_editBone->rad_tail= 0.05f;
796         py_editBone->segments= 1;
797         py_editBone->flag = 0;
798         py_editBone->roll = 0.0f;
799
800         head[0] = head[1] = head[2] = 0.0f;
801         tail[1] = tail[2] = 0.0f;
802         tail[0] = 1.0f;
803         VECCOPY(py_editBone->head, head);
804         VECCOPY(py_editBone->tail, tail);
805
806         return (PyObject*)py_editBone;
807
808 RuntimeError:
809         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
810                 sEditBoneError, " __new__: ", "Internal Error");
811 }
812 //------------------------tp_dealloc
813 //This tells how to 'tear-down' our object when ref count hits 0
814 //the struct EditBone pointer will be handled by the BPy_BonesDict class
815 static void EditBone_dealloc(BPy_EditBone * self)
816 {
817         EditBone_Type.tp_free(self);
818         return;
819 }
820 //------------------TYPE_OBECT DEFINITION--------------------------
821 PyTypeObject EditBone_Type = {
822         PyObject_HEAD_INIT(NULL)       //tp_head
823         0,                                                                                      //tp_internal
824         "EditBone",                                                             //tp_name
825         sizeof(BPy_EditBone),                           //tp_basicsize
826         0,                                                                                      //tp_itemsize
827         (destructor)EditBone_dealloc,           //tp_dealloc
828         0,                                                                                      //tp_print
829         0,                                                                                      //tp_getattr
830         0,                                                                                      //tp_setattr
831         0,                                                                                      //tp_compare
832         (reprfunc)EditBone_repr,                        //tp_repr
833         0,                                                                                      //tp_as_number
834         0,                                                                                      //tp_as_sequence
835         0,                                                                                      //tp_as_mapping
836         0,                                                                                      //tp_hash
837         0,                                                                                      //tp_call
838         0,                                                                                      //tp_str
839         0,                                                                                      //tp_getattro
840         0,                                                                                      //tp_setattro
841         0,                                                                                      //tp_as_buffer
842         Py_TPFLAGS_DEFAULT,                             //tp_flags
843         BPy_EditBone_doc,                                       //tp_doc
844         0,                                                                                      //tp_traverse
845         0,                                                                                      //tp_clear
846         0,                                                                                      //tp_richcompare
847         0,                                                                                      //tp_weaklistoffset
848         0,                                                                                      //tp_iter
849         0,                                                                                      //tp_iternext
850         BPy_EditBone_methods,                           //tp_methods
851         0,                                                                                      //tp_members
852         BPy_EditBone_getset,                            //tp_getset
853         0,                                                                                      //tp_base
854         0,                                                                                      //tp_dict
855         0,                                                                                      //tp_descr_get
856         0,                                                                                      //tp_descr_set
857         0,                                                                                      //tp_dictoffset
858         0,                                                                                      //tp_init
859         0,                                                                                      //tp_alloc
860         (newfunc)EditBone_new,                  //tp_new
861         0,                                                                                      //tp_free
862         0,                                                                                      //tp_is_gc
863         0,                                                                                      //tp_bases
864         0,                                                                                      //tp_mro
865         0,                                                                                      //tp_cache
866         0,                                                                                      //tp_subclasses
867         0,                                                                                      //tp_weaklist
868         0                                                                                       //tp_del
869 };
870
871 //------------------METHOD IMPLEMENTATIONS--------------------------------
872 //------------------------(internal) PyBone_ChildrenAsList
873 static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){
874         Bone *bone = NULL;
875         PyObject *py_bone = NULL;
876
877         for (bone = bones->first; bone; bone = bone->next){
878                 py_bone = PyBone_FromBone(bone);
879                 if (py_bone == NULL)
880                         return 0;
881
882                 if(PyList_Append(list, py_bone) == -1){
883                         goto RuntimeError;
884                 }
885                 if (bone->childbase.first) 
886                         PyBone_ChildrenAsList(list, &bone->childbase);
887         }
888         return 1;
889
890 RuntimeError:
891         return EXPP_intError(PyExc_RuntimeError, "%s%s", 
892                 sBoneError, "Internal error trying to wrap blender bones!");
893 }
894 //-------------------------Bone.hasParent()
895 static PyObject *Bone_hasParent(BPy_Bone *self)
896 {
897         if (self->bone->parent)
898                 return EXPP_incr_ret(Py_True);
899         else
900                 return EXPP_incr_ret(Py_False);
901 }
902 //-------------------------Bone.hasChildren()
903 static PyObject *Bone_hasChildren(BPy_Bone *self)
904 {
905         if (self->bone->childbase.first)
906                 return EXPP_incr_ret(Py_True);
907         else
908                 return EXPP_incr_ret(Py_False);
909 }
910 //-------------------------Bone.getAllChildren()
911 static PyObject *Bone_getAllChildren(BPy_Bone *self)
912 {
913         PyObject *list = NULL;
914
915         if (self->bone->childbase.first){
916                 list = PyList_New(0);
917                 if (!PyBone_ChildrenAsList(list, &self->bone->childbase))
918                         return NULL;
919                 return EXPP_incr_ret(list);
920         }else{
921                 return EXPP_incr_ret(Py_None);
922         }
923 }
924 //------------------ATTRIBUTE IMPLEMENTATIONS-----------------------------
925 //------------------------Bone.name (get)
926 static PyObject *Bone_getName(BPy_Bone *self, void *closure)
927 {
928         return PyString_FromString(self->bone->name);
929 }
930 //------------------------Bone.name (set)
931 //check for char[] overflow here...
932 static int Bone_setName(BPy_Bone *self, PyObject *value, void *closure)
933 {  
934   return EXPP_intError(PyExc_ValueError, "%s%s", 
935                 sBoneError, "You must first call .makeEditable() to edit the armature");
936 }
937 //------------------------Bone.roll (get)
938 static PyObject *Bone_getRoll(BPy_Bone *self, void *closure)
939 {
940         return Py_BuildValue("{s:O, s:O}", 
941                 "BONESPACE", PyFloat_FromDouble((self->bone->roll * (180/Py_PI))),
942                 "ARMATURESPACE", PyFloat_FromDouble((boneRoll_ToArmatureSpace(self->bone) * (180/Py_PI))));
943 }
944 //------------------------Bone.roll (set)
945 static int Bone_setRoll(BPy_Bone *self, PyObject *value, void *closure)
946 {  
947   return EXPP_intError(PyExc_ValueError, "%s%s", 
948                 sBoneError, "You must first call .makeEditable() to edit the armature");
949 }
950 //------------------------Bone.head (get)
951 static PyObject *Bone_getHead(BPy_Bone *self, void *closure)
952 {
953         return Py_BuildValue("{s:O, s:O}", 
954                 "BONESPACE", newVectorObject(self->bone->head, 3, Py_WRAP),
955                 "ARMATURESPACE", newVectorObject(self->bone->arm_head, 3, Py_WRAP));
956 }
957 //------------------------Bone.head (set)
958 static int Bone_setHead(BPy_Bone *self, PyObject *value, void *closure)
959 {  
960   return EXPP_intError(PyExc_ValueError, "%s%s", 
961                 sBoneError, "You must first call .makeEditable() to edit the armature");
962 }
963 //------------------------Bone.tail (get)
964 static PyObject *Bone_getTail(BPy_Bone *self, void *closure)
965 {
966     return Py_BuildValue("{s:O, s:O}", 
967                 "BONESPACE", newVectorObject(self->bone->tail, 3, Py_WRAP),
968                 "ARMATURESPACE", newVectorObject(self->bone->arm_tail, 3, Py_WRAP));
969 }
970 //------------------------Bone.tail (set)
971 static int Bone_setTail(BPy_Bone *self, PyObject *value, void *closure)
972 {  
973   return EXPP_intError(PyExc_ValueError, "%s%s", 
974                 sBoneError, "You must first call .makeEditable() to edit the armature");
975 }
976 //------------------------Bone.weight (get)
977 static PyObject *Bone_getWeight(BPy_Bone *self, void *closure)
978 {
979         return PyFloat_FromDouble(self->bone->weight);
980 }
981 //------------------------Bone.weight (set)
982 static int Bone_setWeight(BPy_Bone *self, PyObject *value, void *closure)
983 {  
984   return EXPP_intError(PyExc_ValueError, "%s%s", 
985                 sBoneError, "You must first call .makeEditable() to edit the armature");
986 }
987 //------------------------Bone.deform_dist (get)
988 static PyObject *Bone_getDeform_dist(BPy_Bone *self, void *closure)
989 {
990     return PyFloat_FromDouble(self->bone->dist);
991 }
992 //------------------------Bone.deform_dist (set)
993 static int Bone_setDeform_dist(BPy_Bone *self, PyObject *value, void *closure)
994 {  
995   return EXPP_intError(PyExc_ValueError, "%s%s", 
996                 sBoneError, "You must first call .makeEditable() to edit the armature");
997 }
998 //------------------------Bone.subdivisions (get)
999 static PyObject *Bone_getSubdivisions(BPy_Bone *self, void *closure)
1000 {
1001     return PyInt_FromLong(self->bone->segments);
1002 }
1003 //------------------------Bone.subdivisions (set)
1004 static int Bone_setSubdivisions(BPy_Bone *self, PyObject *value, void *closure)
1005 {  
1006   return EXPP_intError(PyExc_ValueError, "%s%s", 
1007                 sBoneError, "You must first call .makeEditable() to edit the armature");
1008 }
1009 //------------------------Bone.connected (get)
1010 static PyObject *Bone_getOptions(BPy_Bone *self, void *closure)
1011 {
1012         PyObject *list = NULL;
1013
1014         list = PyList_New(0);
1015         if (list == NULL)
1016                 goto RuntimeError;
1017
1018         if(self->bone->flag & BONE_CONNECTED)
1019                 if (PyList_Append(list, 
1020                         EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
1021                         goto RuntimeError;
1022         if(self->bone->flag & BONE_HINGE)
1023                 if (PyList_Append(list, 
1024                         EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
1025                         goto RuntimeError;
1026         if(self->bone->flag & BONE_NO_DEFORM)
1027                 if (PyList_Append(list, 
1028                         EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
1029                         goto RuntimeError;
1030         if(self->bone->flag & BONE_MULT_VG_ENV)
1031                 if (PyList_Append(list, 
1032                         EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
1033                         goto RuntimeError;
1034         if(self->bone->flag & BONE_HIDDEN_A)
1035                 if (PyList_Append(list, 
1036                         EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
1037                         goto RuntimeError;
1038         if(self->bone->flag & BONE_ROOTSEL)
1039                 if (PyList_Append(list, 
1040                         EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
1041                         goto RuntimeError;
1042         if(self->bone->flag & BONE_SELECTED)
1043                 if (PyList_Append(list, 
1044                         EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
1045                         goto RuntimeError;
1046         if(self->bone->flag & BONE_TIPSEL)
1047                 if (PyList_Append(list, 
1048                         EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
1049                         goto RuntimeError;
1050
1051         return EXPP_incr_ret(list);
1052
1053 RuntimeError:
1054         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1055                 sBoneError, "getOptions(): ", "Internal failure!");
1056 }
1057 //------------------------Bone.connected (set)
1058 static int Bone_setOptions(BPy_Bone *self, PyObject *value, void *closure)
1059 {  
1060   return EXPP_intError(PyExc_ValueError, "%s%s", 
1061                 sBoneError, "You must first call .makeEditable() to edit the armature");
1062 }
1063 //------------------------Bone.parent (get)
1064 static PyObject *Bone_getParent(BPy_Bone *self, void *closure)
1065 {
1066         if (self->bone->parent)
1067                 return PyBone_FromBone(self->bone->parent);
1068         else
1069                 return EXPP_incr_ret(Py_None);
1070 }
1071 //------------------------Bone.parent (set)
1072 static int Bone_setParent(BPy_Bone *self, PyObject *value, void *closure)
1073 {  
1074   return EXPP_intError(PyExc_ValueError, "%s%s", 
1075                 sBoneError, "You must first call .makeEditable() to edit the armature");
1076 }
1077 //------------------------Bone.children (get)
1078 static PyObject *Bone_getChildren(BPy_Bone *self, void *closure)
1079 {
1080         PyObject *list = NULL;
1081         Bone *bone = NULL;
1082         PyObject *py_bone = NULL;
1083
1084         if (self->bone->childbase.first){
1085                 list = PyList_New(0);
1086                 for (bone = self->bone->childbase.first; bone; bone = bone->next){
1087                         py_bone = PyBone_FromBone(bone);
1088                         if (py_bone == NULL)
1089                                 return 0;
1090                         if(PyList_Append(list, py_bone) == -1){
1091                                 goto RuntimeError;
1092                         }
1093                 }
1094                 return EXPP_incr_ret(list);
1095         }else{
1096                 return EXPP_incr_ret(Py_None);
1097         }
1098
1099 RuntimeError:
1100         return EXPP_objError(PyExc_RuntimeError, "%s%s", 
1101                 sBoneError, "Internal error trying to wrap blender bones!");
1102 }
1103 //------------------------Bone.children (set)
1104 static int Bone_setChildren(BPy_Bone *self, PyObject *value, void *closure)
1105 {  
1106   return EXPP_intError(PyExc_ValueError, "%s%s", 
1107                 sBoneError, "You must first call .makeEditable() to edit the armature");
1108 }
1109 //------------------------Bone.matrix (get)
1110 static PyObject *Bone_getMatrix(BPy_Bone *self, void *closure)
1111 {
1112     return Py_BuildValue("{s:O, s:O}", 
1113                 "BONESPACE", newMatrixObject((float*)self->bone->bone_mat, 3,3, Py_WRAP),
1114                 "ARMATURESPACE", newMatrixObject((float*)self->bone->arm_mat, 4,4, Py_WRAP));
1115 }
1116 //------------------------Bone.matrix (set)
1117 static int Bone_setMatrix(BPy_Bone *self, PyObject *value, void *closure)
1118 {  
1119   return EXPP_intError(PyExc_ValueError, "%s%s", 
1120                 sBoneError, "You must first call .makeEditable() to edit the armature");
1121 }
1122 //------------------------Bone.length (get)
1123 static PyObject *Bone_getLength(BPy_Bone *self, void *closure)
1124 {
1125     return PyFloat_FromDouble(self->bone->length);
1126 }
1127 //------------------------Bone.length (set)
1128 static int Bone_setLength(BPy_Bone *self, PyObject *value, void *closure)
1129 {  
1130   return EXPP_intError(PyExc_ValueError, "%s%s", 
1131                 sBoneError, "You must first call .makeEditable() to edit the armature");
1132 }
1133
1134 //------------------------Bone.headRadius (get)
1135 static PyObject *Bone_getHeadRadius(BPy_Bone *self, void *closure)
1136 {
1137
1138         if (self->bone->parent && self->bone->flag & BONE_CONNECTED)
1139                 return PyFloat_FromDouble(self->bone->parent->rad_tail);
1140         else
1141                 return PyFloat_FromDouble(self->bone->rad_head);
1142 }
1143 //------------------------Bone.headRadius (set)
1144 static int Bone_setHeadRadius(BPy_Bone *self, PyObject *value, void *closure)
1145 {  
1146         float radius;
1147         if (!PyArg_Parse(value, "f", &radius))
1148                 goto AttributeError;
1149         CLAMP(radius, 0.0f, 10000.0f);
1150
1151         if (self->bone->parent && self->bone->flag & BONE_CONNECTED)
1152                 self->bone->parent->rad_tail= radius;
1153         else
1154                 self->bone->rad_head= radius;
1155         return 0;
1156
1157 AttributeError:
1158         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
1159                 sEditBoneError, ".headRadius: ", "expects a float");
1160 }
1161
1162 //------------------------Bone.tailRadius (get)
1163 static PyObject *Bone_getTailRadius(BPy_Bone *self, void *closure)
1164 {
1165         return PyFloat_FromDouble(self->bone->rad_tail);
1166 }
1167
1168 //------------------------Bone.headRadius (set)
1169 static int Bone_setTailRadius(BPy_Bone *self, PyObject *value, void *closure)
1170 {  
1171         float radius;
1172         if (!PyArg_Parse(value, "f", &radius))
1173                 goto AttributeError;
1174         CLAMP(radius, 0.0f, 10000.0f);
1175         self->bone->rad_tail= radius;
1176         return 0;
1177
1178 AttributeError:
1179         return EXPP_intError(PyExc_AttributeError, "%s%s%s",
1180                 sEditBoneError, ".headRadius: ", "expects a float");
1181 }
1182
1183 //------------------TYPE_OBECT IMPLEMENTATION--------------------------
1184 //------------------------tp_methods
1185 //This contains a list of all methods the object contains
1186 static PyMethodDef BPy_Bone_methods[] = {
1187         {"hasParent", (PyCFunction) Bone_hasParent, METH_NOARGS, 
1188                 "() - True/False - Bone has a parent"},
1189         {"hasChildren", (PyCFunction) Bone_hasChildren, METH_NOARGS, 
1190                 "() - True/False - Bone has 1 or more children"},
1191         {"getAllChildren", (PyCFunction) Bone_getAllChildren, METH_NOARGS, 
1192                 "() - All the children for this bone - including children's children"},
1193         {NULL, NULL, 0, NULL}
1194 };
1195 //------------------------tp_getset
1196 //This contains methods for attributes that require checking
1197 static PyGetSetDef BPy_Bone_getset[] = {
1198         {"name", (getter)Bone_getName, (setter)Bone_setName, 
1199                 "The name of the bone", NULL},
1200         {"roll", (getter)Bone_getRoll, (setter)Bone_setRoll, 
1201                 "The roll (or rotation around the axis) of the bone", NULL},
1202         {"head", (getter)Bone_getHead, (setter)Bone_setHead, 
1203                 "The start point of the bone", NULL},
1204         {"tail", (getter)Bone_getTail, (setter)Bone_setTail, 
1205                 "The end point of the bone", NULL},
1206         {"matrix", (getter)Bone_getMatrix, (setter)Bone_setMatrix, 
1207                 "The matrix of the bone", NULL},
1208         {"weight", (getter)Bone_getWeight, (setter)Bone_setWeight, 
1209                 "The weight of the bone in relation to a parented mesh", NULL},
1210         {"deform_dist", (getter)Bone_getDeform_dist, (setter)Bone_setDeform_dist, 
1211                 "The distance at which deformation has effect", NULL},
1212         {"subdivisions", (getter)Bone_getSubdivisions, (setter)Bone_setSubdivisions, 
1213                 "The number of subdivisions (for B-Bones)", NULL},
1214         {"options", (getter)Bone_getOptions, (setter)Bone_setOptions, 
1215                 "The options effective on this bone", NULL},
1216         {"parent", (getter)Bone_getParent, (setter)Bone_setParent, 
1217                 "The parent bone of this bone", NULL},
1218         {"children", (getter)Bone_getChildren, (setter)Bone_setChildren, 
1219                 "The child bones of this bone", NULL},
1220         {"length", (getter)Bone_getLength, (setter)Bone_setLength, 
1221                 "The length of this bone", NULL},
1222         {"tailRadius", (getter)Bone_getTailRadius, (setter)Bone_setTailRadius, 
1223                 "Set the radius of this bones tip", NULL},
1224         {"headRadius", (getter)Bone_getHeadRadius, (setter)Bone_setHeadRadius, 
1225                 "Set the radius of this bones head", NULL},
1226         {NULL, NULL, NULL, NULL,NULL}
1227 };
1228 //------------------------tp_repr
1229 //This is the string representation of the object
1230 static PyObject *Bone_repr(BPy_Bone *self)
1231 {
1232         return PyString_FromFormat( "[Bone \"%s\"]", self->bone->name ); 
1233 }
1234 //------------------------tp_dealloc
1235 //This tells how to 'tear-down' our object when ref count hits 0
1236 static void Bone_dealloc(BPy_Bone * self)
1237 {
1238         Bone_Type.tp_free(self);
1239         return;
1240 }
1241 //------------------------tp_doc
1242 //The __doc__ string for this object
1243 static char BPy_Bone_doc[] = "This object wraps a Blender Boneobject.\n\
1244                                           This object is a subobject of the Armature object.";
1245
1246 //------------------TYPE_OBECT DEFINITION--------------------------
1247 PyTypeObject Bone_Type = {
1248         PyObject_HEAD_INIT(NULL)   //tp_head
1249         0,                                                                              //tp_internal
1250         "Bone",                                                         //tp_name
1251         sizeof(BPy_Bone),                                       //tp_basicsize
1252         0,                                                                              //tp_itemsize
1253         (destructor)Bone_dealloc,               //tp_dealloc
1254         0,                                                                              //tp_print
1255         0,                                                                              //tp_getattr
1256         0,                                                                              //tp_setattr
1257         0,                                                                              //tp_compare
1258         (reprfunc) Bone_repr,                   //tp_repr
1259         0,                                                                              //tp_as_number
1260         0,                                                                              //tp_as_sequence
1261         0,                                                                              //tp_as_mapping
1262         0,                                                                              //tp_hash
1263         0,                                                                              //tp_call
1264         0,                                                                              //tp_str
1265         0,                                                                              //tp_getattro
1266         0,                                                                              //tp_setattro
1267         0,                                                                              //tp_as_buffer
1268         Py_TPFLAGS_DEFAULT,         //tp_flags
1269         BPy_Bone_doc,                                   //tp_doc
1270         0,                                                                              //tp_traverse
1271         0,                                                                              //tp_clear
1272         0,                                                                              //tp_richcompare
1273         0,                                                                              //tp_weaklistoffset
1274         0,                                                                              //tp_iter
1275         0,                                                                              //tp_iternext
1276         BPy_Bone_methods,                               //tp_methods
1277         0,                                                                              //tp_members
1278         BPy_Bone_getset,                                //tp_getset
1279         0,                                                                              //tp_base
1280         0,                                                                              //tp_dict
1281         0,                                                                              //tp_descr_get
1282         0,                                                                              //tp_descr_set
1283         0,                                                                              //tp_dictoffset
1284         0,                                                                              //tp_init
1285         0,                                                                              //tp_alloc
1286         0,                                                                              //tp_new
1287         0,                                                                              //tp_free
1288         0,                                                                              //tp_is_gc
1289         0,                                                                              //tp_bases
1290         0,                                                                              //tp_mro
1291         0,                                                                              //tp_cache
1292         0,                                                                              //tp_subclasses
1293         0,                                                                              //tp_weaklist
1294         0                                                                               //tp_del
1295 };
1296 //------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
1297 //-----------------(internal)
1298 //Converts a struct EditBone to a BPy_EditBone
1299 PyObject *PyEditBone_FromEditBone(struct EditBone *editbone)
1300 {
1301         BPy_EditBone *py_editbone = NULL;
1302
1303         py_editbone = (BPy_EditBone*)EditBone_Type.tp_alloc(&EditBone_Type, 0); //*new*
1304         if (!py_editbone)
1305                 goto RuntimeError;
1306
1307         py_editbone->editbone = editbone;
1308
1309         return (PyObject *) py_editbone;
1310
1311 RuntimeError:
1312         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1313                 sEditBoneError, "PyEditBone_FromEditBone: ", "Internal Error Ocurred");
1314 }
1315 //-----------------(internal)
1316 //Converts a struct Bone to a BPy_Bone
1317 PyObject *PyBone_FromBone(struct Bone *bone)
1318 {
1319         BPy_Bone *py_Bone = NULL;
1320
1321         py_Bone = (BPy_Bone*)Bone_Type.tp_alloc(&Bone_Type, 0); //*new*
1322         if (py_Bone == NULL)
1323                 goto RuntimeError;
1324
1325         py_Bone->bone = bone;
1326
1327         return (PyObject *) py_Bone;
1328
1329 RuntimeError:
1330         return EXPP_objError(PyExc_RuntimeError, "%s%s%s", 
1331                 sBoneError, "PyBone_FromBone: ", "Internal Error Ocurred");
1332 }
1333 //-----------------(internal)
1334 //Converts a PyBone to a bBone
1335 struct Bone *PyBone_AsBone(BPy_Bone *py_Bone)
1336 {
1337         return (py_Bone->bone);
1338 }