Blender  V2.59
nla_draw.c
Go to the documentation of this file.
00001 /*
00002  * $Id: nla_draw.c 35824 2011-03-27 17:22:04Z campbellbarton $
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) 2009 Blender Foundation, Joshua Leung
00021  * All rights reserved.
00022  *
00023  * 
00024  * Contributor(s): Joshua Leung (major recode)
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <math.h>
00038 #include <float.h>
00039 
00040 #include "DNA_anim_types.h"
00041 #include "DNA_screen_types.h"
00042 #include "DNA_space_types.h"
00043 #include "DNA_windowmanager_types.h"
00044 
00045 #include "BLI_blenlib.h"
00046 #include "BLI_math.h"
00047 #include "BLI_rand.h"
00048 #include "BLI_dlrbTree.h"
00049 #include "BLI_utildefines.h"
00050 
00051 #include "BKE_fcurve.h"
00052 #include "BKE_nla.h"
00053 #include "BKE_context.h"
00054 #include "BKE_screen.h"
00055 
00056 #include "ED_anim_api.h"
00057 #include "ED_keyframes_draw.h"
00058 
00059 #include "BIF_gl.h"
00060 #include "BIF_glutil.h"
00061 
00062 #include "WM_types.h"
00063 
00064 #include "UI_interface.h"
00065 #include "UI_interface_icons.h"
00066 #include "UI_resources.h"
00067 #include "UI_view2d.h"
00068 
00069 
00070 #include "nla_intern.h" // own include
00071 
00072 
00073 /* *********************************************** */
00074 /* Strips */
00075 
00076 /* Action-Line ---------------------- */
00077 
00078 /* get colors for drawing Action-Line 
00079  * NOTE: color returned includes fine-tuned alpha!
00080  */
00081 static void nla_action_get_color (AnimData *adt, bAction *act, float color[4])
00082 {
00083         // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
00084         if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
00085                 // greenish color (same as tweaking strip) - hardcoded for now
00086                 color[0]= 0.30f;
00087                 color[1]= 0.95f;
00088                 color[2]= 0.10f;
00089                 color[3]= 0.30f;
00090         }
00091         else {
00092                 if (act) {
00093                         // reddish color - hardcoded for now    
00094                         color[0]= 0.8f;
00095                         color[1]= 0.2f;
00096                         color[2]= 0.0f;
00097                         color[3]= 0.4f;
00098                 }
00099                 else {
00100                         // greyish-red color - hardcoded for now
00101                         color[0]= 0.6f;
00102                         color[1]= 0.5f;
00103                         color[2]= 0.5f;
00104                         color[3]= 0.3f;
00105                 }
00106         }
00107 }
00108 
00109 /* draw the keyframes in the specified Action */
00110 static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
00111 {
00112         DLRBT_Tree keys;
00113         ActKeyColumn *ak;
00114         float xscale, f1, f2;
00115         float color[4];
00116         
00117         /* get a list of the keyframes with NLA-scaling applied */
00118         BLI_dlrbTree_init(&keys);
00119         action_to_keylist(adt, act, &keys, NULL);
00120         BLI_dlrbTree_linkedlist_sync(&keys);
00121         
00122         if ELEM(NULL, act, keys.first)
00123                 return;
00124         
00125         /* draw a darkened region behind the strips 
00126          *      - get and reset the background color, this time without the alpha to stand out better 
00127          */
00128         nla_action_get_color(adt, act, color);
00129         glColor3fv(color);
00130         /*      - draw a rect from the first to the last frame (no extra overlaps for now) 
00131          *        that is slightly stumpier than the track background (hardcoded 2-units here)
00132          */
00133         f1= ((ActKeyColumn *)keys.first)->cfra;
00134         f2= ((ActKeyColumn *)keys.last)->cfra;
00135         
00136         glRectf(f1, ymin+2, f2, ymax-2);
00137         
00138         
00139         /* get View2D scaling factor */
00140         UI_view2d_getscale(v2d, &xscale, NULL);
00141         
00142         /* for now, color is hardcoded to be black */
00143         glColor3f(0.0f, 0.0f, 0.0f);
00144         
00145         /* just draw each keyframe as a simple dot (regardless of the selection status) 
00146          *      - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
00147          */
00148         for (ak= keys.first; ak; ak= ak->next)
00149                 draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
00150         
00151         /* free icons */
00152         BLI_dlrbTree_free(&keys);
00153 }
00154 
00155 /* Strips (Proper) ---------------------- */
00156 
00157 /* get colors for drawing NLA-Strips */
00158 static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3])
00159 {
00160         if (strip->type == NLASTRIP_TYPE_TRANSITION) {
00161                 /* Transition Clip */
00162                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
00163                         /* selected - use a bright blue color */
00164                         // FIXME: hardcoded temp-hack colors
00165                         color[0]= 0.18f;
00166                         color[1]= 0.46f;
00167                         color[2]= 0.86f;
00168                 }
00169                 else {
00170                         /* normal, unselected strip - use (hardly noticable) blue tinge */
00171                         // FIXME: hardcoded temp-hack colors
00172                         color[0]= 0.11f;
00173                         color[1]= 0.15f;
00174                         color[2]= 0.19f;
00175                 }
00176         }       
00177         else if (strip->type == NLASTRIP_TYPE_META) {
00178                 /* Meta Clip */
00179                 // TODO: should temporary metas get different colors too?
00180                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
00181                         /* selected - use a bold purple color */
00182                         // FIXME: hardcoded temp-hack colors
00183                         color[0]= 0.41f;
00184                         color[1]= 0.13f;
00185                         color[2]= 0.59f;
00186                 }
00187                 else {
00188                         /* normal, unselected strip - use (hardly noticable) dark purple tinge */
00189                         // FIXME: hardcoded temp-hack colors
00190                         color[0]= 0.20f;
00191                         color[1]= 0.15f;
00192                         color[2]= 0.26f;
00193                 }
00194         }       
00195         else {
00196                 /* Action Clip (default/normal type of strip) */
00197                 if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
00198                         /* active strip should be drawn green when it is acting as the tweaking strip.
00199                          * however, this case should be skipped for when not in EditMode...
00200                          */
00201                         // FIXME: hardcoded temp-hack colors
00202                         color[0]= 0.3f;
00203                         color[1]= 0.95f;
00204                         color[2]= 0.1f;
00205                 }
00206                 else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
00207                         /* alert user that this strip is also used by the tweaking track (this is set when going into
00208                          * 'editmode' for that strip), since the edits made here may not be what the user anticipated
00209                          */
00210                         // FIXME: hardcoded temp-hack colors
00211                         color[0]= 0.85f;
00212                         color[1]= 0.0f;
00213                         color[2]= 0.0f;
00214                 }
00215                 else if (strip->flag & NLASTRIP_FLAG_SELECT) {
00216                         /* selected strip - use theme color for selected */
00217                         UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
00218                 }
00219                 else {
00220                         /* normal, unselected strip - use standard strip theme color */
00221                         UI_GetThemeColor3fv(TH_STRIP, color);
00222                 }
00223         }
00224 }
00225 
00226 /* helper call for drawing influence/time control curves for a given NLA-strip */
00227 static void nla_draw_strip_curves (NlaStrip *strip, float yminc, float ymaxc)
00228 {
00229         const float yheight = ymaxc - yminc;
00230         
00231         /* drawing color is simply a light-grey */
00232         // TODO: is this color suitable?
00233         // XXX nasty hacked color for now... which looks quite bad too...
00234         glColor3f(0.7f, 0.7f, 0.7f);
00235         
00236         /* draw with AA'd line */
00237         glEnable(GL_LINE_SMOOTH);
00238         glEnable(GL_BLEND);
00239         
00240         /* influence -------------------------- */
00241         if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
00242                 FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
00243                 float cfra;
00244                 
00245                 /* plot the curve (over the strip's main region) */
00246                 glBegin(GL_LINE_STRIP);
00247                         /* sample at 1 frame intervals, and draw 
00248                          *      - min y-val is yminc, max is y-maxc, so clamp in those regions
00249                          */
00250                         for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) {
00251                                 float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range
00252                                 glVertex2f(cfra, ((y*yheight)+yminc));
00253                         }
00254                 glEnd(); // GL_LINE_STRIP
00255         }
00256         else {
00257                 /* use blend in/out values only if both aren't zero */
00258                 if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f))==0) {
00259                         glBegin(GL_LINE_STRIP);
00260                                 /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
00261                                 if (IS_EQF(strip->blendin, 0.0f) == 0) {
00262                                         glVertex2f(strip->start,                                        yminc);
00263                                         glVertex2f(strip->start + strip->blendin,       ymaxc);
00264                                 }
00265                                 else
00266                                         glVertex2f(strip->start, ymaxc);
00267                                         
00268                                 /* end of strip */
00269                                 if (IS_EQF(strip->blendout, 0.0f) == 0) {
00270                                         glVertex2f(strip->end - strip->blendout,        ymaxc);
00271                                         glVertex2f(strip->end,                                          yminc);
00272                                 }
00273                                 else
00274                                         glVertex2f(strip->end, ymaxc);
00275                         glEnd(); // GL_LINE_STRIP
00276                 }
00277         }
00278         
00279         /* time -------------------------- */
00280         // XXX do we want to draw this curve? in a different color too?
00281         
00282         /* turn off AA'd lines */
00283         glDisable(GL_LINE_SMOOTH);
00284         glDisable(GL_BLEND);
00285 }
00286 
00287 /* main call for drawing a single NLA-strip */
00288 static void nla_draw_strip (SpaceNla *snla, AnimData *adt, NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
00289 {
00290         float color[3];
00291         
00292         /* get color of strip */
00293         nla_strip_get_color_inside(adt, strip, color);
00294         
00295         /* draw extrapolation info first (as backdrop) */
00296         if (strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
00297                 /* enable transparency... */
00298                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00299                 glEnable(GL_BLEND);
00300                 
00301                 switch (strip->extendmode) {
00302                         /* since this does both sides, only do the 'before' side, and leave the rest to the next case */
00303                         case NLASTRIP_EXTEND_HOLD: 
00304                                 /* only need to draw here if there's no strip before since 
00305                                  * it only applies in such a situation 
00306                                  */
00307                                 if (strip->prev == NULL) {
00308                                         /* set the drawing color to the color of the strip, but with very faint alpha */
00309                                         glColor4f(color[0], color[1], color[2], 0.15f);
00310                                         
00311                                         /* draw the rect to the edge of the screen */
00312                                         glBegin(GL_QUADS);
00313                                                 glVertex2f(v2d->cur.xmin, yminc);
00314                                                 glVertex2f(v2d->cur.xmin, ymaxc);
00315                                                 glVertex2f(strip->start, ymaxc);
00316                                                 glVertex2f(strip->start, yminc);
00317                                         glEnd();
00318                                 }
00319                                 /* no break needed... */
00320                                 
00321                         /* this only draws after the strip */
00322                         case NLASTRIP_EXTEND_HOLD_FORWARD: 
00323                                 /* only need to try and draw if the next strip doesn't occur immediately after */
00324                                 if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end)==0)) {
00325                                         /* set the drawing color to the color of the strip, but this time less faint */
00326                                         glColor4f(color[0], color[1], color[2], 0.3f);
00327                                         
00328                                         /* draw the rect to the next strip or the edge of the screen */
00329                                         glBegin(GL_QUADS);
00330                                                 glVertex2f(strip->end, yminc);
00331                                                 glVertex2f(strip->end, ymaxc);
00332                                                 
00333                                                 if (strip->next) {
00334                                                         glVertex2f(strip->next->start, ymaxc);
00335                                                         glVertex2f(strip->next->start, yminc);
00336                                                 }
00337                                                 else {
00338                                                         glVertex2f(v2d->cur.xmax, ymaxc);
00339                                                         glVertex2f(v2d->cur.xmax, yminc);
00340                                                 }
00341                                         glEnd();
00342                                 }
00343                                 break;
00344                 }
00345                 
00346                 glDisable(GL_BLEND);
00347         }
00348         
00349         /* draw 'inside' of strip itself */
00350         glColor3fv(color);
00351         uiSetRoundBox(15); /* all corners rounded */
00352         uiDrawBoxShade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
00353         
00354         
00355         /* draw strip's control 'curves'
00356          *      - only if user hasn't hidden them...
00357          */
00358         if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
00359                 nla_draw_strip_curves(strip, yminc, ymaxc);
00360         
00361         /* draw strip outline 
00362          *      - color used here is to indicate active vs non-active
00363          */
00364         if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
00365                 /* strip should appear 'sunken', so draw a light border around it */
00366                 glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
00367         }
00368         else {
00369                 /* strip should appear to stand out, so draw a dark border around it */
00370                 glColor3f(0.0f, 0.0f, 0.0f);
00371         }
00372         
00373         /* - line style: dotted for muted */
00374         if (strip->flag & NLASTRIP_FLAG_MUTED)
00375                 setlinestyle(4);
00376                 
00377         /* draw outline */
00378         uiDrawBoxShade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
00379         
00380         /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
00381         if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f)==0) {
00382                 float repeatLen = (strip->actend - strip->actstart) * strip->scale;
00383                 int i;
00384                 
00385                 /* only draw lines for whole-numbered repeats, starting from the first full-repeat
00386                  * up to the last full repeat (but not if it lies on the end of the strip)
00387                  */
00388                 for (i = 1; i < strip->repeat; i++) {
00389                         float repeatPos = strip->start + (repeatLen * i);
00390                         
00391                         /* don't draw if line would end up on or after the end of the strip */
00392                         if (repeatPos < strip->end)
00393                                 fdrawline(repeatPos, yminc+4, repeatPos, ymaxc-4);
00394                 }
00395         }
00396         /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
00397         else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
00398                 NlaStrip *cs;
00399                 float y= (ymaxc-yminc)/2.0f + yminc;
00400                 
00401                 /* only draw first-level of child-strips, but don't draw any lines on the endpoints */
00402                 for (cs= strip->strips.first; cs; cs= cs->next) {
00403                         /* draw start-line if not same as end of previous (and only if not the first strip) 
00404                          *      - on upper half of strip
00405                          */
00406                         if ((cs->prev) && IS_EQF(cs->prev->end, cs->start)==0)
00407                                 fdrawline(cs->start, y, cs->start, ymaxc);
00408                                 
00409                         /* draw end-line if not the last strip
00410                          *      - on lower half of strip
00411                          */
00412                         if (cs->next) 
00413                                 fdrawline(cs->end, yminc, cs->end, y);
00414                 }
00415         }
00416         
00417         /* reset linestyle */
00418         setlinestyle(0);
00419 } 
00420 
00421 /* add the relevant text to the cache of text-strings to draw in pixelspace */
00422 static void nla_draw_strip_text (NlaTrack *UNUSED(nlt), NlaStrip *strip, int UNUSED(index), View2D *v2d, float yminc, float ymaxc)
00423 {
00424         char str[256], dir[3];
00425         char col[4];
00426         rctf rect;
00427         
00428         /* 'dir' - direction that strip is played in */
00429         if (strip->flag & NLASTRIP_FLAG_REVERSE)
00430                 sprintf(dir, "<-");
00431         else
00432                 sprintf(dir, "->");
00433         
00434         /* just print the name and the range */
00435         if (strip->flag & NLASTRIP_FLAG_TEMP_META)
00436                 sprintf(str, "Temp-Meta | %.2f %s %.2f", strip->start, dir, strip->end);
00437         else
00438                 sprintf(str, "%s | %.2f %s %.2f", strip->name, strip->start, dir, strip->end);
00439         
00440         /* set text color - if colors (see above) are light, draw black text, otherwise draw white */
00441         if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) {
00442                 col[0]= col[1]= col[2]= 0;
00443         }
00444         else {
00445                 col[0]= col[1]= col[2]= 255;
00446         }
00447         col[3]= 1.0;
00448 
00449         /* set bounding-box for text 
00450          *      - padding of 2 'units' on either side
00451          */
00452         // TODO: make this centered?
00453         rect.xmin= strip->start + 0.5f;
00454         rect.ymin= yminc;
00455         rect.xmax= strip->end - 0.5f;
00456         rect.ymax= ymaxc;
00457         
00458         /* add this string to the cache of texts to draw*/
00459 
00460         UI_view2d_text_cache_rectf(v2d, &rect, str, col);
00461 }
00462 
00463 /* ---------------------- */
00464 
00465 void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
00466 {
00467         ListBase anim_data = {NULL, NULL};
00468         bAnimListElem *ale;
00469         int filter;
00470         
00471         View2D *v2d= &ar->v2d;
00472         float y= 0.0f;
00473         int items, height;
00474         
00475         /* build list of channels to draw */
00476         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
00477         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00478         
00479         /* Update max-extent of channels here (taking into account scrollers):
00480          *      - this is done to allow the channel list to be scrollable, but must be done here
00481          *        to avoid regenerating the list again and/or also because channels list is drawn first
00482          *      - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
00483          *        start of list offset, and the second is as a correction for the scrollers.
00484          */
00485         height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
00486         /* don't use totrect set, as the width stays the same 
00487          * (NOTE: this is ok here, the configuration is pretty straightforward) 
00488          */
00489         v2d->tot.ymin= (float)(-height);
00490         
00491         /* loop through channels, and set up drawing depending on their type  */        
00492         y= (float)(-NLACHANNEL_HEIGHT);
00493         
00494         for (ale= anim_data.first; ale; ale= ale->next) {
00495                 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
00496                 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
00497                 
00498                 /* check if visible */
00499                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00500                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00501                 {
00502                         /* data to draw depends on the type of channel */
00503                         switch (ale->type) {
00504                                 case ANIMTYPE_NLATRACK:
00505                                 {
00506                                         AnimData *adt= ale->adt;
00507                                         NlaTrack *nlt= (NlaTrack *)ale->data;
00508                                         NlaStrip *strip;
00509                                         int index;
00510                                         
00511                                         /* draw each strip in the track (if visible) */
00512                                         for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) {
00513                                                 if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
00514                                                         /* draw the visualisation of the strip */
00515                                                         nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
00516                                                         
00517                                                         /* add the text for this strip to the cache */
00518                                                         nla_draw_strip_text(nlt, strip, index, v2d, yminc, ymaxc);
00519                                                 }
00520                                         }
00521                                 }
00522                                         break;
00523                                         
00524                                 case ANIMTYPE_NLAACTION:
00525                                 {
00526                                         AnimData *adt= ale->adt;
00527                                         float color[4];
00528                                         
00529                                         /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
00530                                          * and a second darker rect within which we draw keyframe indicator dots if there's data
00531                                          */
00532                                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00533                                         glEnable(GL_BLEND);
00534                                                 
00535                                         /* get colors for drawing */
00536                                         nla_action_get_color(adt, ale->data, color);
00537                                         glColor4fv(color);
00538                                         
00539                                         /* draw slightly shifted up for greater separation from standard channels,
00540                                          * but also slightly shorter for some more contrast when viewing the strips
00541                                          */
00542                                         glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
00543                                         
00544                                         /* draw keyframes in the action */
00545                                         nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP);
00546                                         
00547                                         /* draw 'embossed' lines above and below the strip for effect */
00548                                                 /* white base-lines */
00549                                         glLineWidth(2.0f);
00550                                         glColor4f(1.0f, 1.0f, 1.0f, 0.3);
00551                                         fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
00552                                         fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
00553                                         
00554                                                 /* black top-lines */
00555                                         glLineWidth(1.0f);
00556                                         glColor3f(0.0f, 0.0f, 0.0f);
00557                                         fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
00558                                         fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
00559                                         
00560                                         glDisable(GL_BLEND);
00561                                 }
00562                                         break;
00563                         }
00564                 }
00565                 
00566                 /* adjust y-position for next one */
00567                 y -= NLACHANNEL_STEP;
00568         }
00569         
00570         /* free tempolary channels */
00571         BLI_freelistN(&anim_data);
00572 }
00573 
00574 /* *********************************************** */
00575 /* Channel List */
00576 
00577 /* old code for drawing NLA channels using GL only */
00578 // TODO: depreceate this code...
00579 static void draw_nla_channel_list_gl (bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y)
00580 {
00581         bAnimListElem *ale;
00582         float x = 0.0f;
00583         
00584         /* loop through channels, and set up drawing depending on their type  */        
00585         for (ale= anim_data->first; ale; ale= ale->next) {
00586                 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
00587                 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
00588                 const float ydatac= (float)(y - 7);
00589                 
00590                 /* check if visible */
00591                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00592                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00593                 {
00594                         short indent= 0, offset= 0, sel= 0, group= 0;
00595                         int expand= -1, protect = -1, special= -1, mute = -1;
00596                         char name[128];
00597                         short doDraw=0;
00598                         
00599                         /* determine what needs to be drawn */
00600                         switch (ale->type) {
00601                                 case ANIMTYPE_NLATRACK: /* NLA Track */
00602                                 {
00603                                         NlaTrack *nlt= (NlaTrack *)ale->data;
00604                                         
00605                                         indent= 0;
00606                                         
00607                                         if (ale->id) {
00608                                                 /* special exception for materials and particles */
00609                                                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) {
00610                                                         offset= 21;
00611                                                         indent= 1;
00612                                                 }
00613                                                 else
00614                                                         offset= 14;
00615                                         }
00616                                         else
00617                                                 offset= 0;
00618                                         
00619                                         /* FIXME: 'solo' as the 'special' button?
00620                                          *      - need special icons for these
00621                                          */
00622                                         if (nlt->flag & NLATRACK_SOLO)
00623                                                 special= ICON_LAYER_ACTIVE;
00624                                         else
00625                                                 special= ICON_LAYER_USED;
00626                                                 
00627                                         /* if this track is active and we're tweaking it, don't draw these toggles */
00628                                         // TODO: need a special macro for this...
00629                                         if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 ) 
00630                                         {
00631                                                 if (nlt->flag & NLATRACK_MUTED)
00632                                                         mute = ICON_MUTE_IPO_ON;
00633                                                 else    
00634                                                         mute = ICON_MUTE_IPO_OFF;
00635                                                         
00636                                                 if (EDITABLE_NLT(nlt))
00637                                                         protect = ICON_UNLOCKED;
00638                                                 else
00639                                                         protect = ICON_LOCKED;
00640                                         }
00641                                                 
00642                                         sel = SEL_NLT(nlt);
00643                                         strcpy(name, nlt->name);
00644                                         
00645                                         // draw manually still
00646                                         doDraw= 1;
00647                                 }
00648                                         break;
00649                                 case ANIMTYPE_NLAACTION: /* NLA Action-Line */
00650                                 {
00651                                         bAction *act= (bAction *)ale->data;
00652                                         
00653                                         group = 5;
00654                                         
00655                                         if (ale->id) {
00656                                                 /* special exception for materials and particles */
00657                                                 if (ELEM(GS(ale->id->name),ID_MA,ID_PA)) {
00658                                                         offset= 21;
00659                                                         indent= 1;
00660                                                 }
00661                                                 else
00662                                                         offset= 14;
00663                                         }
00664                                         else
00665                                                 offset= 0;
00666                                         
00667                                         special = ICON_ACTION;
00668                                         
00669                                         if (act)
00670                                                 sprintf(name, "ActAction: <%s>", act->id.name+2);
00671                                         else
00672                                                 sprintf(name, "<No Action>");
00673                                                 
00674                                         // draw manually still
00675                                         doDraw= 1;
00676                                 }
00677                                         break;
00678                                         
00679                                 default: /* handled by standard channel-drawing API */
00680                                         // draw backdrops only...
00681                                         ANIM_channel_draw(ac, ale, yminc, ymaxc);
00682                                         break;
00683                         }       
00684                         
00685                         /* if special types, draw manually for now... */
00686                         if (doDraw) {
00687                                 /* now, start drawing based on this information */
00688                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00689                                 glEnable(GL_BLEND);
00690                                 
00691                                 /* draw backing strip behind channel name */
00692                                 if (group == 5) {
00693                                         /* Action Line */
00694                                         AnimData *adt= ale->adt;
00695                                         
00696                                         // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
00697                                         if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
00698                                                 // greenish color (same as tweaking strip) - hardcoded for now
00699                                                 glColor3f(0.3f, 0.95f, 0.1f);
00700                                         }
00701                                         else {
00702                                                 if (ale->data)
00703                                                         glColor3f(0.8f, 0.2f, 0.0f);    // reddish color - hardcoded for now 
00704                                                 else
00705                                                         glColor3f(0.6f, 0.5f, 0.5f);    // greyish-red color - hardcoded for now
00706                                         }
00707                                         
00708                                         offset += 7 * indent;
00709                                         
00710                                         /* only on top two corners, to show that this channel sits on top of the preceding ones */
00711                                         uiSetRoundBox((1|2)); 
00712                                         
00713                                         /* draw slightly shifted up vertically to look like it has more separtion from other channels,
00714                                          * but we then need to slightly shorten it so that it doesn't look like it overlaps
00715                                          */
00716                                         uiDrawBox(GL_POLYGON, x+offset,  yminc+NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc+NLACHANNEL_SKIP-1, 8);
00717                                         
00718                                         /* clear group value, otherwise we cause errors... */
00719                                         group = 0;
00720                                 }
00721                                 else {
00722                                         /* for normal channels 
00723                                          *      - use 3 shades of color group/standard color for 3 indention level
00724                                          */
00725                                         UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
00726                                         
00727                                         indent += group;
00728                                         offset += 7 * indent;
00729                                         glBegin(GL_QUADS);
00730                                                 glVertex2f(x+offset, yminc);
00731                                                 glVertex2f(x+offset, ymaxc);
00732                                                 glVertex2f((float)v2d->cur.xmax, ymaxc);
00733                                                 glVertex2f((float)v2d->cur.xmax, yminc);
00734                                         glEnd();
00735                                 }
00736                                 
00737                                 /* draw expand/collapse triangle */
00738                                 if (expand > 0) {
00739                                         UI_icon_draw(x+offset, ydatac, expand);
00740                                         offset += 17;
00741                                 }
00742                                 
00743                                 /* draw special icon indicating certain data-types */
00744                                 if (special > -1) {
00745                                         /* for normal channels */
00746                                         UI_icon_draw(x+offset, ydatac, special);
00747                                         offset += 17;
00748                                 }
00749                                 glDisable(GL_BLEND);
00750                                 
00751                                 /* draw name */
00752                                 if (sel)
00753                                         UI_ThemeColor(TH_TEXT_HI);
00754                                 else
00755                                         UI_ThemeColor(TH_TEXT);
00756                                 offset += 3;
00757                                 UI_DrawString(x+offset, y-4, name);
00758                                 
00759                                 /* reset offset - for RHS of panel */
00760                                 offset = 0;
00761                                 
00762                                 /* set blending again, as text drawing may clear it */
00763                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00764                                 glEnable(GL_BLEND);
00765                                 
00766                                 /* draw protect 'lock' */
00767                                 if (protect > -1) {
00768                                         offset = 16;
00769                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, protect);
00770                                 }
00771                                 
00772                                 /* draw mute 'eye' */
00773                                 if (mute > -1) {
00774                                         offset += 16;
00775                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, mute);
00776                                 }
00777                                 
00778                                 /* draw NLA-action line 'status-icons' - only when there's an action */
00779                                 if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
00780                                         AnimData *adt= ale->adt;
00781                                         
00782                                         offset += 16;
00783                                         
00784                                         /* now draw some indicator icons  */
00785                                         if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
00786                                                 /* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
00787                                                 // for now, use pin icon to symbolise this
00788                                                 if (adt->flag & ADT_NLA_EDIT_NOMAP)
00789                                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_PINNED);
00790                                                 else
00791                                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_UNPINNED);
00792                                                 
00793                                                 fdrawline((float)(v2d->cur.xmax-offset), yminc, 
00794                                                                   (float)(v2d->cur.xmax-offset), ymaxc);
00795                                                 offset += 16;
00796                                                 
00797                                                 /* 'tweaking action' indicator - not a button */
00798                                                 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_EDIT); 
00799                                         }
00800                                         else {
00801                                                 /* XXX firstly draw a little rect to help identify that it's different from the toggles */
00802                                                 glBegin(GL_LINE_LOOP);
00803                                                         glVertex2f((float)v2d->cur.xmax-offset-1, y-7);
00804                                                         glVertex2f((float)v2d->cur.xmax-offset-1, y+9);
00805                                                         glVertex2f((float)v2d->cur.xmax-1, y+9);
00806                                                         glVertex2f((float)v2d->cur.xmax-1, y-7);
00807                                                 glEnd(); // GL_LINES
00808                                                 
00809                                                 /* 'push down' icon for normal active-actions */
00810                                                 UI_icon_draw((float)v2d->cur.xmax-offset, ydatac, ICON_FREEZE);
00811                                         }
00812                                 }
00813                                 
00814                                 glDisable(GL_BLEND);
00815                         }
00816                 }
00817                 
00818                 /* adjust y-position for next one */
00819                 y -= NLACHANNEL_STEP;
00820         }
00821 }
00822 
00823 void draw_nla_channel_list (bContext *C, bAnimContext *ac, ARegion *ar)
00824 {
00825         ListBase anim_data = {NULL, NULL};
00826         bAnimListElem *ale;
00827         int filter;
00828         
00829         View2D *v2d= &ar->v2d;
00830         float y= 0.0f;
00831         int items, height;
00832         
00833         /* build list of channels to draw */
00834         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
00835         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
00836         
00837         /* Update max-extent of channels here (taking into account scrollers):
00838          *      - this is done to allow the channel list to be scrollable, but must be done here
00839          *        to avoid regenerating the list again and/or also because channels list is drawn first
00840          *      - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
00841          *        start of list offset, and the second is as a correction for the scrollers.
00842          */
00843         height= ((items*NLACHANNEL_STEP) + (NLACHANNEL_HEIGHT*2));
00844         /* don't use totrect set, as the width stays the same 
00845          * (NOTE: this is ok here, the configuration is pretty straightforward) 
00846          */
00847         v2d->tot.ymin= (float)(-height);
00848         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
00849         UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
00850         
00851         /* draw channels */
00852         {       /* first pass: backdrops + oldstyle drawing */
00853                 y= (float)(-NLACHANNEL_HEIGHT);
00854                 
00855                 draw_nla_channel_list_gl(ac, &anim_data, v2d, y);
00856         }
00857         {       /* second pass: UI widgets */
00858                 uiBlock *block= uiBeginBlock(C, ar, "NLA channel buttons", UI_EMBOSS);
00859                 
00860                 y= (float)(-NLACHANNEL_HEIGHT);
00861                 
00862                 /* set blending again, as may not be set in previous step */
00863                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00864                 glEnable(GL_BLEND);
00865                 
00866                 /* loop through channels, and set up drawing depending on their type  */        
00867                 for (ale= anim_data.first; ale; ale= ale->next) {
00868                         const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF);
00869                         const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF);
00870                         
00871                         /* check if visible */
00872                         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
00873                                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
00874                         {
00875                                 /* draw all channels using standard channel-drawing API */
00876                                 ANIM_channel_draw_widgets(ac, ale, block, yminc, ymaxc);
00877                         }
00878                         
00879                         /* adjust y-position for next one */
00880                         y -= NLACHANNEL_STEP;
00881                 }
00882                 
00883                 uiEndBlock(C, block);
00884                 uiDrawBlock(C, block);
00885                 
00886                 glDisable(GL_BLEND);
00887         }
00888         
00889         /* free tempolary channels */
00890         BLI_freelistN(&anim_data);
00891 }
00892 
00893 /* *********************************************** */