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