Blender  V2.59
drawarmature.c
Go to the documentation of this file.
00001 /*
00002  * $Id: drawarmature.c 38112 2011-07-05 09:35:38Z blendix $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include <stdlib.h>
00036 #include <string.h>
00037 #include <math.h>
00038 
00039 
00040 #include "DNA_anim_types.h"
00041 #include "DNA_armature_types.h"
00042 #include "DNA_constraint_types.h"
00043 #include "DNA_scene_types.h"
00044 #include "DNA_screen_types.h"
00045 #include "DNA_view3d_types.h"
00046 #include "DNA_object_types.h"
00047 
00048 #include "BLI_blenlib.h"
00049 #include "BLI_math.h"
00050 #include "BLI_dlrbTree.h"
00051 #include "BLI_utildefines.h"
00052 
00053 #include "BKE_animsys.h"
00054 #include "BKE_action.h"
00055 #include "BKE_armature.h"
00056 #include "BKE_global.h"
00057 #include "BKE_modifier.h"
00058 #include "BKE_nla.h"
00059 
00060 
00061 #include "BIF_gl.h"
00062 #include "BIF_glutil.h"
00063 
00064 #include "ED_armature.h"
00065 #include "ED_keyframes_draw.h"
00066 
00067 #include "BLF_api.h"
00068 
00069 #include "UI_resources.h"
00070 
00071 #include "view3d_intern.h"
00072 
00073 
00074 /* *************** Armature Drawing - Coloring API ***************************** */
00075 
00076 /* global here is reset before drawing each bone */
00077 static ThemeWireColor *bcolor= NULL;
00078 
00079 /* values of colCode for set_pchan_glcolor */
00080 enum {
00081         PCHAN_COLOR_NORMAL      = 0,            /* normal drawing */
00082         PCHAN_COLOR_SOLID,                              /* specific case where "solid" color is needed */
00083         PCHAN_COLOR_CONSTS,                             /* "constraint" colors (which may/may-not be suppressed) */
00084         
00085         PCHAN_COLOR_SPHEREBONE_BASE,    /* for the 'stick' of sphere (envelope) bones */
00086         PCHAN_COLOR_SPHEREBONE_END,             /* for the ends of sphere (envelope) bones */
00087         PCHAN_COLOR_LINEBONE                    /* for the middle of line-bones */
00088 };      
00089 
00090 /* This function sets the color-set for coloring a certain bone */
00091 static void set_pchan_colorset (Object *ob, bPoseChannel *pchan)
00092 {
00093         bPose *pose= (ob) ? ob->pose : NULL;
00094         bArmature *arm= (ob) ? ob->data : NULL;
00095         bActionGroup *grp= NULL;
00096         short color_index= 0;
00097         
00098         /* sanity check */
00099         if (ELEM4(NULL, ob, arm, pose, pchan)) {
00100                 bcolor= NULL;
00101                 return;
00102         }
00103         
00104         /* only try to set custom color if enabled for armature */
00105         if (arm->flag & ARM_COL_CUSTOM) {       
00106                 /* currently, a bone can only use a custom color set if it's group (if it has one),
00107                  * has been set to use one
00108                  */
00109                 if (pchan->agrp_index) {
00110                         grp= (bActionGroup *)BLI_findlink(&pose->agroups, (pchan->agrp_index - 1));
00111                         if (grp)
00112                                 color_index= grp->customCol;
00113                 }
00114         }
00115         
00116         /* bcolor is a pointer to the color set to use. If NULL, then the default
00117          * color set (based on the theme colors for 3d-view) is used. 
00118          */
00119         if (color_index > 0) {
00120                 bTheme *btheme= U.themes.first;
00121                 bcolor= &btheme->tarm[(color_index - 1)];
00122         }
00123         else if (color_index == -1) {
00124                 /* use the group's own custom color set */
00125                 bcolor= (grp)? &grp->cs : NULL;
00126         }
00127         else 
00128                 bcolor= NULL;
00129 }
00130 
00131 /* This function is for brightening/darkening a given color (like UI_ThemeColorShade()) */
00132 static void cp_shade_color3ub (unsigned char cp[3], const int offset)
00133 {
00134         int r, g, b;
00135         
00136         r= offset + (int) cp[0];
00137         CLAMP(r, 0, 255);
00138         g= offset + (int) cp[1];
00139         CLAMP(g, 0, 255);
00140         b= offset + (int) cp[2];
00141         CLAMP(b, 0, 255);
00142         
00143         cp[0]= r;
00144         cp[1]= g;
00145         cp[2]= b;
00146 }
00147 
00148 /* This function sets the gl-color for coloring a certain bone (based on bcolor) */
00149 static short set_pchan_glColor (short colCode, int boneflag, int constflag)
00150 {
00151         switch (colCode) {
00152         case PCHAN_COLOR_NORMAL:
00153         {
00154                 if (bcolor) {
00155                         unsigned char cp[3];
00156                         
00157                         if (boneflag & BONE_DRAW_ACTIVE) {
00158                                 VECCOPY(cp, bcolor->active);
00159                                 if(!(boneflag & BONE_SELECTED)) {
00160                                         cp_shade_color3ub(cp, -80);
00161                                 }
00162                         }
00163                         else if (boneflag & BONE_SELECTED) {
00164                                 VECCOPY(cp, bcolor->select);
00165                         }
00166                         else {
00167                                 /* a bit darker than solid */
00168                                 VECCOPY(cp, bcolor->solid);
00169                                 cp_shade_color3ub(cp, -50);
00170                         }
00171                         
00172                         glColor3ubv(cp);
00173                 }
00174                 else {
00175                         if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, 40);
00176                         else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_BONE_POSE, 0.15f); /* unselected active */
00177                         else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
00178                         else UI_ThemeColor(TH_WIRE);
00179                 }
00180                 
00181                 return 1;
00182         }
00183                 break;
00184         
00185         case PCHAN_COLOR_SOLID:
00186         {
00187                 if (bcolor) {
00188                         glColor3ubv((unsigned char *)bcolor->solid);
00189                 }
00190                 else 
00191                         UI_ThemeColor(TH_BONE_SOLID);
00192                         
00193                 return 1;
00194         }
00195                 break;
00196                 
00197         case PCHAN_COLOR_CONSTS:
00198         {
00199                 if ( (bcolor == NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS) ) {
00200                         if (constflag & PCHAN_HAS_TARGET) glColor4ub(255, 150, 0, 80);
00201                         else if (constflag & PCHAN_HAS_IK) glColor4ub(255, 255, 0, 80);
00202                         else if (constflag & PCHAN_HAS_SPLINEIK) glColor4ub(200, 255, 0, 80);
00203                         else if (constflag & PCHAN_HAS_CONST) glColor4ub(0, 255, 120, 80);
00204                         else if (constflag) UI_ThemeColor4(TH_BONE_POSE);       // PCHAN_HAS_ACTION 
00205                         
00206                         return 1;
00207                 }
00208                 else 
00209                         return 0;
00210         }
00211                 break;
00212                 
00213         case PCHAN_COLOR_SPHEREBONE_BASE:
00214         {
00215                 if (bcolor) {
00216                         unsigned char cp[3];
00217                         
00218                         if (boneflag & BONE_DRAW_ACTIVE) {
00219                                 VECCOPY(cp, bcolor->active);
00220                         }
00221                         else if (boneflag & BONE_SELECTED) {
00222                                 VECCOPY(cp, bcolor->select);
00223                         }
00224                         else {
00225                                 VECCOPY(cp, bcolor->solid);
00226                         }
00227                         
00228                         glColor3ubv(cp);
00229                 }
00230                 else {
00231                         if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 40);
00232                         else if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_BONE_POSE);
00233                         else UI_ThemeColor(TH_BONE_SOLID);
00234                 }
00235                 
00236                 return 1;
00237         }
00238                 break;
00239         case PCHAN_COLOR_SPHEREBONE_END:
00240         {
00241                 if (bcolor) {
00242                         unsigned char cp[3];
00243                         
00244                         if (boneflag & BONE_DRAW_ACTIVE) {
00245                                 VECCOPY(cp, bcolor->active);
00246                                 cp_shade_color3ub(cp, 10);
00247                         }
00248                         else if (boneflag & BONE_SELECTED) {
00249                                 VECCOPY(cp, bcolor->select);
00250                                 cp_shade_color3ub(cp, -30);
00251                         }
00252                         else {
00253                                 VECCOPY(cp, bcolor->solid);
00254                                 cp_shade_color3ub(cp, -30);
00255                         }
00256                         
00257                         glColor3ubv(cp);
00258                 }
00259                 else {
00260                         if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorShade(TH_BONE_POSE, 10);
00261                         else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_BONE_POSE, -30);
00262                         else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00263                 }
00264         }
00265                 break;
00266                 
00267         case PCHAN_COLOR_LINEBONE:
00268         {
00269                 /* inner part in background color or constraint */
00270                 if ( (constflag) && ((bcolor==NULL) || (bcolor->flag & TH_WIRECOLOR_CONSTCOLS)) ) {
00271                         if (constflag & PCHAN_HAS_TARGET) glColor3ub(255, 150, 0);
00272                         else if (constflag & PCHAN_HAS_IK) glColor3ub(255, 255, 0);
00273                         else if (constflag & PCHAN_HAS_SPLINEIK) glColor3ub(200, 255, 0);
00274                         else if (constflag & PCHAN_HAS_CONST) glColor3ub(0, 255, 120);
00275                         else if (constflag) UI_ThemeColor(TH_BONE_POSE);        /* PCHAN_HAS_ACTION */ 
00276                 }
00277                 else {
00278                         if (bcolor) {
00279                                 char *cp= bcolor->solid;
00280                                 glColor4ub(cp[0], cp[1], cp[2], 204);   
00281                         }
00282                         else
00283                                 UI_ThemeColorShade(TH_BACK, -30);
00284                 }
00285                 
00286                 return 1;
00287         }
00288                 break;
00289         }
00290         
00291         return 0;
00292 }
00293 
00294 static void set_ebone_glColor(const unsigned int boneflag)
00295 {
00296         if (boneflag & BONE_DRAW_ACTIVE && boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
00297         else if (boneflag & BONE_DRAW_ACTIVE) UI_ThemeColorBlend(TH_WIRE, TH_EDGE_SELECT, 0.15f); /* unselected active */
00298         else if (boneflag & BONE_SELECTED) UI_ThemeColorShade(TH_EDGE_SELECT, -20);
00299         else UI_ThemeColor(TH_WIRE);
00300 }
00301 
00302 /* *************** Armature drawing, helper calls for parts ******************* */
00303 
00304 /* half the cube, in Y */
00305 static float cube[8][3] = {
00306 {-1.0,  0.0, -1.0},
00307 {-1.0,  0.0,  1.0},
00308 {-1.0,  1.0,  1.0},
00309 {-1.0,  1.0, -1.0},
00310 { 1.0,  0.0, -1.0},
00311 { 1.0,  0.0,  1.0},
00312 { 1.0,  1.0,  1.0},
00313 { 1.0,  1.0, -1.0},
00314 };
00315 
00316 static void drawsolidcube_size(float xsize, float ysize, float zsize)
00317 {
00318         static GLuint displist=0;
00319         float n[3];
00320         
00321         glScalef(xsize, ysize, zsize);
00322         
00323         n[0]=0; n[1]=0; n[2]=0;
00324 
00325         if(displist==0) {
00326                 displist= glGenLists(1);
00327                 glNewList(displist, GL_COMPILE);
00328 
00329                 glBegin(GL_QUADS);
00330                 n[0]= -1.0;
00331                 glNormal3fv(n); 
00332                 glVertex3fv(cube[0]); glVertex3fv(cube[1]); glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00333                 n[0]=0;
00334                 n[1]= -1.0;
00335                 glNormal3fv(n); 
00336                 glVertex3fv(cube[0]); glVertex3fv(cube[4]); glVertex3fv(cube[5]); glVertex3fv(cube[1]);
00337                 n[1]=0;
00338                 n[0]= 1.0;
00339                 glNormal3fv(n); 
00340                 glVertex3fv(cube[4]); glVertex3fv(cube[7]); glVertex3fv(cube[6]); glVertex3fv(cube[5]);
00341                 n[0]=0;
00342                 n[1]= 1.0;
00343                 glNormal3fv(n); 
00344                 glVertex3fv(cube[7]); glVertex3fv(cube[3]); glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00345                 n[1]=0;
00346                 n[2]= 1.0;
00347                 glNormal3fv(n); 
00348                 glVertex3fv(cube[1]); glVertex3fv(cube[5]); glVertex3fv(cube[6]); glVertex3fv(cube[2]);
00349                 n[2]=0;
00350                 n[2]= -1.0;
00351                 glNormal3fv(n); 
00352                 glVertex3fv(cube[7]); glVertex3fv(cube[4]); glVertex3fv(cube[0]); glVertex3fv(cube[3]);
00353                 glEnd();
00354 
00355                 glEndList();
00356         }
00357 
00358         glCallList(displist);
00359 }
00360 
00361 static void drawcube_size(float xsize, float ysize, float zsize)
00362 {
00363         static GLuint displist=0;
00364         
00365         if(displist == 0) {
00366                 displist= glGenLists(1);
00367                 glNewList(displist, GL_COMPILE);
00368                 
00369                 glBegin(GL_LINE_STRIP);
00370                 glVertex3fv(cube[0]); glVertex3fv(cube[1]);glVertex3fv(cube[2]); glVertex3fv(cube[3]);
00371                 glVertex3fv(cube[0]); glVertex3fv(cube[4]);glVertex3fv(cube[5]); glVertex3fv(cube[6]);
00372                 glVertex3fv(cube[7]); glVertex3fv(cube[4]);
00373                 glEnd();
00374                 
00375                 glBegin(GL_LINES);
00376                 glVertex3fv(cube[1]); glVertex3fv(cube[5]);
00377                 glVertex3fv(cube[2]); glVertex3fv(cube[6]);
00378                 glVertex3fv(cube[3]); glVertex3fv(cube[7]);
00379                 glEnd();
00380                 
00381                 glEndList();
00382         }
00383 
00384         glScalef(xsize, ysize, zsize);
00385         glCallList(displist);
00386         
00387 }
00388 
00389 
00390 static void draw_bonevert(void)
00391 {
00392         static GLuint displist=0;
00393         
00394         if (displist == 0) {
00395                 GLUquadricObj   *qobj;
00396                 
00397                 displist= glGenLists(1);
00398                 glNewList(displist, GL_COMPILE);
00399                         
00400                 glPushMatrix();
00401                 
00402                 qobj    = gluNewQuadric(); 
00403                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
00404                 gluDisk(qobj, 0.0,  0.05, 16, 1);
00405                 
00406                 glRotatef(90, 0, 1, 0);
00407                 gluDisk(qobj, 0.0,  0.05, 16, 1);
00408                 
00409                 glRotatef(90, 1, 0, 0);
00410                 gluDisk(qobj, 0.0,  0.05, 16, 1);
00411                 
00412                 gluDeleteQuadric(qobj);  
00413                 
00414                 glPopMatrix();
00415                 glEndList();
00416         }
00417 
00418         glCallList(displist);
00419 }
00420 
00421 static void draw_bonevert_solid(void)
00422 {
00423         static GLuint displist=0;
00424         
00425         if (displist == 0) {
00426                 GLUquadricObj   *qobj;
00427                 
00428                 displist= glGenLists(1);
00429                 glNewList(displist, GL_COMPILE);
00430                 
00431                 qobj    = gluNewQuadric();
00432                 gluQuadricDrawStyle(qobj, GLU_FILL); 
00433                 glShadeModel(GL_SMOOTH);
00434                 gluSphere(qobj, 0.05, 8, 5);
00435                 glShadeModel(GL_FLAT);
00436                 gluDeleteQuadric(qobj);  
00437                 
00438                 glEndList();
00439         }
00440 
00441         glCallList(displist);
00442 }
00443 
00444 static void draw_bone_octahedral(void)
00445 {
00446         static GLuint displist=0;
00447         
00448         if (displist == 0) {
00449                 float vec[6][3];        
00450                 
00451                 displist= glGenLists(1);
00452                 glNewList(displist, GL_COMPILE);
00453                 
00454                 vec[0][0]= vec[0][1]= vec[0][2]= 0.0f;
00455                 vec[5][0]= vec[5][2]= 0.0f; vec[5][1]= 1.0f;
00456                 
00457                 vec[1][0]= 0.1f; vec[1][2]= 0.1f; vec[1][1]= 0.1f;
00458                 vec[2][0]= 0.1f; vec[2][2]= -0.1f; vec[2][1]= 0.1f;
00459                 vec[3][0]= -0.1f; vec[3][2]= -0.1f; vec[3][1]= 0.1f;
00460                 vec[4][0]= -0.1f; vec[4][2]= 0.1f; vec[4][1]= 0.1f;
00461                 
00462                 /*      Section 1, sides */
00463                 glBegin(GL_LINE_LOOP);
00464                 glVertex3fv(vec[0]);
00465                 glVertex3fv(vec[1]);
00466                 glVertex3fv(vec[5]);
00467                 glVertex3fv(vec[3]);
00468                 glVertex3fv(vec[0]);
00469                 glVertex3fv(vec[4]);
00470                 glVertex3fv(vec[5]);
00471                 glVertex3fv(vec[2]);
00472                 glEnd();
00473                 
00474                 /*      Section 1, square */
00475                 glBegin(GL_LINE_LOOP);
00476                 glVertex3fv(vec[1]);
00477                 glVertex3fv(vec[2]);
00478                 glVertex3fv(vec[3]);
00479                 glVertex3fv(vec[4]);
00480                 glEnd();
00481                 
00482                 glEndList();
00483         }
00484 
00485         glCallList(displist);
00486 }       
00487 
00488 static void draw_bone_solid_octahedral(void)
00489 {
00490         static GLuint displist=0;
00491         
00492         if (displist == 0) {
00493                 float vec[6][3], nor[3];        
00494                 
00495                 displist= glGenLists(1);
00496                 glNewList(displist, GL_COMPILE);
00497                 
00498                 vec[0][0]= vec[0][1]= vec[0][2]= 0.0f;
00499                 vec[5][0]= vec[5][2]= 0.0f; vec[5][1]= 1.0f;
00500                 
00501                 vec[1][0]= 0.1f; vec[1][2]= 0.1f; vec[1][1]= 0.1f;
00502                 vec[2][0]= 0.1f; vec[2][2]= -0.1f; vec[2][1]= 0.1f;
00503                 vec[3][0]= -0.1f; vec[3][2]= -0.1f; vec[3][1]= 0.1f;
00504                 vec[4][0]= -0.1f; vec[4][2]= 0.1f; vec[4][1]= 0.1f;
00505                 
00506                 
00507                 glBegin(GL_TRIANGLES);
00508                 /* bottom */
00509                 normal_tri_v3( nor,vec[2], vec[1], vec[0]);
00510                 glNormal3fv(nor);
00511                 glVertex3fv(vec[2]); glVertex3fv(vec[1]); glVertex3fv(vec[0]);
00512                 
00513                 normal_tri_v3( nor,vec[3], vec[2], vec[0]);
00514                 glNormal3fv(nor);
00515                 glVertex3fv(vec[3]); glVertex3fv(vec[2]); glVertex3fv(vec[0]);
00516                 
00517                 normal_tri_v3( nor,vec[4], vec[3], vec[0]);
00518                 glNormal3fv(nor);
00519                 glVertex3fv(vec[4]); glVertex3fv(vec[3]); glVertex3fv(vec[0]);
00520 
00521                 normal_tri_v3( nor,vec[1], vec[4], vec[0]);
00522                 glNormal3fv(nor);
00523                 glVertex3fv(vec[1]); glVertex3fv(vec[4]); glVertex3fv(vec[0]);
00524 
00525                 /* top */
00526                 normal_tri_v3( nor,vec[5], vec[1], vec[2]);
00527                 glNormal3fv(nor);
00528                 glVertex3fv(vec[5]); glVertex3fv(vec[1]); glVertex3fv(vec[2]);
00529                 
00530                 normal_tri_v3( nor,vec[5], vec[2], vec[3]);
00531                 glNormal3fv(nor);
00532                 glVertex3fv(vec[5]); glVertex3fv(vec[2]); glVertex3fv(vec[3]);
00533                 
00534                 normal_tri_v3( nor,vec[5], vec[3], vec[4]);
00535                 glNormal3fv(nor);
00536                 glVertex3fv(vec[5]); glVertex3fv(vec[3]); glVertex3fv(vec[4]);
00537                 
00538                 normal_tri_v3( nor,vec[5], vec[4], vec[1]);
00539                 glNormal3fv(nor);
00540                 glVertex3fv(vec[5]); glVertex3fv(vec[4]); glVertex3fv(vec[1]);
00541                 
00542                 glEnd();
00543                 
00544                 glEndList();
00545         }
00546 
00547         glCallList(displist);
00548 }       
00549 
00550 /* *************** Armature drawing, bones ******************* */
00551 
00552 
00553 static void draw_bone_points(int dt, int armflag, unsigned int boneflag, int id)
00554 {
00555         /*      Draw root point if we are not connected */
00556         if ((boneflag & BONE_CONNECTED)==0) {
00557                 if (id != -1)
00558                         glLoadName(id | BONESEL_ROOT);
00559                 
00560                 if(dt <= OB_WIRE) {
00561                         if (armflag & ARM_EDITMODE) {
00562                                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00563                                 else UI_ThemeColor(TH_VERTEX);
00564                         }
00565                 }
00566                 else {
00567                         if (armflag & ARM_POSEMODE) 
00568                                 set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
00569                         else
00570                                 UI_ThemeColor(TH_BONE_SOLID);
00571                 }
00572                 
00573                 if (dt > OB_WIRE) 
00574                         draw_bonevert_solid();
00575                 else 
00576                         draw_bonevert();
00577         }
00578         
00579         /*      Draw tip point */
00580         if (id != -1)
00581                 glLoadName(id | BONESEL_TIP);
00582         
00583         if (dt <= OB_WIRE) {
00584                 if (armflag & ARM_EDITMODE) {
00585                         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00586                         else UI_ThemeColor(TH_VERTEX);
00587                 }
00588         }
00589         else {
00590                 if (armflag & ARM_POSEMODE) 
00591                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, 0);
00592                 else
00593                         UI_ThemeColor(TH_BONE_SOLID);
00594         }
00595         
00596         glTranslatef(0.0f, 1.0f, 0.0f);
00597         if (dt > OB_WIRE) 
00598                 draw_bonevert_solid();
00599         else 
00600                 draw_bonevert();
00601         glTranslatef(0.0f, -1.0f, 0.0f);
00602         
00603 }
00604 
00605 /* 16 values of sin function (still same result!) */
00606 static float si[16] = {
00607         0.00000000f,
00608         0.20129852f, 0.39435585f,
00609         0.57126821f, 0.72479278f,
00610         0.84864425f, 0.93775213f,
00611         0.98846832f, 0.99871650f,
00612         0.96807711f, 0.89780453f,
00613         0.79077573f, 0.65137248f,
00614         0.48530196f, 0.29936312f,
00615         0.10116832f
00616 };
00617 /* 16 values of cos function (still same result!) */
00618 static float co[16] ={
00619         1.00000000f,
00620         0.97952994f, 0.91895781f,
00621         0.82076344f, 0.68896691f,
00622         0.52896401f, 0.34730525f,
00623         0.15142777f, -0.05064916f,
00624         -0.25065253f, -0.44039415f,
00625         -0.61210598f, -0.75875812f,
00626         -0.87434661f, -0.95413925f,
00627         -0.99486932f
00628 };
00629 
00630 
00631 
00632 /* smat, imat = mat & imat to draw screenaligned */
00633 static void draw_sphere_bone_dist(float smat[][4], float imat[][4], bPoseChannel *pchan, EditBone *ebone)
00634 {
00635         float head, tail, dist /*, length*/;
00636         float *headvec, *tailvec, dirvec[3];
00637         
00638         /* figure out the sizes of spheres */
00639         if (ebone) {
00640                 /* this routine doesn't call get_matrix_editbone() that calculates it */
00641                 ebone->length = len_v3v3(ebone->head, ebone->tail);
00642 
00643                 /*length= ebone->length;*/ /*UNUSED*/
00644                 tail= ebone->rad_tail;
00645                 dist= ebone->dist;
00646                 if (ebone->parent && (ebone->flag & BONE_CONNECTED))
00647                         head= ebone->parent->rad_tail;
00648                 else
00649                         head= ebone->rad_head;
00650                 headvec= ebone->head;
00651                 tailvec= ebone->tail;
00652         }
00653         else {
00654                 /*length= pchan->bone->length;*/ /*UNUSED*/
00655                 tail= pchan->bone->rad_tail;
00656                 dist= pchan->bone->dist;
00657                 if (pchan->parent && (pchan->bone->flag & BONE_CONNECTED))
00658                         head= pchan->parent->bone->rad_tail;
00659                 else
00660                         head= pchan->bone->rad_head;
00661                 headvec= pchan->pose_head;
00662                 tailvec= pchan->pose_tail;
00663         }
00664         
00665         /* ***** draw it ***** */
00666         
00667         /* move vector to viewspace */
00668         sub_v3_v3v3(dirvec, tailvec, headvec);
00669         mul_mat3_m4_v3(smat, dirvec);
00670         /* clear zcomp */
00671         dirvec[2]= 0.0f;
00672 
00673         if(head != tail) {
00674         /* correcyion when viewing along the bones axis
00675          * it pops in and out but better then artifacts, [#23841] */
00676                 float view_dist= len_v2(dirvec);
00677 
00678                 if(head - view_dist > tail) {
00679                         tailvec= headvec;
00680                         tail = head;
00681                         zero_v3(dirvec);
00682                         dirvec[0]= 0.00001; // XXX. weak but ok
00683                 }
00684                 else if(tail - view_dist > head) {
00685                         headvec= tailvec;
00686                         head = tail;
00687                         zero_v3(dirvec);
00688                         dirvec[0]= 0.00001; // XXX. weak but ok
00689                 }
00690         }
00691 
00692         /* move vector back */
00693         mul_mat3_m4_v3(imat, dirvec);
00694         
00695         if (0.0f != normalize_v3(dirvec)) {
00696                 float norvec[3], vec1[3], vec2[3], vec[3];
00697                 int a;
00698                 
00699                 //mul_v3_fl(dirvec, head);
00700                 cross_v3_v3v3(norvec, dirvec, imat[2]);
00701                 
00702                 glBegin(GL_QUAD_STRIP);
00703                 
00704                 for (a=0; a<16; a++) {
00705                         vec[0]= - *(si+a) * dirvec[0] + *(co+a) * norvec[0];
00706                         vec[1]= - *(si+a) * dirvec[1] + *(co+a) * norvec[1];
00707                         vec[2]= - *(si+a) * dirvec[2] + *(co+a) * norvec[2];
00708                         
00709                         vec1[0]= headvec[0] + head*vec[0];
00710                         vec1[1]= headvec[1] + head*vec[1];
00711                         vec1[2]= headvec[2] + head*vec[2];
00712                         vec2[0]= headvec[0] + (head+dist)*vec[0];
00713                         vec2[1]= headvec[1] + (head+dist)*vec[1];
00714                         vec2[2]= headvec[2] + (head+dist)*vec[2];
00715                         
00716                         glColor4ub(255, 255, 255, 50);
00717                         glVertex3fv(vec1);
00718                         //glColor4ub(255, 255, 255, 0);
00719                         glVertex3fv(vec2);
00720                 }
00721                 
00722                 for (a=15; a>=0; a--) {
00723                         vec[0]= *(si+a) * dirvec[0] + *(co+a) * norvec[0];
00724                         vec[1]= *(si+a) * dirvec[1] + *(co+a) * norvec[1];
00725                         vec[2]= *(si+a) * dirvec[2] + *(co+a) * norvec[2];
00726                         
00727                         vec1[0]= tailvec[0] + tail*vec[0];
00728                         vec1[1]= tailvec[1] + tail*vec[1];
00729                         vec1[2]= tailvec[2] + tail*vec[2];
00730                         vec2[0]= tailvec[0] + (tail+dist)*vec[0];
00731                         vec2[1]= tailvec[1] + (tail+dist)*vec[1];
00732                         vec2[2]= tailvec[2] + (tail+dist)*vec[2];
00733                         
00734                         //glColor4ub(255, 255, 255, 50);
00735                         glVertex3fv(vec1);
00736                         //glColor4ub(255, 255, 255, 0);
00737                         glVertex3fv(vec2);
00738                 }
00739                 /* make it cyclic... */
00740                 
00741                 vec[0]= - *(si) * dirvec[0] + *(co) * norvec[0];
00742                 vec[1]= - *(si) * dirvec[1] + *(co) * norvec[1];
00743                 vec[2]= - *(si) * dirvec[2] + *(co) * norvec[2];
00744                 
00745                 vec1[0]= headvec[0] + head*vec[0];
00746                 vec1[1]= headvec[1] + head*vec[1];
00747                 vec1[2]= headvec[2] + head*vec[2];
00748                 vec2[0]= headvec[0] + (head+dist)*vec[0];
00749                 vec2[1]= headvec[1] + (head+dist)*vec[1];
00750                 vec2[2]= headvec[2] + (head+dist)*vec[2];
00751                 
00752                 //glColor4ub(255, 255, 255, 50);
00753                 glVertex3fv(vec1);
00754                 //glColor4ub(255, 255, 255, 0);
00755                 glVertex3fv(vec2);
00756                 
00757                 glEnd();
00758         }
00759 }
00760 
00761 
00762 /* smat, imat = mat & imat to draw screenaligned */
00763 static void draw_sphere_bone_wire(float smat[][4], float imat[][4], int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
00764 {
00765         float head, tail /*, length*/;
00766         float *headvec, *tailvec, dirvec[3];
00767         
00768         /* figure out the sizes of spheres */
00769         if (ebone) {
00770                 /* this routine doesn't call get_matrix_editbone() that calculates it */
00771                 ebone->length = len_v3v3(ebone->head, ebone->tail);
00772                 
00773                 /*length= ebone->length;*/ /*UNUSED*/
00774                 tail= ebone->rad_tail;
00775                 if (ebone->parent && (boneflag & BONE_CONNECTED))
00776                         head= ebone->parent->rad_tail;
00777                 else
00778                         head= ebone->rad_head;
00779                 headvec= ebone->head;
00780                 tailvec= ebone->tail;
00781         }
00782         else {
00783                 /*length= pchan->bone->length;*/ /*UNUSED*/
00784                 tail= pchan->bone->rad_tail;
00785                 if ((pchan->parent) && (boneflag & BONE_CONNECTED))
00786                         head= pchan->parent->bone->rad_tail;
00787                 else
00788                         head= pchan->bone->rad_head;
00789                 headvec= pchan->pose_head;
00790                 tailvec= pchan->pose_tail;
00791         }
00792         
00793         /* sphere root color */
00794         if (armflag & ARM_EDITMODE) {
00795                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00796                 else UI_ThemeColor(TH_VERTEX);
00797         }
00798         else if (armflag & ARM_POSEMODE)
00799                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
00800         
00801         /*      Draw root point if we are not connected */
00802         if ((boneflag & BONE_CONNECTED)==0) {
00803                 if (id != -1)
00804                         glLoadName(id | BONESEL_ROOT);
00805                 
00806                 drawcircball(GL_LINE_LOOP, headvec, head, imat);
00807         }
00808         
00809         /*      Draw tip point */
00810         if (armflag & ARM_EDITMODE) {
00811                 if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00812                 else UI_ThemeColor(TH_VERTEX);
00813         }
00814         
00815         if (id != -1)
00816                 glLoadName(id | BONESEL_TIP);
00817         
00818         drawcircball(GL_LINE_LOOP, tailvec, tail, imat);
00819         
00820         /* base */
00821         if (armflag & ARM_EDITMODE) {
00822                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
00823                 else UI_ThemeColor(TH_WIRE);
00824         }
00825         
00826         sub_v3_v3v3(dirvec, tailvec, headvec);
00827         
00828         /* move vector to viewspace */
00829         mul_mat3_m4_v3(smat, dirvec);
00830         /* clear zcomp */
00831         dirvec[2]= 0.0f;
00832         /* move vector back */
00833         mul_mat3_m4_v3(imat, dirvec);
00834         
00835         if (0.0f != normalize_v3(dirvec)) {
00836                 float norvech[3], norvect[3], vec[3];
00837                 
00838                 VECCOPY(vec, dirvec);
00839                 
00840                 mul_v3_fl(dirvec, head);
00841                 cross_v3_v3v3(norvech, dirvec, imat[2]);
00842                 
00843                 mul_v3_fl(vec, tail);
00844                 cross_v3_v3v3(norvect, vec, imat[2]);
00845                 
00846                 if (id != -1)
00847                         glLoadName(id | BONESEL_BONE);
00848                 
00849                 glBegin(GL_LINES);
00850                 vec[0]= headvec[0] + norvech[0];
00851                 vec[1]= headvec[1] + norvech[1];
00852                 vec[2]= headvec[2] + norvech[2];
00853                 glVertex3fv(vec);
00854                 vec[0]= tailvec[0] + norvect[0];
00855                 vec[1]= tailvec[1] + norvect[1];
00856                 vec[2]= tailvec[2] + norvect[2];
00857                 glVertex3fv(vec);
00858                 vec[0]= headvec[0] - norvech[0];
00859                 vec[1]= headvec[1] - norvech[1];
00860                 vec[2]= headvec[2] - norvech[2];
00861                 glVertex3fv(vec);
00862                 vec[0]= tailvec[0] - norvect[0];
00863                 vec[1]= tailvec[1] - norvect[1];
00864                 vec[2]= tailvec[2] - norvect[2];
00865                 glVertex3fv(vec);
00866                 
00867                 glEnd();
00868         }
00869 }
00870 
00871 /* does wire only for outline selecting */
00872 static void draw_sphere_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
00873 {
00874         GLUquadricObj   *qobj;
00875         float head, tail, length;
00876         float fac1, fac2;
00877         
00878         glPushMatrix();
00879         qobj    = gluNewQuadric();
00880 
00881         /* figure out the sizes of spheres */
00882         if (ebone) {
00883                 length= ebone->length;
00884                 tail= ebone->rad_tail;
00885                 if (ebone->parent && (boneflag & BONE_CONNECTED))
00886                         head= ebone->parent->rad_tail;
00887                 else
00888                         head= ebone->rad_head;
00889         }
00890         else {
00891                 length= pchan->bone->length;
00892                 tail= pchan->bone->rad_tail;
00893                 if (pchan->parent && (boneflag & BONE_CONNECTED))
00894                         head= pchan->parent->bone->rad_tail;
00895                 else
00896                         head= pchan->bone->rad_head;
00897         }
00898         
00899         /* move to z-axis space */
00900         glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
00901 
00902         if (dt==OB_SOLID) {
00903                 /* set up solid drawing */
00904                 glEnable(GL_COLOR_MATERIAL);
00905                 glEnable(GL_LIGHTING);
00906                 
00907                 gluQuadricDrawStyle(qobj, GLU_FILL); 
00908                 glShadeModel(GL_SMOOTH);
00909         }
00910         else {
00911                 gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); 
00912         }
00913         
00914         /* sphere root color */
00915         if (armflag & ARM_EDITMODE) {
00916                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00917                 else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00918         }
00919         else if (armflag & ARM_POSEMODE)
00920                 set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_END, boneflag, constflag);
00921         else if (dt==OB_SOLID) 
00922                 UI_ThemeColorShade(TH_BONE_SOLID, -30);
00923         
00924         /*      Draw root point if we are not connected */
00925         if ((boneflag & BONE_CONNECTED)==0) {
00926                 if (id != -1)
00927                         glLoadName(id | BONESEL_ROOT);
00928                 gluSphere(qobj, head, 16, 10);
00929         }
00930         
00931         /*      Draw tip point */
00932         if (armflag & ARM_EDITMODE) {
00933                 if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
00934                 else UI_ThemeColorShade(TH_BONE_SOLID, -30);
00935         }
00936 
00937         if (id != -1)
00938                 glLoadName(id | BONESEL_TIP);
00939         
00940         glTranslatef(0.0f, 0.0f, length);
00941         gluSphere(qobj, tail, 16, 10);
00942         glTranslatef(0.0f, 0.0f, -length);
00943         
00944         /* base */
00945         if (armflag & ARM_EDITMODE) {
00946                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_SELECT);
00947                 else UI_ThemeColor(TH_BONE_SOLID);
00948         }
00949         else if (armflag & ARM_POSEMODE)
00950                 set_pchan_glColor(PCHAN_COLOR_SPHEREBONE_BASE, boneflag, constflag);
00951         else if (dt == OB_SOLID)
00952                 UI_ThemeColor(TH_BONE_SOLID);
00953         
00954         fac1= (length-head)/length;
00955         fac2= (length-tail)/length;
00956         
00957         if (length > (head+tail)) {
00958                 if (id != -1)
00959                         glLoadName (id | BONESEL_BONE);
00960                 
00961                 glEnable(GL_POLYGON_OFFSET_FILL);
00962                 glPolygonOffset(-1.0f, -1.0f);
00963                 
00964                 glTranslatef(0.0f, 0.0f, head);
00965                 gluCylinder(qobj, fac1*head + (1.0f-fac1)*tail, fac2*tail + (1.0f-fac2)*head, length-head-tail, 16, 1);
00966                 glTranslatef(0.0f, 0.0f, -head);
00967                 
00968                 glDisable(GL_POLYGON_OFFSET_FILL);
00969                 
00970                 /* draw sphere on extrema */
00971                 glTranslatef(0.0f, 0.0f, length-tail);
00972                 gluSphere(qobj, fac2*tail + (1.0f-fac2)*head, 16, 10);
00973                 glTranslatef(0.0f, 0.0f, -length+tail);
00974                 
00975                 glTranslatef(0.0f, 0.0f, head);
00976                 gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
00977         }
00978         else {          
00979                 /* 1 sphere in center */
00980                 glTranslatef(0.0f, 0.0f, (head + length-tail)/2.0f);
00981                 gluSphere(qobj, fac1*head + (1.0f-fac1)*tail, 16, 10);
00982         }
00983         
00984         /* restore */
00985         if (dt==OB_SOLID) {
00986                 glShadeModel(GL_FLAT);
00987                 glDisable(GL_LIGHTING);
00988                 glDisable(GL_COLOR_MATERIAL);
00989         }
00990         
00991         glPopMatrix();
00992         gluDeleteQuadric(qobj);  
00993 }
00994 
00995 static GLubyte bm_dot6[]= {0x0, 0x18, 0x3C, 0x7E, 0x7E, 0x3C, 0x18, 0x0}; 
00996 static GLubyte bm_dot8[]= {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}; 
00997 
00998 static GLubyte bm_dot5[]= {0x0, 0x0, 0x10, 0x38, 0x7c, 0x38, 0x10, 0x0}; 
00999 static GLubyte bm_dot7[]= {0x0, 0x38, 0x7C, 0xFE, 0xFE, 0xFE, 0x7C, 0x38}; 
01000 
01001 
01002 static void draw_line_bone(int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
01003 {
01004         float length;
01005         
01006         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01007         
01008         if (pchan) 
01009                 length= pchan->bone->length;
01010         else 
01011                 length= ebone->length;
01012         
01013         glPushMatrix();
01014         glScalef(length, length, length);
01015         
01016         /* this chunk not in object mode */
01017         if (armflag & (ARM_EDITMODE|ARM_POSEMODE)) {
01018                 glLineWidth(4.0f);
01019                 if (armflag & ARM_POSEMODE)
01020                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01021                 else if (armflag & ARM_EDITMODE) {
01022                         UI_ThemeColor(TH_WIRE);
01023                 }
01024                 
01025                 /*      Draw root point if we are not connected */
01026                 if ((boneflag & BONE_CONNECTED)==0) {
01027                         if (G.f & G_PICKSEL) {  // no bitmap in selection mode, crashes 3d cards...
01028                                 glLoadName (id | BONESEL_ROOT);
01029                                 glBegin(GL_POINTS);
01030                                 glVertex3f(0.0f, 0.0f, 0.0f);
01031                                 glEnd();
01032                         }
01033                         else {
01034                                 glRasterPos3f(0.0f, 0.0f, 0.0f);
01035                                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot8);
01036                         }
01037                 }
01038                 
01039                 if (id != -1)
01040                         glLoadName((GLuint) id|BONESEL_BONE);
01041                 
01042                 glBegin(GL_LINES);
01043                 glVertex3f(0.0f, 0.0f, 0.0f);
01044                 glVertex3f(0.0f, 1.0f, 0.0f);
01045                 glEnd();
01046                 
01047                 /* tip */
01048                 if (G.f & G_PICKSEL) {  
01049                         /* no bitmap in selection mode, crashes 3d cards... */
01050                         glLoadName(id | BONESEL_TIP);
01051                         glBegin(GL_POINTS);
01052                         glVertex3f(0.0f, 1.0f, 0.0f);
01053                         glEnd();
01054                 }
01055                 else {
01056                         glRasterPos3f(0.0f, 1.0f, 0.0f);
01057                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot7);
01058                 }
01059                 
01060                 /* further we send no names */
01061                 if (id != -1)
01062                         glLoadName(id & 0xFFFF);        /* object tag, for bordersel optim */
01063                 
01064                 if (armflag & ARM_POSEMODE)
01065                         set_pchan_glColor(PCHAN_COLOR_LINEBONE, boneflag, constflag);
01066         }
01067         
01068         glLineWidth(2.0);
01069         
01070         /*Draw root point if we are not connected */
01071         if ((boneflag & BONE_CONNECTED)==0) {
01072                 if ((G.f & G_PICKSEL)==0) {     
01073                         /* no bitmap in selection mode, crashes 3d cards... */
01074                         if (armflag & ARM_EDITMODE) {
01075                                 if (boneflag & BONE_ROOTSEL) UI_ThemeColor(TH_VERTEX_SELECT);
01076                                 else UI_ThemeColor(TH_VERTEX);
01077                         }
01078                         glRasterPos3f(0.0f, 0.0f, 0.0f);
01079                         glBitmap(8, 8, 4, 4, 0, 0, bm_dot6);
01080                 }
01081         }
01082         
01083         if (armflag & ARM_EDITMODE) {
01084                 if (boneflag & BONE_SELECTED) UI_ThemeColor(TH_EDGE_SELECT);
01085                 else UI_ThemeColorShade(TH_BACK, -30);
01086         }
01087         glBegin(GL_LINES);
01088         glVertex3f(0.0f, 0.0f, 0.0f);
01089         glVertex3f(0.0f, 1.0f, 0.0f);
01090         glEnd();
01091         
01092         /* tip */
01093         if ((G.f & G_PICKSEL)==0) {     
01094                 /* no bitmap in selection mode, crashes 3d cards... */
01095                 if (armflag & ARM_EDITMODE) {
01096                         if (boneflag & BONE_TIPSEL) UI_ThemeColor(TH_VERTEX_SELECT);
01097                         else UI_ThemeColor(TH_VERTEX);
01098                 }
01099                 glRasterPos3f(0.0f, 1.0f, 0.0f);
01100                 glBitmap(8, 8, 4, 4, 0, 0, bm_dot5);
01101         }
01102         
01103         glLineWidth(1.0);
01104         
01105         glPopMatrix();
01106 }
01107 
01108 static void draw_b_bone_boxes(int dt, bPoseChannel *pchan, float xwidth, float length, float zwidth)
01109 {
01110         int segments= 0;
01111         
01112         if (pchan) 
01113                 segments= pchan->bone->segments;
01114         
01115         if ((segments > 1) && (pchan)) {
01116                 float dlen= length/(float)segments;
01117                 Mat4 *bbone= b_bone_spline_setup(pchan, 0);
01118                 int a;
01119                 
01120                 for (a=0; a<segments; a++, bbone++) {
01121                         glPushMatrix();
01122                         glMultMatrixf(bbone->mat);
01123                         if (dt==OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth);
01124                         else drawcube_size(xwidth, dlen, zwidth);
01125                         glPopMatrix();
01126                 }
01127         }
01128         else {
01129                 glPushMatrix();
01130                 if (dt==OB_SOLID) drawsolidcube_size(xwidth, length, zwidth);
01131                 else drawcube_size(xwidth, length, zwidth);
01132                 glPopMatrix();
01133         }
01134 }
01135 
01136 static void draw_b_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone)
01137 {
01138         float xwidth, length, zwidth;
01139         
01140         if (pchan) {
01141                 xwidth= pchan->bone->xwidth;
01142                 length= pchan->bone->length;
01143                 zwidth= pchan->bone->zwidth;
01144         }
01145         else {
01146                 xwidth= ebone->xwidth;
01147                 length= ebone->length;
01148                 zwidth= ebone->zwidth;
01149         }
01150         
01151         /* draw points only if... */
01152         if (armflag & ARM_EDITMODE) {
01153                 /* move to unitspace */
01154                 glPushMatrix();
01155                 glScalef(length, length, length);
01156                 draw_bone_points(dt, armflag, boneflag, id);
01157                 glPopMatrix();
01158                 length*= 0.95f; // make vertices visible
01159         }
01160 
01161         /* colors for modes */
01162         if (armflag & ARM_POSEMODE) {
01163                 if (dt <= OB_WIRE)
01164                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01165                 else 
01166                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01167         }
01168         else if (armflag & ARM_EDITMODE) {
01169                 if (dt==OB_WIRE) {
01170                         set_ebone_glColor(boneflag);
01171                 }
01172                 else 
01173                         UI_ThemeColor(TH_BONE_SOLID);
01174         }
01175         
01176         if (id != -1) {
01177                 glLoadName ((GLuint) id|BONESEL_BONE);
01178         }
01179         
01180         /* set up solid drawing */
01181         if (dt > OB_WIRE) {
01182                 glEnable(GL_COLOR_MATERIAL);
01183                 glEnable(GL_LIGHTING);
01184                 
01185                 if (armflag & ARM_POSEMODE)
01186                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01187                 else
01188                         UI_ThemeColor(TH_BONE_SOLID);
01189                 
01190                 draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
01191                 
01192                 /* disable solid drawing */
01193                 glDisable(GL_COLOR_MATERIAL);
01194                 glDisable(GL_LIGHTING);
01195         }
01196         else {  
01197                 /* wire */
01198                 if (armflag & ARM_POSEMODE) {
01199                         if (constflag) {
01200                                 /* set constraint colors */
01201                                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {
01202                                         glEnable(GL_BLEND);
01203                                         
01204                                         draw_b_bone_boxes(OB_SOLID, pchan, xwidth, length, zwidth);
01205                                         
01206                                         glDisable(GL_BLEND);
01207                                 }
01208                                 
01209                                 /* restore colors */
01210                                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01211                         }
01212                 }               
01213                 
01214                 draw_b_bone_boxes(OB_WIRE, pchan, xwidth, length, zwidth);              
01215         }
01216 }
01217 
01218 static void draw_bone(int dt, int armflag, int boneflag, int constflag, unsigned int id, float length)
01219 {
01220         
01221         /*      Draw a 3d octahedral bone, we use normalized space based on length,
01222                 for glDisplayLists */
01223         
01224         glScalef(length, length, length);
01225 
01226         /* set up solid drawing */
01227         if (dt > OB_WIRE) {
01228                 glEnable(GL_COLOR_MATERIAL);
01229                 glEnable(GL_LIGHTING);
01230                 UI_ThemeColor(TH_BONE_SOLID);
01231         }
01232         
01233         /* colors for posemode */
01234         if (armflag & ARM_POSEMODE) {
01235                 if (dt <= OB_WIRE)
01236                         set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01237                 else 
01238                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01239         }
01240         
01241         
01242         draw_bone_points(dt, armflag, boneflag, id);
01243         
01244         /* now draw the bone itself */
01245         if (id != -1) {
01246                 glLoadName((GLuint) id|BONESEL_BONE);
01247         }
01248         
01249         /* wire? */
01250         if (dt <= OB_WIRE) {
01251                 /* colors */
01252                 if (armflag & ARM_EDITMODE) {
01253                         set_ebone_glColor(boneflag);
01254                 }
01255                 else if (armflag & ARM_POSEMODE) {
01256                         if (constflag) {
01257                                 /* draw constraint colors */
01258                                 if (set_pchan_glColor(PCHAN_COLOR_CONSTS, boneflag, constflag)) {       
01259                                         glEnable(GL_BLEND);
01260                                         
01261                                         draw_bone_solid_octahedral();
01262                                         
01263                                         glDisable(GL_BLEND);
01264                                 }
01265                                 
01266                                 /* restore colors */
01267                                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, constflag);
01268                         }
01269                 }               
01270                 draw_bone_octahedral();
01271         }
01272         else {  
01273                 /* solid */
01274                 if (armflag & ARM_POSEMODE)
01275                         set_pchan_glColor(PCHAN_COLOR_SOLID, boneflag, constflag);
01276                 else
01277                         UI_ThemeColor(TH_BONE_SOLID);
01278                 draw_bone_solid_octahedral();
01279         }
01280 
01281         /* disable solid drawing */
01282         if (dt > OB_WIRE) {
01283                 glDisable(GL_COLOR_MATERIAL);
01284                 glDisable(GL_LIGHTING);
01285         }
01286 }
01287 
01288 static void draw_custom_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, int dt, int armflag, int boneflag, unsigned int id, float length)
01289 {
01290         if(ob==NULL) return;
01291         
01292         glScalef(length, length, length);
01293         
01294         /* colors for posemode */
01295         if (armflag & ARM_POSEMODE) {
01296                 set_pchan_glColor(PCHAN_COLOR_NORMAL, boneflag, 0);
01297         }
01298         
01299         if (id != -1) {
01300                 glLoadName((GLuint) id|BONESEL_BONE);
01301         }
01302         
01303         draw_object_instance(scene, v3d, rv3d, ob, dt, armflag & ARM_POSEMODE);
01304 }
01305 
01306 
01307 static void pchan_draw_IK_root_lines(bPoseChannel *pchan, short only_temp)
01308 {
01309         bConstraint *con;
01310         bPoseChannel *parchan;
01311         
01312         for (con= pchan->constraints.first; con; con= con->next) {
01313                 if (con->enforce == 0.0f)
01314                         continue;
01315                 
01316                 switch (con->type) {
01317                         case CONSTRAINT_TYPE_KINEMATIC:
01318                         {
01319                                 bKinematicConstraint *data = (bKinematicConstraint*)con->data;
01320                                 int segcount= 0;
01321                                 
01322                                 /* if only_temp, only draw if it is a temporary ik-chain */
01323                                 if ((only_temp) && !(data->flag & CONSTRAINT_IK_TEMP))
01324                                         continue;
01325                                 
01326                                 setlinestyle(3);
01327                                 glBegin(GL_LINES);
01328                                 
01329                                 /* exclude tip from chain? */
01330                                 if ((data->flag & CONSTRAINT_IK_TIP)==0)
01331                                         parchan= pchan->parent;
01332                                 else
01333                                         parchan= pchan;
01334                                 
01335                                 glVertex3fv(parchan->pose_tail);
01336                                 
01337                                 /* Find the chain's root */
01338                                 while (parchan->parent) {
01339                                         segcount++;
01340                                         if(segcount==data->rootbone || segcount>255) break; // 255 is weak
01341                                         parchan= parchan->parent;
01342                                 }
01343                                 if (parchan)
01344                                         glVertex3fv(parchan->pose_head);
01345                                 
01346                                 glEnd();
01347                                 setlinestyle(0);
01348                         }
01349                                 break;
01350                         case CONSTRAINT_TYPE_SPLINEIK: 
01351                         {
01352                                 bSplineIKConstraint *data = (bSplineIKConstraint*)con->data;
01353                                 int segcount= 0;
01354                                 
01355                                 setlinestyle(3);
01356                                 glBegin(GL_LINES);
01357                                 
01358                                 parchan= pchan;
01359                                 glVertex3fv(parchan->pose_tail);
01360                                 
01361                                 /* Find the chain's root */
01362                                 while (parchan->parent) {
01363                                         segcount++;
01364                                         // FIXME: revise the breaking conditions
01365                                         if(segcount==data->chainlen || segcount>255) break; // 255 is weak
01366                                         parchan= parchan->parent;
01367                                 }
01368                                 if (parchan) // XXX revise the breaking conditions to only stop at the tail?
01369                                         glVertex3fv(parchan->pose_head);
01370                                 
01371                                 glEnd();
01372                                 setlinestyle(0);
01373                         }
01374                                 break;
01375                 }
01376         }
01377 }
01378 
01379 static void bgl_sphere_project(float ax, float az)
01380 {
01381         float dir[3], sine, q3;
01382 
01383         sine= 1.0f - ax*ax - az*az;
01384         q3= (sine < 0.0f)? 0.0f: (float)(2.0*sqrt(sine));
01385 
01386         dir[0]= -az*q3;
01387         dir[1]= 1.0f - 2.0f*sine;
01388         dir[2]= ax*q3;
01389 
01390         glVertex3fv(dir);
01391 }
01392 
01393 static void draw_dof_ellipse(float ax, float az)
01394 {
01395         static float staticSine[16] = {
01396                 0.0f, 0.104528463268f, 0.207911690818f, 0.309016994375f,
01397                 0.406736643076f, 0.5f, 0.587785252292f, 0.669130606359f,
01398                 0.743144825477f, 0.809016994375f, 0.866025403784f,
01399                 0.913545457643f, 0.951056516295f, 0.978147600734f,
01400                 0.994521895368f, 1.0f
01401         };
01402 
01403         int i, j, n=16;
01404         float x, z, px, pz;
01405 
01406         glEnable(GL_BLEND);
01407         glDepthMask(0);
01408 
01409         glColor4ub(70, 70, 70, 50);
01410 
01411         glBegin(GL_QUADS);
01412         pz= 0.0f;
01413         for(i=1; i<n; i++) {
01414                 z= staticSine[i];
01415                 
01416                 px= 0.0f;
01417                 for(j=1; j<n-i+1; j++) {
01418                         x = staticSine[j];
01419                         
01420                         if(j == n-i) {
01421                                 glEnd();
01422                                 glBegin(GL_TRIANGLES);
01423                                 bgl_sphere_project(ax*px, az*z);
01424                                 bgl_sphere_project(ax*px, az*pz);
01425                                 bgl_sphere_project(ax*x, az*pz);
01426                                 glEnd();
01427                                 glBegin(GL_QUADS);
01428                         }
01429                         else {
01430                                 bgl_sphere_project(ax*x, az*z);
01431                                 bgl_sphere_project(ax*x, az*pz);
01432                                 bgl_sphere_project(ax*px, az*pz);
01433                                 bgl_sphere_project(ax*px, az*z);
01434                         }
01435                         
01436                         px= x;
01437                 }
01438                 pz= z;
01439         }
01440         glEnd();
01441 
01442         glDisable(GL_BLEND);
01443         glDepthMask(1);
01444 
01445         glColor3ub(0, 0, 0);
01446 
01447         glBegin(GL_LINE_STRIP);
01448         for (i=0; i<n; i++)
01449                 bgl_sphere_project(staticSine[n-i-1]*ax, staticSine[i]*az);
01450         glEnd();
01451 }
01452 
01453 static void draw_pose_dofs(Object *ob)
01454 {
01455         bArmature *arm= ob->data;
01456         bPoseChannel *pchan;
01457         Bone *bone;
01458         
01459         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01460                 bone= pchan->bone;
01461                 
01462                 if ( (bone) && !(bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))) {
01463                         if (bone->flag & BONE_SELECTED) {
01464                                 if (bone->layer & arm->layer) {
01465                                         if (pchan->ikflag & (BONE_IK_XLIMIT|BONE_IK_ZLIMIT)) {
01466                                                 if (ED_pose_channel_in_IK_chain(ob, pchan)) {
01467                                                         float corner[4][3], posetrans[3], mat[4][4];
01468                                                         float phi=0.0f, theta=0.0f, scale;
01469                                                         int a, i;
01470                                                         
01471                                                         /* in parent-bone pose, but own restspace */
01472                                                         glPushMatrix();
01473                                                         
01474                                                         VECCOPY(posetrans, pchan->pose_mat[3]);
01475                                                         glTranslatef(posetrans[0], posetrans[1], posetrans[2]);
01476                                                         
01477                                                         if (pchan->parent) {
01478                                                                 copy_m4_m4(mat, pchan->parent->pose_mat);
01479                                                                 mat[3][0]= mat[3][1]= mat[3][2]= 0.0f;
01480                                                                 glMultMatrixf(mat);
01481                                                         }
01482                                                         
01483                                                         copy_m4_m3(mat, pchan->bone->bone_mat);
01484                                                         glMultMatrixf(mat);
01485                                                         
01486                                                         scale= bone->length*pchan->size[1];
01487                                                         glScalef(scale, scale, scale);
01488                                                         
01489                                                         if (pchan->ikflag & BONE_IK_XLIMIT) {
01490                                                                 if (pchan->ikflag & BONE_IK_ZLIMIT) {
01491                                                                         float amin[3], amax[3];
01492                                                                         
01493                                                                         for (i=0; i<3; i++) {
01494                                                                                 /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01495                                                                                 amin[i]= (float)sin(pchan->limitmin[i]*0.5f);
01496                                                                                 amax[i]= (float)sin(pchan->limitmax[i]*0.5f);
01497                                                                         }
01498                                                                         
01499                                                                         glScalef(1.0f, -1.0f, 1.0f);
01500                                                                         if ((amin[0] != 0.0f) && (amin[2] != 0.0f))
01501                                                                                 draw_dof_ellipse(amin[0], amin[2]);
01502                                                                         if ((amin[0] != 0.0f) && (amax[2] != 0.0f))
01503                                                                                 draw_dof_ellipse(amin[0], amax[2]);
01504                                                                         if ((amax[0] != 0.0f) && (amin[2] != 0.0f))
01505                                                                                 draw_dof_ellipse(amax[0], amin[2]);
01506                                                                         if ((amax[0] != 0.0f) && (amax[2] != 0.0f))
01507                                                                                 draw_dof_ellipse(amax[0], amax[2]);
01508                                                                         glScalef(1.0f, -1.0f, 1.0f);
01509                                                                 }
01510                                                         }
01511                                                         
01512                                                         /* arcs */
01513                                                         if (pchan->ikflag & BONE_IK_ZLIMIT) {
01514                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
01515                                                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[2]+pchan->limitmax[2]));
01516                                                                 glRotatef(theta, 0.0f, 0.0f, 1.0f);
01517                                                                 
01518                                                                 glColor3ub(50, 50, 255);        // blue, Z axis limit
01519                                                                 glBegin(GL_LINE_STRIP);
01520                                                                 for (a=-16; a<=16; a++) {
01521                                                                         float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01522                                                                         
01523                                                                         phi= fac * (pchan->limitmax[2] - pchan->limitmin[2]);
01524                                                                         
01525                                                                         i= (a == -16) ? 0 : 1;
01526                                                                         corner[i][0]= (float)sin(phi);
01527                                                                         corner[i][1]= (float)cos(phi);
01528                                                                         corner[i][2]= 0.0f;
01529                                                                         glVertex3fv(corner[i]);
01530                                                                 }
01531                                                                 glEnd();
01532                                                                 
01533                                                                 glRotatef(-theta, 0.0f, 0.0f, 1.0f);
01534                                                         }                                       
01535                                                         
01536                                                         if (pchan->ikflag & BONE_IK_XLIMIT) {
01537                                                                 /* OpenGL requires rotations in degrees; so we're taking the average angle here */
01538                                                                 theta= RAD2DEGF(0.5f * (pchan->limitmin[0] + pchan->limitmax[0]));
01539                                                                 glRotatef(theta, 1.0f, 0.0f, 0.0f);
01540                                                                 
01541                                                                 glColor3ub(255, 50, 50);        // Red, X axis limit
01542                                                                 glBegin(GL_LINE_STRIP);
01543                                                                 for (a=-16; a<=16; a++) {
01544                                                                         float fac= ((float)a)/16.0f * 0.5f; /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */
01545                                                                         phi= (float)(0.5*M_PI) + fac * (pchan->limitmax[0] - pchan->limitmin[0]);
01546                                                                         
01547                                                                         i= (a == -16) ? 2 : 3;
01548                                                                         corner[i][0]= 0.0f;
01549                                                                         corner[i][1]= (float)sin(phi);
01550                                                                         corner[i][2]= (float)cos(phi);
01551                                                                         glVertex3fv(corner[i]);
01552                                                                 }
01553                                                                 glEnd();
01554                                                                 
01555                                                                 glRotatef(-theta, 1.0f, 0.0f, 0.0f);
01556                                                         }
01557                                                         
01558                                                         /* out of cone, out of bone */
01559                                                         glPopMatrix(); 
01560                                                 }
01561                                         }
01562                                 }
01563                         }
01564                 }
01565         }
01566 }
01567 
01568 static void bone_matrix_translate_y(float mat[][4], float y)
01569 {
01570         float trans[3];
01571 
01572         VECCOPY(trans, mat[1]);
01573         mul_v3_fl(trans, y);
01574         add_v3_v3(mat[3], trans);
01575 }
01576 
01577 /* assumes object is Armature with pose */
01578 static void draw_pose_bones(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, const short is_ghost, const short is_outline)
01579 {
01580         RegionView3D *rv3d= ar->regiondata;
01581         Object *ob= base->object;
01582         bArmature *arm= ob->data;
01583         bPoseChannel *pchan;
01584         Bone *bone;
01585         GLfloat tmp;
01586         float smat[4][4], imat[4][4], bmat[4][4];
01587         int index= -1;
01588         short do_dashed= 3, draw_wire= 0;
01589         short flag, constflag;
01590         
01591         /* being set below */
01592         arm->layer_used= 0;
01593         
01594         /* hacky... prevent outline select from drawing dashed helplines */
01595         glGetFloatv(GL_LINE_WIDTH, &tmp);
01596         if (tmp > 1.1f) do_dashed &= ~1;
01597         if (v3d->flag & V3D_HIDE_HELPLINES) do_dashed &= ~2;
01598         
01599         /* precalc inverse matrix for drawing screen aligned */
01600         if (arm->drawtype==ARM_ENVELOPE) {
01601                 /* precalc inverse matrix for drawing screen aligned */
01602                 copy_m4_m4(smat, rv3d->viewmatob);
01603                 mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
01604                 invert_m4_m4(imat, smat);
01605                 
01606                 /* and draw blended distances */
01607                 if (arm->flag & ARM_POSEMODE) {
01608                         glEnable(GL_BLEND);
01609                         //glShadeModel(GL_SMOOTH);
01610                         
01611                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
01612                         
01613                         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01614                                 bone= pchan->bone;
01615                                 if (bone) {
01616                                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] 
01617                                          * NOTE: this is the only case with NO_DEFORM==0 flag, as this is for envelope influence drawing 
01618                                          */
01619                                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_NO_DEFORM|BONE_HIDDEN_PG))==0 && 
01620                                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01621                                         {
01622                                                 if (bone->flag & (BONE_SELECTED)) {
01623                                                         if (bone->layer & arm->layer)
01624                                                                 draw_sphere_bone_dist(smat, imat, pchan, NULL);
01625                                                 }
01626                                         }
01627                                 }
01628                         }
01629                         
01630                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
01631                         glDisable(GL_BLEND);
01632                         //glShadeModel(GL_FLAT);
01633                 }
01634         }
01635         
01636         /* little speedup, also make sure transparent only draws once */
01637         glCullFace(GL_BACK); 
01638         glEnable(GL_CULL_FACE);
01639         
01640         /* if solid we draw that first, with selection codes, but without names, axes etc */
01641         if (dt > OB_WIRE) {
01642                 if (arm->flag & ARM_POSEMODE) 
01643                         index= base->selcol;
01644                 
01645                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01646                         bone= pchan->bone;
01647                         arm->layer_used |= bone->layer;
01648                         
01649                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01650                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01651                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01652                         {
01653                                 if (bone->layer & arm->layer) {
01654                                         int use_custom = (pchan->custom) && !(arm->flag & ARM_NO_CUSTOM);
01655                                         glPushMatrix();
01656                                         
01657                                         if(use_custom && pchan->custom_tx) {
01658                                                 glMultMatrixf(pchan->custom_tx->pose_mat);
01659                                         } 
01660                                         else {
01661                                                 glMultMatrixf(pchan->pose_mat);
01662                                         }
01663                                         
01664                                         /* catch exception for bone with hidden parent */
01665                                         flag= bone->flag;
01666                                         if ( (bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)) )
01667                                                 flag &= ~BONE_CONNECTED;
01668                                         
01669                                         /* set temporary flag for drawing bone as active, but only if selected */
01670                                         if (bone == arm->act_bone)
01671                                                 flag |= BONE_DRAW_ACTIVE;
01672                                         
01673                                         /* set color-set to use */
01674                                         set_pchan_colorset(ob, pchan);
01675                                         
01676                                         if (use_custom) {
01677                                                 /* if drawwire, don't try to draw in solid */
01678                                                 if (pchan->bone->flag & BONE_DRAWWIRE) 
01679                                                         draw_wire= 1;
01680                                                 else
01681                                                         draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_SOLID, arm->flag, flag, index, bone->length);
01682                                         }
01683                                         else if (arm->drawtype==ARM_LINE)
01684                                                 ;       /* nothing in solid */
01685                                         else if (arm->drawtype==ARM_ENVELOPE)
01686                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
01687                                         else if (arm->drawtype==ARM_B_BONE)
01688                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, pchan, NULL);
01689                                         else
01690                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, bone->length);
01691                                                 
01692                                         glPopMatrix();
01693                                 }
01694                         }
01695                         
01696                         if (index!= -1) 
01697                                 index+= 0x10000;        // pose bones count in higher 2 bytes only
01698                 }
01699                 
01700                 /* very very confusing... but in object mode, solid draw, we cannot do glLoadName yet,
01701                  * stick bones and/or wire custom-shapes are drawn in next loop 
01702                  */
01703                 if ((arm->drawtype != ARM_LINE) && (draw_wire == 0)) {
01704                         /* object tag, for bordersel optim */
01705                         glLoadName(index & 0xFFFF);     
01706                         index= -1;
01707                 }
01708         }
01709         
01710         /* draw custom bone shapes as wireframes */
01711         if ( !(arm->flag & ARM_NO_CUSTOM) &&
01712                  ((draw_wire) || (dt <= OB_WIRE)) ) 
01713         {
01714                 if (arm->flag & ARM_POSEMODE)
01715                         index= base->selcol;
01716                         
01717                 /* only draw custom bone shapes that need to be drawn as wires */
01718                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01719                         bone= pchan->bone;
01720                         
01721                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01722                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01723                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01724                         {
01725                                 if (bone->layer & arm->layer) {
01726                                         if (pchan->custom) {
01727                                                 if ((dt < OB_SOLID) || (bone->flag & BONE_DRAWWIRE)) {
01728                                                         glPushMatrix();
01729                                                         
01730                                                         if(pchan->custom_tx) {
01731                                                                 glMultMatrixf(pchan->custom_tx->pose_mat);
01732                                                         } 
01733                                                         else {
01734                                                                 glMultMatrixf(pchan->pose_mat);
01735                                                         }
01736                                                         
01737                                                         /* prepare colors */
01738                                                         if(is_ghost) {
01739                                                                 /* 13 October 2009, Disabled this to make ghosting show the right colors (Aligorith) */
01740                                                         }
01741                                                         else if (arm->flag & ARM_POSEMODE)      
01742                                                                 set_pchan_colorset(ob, pchan);
01743                                                         else {
01744                                                                 if ((scene->basact)==base) {
01745                                                                         if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_ACTIVE);
01746                                                                         else UI_ThemeColor(TH_WIRE);
01747                                                                 }
01748                                                                 else {
01749                                                                         if (base->flag & (SELECT+BA_WAS_SEL)) UI_ThemeColor(TH_SELECT);
01750                                                                         else UI_ThemeColor(TH_WIRE);
01751                                                                 }
01752                                                         }
01753                                                                 
01754                                                         /* catch exception for bone with hidden parent */
01755                                                         flag= bone->flag;
01756                                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
01757                                                                 flag &= ~BONE_CONNECTED;
01758                                                                 
01759                                                         /* set temporary flag for drawing bone as active, but only if selected */
01760                                                         if (bone == arm->act_bone)
01761                                                                 flag |= BONE_DRAW_ACTIVE;
01762                                                         
01763                                                         draw_custom_bone(scene, v3d, rv3d, pchan->custom, OB_WIRE, arm->flag, flag, index, bone->length);
01764                                                         
01765                                                         glPopMatrix();
01766                                                 }
01767                                         }
01768                                 }
01769                         }
01770                         
01771                         if (index != -1) 
01772                                 index+= 0x10000;        // pose bones count in higher 2 bytes only
01773                 }
01774                 /* stick bones have not been drawn yet so dont clear object selection in this case */
01775                 if ((arm->drawtype != ARM_LINE) && draw_wire) {
01776                         /* object tag, for bordersel optim */
01777                         glLoadName(index & 0xFFFF);     
01778                         index= -1;
01779                 }
01780         }
01781         
01782         /* wire draw over solid only in posemode */
01783         if ((dt <= OB_WIRE) || (arm->flag & ARM_POSEMODE) || (arm->drawtype==ARM_LINE)) {
01784                 /* draw line check first. we do selection indices */
01785                 if (arm->drawtype==ARM_LINE) {
01786                         if (arm->flag & ARM_POSEMODE) 
01787                                 index= base->selcol;
01788                 }
01789                 /* if solid && posemode, we draw again with polygonoffset */
01790                 else if ((dt > OB_WIRE) && (arm->flag & ARM_POSEMODE)) {
01791                         bglPolygonOffset(rv3d->dist, 1.0);
01792                 }
01793                 else {
01794                         /* and we use selection indices if not done yet */
01795                         if (arm->flag & ARM_POSEMODE) 
01796                                 index= base->selcol;
01797                 }
01798                 
01799                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
01800                         bone= pchan->bone;
01801                         arm->layer_used |= bone->layer;
01802                         
01803                         /* 1) bone must be visible, 2) for OpenGL select-drawing cannot have unselectable [#27194] */
01804                         if ( (bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0 && 
01805                                  ((G.f & G_PICKSEL)==0 || (bone->flag & BONE_UNSELECTABLE)==0) ) 
01806                         {
01807                                 if (bone->layer & arm->layer) {
01808                                         if ((do_dashed & 1) && (pchan->parent)) {
01809                                                 /* Draw a line from our root to the parent's tip 
01810                                                  *      - only if V3D_HIDE_HELPLINES is enabled...
01811                                                  */
01812                                                 if ( (do_dashed & 2) && ((bone->flag & BONE_CONNECTED)==0) ) {
01813                                                         if (arm->flag & ARM_POSEMODE) {
01814                                                                 glLoadName(index & 0xFFFF);     // object tag, for bordersel optim
01815                                                                 UI_ThemeColor(TH_WIRE);
01816                                                         }
01817                                                         setlinestyle(3);
01818                                                         glBegin(GL_LINES);
01819                                                         glVertex3fv(pchan->pose_head);
01820                                                         glVertex3fv(pchan->parent->pose_tail);
01821                                                         glEnd();
01822                                                         setlinestyle(0);
01823                                                 }
01824                                                 
01825                                                 /* Draw a line to IK root bone 
01826                                                  *      - only if temporary chain (i.e. "autoik")
01827                                                  */
01828                                                 if (arm->flag & ARM_POSEMODE) {
01829                                                         if (pchan->constflag & PCHAN_HAS_IK) {
01830                                                                 if (bone->flag & BONE_SELECTED) {
01831                                                                         if (pchan->constflag & PCHAN_HAS_TARGET) glColor3ub(200, 120, 0);
01832                                                                         else glColor3ub(200, 200, 50);  // add theme!
01833                                                                         
01834                                                                         glLoadName(index & 0xFFFF);
01835                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
01836                                                                 }
01837                                                         }
01838                                                         else if (pchan->constflag & PCHAN_HAS_SPLINEIK) {
01839                                                                 if (bone->flag & BONE_SELECTED) {
01840                                                                         glColor3ub(150, 200, 50);       // add theme!
01841                                                                         
01842                                                                         glLoadName(index & 0xFFFF);
01843                                                                         pchan_draw_IK_root_lines(pchan, !(do_dashed & 2));
01844                                                                 }
01845                                                         }       
01846                                                 }
01847                                         }
01848                                         
01849                                         glPushMatrix();
01850                                         if (arm->drawtype != ARM_ENVELOPE)
01851                                                 glMultMatrixf(pchan->pose_mat);
01852                                         
01853                                         /* catch exception for bone with hidden parent */
01854                                         flag= bone->flag;
01855                                         if ((bone->parent) && (bone->parent->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG)))
01856                                                 flag &= ~BONE_CONNECTED;
01857                                         
01858                                         /* set temporary flag for drawing bone as active, but only if selected */
01859                                         if (bone == arm->act_bone)
01860                                                 flag |= BONE_DRAW_ACTIVE;
01861                                         
01862                                         /* extra draw service for pose mode */
01863                                         constflag= pchan->constflag;
01864                                         if (pchan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE))
01865                                                 constflag |= PCHAN_HAS_ACTION;
01866 
01867                                         /* set color-set to use */
01868                                         set_pchan_colorset(ob, pchan);
01869                                         
01870                                         if ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM))
01871                                                 ; // custom bone shapes should not be drawn here!
01872                                         else if (arm->drawtype==ARM_ENVELOPE) {
01873                                                 if (dt < OB_SOLID)
01874                                                         draw_sphere_bone_wire(smat, imat, arm->flag, flag, constflag, index, pchan, NULL);
01875                                         }
01876                                         else if (arm->drawtype==ARM_LINE)
01877                                                 draw_line_bone(arm->flag, flag, constflag, index, pchan, NULL);
01878                                         else if (arm->drawtype==ARM_B_BONE)
01879                                                 draw_b_bone(OB_WIRE, arm->flag, flag, constflag, index, pchan, NULL);
01880                                         else
01881                                                 draw_bone(OB_WIRE, arm->flag, flag, constflag, index, bone->length);
01882                                         
01883                                         glPopMatrix();
01884                                 }
01885                         }
01886                         
01887                         /* pose bones count in higher 2 bytes only */
01888                         if (index != -1) 
01889                                 index+= 0x10000;        
01890                 }
01891                 /* restore things */
01892                 if ((arm->drawtype!=ARM_LINE)&& (dt>OB_WIRE) && (arm->flag & ARM_POSEMODE))
01893                         bglPolygonOffset(rv3d->dist, 0.0);
01894         }       
01895         
01896         /* restore */
01897         glDisable(GL_CULL_FACE);
01898         
01899         /* draw DoFs */
01900         if (arm->flag & ARM_POSEMODE)
01901                 draw_pose_dofs(ob);
01902 
01903         /* finally names and axes */
01904         if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES) && is_outline == 0) {
01905                 /* patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing */
01906                 if ((G.f & G_PICKSEL) == 0) {
01907                         float vec[3];
01908                         
01909                         unsigned char col[4];
01910                         float col_f[4];
01911                         glGetFloatv(GL_CURRENT_COLOR, col_f); /* incase this is not set below */
01912                         rgb_float_to_byte(col_f, col);
01913                         col[3]= 255;
01914                         
01915                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
01916                         
01917                         for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
01918                                 if ((pchan->bone->flag & (BONE_HIDDEN_P|BONE_HIDDEN_PG))==0) {
01919                                         if (pchan->bone->layer & arm->layer) {
01920                                                 if (arm->flag & (ARM_EDITMODE|ARM_POSEMODE)) {
01921                                                         bone= pchan->bone;
01922                                                         UI_GetThemeColor3ubv((bone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
01923                                                 }
01924                                                 else if (dt > OB_WIRE) {
01925                                                         UI_GetThemeColor3ubv(TH_TEXT, col);
01926                                                 }
01927                                                 
01928                                                 /*      Draw names of bone      */
01929                                                 if (arm->flag & ARM_DRAWNAMES) {
01930                                                         mid_v3_v3v3(vec, pchan->pose_head, pchan->pose_tail);
01931                                                         view3d_cached_text_draw_add(vec, pchan->name, 10, 0, col);
01932                                                 }       
01933                                                 
01934                                                 /*      Draw additional axes on the bone tail  */
01935                                                 if ( (arm->flag & ARM_DRAWAXES) && (arm->flag & ARM_POSEMODE) ) {
01936                                                         glPushMatrix();
01937                                                         copy_m4_m4(bmat, pchan->pose_mat);
01938                                                         bone_matrix_translate_y(bmat, pchan->bone->length);
01939                                                         glMultMatrixf(bmat);
01940                                                         
01941                                                         glColor3ubv(col);
01942                                                         drawaxes(pchan->bone->length*0.25f, OB_ARROWS);
01943                                                         
01944                                                         glPopMatrix();
01945                                                 }
01946                                         }
01947                                 }
01948                         }
01949                         
01950                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
01951                 }
01952         }
01953 }
01954 
01955 /* in editmode, we don't store the bone matrix... */
01956 static void get_matrix_editbone(EditBone *eBone, float bmat[][4])
01957 {
01958         float           delta[3];
01959         float           mat[3][3];
01960         
01961         /* Compose the parent transforms (i.e. their translations) */
01962         sub_v3_v3v3(delta, eBone->tail, eBone->head);   
01963         
01964         eBone->length = (float)sqrt(delta[0]*delta[0] + delta[1]*delta[1] +delta[2]*delta[2]);
01965         
01966         vec_roll_to_mat3(delta, eBone->roll, mat);
01967         copy_m4_m3(bmat, mat);
01968 
01969         add_v3_v3(bmat[3], eBone->head);
01970 }
01971 
01972 static void draw_ebones(View3D *v3d, ARegion *ar, Object *ob, int dt)
01973 {
01974         RegionView3D *rv3d= ar->regiondata;
01975         EditBone *eBone;
01976         bArmature *arm= ob->data;
01977         float smat[4][4], imat[4][4], bmat[4][4];
01978         unsigned int index;
01979         int flag;
01980         
01981         /* being set in code below */
01982         arm->layer_used= 0;
01983         
01984         /* envelope (deform distance) */
01985         if(arm->drawtype==ARM_ENVELOPE) {
01986                 /* precalc inverse matrix for drawing screen aligned */
01987                 copy_m4_m4(smat, rv3d->viewmatob);
01988                 mul_mat3_m4_fl(smat, 1.0f/len_v3(ob->obmat[0]));
01989                 invert_m4_m4(imat, smat);
01990                 
01991                 /* and draw blended distances */
01992                 glEnable(GL_BLEND);
01993                 //glShadeModel(GL_SMOOTH);
01994                 
01995                 if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
01996 
01997                 for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
01998                         if (eBone->layer & arm->layer) {
01999                                 if ((eBone->flag & (BONE_HIDDEN_A|BONE_NO_DEFORM))==0) {
02000                                         if (eBone->flag & (BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL))
02001                                                 draw_sphere_bone_dist(smat, imat, NULL, eBone);
02002                                 }
02003                         }
02004                 }
02005                 
02006                 if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02007                 glDisable(GL_BLEND);
02008                 //glShadeModel(GL_FLAT);
02009         }
02010         
02011         /* if solid we draw it first */
02012         if ((dt > OB_WIRE) && (arm->drawtype!=ARM_LINE)) {
02013                 for (eBone=arm->edbo->first, index=0; eBone; eBone=eBone->next, index++) {
02014                         if (eBone->layer & arm->layer) {
02015                                 if ((eBone->flag & BONE_HIDDEN_A)==0) {
02016                                         glPushMatrix();
02017                                         get_matrix_editbone(eBone, bmat);
02018                                         glMultMatrixf(bmat);
02019                                         
02020                                         /* catch exception for bone with hidden parent */
02021                                         flag= eBone->flag;
02022                                         if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
02023                                                 flag &= ~BONE_CONNECTED;
02024                                                 
02025                                         /* set temporary flag for drawing bone as active, but only if selected */
02026                                         if (eBone == arm->act_edbone)
02027                                                 flag |= BONE_DRAW_ACTIVE;
02028                                         
02029                                         if (arm->drawtype==ARM_ENVELOPE)
02030                                                 draw_sphere_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
02031                                         else if(arm->drawtype==ARM_B_BONE)
02032                                                 draw_b_bone(OB_SOLID, arm->flag, flag, 0, index, NULL, eBone);
02033                                         else {
02034                                                 draw_bone(OB_SOLID, arm->flag, flag, 0, index, eBone->length);
02035                                         }
02036                                         
02037                                         glPopMatrix();
02038                                 }
02039                         }
02040                 }
02041         }
02042         
02043         /* if wire over solid, set offset */
02044         index= -1;
02045         glLoadName(-1);
02046         if (arm->drawtype==ARM_LINE) {
02047                 if(G.f & G_PICKSEL)
02048                         index= 0;
02049         }
02050         else if (dt > OB_WIRE) 
02051                 bglPolygonOffset(rv3d->dist, 1.0f);
02052         else if (arm->flag & ARM_EDITMODE) 
02053                 index= 0;       /* do selection codes */
02054         
02055         for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
02056                 arm->layer_used |= eBone->layer;
02057                 if (eBone->layer & arm->layer) {
02058                         if ((eBone->flag & BONE_HIDDEN_A)==0) {
02059                                 
02060                                 /* catch exception for bone with hidden parent */
02061                                 flag= eBone->flag;
02062                                 if ( (eBone->parent) && !EBONE_VISIBLE(arm, eBone->parent))
02063                                         flag &= ~BONE_CONNECTED;
02064                                         
02065                                 /* set temporary flag for drawing bone as active, but only if selected */
02066                                 if (eBone == arm->act_edbone)
02067                                         flag |= BONE_DRAW_ACTIVE;
02068                                 
02069                                 if (arm->drawtype == ARM_ENVELOPE) {
02070                                         if (dt < OB_SOLID)
02071                                                 draw_sphere_bone_wire(smat, imat, arm->flag, flag, 0, index, NULL, eBone);
02072                                 }
02073                                 else {
02074                                         glPushMatrix();
02075                                         get_matrix_editbone(eBone, bmat);
02076                                         glMultMatrixf(bmat);
02077                                         
02078                                         if (arm->drawtype == ARM_LINE) 
02079                                                 draw_line_bone(arm->flag, flag, 0, index, NULL, eBone);
02080                                         else if (arm->drawtype == ARM_B_BONE)
02081                                                 draw_b_bone(OB_WIRE, arm->flag, flag, 0, index, NULL, eBone);
02082                                         else
02083                                                 draw_bone(OB_WIRE, arm->flag, flag, 0, index, eBone->length);
02084                                         
02085                                         glPopMatrix();
02086                                 }
02087                                 
02088                                 /* offset to parent */
02089                                 if (eBone->parent) {
02090                                         UI_ThemeColor(TH_WIRE);
02091                                         glLoadName (-1);                // -1 here is OK!
02092                                         setlinestyle(3);
02093                                         
02094                                         glBegin(GL_LINES);
02095                                         glVertex3fv(eBone->parent->tail);
02096                                         glVertex3fv(eBone->head);
02097                                         glEnd();
02098                                         
02099                                         setlinestyle(0);
02100                                 }
02101                         }
02102                 }
02103                 if(index!=-1) index++;
02104         }
02105         
02106         /* restore */
02107         if(index!=-1) glLoadName(-1);
02108         if (arm->drawtype==ARM_LINE);
02109         else if (dt>OB_WIRE) bglPolygonOffset(rv3d->dist, 0.0f);
02110         
02111         /* finally names and axes */
02112         if (arm->flag & (ARM_DRAWNAMES|ARM_DRAWAXES)) {
02113                 // patch for several 3d cards (IBM mostly) that crash on glSelect with text drawing
02114                 if ((G.f & G_PICKSEL) == 0) {
02115                         float vec[3];
02116                         unsigned char col[4];
02117                         col[3]= 255;
02118                         
02119                         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02120                         
02121                         for (eBone=arm->edbo->first; eBone; eBone=eBone->next) {
02122                                 if(eBone->layer & arm->layer) {
02123                                         if ((eBone->flag & BONE_HIDDEN_A)==0) {
02124 
02125                                                 UI_GetThemeColor3ubv((eBone->flag & BONE_SELECTED) ? TH_TEXT_HI : TH_TEXT, col);
02126 
02127                                                 /*      Draw name */
02128                                                 if (arm->flag & ARM_DRAWNAMES) {
02129                                                         mid_v3_v3v3(vec, eBone->head, eBone->tail);
02130                                                         glRasterPos3fv(vec);
02131                                                         view3d_cached_text_draw_add(vec, eBone->name, 10, 0, col);
02132                                                 }                                       
02133                                                 /*      Draw additional axes */
02134                                                 if (arm->flag & ARM_DRAWAXES) {
02135                                                         glPushMatrix();
02136                                                         get_matrix_editbone(eBone, bmat);
02137                                                         bone_matrix_translate_y(bmat, eBone->length);
02138                                                         glMultMatrixf(bmat);
02139 
02140                                                         glColor3ubv(col);
02141                                                         drawaxes(eBone->length*0.25f, OB_ARROWS);
02142                                                         
02143                                                         glPopMatrix();
02144                                                 }
02145                                                 
02146                                         }
02147                                 }
02148                         }
02149                         
02150                         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02151                 }
02152         }
02153 }
02154 
02155 /* ****************************** Armature Visualisation ******************************** */
02156 
02157 /* ---------- Paths --------- */
02158 
02159 /* draw bone paths
02160  *      - in view space 
02161  */
02162 static void draw_pose_paths(Scene *scene, View3D *v3d, ARegion *ar, Object *ob)
02163 {
02164         bAnimVizSettings *avs= &ob->pose->avs;
02165         bArmature *arm= ob->data;
02166         bPoseChannel *pchan;
02167         
02168         /* setup drawing environment for paths */
02169         draw_motion_paths_init(v3d, ar);
02170         
02171         /* draw paths where they exist and they releated bone is visible */
02172         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
02173                 if ((pchan->bone->layer & arm->layer) && (pchan->mpath))
02174                         draw_motion_path_instance(scene, ob, pchan, avs, pchan->mpath);
02175         }
02176         
02177         /* cleanup after drawing */
02178         draw_motion_paths_cleanup(v3d);
02179 }
02180 
02181 
02182 /* ---------- Ghosts --------- */
02183 
02184 /* helper function for ghost drawing - sets/removes flags for temporarily 
02185  * hiding unselected bones while drawing ghosts
02186  */
02187 static void ghost_poses_tag_unselected(Object *ob, short unset)
02188 {
02189         bArmature *arm= ob->data;
02190         bPose *pose= ob->pose;
02191         bPoseChannel *pchan;
02192         
02193         /* don't do anything if no hiding any bones */
02194         if ((arm->flag & ARM_GHOST_ONLYSEL)==0)
02195                 return;
02196                 
02197         /* loop over all pchans, adding/removing tags as appropriate */
02198         for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
02199                 if ((pchan->bone) && (arm->layer & pchan->bone->layer)) {
02200                         if (unset) {
02201                                 /* remove tags from all pchans if cleaning up */
02202                                 pchan->bone->flag &= ~BONE_HIDDEN_PG;
02203                         }
02204                         else {
02205                                 /* set tags on unselected pchans only */
02206                                 if ((pchan->bone->flag & BONE_SELECTED)==0)
02207                                         pchan->bone->flag |= BONE_HIDDEN_PG;
02208                         }
02209                 }
02210         }
02211 }
02212 
02213 /* draw ghosts that occur within a frame range 
02214  *      note: object should be in posemode 
02215  */
02216 static void draw_ghost_poses_range(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02217 {
02218         Object *ob= base->object;
02219         AnimData *adt= BKE_animdata_from_id(&ob->id);
02220         bArmature *arm= ob->data;
02221         bPose *posen, *poseo;
02222         float start, end, stepsize, range, colfac;
02223         int cfrao, flago, ipoflago;
02224         
02225         start = (float)arm->ghostsf;
02226         end = (float)arm->ghostef;
02227         if (end <= start)
02228                 return;
02229         
02230         stepsize= (float)(arm->ghostsize);
02231         range= (float)(end - start);
02232         
02233         /* store values */
02234         ob->mode &= ~OB_MODE_POSE;
02235         cfrao= CFRA;
02236         flago= arm->flag;
02237         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02238         ipoflago= ob->ipoflag; 
02239         ob->ipoflag |= OB_DISABLE_PATH;
02240         
02241         /* copy the pose */
02242         poseo= ob->pose;
02243         copy_pose(&posen, ob->pose, 1);
02244         ob->pose= posen;
02245         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02246         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
02247         
02248         glEnable(GL_BLEND);
02249         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02250         
02251         /* draw from first frame of range to last */
02252         for (CFRA= (int)start; CFRA < end; CFRA += (int)stepsize) {
02253                 colfac = (end - (float)CFRA) / range;
02254                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02255                 
02256                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02257                 where_is_pose(scene, ob);
02258                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02259         }
02260         glDisable(GL_BLEND);
02261         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02262 
02263         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
02264         free_pose(posen);
02265         
02266         /* restore */
02267         CFRA= cfrao;
02268         ob->pose= poseo;
02269         arm->flag= flago;
02270         armature_rebuild_pose(ob, ob->data);
02271         ob->mode |= OB_MODE_POSE;
02272         ob->ipoflag= ipoflago; 
02273 }
02274 
02275 /* draw ghosts on keyframes in action within range 
02276  *      - object should be in posemode 
02277  */
02278 static void draw_ghost_poses_keys(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02279 {
02280         Object *ob= base->object;
02281         AnimData *adt= BKE_animdata_from_id(&ob->id);
02282         bAction *act= (adt) ? adt->action : NULL;
02283         bArmature *arm= ob->data;
02284         bPose *posen, *poseo;
02285         DLRBT_Tree keys;
02286         ActKeyColumn *ak, *akn;
02287         float start, end, range, colfac, i;
02288         int cfrao, flago;
02289         
02290         start = (float)arm->ghostsf;
02291         end = (float)arm->ghostef;
02292         if (end <= start)
02293                 return;
02294         
02295         /* get keyframes - then clip to only within range */
02296         BLI_dlrbTree_init(&keys);
02297         action_to_keylist(adt, act, &keys, NULL);
02298         BLI_dlrbTree_linkedlist_sync(&keys);
02299         
02300         range= 0;
02301         for (ak= keys.first; ak; ak= akn) {
02302                 akn= ak->next;
02303                 
02304                 if ((ak->cfra < start) || (ak->cfra > end))
02305                         BLI_freelinkN((ListBase *)&keys, ak);
02306                 else
02307                         range++;
02308         }
02309         if (range == 0) return;
02310         
02311         /* store values */
02312         ob->mode &= ~OB_MODE_POSE;
02313         cfrao= CFRA;
02314         flago= arm->flag;
02315         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02316         ob->ipoflag |= OB_DISABLE_PATH;
02317         
02318         /* copy the pose */
02319         poseo= ob->pose;
02320         copy_pose(&posen, ob->pose, 1);
02321         ob->pose= posen;
02322         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02323         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
02324         
02325         glEnable(GL_BLEND);
02326         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02327         
02328         /* draw from first frame of range to last */
02329         for (ak=keys.first, i=0; ak; ak=ak->next, i++) {
02330                 colfac = i/range;
02331                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02332                 
02333                 CFRA= (int)ak->cfra;
02334                 
02335                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02336                 where_is_pose(scene, ob);
02337                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02338         }
02339         glDisable(GL_BLEND);
02340         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02341 
02342         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
02343         BLI_dlrbTree_free(&keys);
02344         free_pose(posen);
02345         
02346         /* restore */
02347         CFRA= cfrao;
02348         ob->pose= poseo;
02349         arm->flag= flago;
02350         armature_rebuild_pose(ob, ob->data);
02351         ob->mode |= OB_MODE_POSE;
02352 }
02353 
02354 /* draw ghosts around current frame
02355  *      - object is supposed to be armature in posemode 
02356  */
02357 static void draw_ghost_poses(Scene *scene, View3D *v3d, ARegion *ar, Base *base)
02358 {
02359         Object *ob= base->object;
02360         AnimData *adt= BKE_animdata_from_id(&ob->id);
02361         bArmature *arm= ob->data;
02362         bPose *posen, *poseo;
02363         float cur, start, end, stepsize, range, colfac, actframe, ctime;
02364         int cfrao, flago;
02365         
02366         /* pre conditions, get an action with sufficient frames */
02367         if ELEM(NULL, adt, adt->action)
02368                 return;
02369 
02370         calc_action_range(adt->action, &start, &end, 0);
02371         if (start == end)
02372                 return;
02373 
02374         stepsize= (float)(arm->ghostsize);
02375         range= (float)(arm->ghostep)*stepsize + 0.5f;   /* plus half to make the for loop end correct */
02376         
02377         /* store values */
02378         ob->mode &= ~OB_MODE_POSE;
02379         cfrao= CFRA;
02380         actframe= BKE_nla_tweakedit_remap(adt, (float)CFRA, 0);
02381         flago= arm->flag;
02382         arm->flag &= ~(ARM_DRAWNAMES|ARM_DRAWAXES);
02383         
02384         /* copy the pose */
02385         poseo= ob->pose;
02386         copy_pose(&posen, ob->pose, 1);
02387         ob->pose= posen;
02388         armature_rebuild_pose(ob, ob->data);    /* child pointers for IK */
02389         ghost_poses_tag_unselected(ob, 0);              /* hide unselected bones if need be */
02390         
02391         glEnable(GL_BLEND);
02392         if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
02393         
02394         /* draw from darkest blend to lowest */
02395         for(cur= stepsize; cur<range; cur+=stepsize) {
02396                 ctime= cur - (float)fmod(cfrao, stepsize);      /* ensures consistent stepping */
02397                 colfac= ctime/range;
02398                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02399                 
02400                 /* only within action range */
02401                 if (actframe+ctime >= start && actframe+ctime <= end) {
02402                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe+ctime, NLATIME_CONVERT_MAP);
02403                         
02404                         if (CFRA != cfrao) {
02405                                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02406                                 where_is_pose(scene, ob);
02407                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02408                         }
02409                 }
02410                 
02411                 ctime= cur + (float)fmod((float)cfrao, stepsize) - stepsize+1.0f;       /* ensures consistent stepping */
02412                 colfac= ctime/range;
02413                 UI_ThemeColorShadeAlpha(TH_WIRE, 0, -128-(int)(120.0*sqrt(colfac)));
02414                 
02415                 /* only within action range */
02416                 if ((actframe-ctime >= start) && (actframe-ctime <= end)) {
02417                         CFRA= (int)BKE_nla_tweakedit_remap(adt, actframe-ctime, NLATIME_CONVERT_MAP);
02418                         
02419                         if (CFRA != cfrao) {
02420                                 BKE_animsys_evaluate_animdata(&ob->id, adt, (float)CFRA, ADT_RECALC_ALL);
02421                                 where_is_pose(scene, ob);
02422                                 draw_pose_bones(scene, v3d, ar, base, OB_WIRE, TRUE, FALSE);
02423                         }
02424                 }
02425         }
02426         glDisable(GL_BLEND);
02427         if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
02428 
02429         ghost_poses_tag_unselected(ob, 1);              /* unhide unselected bones if need be */
02430         free_pose(posen);
02431         
02432         /* restore */
02433         CFRA= cfrao;
02434         ob->pose= poseo;
02435         arm->flag= flago;
02436         armature_rebuild_pose(ob, ob->data);
02437         ob->mode |= OB_MODE_POSE;
02438 }
02439 
02440 /* ********************************** Armature Drawing - Main ************************* */
02441 
02442 /* called from drawobject.c, return 1 if nothing was drawn */
02443 int draw_armature(Scene *scene, View3D *v3d, ARegion *ar, Base *base, int dt, int flag, const short is_outline)
02444 {
02445         Object *ob= base->object;
02446         bArmature *arm= ob->data;
02447         int retval= 0;
02448 
02449         if(v3d->flag2 & V3D_RENDER_OVERRIDE)
02450                 return 1;
02451         
02452         if(dt>OB_WIRE && arm->drawtype!=ARM_LINE) {
02453                 /* we use color for solid lighting */
02454                 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
02455                 glEnable(GL_COLOR_MATERIAL);
02456                 glColor3ub(255,255,255);        // clear spec
02457                 glDisable(GL_COLOR_MATERIAL);
02458                 
02459                 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
02460                 glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW); // only for lighting...
02461         }
02462         
02463         /* arm->flag is being used to detect mode... */
02464         /* editmode? */
02465         if(arm->edbo) {
02466                 arm->flag |= ARM_EDITMODE;
02467                 draw_ebones(v3d, ar, ob, dt);
02468                 arm->flag &= ~ARM_EDITMODE;
02469         }
02470         else{
02471                 /*      Draw Pose */
02472                 if(ob->pose && ob->pose->chanbase.first) {
02473                         /* drawing posemode selection indices or colors only in these cases */
02474                         if(!(base->flag & OB_FROMDUPLI)) {
02475                                 if(G.f & G_PICKSEL) {
02476 #if 0                           /* nifty but actually confusing to allow bone selection out of posemode */
02477                                         if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
02478                                                 if(ob==modifiers_isDeformedByArmature(OBACT))
02479                                                         arm->flag |= ARM_POSEMODE;
02480                                         }
02481                                         else
02482 #endif
02483                                         if(ob->mode & OB_MODE_POSE) {
02484                                                 arm->flag |= ARM_POSEMODE;
02485                                         }
02486                                 }
02487                                 else if(ob->mode & OB_MODE_POSE) {
02488                                         if (arm->ghosttype == ARM_GHOST_RANGE) {
02489                                                 draw_ghost_poses_range(scene, v3d, ar, base);
02490                                         }
02491                                         else if (arm->ghosttype == ARM_GHOST_KEYS) {
02492                                                 draw_ghost_poses_keys(scene, v3d, ar, base);
02493                                         }
02494                                         else if (arm->ghosttype == ARM_GHOST_CUR) {
02495                                                 if (arm->ghostep)
02496                                                         draw_ghost_poses(scene, v3d, ar, base);
02497                                         }
02498                                         if ((flag & DRAW_SCENESET)==0) {
02499                                                 if(ob==OBACT) 
02500                                                         arm->flag |= ARM_POSEMODE;
02501                                                 else if(OBACT && (OBACT->mode & OB_MODE_WEIGHT_PAINT)) {
02502                                                         if(ob==modifiers_isDeformedByArmature(OBACT))
02503                                                                 arm->flag |= ARM_POSEMODE;
02504                                                 }
02505                                                 draw_pose_paths(scene, v3d, ar, ob);
02506                                         }
02507                                 }       
02508                         }
02509                         draw_pose_bones(scene, v3d, ar, base, dt, FALSE, is_outline);
02510                         arm->flag &= ~ARM_POSEMODE; 
02511                         
02512                         if(ob->mode & OB_MODE_POSE)
02513                                 UI_ThemeColor(TH_WIRE); /* restore, for extra draw stuff */
02514                 }
02515                 else retval= 1;
02516         }
02517         /* restore */
02518         glFrontFace(GL_CCW);
02519 
02520         return retval;
02521 }
02522 
02523 /* *************** END Armature drawing ******************* */
02524 
02525