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