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