At last... this merge should finally do the trick!
[blender.git] / source / blender / editors / space_action / action_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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /* System includes ----------------------------------------------------- */
31
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <float.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45
46 /* Types --------------------------------------------------------------- */
47
48 #include "DNA_listBase.h"
49 #include "DNA_anim_types.h"
50 #include "DNA_action_types.h"
51 #include "DNA_armature_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_constraint_types.h"
59 #include "DNA_key_types.h"
60 #include "DNA_lamp_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_userdef_types.h"
63 #include "DNA_gpencil_types.h"
64 #include "DNA_windowmanager_types.h"
65 #include "DNA_world_types.h"
66
67 #include "BKE_action.h"
68 #include "BKE_depsgraph.h"
69 #include "BKE_fcurve.h"
70 #include "BKE_key.h"
71 #include "BKE_material.h"
72 #include "BKE_object.h"
73 #include "BKE_global.h"         // XXX remove me!
74 #include "BKE_context.h"
75 #include "BKE_utildefines.h"
76
77 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
78
79 #include "BIF_gl.h"
80 #include "BIF_glutil.h"
81
82 #include "UI_interface.h"
83 #include "UI_interface_icons.h"
84 #include "UI_resources.h"
85 #include "UI_view2d.h"
86
87 #include "ED_anim_api.h"
88 #include "ED_keyframing.h"
89 #include "ED_keyframes_draw.h"
90 #include "ED_screen.h"
91 #include "ED_space_api.h"
92
93 #if 0 // XXX old includes for reference only
94         #include "BIF_editaction.h"
95         #include "BIF_editkey.h"
96         #include "BIF_editnla.h"
97         #include "BIF_drawgpencil.h"
98         #include "BIF_keyframing.h"
99         #include "BIF_language.h"
100         #include "BIF_space.h"
101         
102         #include "BDR_editcurve.h"
103         #include "BDR_gpencil.h"
104
105         #include "BSE_drawnla.h"
106         #include "BSE_drawipo.h"
107         #include "BSE_drawview.h"
108         #include "BSE_editaction_types.h"
109         #include "BSE_editipo.h"
110         #include "BSE_headerbuttons.h"
111         #include "BSE_time.h"
112         #include "BSE_view.h"
113 #endif // XXX old defines for reference only
114
115 /* XXX */
116 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
117
118 /********************************** Slider Stuff **************************** */
119
120 #if 0 // XXX all of this slider stuff will need a rethink!
121 /* sliders for shapekeys */
122 static void meshactionbuts(SpaceAction *saction, Object *ob, Key *key)
123 {
124         int           i;
125         char          str[64];
126         float         x, y;
127         uiBlock       *block;
128         uiBut             *but;
129         
130         /* lets make the shapekey sliders */
131         
132         /* reset the damn myortho2 or the sliders won't draw/redraw
133          * correctly *grumble*
134          */
135         mywinset(curarea->win);
136         myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
137         
138     sprintf(str, "actionbuttonswin %d", curarea->win);
139     block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS);
140
141         x = ACHANNEL_NAMEWIDTH + 1;
142     y = 0.0f;
143         
144         uiBlockSetEmboss(block, UI_EMBOSSN);
145
146         if (!(G.saction->flag & SACTION_SLIDERS)) {
147                 ACTWIDTH = ACHANNEL_NAMEWIDTH;
148                 but=uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
149                                           ICON_DISCLOSURE_TRI_RIGHT,
150                                           ACHANNEL_NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
151                                           XIC,YIC-2,
152                                           &(G.saction->flag), 0, 0, 0, 0, 
153                                           "Show action window sliders");
154                 /* no hilite, the winmatrix is not correct later on... */
155                 uiButSetFlag(but, UI_NO_HILITE);
156         }
157         else {
158                 but= uiDefIconButBitS(block, TOG, SACTION_SLIDERS, B_REDR, 
159                                           ICON_DISCLOSURE_TRI_DOWN,
160                                           ACHANNEL_NAMEWIDTH - XIC - 5, (short)y + CHANNELHEIGHT,
161                                           XIC,YIC-2,
162                                           &(G.saction->flag), 0, 0, 0, 0, 
163                                           "Hide action window sliders");
164                 /* no hilite, the winmatrix is not correct later on... */
165                 uiButSetFlag(but, UI_NO_HILITE);
166                 
167                 ACTWIDTH = ACHANNEL_NAMEWIDTH + SLIDERWIDTH;
168                 
169                 /* sliders are open so draw them */
170                 BIF_ThemeColor(TH_FACE); 
171                 
172                 glRects(ACHANNEL_NAMEWIDTH,  0,  ACHANNEL_NAMEWIDTH+SLIDERWIDTH,  curarea->winy);
173                 uiBlockSetEmboss(block, UI_EMBOSS);
174                 for (i=1; i < key->totkey; i++) {
175                         make_rvk_slider(block, ob, i, 
176                                                         (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
177                         
178                         y-=CHANNELHEIGHT+CHANNELSKIP;
179                         
180                         /* see sliderval array in editkey.c */
181                         if (i >= 255) break;
182                 }
183         }
184         uiDrawBlock(C, block);
185 }
186
187 static void icu_slider_func(void *voidicu, void *voidignore) 
188 {
189         /* the callback for the icu sliders ... copies the
190          * value from the icu->curval into a bezier at the
191          * right frame on the right ipo curve (creating both the
192          * ipo curve and the bezier if needed).
193          */
194         IpoCurve  *icu= voidicu;
195         BezTriple *bezt=NULL;
196         float cfra, icuval;
197
198         cfra = frame_to_float(CFRA);
199         if (G.saction->pin==0 && OBACT)
200                 cfra= get_action_frame(OBACT, cfra);
201         
202         /* if the ipocurve exists, try to get a bezier
203          * for this frame
204          */
205         bezt = get_bezt_icu_time(icu, &cfra, &icuval);
206
207         /* create the bezier triple if one doesn't exist,
208          * otherwise modify it's value
209          */
210         if (bezt == NULL) {
211                 insert_vert_icu(icu, cfra, icu->curval, 0);
212         }
213         else {
214                 bezt->vec[1][1] = icu->curval;
215         }
216
217         /* make sure the Ipo's are properly processed and
218          * redraw as necessary
219          */
220         sort_time_ipocurve(icu);
221         testhandles_ipocurve(icu);
222         
223         /* nla-update (in case this affects anything) */
224         synchronize_action_strips();
225         
226         /* do redraw pushes, and also the depsgraph flushes */
227         if (OBACT->pose || ob_get_key(OBACT))
228                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC);
229         else
230                 DAG_object_flush_update(G.scene, OBACT, OB_RECALC_OB);
231         
232         allqueue(REDRAWVIEW3D, 0);
233         allqueue(REDRAWACTION, 0);
234         allqueue(REDRAWNLA, 0);
235         allqueue(REDRAWIPO, 0);
236         allspace(REMAKEIPO, 0);
237         allqueue(REDRAWBUTSALL, 0);
238 }
239
240 static void make_icu_slider(uiBlock *block, IpoCurve *icu,
241                                          int x, int y, int w, int h, char *tip)
242 {
243         /* create a slider for the ipo-curve*/
244         uiBut *but;
245         
246         if(icu == NULL) return;
247         
248         if (IS_EQ(icu->slide_max, icu->slide_min)) {
249                 if (IS_EQ(icu->ymax, icu->ymin)) {
250                         if (ELEM(icu->blocktype, ID_CO, ID_KE)) {
251                                 /* hack for constraints and shapekeys (and maybe a few others) */
252                                 icu->slide_min= 0.0;
253                                 icu->slide_max= 1.0;
254                         }
255                         else {
256                                 icu->slide_min= -100;
257                                 icu->slide_max= 100;
258                         }
259                 }
260                 else {
261                         icu->slide_min= icu->ymin;
262                         icu->slide_max= icu->ymax;
263                 }
264         }
265         if (icu->slide_min >= icu->slide_max) {
266                 SWAP(float, icu->slide_min, icu->slide_max);
267         }
268
269         but=uiDefButF(block, NUMSLI, REDRAWVIEW3D, "",
270                                   x, y , w, h,
271                                   &(icu->curval), icu->slide_min, icu->slide_max, 
272                                   10, 2, tip);
273         
274         uiButSetFunc(but, icu_slider_func, icu, NULL);
275         
276         // no hilite, the winmatrix is not correct later on...
277         uiButSetFlag(but, UI_NO_HILITE);
278 }
279
280 /* sliders for ipo-curves of active action-channel */
281 static void action_icu_buts(SpaceAction *saction)
282 {
283         ListBase act_data = {NULL, NULL};
284         bActListElem *ale;
285         int filter;
286         void *data;
287         short datatype;
288         
289         char          str[64];
290         float           x, y;
291         uiBlock       *block;
292
293         /* lets make the action sliders */
294
295         /* reset the damn myortho2 or the sliders won't draw/redraw
296          * correctly *grumble*
297          */
298         mywinset(curarea->win);
299         myortho2(-0.375f, curarea->winx-0.375f, G.v2d->cur.ymin, G.v2d->cur.ymax);
300         
301     sprintf(str, "actionbuttonswin %d", curarea->win);
302     block= uiNewBlock (&curarea->uiblocks, str, UI_EMBOSS);
303
304         x = (float)ACHANNEL_NAMEWIDTH + 1;
305     y = 0.0f;
306         
307         uiBlockSetEmboss(block, UI_EMBOSSN);
308
309         if (G.saction->flag & SACTION_SLIDERS) {
310                 /* sliders are open so draw them */
311                 
312                 /* get editor data */
313                 data= get_action_context(&datatype);
314                 if (data == NULL) return;
315                 
316                 /* build list of channels to draw */
317                 filter= (ACTFILTER_FORDRAWING|ACTFILTER_VISIBLE|ACTFILTER_CHANNELS);
318                 actdata_filter(&act_data, filter, data, datatype);
319                 
320                 /* draw backdrop first */
321                 BIF_ThemeColor(TH_FACE); // change this color... it's ugly
322                 glRects(ACHANNEL_NAMEWIDTH,  (short)G.v2d->cur.ymin,  ACHANNEL_NAMEWIDTH+SLIDERWIDTH,  (short)G.v2d->cur.ymax);
323                 
324                 uiBlockSetEmboss(block, UI_EMBOSS);
325                 for (ale= act_data.first; ale; ale= ale->next) {
326                         const float yminc= y-CHANNELHEIGHT/2;
327                         const float ymaxc= y+CHANNELHEIGHT/2;
328                         
329                         /* check if visible */
330                         if ( IN_RANGE(yminc, G.v2d->cur.ymin, G.v2d->cur.ymax) ||
331                                  IN_RANGE(ymaxc, G.v2d->cur.ymin, G.v2d->cur.ymax) ) 
332                         {
333                                 /* determine what needs to be drawn */
334                                 switch (ale->type) {
335                                         case ACTTYPE_CONCHAN: /* constraint channel */
336                                         {
337                                                 bActionChannel *achan = (bActionChannel *)ale->owner;
338                                                 IpoCurve *icu = (IpoCurve *)ale->key_data;
339                                                 
340                                                 /* only show if owner is selected */
341                                                 if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
342                                                         make_icu_slider(block, icu,
343                                                                                         (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
344                                                                                         "Slider to control current value of Constraint Influence");
345                                                 }
346                                         }
347                                                 break;
348                                         case ACTTYPE_ICU: /* ipo-curve channel */
349                                         {
350                                                 bActionChannel *achan = (bActionChannel *)ale->owner;
351                                                 IpoCurve *icu = (IpoCurve *)ale->key_data;
352                                                 
353                                                 /* only show if owner is selected */
354                                                 if ((ale->ownertype == ACTTYPE_OBJECT) || SEL_ACHAN(achan)) {
355                                                         make_icu_slider(block, icu,
356                                                                                         (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
357                                                                                         "Slider to control current value of IPO-Curve");
358                                                 }
359                                         }
360                                                 break;
361                                         case ACTTYPE_SHAPEKEY: /* shapekey channel */
362                                         {
363                                                 Object *ob= (Object *)ale->id;
364                                                 IpoCurve *icu= (IpoCurve *)ale->key_data;
365                                                 
366                                                 // TODO: only show if object is active 
367                                                 if (icu) {
368                                                         make_icu_slider(block, icu,
369                                                                                 (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-2, 
370                                                                                 "Slider to control ShapeKey");
371                                                 }
372                                                 else if (ob && ale->index) {
373                                                         make_rvk_slider(block, ob, ale->index, 
374                                                                         (int)x, (int)y, SLIDERWIDTH-2, CHANNELHEIGHT-1, "Slider to control Shape Keys");
375                                                 }
376                                         }
377                                                 break;
378                                 }
379                         }
380                         
381                         /* adjust y-position for next one */
382                         y-=CHANNELHEIGHT+CHANNELSKIP;
383                 }
384                 
385                 /* free tempolary channels */
386                 BLI_freelistN(&act_data);
387         }
388         uiDrawBlock(C, block);
389 }
390
391 #endif // XXX all of this slider stuff will need a rethink 
392
393
394 /* ************************************************************************* */
395 /* Channel List */
396
397 /* left hand part */
398 void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar) 
399 {
400         ListBase anim_data = {NULL, NULL};
401         bAnimListElem *ale;
402         int filter;
403         
404         View2D *v2d= &ar->v2d;
405         float x= 0.0f, y= 0.0f;
406         int items, height;
407         
408         /* build list of channels to draw */
409         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
410         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
411         
412         /* Update max-extent of channels here (taking into account scrollers):
413          *      - this is done to allow the channel list to be scrollable, but must be done here
414          *        to avoid regenerating the list again and/or also because channels list is drawn first
415          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
416          *        start of list offset, and the second is as a correction for the scrollers.
417          */
418         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
419         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
420                 /* don't use totrect set, as the width stays the same 
421                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
422                  */
423                 v2d->tot.ymin= (float)(-height);
424         }
425         
426         /* loop through channels, and set up drawing depending on their type  */        
427         y= (float)ACHANNEL_FIRST;
428         
429         for (ale= anim_data.first; ale; ale= ale->next) {
430                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
431                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
432                 
433                 /* check if visible */
434                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
435                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
436                 {
437                         bActionGroup *grp = NULL;
438                         short indent= 0, offset= 0, sel= 0, group= 0;
439                         int expand= -1, protect = -1, special= -1, mute = -1;
440                         char name[128];
441                         
442                         /* determine what needs to be drawn */
443                         switch (ale->type) {
444                                 case ANIMTYPE_SCENE: /* scene */
445                                 {
446                                         Scene *sce= (Scene *)ale->data;
447                                         
448                                         group= 4;
449                                         indent= 0;
450                                         
451                                         special= ICON_SCENE_DATA;
452                                                 
453                                         /* only show expand if there are any channels */
454                                         if (EXPANDED_SCEC(sce))
455                                                 expand= ICON_TRIA_DOWN;
456                                         else
457                                                 expand= ICON_TRIA_RIGHT;
458                                         
459                                         sel = SEL_SCEC(sce);
460                                         strcpy(name, sce->id.name+2);
461                                 }
462                                         break;
463                                 case ANIMTYPE_OBJECT: /* object */
464                                 {
465                                         Base *base= (Base *)ale->data;
466                                         Object *ob= base->object;
467                                         
468                                         group= 4;
469                                         indent= 0;
470                                         
471                                         /* icon depends on object-type */
472                                         if (ob->type == OB_ARMATURE)
473                                                 special= ICON_ARMATURE_DATA;
474                                         else    
475                                                 special= ICON_OBJECT_DATA;
476                                                 
477                                         /* only show expand if there are any channels */
478                                         if (EXPANDED_OBJC(ob))
479                                                 expand= ICON_TRIA_DOWN;
480                                         else
481                                                 expand= ICON_TRIA_RIGHT;
482                                         
483                                         sel = SEL_OBJC(base);
484                                         strcpy(name, ob->id.name+2);
485                                 }
486                                         break;
487                                 case ANIMTYPE_FILLACTD: /* action widget */
488                                 {
489                                         bAction *act= (bAction *)ale->data;
490                                         
491                                         group = 4;
492                                         indent= 1;
493                                         special= ICON_ACTION;
494                                         
495                                         if (EXPANDED_ACTC(act))
496                                                 expand= ICON_TRIA_DOWN;
497                                         else
498                                                 expand= ICON_TRIA_RIGHT;
499                                         
500                                         sel = SEL_ACTC(act);
501                                         strcpy(name, act->id.name+2);
502                                 }
503                                         break;
504                                 case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
505                                 {
506                                         Object *ob = (Object *)ale->data;
507                                         
508                                         group = 4;
509                                         indent = 1;
510                                         special = ICON_MATERIAL_DATA;
511                                         
512                                         if (FILTER_MAT_OBJC(ob))
513                                                 expand = ICON_TRIA_DOWN;
514                                         else
515                                                 expand = ICON_TRIA_RIGHT;
516                                                 
517                                         strcpy(name, "Materials");
518                                 }
519                                         break;
520                                 
521                                 
522                                 case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
523                                 {
524                                         Material *ma = (Material *)ale->data;
525                                         
526                                         group = 0;
527                                         indent = 0;
528                                         special = ICON_MATERIAL_DATA;
529                                         offset = 21;
530                                         
531                                         if (FILTER_MAT_OBJD(ma))
532                                                 expand = ICON_TRIA_DOWN;
533                                         else
534                                                 expand = ICON_TRIA_RIGHT;
535                                         
536                                         strcpy(name, ma->id.name+2);
537                                 }
538                                         break;
539                                 case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
540                                 {
541                                         Lamp *la = (Lamp *)ale->data;
542                                         
543                                         group = 4;
544                                         indent = 1;
545                                         special = ICON_LAMP_DATA;
546                                         
547                                         if (FILTER_LAM_OBJD(la))
548                                                 expand = ICON_TRIA_DOWN;
549                                         else
550                                                 expand = ICON_TRIA_RIGHT;
551                                         
552                                         strcpy(name, la->id.name+2);
553                                 }
554                                         break;
555                                 case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
556                                 {
557                                         Camera *ca = (Camera *)ale->data;
558                                         
559                                         group = 4;
560                                         indent = 1;
561                                         special = ICON_CAMERA_DATA;
562                                         
563                                         if (FILTER_CAM_OBJD(ca))
564                                                 expand = ICON_TRIA_DOWN;
565                                         else
566                                                 expand = ICON_TRIA_RIGHT;
567                                         
568                                         strcpy(name, ca->id.name+2);
569                                 }
570                                         break;
571                                 case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
572                                 {
573                                         Curve *cu = (Curve *)ale->data;
574                                         
575                                         group = 4;
576                                         indent = 1;
577                                         special = ICON_CURVE_DATA;
578                                         
579                                         if (FILTER_CUR_OBJD(cu))
580                                                 expand = ICON_TRIA_DOWN;
581                                         else
582                                                 expand = ICON_TRIA_RIGHT;
583                                         
584                                         strcpy(name, cu->id.name+2);
585                                 }
586                                         break;
587                                 case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
588                                 {
589                                         Key *key= (Key *)ale->data;
590                                         
591                                         group = 4;
592                                         indent = 1;
593                                         special = ICON_SHAPEKEY_DATA; // XXX 
594                                         
595                                         if (FILTER_SKE_OBJD(key))       
596                                                 expand = ICON_TRIA_DOWN;
597                                         else
598                                                 expand = ICON_TRIA_RIGHT;
599                                                 
600                                         //sel = SEL_OBJC(base);
601                                         strcpy(name, "Shape Keys");
602                                 }
603                                         break;
604                                 case ANIMTYPE_DSWOR: /* world (dopesheet) expand widget */
605                                 {
606                                         World *wo= (World *)ale->data;
607                                         
608                                         group = 4;
609                                         indent = 1;
610                                         special = ICON_WORLD_DATA;
611                                         
612                                         if (FILTER_WOR_SCED(wo))        
613                                                 expand = ICON_TRIA_DOWN;
614                                         else
615                                                 expand = ICON_TRIA_RIGHT;
616                                         
617                                         strcpy(name, wo->id.name+2);
618                                 }
619                                         break;
620                                         
621                                 
622                                 case ANIMTYPE_GROUP: /* action group */
623                                 {
624                                         bActionGroup *agrp= (bActionGroup *)ale->data;
625                                         
626                                         group= 2;
627                                         indent= 0;
628                                         special= -1;
629                                         
630                                         if (ale->id) {
631                                                 /* special exception for materials */
632                                                 if (GS(ale->id->name) == ID_MA) 
633                                                         offset= 25;
634                                                 else
635                                                         offset= 14;
636                                         }
637                                         else
638                                                 offset= 0;
639                                         
640                                         /* only show expand if there are any channels */
641                                         if (agrp->channels.first) {
642                                                 if (EXPANDED_AGRP(agrp))
643                                                         expand = ICON_TRIA_DOWN;
644                                                 else
645                                                         expand = ICON_TRIA_RIGHT;
646                                         }
647                                         
648                                         if (EDITABLE_AGRP(agrp))
649                                                 protect = ICON_UNLOCKED;
650                                         else
651                                                 protect = ICON_LOCKED;
652                                                 
653                                         sel = SEL_AGRP(agrp);
654                                         strcpy(name, agrp->name);
655                                 }
656                                         break;
657                                 case ANIMTYPE_FCURVE: /* F-Curve channel */
658                                 {
659                                         FCurve *fcu = (FCurve *)ale->data;
660                                         
661                                         indent = 0;
662                                         
663                                         group= (fcu->grp) ? 1 : 0;
664                                         grp= fcu->grp;
665                                         
666                                         if (ale->id) {
667                                                 /* special exception for materials */
668                                                 if (GS(ale->id->name) == ID_MA) {
669                                                         offset= 21;
670                                                         indent= 1;
671                                                 }
672                                                 else
673                                                         offset= 14;
674                                         }
675                                         else
676                                                 offset= 0;
677                                         
678                                         if (fcu->flag & FCURVE_MUTED)
679                                                 mute = ICON_MUTE_IPO_ON;
680                                         else    
681                                                 mute = ICON_MUTE_IPO_OFF;
682                                                 
683                                         if (fcu->bezt) {
684                                                 if (EDITABLE_FCU(fcu))
685                                                         protect = ICON_UNLOCKED;
686                                                 else
687                                                         protect = ICON_LOCKED;
688                                         }
689                                         else
690                                                 protect = ICON_ZOOMOUT; // XXX editability is irrelevant here, but this icon is temp...
691                                         
692                                         sel = SEL_FCU(fcu);
693                                         
694                                         getname_anim_fcurve(name, ale->id, fcu);
695                                 }
696                                         break;
697                                 
698                                 case ANIMTYPE_SHAPEKEY: /* shapekey channel */
699                                 {
700                                         KeyBlock *kb = (KeyBlock *)ale->data;
701                                         
702                                         indent = 0;
703                                         special = -1;
704                                         
705                                         offset= (ale->id) ? 21 : 0;
706                                         
707                                         if (kb->name[0] == '\0')
708                                                 sprintf(name, "Key %d", ale->index);
709                                         else
710                                                 strcpy(name, kb->name);
711                                 }
712                                         break;
713                                 
714                                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
715                                 {
716                                         bGPdata *gpd = (bGPdata *)ale->data;
717                                         ScrArea *sa = (ScrArea *)ale->owner;
718                                         
719                                         indent = 0;
720                                         group= 3;
721                                         
722                                         /* only show expand if there are any channels */
723                                         if (gpd->layers.first) {
724                                                 if (gpd->flag & GP_DATA_EXPAND)
725                                                         expand = ICON_TRIA_DOWN;
726                                                 else
727                                                         expand = ICON_TRIA_RIGHT;
728                                         }
729                                         
730                                         switch (sa->spacetype) {
731                                                 case SPACE_VIEW3D:
732                                                 {
733                                                         /* this shouldn't cause any overflow... */
734                                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
735                                                         strcpy(name, "3dView");
736                                                         special= ICON_VIEW3D;
737                                                 }
738                                                         break;
739                                                 case SPACE_NODE:
740                                                 {
741                                                         SpaceNode *snode= sa->spacedata.first;
742                                                         char treetype[12];
743                                                         
744                                                         if (snode->treetype == 1)
745                                                                 strcpy(treetype, "Composite");
746                                                         else
747                                                                 strcpy(treetype, "Material");
748                                                         sprintf(name, "Nodes:%s", treetype);
749                                                         
750                                                         special= ICON_NODE;
751                                                 }
752                                                         break;
753                                                 case SPACE_SEQ:
754                                                 {
755                                                         SpaceSeq *sseq= sa->spacedata.first;
756                                                         char imgpreview[10];
757                                                         
758                                                         switch (sseq->mainb) {
759                                                                 case 1:         sprintf(imgpreview, "Image...");        break;
760                                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
761                                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
762                                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
763                                                                 
764                                                                 default:        sprintf(imgpreview, "Sequence");        break;
765                                                         }
766                                                         sprintf(name, "Sequencer:%s", imgpreview);
767                                                         
768                                                         special= ICON_SEQUENCE;
769                                                 }
770                                                         break;
771                                                 case SPACE_IMAGE:
772                                                 {
773                                                         SpaceImage *sima= sa->spacedata.first;
774                                                         
775                                                         if (sima->image)
776                                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
777                                                         else
778                                                                 strcpy(name, "Image:<None>");
779                                                                 
780                                                         special= ICON_IMAGE_COL;
781                                                 }
782                                                         break;
783                                                 
784                                                 default:
785                                                 {
786                                                         sprintf(name, "<Unknown GP-Data Source>");
787                                                         special= -1;
788                                                 }
789                                                         break;
790                                         }
791                                 }
792                                         break;
793                                 case ANIMTYPE_GPLAYER: /* gpencil layer */
794                                 {
795                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
796                                         
797                                         indent = 0;
798                                         special = -1;
799                                         expand = -1;
800                                         group = 1;
801                                         
802                                         if (EDITABLE_GPL(gpl))
803                                                 protect = ICON_UNLOCKED;
804                                         else
805                                                 protect = ICON_LOCKED;
806                                                 
807                                         if (gpl->flag & GP_LAYER_HIDE)
808                                                 mute = ICON_MUTE_IPO_ON;
809                                         else
810                                                 mute = ICON_MUTE_IPO_OFF;
811                                         
812                                         sel = SEL_GPL(gpl);
813                                         BLI_snprintf(name, 32, gpl->info);
814                                 }
815                                         break;
816                         }       
817                         
818                         /* now, start drawing based on this information */
819                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
820                         glEnable(GL_BLEND);
821                         
822                         /* draw backing strip behind channel name */
823                         if (group == 4) {
824                                 /* only used in dopesheet... */
825                                 if (ELEM(ale->type, ANIMTYPE_SCENE, ANIMTYPE_OBJECT)) {
826                                         /* object channel - darker */
827                                         UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
828                                         uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
829                                         gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
830                                 }
831                                 else {
832                                         /* sub-object folders - lighter */
833                                         UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
834                                         
835                                         offset += 7 * indent;
836                                         glBegin(GL_QUADS);
837                                                 glVertex2f(x+offset, yminc);
838                                                 glVertex2f(x+offset, ymaxc);
839                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
840                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
841                                         glEnd();
842                                         
843                                         /* clear group value, otherwise we cause errors... */
844                                         group = 0;
845                                 }
846                         }
847                         else if (group == 3) {
848                                 /* only for gp-data channels */
849                                 UI_ThemeColorShade(TH_GROUP, 20);
850                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
851                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
852                         }
853                         else if (group == 2) {
854                                 /* only for action group channels */
855                                 if (ale->flag & AGRP_ACTIVE)
856                                         UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
857                                 else
858                                         UI_ThemeColorShade(TH_GROUP, 20);
859                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
860                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
861                         }
862                         else {
863                                 /* for normal channels 
864                                  *      - use 3 shades of color group/standard color for 3 indention level
865                                  *      - only use group colors if allowed to, and if actually feasible
866                                  */
867                                 if ( !(saction->flag & SACTION_NODRAWGCOLORS) && 
868                                          (grp) && (grp->customCol) ) 
869                                 {
870                                         char cp[3];
871                                         
872                                         if (indent == 2) {
873                                                 VECCOPY(cp, grp->cs.solid);
874                                         }
875                                         else if (indent == 1) {
876                                                 VECCOPY(cp, grp->cs.select);
877                                         }
878                                         else {
879                                                 VECCOPY(cp, grp->cs.active);
880                                         }
881                                         
882                                         glColor3ub(cp[0], cp[1], cp[2]);
883                                 }
884                                 else
885                                         UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
886                                 
887                                 indent += group;
888                                 offset += 7 * indent;
889                                 glBegin(GL_QUADS);
890                                         glVertex2f(x+offset, yminc);
891                                         glVertex2f(x+offset, ymaxc);
892                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
893                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
894                                 glEnd();
895                         }
896                         
897                         /* draw expand/collapse triangle */
898                         if (expand > 0) {
899                                 UI_icon_draw(x+offset, yminc, expand);
900                                 offset += 17;
901                         }
902                         
903                         /* draw special icon indicating certain data-types */
904                         if (special > -1) {
905                                 if (ELEM(group, 3, 4)) {
906                                         /* for gpdatablock channels */
907                                         UI_icon_draw(x+offset, yminc, special);
908                                         offset += 17;
909                                 }
910                                 else {
911                                         /* for normal channels */
912                                         UI_icon_draw(x+offset, yminc, special);
913                                         offset += 17;
914                                 }
915                         }
916                         glDisable(GL_BLEND);
917                         
918                         /* draw name */
919                         if (sel)
920                                 UI_ThemeColor(TH_TEXT_HI);
921                         else
922                                 UI_ThemeColor(TH_TEXT);
923                         offset += 3;
924                         UI_DrawString(x+offset, y-4, name);
925                         
926                         /* reset offset - for RHS of panel */
927                         offset = 0;
928                         
929                         /* set blending again, as text drawing may clear it */
930                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
931                         glEnable(GL_BLEND);
932                         
933                         /* draw protect 'lock' */
934                         if (protect > -1) {
935                                 offset = 16;
936                                 UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
937                         }
938                         
939                         /* draw mute 'eye' */
940                         if (mute > -1) {
941                                 offset += 16;
942                                 UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
943                         }
944                         glDisable(GL_BLEND);
945                 }
946                 
947                 /* adjust y-position for next one */
948                 y -= ACHANNEL_STEP;
949         }
950         
951         /* free tempolary channels */
952         BLI_freelistN(&anim_data);
953 }
954
955 /* ************************************************************************* */
956 /* Keyframes */
957
958 ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
959 {
960         static ActKeysInc aki;
961         
962         /* no need to set settings if wrong context */
963         if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
964                 return NULL;
965         
966         /* if strip is mapped, store settings */
967         aki.adt= ANIM_nla_mapping_get(ac, ale);
968         
969         if (ac->datatype == ANIMCONT_DOPESHEET)
970                 aki.ads= (bDopeSheet *)ac->data;
971         else
972                 aki.ads= NULL;
973         aki.actmode= ac->datatype;
974                 
975         /* always return pointer... */
976         return &aki;
977 }
978
979
980 /* draw keyframes in each channel */
981 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
982 {
983         ListBase anim_data = {NULL, NULL};
984         bAnimListElem *ale;
985         int filter;
986         
987         View2D *v2d= &ar->v2d;
988         AnimData *adt= NULL;
989         gla2DDrawInfo *di;
990         rcti scr_rct;
991         
992         int act_start, act_end, dummy;
993         int height, items;
994         float y, sta, end;
995         
996         char col1[3], col2[3];
997         char col1a[3], col2a[3];
998         char col1b[3], col2b[3];
999         
1000         
1001         /* get theme colors */
1002         UI_GetThemeColor3ubv(TH_BACK, col2);
1003         UI_GetThemeColor3ubv(TH_HILITE, col1);
1004         UI_GetThemeColor3ubv(TH_GROUP, col2a);
1005         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
1006         
1007         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
1008         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
1009         
1010         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
1011         scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
1012         scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
1013         scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
1014         scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax; 
1015         di= glaBegin2DDraw(&scr_rct, &v2d->cur);
1016
1017         /* if in NLA there's a strip active, map the view */
1018         if (ac->datatype == ANIMCONT_ACTION) {
1019                 adt= ANIM_nla_mapping_get(ac, NULL);
1020                 
1021                 if (adt)
1022                         ANIM_nla_mapping_draw(di, adt, 0);
1023                 
1024                 /* start and end of action itself */
1025                 calc_action_range(ac->data, &sta, &end, 0);
1026                 gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
1027                 gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
1028                 
1029                 if (adt)
1030                         ANIM_nla_mapping_draw(di, adt, 1);
1031         }
1032         
1033         /* build list of channels to draw */
1034         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
1035         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1036         
1037         /* Update max-extent of channels here (taking into account scrollers):
1038          *      - this is done to allow the channel list to be scrollable, but must be done here
1039          *        to avoid regenerating the list again and/or also because channels list is drawn first
1040          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
1041          *        start of list offset, and the second is as a correction for the scrollers.
1042          */
1043         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
1044         /* don't use totrect set, as the width stays the same 
1045          * (NOTE: this is ok here, the configuration is pretty straightforward) 
1046          */
1047         v2d->tot.ymin= (float)(-height);
1048         
1049         /* first backdrop strips */
1050         y= (float)(-ACHANNEL_HEIGHT);
1051         glEnable(GL_BLEND);
1052         
1053         for (ale= anim_data.first; ale; ale= ale->next) {
1054                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1055                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1056                 
1057                 /* check if visible */
1058                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1059                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1060                 {
1061                         int frame1_x, channel_y, sel=0;
1062                         
1063                         /* determine if any need to draw channel */
1064                         if (ale->datatype != ALE_NONE) {
1065                                 /* determine if channel is selected */
1066                                 switch (ale->type) {
1067                                         case ANIMTYPE_SCENE:
1068                                         {
1069                                                 Scene *sce= (Scene *)ale->data;
1070                                                 sel = SEL_SCEC(sce);
1071                                         }
1072                                                 break;
1073                                         case ANIMTYPE_OBJECT:
1074                                         {
1075                                                 Base *base= (Base *)ale->data;
1076                                                 sel = SEL_OBJC(base);
1077                                         }
1078                                                 break;
1079                                         case ANIMTYPE_GROUP:
1080                                         {
1081                                                 bActionGroup *agrp = (bActionGroup *)ale->data;
1082                                                 sel = SEL_AGRP(agrp);
1083                                         }
1084                                                 break;
1085                                         case ANIMTYPE_FCURVE:
1086                                         {
1087                                                 FCurve *fcu = (FCurve *)ale->data;
1088                                                 sel = SEL_FCU(fcu);
1089                                         }
1090                                                 break;
1091                                         case ANIMTYPE_GPLAYER:
1092                                         {
1093                                                 bGPDlayer *gpl = (bGPDlayer *)ale->data;
1094                                                 sel = SEL_GPL(gpl);
1095                                         }
1096                                                 break;
1097                                 }
1098                                 
1099                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
1100                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1101                                         
1102                                         switch (ale->type) {
1103                                                 case ANIMTYPE_SCENE:
1104                                                 case ANIMTYPE_OBJECT:
1105                                                 {
1106                                                         if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
1107                                                         else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
1108                                                 }
1109                                                         break;
1110                                                 
1111                                                 case ANIMTYPE_FILLACTD:
1112                                                 case ANIMTYPE_FILLMATD:
1113                                                 case ANIMTYPE_DSSKEY:
1114                                                 case ANIMTYPE_DSWOR:
1115                                                 {
1116                                                         if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
1117                                                         else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
1118                                                 }
1119                                                         break;
1120                                                 
1121                                                 case ANIMTYPE_GROUP:
1122                                                 {
1123                                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
1124                                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
1125                                                 }
1126                                                         break;
1127                                                 
1128                                                 default:
1129                                                 {
1130                                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1131                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1132                                                 }
1133                                                         break;
1134                                         }
1135                                         
1136                                         /* draw region twice: firstly backdrop, then the current range */
1137                                         glRectf((float)frame1_x,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1138                                         
1139                                         if (ac->datatype == ANIMCONT_ACTION)
1140                                                 glRectf((float)act_start,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)act_end,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1141                                 }
1142                                 else if (ac->datatype == ANIMCONT_SHAPEKEY) {
1143                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
1144                                         
1145                                         /* all frames that have a frame number less than one
1146                                          * get a desaturated orange background
1147                                          */
1148                                         glColor4ub(col2[0], col2[1], col2[2], 0x22);
1149                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1150                                         
1151                                         /* frames one and higher get a saturated orange background */
1152                                         glColor4ub(col2[0], col2[1], col2[2], 0x44);
1153                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1154                                 }
1155                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
1156                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1157                                         
1158                                         /* frames less than one get less saturated background */
1159                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1160                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1161                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1162                                         
1163                                         /* frames one and higher get a saturated background */
1164                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
1165                                         else glColor4ub(col2[0], col2[1], col2[2], 0x44);
1166                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1167                                 }
1168                         }
1169                 }
1170                 
1171                 /*      Increment the step */
1172                 y -= ACHANNEL_STEP;
1173         }               
1174         glDisable(GL_BLEND);
1175         
1176         /* Draw keyframes 
1177          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
1178          *         This is to try to optimise this for heavier data sets
1179          *      2) Keyframes which are out of view horizontally are disregarded 
1180          */
1181         y= (float)(-ACHANNEL_HEIGHT);
1182         
1183         for (ale= anim_data.first; ale; ale= ale->next) {
1184                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1185                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1186                 
1187                 /* check if visible */
1188                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1189                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1190                 {
1191                         /* check if anything to show for this channel */
1192                         if (ale->datatype != ALE_NONE) {
1193                                 ActKeysInc *aki= init_aki_data(ac, ale); 
1194                                 adt= ANIM_nla_mapping_get(ac, ale);
1195                                 
1196                                 if (adt)
1197                                         ANIM_nla_mapping_draw(di, adt, 0);
1198                                 
1199                                 /* draw 'keyframes' for each specific datatype */
1200                                 switch (ale->datatype) {
1201                                         case ALE_SCE:
1202                                                 draw_scene_channel(di, aki, ale->key_data, y);
1203                                                 break;
1204                                         case ALE_OB:
1205                                                 draw_object_channel(di, aki, ale->key_data, y);
1206                                                 break;
1207                                         case ALE_ACT:
1208                                                 draw_action_channel(di, aki, ale->key_data, y);
1209                                                 break;
1210                                         case ALE_GROUP:
1211                                                 draw_agroup_channel(di, aki, ale->data, y);
1212                                                 break;
1213                                         case ALE_FCURVE:
1214                                                 draw_fcurve_channel(di, aki, ale->key_data, y);
1215                                                 break;
1216                                         case ALE_GPFRAME:
1217                                                 draw_gpl_channel(di, aki, ale->data, y);
1218                                                 break;
1219                                 }
1220                                 
1221                                 if (adt) 
1222                                         ANIM_nla_mapping_draw(di, adt, 1);
1223                         }
1224                 }
1225                 
1226                 y-= ACHANNEL_STEP;
1227         }
1228         
1229         /* free tempolary channels used for drawing */
1230         BLI_freelistN(&anim_data);
1231
1232         /* black line marking 'current frame' for Time-Slide transform mode */
1233         if (saction->flag & SACTION_MOVING) {
1234                 int frame1_x;
1235                 
1236                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
1237                 cpack(0x0);
1238                 
1239                 glBegin(GL_LINES);
1240                         glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
1241                         glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
1242                 glEnd();
1243         }
1244         
1245         glaEnd2DDraw(di);
1246 }