Animato - Basic version patching support
[blender.git] / source / blender / editors / space_action / action_draw.c
1 /**
2  * $Id: drawaction.c 17746 2008-12-08 11:19:44Z aligorith $
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /* System includes ----------------------------------------------------- */
31
32 #include <math.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <float.h>
36
37 #ifdef HAVE_CONFIG_H
38 #include <config.h>
39 #endif
40
41 #include "MEM_guardedalloc.h"
42
43 #include "BLI_blenlib.h"
44 #include "BLI_arithb.h"
45
46 /* Types --------------------------------------------------------------- */
47
48 #include "DNA_listBase.h"
49 #include "DNA_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(&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_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 = 2;
621                                         protect = -1; // for now, until this can be supported by others
622                                         
623                                         group= (ale->grp) ? 1 : 0;
624                                         grp= ale->grp;
625                                         
626                                         if (ale->id) {
627                                                 if (GS(ale->id->name) == ID_MA)
628                                                         offset= 21;
629                                                 else
630                                                         offset= 0;
631                                         }
632                                         else
633                                                 offset= 0;
634                                         
635                                         if (fcu->flag & FCURVE_MUTED)
636                                                 mute = ICON_MUTE_IPO_ON;
637                                         else    
638                                                 mute = ICON_MUTE_IPO_OFF;
639                                                 
640                                         if (EDITABLE_FCU(fcu))
641                                                 protect = ICON_UNLOCKED;
642                                         else
643                                                 protect = ICON_LOCKED;
644                                         
645                                         sel = SEL_FCU(fcu);
646                                         
647                                         // for now, we just print the full path... this needs more work!
648                                         sprintf(name, "%s[%d]", fcu->rna_path, fcu->array_index);
649                                 }
650                                         break;
651                                 
652                                 case ANIMTYPE_SHAPEKEY: /* shapekey channel */
653                                 {
654                                         KeyBlock *kb = (KeyBlock *)ale->data;
655                                         
656                                         indent = 0;
657                                         special = -1;
658                                         
659                                         offset= (ale->id) ? 21 : 0;
660                                         
661                                         if (kb->name[0] == '\0')
662                                                 sprintf(name, "Key %d", ale->index);
663                                         else
664                                                 strcpy(name, kb->name);
665                                 }
666                                         break;
667                                 
668                                 case ANIMTYPE_GPDATABLOCK: /* gpencil datablock */
669                                 {
670                                         bGPdata *gpd = (bGPdata *)ale->data;
671                                         ScrArea *sa = (ScrArea *)ale->owner;
672                                         
673                                         indent = 0;
674                                         group= 3;
675                                         
676                                         /* only show expand if there are any channels */
677                                         if (gpd->layers.first) {
678                                                 if (gpd->flag & GP_DATA_EXPAND)
679                                                         expand = ICON_TRIA_DOWN;
680                                                 else
681                                                         expand = ICON_TRIA_RIGHT;
682                                         }
683                                         
684                                         switch (sa->spacetype) {
685                                                 case SPACE_VIEW3D:
686                                                 {
687                                                         /* this shouldn't cause any overflow... */
688                                                         //sprintf(name, "3DView:%s", view3d_get_name(sa->spacedata.first)); // XXX missing func..
689                                                         strcpy(name, "3dView");
690                                                         special= ICON_VIEW3D;
691                                                 }
692                                                         break;
693                                                 case SPACE_NODE:
694                                                 {
695                                                         SpaceNode *snode= sa->spacedata.first;
696                                                         char treetype[12];
697                                                         
698                                                         if (snode->treetype == 1)
699                                                                 strcpy(treetype, "Composite");
700                                                         else
701                                                                 strcpy(treetype, "Material");
702                                                         sprintf(name, "Nodes:%s", treetype);
703                                                         
704                                                         special= ICON_NODE;
705                                                 }
706                                                         break;
707                                                 case SPACE_SEQ:
708                                                 {
709                                                         SpaceSeq *sseq= sa->spacedata.first;
710                                                         char imgpreview[10];
711                                                         
712                                                         switch (sseq->mainb) {
713                                                                 case 1:         sprintf(imgpreview, "Image...");        break;
714                                                                 case 2:         sprintf(imgpreview, "Luma...");         break;
715                                                                 case 3:         sprintf(imgpreview, "Chroma...");       break;
716                                                                 case 4:         sprintf(imgpreview, "Histogram");       break;
717                                                                 
718                                                                 default:        sprintf(imgpreview, "Sequence");        break;
719                                                         }
720                                                         sprintf(name, "Sequencer:%s", imgpreview);
721                                                         
722                                                         special= ICON_SEQUENCE;
723                                                 }
724                                                         break;
725                                                 case SPACE_IMAGE:
726                                                 {
727                                                         SpaceImage *sima= sa->spacedata.first;
728                                                         
729                                                         if (sima->image)
730                                                                 sprintf(name, "Image:%s", sima->image->id.name+2);
731                                                         else
732                                                                 strcpy(name, "Image:<None>");
733                                                                 
734                                                         special= ICON_IMAGE_COL;
735                                                 }
736                                                         break;
737                                                 
738                                                 default:
739                                                 {
740                                                         sprintf(name, "<Unknown GP-Data Source>");
741                                                         special= -1;
742                                                 }
743                                                         break;
744                                         }
745                                 }
746                                         break;
747                                 case ANIMTYPE_GPLAYER: /* gpencil layer */
748                                 {
749                                         bGPDlayer *gpl = (bGPDlayer *)ale->data;
750                                         
751                                         indent = 0;
752                                         special = -1;
753                                         expand = -1;
754                                         group = 1;
755                                         
756                                         if (EDITABLE_GPL(gpl))
757                                                 protect = ICON_UNLOCKED;
758                                         else
759                                                 protect = ICON_LOCKED;
760                                                 
761                                         if (gpl->flag & GP_LAYER_HIDE)
762                                                 mute = ICON_MUTE_IPO_ON;
763                                         else
764                                                 mute = ICON_MUTE_IPO_OFF;
765                                         
766                                         sel = SEL_GPL(gpl);
767                                         BLI_snprintf(name, 32, gpl->info);
768                                 }
769                                         break;
770                         }       
771                         
772                         /* now, start drawing based on this information */
773                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
774                         glEnable(GL_BLEND);
775                         
776                         /* draw backing strip behind channel name */
777                         if (group == 4) {
778                                 /* only used in dopesheet... */
779                                 if (ale->type == ANIMTYPE_OBJECT) {
780                                         /* object channel - darker */
781                                         UI_ThemeColor(TH_DOPESHEET_CHANNELOB);
782                                         uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
783                                         gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
784                                 }
785                                 else {
786                                         /* sub-object folders - lighter */
787                                         UI_ThemeColor(TH_DOPESHEET_CHANNELSUBOB);
788                                         
789                                         offset += 7 * indent;
790                                         glBegin(GL_QUADS);
791                                                 glVertex2f(x+offset, yminc);
792                                                 glVertex2f(x+offset, ymaxc);
793                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
794                                                 glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
795                                         glEnd();
796                                         
797                                         /* clear group value, otherwise we cause errors... */
798                                         group = 0;
799                                 }
800                         }
801                         else if (group == 3) {
802                                 /* only for gp-data channels */
803                                 UI_ThemeColorShade(TH_GROUP, 20);
804                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
805                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
806                         }
807                         else if (group == 2) {
808                                 /* only for action group channels */
809                                 if (ale->flag & AGRP_ACTIVE)
810                                         UI_ThemeColorShade(TH_GROUP_ACTIVE, 10);
811                                 else
812                                         UI_ThemeColorShade(TH_GROUP, 20);
813                                 uiSetRoundBox((expand == ICON_TRIA_DOWN)? (1):(1|8));
814                                 gl_round_box(GL_POLYGON, x+offset,  yminc, (float)ACHANNEL_NAMEWIDTH, ymaxc, 8);
815                         }
816                         else {
817                                 /* for normal channels 
818                                  *      - use 3 shades of color group/standard color for 3 indention level
819                                  *      - only use group colors if allowed to, and if actually feasible
820                                  */
821                                 if ( !(saction->flag & SACTION_NODRAWGCOLORS) && 
822                                          (grp) && (grp->customCol) ) 
823                                 {
824                                         char cp[3];
825                                         
826                                         if (indent == 2) {
827                                                 VECCOPY(cp, grp->cs.solid);
828                                         }
829                                         else if (indent == 1) {
830                                                 VECCOPY(cp, grp->cs.select);
831                                         }
832                                         else {
833                                                 VECCOPY(cp, grp->cs.active);
834                                         }
835                                         
836                                         glColor3ub(cp[0], cp[1], cp[2]);
837                                 }
838                                 else
839                                         UI_ThemeColorShade(TH_HEADER, ((indent==0)?20: (indent==1)?-20: -40));
840                                 
841                                 indent += group;
842                                 offset += 7 * indent;
843                                 glBegin(GL_QUADS);
844                                         glVertex2f(x+offset, yminc);
845                                         glVertex2f(x+offset, ymaxc);
846                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, ymaxc);
847                                         glVertex2f((float)ACHANNEL_NAMEWIDTH, yminc);
848                                 glEnd();
849                         }
850                         
851                         /* draw expand/collapse triangle */
852                         if (expand > 0) {
853                                 UI_icon_draw(x+offset, yminc, expand);
854                                 offset += 17;
855                         }
856                         
857                         /* draw special icon indicating certain data-types */
858                         if (special > -1) {
859                                 if (ELEM(group, 3, 4)) {
860                                         /* for gpdatablock channels */
861                                         UI_icon_draw(x+offset, yminc, special);
862                                         offset += 17;
863                                 }
864                                 else {
865                                         /* for ipo/constraint channels */
866                                         UI_icon_draw(x+offset, yminc, special);
867                                         offset += 17;
868                                 }
869                         }
870                         glDisable(GL_BLEND);
871                         
872                         /* draw name */
873                         if (sel)
874                                 UI_ThemeColor(TH_TEXT_HI);
875                         else
876                                 UI_ThemeColor(TH_TEXT);
877                         offset += 3;
878                         ui_rasterpos_safe(x+offset, y-4, 1.0f);
879                         UI_DrawString(G.font, name, 0);
880                         
881                         /* reset offset - for RHS of panel */
882                         offset = 0;
883                         
884                         /* set blending again, as text drawing may clear it */
885                         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
886                         glEnable(GL_BLEND);
887                         
888                         /* draw protect 'lock' */
889                         if (protect > -1) {
890                                 offset = 16;
891                                 UI_icon_draw((float)ACHANNEL_NAMEWIDTH-offset, yminc, protect);
892                         }
893                         
894                         /* draw mute 'eye' */
895                         if (mute > -1) {
896                                 offset += 16;
897                                 UI_icon_draw((float)(ACHANNEL_NAMEWIDTH-offset), yminc, mute);
898                         }
899                         glDisable(GL_BLEND);
900                 }
901                 
902                 /* adjust y-position for next one */
903                 y -= ACHANNEL_STEP;
904         }
905         
906         /* free tempolary channels */
907         BLI_freelistN(&anim_data);
908 }
909
910 /* ************************************************************************* */
911 /* Keyframes */
912
913 ActKeysInc *init_aki_data(bAnimContext *ac, bAnimListElem *ale)
914 {
915         static ActKeysInc aki;
916         
917         /* no need to set settings if wrong context */
918         if ((ac->data == NULL) || ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)==0)
919                 return NULL;
920         
921         /* if strip is mapped, store settings */
922         aki.ob= ANIM_nla_mapping_get(ac, ale);
923         
924         if (ac->datatype == ANIMCONT_DOPESHEET)
925                 aki.ads= (bDopeSheet *)ac->data;
926         else
927                 aki.ads= NULL;
928         aki.actmode= ac->datatype;
929                 
930         /* always return pointer... */
931         return &aki;
932 }
933
934
935 /* draw keyframes in each channel */
936 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
937 {
938         ListBase anim_data = {NULL, NULL};
939         bAnimListElem *ale;
940         int filter;
941         
942         View2D *v2d= &ar->v2d;
943         Object *nob= NULL;
944         gla2DDrawInfo *di;
945         rcti scr_rct;
946         
947         int act_start, act_end, dummy;
948         int height, items;
949         float y, sta, end;
950         
951         char col1[3], col2[3];
952         char col1a[3], col2a[3];
953         char col1b[3], col2b[3];
954         
955         
956         /* get theme colors */
957         UI_GetThemeColor3ubv(TH_SHADE2, col2);
958         UI_GetThemeColor3ubv(TH_HILITE, col1);
959         UI_GetThemeColor3ubv(TH_GROUP, col2a);
960         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
961         
962         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
963         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
964         
965         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
966         scr_rct.xmin= ar->winrct.xmin + ar->v2d.mask.xmin;
967         scr_rct.ymin= ar->winrct.ymin + ar->v2d.mask.ymin;
968         scr_rct.xmax= ar->winrct.xmin + ar->v2d.hor.xmax;
969         scr_rct.ymax= ar->winrct.ymin + ar->v2d.mask.ymax; 
970         di= glaBegin2DDraw(&scr_rct, &v2d->cur);
971
972         /* if in NLA there's a strip active, map the view */
973         if (ac->datatype == ANIMCONT_ACTION) {
974                 nob= ANIM_nla_mapping_get(ac, NULL);
975                 
976                 if (nob)
977                         ANIM_nla_mapping_draw(di, nob, 0);
978                 
979                 /* start and end of action itself */
980                 calc_action_range(ac->data, &sta, &end, 0);
981                 gla2DDrawTranslatePt(di, sta, 0.0f, &act_start, &dummy);
982                 gla2DDrawTranslatePt(di, end, 0.0f, &act_end, &dummy);
983                 
984                 if (nob)
985                         ANIM_nla_mapping_draw(di, nob, 1);
986         }
987         
988         /* build list of channels to draw */
989         filter= (ANIMFILTER_VISIBLE|ANIMFILTER_CHANNELS);
990         items= ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
991         
992         /* Update max-extent of channels here (taking into account scrollers):
993          *      - this is done to allow the channel list to be scrollable, but must be done here
994          *        to avoid regenerating the list again and/or also because channels list is drawn first
995          *      - offset of ACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for 
996          *        start of list offset, and the second is as a correction for the scrollers.
997          */
998         height= ((items*ACHANNEL_STEP) + (ACHANNEL_HEIGHT*2));
999         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
1000                 /* don't use totrect set, as the width stays the same 
1001                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
1002                  */
1003                 v2d->tot.ymin= (float)(-height);
1004         }
1005         
1006         /* first backdrop strips */
1007         y= (float)(-ACHANNEL_HEIGHT);
1008         glEnable(GL_BLEND);
1009         
1010         for (ale= anim_data.first; ale; ale= ale->next) {
1011                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1012                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1013                 
1014                 /* check if visible */
1015                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1016                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1017                 {
1018                         int frame1_x, channel_y, sel=0;
1019                         
1020                         /* determine if any need to draw channel */
1021                         if (ale->datatype != ALE_NONE) {
1022                                 /* determine if channel is selected */
1023                                 switch (ale->type) {
1024                                         case ANIMTYPE_OBJECT:
1025                                         {
1026                                                 Base *base= (Base *)ale->data;
1027                                                 sel = SEL_OBJC(base);
1028                                         }
1029                                                 break;
1030                                         case ANIMTYPE_GROUP:
1031                                         {
1032                                                 bActionGroup *agrp = (bActionGroup *)ale->data;
1033                                                 sel = SEL_AGRP(agrp);
1034                                         }
1035                                                 break;
1036                                         case ANIMTYPE_FCURVE:
1037                                         {
1038                                                 FCurve *fcu = (FCurve *)ale->data;
1039                                                 sel = SEL_FCU(fcu);
1040                                         }
1041                                                 break;
1042                                         case ANIMTYPE_GPLAYER:
1043                                         {
1044                                                 bGPDlayer *gpl = (bGPDlayer *)ale->data;
1045                                                 sel = SEL_GPL(gpl);
1046                                         }
1047                                                 break;
1048                                 }
1049                                 
1050                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
1051                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1052                                         
1053                                         switch (ale->type) {
1054                                                 case ANIMTYPE_OBJECT:
1055                                                 {
1056                                                         if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45); 
1057                                                         else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22); 
1058                                                 }
1059                                                         break;
1060                                                 
1061                                                 case ANIMTYPE_FILLACTD:
1062                                                 case ANIMTYPE_FILLMATD:
1063                                                 case ANIMTYPE_DSSKEY:
1064                                                 {
1065                                                         if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45); 
1066                                                         else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22); 
1067                                                 }
1068                                                         break;
1069                                                 
1070                                                 case ANIMTYPE_GROUP:
1071                                                 {
1072                                                         if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
1073                                                         else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
1074                                                 }
1075                                                         break;
1076                                                 
1077                                                 default:
1078                                                 {
1079                                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1080                                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1081                                                 }
1082                                                         break;
1083                                         }
1084                                         
1085                                         /* draw region twice: firstly backdrop, then the current range */
1086                                         glRectf((float)frame1_x,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1087                                         
1088                                         if (ac->datatype == ANIMCONT_ACTION)
1089                                                 glRectf((float)act_start,  (float)channel_y-ACHANNEL_HEIGHT_HALF,  (float)act_end,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1090                                 }
1091                                 else if (ac->datatype == ANIMCONT_SHAPEKEY) {
1092                                         gla2DDrawTranslatePt(di, 1, y, &frame1_x, &channel_y);
1093                                         
1094                                         /* all frames that have a frame number less than one
1095                                          * get a desaturated orange background
1096                                          */
1097                                         glColor4ub(col2[0], col2[1], col2[2], 0x22);
1098                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1099                                         
1100                                         /* frames one and higher get a saturated orange background */
1101                                         glColor4ub(col2[0], col2[1], col2[2], 0x44);
1102                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1103                                 }
1104                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
1105                                         gla2DDrawTranslatePt(di, v2d->cur.xmin, y, &frame1_x, &channel_y);
1106                                         
1107                                         /* frames less than one get less saturated background */
1108                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
1109                                         else glColor4ub(col2[0], col2[1], col2[2], 0x22);
1110                                         glRectf(0.0f, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)frame1_x, (float)channel_y+ACHANNEL_HEIGHT_HALF);
1111                                         
1112                                         /* frames one and higher get a saturated background */
1113                                         if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
1114                                         else glColor4ub(col2[0], col2[1], col2[2], 0x44);
1115                                         glRectf((float)frame1_x, (float)channel_y-ACHANNEL_HEIGHT_HALF, (float)v2d->hor.xmax,  (float)channel_y+ACHANNEL_HEIGHT_HALF);
1116                                 }
1117                         }
1118                 }
1119                 
1120                 /*      Increment the step */
1121                 y -= ACHANNEL_STEP;
1122         }               
1123         glDisable(GL_BLEND);
1124         
1125         /* Draw keyframes 
1126          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
1127          *         This is to try to optimise this for heavier data sets
1128          *      2) Keyframes which are out of view horizontally are disregarded 
1129          */
1130         y= (float)(-ACHANNEL_HEIGHT);
1131         
1132         for (ale= anim_data.first; ale; ale= ale->next) {
1133                 const float yminc= (float)(y - ACHANNEL_HEIGHT_HALF);
1134                 const float ymaxc= (float)(y + ACHANNEL_HEIGHT_HALF);
1135                 
1136                 /* check if visible */
1137                 if ( IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
1138                          IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) ) 
1139                 {
1140                         /* check if anything to show for this channel */
1141                         if (ale->datatype != ALE_NONE) {
1142                                 ActKeysInc *aki= init_aki_data(ac, ale); 
1143                                 nob= ANIM_nla_mapping_get(ac, ale);
1144                                 
1145                                 if (nob)
1146                                         ANIM_nla_mapping_draw(di, nob, 0);
1147                                 
1148                                 /* draw 'keyframes' for each specific datatype */
1149                                 switch (ale->datatype) {
1150                                         case ALE_OB:
1151                                                 draw_object_channel(di, aki, ale->key_data, y);
1152                                                 break;
1153                                         case ALE_ACT:
1154                                                 draw_action_channel(di, aki, ale->key_data, y);
1155                                                 break;
1156                                         case ALE_GROUP:
1157                                                 draw_agroup_channel(di, aki, ale->data, y);
1158                                                 break;
1159                                         case ALE_FCURVE:
1160                                                 draw_fcurve_channel(di, aki, ale->key_data, y);
1161                                                 break;
1162                                         case ALE_GPFRAME:
1163                                                 draw_gpl_channel(di, aki, ale->data, y);
1164                                                 break;
1165                                 }
1166                                 
1167                                 if (nob) 
1168                                         ANIM_nla_mapping_draw(di, nob, 1);
1169                         }
1170                 }
1171                 
1172                 y-= ACHANNEL_STEP;
1173         }
1174         
1175         /* free tempolary channels used for drawing */
1176         BLI_freelistN(&anim_data);
1177
1178         /* black line marking 'current frame' for Time-Slide transform mode */
1179         if (saction->flag & SACTION_MOVING) {
1180                 int frame1_x;
1181                 
1182                 gla2DDrawTranslatePt(di, saction->timeslide, 0, &frame1_x, &dummy);
1183                 cpack(0x0);
1184                 
1185                 glBegin(GL_LINES);
1186                         glVertex2f((float)frame1_x, (float)v2d->mask.ymin - 100);
1187                         glVertex2f((float)frame1_x, (float)v2d->mask.ymax);
1188                 glEnd();
1189         }
1190         
1191         glaEnd2DDraw(di);
1192 }