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