Blender V2.61 - r43446

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