0912edb70767219ca687e2dca3ae17202164d378
[blender-staging.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         
406         View2D *v2d= &ar->v2d;
407         float x= 0.0f, y= 0.0f;
408         int items, height;
409         
410         /* build list of channels to draw */
411         filter= (ANIMFILTER_FORDRAWING|ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
412         items= ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
413         
414         /* Update max-extent of channels here (taking into account scrollers):
415          *      - this is done to allow the channel list to be scrollable, but must be done here
416          *        to avoid regenerating the list again and/or also because channels list is drawn first
417          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
418          *        start of list offset, and the second is as a correction for the scrollers.
419          */
420         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
421         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
422                 /* don't use totrect set, as the width stays the same 
423                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
424                  */
425                 v2d->tot.ymin= (float)(-height);
426         }
427         
428         /* loop through channels, and set up drawing depending on their type  */        
429         y= (float)ACHANNEL_FIRST;
430         
431         for (ale= anim_data.first; ale; ale= ale->next) {
432                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
433                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
434                 
435                 /* check if visible */
436                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
437                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
438                 {
439                         bActionGroup *grp = NULL;
440                         short indent= 0, offset= 0, sel= 0, group= 0;
441                         int expand= -1, protect = -1, special= -1, mute = -1;
442                         char name[64];
443                         
444                         /* determine what needs to be drawn */
445                         switch (ale->type) {
446                                 case ANIMTYPE_OBJECT: /* object */
447                                 {
448                                         Base *base= (Base *)ale->data;
449                                         Object *ob= base->object;
450                                         
451                                         group= 4;
452                                         indent= 0;
453                                         
454                                         /* icon depends on object-type */
455                                         if (ob->type == OB_ARMATURE)
456                                                 special= ICON_ARMATURE;
457                                         else    
458                                                 special= ICON_OBJECT;
459                                                 
460                                         /* only show expand if there are any channels */
461                                         if (EXPANDED_OBJC(ob))
462                                                 expand= ICON_TRIA_DOWN;
463                                         else
464                                                 expand= ICON_TRIA_RIGHT;
465                                         
466                                         sel = SEL_OBJC(base);
467                                         strcpy(name, ob->id.name+2);
468                                 }
469                                         break;
470                                 case ANIMTYPE_FILLACTD: /* action widget */
471                                 {
472                                         bAction *act= (bAction *)ale->data;
473                                         
474                                         group = 4;
475                                         indent= 1;
476                                         special= ICON_ACTION;
477                                         
478                                         if (EXPANDED_ACTC(act))
479                                                 expand= ICON_TRIA_DOWN;
480                                         else
481                                                 expand= ICON_TRIA_RIGHT;
482                                         
483                                         sel = SEL_ACTC(act);
484                                         strcpy(name, "Action");
485                                 }
486                                         break;
487                                 case ANIMTYPE_FILLIPOD: /* ipo (dopesheet) expand widget */
488                                 {
489                                         Object *ob = (Object *)ale->data;
490                                         
491                                         group = 4;
492                                         indent = 1;
493                                         special = ICON_IPO;
494                                         
495                                         if (FILTER_IPO_OBJC(ob))        
496                                                 expand = ICON_TRIA_DOWN;
497                                         else
498                                                 expand = ICON_TRIA_RIGHT;
499                                         
500                                         //sel = SEL_OBJC(base);
501                                         strcpy(name, "IPO Curves");
502                                 }
503                                         break;
504                                 case ANIMTYPE_FILLCOND: /* constraint channels (dopesheet) expand widget */
505                                 {
506                                         Object *ob = (Object *)ale->data;
507                                         
508                                         group = 4;
509                                         indent = 1;
510                                         special = ICON_CONSTRAINT;
511                                         
512                                         if (FILTER_CON_OBJC(ob))        
513                                                 expand = ICON_TRIA_DOWN;
514                                         else
515                                                 expand = ICON_TRIA_RIGHT;
516                                                 
517                                         //sel = SEL_OBJC(base);
518                                         strcpy(name, "Constraints");
519                                 }
520                                         break;
521                                 case ANIMTYPE_FILLMATD: /* object materials (dopesheet) expand widget */
522                                 {
523                                         Object *ob = (Object *)ale->data;
524                                         
525                                         group = 4;
526                                         indent = 1;
527                                         special = ICON_MATERIAL;
528                                         
529                                         if (FILTER_MAT_OBJC(ob))
530                                                 expand = ICON_TRIA_DOWN;
531                                         else
532                                                 expand = ICON_TRIA_RIGHT;
533                                                 
534                                         strcpy(name, "Materials");
535                                 }
536                                         break;
537                                 
538                                 
539                                 case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
540                                 {
541                                         Material *ma = (Material *)ale->data;
542                                         
543                                         group = 0;
544                                         indent = 0;
545                                         special = ICON_MATERIAL;
546                                         offset = 21;
547                                         
548                                         if (FILTER_MAT_OBJD(ma))
549                                                 expand = ICON_TRIA_DOWN;
550                                         else
551                                                 expand = ICON_TRIA_RIGHT;
552                                         
553                                         strcpy(name, ma->id.name+2);
554                                 }
555                                         break;
556                                 case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
557                                 {
558                                         Lamp *la = (Lamp *)ale->data;
559                                         
560                                         group = 4;
561                                         indent = 1;
562                                         special = ICON_LAMP;
563                                         
564                                         if (FILTER_LAM_OBJD(la))
565                                                 expand = ICON_TRIA_DOWN;
566                                         else
567                                                 expand = ICON_TRIA_RIGHT;
568                                         
569                                         strcpy(name, la->id.name+2);
570                                 }
571                                         break;
572                                 case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
573                                 {
574                                         Camera *ca = (Camera *)ale->data;
575                                         
576                                         group = 4;
577                                         indent = 1;
578                                         special = ICON_CAMERA;
579                                         
580                                         if (FILTER_CAM_OBJD(ca))
581                                                 expand = ICON_TRIA_DOWN;
582                                         else
583                                                 expand = ICON_TRIA_RIGHT;
584                                         
585                                         strcpy(name, ca->id.name+2);
586                                 }
587                                         break;
588                                 case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
589                                 {
590                                         Curve *cu = (Curve *)ale->data;
591                                         
592                                         group = 4;
593                                         indent = 1;
594                                         special = ICON_CURVE;
595                                         
596                                         if (FILTER_CUR_OBJD(cu))
597                                                 expand = ICON_TRIA_DOWN;
598                                         else
599                                                 expand = ICON_TRIA_RIGHT;
600                                         
601                                         strcpy(name, cu->id.name+2);
602                                 }
603                                         break;
604                                 case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
605                                 {
606                                         Key *key= (Key *)ale->data;
607                                         
608                                         group = 4;
609                                         indent = 1;
610                                         special = ICON_EDIT;
611                                         
612                                         if (FILTER_SKE_OBJD(key))       
613                                                 expand = ICON_TRIA_DOWN;
614                                         else
615                                                 expand = ICON_TRIA_RIGHT;
616                                                 
617                                         //sel = SEL_OBJC(base);
618                                         strcpy(name, "Shape Keys");
619                                 }
620                                         break;
621                                         
622                                 
623                                 case ANIMTYPE_GROUP: /* action group */
624                                 {
625                                         bActionGroup *agrp= (bActionGroup *)ale->data;
626                                         
627                                         group= 2;
628                                         indent= 0;
629                                         special= -1;
630                                         
631                                         offset= (ale->id) ? 21 : 0;
632                                         
633                                         /* only show expand if there are any channels */
634                                         if (agrp->channels.first) {
635                                                 if (EXPANDED_AGRP(agrp))
636                                                         expand = ICON_TRIA_DOWN;
637                                                 else
638                                                         expand = ICON_TRIA_RIGHT;
639                                         }
640                                         
641                                         if (EDITABLE_AGRP(agrp))
642                                                 protect = ICON_UNLOCKED;
643                                         else
644                                                 protect = ICON_LOCKED;
645                                                 
646                                         sel = SEL_AGRP(agrp);
647                                         strcpy(name, agrp->name);
648                                 }
649                                         break;
650                                 case ANIMTYPE_ACHAN: /* action channel */
651                                 {
652                                         bActionChannel *achan= (bActionChannel *)ale->data;
653                                         
654                                         group= (ale->grp) ? 1 : 0;
655                                         grp= ale->grp;
656                                         
657                                         indent = 0;
658                                         special = -1;
659                                         
660                                         offset= (ale->id) ? 21 : 0;
661                                         
662                                         if (EXPANDED_ACHAN(achan))
663                                                 expand = ICON_TRIA_DOWN;
664                                         else
665                                                 expand = ICON_TRIA_RIGHT;
666                                                 
667                                         if (EDITABLE_ACHAN(achan))
668                                                 protect = ICON_UNLOCKED;
669                                         else
670                                                 protect = ICON_LOCKED;
671                                                 
672                                         if (achan->ipo) {
673                                                 if (achan->ipo->muteipo)
674                                                         mute = ICON_MUTE_IPO_ON;
675                                                 else
676                                                         mute = ICON_MUTE_IPO_OFF;
677                                         }
678                                         
679                                         sel = SEL_ACHAN(achan);
680                                         strcpy(name, achan->name);
681                                 }
682                                         break;
683                                 case ANIMTYPE_CONCHAN: /* constraint channel */
684                                 {
685                                         bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
686                                         
687                                         group= (ale->grp) ? 1 : 0;
688                                         grp= ale->grp;
689                                         
690                                         if (ale->id) {
691                                                 if (ale->ownertype == ANIMTYPE_ACHAN) {
692                                                         /* for constraint channels under Action in Dopesheet */
693                                                         indent= 2;
694                                                         offset= 21;
695                                                 }
696                                                 else {
697                                                         /* for constraint channels under Object in Dopesheet */
698                                                         indent= 2;
699                                                         offset = 0;
700                                                 }
701                                         }
702                                         else {
703                                                 /* for normal constraint channels in Action Editor */
704                                                 indent= 2;
705                                                 offset= 0;
706                                         }
707                                         
708                                         if (EDITABLE_CONCHAN(conchan))
709                                                 protect = ICON_UNLOCKED;
710                                         else
711                                                 protect = ICON_LOCKED;
712                                                 
713                                         if (conchan->ipo) {
714                                                 if (conchan->ipo->muteipo)
715                                                         mute = ICON_MUTE_IPO_ON;
716                                                 else
717                                                         mute = ICON_MUTE_IPO_OFF;
718                                         }
719                                         
720                                         sel = SEL_CONCHAN(conchan);
721                                         strcpy(name, conchan->name);
722                                 }
723                                         break;
724                                 case ANIMTYPE_ICU: /* ipo-curve channel */
725                                 {
726                                         IpoCurve *icu = (IpoCurve *)ale->data;
727                                         
728                                         indent = 2;
729                                         protect = -1; // for now, until this can be supported by others
730                                         
731                                         group= (ale->grp) ? 1 : 0;
732                                         grp= ale->grp;
733                                         
734                                         if (ale->id) {
735                                                 if ((GS(ale->id->name)==ID_MA) || (ale->ownertype == ANIMTYPE_ACHAN))
736                                                         offset= 21;
737                                                 else
738                                                         offset= 0;
739                                         }
740                                         else
741                                                 offset= 0;
742                                         
743                                         if (icu->flag & IPO_MUTE)
744                                                 mute = ICON_MUTE_IPO_ON;
745                                         else    
746                                                 mute = ICON_MUTE_IPO_OFF;
747                                                 
748                                         if (EDITABLE_ICU(icu))
749                                                 protect = ICON_UNLOCKED;
750                                         else
751                                                 protect = ICON_LOCKED;
752                                         
753                                         sel = SEL_ICU(icu);
754                                         if (saction->pin)
755                                                 strcpy(name, getname_ipocurve(icu, NULL)); // xxx func to eventually eliminate
756                                         else
757                                                 strcpy(name, getname_ipocurve(icu, ac->obact)); // xxx func to eventually eliminate
758                                 }
759                                         break;
760                                 case ANIMTYPE_FILLIPO: /* ipo expand widget */
761                                 {
762                                         bActionChannel *achan = (bActionChannel *)ale->data;
763                                         
764                                         indent = 1;
765                                         special = geticon_ipo_blocktype(achan->ipo->blocktype); // xxx func to eventually eliminate
766                                         
767                                         group= (ale->grp) ? 1 : 0;
768                                         grp= ale->grp;
769                                         
770                                         offset= (ale->id) ? 21 : 0;
771                                         
772                                         if (FILTER_IPO_ACHAN(achan))    
773                                                 expand = ICON_TRIA_DOWN;
774                                         else
775                                                 expand = ICON_TRIA_RIGHT;
776                                         
777                                         sel = SEL_ACHAN(achan);
778                                         strcpy(name, "IPO Curves");
779                                 }
780                                         break;
781                                 case ANIMTYPE_FILLCON: /* constraint expand widget */
782                                 {
783                                         bActionChannel *achan = (bActionChannel *)ale->data;
784                                         
785                                         indent = 1;
786                                         special = ICON_CONSTRAINT;
787                                         
788                                         group= (ale->grp) ? 1 : 0;
789                                         grp= ale->grp;
790                                         
791                                         offset= (ale->id) ? 21 : 0;
792                                         
793                                         if (FILTER_CON_ACHAN(achan))    
794                                                 expand = ICON_TRIA_DOWN;
795                                         else
796                                                 expand = ICON_TRIA_RIGHT;
797                                                 
798                                         sel = SEL_ACHAN(achan);
799                                         strcpy(name, "Constraint");
800                                 }
801                                         break;
802                                 
803                                 
804                                 case ANIMTYPE_SHAPEKEY: /* shapekey channel */
805                                 {
806                                         KeyBlock *kb = (KeyBlock *)ale->data;
807                                         
808                                         indent = 0;
809                                         special = -1;
810                                         
811                                         offset= (ale->id) ? 21 : 0;
812                                         
813                                         if (kb->name[0] == '\0')
814                                                 sprintf(name, "Key %d", ale->index);
815                                         else
816                                                 strcpy(name, kb->name);
817                                 }
818                                         break;
819                                 
820                                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
821                                 {
822                                         bGPdata *gpd = (bGPdata *)ale->data;
823                                         ScrArea *sa = (ScrArea *)ale->owner;
824                                         
825                                         indent = 0;
826                                         group= 3;
827                                         
828                                         /* only show expand if there are any channels */
829                                         if (gpd->layers.first) {
830                                                 if (gpd->flag & GP_DATA_EXPAND)
831                                                         expand = ICON_TRIA_DOWN;
832                                                 else
833                                                         expand = ICON_TRIA_RIGHT;
834                                         }
835                                         
836                                         switch (sa->spacetype) {
837                                                 case SPACE_VIEW3D:
838                                                 {
839                                                         /* this shouldn't cause any overflow... */
840                                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
841                                                         strcpy(name, "3dView");
842                                                         special= ICON_VIEW3D;
843                                                 }
844                                                         break;
845                                                 case SPACE_NODE:
846                                                 {
847                                                         SpaceNode *snode= sa->spacedata.first;
848                                                         char treetype[12];
849                                                         
850                                                         if (snode->treetype == 1)
851                                                                 strcpy(treetype, "Composite");
852                                                         else
853                                                                 strcpy(treetype, "Material");
854                                                         sprintf(name, "Nodes:%s", treetype);
855                                                         
856                                                         special= ICON_NODE;
857                                                 }
858                                                         break;
859                                                 case SPACE_SEQ:
860                                                 {
861                                                         SpaceSeq *sseq= sa->spacedata.first;
862                                                         char imgpreview[10];
863                                                         
864                                                         switch (sseq->mainb) {
865                                                                 case 1:         sprintf(imgpreview, "Image...");        break;
866                                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
867                                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
868                                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
869                                                                 
870                                                                 default:        sprintf(imgpreview, "Sequence");        break;
871                                                         }
872                                                         sprintf(name, "Sequencer:%s", imgpreview);
873                                                         
874                                                         special= ICON_SEQUENCE;
875                                                 }
876                                                         break;
877                                                 case SPACE_IMAGE:
878                                                 {
879                                                         SpaceImage *sima= sa->spacedata.first;
880                                                         
881                                                         if (sima->image)
882                                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
883                                                         else
884                                                                 strcpy(name, "Image:<None>");
885                                                                 
886                                                         special= ICON_IMAGE_COL;
887                                                 }
888                                                         break;
889                                                 
890                                                 default:
891                                                 {
892                                                         sprintf(name, "<Unknown GP-Data Source>");
893                                                         special= -1;
894                                                 }
895                                                         break;
896                                         }
897                                 }
898                                         break;
899                                 case ANIMTYPE_GPLAYER: /* gpencil layer */
900                                 {
901                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
902                                         
903                                         indent = 0;
904                                         special = -1;
905                                         expand = -1;
906                                         group = 1;
907                                         
908                                         if (EDITABLE_GPL(gpl))
909                                                 protect = ICON_UNLOCKED;
910                                         else
911                                                 protect = ICON_LOCKED;
912                                                 
913                                         if (gpl->flag & GP_LAYER_HIDE)
914                                                 mute = ICON_MUTE_IPO_ON;
915                                         else
916                                                 mute = ICON_MUTE_IPO_OFF;
917                                         
918                                         sel = SEL_GPL(gpl);
919                                         BLI_snprintf(name, 32, gpl->info);
920                                 }
921                                         break;
922                         }       
923                         
924                         /* now, start drawing based on this information */
925                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
926                         glEnable(GL_BLEND);
927                         
928                         /* draw backing strip behind channel name */
929                         if (group == 4) {
930                                 /* only used in dopesheet... */
931                                 if (ale->type == ANIMTYPE_OBJECT) {
932                                         /* object channel - darker */
933                                         UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
934                                         uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
935                                         gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
936                                 }
937                                 else {
938                                         /* sub-object folders - lighter */
939                                         UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
940                                         
941                                         offset += 7 * indent;
942                                         glBegin(GL_QUADS);
943                                                 glVertex2f(x+offset, yminc);
944                                                 glVertex2f(x+offset, ymaxc);
945                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
946                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
947                                         glEnd();
948                                         
949                                         /* clear group value, otherwise we cause errors... */
950                                         group = 0;
951                                 }
952                         }
953                         else if (group == 3) {
954                                 /* only for gp-data channels */
955                                 UI_ThemeColorShade(TH_GROUP, 20);
956                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
957                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
958                         }
959                         else if (group == 2) {
960                                 /* only for action group channels */
961                                 if (ale->flag & AGRP_ACTIVE)
962                                         UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
963                                 else
964                                         UI_ThemeColorShade(TH_GROUP, 20);
965                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
966                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
967                         }
968                         else {
969                                 /* for normal channels 
970                                  *      - use 3 shades of color group/standard color for 3 indention level
971                                  *      - only use group colors if allowed to, and if actually feasible
972                                  */
973                                 if ( !(saction->flag & SACTION_NODRAWGCOLORS) && 
974                                          (grp) && (grp->customCol) ) 
975                                 {
976                                         char cp[3];
977                                         
978                                         if (indent == 2) {
979                                                 VECCOPY(cp, grp->cs.solid);
980                                         }
981                                         else if (indent == 1) {
982                                                 VECCOPY(cp, grp->cs.select);
983                                         }
984                                         else {
985                                                 VECCOPY(cp, grp->cs.active);
986                                         }
987                                         
988                                         glColor3ub(cp[0], cp[1], cp[2]);
989                                 }
990                                 else
991                                         UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
992                                 
993                                 indent += group;
994                                 offset += 7 * indent;
995                                 glBegin(GL_QUADS);
996                                         glVertex2f(x+offset, yminc);
997                                         glVertex2f(x+offset, ymaxc);
998                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
999                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
1000                                 glEnd();
1001                         }
1002                         
1003                         /* draw expand/collapse triangle */
1004                         if (expand > 0) {
1005                                 UI_icon_draw(x+offset, yminc, expand);
1006                                 offset += 17;
1007                         }
1008                         
1009                         /* draw special icon indicating certain data-types */
1010                         if (special > -1) {
1011                                 if (ELEM(group, 3, 4)) {
1012                                         /* for gpdatablock channels */
1013                                         UI_icon_draw(x+offset, yminc, special);
1014                                         offset += 17;
1015                                 }
1016                                 else {
1017                                         /* for ipo/constraint channels */
1018                                         UI_icon_draw(x+offset, yminc, special);
1019                                         offset += 17;
1020                                 }
1021                         }
1022                         glDisable(GL_BLEND);
1023                         
1024                         /* draw name */
1025                         if (sel)
1026                                 UI_ThemeColor(TH_TEXT_HI);
1027                         else
1028                                 UI_ThemeColor(TH_TEXT);
1029                         offset += 3;
1030                         ui_rasterpos_safe(x+offset, y-4, 1.0f);
1031                         UI_DrawString(G.font, name, 0);
1032                         
1033                         /* reset offset - for RHS of panel */
1034                         offset = 0;
1035                         
1036                         /* set blending again, as text drawing may clear it */
1037                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1038                         glEnable(GL_BLEND);
1039                         
1040                         /* draw protect 'lock' */
1041                         if (protect > -1) {
1042                                 offset = 16;
1043                                 UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
1044                         }
1045                         
1046                         /* draw mute 'eye' */
1047                         if (mute > -1) {
1048                                 offset += 16;
1049                                 UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
1050                         }
1051                         glDisable(GL_BLEND);
1052                 }
1053                 
1054                 /* adjust y-position for next one */
1055                 y -= ACHANNEL_STEP;
1056         }
1057         
1058         /* free tempolary channels */
1059         BLI_freelistN(&anim_data);
1060 }
1061
1062 /* ************************************************************************* */
1063 /* Keyframes */
1064
1065 ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
1066 {
1067         static ActKeysInc aki;
1068         
1069         /* no need to set settings if wrong context */
1070         if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
1071                 return NULL;
1072         
1073         /* if strip is mapped, store settings */
1074         aki.ob= ANIM_nla_mapping_get(ac, ale);
1075         
1076         if (ac->datatype == ANIMCONT_DOPESHEET)
1077                 aki.ads= (bDopeSheet *)ac->data;
1078         else
1079                 aki.ads= NULL;
1080         aki.actmode= ac->datatype;
1081                 
1082         /* always return pointer... */
1083         return &aki;
1084 }
1085
1086
1087 /* draw keyframes in each channel */
1088 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
1089 {
1090         ListBase anim_data = {NULL, NULL};
1091         bAnimListElem *ale;
1092         int filter;
1093         
1094         View2D *v2d= &ar->v2d;
1095         Object *nob= NULL;
1096         gla2DDrawInfo *di;
1097         rcti scr_rct;
1098         
1099         int act_start, act_end, dummy;
1100         int height, items;
1101         float y, sta, end;
1102         
1103         char col1[3], col2[3];
1104         char col1a[3], col2a[3];
1105         char col1b[3], col2b[3];
1106         
1107         
1108         /* get theme colors */
1109         UI_GetThemeColor3ubv(TH_SHADE2, col2);
1110         UI_GetThemeColor3ubv(TH_HILITE, col1);
1111         UI_GetThemeColor3ubv(TH_GROUP, col2a);
1112         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
1113         
1114         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
1115         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
1116         
1117         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
1118         scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
1119         scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
1120         scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
1121         scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax; 
1122         di= glaBegin2DDraw(&scr_rct, &v2d->cur);
1123
1124         /* if in NLA there's a strip active, map the view */
1125         if (ac->datatype == ANIMCONT_ACTION) {
1126                 nob= ANIM_nla_mapping_get(ac, NULL);
1127                 
1128                 if (nob)
1129                         ANIM_nla_mapping_draw(di, nob, 0);
1130                 
1131                 /* start and end of action itself */
1132                 calc_action_range(ac->data, &sta, &end, 0);
1133                 gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
1134                 gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
1135                 
1136                 if (nob)
1137                         ANIM_nla_mapping_draw(di, nob, 1);
1138         }
1139         
1140         /* build list of channels to draw */
1141         filter= (ANIMFILTER_FORDRAWING|ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
1142         items= ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
1143         
1144         /* Update max-extent of channels here (taking into account scrollers):
1145          *      - this is done to allow the channel list to be scrollable, but must be done here
1146          *        to avoid regenerating the list again and/or also because channels list is drawn first
1147          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
1148          *        start of list offset, and the second is as a correction for the scrollers.
1149          */
1150         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
1151         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
1152                 /* don't use totrect set, as the width stays the same 
1153                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
1154                  */
1155                 v2d->tot.ymin= (float)(-height);
1156         }
1157         
1158         /* first backdrop strips */
1159         y= (float)(-ACHANNEL_HEIGHT);
1160         glEnable(GL_BLEND);
1161         
1162         for (ale= anim_data.first; ale; ale= ale->next) {
1163                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1164                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1165                 
1166                 /* check if visible */
1167                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1168                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1169                 {
1170                         int frame1_x, channel_y, sel=0;
1171                         
1172                         /* determine if any need to draw channel */
1173                         if (ale->datatype != ALE_NONE) {
1174                                 /* determine if channel is selected */
1175                                 switch (ale->type) {
1176                                         case ANIMTYPE_OBJECT:
1177                                         {
1178                                                 Base *base= (Base *)ale->data;
1179                                                 sel = SEL_OBJC(base);
1180                                         }
1181                                                 break;
1182                                         case ANIMTYPE_GROUP:
1183                                         {
1184                                                 bActionGroup *agrp = (bActionGroup *)ale->data;
1185                                                 sel = SEL_AGRP(agrp);
1186                                         }
1187                                                 break;
1188                                         case ANIMTYPE_ACHAN:
1189                                         {
1190                                                 bActionChannel *achan = (bActionChannel *)ale->data;
1191                                                 sel = SEL_ACHAN(achan);
1192                                         }
1193                                                 break;
1194                                         case ANIMTYPE_CONCHAN:
1195                                         {
1196                                                 bConstraintChannel *conchan = (bConstraintChannel *)ale->data;
1197                                                 sel = SEL_CONCHAN(conchan);
1198                                         }
1199                                                 break;
1200                                         case ANIMTYPE_ICU:
1201                                         {
1202                                                 IpoCurve *icu = (IpoCurve *)ale->data;
1203                                                 sel = SEL_ICU(icu);
1204                                         }
1205                                                 break;
1206                                         case ANIMTYPE_GPLAYER:
1207                                         {
1208                                                 bGPDlayer *gpl = (bGPDlayer *)ale->data;
1209                                                 sel = SEL_GPL(gpl);
1210                                         }
1211                                                 break;
1212                                 }
1213                                 
1214                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
1215                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1216                                         
1217                                         switch (ale->type) {
1218                                                 case ANIMTYPE_OBJECT:
1219                                                 {
1220                                                         if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
1221                                                         else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
1222                                                 }
1223                                                         break;
1224                                                         
1225                                                 case ANIMTYPE_FILLIPOD:
1226                                                 case ANIMTYPE_FILLACTD:
1227                                                 case ANIMTYPE_FILLCOND:
1228                                                 case ANIMTYPE_DSSKEY:
1229                                                 {
1230                                                         if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
1231                                                         else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
1232                                                 }
1233                                                         break;
1234                                                 
1235                                                 case ANIMTYPE_GROUP:
1236                                                 {
1237                                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
1238                                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
1239                                                 }
1240                                                         break;
1241                                                 
1242                                                 default:
1243                                                 {
1244                                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1245                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1246                                                 }
1247                                                         break;
1248                                         }
1249                                         
1250                                         /* draw region twice: firstly backdrop, then the current range */
1251                                         glRectf((float)frame1_x,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1252                                         
1253                                         if (ac->datatype == ANIMCONT_ACTION)
1254                                                 glRectf((float)act_start,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)act_end,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1255                                 }
1256                                 else if (ac->datatype == ANIMCONT_SHAPEKEY) {
1257                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
1258                                         
1259                                         /* all frames that have a frame number less than one
1260                                          * get a desaturated orange background
1261                                          */
1262                                         glColor4ub(col2[0], col2[1], col2[2], 0x22);
1263                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1264                                         
1265                                         /* frames one and higher get a saturated orange background */
1266                                         glColor4ub(col2[0], col2[1], col2[2], 0x44);
1267                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1268                                 }
1269                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
1270                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1271                                         
1272                                         /* frames less than one get less saturated background */
1273                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1274                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1275                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1276                                         
1277                                         /* frames one and higher get a saturated background */
1278                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
1279                                         else glColor4ub(col2[0], col2[1], col2[2], 0x44);
1280                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1281                                 }
1282                         }
1283                 }
1284                 
1285                 /*      Increment the step */
1286                 y -= ACHANNEL_STEP;
1287         }               
1288         glDisable(GL_BLEND);
1289         
1290         /* Draw keyframes 
1291          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
1292          *         This is to try to optimise this for heavier data sets
1293          *      2) Keyframes which are out of view horizontally are disregarded 
1294          */
1295         y= (float)(-ACHANNEL_HEIGHT);
1296         
1297         for (ale= anim_data.first; ale; ale= ale->next) {
1298                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1299                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1300                 
1301                 /* check if visible */
1302                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1303                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1304                 {
1305                         /* check if anything to show for this channel */
1306                         if (ale->datatype != ALE_NONE) {
1307                                 ActKeysInc *aki= init_aki_data(ac, ale); 
1308                                 nob= ANIM_nla_mapping_get(ac, ale);
1309                                 
1310                                 if (nob)
1311                                         ANIM_nla_mapping_draw(di, nob, 0);
1312                                 
1313                                 /* draw 'keyframes' for each specific datatype */
1314                                 switch (ale->datatype) {
1315                                         case ALE_OB:
1316                                                 draw_object_channel(di, aki, ale->key_data, y);
1317                                                 break;
1318                                         case ALE_ACT:
1319                                                 draw_action_channel(di, aki, ale->key_data, y);
1320                                                 break;
1321                                         case ALE_GROUP:
1322                                                 draw_agroup_channel(di, aki, ale->data, y);
1323                                                 break;
1324                                         case ALE_IPO:
1325                                                 draw_ipo_channel(di, aki, ale->key_data, y);
1326                                                 break;
1327                                         case ALE_ICU:
1328                                                 draw_icu_channel(di, aki, ale->key_data, y);
1329                                                 break;
1330                                         case ALE_GPFRAME:
1331                                                 draw_gpl_channel(di, aki, ale->data, y);
1332                                                 break;
1333                                 }
1334                                 
1335                                 if (nob) 
1336                                         ANIM_nla_mapping_draw(di, nob, 1);
1337                         }
1338                 }
1339                 
1340                 y-= ACHANNEL_STEP;
1341         }
1342         
1343         /* free tempolary channels used for drawing */
1344         BLI_freelistN(&anim_data);
1345
1346         /* black line marking 'current frame' for Time-Slide transform mode */
1347         if (saction->flag & SACTION_MOVING) {
1348                 int frame1_x;
1349                 
1350                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
1351                 cpack(0x0);
1352                 
1353                 glBegin(GL_LINES);
1354                         glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
1355                         glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
1356                 glEnd();
1357         }
1358         
1359         glaEnd2DDraw(di);
1360 }