Sound clip NLA Strips for Nexyon
[blender-staging.git] / source / blender / editors / space_nla / nla_draw.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Joshua Leung (major recode)
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 /** \file blender/editors/space_nla/nla_draw.c
30  *  \ingroup spnla
31  */
32
33
34 #include <string.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <math.h>
38 #include <float.h>
39
40 #include "DNA_anim_types.h"
41 #include "DNA_node_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_space_types.h"
44 #include "DNA_windowmanager_types.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_math.h"
48 #include "BLI_rand.h"
49 #include "BLI_dlrbTree.h"
50 #include "BLI_utildefines.h"
51
52 #include "BKE_fcurve.h"
53 #include "BKE_nla.h"
54 #include "BKE_context.h"
55 #include "BKE_screen.h"
56
57 #include "ED_anim_api.h"
58 #include "ED_keyframes_draw.h"
59
60 #include "BIF_gl.h"
61 #include "BIF_glutil.h"
62
63 #include "WM_types.h"
64
65 #include "UI_interface.h"
66 #include "UI_interface_icons.h"
67 #include "UI_resources.h"
68 #include "UI_view2d.h"
69
70
71 #include "nla_intern.h" // own include
72
73
74 /* *********************************************** */
75 /* Strips */
76
77 /* Action-Line ---------------------- */
78
79 /* get colors for drawing Action-Line 
80  * NOTE: color returned includes fine-tuned alpha!
81  */
82 static void nla_action_get_color (AnimData *adt, bAction *act, float color[4])
83 {
84         if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
85                 // greenish color (same as tweaking strip) - hardcoded for now
86                 color[0]= 0.30f;
87                 color[1]= 0.95f;
88                 color[2]= 0.10f;
89                 color[3]= 0.30f;
90         }
91         else {
92                 if (act) {
93                         // reddish color - hardcoded for now    
94                         color[0]= 0.8f;
95                         color[1]= 0.2f;
96                         color[2]= 0.0f;
97                         color[3]= 0.4f;
98                 }
99                 else {
100                         // greyish-red color - hardcoded for now
101                         color[0]= 0.6f;
102                         color[1]= 0.5f;
103                         color[2]= 0.5f;
104                         color[3]= 0.3f;
105                 }
106         }
107         
108         /* when an NLA track is tagged "solo", action doesn't contribute, so shouldn't be as prominent */
109         if (adt && (adt->flag & ADT_NLA_SOLO_TRACK))
110                 color[3] *= 0.15f;
111 }
112
113 /* draw the keyframes in the specified Action */
114 static void nla_action_draw_keyframes (AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
115 {
116         DLRBT_Tree keys;
117         ActKeyColumn *ak;
118         float xscale, f1, f2;
119         float color[4];
120         
121         /* get a list of the keyframes with NLA-scaling applied */
122         BLI_dlrbTree_init(&keys);
123         action_to_keylist(adt, act, &keys, NULL);
124         BLI_dlrbTree_linkedlist_sync(&keys);
125         
126         if ELEM(NULL, act, keys.first)
127                 return;
128         
129         /* draw a darkened region behind the strips 
130          *      - get and reset the background color, this time without the alpha to stand out better 
131          *        (amplified alpha is used instead)
132          */
133         nla_action_get_color(adt, act, color);
134         color[3] *= 2.5f;
135         
136         glColor4fv(color);
137         /*      - draw a rect from the first to the last frame (no extra overlaps for now) 
138          *        that is slightly stumpier than the track background (hardcoded 2-units here)
139          */
140         f1= ((ActKeyColumn *)keys.first)->cfra;
141         f2= ((ActKeyColumn *)keys.last)->cfra;
142         
143         glRectf(f1, ymin+2, f2, ymax-2);
144         
145         
146         /* get View2D scaling factor */
147         UI_view2d_getscale(v2d, &xscale, NULL);
148         
149         /* for now, color is hardcoded to be black */
150         glColor3f(0.0f, 0.0f, 0.0f);
151         
152         /* just draw each keyframe as a simple dot (regardless of the selection status) 
153          *      - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
154          */
155         for (ak= keys.first; ak; ak= ak->next)
156                 draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
157         
158         /* free icons */
159         BLI_dlrbTree_free(&keys);
160 }
161
162 /* Strips (Proper) ---------------------- */
163
164 /* get colors for drawing NLA-Strips */
165 static void nla_strip_get_color_inside (AnimData *adt, NlaStrip *strip, float color[3])
166 {
167         if (strip->type == NLASTRIP_TYPE_TRANSITION) {
168                 /* Transition Clip */
169                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
170                         /* selected - use a bright blue color */
171                         // FIXME: hardcoded temp-hack colors
172                         color[0]= 0.18f;
173                         color[1]= 0.46f;
174                         color[2]= 0.86f;
175                 }
176                 else {
177                         /* normal, unselected strip - use (hardly noticable) blue tinge */
178                         // FIXME: hardcoded temp-hack colors
179                         color[0]= 0.11f;
180                         color[1]= 0.15f;
181                         color[2]= 0.19f;
182                 }
183         }       
184         else if (strip->type == NLASTRIP_TYPE_META) {
185                 /* Meta Clip */
186                 // TODO: should temporary metas get different colors too?
187                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
188                         /* selected - use a bold purple color */
189                         // FIXME: hardcoded temp-hack colors
190                         color[0]= 0.41f;
191                         color[1]= 0.13f;
192                         color[2]= 0.59f;
193                 }
194                 else {
195                         /* normal, unselected strip - use (hardly noticable) dark purple tinge */
196                         // FIXME: hardcoded temp-hack colors
197                         color[0]= 0.20f;
198                         color[1]= 0.15f;
199                         color[2]= 0.26f;
200                 }
201         }
202         else if (strip->type == NLASTRIP_TYPE_SOUND) {
203                 /* Sound Clip */
204                 if (strip->flag & NLASTRIP_FLAG_SELECT) {
205                         /* selected - use a bright teal color */
206                         // FIXME: hardcoded temp-hack colors
207                         color[0]= 0.12f;
208                         color[1]= 0.48f;
209                         color[2]= 0.48f;
210                 }
211                 else {
212                         /* normal, unselected strip - use (hardly noticable) teal tinge */
213                         // FIXME: hardcoded temp-hack colors
214                         color[0]= 0.17f;
215                         color[1]= 0.24f;
216                         color[2]= 0.24f;
217                 }
218         }
219         else {
220                 /* Action Clip (default/normal type of strip) */
221                 if ((strip->flag & NLASTRIP_FLAG_ACTIVE) && (adt && (adt->flag & ADT_NLA_EDIT_ON))) {
222                         /* active strip should be drawn green when it is acting as the tweaking strip.
223                          * however, this case should be skipped for when not in EditMode...
224                          */
225                         // FIXME: hardcoded temp-hack colors
226                         color[0]= 0.3f;
227                         color[1]= 0.95f;
228                         color[2]= 0.1f;
229                 }
230                 else if (strip->flag & NLASTRIP_FLAG_TWEAKUSER) {
231                         /* alert user that this strip is also used by the tweaking track (this is set when going into
232                          * 'editmode' for that strip), since the edits made here may not be what the user anticipated
233                          */
234                         // FIXME: hardcoded temp-hack colors
235                         color[0]= 0.85f;
236                         color[1]= 0.0f;
237                         color[2]= 0.0f;
238                 }
239                 else if (strip->flag & NLASTRIP_FLAG_SELECT) {
240                         /* selected strip - use theme color for selected */
241                         UI_GetThemeColor3fv(TH_STRIP_SELECT, color);
242                 }
243                 else {
244                         /* normal, unselected strip - use standard strip theme color */
245                         UI_GetThemeColor3fv(TH_STRIP, color);
246                 }
247         }
248 }
249
250 /* helper call for drawing influence/time control curves for a given NLA-strip */
251 static void nla_draw_strip_curves (NlaStrip *strip, float yminc, float ymaxc)
252 {
253         const float yheight = ymaxc - yminc;
254         
255         /* drawing color is simply a light-grey */
256         // TODO: is this color suitable?
257         // XXX nasty hacked color for now... which looks quite bad too...
258         glColor3f(0.7f, 0.7f, 0.7f);
259         
260         /* draw with AA'd line */
261         glEnable(GL_LINE_SMOOTH);
262         glEnable(GL_BLEND);
263         
264         /* influence -------------------------- */
265         if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
266                 FCurve *fcu= list_find_fcurve(&strip->fcurves, "influence", 0);
267                 float cfra;
268                 
269                 /* plot the curve (over the strip's main region) */
270                 glBegin(GL_LINE_STRIP);
271                         /* sample at 1 frame intervals, and draw 
272                          *      - min y-val is yminc, max is y-maxc, so clamp in those regions
273                          */
274                         for (cfra= strip->start; cfra <= strip->end; cfra += 1.0f) {
275                                 float y= evaluate_fcurve(fcu, cfra); // assume this to be in 0-1 range
276                                 glVertex2f(cfra, ((y*yheight)+yminc));
277                         }
278                 glEnd(); // GL_LINE_STRIP
279         }
280         else {
281                 /* use blend in/out values only if both aren't zero */
282                 if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f))==0) {
283                         glBegin(GL_LINE_STRIP);
284                                 /* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
285                                 if (IS_EQF(strip->blendin, 0.0f) == 0) {
286                                         glVertex2f(strip->start,                                        yminc);
287                                         glVertex2f(strip->start + strip->blendin,       ymaxc);
288                                 }
289                                 else
290                                         glVertex2f(strip->start, ymaxc);
291                                         
292                                 /* end of strip */
293                                 if (IS_EQF(strip->blendout, 0.0f) == 0) {
294                                         glVertex2f(strip->end - strip->blendout,        ymaxc);
295                                         glVertex2f(strip->end,                                          yminc);
296                                 }
297                                 else
298                                         glVertex2f(strip->end, ymaxc);
299                         glEnd(); // GL_LINE_STRIP
300                 }
301         }
302         
303         /* time -------------------------- */
304         // XXX do we want to draw this curve? in a different color too?
305         
306         /* turn off AA'd lines */
307         glDisable(GL_LINE_SMOOTH);
308         glDisable(GL_BLEND);
309 }
310
311 /* main call for drawing a single NLA-strip */
312 static void nla_draw_strip (SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
313 {
314         short nonSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO)==0);
315         float color[3];
316         
317         /* get color of strip */
318         nla_strip_get_color_inside(adt, strip, color);
319         
320         /* draw extrapolation info first (as backdrop)
321          *      - but this should only be drawn if track has some contribution
322          */
323         if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (nonSolo == 0)) {
324                 /* enable transparency... */
325                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
326                 glEnable(GL_BLEND);
327                 
328                 switch (strip->extendmode) {
329                         /* since this does both sides, only do the 'before' side, and leave the rest to the next case */
330                         case NLASTRIP_EXTEND_HOLD: 
331                                 /* only need to draw here if there's no strip before since 
332                                  * it only applies in such a situation 
333                                  */
334                                 if (strip->prev == NULL) {
335                                         /* set the drawing color to the color of the strip, but with very faint alpha */
336                                         glColor4f(color[0], color[1], color[2], 0.15f);
337                                         
338                                         /* draw the rect to the edge of the screen */
339                                         glBegin(GL_QUADS);
340                                                 glVertex2f(v2d->cur.xmin, yminc);
341                                                 glVertex2f(v2d->cur.xmin, ymaxc);
342                                                 glVertex2f(strip->start, ymaxc);
343                                                 glVertex2f(strip->start, yminc);
344                                         glEnd();
345                                 }
346                                 /* no break needed... */
347                                 
348                         /* this only draws after the strip */
349                         case NLASTRIP_EXTEND_HOLD_FORWARD: 
350                                 /* only need to try and draw if the next strip doesn't occur immediately after */
351                                 if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end)==0)) {
352                                         /* set the drawing color to the color of the strip, but this time less faint */
353                                         glColor4f(color[0], color[1], color[2], 0.3f);
354                                         
355                                         /* draw the rect to the next strip or the edge of the screen */
356                                         glBegin(GL_QUADS);
357                                                 glVertex2f(strip->end, yminc);
358                                                 glVertex2f(strip->end, ymaxc);
359                                                 
360                                                 if (strip->next) {
361                                                         glVertex2f(strip->next->start, ymaxc);
362                                                         glVertex2f(strip->next->start, yminc);
363                                                 }
364                                                 else {
365                                                         glVertex2f(v2d->cur.xmax, ymaxc);
366                                                         glVertex2f(v2d->cur.xmax, yminc);
367                                                 }
368                                         glEnd();
369                                 }
370                                 break;
371                 }
372                 
373                 glDisable(GL_BLEND);
374         }
375         
376         
377         /* draw 'inside' of strip itself */
378         if (nonSolo == 0) {
379                 /* strip is in normal track */
380                 glColor3fv(color);
381                 uiSetRoundBox(15); /* all corners rounded */
382                 
383                 uiDrawBoxShade(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
384         }
385         else {
386                 /* strip is in disabled track - make less visible */
387                 glColor4f(color[0], color[1], color[2], 0.1f);
388                 
389                 glEnable(GL_BLEND);
390                         glRectf(strip->start, yminc, strip->end, ymaxc);
391                 glDisable(GL_BLEND);
392         }
393         
394         
395         /* draw strip's control 'curves'
396          *      - only if user hasn't hidden them...
397          */
398         if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
399                 nla_draw_strip_curves(strip, yminc, ymaxc);
400         
401         
402         /* draw strip outline 
403          *      - color used here is to indicate active vs non-active
404          */
405         if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
406                 /* strip should appear 'sunken', so draw a light border around it */
407                 glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
408         }
409         else {
410                 /* strip should appear to stand out, so draw a dark border around it */
411                 glColor3f(0.0f, 0.0f, 0.0f);
412         }
413         
414         /* - line style: dotted for muted */
415         if (strip->flag & NLASTRIP_FLAG_MUTED)
416                 setlinestyle(4);
417                 
418         /* draw outline */
419         uiDrawBoxShade(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
420         
421         /* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
422         if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f)==0) {
423                 float repeatLen = (strip->actend - strip->actstart) * strip->scale;
424                 int i;
425                 
426                 /* only draw lines for whole-numbered repeats, starting from the first full-repeat
427                  * up to the last full repeat (but not if it lies on the end of the strip)
428                  */
429                 for (i = 1; i < strip->repeat; i++) {
430                         float repeatPos = strip->start + (repeatLen * i);
431                         
432                         /* don't draw if line would end up on or after the end of the strip */
433                         if (repeatPos < strip->end)
434                                 fdrawline(repeatPos, yminc+4, repeatPos, ymaxc-4);
435                 }
436         }
437         /* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
438         else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
439                 NlaStrip *cs;
440                 float y= (ymaxc-yminc)/2.0f + yminc;
441                 
442                 /* only draw first-level of child-strips, but don't draw any lines on the endpoints */
443                 for (cs= strip->strips.first; cs; cs= cs->next) {
444                         /* draw start-line if not same as end of previous (and only if not the first strip) 
445                          *      - on upper half of strip
446                          */
447                         if ((cs->prev) && IS_EQF(cs->prev->end, cs->start)==0)
448                                 fdrawline(cs->start, y, cs->start, ymaxc);
449                                 
450                         /* draw end-line if not the last strip
451                          *      - on lower half of strip
452                          */
453                         if (cs->next) 
454                                 fdrawline(cs->end, yminc, cs->end, y);
455                 }
456         }
457         
458         /* reset linestyle */
459         setlinestyle(0);
460
461
462 /* add the relevant text to the cache of text-strings to draw in pixelspace */
463 static void nla_draw_strip_text (AnimData *adt, NlaTrack *nlt, NlaStrip *strip, int index, View2D *v2d, float yminc, float ymaxc)
464 {
465         short notSolo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO)==0);
466         char str[256];
467         char col[4];
468         float xofs;
469         rctf rect;
470         
471         /* just print the name and the range */
472         if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
473                 sprintf(str, "%d) Temp-Meta", index);
474         }
475         else {
476                 if (strip->flag & NLASTRIP_FLAG_REVERSE)
477                         sprintf(str, "%s", strip->name);
478                 else
479                         sprintf(str, "%s", strip->name);
480         }
481         
482         /* set text color - if colors (see above) are light, draw black text, otherwise draw white */
483         if (strip->flag & (NLASTRIP_FLAG_ACTIVE|NLASTRIP_FLAG_SELECT|NLASTRIP_FLAG_TWEAKUSER)) {
484                 col[0]= col[1]= col[2]= 0;
485         }
486         else {
487                 col[0]= col[1]= col[2]= 255;
488         }
489         
490         /* text opacity depends on whether if there's a solo'd track, this isn't it */
491         if (notSolo == 0)
492                 col[3]= 255;
493         else
494                 col[3]= 128;
495         
496         /* determine the amount of padding required - cannot be constant otherwise looks weird in some cases */
497         if ((strip->end - strip->start) <= 5.0f)
498                 xofs = 0.5f;
499         else
500                 xofs = 1.0f;
501         
502         /* set bounding-box for text 
503          *      - padding of 2 'units' on either side
504          */
505         // TODO: make this centered?
506         rect.xmin= strip->start + xofs;
507         rect.ymin= yminc;
508         rect.xmax= strip->end - xofs;
509         rect.ymax= ymaxc;
510         
511         /* add this string to the cache of texts to draw */
512         UI_view2d_text_cache_rectf(v2d, &rect, str, col);
513 }
514
515 /* add frame extents to cache of text-strings to draw in pixelspace
516  * for now, only used when transforming strips
517  */
518 static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, View2D *v2d, float UNUSED(yminc), float ymaxc)
519 {
520         const float ytol = 1.0f; /* small offset to vertical positioning of text, for legibility */
521         const char col[4] = {220, 220, 220, 255}; /* light grey */
522         char str[16] = "";
523         
524         
525         /* Always draw times above the strip, whereas sequencer drew below + above.
526          * However, we should be fine having everything on top, since these tend to be 
527          * quite spaced out. 
528          *      - 1 dp is compromise between lack of precision (ints only, as per sequencer)
529          *        while also preserving some accuracy, since we do use floats
530          */
531                 /* start frame */
532         sprintf(str, "%.1f", strip->start);
533         UI_view2d_text_cache_add(v2d, strip->start-1.0f, ymaxc+ytol, str, col);
534         
535                 /* end frame */
536         sprintf(str, "%.1f", strip->end);
537         UI_view2d_text_cache_add(v2d, strip->end, ymaxc+ytol, str, col);
538 }
539
540 /* ---------------------- */
541
542 void draw_nla_main_data (bAnimContext *ac, SpaceNla *snla, ARegion *ar)
543 {
544         ListBase anim_data = {NULL, NULL};
545         bAnimListElem *ale;
546         int filter;
547         
548         View2D *v2d= &ar->v2d;
549         float y= 0.0f;
550         size_t items;
551         int height;
552         
553         /* build list of channels to draw */
554         filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
555         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
556         
557         /* Update max-extent of channels here (taking into account scrollers):
558          *      - this is done to allow the channel list to be scrollable, but must be done here
559          *        to avoid regenerating the list again and/or also because channels list is drawn first
560          *      - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
561          *        start of list offset, and the second is as a correction for the scrollers.
562          */
563         height= ((items*NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla)*2));
564         /* don't use totrect set, as the width stays the same 
565          * (NOTE: this is ok here, the configuration is pretty straightforward) 
566          */
567         v2d->tot.ymin= (float)(-height);
568         
569         /* loop through channels, and set up drawing depending on their type  */        
570         y= (float)(-NLACHANNEL_HEIGHT(snla));
571         
572         for (ale= anim_data.first; ale; ale= ale->next) {
573                 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
574                 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
575                 
576                 /* check if visible */
577                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
578                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
579                 {
580                         /* data to draw depends on the type of channel */
581                         switch (ale->type) {
582                                 case ANIMTYPE_NLATRACK:
583                                 {
584                                         AnimData *adt= ale->adt;
585                                         NlaTrack *nlt= (NlaTrack *)ale->data;
586                                         NlaStrip *strip;
587                                         int index;
588                                         
589                                         /* draw each strip in the track (if visible) */
590                                         for (strip=nlt->strips.first, index=1; strip; strip=strip->next, index++) {
591                                                 if (BKE_nlastrip_within_bounds(strip, v2d->cur.xmin, v2d->cur.xmax)) {
592                                                         /* draw the visualisation of the strip */
593                                                         nla_draw_strip(snla, adt, nlt, strip, v2d, yminc, ymaxc);
594                                                         
595                                                         /* add the text for this strip to the cache */
596                                                         nla_draw_strip_text(adt, nlt, strip, index, v2d, yminc, ymaxc);
597                                                         
598                                                         /* if transforming strips (only real reason for temp-metas currently), 
599                                                          * add to the cache the frame numbers of the strip's extents
600                                                          */
601                                                         if (strip->flag & NLASTRIP_FLAG_TEMP_META)
602                                                                 nla_draw_strip_frames_text(nlt, strip, v2d, yminc, ymaxc);
603                                                 }
604                                         }
605                                 }
606                                         break;
607                                         
608                                 case ANIMTYPE_NLAACTION:
609                                 {
610                                         AnimData *adt= ale->adt;
611                                         float color[4];
612                                         
613                                         /* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
614                                          * and a second darker rect within which we draw keyframe indicator dots if there's data
615                                          */
616                                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
617                                         glEnable(GL_BLEND);
618                                                 
619                                         /* get colors for drawing */
620                                         nla_action_get_color(adt, ale->data, color);
621                                         glColor4fv(color);
622                                         
623                                         /* draw slightly shifted up for greater separation from standard channels,
624                                          * but also slightly shorter for some more contrast when viewing the strips
625                                          */
626                                         glRectf(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
627                                         
628                                         /* draw keyframes in the action */
629                                         nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc+NLACHANNEL_SKIP, ymaxc-NLACHANNEL_SKIP);
630                                         
631                                         /* draw 'embossed' lines above and below the strip for effect */
632                                                 /* white base-lines */
633                                         glLineWidth(2.0f);
634                                         glColor4f(1.0f, 1.0f, 1.0f, 0.3);
635                                         fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
636                                         fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
637                                         
638                                                 /* black top-lines */
639                                         glLineWidth(1.0f);
640                                         glColor3f(0.0f, 0.0f, 0.0f);
641                                         fdrawline(v2d->cur.xmin, yminc+NLACHANNEL_SKIP, v2d->cur.xmax, yminc+NLACHANNEL_SKIP);
642                                         fdrawline(v2d->cur.xmin, ymaxc-NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc-NLACHANNEL_SKIP);
643                                         
644                                         glDisable(GL_BLEND);
645                                 }
646                                         break;
647                         }
648                 }
649                 
650                 /* adjust y-position for next one */
651                 y -= NLACHANNEL_STEP(snla);
652         }
653         
654         /* free tempolary channels */
655         BLI_freelistN(&anim_data);
656 }
657
658 /* *********************************************** */
659 /* Channel List */
660
661 /* old code for drawing NLA channels using GL only */
662 // TODO: depreceate this code...
663 static void draw_nla_channel_list_gl (bAnimContext *ac, ListBase *anim_data, View2D *v2d, float y)
664 {
665         SpaceNla *snla = (SpaceNla *)ac->sl;
666         bAnimListElem *ale;
667         float x = 0.0f;
668         
669         /* loop through channels, and set up drawing depending on their type  */        
670         for (ale= anim_data->first; ale; ale= ale->next) {
671                 const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
672                 const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
673                 const float ydatac= (float)(y - 7);
674                 
675                 /* check if visible */
676                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
677                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
678                 {
679                         AnimData *adt = ale->adt;
680                         
681                         short indent= 0, offset= 0, sel= 0, group= 0, nonSolo= 0;
682                         int expand= -1, protect = -1, special= -1, mute = -1;
683                         char name[128];
684                         short doDraw=0;
685                         
686                         /* determine what needs to be drawn */
687                         switch (ale->type) {
688                                 case ANIMTYPE_NLATRACK: /* NLA Track */
689                                 {
690                                         NlaTrack *nlt= (NlaTrack *)ale->data;
691                                         
692                                         /* 'solo' as the 'special' button? */
693                                         if (nlt->flag & NLATRACK_SOLO)
694                                                 special= ICON_SOLO_ON;
695                                         else
696                                                 special= ICON_SOLO_OFF;
697                                                 
698                                         /* if this track is active and we're tweaking it, don't draw these toggles */
699                                         // TODO: need a special macro for this...
700                                         if ( ((nlt->flag & NLATRACK_ACTIVE) && (nlt->flag & NLATRACK_DISABLED)) == 0 ) 
701                                         {
702                                                 if (nlt->flag & NLATRACK_MUTED)
703                                                         mute = ICON_MUTE_IPO_ON;
704                                                 else    
705                                                         mute = ICON_MUTE_IPO_OFF;
706                                                         
707                                                 if (EDITABLE_NLT(nlt))
708                                                         protect = ICON_UNLOCKED;
709                                                 else
710                                                         protect = ICON_LOCKED;
711                                         }
712                                         
713                                         /* is track enabled for solo drawing? */
714                                         if ((adt) && (adt->flag & ADT_NLA_SOLO_TRACK)) {
715                                                 if ((nlt->flag & NLATRACK_SOLO) == 0) {
716                                                         /* tag for special non-solo handling; also hide the mute toggles */
717                                                         nonSolo= 1;
718                                                         mute = 0;
719                                                 }
720                                         }
721                                                 
722                                         sel = SEL_NLT(nlt);
723                                         strcpy(name, nlt->name);
724                                         
725                                         // draw manually still
726                                         doDraw= 1;
727                                 }
728                                         break;
729                                 case ANIMTYPE_NLAACTION: /* NLA Action-Line */
730                                 {
731                                         bAction *act= (bAction *)ale->data;
732                                         
733                                         group = 5;
734                                         
735                                         special = ICON_ACTION;
736                                         
737                                         if (act)
738                                                 sprintf(name, "%s", act->id.name+2);
739                                         else
740                                                 sprintf(name, "<No Action>");
741                                                 
742                                         // draw manually still
743                                         doDraw= 1;
744                                 }
745                                         break;
746                                         
747                                 default: /* handled by standard channel-drawing API */
748                                         // draw backdrops only...
749                                         ANIM_channel_draw(ac, ale, yminc, ymaxc);
750                                         break;
751                         }       
752                         
753                         /* if special types, draw manually for now... */
754                         if (doDraw) {
755                                 if (ale->id) {
756                                         /* special exception for textures */
757                                         if (GS(ale->id->name) == ID_TE) {
758                                                 offset= 14;
759                                                 indent= 1;
760                                         }
761                                         /* special exception for nodetrees */
762                                         else if (GS(ale->id->name) == ID_NT) {
763                                                 bNodeTree *ntree = (bNodeTree *)ale->id;
764                                                 
765                                                 switch (ntree->type) {
766                                                         case NTREE_SHADER:
767                                                         {
768                                                                 /* same as for textures */
769                                                                 offset= 14;
770                                                                 indent= 1;
771                                                         }
772                                                                 break;
773                                                                 
774                                                         case NTREE_TEXTURE:
775                                                         {
776                                                                 /* even more */
777                                                                 offset= 21;
778                                                                 indent= 1;
779                                                         }       
780                                                                 break;
781                                                                 
782                                                         default:
783                                                                 /* normal will do */
784                                                                 offset= 14;
785                                                                 break;
786                                                 }
787                                         }
788                                         else
789                                                 offset= 14;
790                                 }
791                                 else
792                                         offset= 0;
793                                 
794                                 /* now, start drawing based on this information */
795                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
796                                 glEnable(GL_BLEND);
797                                 
798                                 /* draw backing strip behind channel name */
799                                 if (group == 5) {
800                                         /* Action Line */
801                                         // TODO: if tweaking some action, use the same color as for the tweaked track (quick hack done for now)
802                                         if (adt && (adt->flag & ADT_NLA_EDIT_ON)) {
803                                                 // greenish color (same as tweaking strip) - hardcoded for now
804                                                 glColor3f(0.3f, 0.95f, 0.1f);
805                                         }
806                                         else {
807                                                 /* if a track is being solo'd, action is ignored, so draw less boldly (alpha lower) */
808                                                 float alpha = (adt && (adt->flag & ADT_NLA_SOLO_TRACK))? 0.3f : 1.0f;
809                                                 
810                                                 if (ale->data)
811                                                         glColor4f(0.8f, 0.2f, 0.0f, alpha);     // reddish color - hardcoded for now 
812                                                 else
813                                                         glColor4f(0.6f, 0.5f, 0.5f, alpha); // greyish-red color - hardcoded for now
814                                         }
815                                         
816                                         offset += 7 * indent;
817                                         
818                                         /* only on top two corners, to show that this channel sits on top of the preceding ones */
819                                         uiSetRoundBox((1|2)); 
820                                         
821                                         /* draw slightly shifted up vertically to look like it has more separtion from other channels,
822                                          * but we then need to slightly shorten it so that it doesn't look like it overlaps
823                                          */
824                                         uiDrawBox(GL_POLYGON, x+offset,  yminc+NLACHANNEL_SKIP, (float)v2d->cur.xmax, ymaxc+NLACHANNEL_SKIP-1, 8);
825                                         
826                                         /* clear group value, otherwise we cause errors... */
827                                         group = 0;
828                                 }
829                                 else {
830                                         /* NLA tracks - darker color if not solo track when we're showing solo */
831                                         UI_ThemeColorShade(TH_HEADER, ((nonSolo == 0)? 20 : -20));
832                                         
833                                         indent += group;
834                                         offset += 7 * indent;
835                                         glBegin(GL_QUADS);
836                                                 glVertex2f(x+offset, yminc);
837                                                 glVertex2f(x+offset, ymaxc);
838                                                 glVertex2f((float)v2d->cur.xmax, ymaxc);
839                                                 glVertex2f((float)v2d->cur.xmax, yminc);
840                                         glEnd();
841                                 }
842                                 
843                                 /* draw expand/collapse triangle */
844                                 if (expand > 0) {
845                                         UI_icon_draw(x+offset, ydatac, expand);
846                                         offset += 17;
847                                 }
848                                 
849                                 /* draw special icon indicating certain data-types */
850                                 if (special > -1) {
851                                         /* for normal channels */
852                                         UI_icon_draw(x+offset, ydatac, special);
853                                         offset += 17;
854                                 }
855                                 glDisable(GL_BLEND);
856                                 
857                                 /* draw name */
858                                 if (sel)
859                                         UI_ThemeColor(TH_TEXT_HI);
860                                 else
861                                         UI_ThemeColor(TH_TEXT);
862                                 offset += 3;
863                                 UI_DrawString(x+offset, y-4, name);
864                                 
865                                 /* reset offset - for RHS of panel */
866                                 offset = 0;
867                                 
868                                 /* set blending again, as text drawing may clear it */
869                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
870                                 glEnable(GL_BLEND);
871                                 
872                                 /* draw protect 'lock' */
873                                 if (protect > -1) {
874                                         offset = 16;
875                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, protect);
876                                 }
877                                 
878                                 /* draw mute 'eye' */
879                                 if (mute > -1) {
880                                         offset += 16;
881                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, mute);
882                                 }
883                                 
884                                 /* draw NLA-action line 'status-icons' - only when there's an action */
885                                 if ((ale->type == ANIMTYPE_NLAACTION) && (ale->data)) {
886                                         AnimData *adt= ale->adt;
887                                         
888                                         offset += 16;
889                                         
890                                         /* now draw some indicator icons  */
891                                         if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
892                                                 /* toggle for tweaking with mapping/no-mapping (i.e. 'in place editing' toggle) */
893                                                 // for now, use pin icon to symbolise this
894                                                 if (adt->flag & ADT_NLA_EDIT_NOMAP)
895                                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_PINNED);
896                                                 else
897                                                         UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_UNPINNED);
898                                                 
899                                                 fdrawline((float)(v2d->cur.xmax-offset), yminc, 
900                                                                   (float)(v2d->cur.xmax-offset), ymaxc);
901                                                 offset += 16;
902                                                 
903                                                 /* 'tweaking action' indicator - not a button */
904                                                 UI_icon_draw((float)(v2d->cur.xmax-offset), ydatac, ICON_EDIT); 
905                                         }
906                                         else {
907                                                 /* XXX firstly draw a little rect to help identify that it's different from the toggles */
908                                                 glBegin(GL_LINE_LOOP);
909                                                         glVertex2f((float)v2d->cur.xmax-offset-1, y-7);
910                                                         glVertex2f((float)v2d->cur.xmax-offset-1, y+9);
911                                                         glVertex2f((float)v2d->cur.xmax-1, y+9);
912                                                         glVertex2f((float)v2d->cur.xmax-1, y-7);
913                                                 glEnd(); // GL_LINES
914                                                 
915                                                 /* 'push down' icon for normal active-actions */
916                                                 UI_icon_draw((float)v2d->cur.xmax-offset, ydatac, ICON_FREEZE);
917                                         }
918                                 }
919                                 
920                                 glDisable(GL_BLEND);
921                         }
922                 }
923                 
924                 /* adjust y-position for next one */
925                 y -= NLACHANNEL_STEP(snla);
926         }
927 }
928
929 void draw_nla_channel_list (bContext *C, bAnimContext *ac, ARegion *ar)
930 {
931         ListBase anim_data = {NULL, NULL};
932         bAnimListElem *ale;
933         int filter;
934         
935         SpaceNla *snla = (SpaceNla *)ac->sl;
936         View2D *v2d= &ar->v2d;
937         float y= 0.0f;
938         size_t items;
939         int height;
940         
941         /* build list of channels to draw */
942         filter= (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
943         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
944         
945         /* Update max-extent of channels here (taking into account scrollers):
946          *      - this is done to allow the channel list to be scrollable, but must be done here
947          *        to avoid regenerating the list again and/or also because channels list is drawn first
948          *      - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
949          *        start of list offset, and the second is as a correction for the scrollers.
950          */
951         height= ((items*NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla)*2));
952         /* don't use totrect set, as the width stays the same 
953          * (NOTE: this is ok here, the configuration is pretty straightforward) 
954          */
955         v2d->tot.ymin= (float)(-height);
956         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
957         UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
958         
959         /* draw channels */
960         {       /* first pass: backdrops + oldstyle drawing */
961                 y= (float)(-NLACHANNEL_HEIGHT(snla));
962                 
963                 draw_nla_channel_list_gl(ac, &anim_data, v2d, y);
964         }
965         {       /* second pass: UI widgets */
966                 uiBlock *block= uiBeginBlock(C, ar, "NLA channel buttons", UI_EMBOSS);
967                 size_t channel_index = 0;
968                 
969                 y= (float)(-NLACHANNEL_HEIGHT(snla));
970                 
971                 /* set blending again, as may not be set in previous step */
972                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
973                 glEnable(GL_BLEND);
974                 
975                 /* loop through channels, and set up drawing depending on their type  */        
976                 for (ale= anim_data.first; ale; ale= ale->next) {
977                         const float yminc= (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
978                         const float ymaxc= (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
979                         
980                         /* check if visible */
981                         if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
982                                  IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
983                         {
984                                 /* draw all channels using standard channel-drawing API */
985                                 ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
986                         }
987                         
988                         /* adjust y-position for next one */
989                         y -= NLACHANNEL_STEP(snla);
990                         channel_index++;
991                 }
992                 
993                 uiEndBlock(C, block);
994                 uiDrawBlock(C, block);
995                 
996                 glDisable(GL_BLEND);
997         }
998         
999         /* free tempolary channels */
1000         BLI_freelistN(&anim_data);
1001 }
1002
1003 /* *********************************************** */