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