size for static string was too small, we should really have dynamic sized strings...
[blender.git] / source / blender / editors / space_view3d / drawarmature.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_view3d/drawarmature.c
29  *  \ingroup spview3d
30  */
31
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36
37
38 #include "DNA_anim_types.h"
39 #include "DNA_armature_types.h"
40 #include "DNA_constraint_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_view3d_types.h"
44 #include "DNA_object_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_dlrbTree.h"
49 #include "BLI_utildefines.h"
50
51 #include "BKE_animsys.h"
52 #include "BKE_action.h"
53 #include "BKE_armature.h"
54 #include "BKE_global.h"
55 #include "BKE_modifier.h"
56 #include "BKE_nla.h"
57
58
59 #include "BIF_gl.h"
60 #include "BIF_glutil.h"
61
62 #include "ED_armature.h"
63 #include "ED_keyframes_draw.h"
64
65 #include "BLF_api.h"
66
67 #include "UI_resources.h"
68
69 #include "view3d_intern.h"
70
71
72 /* *************** Armature Drawing - Coloring API ***************************** */
73
74 /* global here is reset before drawing each bone */
75 static ThemeWireColor *bcolor= NULL;
76
77 /* values of colCode for set_pchan_glcolor */
78 enum {
79         PCHAN_COLOR_NORMAL      = 0,            /* normal drawing */
80         PCHAN_COLOR_SOLID,                              /* specific case where "solid" color is needed */
81         PCHAN_COLOR_CONSTS,                             /* "constraint" colors (which may/may-not be suppressed) */
82         
83         PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
84         PCHAN_COLOR_SPHEREBONE_END,             /* for the ends of sphere (envelope) bones */
85         PCHAN_COLOR_LINEBONE                    /* for the middle of line-bones */
86 };
87
88 /* This function sets the color-set for coloring a certain bone */
89 static void set_pchan_colorset (Object *ob, bPoseChannel *pchan)
90 {
91         bPose *pose= (ob) ? ob->pose : NULL;
92         bArmature *arm= (ob) ? ob->data : NULL;
93         bActionGroup *grp= NULL;
94         short color_index= 0;
95         
96         /* sanity check */
97         if (ELEM4(NULL, ob, arm, pose, pchan)) {
98                 bcolor= NULL;
99                 return;
100         }
101         
102         /* only try to set custom color if enabled for armature */
103         if (arm->flag & ARM_COL_CUSTOM) {       
104                 /* currently, a bone can only use a custom color set if it's group (if it has one),
105                  * has been set to use one
106                  */
107                 if (pchan->agrp_index) {
108                         grp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
109                         if (grp)
110                                 color_index= grp->customCol;
111                 }
112         }
113         
114         /* bcolor is a pointer to the color set to use. If NULL, then the default
115          * color set (based on the theme colors for 3d-view) is used. 
116          */
117         if (color_index > 0) {
118                 bTheme *btheme= UI_GetTheme();
119                 bcolor= &btheme->tarm[(color_index - 1)];
120         }
121         else if (color_index == -1) {
122                 /* use the group's own custom color set */
123                 bcolor= (grp)? &grp->cs : NULL;
124         }
125         else 
126                 bcolor= NULL;
127 }
128
129 /* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
130 static void cp_shade_color3ub (unsigned char cp[3], const int offset)
131 {
132         int r, g, b;
133         
134         r= offset + (int) cp[0];
135         CLAMP(r, 0, 255);
136         g= offset + (int) cp[1];
137         CLAMP(g, 0, 255);
138         b= offset + (int) cp[2];
139         CLAMP(b, 0, 255);
140         
141         cp[0]= r;
142         cp[1]= g;
143         cp[2]= b;
144 }
145
146 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
147 static short set_pchan_glColor (short colCode, int boneflag, short constflag)
148 {
149         switch (colCode) {
150         case PCHAN_COLOR_NORMAL:
151         {
152                 if (bcolor) {
153                         unsigned char cp[3];
154                         
155                         if (boneflag & BONE_DRAW_ACTIVE) {
156                                 copy_v3_v3_char((char *)cp, bcolor->active);
157                                 if(!(boneflag & BONE_SELECTED)) {
158                                         cp_shade_color3ub(cp, -80);
159                                 }
160                         }
161                         else if (boneflag & BONE_SELECTED) {
162                                 copy_v3_v3_char((char *)cp, bcolor->select);
163                         }
164                         else {
165                                 /* a bit darker than solid */
166                                 copy_v3_v3_char((char *)cp, bcolor->solid);
167                                 cp_shade_color3ub(cp, -50);
168                         }
169                         
170                         glColor3ubv(cp);
171                 }
172                 else {
173                         if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, 40);
174                         else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
175                         else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
176                         else UI_ThemeColor(TH_WIRE);
177                 }
178                 
179                 return 1;
180         }
181                 break;
182         
183         case PCHAN_COLOR_SOLID:
184         {
185                 if (bcolor) {
186                         glColor3ubv((unsigned char *)bcolor->solid);
187                 }
188                 else 
189                         UI_ThemeColor(TH_BONE_SOLID);
190                         
191                 return 1;
192         }
193                 break;
194                 
195         case PCHAN_COLOR_CONSTS:
196         {
197                 if ( (bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) ) {
198                         if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
199                         else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
200                         else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80);
201                         else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
202                         
203                         return 1;
204                 }
205                 else 
206                         return 0;
207         }
208                 break;
209                 
210         case PCHAN_COLOR_SPHEREBONE_BASE:
211         {
212                 if (bcolor) {
213                         unsigned char cp[3];
214                         
215                         if (boneflag & BONE_DRAW_ACTIVE) {
216                                 copy_v3_v3_char((char *)cp, bcolor->active);
217                         }
218                         else if (boneflag & BONE_SELECTED) {
219                                 copy_v3_v3_char((char *)cp, bcolor->select);
220                         }
221                         else {
222                                 copy_v3_v3_char((char *)cp, bcolor->solid);
223                         }
224                         
225                         glColor3ubv(cp);
226                 }
227                 else {
228                         if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
229                         else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
230                         else UI_ThemeColor(TH_BONE_SOLID);
231                 }
232                 
233                 return 1;
234         }
235                 break;
236         case PCHAN_COLOR_SPHEREBONE_END:
237         {
238                 if (bcolor) {
239                         unsigned char cp[3];
240                         
241                         if (boneflag & BONE_DRAW_ACTIVE) {
242                                 copy_v3_v3_char((char *)cp, bcolor->active);
243                                 cp_shade_color3ub(cp, 10);
244                         }
245                         else if (boneflag & BONE_SELECTED) {
246                                 copy_v3_v3_char((char *)cp, bcolor->select);
247                                 cp_shade_color3ub(cp, -30);
248                         }
249                         else {
250                                 copy_v3_v3_char((char *)cp, bcolor->solid);
251                                 cp_shade_color3ub(cp, -30);
252                         }
253                         
254                         glColor3ubv(cp);
255                 }
256                 else {
257                         if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10);
258                         else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30);
259                         else UI_ThemeColorShade(TH_BONE_SOLID, -30);
260                 }
261         }
262                 break;
263                 
264         case PCHAN_COLOR_LINEBONE:
265         {
266                 /* inner part in background color or constraint */
267                 if ( (constflag) && ((bcolor==NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) {
268                         if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
269                         else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
270                         else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0);
271                         else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
272                         else if (constflag) UI_ThemeColor(TH_BONE_POSE);        /* PCHAN_HAS_ACTION */ 
273                 }
274                 else {
275                         if (bcolor) {
276                                 char *cp= bcolor->solid;
277                                 glColor4ub(cp[0], cp[1], cp[2], 204);   
278                         }
279                         else
280                                 UI_ThemeColorShade(TH_BACK, -30);
281                 }
282                 
283                 return 1;
284         }
285                 break;
286         }
287         
288         return 0;
289 }
290
291 static void set_ebone_glColor(const unsigned int boneflag)
292 {
293         if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
294         else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, 0.15f); /* unselected active */
295         else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20);
296         else UI_ThemeColor(TH_WIRE);
297 }
298
299 /* *************** Armature drawing, helper calls for parts ******************* */
300
301 /* half the cube, in Y */
302 static float cube[8][3] = {
303 {-1.0,  0.0, -1.0},
304 {-1.0,  0.0,  1.0},
305 {-1.0,  1.0,  1.0},
306 {-1.0,  1.0, -1.0},
307 { 1.0,  0.0, -1.0},
308 { 1.0,  0.0,  1.0},
309 { 1.0,  1.0,  1.0},
310 { 1.0,  1.0, -1.0},
311 };
312
313 static void drawsolidcube_size(float xsize, float ysize, float zsize)
314 {
315         static GLuint displist=0;
316         float n[3]= {0.0f};
317         
318         glScalef(xsize, ysize, zsize);
319
320         if(displist==0) {
321                 displist= glGenLists(1);
322                 glNewList(displist, GL_COMPILE);
323
324                 glBegin(GL_QUADS);
325                 n[0]= -1.0;
326                 glNormal3fv(n); 
327                 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
328                 n[0]=0;
329                 n[1]= -1.0;
330                 glNormal3fv(n); 
331                 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
332                 n[1]=0;
333                 n[0]= 1.0;
334                 glNormal3fv(n); 
335                 glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
336                 n[0]=0;
337                 n[1]= 1.0;
338                 glNormal3fv(n); 
339                 glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
340                 n[1]=0;
341                 n[2]= 1.0;
342                 glNormal3fv(n); 
343                 glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
344                 n[2]= -1.0;
345                 glNormal3fv(n); 
346                 glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
347                 glEnd();
348
349                 glEndList();
350         }
351
352         glCallList(displist);
353 }
354
355 static void drawcube_size(float xsize, float ysize, float zsize)
356 {
357         static GLuint displist=0;
358         
359         if(displist == 0) {
360                 displist= glGenLists(1);
361                 glNewList(displist, GL_COMPILE);
362                 
363                 glBegin(GL_LINE_STRIP);
364                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
365                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
366                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
367                 glEnd();
368                 
369                 glBegin(GL_LINES);
370                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
371                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
372                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
373                 glEnd();
374                 
375                 glEndList();
376         }
377
378         glScalef(xsize, ysize, zsize);
379         glCallList(displist);
380         
381 }
382
383
384 static void draw_bonevert(void)
385 {
386         static GLuint displist=0;
387         
388         if (displist == 0) {
389                 GLUquadricObj   *qobj;
390                 
391                 displist= glGenLists(1);
392                 glNewList(displist, GL_COMPILE);
393                         
394                 glPushMatrix();
395                 
396                 qobj    = gluNewQuadric(); 
397                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
398                 gluDisk(qobj, 0.0,  0.05, 16, 1);
399                 
400                 glRotatef(90, 0, 1, 0);
401                 gluDisk(qobj, 0.0,  0.05, 16, 1);
402                 
403                 glRotatef(90, 1, 0, 0);
404                 gluDisk(qobj, 0.0,  0.05, 16, 1);
405                 
406                 gluDeleteQuadric(qobj);  
407                 
408                 glPopMatrix();
409                 glEndList();
410         }
411
412         glCallList(displist);
413 }
414
415 static void draw_bonevert_solid(void)
416 {
417         static GLuint displist=0;
418         
419         if (displist == 0) {
420                 GLUquadricObj   *qobj;
421                 
422                 displist= glGenLists(1);
423                 glNewList(displist, GL_COMPILE);
424                 
425                 qobj    = gluNewQuadric();
426                 gluQuadricDrawStyle(qobj, GLU_FILL); 
427                 glShadeModel(GL_SMOOTH);
428                 gluSphere(qobj, 0.05, 8, 5);
429                 glShadeModel(GL_FLAT);
430                 gluDeleteQuadric(qobj);  
431                 
432                 glEndList();
433         }
434
435         glCallList(displist);
436 }
437
438 static float bone_octahedral_verts[6][3]= {
439         { 0.0f, 0.0f,  0.0f},
440         { 0.1f, 0.1f,  0.1f},
441         { 0.1f, 0.1f, -0.1f},
442         {-0.1f, 0.1f, -0.1f},
443         {-0.1f, 0.1f,  0.1f},
444         { 0.0f, 1.0f,  0.0f}
445 };
446
447 static unsigned int bone_octahedral_wire_sides[8]= {0, 1, 5, 3, 0, 4, 5, 2};
448 static unsigned int bone_octahedral_wire_square[8]= {1, 2, 3, 4, 1};
449
450 static unsigned int bone_octahedral_solid_tris[8][3]= {
451         {2, 1, 0}, /* bottom */
452         {3, 2, 0},
453         {4, 3, 0},
454         {1, 4, 0},
455
456         {5, 1, 2}, /* top */
457         {5, 2, 3},
458         {5, 3, 4},
459         {5, 4, 1}
460 };
461
462 /* aligned with bone_octahedral_solid_tris */
463 static float bone_octahedral_solid_normals[8][3]= {
464         { 0.70710683f, -0.70710683f,  0.00000000f},
465         {-0.00000000f, -0.70710683f, -0.70710683f},
466         {-0.70710683f, -0.70710683f,  0.00000000f},
467         { 0.00000000f, -0.70710683f,  0.70710683f},
468         { 0.99388373f,  0.11043154f, -0.00000000f},
469         { 0.00000000f,  0.11043154f, -0.99388373f},
470         {-0.99388373f,  0.11043154f,  0.00000000f},
471         { 0.00000000f,  0.11043154f,  0.99388373f}
472 };
473
474 static void draw_bone_octahedral(void)
475 {
476         static GLuint displist=0;
477         
478         if (displist == 0) {
479                 displist= glGenLists(1);
480                 glNewList(displist, GL_COMPILE);
481
482                 /*      Section 1, sides */
483                 glEnableClientState(GL_VERTEX_ARRAY);
484                 glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
485                 glDrawElements(GL_LINE_LOOP,
486                                sizeof(bone_octahedral_wire_sides)/sizeof(*bone_octahedral_wire_sides),
487                                GL_UNSIGNED_INT,
488                                bone_octahedral_wire_sides);
489
490                 /*      Section 1, square */
491                 glDrawElements(GL_LINE_LOOP,
492                                sizeof(bone_octahedral_wire_square)/sizeof(*bone_octahedral_wire_square),
493                                GL_UNSIGNED_INT,
494                                bone_octahedral_wire_square);
495                 glDisableClientState(GL_VERTEX_ARRAY);
496                 
497                 glEndList();
498         }
499
500         glCallList(displist);
501 }       
502
503 static void draw_bone_solid_octahedral(void)
504 {
505         static GLuint displist=0;
506
507         if (displist == 0) {
508                 int i;
509
510                 displist= glGenLists(1);
511                 glNewList(displist, GL_COMPILE);
512
513 #if 1
514                 glBegin(GL_TRIANGLES);
515                 for(i= 0; i < 8; i++) {
516                         glNormal3fv(bone_octahedral_solid_normals[i]);
517                         glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][0]]);
518                         glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][1]]);
519                         glVertex3fv(bone_octahedral_verts[bone_octahedral_solid_tris[i][2]]);
520                 }
521
522                 glEnd();
523
524 #else   /* not working because each vert needs a different normal */
525                 glEnableClientState(GL_NORMAL_ARRAY);
526                 glEnableClientState(GL_VERTEX_ARRAY);
527                 glNormalPointer(GL_FLOAT, 0, bone_octahedral_solid_normals);
528                 glVertexPointer(3, GL_FLOAT, 0, bone_octahedral_verts);
529                 glDrawElements(GL_TRIANGLES, sizeof(bone_octahedral_solid_tris)/sizeof(unsigned int), GL_UNSIGNED_INT, bone_octahedral_solid_tris);
530                 glDisableClientState(GL_NORMAL_ARRAY);
531                 glDisableClientState(GL_VERTEX_ARRAY);
532 #endif
533
534                 glEndList();
535         }
536
537         glCallList(displist);
538 }       
539
540 /* *************** Armature drawing, bones ******************* */
541
542
543 static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
544 {
545         /*      Draw root point if we are not connected */
546         if ((boneflag & BONE_CONNECTED)==0) {
547                 if (id != -1)
548                         glLoadName(id | BONESEL_ROOT);
549                 
550                 if(dt <= OB_WIRE) {
551                         if (armflag & ARM_EDITMODE) {
552                                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
553                                 else UI_ThemeColor(TH_VERTEX);
554                         }
555                 }
556                 else {
557                         if (armflag & ARM_POSEMODE) 
558                                 set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
559                         else
560                                 UI_ThemeColor(TH_BONE_SOLID);
561                 }
562                 
563                 if (dt > OB_WIRE) 
564                         draw_bonevert_solid();
565                 else 
566                         draw_bonevert();
567         }
568         
569         /*      Draw tip point */
570         if (id != -1)
571                 glLoadName(id | BONESEL_TIP);
572         
573         if (dt <= OB_WIRE) {
574                 if (armflag & ARM_EDITMODE) {
575                         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
576                         else UI_ThemeColor(TH_VERTEX);
577                 }
578         }
579         else {
580                 if (armflag & ARM_POSEMODE) 
581                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
582                 else
583                         UI_ThemeColor(TH_BONE_SOLID);
584         }
585         
586         glTranslatef(0.0f, 1.0f, 0.0f);
587         if (dt > OB_WIRE) 
588                 draw_bonevert_solid();
589         else 
590                 draw_bonevert();
591         glTranslatef(0.0f, -1.0f, 0.0f);
592         
593 }
594
595 /* 16 values of sin function (still same result!) */
596 static float si[16] = {
597         0.00000000f,
598         0.20129852f, 0.39435585f,
599         0.57126821f, 0.72479278f,
600         0.84864425f, 0.93775213f,
601         0.98846832f, 0.99871650f,
602         0.96807711f, 0.89780453f,
603         0.79077573f, 0.65137248f,
604         0.48530196f, 0.29936312f,
605         0.10116832f
606 };
607 /* 16 values of cos function (still same result!) */
608 static float co[16] ={
609         1.00000000f,
610         0.97952994f, 0.91895781f,
611         0.82076344f, 0.68896691f,
612         0.52896401f, 0.34730525f,
613         0.15142777f, -0.05064916f,
614         -0.25065253f, -0.44039415f,
615         -0.61210598f, -0.75875812f,
616         -0.87434661f, -0.95413925f,
617         -0.99486932f
618 };
619
620
621
622 /* smat, imat = mat & imat to draw screenaligned */
623 static void draw_sphere_bone_dist(float smat[][4], float imat[][4], bPoseChannel *pchan, EditBone *ebone)
624 {
625         float head, tail, dist /*, length*/;
626         float *headvec, *tailvec, dirvec[3];
627         
628         /* figure out the sizes of spheres */
629         if (ebone) {
630                 /* this routine doesn't call get_matrix_editbone() that calculates it */
631                 ebone->length = len_v3v3(ebone->head, ebone->tail);
632
633                 /*length= ebone->length;*/ /*UNUSED*/
634                 tail= ebone->rad_tail;
635                 dist= ebone->dist;
636                 if (ebone->parent && (ebone->flag & BONE_CONNECTED))
637                         head= ebone->parent->rad_tail;
638                 else
639                         head= ebone->rad_head;
640                 headvec= ebone->head;
641                 tailvec= ebone->tail;
642         }
643         else {
644                 /*length= pchan->bone->length;*/ /*UNUSED*/
645                 tail= pchan->bone->rad_tail;
646                 dist= pchan->bone->dist;
647                 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
648                         head= pchan->parent->bone->rad_tail;
649                 else
650                         head= pchan->bone->rad_head;
651                 headvec= pchan->pose_head;
652                 tailvec= pchan->pose_tail;
653         }
654         
655         /* ***** draw it ***** */
656         
657         /* move vector to viewspace */
658         sub_v3_v3v3(dirvec, tailvec, headvec);
659         mul_mat3_m4_v3(smat, dirvec);
660         /* clear zcomp */
661         dirvec[2]= 0.0f;
662
663         if(head != tail) {
664         /* correcyion when viewing along the bones axis
665          * it pops in and out but better then artifacts, [#23841] */
666                 float view_dist= len_v2(dirvec);
667
668                 if(head - view_dist > tail) {
669                         tailvec= headvec;
670                         tail = head;
671                         zero_v3(dirvec);
672                         dirvec[0]= 0.00001; // XXX. weak but ok
673                 }
674                 else if(tail - view_dist > head) {
675                         headvec= tailvec;
676                         head = tail;
677                         zero_v3(dirvec);
678                         dirvec[0]= 0.00001; // XXX. weak but ok
679                 }
680         }
681
682         /* move vector back */
683         mul_mat3_m4_v3(imat, dirvec);
684         
685         if (0.0f != normalize_v3(dirvec)) {
686                 float norvec[3], vec1[3], vec2[3], vec[3];
687                 int a;
688                 
689                 //mul_v3_fl(dirvec, head);
690                 cross_v3_v3v3(norvec, dirvec, imat[2]);
691                 
692                 glBegin(GL_QUAD_STRIP);
693                 
694                 for (a=0; a<16; a++) {
695                         vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
696                         vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
697                         vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
698
699                         madd_v3_v3v3fl(vec1, headvec, vec, head);
700                         madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
701                         
702                         glColor4ub(255, 255, 255, 50);
703                         glVertex3fv(vec1);
704                         //glColor4ub(255, 255, 255, 0);
705                         glVertex3fv(vec2);
706                 }
707                 
708                 for (a=15; a>=0; a--) {
709                         vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
710                         vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
711                         vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
712
713                         madd_v3_v3v3fl(vec1, tailvec, vec, tail);
714                         madd_v3_v3v3fl(vec2, tailvec, vec, tail + dist);
715                         
716                         //glColor4ub(255, 255, 255, 50);
717                         glVertex3fv(vec1);
718                         //glColor4ub(255, 255, 255, 0);
719                         glVertex3fv(vec2);
720                 }
721                 /* make it cyclic... */
722                 
723                 vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
724                 vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
725                 vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
726
727                 madd_v3_v3v3fl(vec1, headvec, vec, head);
728                 madd_v3_v3v3fl(vec2, headvec, vec, head + dist);
729
730                 //glColor4ub(255, 255, 255, 50);
731                 glVertex3fv(vec1);
732                 //glColor4ub(255, 255, 255, 0);
733                 glVertex3fv(vec2);
734                 
735                 glEnd();
736         }
737 }
738
739
740 /* smat, imat = mat & imat to draw screenaligned */
741 static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
742 {
743         float head, tail /*, length*/;
744         float *headvec, *tailvec, dirvec[3];
745         
746         /* figure out the sizes of spheres */
747         if (ebone) {
748                 /* this routine doesn't call get_matrix_editbone() that calculates it */
749                 ebone->length = len_v3v3(ebone->head, ebone->tail);
750                 
751                 /*length= ebone->length;*/ /*UNUSED*/
752                 tail= ebone->rad_tail;
753                 if (ebone->parent && (boneflag & BONE_CONNECTED))
754                         head= ebone->parent->rad_tail;
755                 else
756                         head= ebone->rad_head;
757                 headvec= ebone->head;
758                 tailvec= ebone->tail;
759         }
760         else {
761                 /*length= pchan->bone->length;*/ /*UNUSED*/
762                 tail= pchan->bone->rad_tail;
763                 if ((pchan->parent) && (boneflag & BONE_CONNECTED))
764                         head= pchan->parent->bone->rad_tail;
765                 else
766                         head= pchan->bone->rad_head;
767                 headvec= pchan->pose_head;
768                 tailvec= pchan->pose_tail;
769         }
770         
771         /* sphere root color */
772         if (armflag & ARM_EDITMODE) {
773                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
774                 else UI_ThemeColor(TH_VERTEX);
775         }
776         else if (armflag & ARM_POSEMODE)
777                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
778         
779         /*      Draw root point if we are not connected */
780         if ((boneflag & BONE_CONNECTED)==0) {
781                 if (id != -1)
782                         glLoadName(id | BONESEL_ROOT);
783                 
784                 drawcircball(GL_LINE_LOOP, headvec, head, imat);
785         }
786         
787         /*      Draw tip point */
788         if (armflag & ARM_EDITMODE) {
789                 if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
790                 else UI_ThemeColor(TH_VERTEX);
791         }
792         
793         if (id != -1)
794                 glLoadName(id | BONESEL_TIP);
795         
796         drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
797         
798         /* base */
799         if (armflag & ARM_EDITMODE) {
800                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
801                 else UI_ThemeColor(TH_WIRE);
802         }
803         
804         sub_v3_v3v3(dirvec, tailvec, headvec);
805         
806         /* move vector to viewspace */
807         mul_mat3_m4_v3(smat, dirvec);
808         /* clear zcomp */
809         dirvec[2]= 0.0f;
810         /* move vector back */
811         mul_mat3_m4_v3(imat, dirvec);
812         
813         if (0.0f != normalize_v3(dirvec)) {
814                 float norvech[3], norvect[3], vec[3];
815                 
816                 copy_v3_v3(vec, dirvec);
817                 
818                 mul_v3_fl(dirvec, head);
819                 cross_v3_v3v3(norvech, dirvec, imat[2]);
820                 
821                 mul_v3_fl(vec, tail);
822                 cross_v3_v3v3(norvect, vec, imat[2]);
823                 
824                 if (id != -1)
825                         glLoadName(id | BONESEL_BONE);
826                 
827                 glBegin(GL_LINES);
828
829                 add_v3_v3v3(vec, headvec, norvech);
830                 glVertex3fv(vec);
831
832                 add_v3_v3v3(vec, tailvec, norvect);
833                 glVertex3fv(vec);
834
835                 sub_v3_v3v3(vec, headvec, norvech);
836                 glVertex3fv(vec);
837
838                 sub_v3_v3v3(vec, tailvec, norvect);
839                 glVertex3fv(vec);
840                 
841                 glEnd();
842         }
843 }
844
845 /* does wire only for outline selecting */
846 static void draw_sphere_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
847 {
848         GLUquadricObj   *qobj;
849         float head, tail, length;
850         float fac1, fac2;
851         
852         glPushMatrix();
853         qobj    = gluNewQuadric();
854
855         /* figure out the sizes of spheres */
856         if (ebone) {
857                 length= ebone->length;
858                 tail= ebone->rad_tail;
859                 if (ebone->parent && (boneflag & BONE_CONNECTED))
860                         head= ebone->parent->rad_tail;
861                 else
862                         head= ebone->rad_head;
863         }
864         else {
865                 length= pchan->bone->length;
866                 tail= pchan->bone->rad_tail;
867                 if (pchan->parent && (boneflag & BONE_CONNECTED))
868                         head= pchan->parent->bone->rad_tail;
869                 else
870                         head= pchan->bone->rad_head;
871         }
872         
873         /* move to z-axis space */
874         glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
875
876         if (dt==OB_SOLID) {
877                 /* set up solid drawing */
878                 glEnable(GL_COLOR_MATERIAL);
879                 glEnable(GL_LIGHTING);
880                 
881                 gluQuadricDrawStyle(qobj, GLU_FILL); 
882                 glShadeModel(GL_SMOOTH);
883         }
884         else {
885                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
886         }
887         
888         /* sphere root color */
889         if (armflag & ARM_EDITMODE) {
890                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
891                 else UI_ThemeColorShade(TH_BONE_SOLID, -30);
892         }
893         else if (armflag & ARM_POSEMODE)
894                 set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
895         else if (dt==OB_SOLID) 
896                 UI_ThemeColorShade(TH_BONE_SOLID, -30);
897         
898         /*      Draw root point if we are not connected */
899         if ((boneflag & BONE_CONNECTED)==0) {
900                 if (id != -1)
901                         glLoadName(id | BONESEL_ROOT);
902                 gluSphere(qobj, head, 16, 10);
903         }
904         
905         /*      Draw tip point */
906         if (armflag & ARM_EDITMODE) {
907                 if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
908                 else UI_ThemeColorShade(TH_BONE_SOLID, -30);
909         }
910
911         if (id != -1)
912                 glLoadName(id | BONESEL_TIP);
913         
914         glTranslatef(0.0f, 0.0f, length);
915         gluSphere(qobj, tail, 16, 10);
916         glTranslatef(0.0f, 0.0f, -length);
917         
918         /* base */
919         if (armflag & ARM_EDITMODE) {
920                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
921                 else UI_ThemeColor(TH_BONE_SOLID);
922         }
923         else if (armflag & ARM_POSEMODE)
924                 set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
925         else if (dt == OB_SOLID)
926                 UI_ThemeColor(TH_BONE_SOLID);
927         
928         fac1= (length-head)/length;
929         fac2= (length-tail)/length;
930         
931         if (length > (head+tail)) {
932                 if (id != -1)
933                         glLoadName (id | BONESEL_BONE);
934                 
935                 glEnable(GL_POLYGON_OFFSET_FILL);
936                 glPolygonOffset(-1.0f, -1.0f);
937                 
938                 glTranslatef(0.0f, 0.0f, head);
939                 gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
940                 glTranslatef(0.0f, 0.0f, -head);
941                 
942                 glDisable(GL_POLYGON_OFFSET_FILL);
943                 
944                 /* draw sphere on extrema */
945                 glTranslatef(0.0f, 0.0f, length-tail);
946                 gluSphere(qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
947                 glTranslatef(0.0f, 0.0f, -length+tail);
948                 
949                 glTranslatef(0.0f, 0.0f, head);
950                 gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
951         }
952         else {          
953                 /* 1 sphere in center */
954                 glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0f);
955                 gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
956         }
957         
958         /* restore */
959         if (dt==OB_SOLID) {
960                 glShadeModel(GL_FLAT);
961                 glDisable(GL_LIGHTING);
962                 glDisable(GL_COLOR_MATERIAL);
963         }
964         
965         glPopMatrix();
966         gluDeleteQuadric(qobj);  
967 }
968
969 static GLubyte bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; 
970 static GLubyte bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; 
971
972 static GLubyte bm_dot5[]= {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; 
973 static GLubyte bm_dot7[]= {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; 
974
975
976 static void draw_line_bone(int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
977 {
978         float length;
979         
980         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
981         
982         if (pchan) 
983                 length= pchan->bone->length;
984         else 
985                 length= ebone->length;
986         
987         glPushMatrix();
988         glScalef(length, length, length);
989         
990         /* this chunk not in object mode */
991         if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
992                 glLineWidth(4.0f);
993                 if (armflag & ARM_POSEMODE)
994                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
995                 else if (armflag & ARM_EDITMODE) {
996                         UI_ThemeColor(TH_WIRE);
997                 }
998                 
999                 /*      Draw root point if we are not connected */
1000                 if ((boneflag & BONE_CONNECTED)==0) {
1001                         if (G.f & G_PICKSEL) {  // no bitmap in selection mode, crashes 3d cards...
1002                                 glLoadName (id | BONESEL_ROOT);
1003                                 glBegin(GL_POINTS);
1004                                 glVertex3f(0.0f, 0.0f, 0.0f);
1005                                 glEnd();
1006                         }
1007                         else {
1008                                 glRasterPos3f(0.0f, 0.0f, 0.0f);
1009                                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
1010                         }
1011                 }
1012                 
1013                 if (id != -1)
1014                         glLoadName((GLuint) id|BONESEL_BONE);
1015                 
1016                 glBegin(GL_LINES);
1017                 glVertex3f(0.0f, 0.0f, 0.0f);
1018                 glVertex3f(0.0f, 1.0f, 0.0f);
1019                 glEnd();
1020                 
1021                 /* tip */
1022                 if (G.f & G_PICKSEL) {  
1023                         /* no bitmap in selection mode, crashes 3d cards... */
1024                         glLoadName(id | BONESEL_TIP);
1025                         glBegin(GL_POINTS);
1026                         glVertex3f(0.0f, 1.0f, 0.0f);
1027                         glEnd();
1028                 }
1029                 else {
1030                         glRasterPos3f(0.0f, 1.0f, 0.0f);
1031                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
1032                 }
1033                 
1034                 /* further we send no names */
1035                 if (id != -1)
1036                         glLoadName(id & 0xFFFF);        /* object tag, for bordersel optim */
1037                 
1038                 if (armflag & ARM_POSEMODE)
1039                         set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
1040         }
1041         
1042         glLineWidth(2.0);
1043         
1044         /*Draw root point if we are not connected */
1045         if ((boneflag & BONE_CONNECTED)==0) {
1046                 if ((G.f & G_PICKSEL)==0) {     
1047                         /* no bitmap in selection mode, crashes 3d cards... */
1048                         if (armflag & ARM_EDITMODE) {
1049                                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
1050                                 else UI_ThemeColor(TH_VERTEX);
1051                         }
1052                         glRasterPos3f(0.0f, 0.0f, 0.0f);
1053                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
1054                 }
1055         }
1056         
1057         if (armflag & ARM_EDITMODE) {
1058                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
1059                 else UI_ThemeColorShade(TH_BACK, -30);
1060         }
1061         glBegin(GL_LINES);
1062         glVertex3f(0.0f, 0.0f, 0.0f);
1063         glVertex3f(0.0f, 1.0f, 0.0f);
1064         glEnd();
1065         
1066         /* tip */
1067         if ((G.f & G_PICKSEL)==0) {     
1068                 /* no bitmap in selection mode, crashes 3d cards... */
1069                 if (armflag & ARM_EDITMODE) {
1070                         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
1071                         else UI_ThemeColor(TH_VERTEX);
1072                 }
1073                 glRasterPos3f(0.0f, 1.0f, 0.0f);
1074                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
1075         }
1076         
1077         glLineWidth(1.0);
1078         
1079         glPopMatrix();
1080 }
1081
1082 static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
1083 {
1084         int segments= 0;
1085         
1086         if (pchan) 
1087                 segments= pchan->bone->segments;
1088         
1089         if ((segments > 1) && (pchan)) {
1090                 float dlen= length/(float)segments;
1091                 Mat4 *bbone= b_bone_spline_setup(pchan, 0);
1092                 int a;
1093                 
1094                 for (a=0; a<segments; a++, bbone++) {
1095                         glPushMatrix();
1096                         glMultMatrixf(bbone->mat);
1097                         if (dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
1098                         else drawcube_size(xwidth, dlen, zwidth);
1099                         glPopMatrix();
1100                 }
1101         }
1102         else {
1103                 glPushMatrix();
1104                 if (dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
1105                 else drawcube_size(xwidth, length, zwidth);
1106                 glPopMatrix();
1107         }
1108 }
1109
1110 static void draw_b_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
1111 {
1112         float xwidth, length, zwidth;
1113         
1114         if (pchan) {
1115                 xwidth= pchan->bone->xwidth;
1116                 length= pchan->bone->length;
1117                 zwidth= pchan->bone->zwidth;
1118         }
1119         else {
1120                 xwidth= ebone->xwidth;
1121                 length= ebone->length;
1122                 zwidth= ebone->zwidth;
1123         }
1124         
1125         /* draw points only if... */
1126         if (armflag & ARM_EDITMODE) {
1127                 /* move to unitspace */
1128                 glPushMatrix();
1129                 glScalef(length, length, length);
1130                 draw_bone_points(dt, armflag, boneflag, id);
1131                 glPopMatrix();
1132                 length*= 0.95f; // make vertices visible
1133         }
1134
1135         /* colors for modes */
1136         if (armflag & ARM_POSEMODE) {
1137                 if (dt <= OB_WIRE)
1138                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
1139                 else 
1140                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
1141         }
1142         else if (armflag & ARM_EDITMODE) {
1143                 if (dt==OB_WIRE) {
1144                         set_ebone_glColor(boneflag);
1145                 }
1146                 else 
1147                         UI_ThemeColor(TH_BONE_SOLID);
1148         }
1149         
1150         if (id != -1) {
1151                 glLoadName ((GLuint) id|BONESEL_BONE);
1152         }
1153         
1154         /* set up solid drawing */
1155         if (dt > OB_WIRE) {
1156                 glEnable(GL_COLOR_MATERIAL);
1157                 glEnable(GL_LIGHTING);
1158                 
1159                 if (armflag & ARM_POSEMODE)
1160                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
1161                 else
1162                         UI_ThemeColor(TH_BONE_SOLID);
1163                 
1164                 draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
1165                 
1166                 /* disable solid drawing */
1167                 glDisable(GL_COLOR_MATERIAL);
1168                 glDisable(GL_LIGHTING);
1169         }
1170         else {  
1171                 /* wire */
1172                 if (armflag & ARM_POSEMODE) {
1173                         if (constflag) {
1174                                 /* set constraint colors */
1175                                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
1176                                         glEnable(GL_BLEND);
1177                                         
1178                                         draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
1179                                         
1180                                         glDisable(GL_BLEND);
1181                                 }
1182                                 
1183                                 /* restore colors */
1184                                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
1185                         }
1186                 }               
1187                 
1188                 draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);              
1189         }
1190 }
1191
1192 static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float length, int segments)
1193 {
1194         if ((segments > 1) && (pchan)) {
1195                 float dlen= length/(float)segments;
1196                 Mat4 *bbone = bbones;
1197                 int a;
1198                 
1199                 for (a=0; a<segments; a++, bbone++) {
1200                         glPushMatrix();
1201                         glMultMatrixf(bbone->mat);
1202                         
1203                         glBegin(GL_LINES);
1204                         glVertex3f(0.0f, 0.0f, 0.0f);
1205                         glVertex3f(0.0f, dlen, 0.0f);
1206                         glEnd(); // GL_LINES
1207                         
1208                         glPopMatrix();
1209                 }
1210         }
1211         else {
1212                 glPushMatrix();
1213                 
1214                 glBegin(GL_LINES);
1215                 glVertex3f(0.0f, 0.0f, 0.0f);
1216                 glVertex3f(0.0f, length, 0.0f);
1217                 glEnd();
1218                 
1219                 glPopMatrix();
1220         }
1221 }
1222
1223 static void draw_wire_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
1224 {
1225         Mat4 *bbones = NULL;
1226         int segments = 0;
1227         float length;
1228         
1229         if (pchan) {
1230                 segments= pchan->bone->segments;
1231                 length= pchan->bone->length;
1232                 
1233                 if (segments > 1)
1234                         bbones = b_bone_spline_setup(pchan, 0);
1235         }
1236         else 
1237                 length= ebone->length;
1238         
1239         /* draw points only if... */
1240         if (armflag & ARM_EDITMODE) {
1241                 /* move to unitspace */
1242                 glPushMatrix();
1243                 glScalef(length, length, length);
1244                 draw_bone_points(dt, armflag, boneflag, id);
1245                 glPopMatrix();
1246                 length *= 0.95f;        // make vertices visible
1247         }
1248         
1249         /* this chunk not in object mode */
1250         if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
1251                 if (id != -1)
1252                         glLoadName((GLuint) id|BONESEL_BONE);
1253                 
1254                 draw_wire_bone_segments(pchan, bbones, length, segments);
1255                 
1256                 /* further we send no names */
1257                 if (id != -1)
1258                         glLoadName(id & 0xFFFF);        /* object tag, for bordersel optim */
1259         }
1260         
1261         /* colors for modes */
1262         if (armflag & ARM_POSEMODE) {
1263                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
1264         }
1265         else if (armflag & ARM_EDITMODE) {
1266                 set_ebone_glColor(boneflag);
1267         }
1268         
1269         /* draw normal */
1270         draw_wire_bone_segments(pchan, bbones, length, segments);
1271 }
1272
1273 static void draw_bone(int dt, int armflag, int boneflag, short constflag, unsigned int id, float length)
1274 {
1275         
1276         /*      Draw a 3d octahedral bone, we use normalized space based on length,
1277                 for glDisplayLists */
1278         
1279         glScalef(length, length, length);
1280
1281         /* set up solid drawing */
1282         if (dt > OB_WIRE) {
1283                 glEnable(GL_COLOR_MATERIAL);
1284                 glEnable(GL_LIGHTING);
1285                 UI_ThemeColor(TH_BONE_SOLID);
1286         }
1287         
1288         /* colors for posemode */
1289         if (armflag & ARM_POSEMODE) {
1290                 if (dt <= OB_WIRE)
1291                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
1292                 else 
1293                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
1294         }
1295         
1296         
1297         draw_bone_points(dt, armflag, boneflag, id);
1298         
1299         /* now draw the bone itself */
1300         if (id != -1) {
1301                 glLoadName((GLuint) id|BONESEL_BONE);
1302         }
1303         
1304         /* wire? */
1305         if (dt <= OB_WIRE) {
1306                 /* colors */
1307                 if (armflag & ARM_EDITMODE) {
1308                         set_ebone_glColor(boneflag);
1309                 }
1310                 else if (armflag & ARM_POSEMODE) {
1311                         if (constflag) {
1312                                 /* draw constraint colors */
1313                                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {       
1314                                         glEnable(GL_BLEND);
1315                                         
1316                                         draw_bone_solid_octahedral();
1317                                         
1318                                         glDisable(GL_BLEND);
1319                                 }
1320                                 
1321                                 /* restore colors */
1322                                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
1323                         }
1324                 }               
1325                 draw_bone_octahedral();
1326         }
1327         else {  
1328                 /* solid */
1329                 if (armflag & ARM_POSEMODE)
1330                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
1331                 else
1332                         UI_ThemeColor(TH_BONE_SOLID);
1333                 draw_bone_solid_octahedral();
1334         }
1335
1336         /* disable solid drawing */
1337         if (dt > OB_WIRE) {
1338                 glDisable(GL_COLOR_MATERIAL);
1339                 glDisable(GL_LIGHTING);
1340         }
1341 }
1342
1343 static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int armflag, int boneflag, unsigned int id, float length)
1344 {
1345         if(ob==NULL) return;
1346         
1347         glScalef(length, length, length);
1348         
1349         /* colors for posemode */
1350         if (armflag & ARM_POSEMODE) {
1351                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0);
1352         }
1353         
1354         if (id != -1) {
1355                 glLoadName((GLuint) id|BONESEL_BONE);
1356         }
1357         
1358         draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
1359 }
1360
1361
1362 static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
1363 {
1364         bConstraint *con;
1365         bPoseChannel *parchan;
1366         
1367         for (con= pchan->constraints.first; con; con= con->next) {
1368                 if (con->enforce == 0.0f)
1369                         continue;
1370                 
1371                 switch (con->type) {
1372                         case CONSTRAINT_TYPE_KINEMATIC:
1373                         {
1374                                 bKinematicConstraint *data = (bKinematicConstraint*)con->data;
1375                                 int segcount= 0;
1376                                 
1377                                 /* if only_temp, only draw if it is a temporary ik-chain */
1378                                 if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
1379                                         continue;
1380                                 
1381                                 setlinestyle(3);
1382                                 glBegin(GL_LINES);
1383                                 
1384                                 /* exclude tip from chain? */
1385                                 if ((data->flag & CONSTRAINT_IK_TIP)==0)
1386                                         parchan= pchan->parent;
1387                                 else
1388                                         parchan= pchan;
1389                                 
1390                                 glVertex3fv(parchan->pose_tail);
1391                                 
1392                                 /* Find the chain's root */
1393                                 while (parchan->parent) {
1394                                         segcount++;
1395                                         if(segcount==data->rootbone || segcount>255) break; // 255 is weak
1396                                         parchan= parchan->parent;
1397                                 }
1398                                 if (parchan)
1399                                         glVertex3fv(parchan->pose_head);
1400                                 
1401                                 glEnd();
1402                                 setlinestyle(0);
1403                         }
1404                                 break;
1405                         case CONSTRAINT_TYPE_SPLINEIK: 
1406                         {
1407                                 bSplineIKConstraint *data = (bSplineIKConstraint*)con->data;
1408                                 int segcount= 0;
1409                                 
1410                                 setlinestyle(3);
1411                                 glBegin(GL_LINES);
1412                                 
1413                                 parchan= pchan;
1414                                 glVertex3fv(parchan->pose_tail);
1415                                 
1416                                 /* Find the chain's root */
1417                                 while (parchan->parent) {
1418                                         segcount++;
1419                                         // FIXME: revise the breaking conditions
1420                                         if(segcount==data->chainlen || segcount>255) break; // 255 is weak
1421                                         parchan= parchan->parent;
1422                                 }
1423                                 if (parchan) // XXX revise the breaking conditions to only stop at the tail?
1424                                         glVertex3fv(parchan->pose_head);
1425                                 
1426                                 glEnd();
1427                                 setlinestyle(0);
1428                         }
1429                                 break;
1430                 }
1431         }
1432 }
1433
1434 static void bgl_sphere_project(float ax, float az)
1435 {
1436         float dir[3], sine, q3;
1437
1438         sine= 1.0f - ax*ax - az*az;
1439         q3= (sine < 0.0f)? 0.0f: (float)(2.0*sqrt(sine));
1440
1441         dir[0]= -az*q3;
1442         dir[1]= 1.0f - 2.0f*sine;
1443         dir[2]= ax*q3;
1444
1445         glVertex3fv(dir);
1446 }
1447
1448 static void draw_dof_ellipse(float ax, float az)
1449 {
1450         static float staticSine[16] = {
1451                 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
1452                 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
1453                 0.743144825477f, 0.809016994375f, 0.866025403784f,
1454                 0.913545457643f, 0.951056516295f, 0.978147600734f,
1455                 0.994521895368f, 1.0f
1456         };
1457
1458         int i, j, n=16;
1459         float x, z, px, pz;
1460
1461         glEnable(GL_BLEND);
1462         glDepthMask(0);
1463
1464         glColor4ub(70, 70, 70, 50);
1465
1466         glBegin(GL_QUADS);
1467         pz= 0.0f;
1468         for(i=1; i<n; i++) {
1469                 z= staticSine[i];
1470                 
1471                 px= 0.0f;
1472                 for(j=1; j<n-i+1; j++) {
1473                         x = staticSine[j];
1474                         
1475                         if(j == n-i) {
1476                                 glEnd();
1477                                 glBegin(GL_TRIANGLES);
1478                                 bgl_sphere_project(ax*px, az*z);
1479                                 bgl_sphere_project(ax*px, az*pz);
1480                                 bgl_sphere_project(ax*x, az*pz);
1481                                 glEnd();
1482                                 glBegin(GL_QUADS);
1483                         }
1484                         else {
1485                                 bgl_sphere_project(ax*x, az*z);
1486                                 bgl_sphere_project(ax*x, az*pz);
1487                                 bgl_sphere_project(ax*px, az*pz);
1488                                 bgl_sphere_project(ax*px, az*z);
1489                         }
1490                         
1491                         px= x;
1492                 }
1493                 pz= z;
1494         }
1495         glEnd();
1496
1497         glDisable(GL_BLEND);
1498         glDepthMask(1);
1499
1500         glColor3ub(0, 0, 0);
1501
1502         glBegin(GL_LINE_STRIP);
1503         for (i=0; i<n; i++)
1504                 bgl_sphere_project(staticSine[n-i-1]*ax, staticSine[i]*az);
1505         glEnd();
1506 }
1507
1508 static void draw_pose_dofs(Object *ob)
1509 {
1510         bArmature *arm= ob->data;
1511         bPoseChannel *pchan;
1512         Bone *bone;
1513         
1514         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1515                 bone= pchan->bone;
1516                 
1517                 if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
1518                         if (bone->flag & BONE_SELECTED) {
1519                                 if (bone->layer & arm->layer) {
1520                                         if (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
1521                                                 if (ED_pose_channel_in_IK_chain(ob, pchan)) {
1522                                                         float corner[4][3], posetrans[3], mat[4][4];
1523                                                         float phi=0.0f, theta=0.0f, scale;
1524                                                         int a, i;
1525                                                         
1526                                                         /* in parent-bone pose, but own restspace */
1527                                                         glPushMatrix();
1528                                                         
1529                                                         copy_v3_v3(posetrans, pchan->pose_mat[3]);
1530                                                         glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
1531                                                         
1532                                                         if (pchan->parent) {
1533                                                                 copy_m4_m4(mat, pchan->parent->pose_mat);
1534                                                                 mat[3][0]= mat[3][1]= mat[3][2]= 0.0f;
1535                                                                 glMultMatrixf(mat);
1536                                                         }
1537                                                         
1538                                                         copy_m4_m3(mat, pchan->bone->bone_mat);
1539                                                         glMultMatrixf(mat);
1540                                                         
1541                                                         scale= bone->length*pchan->size[1];
1542                                                         glScalef(scale, scale, scale);
1543                                                         
1544                                                         if (pchan->ikflag & BONE_IK_XLIMIT) {
1545                                                                 if (pchan->ikflag & BONE_IK_ZLIMIT) {
1546                                                                         float amin[3], amax[3];
1547                                                                         
1548                                                                         for (i=0; i<3; i++) {
1549                                                                                 /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1550                                                                                 amin[i]= (float)sin(pchan->limitmin[i]*0.5f);
1551                                                                                 amax[i]= (float)sin(pchan->limitmax[i]*0.5f);
1552                                                                         }
1553                                                                         
1554                                                                         glScalef(1.0f, -1.0f, 1.0f);
1555                                                                         if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
1556                                                                                 draw_dof_ellipse(amin[0], amin[2]);
1557                                                                         if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
1558                                                                                 draw_dof_ellipse(amin[0], amax[2]);
1559                                                                         if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
1560                                                                                 draw_dof_ellipse(amax[0], amin[2]);
1561                                                                         if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
1562                                                                                 draw_dof_ellipse(amax[0], amax[2]);
1563                                                                         glScalef(1.0f, -1.0f, 1.0f);
1564                                                                 }
1565                                                         }
1566                                                         
1567                                                         /* arcs */
1568                                                         if (pchan->ikflag & BONE_IK_ZLIMIT) {
1569                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
1570                                                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[2]+pchan->limitmax[2]));
1571                                                                 glRotatef(theta, 0.0f, 0.0f, 1.0f);
1572                                                                 
1573                                                                 glColor3ub(50, 50, 255);        // blue, Z axis limit
1574                                                                 glBegin(GL_LINE_STRIP);
1575                                                                 for (a=-16; a<=16; a++) {
1576                                                                         float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1577                                                                         
1578                                                                         phi= fac * (pchan->limitmax[2] - pchan->limitmin[2]);
1579                                                                         
1580                                                                         i= (a == -16) ? 0 : 1;
1581                                                                         corner[i][0]= (float)sin(phi);
1582                                                                         corner[i][1]= (float)cos(phi);
1583                                                                         corner[i][2]= 0.0f;
1584                                                                         glVertex3fv(corner[i]);
1585                                                                 }
1586                                                                 glEnd();
1587                                                                 
1588                                                                 glRotatef(-theta, 0.0f, 0.0f, 1.0f);
1589                                                         }                                       
1590                                                         
1591                                                         if (pchan->ikflag & BONE_IK_XLIMIT) {
1592                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
1593                                                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
1594                                                                 glRotatef(theta, 1.0f, 0.0f, 0.0f);
1595                                                                 
1596                                                                 glColor3ub(255, 50, 50);        // Red, X axis limit
1597                                                                 glBegin(GL_LINE_STRIP);
1598                                                                 for (a=-16; a<=16; a++) {
1599                                                                         float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
1600                                                                         phi= (float)(0.5*M_PI) + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
1601                                                                         
1602                                                                         i= (a == -16) ? 2 : 3;
1603                                                                         corner[i][0]= 0.0f;
1604                                                                         corner[i][1]= (float)sin(phi);
1605                                                                         corner[i][2]= (float)cos(phi);
1606                                                                         glVertex3fv(corner[i]);
1607                                                                 }
1608                                                                 glEnd();
1609                                                                 
1610                                                                 glRotatef(-theta, 1.0f, 0.0f, 0.0f);
1611                                                         }
1612                                                         
1613                                                         /* out of cone, out of bone */
1614                                                         glPopMatrix(); 
1615                                                 }
1616                                         }
1617                                 }
1618                         }
1619                 }
1620         }
1621 }
1622
1623 static void bone_matrix_translate_y(float mat[][4], float y)
1624 {
1625         float trans[3];
1626
1627         copy_v3_v3(trans, mat[1]);
1628         mul_v3_fl(trans, y);
1629         add_v3_v3(mat[3], trans);
1630 }
1631
1632 /* assumes object is Armature with pose */
1633 static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, const short is_ghost, const short is_outline)
1634 {
1635         RegionView3D *rv3d= ar->regiondata;
1636         Object *ob= base->object;
1637         bArmature *arm= ob->data;
1638         bPoseChannel *pchan;
1639         Bone *bone;
1640         GLfloat tmp;
1641         float smat[4][4], imat[4][4], bmat[4][4];
1642         int index= -1;
1643         short do_dashed= 3, draw_wire= 0;
1644         int flag;
1645         
1646         /* being set below */
1647         arm->layer_used= 0;
1648         
1649         /* hacky... prevent outline select from drawing dashed helplines */
1650         glGetFloatv(GL_LINE_WIDTH, &tmp);
1651         if (tmp > 1.1f) do_dashed &= ~1;
1652         if (v3d->flag & V3D_HIDE_HELPLINES) do_dashed &= ~2;
1653         
1654         /* precalc inverse matrix for drawing screen aligned */
1655         if (arm->drawtype==ARM_ENVELOPE) {
1656                 /* precalc inverse matrix for drawing screen aligned */
1657                 copy_m4_m4(smat, rv3d->viewmatob);
1658                 mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
1659                 invert_m4_m4(imat, smat);
1660                 
1661                 /* and draw blended distances */
1662                 if (arm->flag & ARM_POSEMODE) {
1663                         glEnable(GL_BLEND);
1664                         //glShadeModel(GL_SMOOTH);
1665                         
1666                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1667                         
1668                         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1669                                 bone= pchan->bone;
1670                                 if (bone) {
1671                                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] 
1672                                          * NOTE: this is the only case with NO_DEFORM==0 flag, as this is for envelope influence drawing 
1673                                          */
1674                                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM|BONE_HIDDEN_PG))==0 && 
1675                                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
1676                                         {
1677                                                 if (bone->flag & (BONE_SELECTED)) {
1678                                                         if (bone->layer & arm->layer)
1679                                                                 draw_sphere_bone_dist(smat, imat, pchan, NULL);
1680                                                 }
1681                                         }
1682                                 }
1683                         }
1684                         
1685                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
1686                         glDisable(GL_BLEND);
1687                         //glShadeModel(GL_FLAT);
1688                 }
1689         }
1690         
1691         /* little speedup, also make sure transparent only draws once */
1692         glCullFace(GL_BACK); 
1693         glEnable(GL_CULL_FACE);
1694         
1695         /* if solid we draw that first, with selection codes, but without names, axes etc */
1696         if (dt > OB_WIRE) {
1697                 if (arm->flag & ARM_POSEMODE) 
1698                         index= base->selcol;
1699                 
1700                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1701                         bone= pchan->bone;
1702                         arm->layer_used |= bone->layer;
1703                         
1704                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
1705                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
1706                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
1707                         {
1708                                 if (bone->layer & arm->layer) {
1709                                         int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
1710                                         glPushMatrix();
1711                                         
1712                                         if (use_custom && pchan->custom_tx) {
1713                                                 glMultMatrixf(pchan->custom_tx->pose_mat);
1714                                         } 
1715                                         else {
1716                                                 glMultMatrixf(pchan->pose_mat);
1717                                         }
1718                                         
1719                                         /* catch exception for bone with hidden parent */
1720                                         flag= bone->flag;
1721                                         if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) )
1722                                                 flag &= ~BONE_CONNECTED;
1723                                         
1724                                         /* set temporary flag for drawing bone as active, but only if selected */
1725                                         if (bone == arm->act_bone)
1726                                                 flag |= BONE_DRAW_ACTIVE;
1727                                         
1728                                         /* set color-set to use */
1729                                         set_pchan_colorset(ob, pchan);
1730                                         
1731                                         if (use_custom) {
1732                                                 /* if drawwire, don't try to draw in solid */
1733                                                 if (pchan->bone->flag & BONE_DRAWWIRE) 
1734                                                         draw_wire= 1;
1735                                                 else
1736                                                         draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, bone->length);
1737                                         }
1738                                         else if (arm->drawtype==ARM_LINE)
1739                                                 ;       /* nothing in solid */
1740                                         else if (arm->drawtype==ARM_WIRE)
1741                                                 ;       /* nothing in solid */
1742                                         else if (arm->drawtype==ARM_ENVELOPE)
1743                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
1744                                         else if (arm->drawtype==ARM_B_BONE)
1745                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
1746                                         else
1747                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
1748                                                 
1749                                         glPopMatrix();
1750                                 }
1751                         }
1752                         
1753                         if (index!= -1) 
1754                                 index+= 0x10000;        // pose bones count in higher 2 bytes only
1755                 }
1756                 
1757                 /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
1758                  * stick bones and/or wire custom-shapes are drawn in next loop 
1759                  */
1760                 if (ELEM(arm->drawtype,ARM_LINE,ARM_WIRE)==0 && (draw_wire == 0)) {
1761                         /* object tag, for bordersel optim */
1762                         glLoadName(index & 0xFFFF);     
1763                         index= -1;
1764                 }
1765         }
1766         
1767         /* draw custom bone shapes as wireframes */
1768         if ( !(arm->flag & ARM_NO_CUSTOM) &&
1769                  ((draw_wire) || (dt <= OB_WIRE)) ) 
1770         {
1771                 if (arm->flag & ARM_POSEMODE)
1772                         index= base->selcol;
1773                         
1774                 /* only draw custom bone shapes that need to be drawn as wires */
1775                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1776                         bone= pchan->bone;
1777                         
1778                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
1779                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
1780                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
1781                         {
1782                                 if (bone->layer & arm->layer) {
1783                                         if (pchan->custom) {
1784                                                 if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
1785                                                         glPushMatrix();
1786                                                         
1787                                                         if(pchan->custom_tx) {
1788                                                                 glMultMatrixf(pchan->custom_tx->pose_mat);
1789                                                         } 
1790                                                         else {
1791                                                                 glMultMatrixf(pchan->pose_mat);
1792                                                         }
1793                                                         
1794                                                         /* prepare colors */
1795                                                         if(is_ghost) {
1796                                                                 /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
1797                                                         }
1798                                                         else if (arm->flag & ARM_POSEMODE)      
1799                                                                 set_pchan_colorset(ob, pchan);
1800                                                         else {
1801                                                                 if ((scene->basact)==base) {
1802                                                                         if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
1803                                                                         else UI_ThemeColor(TH_WIRE);
1804                                                                 }
1805                                                                 else {
1806                                                                         if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
1807                                                                         else UI_ThemeColor(TH_WIRE);
1808                                                                 }
1809                                                         }
1810                                                                 
1811                                                         /* catch exception for bone with hidden parent */
1812                                                         flag= bone->flag;
1813                                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
1814                                                                 flag &= ~BONE_CONNECTED;
1815                                                                 
1816                                                         /* set temporary flag for drawing bone as active, but only if selected */
1817                                                         if (bone == arm->act_bone)
1818                                                                 flag |= BONE_DRAW_ACTIVE;
1819                                                         
1820                                                         draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length);
1821                                                         
1822                                                         glPopMatrix();
1823                                                 }
1824                                         }
1825                                 }
1826                         }
1827                         
1828                         if (index != -1) 
1829                                 index+= 0x10000;        // pose bones count in higher 2 bytes only
1830                 }
1831                 /* stick or wire bones have not been drawn yet so dont clear object selection in this case */
1832                 if (ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)==0 && draw_wire) {
1833                         /* object tag, for bordersel optim */
1834                         glLoadName(index & 0xFFFF);     
1835                         index= -1;
1836                 }
1837         }
1838         
1839         /* wire draw over solid only in posemode */
1840         if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
1841                 /* draw line check first. we do selection indices */
1842                 if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
1843                         if (arm->flag & ARM_POSEMODE) 
1844                                 index= base->selcol;
1845                 }
1846                 /* if solid && posemode, we draw again with polygonoffset */
1847                 else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
1848                         bglPolygonOffset(rv3d->dist, 1.0);
1849                 }
1850                 else {
1851                         /* and we use selection indices if not done yet */
1852                         if (arm->flag & ARM_POSEMODE) 
1853                                 index= base->selcol;
1854                 }
1855                 
1856                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
1857                         bone= pchan->bone;
1858                         arm->layer_used |= bone->layer;
1859                         
1860                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
1861                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
1862                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
1863                         {
1864                                 if (bone->layer & arm->layer) {
1865                                         const short constflag= pchan->constflag;
1866                                         if ((do_dashed & 1) && (pchan->parent)) {
1867                                                 /* Draw a line from our root to the parent's tip 
1868                                                  *      - only if V3D_HIDE_HELPLINES is enabled...
1869                                                  */
1870                                                 if ( (do_dashed & 2) && ((bone->flag & BONE_CONNECTED)==0) ) {
1871                                                         if (arm->flag & ARM_POSEMODE) {
1872                                                                 glLoadName(index & 0xFFFF);     // object tag, for bordersel optim
1873                                                                 UI_ThemeColor(TH_WIRE);
1874                                                         }
1875                                                         setlinestyle(3);
1876                                                         glBegin(GL_LINES);
1877                                                         glVertex3fv(pchan->pose_head);
1878                                                         glVertex3fv(pchan->parent->pose_tail);
1879                                                         glEnd();
1880                                                         setlinestyle(0);
1881                                                 }
1882                                                 
1883                                                 /* Draw a line to IK root bone 
1884                                                  *      - only if temporary chain (i.e. "autoik")
1885                                                  */
1886                                                 if (arm->flag & ARM_POSEMODE) {
1887                                                         if (constflag & PCHAN_HAS_IK) {
1888                                                                 if (bone->flag & BONE_SELECTED) {
1889                                                                         if (constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
1890                                                                         else glColor3ub(200, 200, 50);  // add theme!
1891                                                                         
1892                                                                         glLoadName(index & 0xFFFF);
1893                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
1894                                                                 }
1895                                                         }
1896                                                         else if (constflag & PCHAN_HAS_SPLINEIK) {
1897                                                                 if (bone->flag & BONE_SELECTED) {
1898                                                                         glColor3ub(150, 200, 50);       // add theme!
1899                                                                         
1900                                                                         glLoadName(index & 0xFFFF);
1901                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
1902                                                                 }
1903                                                         }       
1904                                                 }
1905                                         }
1906                                         
1907                                         glPushMatrix();
1908                                         if (arm->drawtype != ARM_ENVELOPE)
1909                                                 glMultMatrixf(pchan->pose_mat);
1910                                         
1911                                         /* catch exception for bone with hidden parent */
1912                                         flag= bone->flag;
1913                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
1914                                                 flag &= ~BONE_CONNECTED;
1915                                         
1916                                         /* set temporary flag for drawing bone as active, but only if selected */
1917                                         if (bone == arm->act_bone)
1918                                                 flag |= BONE_DRAW_ACTIVE;
1919                                         
1920                                         /* extra draw service for pose mode */
1921
1922                                         /* set color-set to use */
1923                                         set_pchan_colorset(ob, pchan);
1924                                         
1925                                         if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM))
1926                                                 ; // custom bone shapes should not be drawn here!
1927                                         else if (arm->drawtype==ARM_ENVELOPE) {
1928                                                 if (dt < OB_SOLID)
1929                                                         draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
1930                                         }
1931                                         else if (arm->drawtype==ARM_LINE)
1932                                                 draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
1933                                         else if (arm->drawtype==ARM_WIRE)
1934                                                 draw_wire_bone(dt, arm->flag, flag, constflag, index, pchan, NULL);
1935                                         else if (arm->drawtype==ARM_B_BONE)
1936                                                 draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
1937                                         else
1938                                                 draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
1939                                         
1940                                         glPopMatrix();
1941                                 }
1942                         }
1943                         
1944                         /* pose bones count in higher 2 bytes only */
1945                         if (index != -1) 
1946                                 index+= 0x10000;        
1947                 }
1948                 /* restore things */
1949                 if (!ELEM(arm->drawtype, ARM_WIRE, ARM_LINE) && (dt>OB_WIRE) && (arm->flag & ARM_POSEMODE))
1950                         bglPolygonOffset(rv3d->dist, 0.0);
1951         }       
1952         
1953         /* restore */
1954         glDisable(GL_CULL_FACE);
1955         
1956         /* draw DoFs */
1957         if (arm->flag & ARM_POSEMODE)
1958                 draw_pose_dofs(ob);
1959
1960         /* finally names and axes */
1961         if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES) && is_outline == 0) {
1962                 /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
1963                 if ((G.f & G_PICKSEL) == 0) {
1964                         float vec[3];
1965                         
1966                         unsigned char col[4];
1967                         float col_f[4];
1968                         glGetFloatv(GL_CURRENT_COLOR, col_f); /* incase this is not set below */
1969                         rgb_float_to_uchar(col, col_f);
1970                         col[3]= 255;
1971                         
1972                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1973                         
1974                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
1975                                 if ((pchan->bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0) {
1976                                         if (pchan->bone->layer & arm->layer) {
1977                                                 if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) {
1978                                                         bone= pchan->bone;
1979                                                         UI_GetThemeColor3ubv((bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
1980                                                 }
1981                                                 else if (dt > OB_WIRE) {
1982                                                         UI_GetThemeColor3ubv(TH_TEXT, col);
1983                                                 }
1984                                                 
1985                                                 /*      Draw names of bone      */
1986                                                 if (arm->flag & ARM_DRAWNAMES) {
1987                                                         mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
1988                                                         view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col);
1989                                                 }       
1990                                                 
1991                                                 /*      Draw additional axes on the bone tail  */
1992                                                 if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) {
1993                                                         glPushMatrix();
1994                                                         copy_m4_m4(bmat, pchan->pose_mat);
1995                                                         bone_matrix_translate_y(bmat, pchan->bone->length);
1996                                                         glMultMatrixf(bmat);
1997                                                         
1998                                                         glColor3ubv(col);
1999                                                         drawaxes(pchan->bone->length*0.25f, OB_ARROWS);
2000                                                         
2001                                                         glPopMatrix();
2002                                                 }
2003                                         }
2004                                 }
2005                         }
2006                         
2007                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2008                 }
2009         }
2010 }
2011
2012 /* in editmode, we don't store the bone matrix... */
2013 static void get_matrix_editbone(EditBone *eBone, float bmat[][4])
2014 {
2015         float           delta[3];
2016         float           mat[3][3];
2017         
2018         /* Compose the parent transforms (i.e. their translations) */
2019         sub_v3_v3v3(delta, eBone->tail, eBone->head);   
2020         
2021         eBone->length = (float)sqrt(delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
2022         
2023         vec_roll_to_mat3(delta, eBone->roll, mat);
2024         copy_m4_m3(bmat, mat);
2025
2026         add_v3_v3(bmat[3], eBone->head);
2027 }
2028
2029 static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
2030 {
2031         RegionView3D *rv3d= ar->regiondata;
2032         EditBone *eBone;
2033         bArmature *arm= ob->data;
2034         float smat[4][4], imat[4][4], bmat[4][4];
2035         unsigned int index;
2036         int flag;
2037         
2038         /* being set in code below */
2039         arm->layer_used= 0;
2040         
2041         /* envelope (deform distance) */
2042         if(arm->drawtype==ARM_ENVELOPE) {
2043                 /* precalc inverse matrix for drawing screen aligned */
2044                 copy_m4_m4(smat, rv3d->viewmatob);
2045                 mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
2046                 invert_m4_m4(imat, smat);
2047                 
2048                 /* and draw blended distances */
2049                 glEnable(GL_BLEND);
2050                 //glShadeModel(GL_SMOOTH);
2051                 
2052                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2053
2054                 for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
2055                         if (eBone->layer & arm->layer) {
2056                                 if ((eBone->flag & (BONE_HIDDEN_A|BONE_NO_DEFORM))==0) {
2057                                         if (eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
2058                                                 draw_sphere_bone_dist(smat, imat, NULL, eBone);
2059                                 }
2060                         }
2061                 }
2062                 
2063                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2064                 glDisable(GL_BLEND);
2065                 //glShadeModel(GL_FLAT);
2066         }
2067         
2068         /* if solid we draw it first */
2069         if ((dt > OB_WIRE) && (arm->drawtype != ARM_LINE)) {
2070                 for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
2071                         if (eBone->layer & arm->layer) {
2072                                 if ((eBone->flag & BONE_HIDDEN_A)==0) {
2073                                         glPushMatrix();
2074                                         get_matrix_editbone(eBone, bmat);
2075                                         glMultMatrixf(bmat);
2076                                         
2077                                         /* catch exception for bone with hidden parent */
2078                                         flag= eBone->flag;
2079                                         if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
2080                                                 flag &= ~BONE_CONNECTED;
2081                                                 
2082                                         /* set temporary flag for drawing bone as active, but only if selected */
2083                                         if (eBone == arm->act_edbone)
2084                                                 flag |= BONE_DRAW_ACTIVE;
2085                                         
2086                                         if (arm->drawtype==ARM_ENVELOPE)
2087                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2088                                         else if(arm->drawtype==ARM_B_BONE)
2089                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2090                                         else if (arm->drawtype==ARM_WIRE)
2091                                                 draw_wire_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
2092                                         else {
2093                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
2094                                         }
2095                                         
2096                                         glPopMatrix();
2097                                 }
2098                         }
2099                 }
2100         }
2101         
2102         /* if wire over solid, set offset */
2103         index= -1;
2104         glLoadName(-1);
2105         if ELEM(arm->drawtype, ARM_LINE, ARM_WIRE) {
2106                 if(G.f & G_PICKSEL)
2107                         index= 0;
2108         }
2109         else if (dt > OB_WIRE) 
2110                 bglPolygonOffset(rv3d->dist, 1.0f);
2111         else if (arm->flag & ARM_EDITMODE) 
2112                 index= 0;       /* do selection codes */
2113         
2114         for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
2115                 arm->layer_used |= eBone->layer;
2116                 if (eBone->layer & arm->layer) {
2117                         if ((eBone->flag & BONE_HIDDEN_A)==0) {
2118                                 
2119                                 /* catch exception for bone with hidden parent */
2120                                 flag= eBone->flag;
2121                                 if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
2122                                         flag &= ~BONE_CONNECTED;
2123                                         
2124                                 /* set temporary flag for drawing bone as active, but only if selected */
2125                                 if (eBone == arm->act_edbone)
2126                                         flag |= BONE_DRAW_ACTIVE;
2127                                 
2128                                 if (arm->drawtype == ARM_ENVELOPE) {
2129                                         if (dt < OB_SOLID)
2130                                                 draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
2131                                 }
2132                                 else {
2133                                         glPushMatrix();
2134                                         get_matrix_editbone(eBone, bmat);
2135                                         glMultMatrixf(bmat);
2136                                         
2137                                         if (arm->drawtype == ARM_LINE) 
2138                                                 draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
2139                                         else if (arm->drawtype==ARM_WIRE)
2140                                                 draw_wire_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
2141                                         else if (arm->drawtype == ARM_B_BONE)
2142                                                 draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
2143                                         else
2144                                                 draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
2145                                         
2146                                         glPopMatrix();
2147                                 }
2148                                 
2149                                 /* offset to parent */
2150                                 if (eBone->parent) {
2151                                         UI_ThemeColor(TH_WIRE);
2152                                         glLoadName (-1);                // -1 here is OK!
2153                                         setlinestyle(3);
2154                                         
2155                                         glBegin(GL_LINES);
2156                                         glVertex3fv(eBone->parent->tail);
2157                                         glVertex3fv(eBone->head);
2158                                         glEnd();
2159                                         
2160                                         setlinestyle(0);
2161                                 }
2162                         }
2163                 }
2164                 if(index!=-1) index++;
2165         }
2166         
2167         /* restore */
2168         if(index!=-1) glLoadName(-1);
2169         if ELEM(arm->drawtype,ARM_LINE,ARM_WIRE);
2170         else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
2171         
2172         /* finally names and axes */
2173         if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
2174                 // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
2175                 if ((G.f & G_PICKSEL) == 0) {
2176                         float vec[3];
2177                         unsigned char col[4];
2178                         col[3]= 255;
2179                         
2180                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2181                         
2182                         for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
2183                                 if(eBone->layer & arm->layer) {
2184                                         if ((eBone->flag & BONE_HIDDEN_A)==0) {
2185
2186                                                 UI_GetThemeColor3ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
2187
2188                                                 /*      Draw name */
2189                                                 if (arm->flag & ARM_DRAWNAMES) {
2190                                                         mid_v3_v3v3(vec, eBone->head, eBone->tail);
2191                                                         glRasterPos3fv(vec);
2192                                                         view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col);
2193                                                 }                                       
2194                                                 /*      Draw additional axes */
2195                                                 if (arm->flag & ARM_DRAWAXES) {
2196                                                         glPushMatrix();
2197                                                         get_matrix_editbone(eBone, bmat);
2198                                                         bone_matrix_translate_y(bmat, eBone->length);
2199                                                         glMultMatrixf(bmat);
2200
2201                                                         glColor3ubv(col);
2202                                                         drawaxes(eBone->length*0.25f, OB_ARROWS);
2203                                                         
2204                                                         glPopMatrix();
2205                                                 }
2206                                                 
2207                                         }
2208                                 }
2209                         }
2210                         
2211                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2212                 }
2213         }
2214 }
2215
2216 /* ****************************** Armature Visualisation ******************************** */
2217
2218 /* ---------- Paths --------- */
2219
2220 /* draw bone paths
2221  *      - in view space 
2222  */
2223 static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
2224 {
2225         bAnimVizSettings *avs= &ob->pose->avs;
2226         bArmature *arm= ob->data;
2227         bPoseChannel *pchan;
2228         
2229         /* setup drawing environment for paths */
2230         draw_motion_paths_init(v3d, ar);
2231         
2232         /* draw paths where they exist and they releated bone is visible */
2233         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2234                 if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
2235                         draw_motion_path_instance(scene, ob, pchan, avs, pchan->mpath);
2236         }
2237         
2238         /* cleanup after drawing */
2239         draw_motion_paths_cleanup(v3d);
2240 }
2241
2242
2243 /* ---------- Ghosts --------- */
2244
2245 /* helper function for ghost drawing - sets/removes flags for temporarily 
2246  * hiding unselected bones while drawing ghosts
2247  */
2248 static void ghost_poses_tag_unselected(Object *ob, short unset)
2249 {
2250         bArmature *arm= ob->data;
2251         bPose *pose= ob->pose;
2252         bPoseChannel *pchan;
2253         
2254         /* don't do anything if no hiding any bones */
2255         if ((arm->flag & ARM_GHOST_ONLYSEL)==0)
2256                 return;
2257                 
2258         /* loop over all pchans, adding/removing tags as appropriate */
2259         for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
2260                 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
2261                         if (unset) {
2262                                 /* remove tags from all pchans if cleaning up */
2263                                 pchan->bone->flag &= ~BONE_HIDDEN_PG;
2264                         }
2265                         else {
2266                                 /* set tags on unselected pchans only */
2267                                 if ((pchan->bone->flag & BONE_SELECTED)==0)
2268                                         pchan->bone->flag |= BONE_HIDDEN_PG;
2269                         }
2270                 }
2271         }
2272 }
2273
2274 /* draw ghosts that occur within a frame range 
2275  *      note: object should be in posemode 
2276  */
2277 static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
2278 {
2279         Object *ob= base->object;
2280         AnimData *adt= BKE_animdata_from_id(&ob->id);
2281         bArmature *arm= ob->data;
2282         bPose *posen, *poseo;
2283         float start, end, stepsize, range, colfac;
2284         int cfrao, flago, ipoflago;
2285         
2286         start = (float)arm->ghostsf;
2287         end = (float)arm->ghostef;
2288         if (end <= start)
2289                 return;
2290         
2291         stepsize= (float)(arm->ghostsize);
2292         range= (float)(end - start);
2293         
2294         /* store values */
2295         ob->mode &= ~OB_MODE_POSE;
2296         cfrao= CFRA;
2297         flago= arm->flag;
2298         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
2299         ipoflago= ob->ipoflag; 
2300         ob->ipoflag |= OB_DISABLE_PATH;
2301         
2302         /* copy the pose */
2303         poseo= ob->pose;
2304         copy_pose(&posen, ob->pose, 1);
2305         ob->pose= posen;
2306         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
2307         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
2308         
2309         glEnable(GL_BLEND);
2310         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2311         
2312         /* draw from first frame of range to last */
2313         for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) {
2314                 colfac = (end - (float)CFRA) / range;
2315                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
2316                 
2317                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
2318                 where_is_pose(scene, ob);
2319                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
2320         }
2321         glDisable(GL_BLEND);
2322         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2323
2324         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
2325         free_pose(posen);
2326         
2327         /* restore */
2328         CFRA= cfrao;
2329         ob->pose= poseo;
2330         arm->flag= flago;
2331         armature_rebuild_pose(ob, ob->data);
2332         ob->mode |= OB_MODE_POSE;
2333         ob->ipoflag= ipoflago; 
2334 }
2335
2336 /* draw ghosts on keyframes in action within range 
2337  *      - object should be in posemode 
2338  */
2339 static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
2340 {
2341         Object *ob= base->object;
2342         AnimData *adt= BKE_animdata_from_id(&ob->id);
2343         bAction *act= (adt) ? adt->action : NULL;
2344         bArmature *arm= ob->data;
2345         bPose *posen, *poseo;
2346         DLRBT_Tree keys;
2347         ActKeyColumn *ak, *akn;
2348         float start, end, range, colfac, i;
2349         int cfrao, flago;
2350         
2351         start = (float)arm->ghostsf;
2352         end = (float)arm->ghostef;
2353         if (end <= start)
2354                 return;
2355         
2356         /* get keyframes - then clip to only within range */
2357         BLI_dlrbTree_init(&keys);
2358         action_to_keylist(adt, act, &keys, NULL);
2359         BLI_dlrbTree_linkedlist_sync(&keys);
2360         
2361         range= 0;
2362         for (ak= keys.first; ak; ak= akn) {
2363                 akn= ak->next;
2364                 
2365                 if ((ak->cfra < start) || (ak->cfra > end))
2366                         BLI_freelinkN((ListBase *)&keys, ak);
2367                 else
2368                         range++;
2369         }
2370         if (range == 0) return;
2371         
2372         /* store values */
2373         ob->mode &= ~OB_MODE_POSE;
2374         cfrao= CFRA;
2375         flago= arm->flag;
2376         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
2377         ob->ipoflag |= OB_DISABLE_PATH;
2378         
2379         /* copy the pose */
2380         poseo= ob->pose;
2381         copy_pose(&posen, ob->pose, 1);
2382         ob->pose= posen;
2383         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
2384         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
2385         
2386         glEnable(GL_BLEND);
2387         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2388         
2389         /* draw from first frame of range to last */
2390         for (ak=keys.first, i=0; ak; ak=ak->next, i++) {
2391                 colfac = i/range;
2392                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
2393                 
2394                 CFRA= (int)ak->cfra;
2395                 
2396                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
2397                 where_is_pose(scene, ob);
2398                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
2399         }
2400         glDisable(GL_BLEND);
2401         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2402
2403         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
2404         BLI_dlrbTree_free(&keys);
2405         free_pose(posen);
2406         
2407         /* restore */
2408         CFRA= cfrao;
2409         ob->pose= poseo;
2410         arm->flag= flago;
2411         armature_rebuild_pose(ob, ob->data);
2412         ob->mode |= OB_MODE_POSE;
2413 }
2414
2415 /* draw ghosts around current frame
2416  *      - object is supposed to be armature in posemode 
2417  */
2418 static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
2419 {
2420         Object *ob= base->object;
2421         AnimData *adt= BKE_animdata_from_id(&ob->id);
2422         bArmature *arm= ob->data;
2423         bPose *posen, *poseo;
2424         float cur, start, end, stepsize, range, colfac, actframe, ctime;
2425         int cfrao, flago;
2426         
2427         /* pre conditions, get an action with sufficient frames */
2428         if ELEM(NULL, adt, adt->action)
2429                 return;
2430
2431         calc_action_range(adt->action, &start, &end, 0);
2432         if (start == end)
2433                 return;
2434
2435         stepsize= (float)(arm->ghostsize);
2436         range= (float)(arm->ghostep)*stepsize + 0.5f;   /* plus half to make the for loop end correct */
2437         
2438         /* store values */
2439         ob->mode &= ~OB_MODE_POSE;
2440         cfrao= CFRA;
2441         actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
2442         flago= arm->flag;
2443         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
2444         
2445         /* copy the pose */
2446         poseo= ob->pose;
2447         copy_pose(&posen, ob->pose, 1);
2448         ob->pose= posen;
2449         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
2450         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
2451         
2452         glEnable(GL_BLEND);
2453         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
2454         
2455         /* draw from darkest blend to lowest */
2456         for(cur= stepsize; cur<range; cur+=stepsize) {
2457                 ctime= cur - (float)fmod(cfrao, stepsize);      /* ensures consistent stepping */
2458                 colfac= ctime/range;
2459                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
2460                 
2461                 /* only within action range */
2462                 if (actframe+ctime >= start && actframe+ctime <= end) {
2463                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
2464                         
2465                         if (CFRA != cfrao) {
2466                                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
2467                                 where_is_pose(scene, ob);
2468                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
2469                         }
2470                 }
2471                 
2472                 ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f;       /* ensures consistent stepping */
2473                 colfac= ctime/range;
2474                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
2475                 
2476                 /* only within action range */
2477                 if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
2478                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
2479                         
2480                         if (CFRA != cfrao) {
2481                                 BKE_animsys_evaluate_animdata(scene, &ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
2482                                 where_is_pose(scene, ob);
2483                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
2484                         }
2485                 }
2486         }
2487         glDisable(GL_BLEND);
2488         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
2489
2490         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
2491         free_pose(posen);
2492         
2493         /* restore */
2494         CFRA= cfrao;
2495         ob->pose= poseo;
2496         arm->flag= flago;
2497         armature_rebuild_pose(ob, ob->data);
2498         ob->mode |= OB_MODE_POSE;
2499 }
2500
2501 /* ********************************** Armature Drawing - Main ************************* */
2502
2503 /* called from drawobject.c, return 1 if nothing was drawn */
2504 int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline)
2505 {
2506         Object *ob= base->object;
2507         bArmature *arm= ob->data;
2508         int retval= 0;
2509
2510         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
2511                 return 1;
2512         
2513         if(dt>OB_WIRE && !ELEM(arm->drawtype, ARM_LINE, ARM_WIRE)) {
2514                 /* we use color for solid lighting */
2515                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
2516                 glEnable(GL_COLOR_MATERIAL);
2517                 glColor3ub(255,255,255);        // clear spec
2518                 glDisable(GL_COLOR_MATERIAL);
2519                 
2520                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
2521                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
2522         }
2523         
2524         /* arm->flag is being used to detect mode... */
2525         /* editmode? */
2526         if(arm->edbo) {
2527                 arm->flag |= ARM_EDITMODE;
2528                 draw_ebones(v3d, ar, ob, dt);
2529                 arm->flag &= ~ARM_EDITMODE;
2530         }
2531         else{
2532                 /*      Draw Pose */
2533                 if(ob->pose && ob->pose->chanbase.first) {
2534                         /* drawing posemode selection indices or colors only in these cases */
2535                         if(!(base->flag & OB_FROMDUPLI)) {
2536                                 if(G.f & G_PICKSEL) {
2537 #if 0                           /* nifty but actually confusing to allow bone selection out of posemode */
2538                                         if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
2539                                                 if(ob==modifiers_isDeformedByArmature(OBACT))
2540                                                         arm->flag |= ARM_POSEMODE;
2541                                         }
2542                                         else
2543 #endif
2544                                         if(ob->mode & OB_MODE_POSE) {
2545                                                 arm->flag |= ARM_POSEMODE;
2546                                         }
2547                                 }
2548                                 else if(ob->mode & OB_MODE_POSE) {
2549                                         if (arm->ghosttype == ARM_GHOST_RANGE) {
2550                                                 draw_ghost_poses_range(scene, v3d, ar, base);
2551                                         }
2552                                         else if (arm->ghosttype == ARM_GHOST_KEYS) {
2553                                                 draw_ghost_poses_keys(scene, v3d, ar, base);
2554                                         }
2555                                         else if (arm->ghosttype == ARM_GHOST_CUR) {
2556                                                 if (arm->ghostep)
2557                                                         draw_ghost_poses(scene, v3d, ar, base);
2558                                         }
2559                                         if ((flag & DRAW_SCENESET)==0) {
2560                                                 if(ob==OBACT) 
2561                                                         arm->flag |= ARM_POSEMODE;
2562                                                 else if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
2563                                                         if(ob==modifiers_isDeformedByArmature(OBACT))
2564                                                                 arm->flag |= ARM_POSEMODE;
2565                                                 }
2566                                                 draw_pose_paths(scene, v3d, ar, ob);
2567                                         }
2568                                 }       
2569                         }
2570                         draw_pose_bones(scene, v3d, ar, base, dt, FALSE, is_outline);
2571                         arm->flag &= ~ARM_POSEMODE; 
2572                         
2573                         if(ob->mode & OB_MODE_POSE)
2574                                 UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
2575                 }
2576                 else retval= 1;
2577         }
2578         /* restore */
2579         glFrontFace(GL_CCW);
2580
2581         return retval;
2582 }
2583
2584 /* *************** END Armature drawing ******************* */
2585
2586