Blender V2.61 - r43446

drawanimviz.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2009 by the Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Joshua Leung
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036 
00037 #include "BLO_sys_types.h"
00038 
00039 #include "DNA_anim_types.h"
00040 #include "DNA_armature_types.h"
00041 #include "DNA_scene_types.h"
00042 #include "DNA_screen_types.h"
00043 #include "DNA_view3d_types.h"
00044 #include "DNA_object_types.h"
00045 
00046 #include "BLI_blenlib.h"
00047 #include "BLI_math.h"
00048 #include "BLI_dlrbTree.h"
00049 
00050 #include "BKE_animsys.h"
00051 #include "BKE_action.h"
00052 
00053 #include "BIF_gl.h"
00054 
00055 #include "ED_armature.h"
00056 #include "ED_keyframes_draw.h"
00057 
00058 #include "BLF_api.h"
00059 
00060 #include "UI_resources.h"
00061 
00062 #include "view3d_intern.h"
00063 
00064 /* ************************************ Motion Paths ************************************* */
00065 
00066 // TODO: 
00067 //  - options to draw paths with lines
00068 //  - include support for editing the path verts
00069 
00070 /* Set up drawing environment for drawing motion paths */
00071 void draw_motion_paths_init(View3D *v3d, ARegion *ar) 
00072 {
00073     RegionView3D *rv3d= ar->regiondata;
00074     
00075     if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
00076     
00077     glPushMatrix();
00078     glLoadMatrixf(rv3d->viewmat);
00079 }
00080 
00081 /* Draw the given motion path for an Object or a Bone 
00082  *  - assumes that the viewport has already been initialised properly
00083  *      i.e. draw_motion_paths_init() has been called
00084  */
00085 void draw_motion_path_instance(Scene *scene, 
00086             Object *ob, bPoseChannel *pchan, bAnimVizSettings *avs, bMotionPath *mpath)
00087 {
00088     //RegionView3D *rv3d= ar->regiondata;
00089     bMotionPathVert *mpv, *mpv_start;
00090     int i, stepsize= avs->path_step;
00091     int sfra, efra, len;
00092     
00093     
00094     /* get frame ranges */
00095     if (avs->path_type == MOTIONPATH_TYPE_ACFRA) {
00096         int sind;
00097         
00098         /* With "Around Current", we only choose frames from around 
00099          * the current frame to draw. However, this range is still 
00100          * restricted by the limits of the original path.
00101          */
00102         sfra= CFRA - avs->path_bc;
00103         efra= CFRA + avs->path_ac;
00104         if (sfra < mpath->start_frame) sfra= mpath->start_frame;
00105         if (efra > mpath->end_frame) efra= mpath->end_frame;
00106         
00107         len= efra - sfra;
00108         
00109         sind= sfra - mpath->start_frame;
00110         mpv_start= (mpath->points + sind);
00111     }
00112     else {
00113         sfra= mpath->start_frame;
00114         efra = sfra + mpath->length;
00115         len = mpath->length;
00116         mpv_start= mpath->points;
00117     }
00118 
00119     if(len <= 0) {
00120         return;
00121     }
00122 
00123     /* draw curve-line of path */
00124     glShadeModel(GL_SMOOTH);
00125     
00126     glBegin(GL_LINE_STRIP);                 
00127     for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
00128         short sel= (pchan) ? (pchan->bone->flag & BONE_SELECTED) : (ob->flag & SELECT);
00129         float intensity; /* how faint */
00130         
00131         /* set color
00132          *  - more intense for active/selected bones, less intense for unselected bones
00133          *  - black for before current frame, green for current frame, blue for after current frame
00134          *  - intensity decreases as distance from current frame increases
00135          */
00136         #define SET_INTENSITY(A, B, C, min, max) (((1.0f - ((C - B) / (C - A))) * (max-min)) + min) 
00137         if ((sfra+i) < CFRA) {
00138             /* black - before cfra */
00139             if (sel) {
00140                 // intensity= 0.5f;
00141                 intensity = SET_INTENSITY(sfra, i, CFRA, 0.25f, 0.75f);
00142             }
00143             else {
00144                 //intensity= 0.8f;
00145                 intensity = SET_INTENSITY(sfra, i, CFRA, 0.68f, 0.92f);
00146             }
00147             UI_ThemeColorBlend(TH_WIRE, TH_BACK, intensity);
00148         }
00149         else if ((sfra+i) > CFRA) {
00150             /* blue - after cfra */
00151             if (sel) {
00152                 //intensity = 0.5f;
00153                 intensity = SET_INTENSITY(CFRA, i, efra, 0.25f, 0.75f);
00154             }
00155             else {
00156                 //intensity = 0.8f;
00157                 intensity = SET_INTENSITY(CFRA, i, efra, 0.68f, 0.92f);
00158             }
00159             UI_ThemeColorBlend(TH_BONE_POSE, TH_BACK, intensity);
00160         }
00161         else {
00162             /* green - on cfra */
00163             if (sel) {
00164                 intensity= 0.5f;
00165             }
00166             else {
00167                 intensity= 0.99f;
00168             }
00169             UI_ThemeColorBlendShade(TH_CFRAME, TH_BACK, intensity, 10);
00170         }   
00171         
00172         /* draw a vertex with this color */ 
00173         glVertex3fv(mpv->co);
00174     }
00175     
00176     glEnd();
00177     glShadeModel(GL_FLAT);
00178     
00179     glPointSize(1.0);
00180     
00181     /* draw little black point at each frame
00182      * NOTE: this is not really visible/noticable
00183      */
00184     glBegin(GL_POINTS);
00185     for (i=0, mpv=mpv_start; i < len; i++, mpv++) 
00186         glVertex3fv(mpv->co);
00187     glEnd();
00188     
00189     /* Draw little white dots at each framestep value */
00190     UI_ThemeColor(TH_TEXT_HI);
00191     glBegin(GL_POINTS);
00192     for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) 
00193         glVertex3fv(mpv->co);
00194     glEnd();
00195     
00196     /* Draw big green dot where the current frame is */
00197     // NOTE: only do this when drawing keyframes for now... 
00198     if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
00199         UI_ThemeColor(TH_CFRAME);
00200         glPointSize(6.0f);
00201         
00202         glBegin(GL_POINTS);
00203             mpv = mpv_start + (CFRA - sfra);
00204             glVertex3fv(mpv->co);
00205         glEnd();
00206         
00207         glPointSize(1.0f);
00208         UI_ThemeColor(TH_TEXT_HI);
00209     }
00210     
00211     // XXX, this isnt up to date but probably should be kept so.
00212     invert_m4_m4(ob->imat, ob->obmat);
00213     
00214     /* Draw frame numbers at each framestep value */
00215     if (avs->path_viewflag & MOTIONPATH_VIEW_FNUMS) {
00216         unsigned char col[4];
00217         UI_GetThemeColor3ubv(TH_TEXT_HI, col);
00218         col[3]= 255;
00219 
00220         for (i=0, mpv=mpv_start; i < len; i+=stepsize, mpv+=stepsize) {
00221             char numstr[32];
00222             float co[3];
00223             
00224             /* only draw framenum if several consecutive highlighted points don't occur on same point */
00225             if (i == 0) {
00226                 sprintf(numstr, "%d", (i+sfra));
00227                 mul_v3_m4v3(co, ob->imat, mpv->co);
00228                 view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col);
00229             }
00230             else if ((i > stepsize) && (i < len-stepsize)) { 
00231                 bMotionPathVert *mpvP = (mpv - stepsize);
00232                 bMotionPathVert *mpvN = (mpv + stepsize);
00233                 
00234                 if ((equals_v3v3(mpv->co, mpvP->co)==0) || (equals_v3v3(mpv->co, mpvN->co)==0)) {
00235                     sprintf(numstr, "%d", (sfra+i));
00236                     mul_v3_m4v3(co, ob->imat, mpv->co);
00237                     view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col);
00238                 }
00239             }
00240         }
00241     }
00242     
00243     /* Keyframes - dots and numbers */
00244     if (avs->path_viewflag & MOTIONPATH_VIEW_KFRAS) {
00245         unsigned char col[4];
00246 
00247         AnimData *adt= BKE_animdata_from_id(&ob->id);
00248         DLRBT_Tree keys;
00249         
00250         /* build list of all keyframes in active action for object or pchan */
00251         BLI_dlrbTree_init(&keys);
00252         
00253         if (adt) {
00254             /* it is assumed that keyframes for bones are all grouped in a single group
00255              * unless an option is set to always use the whole action
00256              */
00257             if ((pchan) && (avs->path_viewflag & MOTIONPATH_VIEW_KFACT)==0) {
00258                 bActionGroup *agrp= action_groups_find_named(adt->action, pchan->name);
00259                 
00260                 if (agrp) {
00261                     agroup_to_keylist(adt, agrp, &keys, NULL);
00262                     BLI_dlrbTree_linkedlist_sync(&keys);
00263                 }
00264             }
00265             else {
00266                 action_to_keylist(adt, adt->action, &keys, NULL);
00267                 BLI_dlrbTree_linkedlist_sync(&keys);
00268             }
00269         }
00270         
00271         /* Draw slightly-larger yellow dots at each keyframe */
00272         UI_GetThemeColor3ubv(TH_VERTEX_SELECT, col);
00273         col[3]= 255;
00274 
00275         glPointSize(4.0f); // XXX perhaps a bit too big
00276         glColor3ubv(col);
00277         
00278         glBegin(GL_POINTS);
00279         for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
00280             float mframe= (float)(sfra + i);
00281             
00282             if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe))
00283                 glVertex3fv(mpv->co);
00284         }
00285         glEnd();
00286         
00287         glPointSize(1.0f);
00288         
00289         /* Draw frame numbers of keyframes  */
00290         if (avs->path_viewflag & MOTIONPATH_VIEW_KFNOS) {
00291             float co[3];
00292             for (i=0, mpv=mpv_start; i < len; i++, mpv++) {
00293                 float mframe= (float)(sfra + i);
00294                 
00295                 if (BLI_dlrbTree_search_exact(&keys, compare_ak_cfraPtr, &mframe)) {
00296                     char numstr[32];
00297                     
00298                     sprintf(numstr, "%d", (sfra+i));
00299                     mul_v3_m4v3(co, ob->imat, mpv->co);
00300                     view3d_cached_text_draw_add(co, numstr, 0, V3D_CACHE_TEXT_WORLDSPACE|V3D_CACHE_TEXT_ASCII, col);
00301                 }
00302             }
00303         }
00304         
00305         BLI_dlrbTree_free(&keys);
00306     }
00307 }
00308 
00309 /* Clean up drawing environment after drawing motion paths */
00310 void draw_motion_paths_cleanup(View3D *v3d)
00311 {
00312     if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
00313     glPopMatrix();
00314 }