Blender V2.61 - r43446

action_draw.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) 2001-2002 by NaN Holding BV.
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 /* System includes ----------------------------------------------------- */
00034 
00035 #include <math.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <float.h>
00039 
00040 #include "BLI_blenlib.h"
00041 #include "BLI_math.h"
00042 #include "BLI_utildefines.h"
00043 
00044 /* Types --------------------------------------------------------------- */
00045 
00046 #include "DNA_anim_types.h"
00047 #include "DNA_screen_types.h"
00048 
00049 #include "BKE_action.h"
00050 #include "BKE_context.h"
00051 
00052 
00053 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
00054 
00055 #include "BIF_gl.h"
00056 
00057 #include "UI_interface.h"
00058 #include "UI_resources.h"
00059 #include "UI_view2d.h"
00060 
00061 #include "ED_anim_api.h"
00062 #include "ED_keyframes_draw.h"
00063 
00064 #include "action_intern.h"
00065 
00066 /* ************************************************************************* */
00067 /* Channel List */
00068 
00069 /* left hand part */
00070 void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) 
00071 {
00072     ListBase anim_data = {NULL, NULL};
00073     bAnimListElem *ale;
00074     int filter;
00075     
00076     View2D *v2d= &ar->v2d;
00077     float y= 0.0f;
00078     size_t items;
00079     int height;
00080     
00081     /* build list of channels to draw */
00082     filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
00083     items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00084     
00085     /* Update max-extent of channels here (taking into account scrollers):
00086      *  - this is done to allow the channel list to be scrollable, but must be done here
00087      *    to avoid regenerating the list again and/or also because channels list is drawn first
00088      *  - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
00089      *    start of list offset, and the second is as a correction for the scrollers.
00090      */
00091     height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
00092     if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
00093         /* don't use totrect set, as the width stays the same 
00094          * (NOTE: this is ok here, the configuration is pretty straightforward) 
00095          */
00096         v2d->tot.ymin= (float)(-height);
00097     }
00098     /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
00099     UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
00100     
00101     /* loop through channels, and set up drawing depending on their type  */    
00102     {   /* first pass: just the standard GL-drawing for backdrop + text */
00103         y= (float)ACHANNEL_FIRST;
00104         
00105         for (ale= anim_data.first; ale; ale= ale->next) {
00106             float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
00107             float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
00108             
00109             /* check if visible */
00110             if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00111                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00112             {
00113                 /* draw all channels using standard channel-drawing API */
00114                 ANIM_channel_draw(ac, ale, yminc, ymaxc);
00115             }
00116             
00117             /* adjust y-position for next one */
00118             y -= ACHANNEL_STEP;
00119         }
00120     }
00121     {   /* second pass: widgets */
00122         uiBlock *block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
00123         size_t channel_index = 0;
00124         
00125         y= (float)ACHANNEL_FIRST;
00126         
00127         for (ale= anim_data.first; ale; ale= ale->next) {
00128             float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
00129             float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
00130             
00131             /* check if visible */
00132             if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00133                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00134             {
00135                 /* draw all channels using standard channel-drawing API */
00136                 ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
00137             }
00138             
00139             /* adjust y-position for next one */
00140             y -= ACHANNEL_STEP;
00141             channel_index++;
00142         }
00143         
00144         uiEndBlock(C, block);
00145         uiDrawBlock(C, block);
00146     }
00147     
00148     /* free tempolary channels */
00149     BLI_freelistN(&anim_data);
00150 }
00151 
00152 /* ************************************************************************* */
00153 /* Keyframes */
00154 
00155 /* extra padding for lengths (to go under scrollers) */
00156 #define EXTRA_SCROLL_PAD    100.0f
00157 
00158 /* draw keyframes in each channel */
00159 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
00160 {
00161     ListBase anim_data = {NULL, NULL};
00162     bAnimListElem *ale;
00163     int filter;
00164     
00165     View2D *v2d= &ar->v2d;
00166     bDopeSheet *ads= &saction->ads;
00167     AnimData *adt= NULL;
00168     
00169     float act_start, act_end, y;
00170     size_t items;
00171     int height;
00172     
00173     unsigned char col1[3], col2[3];
00174     unsigned char col1a[3], col2a[3];
00175     unsigned char col1b[3], col2b[3];
00176     
00177     
00178     /* get theme colors */
00179     UI_GetThemeColor3ubv(TH_BACK, col2);
00180     UI_GetThemeColor3ubv(TH_HILITE, col1);
00181     
00182     UI_GetThemeColor3ubv(TH_GROUP, col2a);
00183     UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
00184     
00185     UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
00186     UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
00187     
00188     /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
00189 
00190     /* if in NLA there's a strip active, map the view */
00191     if (ac->datatype == ANIMCONT_ACTION) {
00192         /* adt= ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */
00193         
00194         /* start and end of action itself */
00195         calc_action_range(ac->data, &act_start, &act_end, 0);
00196     }
00197     
00198     /* build list of channels to draw */
00199     filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
00200     items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00201     
00202     /* Update max-extent of channels here (taking into account scrollers):
00203      *  - this is done to allow the channel list to be scrollable, but must be done here
00204      *    to avoid regenerating the list again and/or also because channels list is drawn first
00205      *  - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
00206      *    start of list offset, and the second is as a correction for the scrollers.
00207      */
00208     height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
00209     /* don't use totrect set, as the width stays the same 
00210      * (NOTE: this is ok here, the configuration is pretty straightforward) 
00211      */
00212     v2d->tot.ymin= (float)(-height);
00213     
00214     /* first backdrop strips */
00215     y= (float)(-ACHANNEL_HEIGHT);
00216     glEnable(GL_BLEND);
00217     
00218     for (ale= anim_data.first; ale; ale= ale->next) {
00219         const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
00220         const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
00221         
00222         /* check if visible */
00223         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00224              IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00225         {
00226             bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
00227             int sel=0;
00228             
00229             /* determine if any need to draw channel */
00230             if (ale->datatype != ALE_NONE) {
00231                 /* determine if channel is selected */
00232                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
00233                     sel= ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
00234                 
00235                 if (ELEM3(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
00236                     switch (ale->type) {
00237                         case ANIMTYPE_SUMMARY:
00238                         {
00239                             // FIXME: hardcoded colors - reddish color from NLA
00240                             glColor4f(0.8f, 0.2f, 0.0f, 0.4f);
00241                         }
00242                             break;
00243                         
00244                         case ANIMTYPE_SCENE:
00245                         case ANIMTYPE_OBJECT:
00246                         {
00247                             if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
00248                             else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
00249                         }
00250                             break;
00251                         
00252                         case ANIMTYPE_FILLACTD:
00253                         case ANIMTYPE_DSSKEY:
00254                         case ANIMTYPE_DSWOR:
00255                         {
00256                             if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
00257                             else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
00258                         }
00259                             break;
00260                         
00261                         case ANIMTYPE_GROUP:
00262                         {
00263                             if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
00264                             else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
00265                         }
00266                             break;
00267                         
00268                         default:
00269                         {
00270                             if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
00271                             else glColor4ub(col2[0], col2[1], col2[2], 0x22);
00272                         }
00273                             break;
00274                     }
00275                     
00276                     /* draw region twice: firstly backdrop, then the current range */
00277                     glRectf(v2d->cur.xmin,  (float)y-ACHANNEL_HEIGHT_HALF,  v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
00278                     
00279                     if (ac->datatype == ANIMCONT_ACTION)
00280                         glRectf(act_start,  (float)y-ACHANNEL_HEIGHT_HALF,  act_end,  (float)y+ACHANNEL_HEIGHT_HALF);
00281                 }
00282                 else if (ac->datatype == ANIMCONT_GPENCIL) {
00283                     /* frames less than one get less saturated background */
00284                     if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
00285                     else glColor4ub(col2[0], col2[1], col2[2], 0x22);
00286                     glRectf(0.0f, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmin, (float)y+ACHANNEL_HEIGHT_HALF);
00287                     
00288                     /* frames one and higher get a saturated background */
00289                     if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
00290                     else glColor4ub(col2[0], col2[1], col2[2], 0x44);
00291                     glRectf(v2d->cur.xmin, (float)y-ACHANNEL_HEIGHT_HALF, v2d->cur.xmax+EXTRA_SCROLL_PAD,  (float)y+ACHANNEL_HEIGHT_HALF);
00292                 }
00293             }
00294         }
00295         
00296         /*  Increment the step */
00297         y -= ACHANNEL_STEP;
00298     }       
00299     glDisable(GL_BLEND);
00300     
00301     /* Draw keyframes 
00302      *  1) Only channels that are visible in the Action Editor get drawn/evaluated.
00303      *     This is to try to optimise this for heavier data sets
00304      *  2) Keyframes which are out of view horizontally are disregarded 
00305      */
00306     y= (float)(-ACHANNEL_HEIGHT);
00307     
00308     for (ale= anim_data.first; ale; ale= ale->next) {
00309         const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
00310         const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
00311         
00312         /* check if visible */
00313         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00314              IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00315         {
00316             /* check if anything to show for this channel */
00317             if (ale->datatype != ALE_NONE) {
00318                 adt= ANIM_nla_mapping_get(ac, ale);
00319                 
00320                 /* draw 'keyframes' for each specific datatype */
00321                 switch (ale->datatype) {
00322                     case ALE_ALL:
00323                         draw_summary_channel(v2d, ale->data, y);
00324                         break;
00325                     case ALE_SCE:
00326                         draw_scene_channel(v2d, ads, ale->key_data, y);
00327                         break;
00328                     case ALE_OB:
00329                         draw_object_channel(v2d, ads, ale->key_data, y);
00330                         break;
00331                     case ALE_ACT:
00332                         draw_action_channel(v2d, adt, ale->key_data, y);
00333                         break;
00334                     case ALE_GROUP:
00335                         draw_agroup_channel(v2d, adt, ale->data, y);
00336                         break;
00337                     case ALE_FCURVE:
00338                         draw_fcurve_channel(v2d, adt, ale->key_data, y);
00339                         break;
00340                     case ALE_GPFRAME:
00341                         draw_gpl_channel(v2d, ads, ale->data, y);
00342                         break;
00343                 }
00344             }
00345         }
00346         
00347         y-= ACHANNEL_STEP;
00348     }
00349     
00350     /* free tempolary channels used for drawing */
00351     BLI_freelistN(&anim_data);
00352 
00353     /* black line marking 'current frame' for Time-Slide transform mode */
00354     if (saction->flag & SACTION_MOVING) {
00355         glColor3f(0.0f, 0.0f, 0.0f);
00356         
00357         glBegin(GL_LINES);
00358             glVertex2f(saction->timeslide, v2d->cur.ymin-EXTRA_SCROLL_PAD);
00359             glVertex2f(saction->timeslide, v2d->cur.ymax);
00360         glEnd();
00361     }
00362 }