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