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