3152abcae9415e62866616cc4a79d516856c1edc
[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_anim_types.h"
50 #include "DNA_action_types.h"
51 #include "DNA_armature_types.h"
52 #include "DNA_camera_types.h"
53 #include "DNA_curve_types.h"
54 #include "DNA_object_types.h"
55 #include "DNA_screen_types.h"
56 #include "DNA_scene_types.h"
57 #include "DNA_space_types.h"
58 #include "DNA_constraint_types.h"
59 #include "DNA_key_types.h"
60 #include "DNA_lamp_types.h"
61 #include "DNA_material_types.h"
62 #include "DNA_userdef_types.h"
63 #include "DNA_gpencil_types.h"
64 #include "DNA_windowmanager_types.h"
65
66 #include "BKE_action.h"
67 #include "BKE_depsgraph.h"
68 #include "BKE_fcurve.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_VISIBLE|ANIMFILTER_CHANNELS);
412         items= ANIM_animdata_filter(ac, &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[128];
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_FILLMATD: /* object materials (dopesheet) expand widget */
488                                 {
489                                         Object *ob = (Object *)ale->data;
490                                         
491                                         group = 4;
492                                         indent = 1;
493                                         special = ICON_MATERIAL;
494                                         
495                                         if (FILTER_MAT_OBJC(ob))
496                                                 expand = ICON_TRIA_DOWN;
497                                         else
498                                                 expand = ICON_TRIA_RIGHT;
499                                                 
500                                         strcpy(name, "Materials");
501                                 }
502                                         break;
503                                 
504                                 
505                                 case ANIMTYPE_DSMAT: /* single material (dopesheet) expand widget */
506                                 {
507                                         Material *ma = (Material *)ale->data;
508                                         
509                                         group = 0;
510                                         indent = 0;
511                                         special = ICON_MATERIAL;
512                                         offset = 21;
513                                         
514                                         if (FILTER_MAT_OBJD(ma))
515                                                 expand = ICON_TRIA_DOWN;
516                                         else
517                                                 expand = ICON_TRIA_RIGHT;
518                                         
519                                         strcpy(name, ma->id.name+2);
520                                 }
521                                         break;
522                                 case ANIMTYPE_DSLAM: /* lamp (dopesheet) expand widget */
523                                 {
524                                         Lamp *la = (Lamp *)ale->data;
525                                         
526                                         group = 4;
527                                         indent = 1;
528                                         special = ICON_LAMP;
529                                         
530                                         if (FILTER_LAM_OBJD(la))
531                                                 expand = ICON_TRIA_DOWN;
532                                         else
533                                                 expand = ICON_TRIA_RIGHT;
534                                         
535                                         strcpy(name, la->id.name+2);
536                                 }
537                                         break;
538                                 case ANIMTYPE_DSCAM: /* camera (dopesheet) expand widget */
539                                 {
540                                         Camera *ca = (Camera *)ale->data;
541                                         
542                                         group = 4;
543                                         indent = 1;
544                                         special = ICON_CAMERA;
545                                         
546                                         if (FILTER_CAM_OBJD(ca))
547                                                 expand = ICON_TRIA_DOWN;
548                                         else
549                                                 expand = ICON_TRIA_RIGHT;
550                                         
551                                         strcpy(name, ca->id.name+2);
552                                 }
553                                         break;
554                                 case ANIMTYPE_DSCUR: /* curve (dopesheet) expand widget */
555                                 {
556                                         Curve *cu = (Curve *)ale->data;
557                                         
558                                         group = 4;
559                                         indent = 1;
560                                         special = ICON_CURVE;
561                                         
562                                         if (FILTER_CUR_OBJD(cu))
563                                                 expand = ICON_TRIA_DOWN;
564                                         else
565                                                 expand = ICON_TRIA_RIGHT;
566                                         
567                                         strcpy(name, cu->id.name+2);
568                                 }
569                                         break;
570                                 case ANIMTYPE_DSSKEY: /* shapekeys (dopesheet) expand widget */
571                                 {
572                                         Key *key= (Key *)ale->data;
573                                         
574                                         group = 4;
575                                         indent = 1;
576                                         special = ICON_EDIT;
577                                         
578                                         if (FILTER_SKE_OBJD(key))       
579                                                 expand = ICON_TRIA_DOWN;
580                                         else
581                                                 expand = ICON_TRIA_RIGHT;
582                                                 
583                                         //sel = SEL_OBJC(base);
584                                         strcpy(name, "Shape Keys");
585                                 }
586                                         break;
587                                         
588                                 
589                                 case ANIMTYPE_GROUP: /* action group */
590                                 {
591                                         bActionGroup *agrp= (bActionGroup *)ale->data;
592                                         
593                                         group= 2;
594                                         indent= 0;
595                                         special= -1;
596                                         
597                                         offset= (ale->id) ? 21 : 0;
598                                         
599                                         /* only show expand if there are any channels */
600                                         if (agrp->channels.first) {
601                                                 if (EXPANDED_AGRP(agrp))
602                                                         expand = ICON_TRIA_DOWN;
603                                                 else
604                                                         expand = ICON_TRIA_RIGHT;
605                                         }
606                                         
607                                         if (EDITABLE_AGRP(agrp))
608                                                 protect = ICON_UNLOCKED;
609                                         else
610                                                 protect = ICON_LOCKED;
611                                                 
612                                         sel = SEL_AGRP(agrp);
613                                         strcpy(name, agrp->name);
614                                 }
615                                         break;
616                                 case ANIMTYPE_FCURVE: /* F-Curve channel */
617                                 {
618                                         FCurve *fcu = (FCurve *)ale->data;
619                                         
620                                         indent = 0;
621                                         
622                                         //group= (ale->grp) ? 1 : 0;
623                                         //grp= ale->grp;
624                                         
625                                         switch (ale->ownertype) {
626                                                 case ANIMTYPE_NONE:     /* no owner */
627                                                 case ANIMTYPE_FCURVE: 
628                                                         offset= 0;
629                                                         break;
630                                                         
631                                                 case ANIMTYPE_DSMAT: /* for now, this is special case for materials */
632                                                         offset= 21;
633                                                         indent= 1;
634                                                         break;
635                                                         
636                                                 default:
637                                                         offset= 14;
638                                                         break;
639                                         }
640                                         
641                                         if (fcu->flag & FCURVE_MUTED)
642                                                 mute = ICON_MUTE_IPO_ON;
643                                         else    
644                                                 mute = ICON_MUTE_IPO_OFF;
645                                                 
646                                         if (EDITABLE_FCU(fcu))
647                                                 protect = ICON_UNLOCKED;
648                                         else
649                                                 protect = ICON_LOCKED;
650                                         
651                                         sel = SEL_FCU(fcu);
652                                         
653                                         // for now, we just print the full path... this needs more work!
654                                         getname_anim_fcurve(name, ale->id, fcu);
655                                         //sprintf(name, "%s[%d]", fcu->rna_path, fcu->array_index);
656                                 }
657                                         break;
658                                 
659                                 case ANIMTYPE_SHAPEKEY: /* shapekey channel */
660                                 {
661                                         KeyBlock *kb = (KeyBlock *)ale->data;
662                                         
663                                         indent = 0;
664                                         special = -1;
665                                         
666                                         offset= (ale->id) ? 21 : 0;
667                                         
668                                         if (kb->name[0] == '\0')
669                                                 sprintf(name, "Key %d", ale->index);
670                                         else
671                                                 strcpy(name, kb->name);
672                                 }
673                                         break;
674                                 
675                                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
676                                 {
677                                         bGPdata *gpd = (bGPdata *)ale->data;
678                                         ScrArea *sa = (ScrArea *)ale->owner;
679                                         
680                                         indent = 0;
681                                         group= 3;
682                                         
683                                         /* only show expand if there are any channels */
684                                         if (gpd->layers.first) {
685                                                 if (gpd->flag & GP_DATA_EXPAND)
686                                                         expand = ICON_TRIA_DOWN;
687                                                 else
688                                                         expand = ICON_TRIA_RIGHT;
689                                         }
690                                         
691                                         switch (sa->spacetype) {
692                                                 case SPACE_VIEW3D:
693                                                 {
694                                                         /* this shouldn't cause any overflow... */
695                                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
696                                                         strcpy(name, "3dView");
697                                                         special= ICON_VIEW3D;
698                                                 }
699                                                         break;
700                                                 case SPACE_NODE:
701                                                 {
702                                                         SpaceNode *snode= sa->spacedata.first;
703                                                         char treetype[12];
704                                                         
705                                                         if (snode->treetype == 1)
706                                                                 strcpy(treetype, "Composite");
707                                                         else
708                                                                 strcpy(treetype, "Material");
709                                                         sprintf(name, "Nodes:%s", treetype);
710                                                         
711                                                         special= ICON_NODE;
712                                                 }
713                                                         break;
714                                                 case SPACE_SEQ:
715                                                 {
716                                                         SpaceSeq *sseq= sa->spacedata.first;
717                                                         char imgpreview[10];
718                                                         
719                                                         switch (sseq->mainb) {
720                                                                 case 1:         sprintf(imgpreview, "Image...");        break;
721                                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
722                                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
723                                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
724                                                                 
725                                                                 default:        sprintf(imgpreview, "Sequence");        break;
726                                                         }
727                                                         sprintf(name, "Sequencer:%s", imgpreview);
728                                                         
729                                                         special= ICON_SEQUENCE;
730                                                 }
731                                                         break;
732                                                 case SPACE_IMAGE:
733                                                 {
734                                                         SpaceImage *sima= sa->spacedata.first;
735                                                         
736                                                         if (sima->image)
737                                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
738                                                         else
739                                                                 strcpy(name, "Image:<None>");
740                                                                 
741                                                         special= ICON_IMAGE_COL;
742                                                 }
743                                                         break;
744                                                 
745                                                 default:
746                                                 {
747                                                         sprintf(name, "<Unknown GP-Data Source>");
748                                                         special= -1;
749                                                 }
750                                                         break;
751                                         }
752                                 }
753                                         break;
754                                 case ANIMTYPE_GPLAYER: /* gpencil layer */
755                                 {
756                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
757                                         
758                                         indent = 0;
759                                         special = -1;
760                                         expand = -1;
761                                         group = 1;
762                                         
763                                         if (EDITABLE_GPL(gpl))
764                                                 protect = ICON_UNLOCKED;
765                                         else
766                                                 protect = ICON_LOCKED;
767                                                 
768                                         if (gpl->flag & GP_LAYER_HIDE)
769                                                 mute = ICON_MUTE_IPO_ON;
770                                         else
771                                                 mute = ICON_MUTE_IPO_OFF;
772                                         
773                                         sel = SEL_GPL(gpl);
774                                         BLI_snprintf(name, 32, gpl->info);
775                                 }
776                                         break;
777                         }       
778                         
779                         /* now, start drawing based on this information */
780                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
781                         glEnable(GL_BLEND);
782                         
783                         /* draw backing strip behind channel name */
784                         if (group == 4) {
785                                 /* only used in dopesheet... */
786                                 if (ale->type == ANIMTYPE_OBJECT) {
787                                         /* object channel - darker */
788                                         UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
789                                         uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
790                                         gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
791                                 }
792                                 else {
793                                         /* sub-object folders - lighter */
794                                         UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
795                                         
796                                         offset += 7 * indent;
797                                         glBegin(GL_QUADS);
798                                                 glVertex2f(x+offset, yminc);
799                                                 glVertex2f(x+offset, ymaxc);
800                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
801                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
802                                         glEnd();
803                                         
804                                         /* clear group value, otherwise we cause errors... */
805                                         group = 0;
806                                 }
807                         }
808                         else if (group == 3) {
809                                 /* only for gp-data channels */
810                                 UI_ThemeColorShade(TH_GROUP, 20);
811                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
812                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
813                         }
814                         else if (group == 2) {
815                                 /* only for action group channels */
816                                 if (ale->flag & AGRP_ACTIVE)
817                                         UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
818                                 else
819                                         UI_ThemeColorShade(TH_GROUP, 20);
820                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
821                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
822                         }
823                         else {
824                                 /* for normal channels 
825                                  *      - use 3 shades of color group/standard color for 3 indention level
826                                  *      - only use group colors if allowed to, and if actually feasible
827                                  */
828                                 if ( !(saction->flag & SACTION_NODRAWGCOLORS) && 
829                                          (grp) && (grp->customCol) ) 
830                                 {
831                                         char cp[3];
832                                         
833                                         if (indent == 2) {
834                                                 VECCOPY(cp, grp->cs.solid);
835                                         }
836                                         else if (indent == 1) {
837                                                 VECCOPY(cp, grp->cs.select);
838                                         }
839                                         else {
840                                                 VECCOPY(cp, grp->cs.active);
841                                         }
842                                         
843                                         glColor3ub(cp[0], cp[1], cp[2]);
844                                 }
845                                 else
846                                         UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
847                                 
848                                 indent += group;
849                                 offset += 7 * indent;
850                                 glBegin(GL_QUADS);
851                                         glVertex2f(x+offset, yminc);
852                                         glVertex2f(x+offset, ymaxc);
853                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
854                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
855                                 glEnd();
856                         }
857                         
858                         /* draw expand/collapse triangle */
859                         if (expand > 0) {
860                                 UI_icon_draw(x+offset, yminc, expand);
861                                 offset += 17;
862                         }
863                         
864                         /* draw special icon indicating certain data-types */
865                         if (special > -1) {
866                                 if (ELEM(group, 3, 4)) {
867                                         /* for gpdatablock channels */
868                                         UI_icon_draw(x+offset, yminc, special);
869                                         offset += 17;
870                                 }
871                                 else {
872                                         /* for ipo/constraint channels */
873                                         UI_icon_draw(x+offset, yminc, special);
874                                         offset += 17;
875                                 }
876                         }
877                         glDisable(GL_BLEND);
878                         
879                         /* draw name */
880                         if (sel)
881                                 UI_ThemeColor(TH_TEXT_HI);
882                         else
883                                 UI_ThemeColor(TH_TEXT);
884                         offset += 3;
885                         ui_rasterpos_safe(x+offset, y-4, 1.0f);
886                         UI_DrawString(G.font, name, 0);
887                         
888                         /* reset offset - for RHS of panel */
889                         offset = 0;
890                         
891                         /* set blending again, as text drawing may clear it */
892                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
893                         glEnable(GL_BLEND);
894                         
895                         /* draw protect 'lock' */
896                         if (protect > -1) {
897                                 offset = 16;
898                                 UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
899                         }
900                         
901                         /* draw mute 'eye' */
902                         if (mute > -1) {
903                                 offset += 16;
904                                 UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
905                         }
906                         glDisable(GL_BLEND);
907                 }
908                 
909                 /* adjust y-position for next one */
910                 y -= ACHANNEL_STEP;
911         }
912         
913         /* free tempolary channels */
914         BLI_freelistN(&anim_data);
915 }
916
917 /* ************************************************************************* */
918 /* Keyframes */
919
920 ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
921 {
922         static ActKeysInc aki;
923         
924         /* no need to set settings if wrong context */
925         if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
926                 return NULL;
927         
928         /* if strip is mapped, store settings */
929         aki.ob= ANIM_nla_mapping_get(ac, ale);
930         
931         if (ac->datatype == ANIMCONT_DOPESHEET)
932                 aki.ads= (bDopeSheet *)ac->data;
933         else
934                 aki.ads= NULL;
935         aki.actmode= ac->datatype;
936                 
937         /* always return pointer... */
938         return &aki;
939 }
940
941
942 /* draw keyframes in each channel */
943 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
944 {
945         ListBase anim_data = {NULL, NULL};
946         bAnimListElem *ale;
947         int filter;
948         
949         View2D *v2d= &ar->v2d;
950         Object *nob= NULL;
951         gla2DDrawInfo *di;
952         rcti scr_rct;
953         
954         int act_start, act_end, dummy;
955         int height, items;
956         float y, sta, end;
957         
958         char col1[3], col2[3];
959         char col1a[3], col2a[3];
960         char col1b[3], col2b[3];
961         
962         
963         /* get theme colors */
964         UI_GetThemeColor3ubv(TH_SHADE2, col2);
965         UI_GetThemeColor3ubv(TH_HILITE, col1);
966         UI_GetThemeColor3ubv(TH_GROUP, col2a);
967         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
968         
969         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
970         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
971         
972         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
973         scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
974         scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
975         scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
976         scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax; 
977         di= glaBegin2DDraw(&scr_rct, &v2d->cur);
978
979         /* if in NLA there's a strip active, map the view */
980         if (ac->datatype == ANIMCONT_ACTION) {
981                 nob= ANIM_nla_mapping_get(ac, NULL);
982                 
983                 if (nob)
984                         ANIM_nla_mapping_draw(di, nob, 0);
985                 
986                 /* start and end of action itself */
987                 calc_action_range(ac->data, &sta, &end, 0);
988                 gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
989                 gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
990                 
991                 if (nob)
992                         ANIM_nla_mapping_draw(di, nob, 1);
993         }
994         
995         /* build list of channels to draw */
996         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
997         items= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
998         
999         /* Update max-extent of channels here (taking into account scrollers):
1000          *      - this is done to allow the channel list to be scrollable, but must be done here
1001          *        to avoid regenerating the list again and/or also because channels list is drawn first
1002          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
1003          *        start of list offset, and the second is as a correction for the scrollers.
1004          */
1005         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
1006         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
1007                 /* don't use totrect set, as the width stays the same 
1008                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
1009                  */
1010                 v2d->tot.ymin= (float)(-height);
1011         }
1012         
1013         /* first backdrop strips */
1014         y= (float)(-ACHANNEL_HEIGHT);
1015         glEnable(GL_BLEND);
1016         
1017         for (ale= anim_data.first; ale; ale= ale->next) {
1018                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1019                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1020                 
1021                 /* check if visible */
1022                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1023                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1024                 {
1025                         int frame1_x, channel_y, sel=0;
1026                         
1027                         /* determine if any need to draw channel */
1028                         if (ale->datatype != ALE_NONE) {
1029                                 /* determine if channel is selected */
1030                                 switch (ale->type) {
1031                                         case ANIMTYPE_OBJECT:
1032                                         {
1033                                                 Base *base= (Base *)ale->data;
1034                                                 sel = SEL_OBJC(base);
1035                                         }
1036                                                 break;
1037                                         case ANIMTYPE_GROUP:
1038                                         {
1039                                                 bActionGroup *agrp = (bActionGroup *)ale->data;
1040                                                 sel = SEL_AGRP(agrp);
1041                                         }
1042                                                 break;
1043                                         case ANIMTYPE_FCURVE:
1044                                         {
1045                                                 FCurve *fcu = (FCurve *)ale->data;
1046                                                 sel = SEL_FCU(fcu);
1047                                         }
1048                                                 break;
1049                                         case ANIMTYPE_GPLAYER:
1050                                         {
1051                                                 bGPDlayer *gpl = (bGPDlayer *)ale->data;
1052                                                 sel = SEL_GPL(gpl);
1053                                         }
1054                                                 break;
1055                                 }
1056                                 
1057                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
1058                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1059                                         
1060                                         switch (ale->type) {
1061                                                 case ANIMTYPE_OBJECT:
1062                                                 {
1063                                                         if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
1064                                                         else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
1065                                                 }
1066                                                         break;
1067                                                 
1068                                                 case ANIMTYPE_FILLACTD:
1069                                                 case ANIMTYPE_FILLMATD:
1070                                                 case ANIMTYPE_DSSKEY:
1071                                                 {
1072                                                         if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
1073                                                         else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
1074                                                 }
1075                                                         break;
1076                                                 
1077                                                 case ANIMTYPE_GROUP:
1078                                                 {
1079                                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
1080                                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
1081                                                 }
1082                                                         break;
1083                                                 
1084                                                 default:
1085                                                 {
1086                                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1087                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1088                                                 }
1089                                                         break;
1090                                         }
1091                                         
1092                                         /* draw region twice: firstly backdrop, then the current range */
1093                                         glRectf((float)frame1_x,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1094                                         
1095                                         if (ac->datatype == ANIMCONT_ACTION)
1096                                                 glRectf((float)act_start,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)act_end,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1097                                 }
1098                                 else if (ac->datatype == ANIMCONT_SHAPEKEY) {
1099                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
1100                                         
1101                                         /* all frames that have a frame number less than one
1102                                          * get a desaturated orange background
1103                                          */
1104                                         glColor4ub(col2[0], col2[1], col2[2], 0x22);
1105                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1106                                         
1107                                         /* frames one and higher get a saturated orange background */
1108                                         glColor4ub(col2[0], col2[1], col2[2], 0x44);
1109                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1110                                 }
1111                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
1112                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1113                                         
1114                                         /* frames less than one get less saturated background */
1115                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1116                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1117                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1118                                         
1119                                         /* frames one and higher get a saturated background */
1120                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
1121                                         else glColor4ub(col2[0], col2[1], col2[2], 0x44);
1122                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1123                                 }
1124                         }
1125                 }
1126                 
1127                 /*      Increment the step */
1128                 y -= ACHANNEL_STEP;
1129         }               
1130         glDisable(GL_BLEND);
1131         
1132         /* Draw keyframes 
1133          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
1134          *         This is to try to optimise this for heavier data sets
1135          *      2) Keyframes which are out of view horizontally are disregarded 
1136          */
1137         y= (float)(-ACHANNEL_HEIGHT);
1138         
1139         for (ale= anim_data.first; ale; ale= ale->next) {
1140                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1141                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1142                 
1143                 /* check if visible */
1144                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1145                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1146                 {
1147                         /* check if anything to show for this channel */
1148                         if (ale->datatype != ALE_NONE) {
1149                                 ActKeysInc *aki= init_aki_data(ac, ale); 
1150                                 nob= ANIM_nla_mapping_get(ac, ale);
1151                                 
1152                                 if (nob)
1153                                         ANIM_nla_mapping_draw(di, nob, 0);
1154                                 
1155                                 /* draw 'keyframes' for each specific datatype */
1156                                 switch (ale->datatype) {
1157                                         case ALE_OB:
1158                                                 draw_object_channel(di, aki, ale->key_data, y);
1159                                                 break;
1160                                         case ALE_ACT:
1161                                                 draw_action_channel(di, aki, ale->key_data, y);
1162                                                 break;
1163                                         case ALE_GROUP:
1164                                                 draw_agroup_channel(di, aki, ale->data, y);
1165                                                 break;
1166                                         case ALE_FCURVE:
1167                                                 draw_fcurve_channel(di, aki, ale->key_data, y);
1168                                                 break;
1169                                         case ALE_GPFRAME:
1170                                                 draw_gpl_channel(di, aki, ale->data, y);
1171                                                 break;
1172                                 }
1173                                 
1174                                 if (nob) 
1175                                         ANIM_nla_mapping_draw(di, nob, 1);
1176                         }
1177                 }
1178                 
1179                 y-= ACHANNEL_STEP;
1180         }
1181         
1182         /* free tempolary channels used for drawing */
1183         BLI_freelistN(&anim_data);
1184
1185         /* black line marking 'current frame' for Time-Slide transform mode */
1186         if (saction->flag & SACTION_MOVING) {
1187                 int frame1_x;
1188                 
1189                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
1190                 cpack(0x0);
1191                 
1192                 glBegin(GL_LINES);
1193                         glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
1194                         glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
1195                 glEnd();
1196         }
1197         
1198         glaEnd2DDraw(di);
1199 }