Dopesheet: Added "Moving Hold" as a keyframe type
[blender.git] / source / blender / editors / animation / keyframes_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung (full recode)
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/animation/keyframes_draw.c
29  *  \ingroup edanimation
30  */
31
32
33 /* System includes ----------------------------------------------------- */
34
35 #include <math.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <float.h>
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_dlrbTree.h"
43 #include "BLI_math.h"
44 #include "BLI_utildefines.h"
45
46 #include "DNA_anim_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_gpencil_types.h"
50 #include "DNA_mask_types.h"
51
52 #include "BKE_fcurve.h"
53
54 #include "BIF_gl.h"
55
56 #include "UI_resources.h"
57 #include "UI_view2d.h"
58
59 #include "ED_anim_api.h"
60 #include "ED_keyframes_draw.h"
61
62 /* *************************** Keyframe Processing *************************** */
63
64 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
65
66 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
67 /* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
68 short compare_ak_cfraPtr(void *node, void *data)
69 {
70         ActKeyColumn *ak = (ActKeyColumn *)node;
71         const float *cframe = data;
72         float val = *cframe;
73         
74         if (IS_EQT(val, ak->cfra, BEZT_BINARYSEARCH_THRESH))
75                 return 0;
76         
77         if (val < ak->cfra)
78                 return -1;
79         else if (val > ak->cfra)
80                 return 1;
81         else
82                 return 0;
83 }
84
85 /* --------------- */
86
87 /* Comparator callback used for ActKeyColumns and BezTriple */
88 static short compare_ak_bezt(void *node, void *data)
89 {
90         ActKeyColumn *ak = (ActKeyColumn *)node;
91         BezTriple *bezt = (BezTriple *)data;
92         
93         if (bezt->vec[1][0] < ak->cfra)
94                 return -1;
95         else if (bezt->vec[1][0] > ak->cfra)
96                 return 1;
97         else
98                 return 0;
99 }
100
101 /* New node callback used for building ActKeyColumns from BezTriples */
102 static DLRBT_Node *nalloc_ak_bezt(void *data)
103 {
104         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
105         BezTriple *bezt = (BezTriple *)data;
106         
107         /* store settings based on state of BezTriple */
108         ak->cfra = bezt->vec[1][0];
109         ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
110         ak->key_type = BEZKEYTYPE(bezt);
111         
112         /* set 'modified', since this is used to identify long keyframes */
113         ak->modified = 1;
114         
115         return (DLRBT_Node *)ak;
116 }
117
118 /* Node updater callback used for building ActKeyColumns from BezTriples */
119 static void nupdate_ak_bezt(void *node, void *data)
120 {
121         ActKeyColumn *ak = (ActKeyColumn *)node;
122         BezTriple *bezt = (BezTriple *)data;
123         
124         /* set selection status and 'touched' status */
125         if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
126         ak->modified += 1;
127         
128         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
129         if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
130                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
131 }
132
133 /* ......... */
134
135 /* Comparator callback used for ActKeyColumns and GPencil frame */
136 static short compare_ak_gpframe(void *node, void *data)
137 {
138         ActKeyColumn *ak = (ActKeyColumn *)node;
139         bGPDframe *gpf = (bGPDframe *)data;
140         
141         if (gpf->framenum < ak->cfra)
142                 return -1;
143         else if (gpf->framenum > ak->cfra)
144                 return 1;
145         else
146                 return 0;
147 }
148
149 /* New node callback used for building ActKeyColumns from GPencil frames */
150 static DLRBT_Node *nalloc_ak_gpframe(void *data)
151 {
152         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
153         bGPDframe *gpf = (bGPDframe *)data;
154         
155         /* store settings based on state of BezTriple */
156         ak->cfra = gpf->framenum;
157         ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
158         ak->key_type = gpf->key_type;
159         
160         /* set 'modified', since this is used to identify long keyframes */
161         ak->modified = 1;
162         
163         return (DLRBT_Node *)ak;
164 }
165
166 /* Node updater callback used for building ActKeyColumns from GPencil frames */
167 static void nupdate_ak_gpframe(void *node, void *data)
168 {
169         ActKeyColumn *ak = (ActKeyColumn *)node;
170         bGPDframe *gpf = (bGPDframe *)data;
171         
172         /* set selection status and 'touched' status */
173         if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
174         ak->modified += 1;
175         
176         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
177         if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
178                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
179 }
180
181 /* ......... */
182
183 /* Comparator callback used for ActKeyColumns and GPencil frame */
184 static short compare_ak_masklayshape(void *node, void *data)
185 {
186         ActKeyColumn *ak = (ActKeyColumn *)node;
187         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
188
189         if (masklay_shape->frame < ak->cfra)
190                 return -1;
191         else if (masklay_shape->frame > ak->cfra)
192                 return 1;
193         else
194                 return 0;
195 }
196
197 /* New node callback used for building ActKeyColumns from GPencil frames */
198 static DLRBT_Node *nalloc_ak_masklayshape(void *data)
199 {
200         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
201         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
202
203         /* store settings based on state of BezTriple */
204         ak->cfra = masklay_shape->frame;
205         ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
206
207         /* set 'modified', since this is used to identify long keyframes */
208         ak->modified = 1;
209
210         return (DLRBT_Node *)ak;
211 }
212
213 /* Node updater callback used for building ActKeyColumns from GPencil frames */
214 static void nupdate_ak_masklayshape(void *node, void *data)
215 {
216         ActKeyColumn *ak = (ActKeyColumn *)node;
217         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
218
219         /* set selection status and 'touched' status */
220         if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
221         ak->modified += 1;
222 }
223
224
225 /* --------------- */
226
227 /* Add the given BezTriple to the given 'list' of Keyframes */
228 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
229 {
230         if (ELEM(NULL, keys, bezt))
231                 return;
232         else
233                 BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
234 }
235
236 /* Add the given GPencil Frame to the given 'list' of Keyframes */
237 static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
238 {
239         if (ELEM(NULL, keys, gpf))
240                 return;
241         else
242                 BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
243 }
244
245 /* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
246 static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape)
247 {
248         if (ELEM(NULL, keys, masklay_shape))
249                 return;
250         else
251                 BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape);
252 }
253
254 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
255
256 /* Comparator callback used for ActKeyBlock and cframe float-value pointer */
257 /* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
258 short compare_ab_cfraPtr(void *node, void *data)
259 {
260         ActKeyBlock *ab = (ActKeyBlock *)node;
261         const float *cframe = data;
262         float val = *cframe;
263         
264         if (val < ab->start)
265                 return -1;
266         else if (val > ab->start)
267                 return 1;
268         else
269                 return 0;
270 }
271
272 /* --------------- */
273
274 /* Create a ActKeyColumn for a pair of BezTriples */
275 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
276 {
277         ActKeyBlock *ab = MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
278         
279         ab->start = prev->vec[1][0];
280         ab->end = beztn->vec[1][0];
281         ab->val = beztn->vec[1][1];
282         
283         ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
284         ab->modified = 1;
285         
286         if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
287                 ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
288         
289         return ab;
290 }
291
292 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt, BezTriple *beztn)
293 {
294         ActKeyBlock *new_ab = NULL;
295         BezTriple *prev = NULL;
296         
297         /* get the BezTriple immediately before the given one which has the same value */
298         if (beztn != first_bezt) {
299                 /* XXX: Unless I'm overlooking some details from the past, this should be sufficient? 
300                  *      The old code did some elaborate stuff trying to find keyframe columns for
301                  *      the given BezTriple, then step backwards to the column before that, and find
302                  *      an appropriate BezTriple with matching values there. Maybe that was warranted
303                  *      in the past, but now, that list is only ever filled with keyframes from the 
304                  *      current FCurve.
305                  *
306                  *      -- Aligorith (20140415)
307                  */
308                 prev = beztn - 1;
309         }
310         
311         
312         /* check if block needed */
313         if (prev == NULL) return;
314         
315         if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
316                 /* Animator tagged a "moving hold"
317                  *   - Previous key must also be tagged as a moving hold, otherwise
318                  *     we're just dealing with the first of a pair, and we don't
319                  *     want to be creating any phantom holds...
320                  */
321                 if (BEZKEYTYPE(prev) != BEZT_KEYTYPE_MOVEHOLD)
322                         return;
323         }
324         else {
325                 /* Check for same values...
326                  *  - Handles must have same central value as each other
327                  *  - Handles which control that section of the curve must be constant
328                  */
329                 if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
330                 
331                 if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
332                 if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
333         }
334         
335         /* if there are no blocks already, just add as root */
336         if (blocks->root == NULL) {
337                 /* just add this as the root, then call the tree-balancing functions to validate */
338                 new_ab = bezts_to_new_actkeyblock(prev, beztn);
339                 blocks->root = (DLRBT_Node *)new_ab;
340         }
341         else {
342                 ActKeyBlock *ab, *abn = NULL;
343                 
344                 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
345                  * Note: we perform a tree traversal here NOT a standard linked-list traversal...
346                  * Note: we can't search from end to try to optimize this as it causes errors there's
347                  *      an A ___ B |---| B situation
348                  */
349                 // FIXME: here there is a bug where we are trying to get the summary for the following channels
350                 //              A|--------------|A ______________ B|--------------|B
351                 //              A|------------------------------------------------|A
352                 //              A|----|A|---|A|-----------------------------------|A
353                 for (ab = blocks->root; ab; ab = abn) {
354                         /* check if this is a match, or whether we go left or right 
355                          * NOTE: we now use a float threshold to prevent precision errors causing problems with summaries
356                          */
357                         if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
358                                 /* set selection status and 'touched' status */
359                                 if (BEZT_ISSEL_ANY(beztn))
360                                         ab->sel = SELECT;
361                                         
362                                 /* XXX: only when the first one was a moving hold? */
363                                 if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
364                                         ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
365                                 
366                                 ab->modified++;
367                                 
368                                 /* done... no need to insert */
369                                 return;
370                         }
371                         else {
372                                 ActKeyBlock **abnp = NULL; /* branch to go down - used to hook new blocks to parents */
373                                 
374                                 /* check if go left or right, but if not available, add new node */
375                                 if (ab->start < prev->vec[1][0]) 
376                                         abnp = &ab->right;
377                                 else
378                                         abnp = &ab->left;
379                                         
380                                 /* if this does not exist, add a new node, otherwise continue... */
381                                 if (*abnp == NULL) {
382                                         /* add a new node representing this, and attach it to the relevant place */
383                                         new_ab = bezts_to_new_actkeyblock(prev, beztn);
384                                         new_ab->parent = ab;
385                                         *abnp = new_ab;
386                                         break;
387                                 }
388                                 else
389                                         abn = *abnp;
390                         }
391                 }
392         }
393         
394         /* now, balance the tree taking into account this newly added node */
395         BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
396 }
397
398 /* --------- */
399
400 /* Handle the 'touched' status of ActKeyColumn tree nodes */
401 static void set_touched_actkeycolumn(ActKeyColumn *ak)
402 {
403         /* sanity check */
404         if (ak == NULL)
405                 return;
406                 
407         /* deal with self first */
408         if (ak->modified) {
409                 ak->modified = 0;
410                 ak->totcurve++;
411         }
412         
413         /* children */
414         set_touched_actkeycolumn(ak->left);
415         set_touched_actkeycolumn(ak->right);
416 }
417
418 /* Handle the 'touched' status of ActKeyBlock tree nodes */
419 static void set_touched_actkeyblock(ActKeyBlock *ab)
420 {
421         /* sanity check */
422         if (ab == NULL)
423                 return;
424                 
425         /* deal with self first */
426         if (ab->modified) {
427                 ab->modified = 0;
428                 ab->totcurve++;
429         }
430         
431         /* children */
432         set_touched_actkeyblock(ab->left);
433         set_touched_actkeyblock(ab->right);
434 }
435
436 /* --------- */
437
438 /* Checks if ActKeyBlock should exist... */
439 bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
440 {
441         ActKeyColumn *ak;
442         short startCurves, endCurves, totCurves;
443         
444         /* check that block is valid */
445         if (ab == NULL)
446                 return 0;
447         
448         /* find out how many curves occur at each keyframe */
449         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
450         startCurves = (ak) ? ak->totcurve : 0;
451         
452         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
453         endCurves = (ak) ? ak->totcurve : 0;
454         
455         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
456         if (!startCurves && !endCurves) 
457                 return 0;
458         
459         totCurves = (startCurves > endCurves) ? endCurves : startCurves;
460         return (ab->totcurve >= totCurves);
461 }
462
463 /* *************************** Keyframe Drawing *************************** */
464
465 /* coordinates for diamond shape */
466 static const float _unit_diamond_shape[4][2] = {
467         {0.0f, 1.0f},   /* top vert */
468         {1.0f, 0.0f},   /* mid-right */
469         {0.0f, -1.0f},  /* bottom vert */
470         {-1.0f, 0.0f}   /* mid-left */
471 }; 
472
473 /* draw a simple diamond shape with OpenGL */
474 void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel, short key_type, short mode, float alpha)
475 {
476         static GLuint displist1 = 0;
477         static GLuint displist2 = 0;
478         
479         /* initialize 2 display lists for diamond shape - one empty, one filled */
480         if (displist1 == 0) {
481                 displist1 = glGenLists(1);
482                 glNewList(displist1, GL_COMPILE);
483                         
484                 glBegin(GL_LINE_LOOP);
485                 glVertex2fv(_unit_diamond_shape[0]);
486                 glVertex2fv(_unit_diamond_shape[1]);
487                 glVertex2fv(_unit_diamond_shape[2]);
488                 glVertex2fv(_unit_diamond_shape[3]);
489                 glEnd();
490
491                 glEndList();
492         }
493         if (displist2 == 0) {
494                 displist2 = glGenLists(1);
495                 glNewList(displist2, GL_COMPILE);
496                         
497                 glBegin(GL_QUADS);
498                 glVertex2fv(_unit_diamond_shape[0]);
499                 glVertex2fv(_unit_diamond_shape[1]);
500                 glVertex2fv(_unit_diamond_shape[2]);
501                 glVertex2fv(_unit_diamond_shape[3]);
502                 glEnd();
503
504                 glEndList();
505         }
506         
507         /* tweak size of keyframe shape according to type of keyframe 
508          * - 'proper' keyframes have key_type = 0, so get drawn at full size
509          */
510         switch (key_type) {
511                 case BEZT_KEYTYPE_KEYFRAME:  /* must be full size */
512                         break;
513                 
514                 case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
515                         hsize *= 0.85f;
516                         break;
517                 
518                 case BEZT_KEYTYPE_MOVEHOLD:  /* slightly smaller than normal keyframes (but by less than for breakdowns) */
519                         //hsize *= 0.72f;
520                         hsize *= 0.95f;
521                         break;
522                         
523                 case BEZT_KEYTYPE_EXTREME:   /* slightly larger */
524                         hsize *= 1.2f;
525                         break;
526                 
527                 default:
528                         hsize -= 0.5f * key_type;
529                         break;
530         }
531         
532         /* adjust view transform before starting */
533         glTranslatef(x, y, 0.0f);
534         glScalef(1.0f / xscale * hsize, hsize, 1.0f);
535         
536         /* anti-aliased lines for more consistent appearance */
537         glEnable(GL_LINE_SMOOTH);
538         
539         /* draw! */
540         if (ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH)) {
541                 float inner_col[4];
542                 
543                 /* get interior colors from theme (for selected and unselected only) */
544                 switch (key_type) {
545                         case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
546                         {
547                                 if (sel)  UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN_SELECT, inner_col);
548                                 else UI_GetThemeColor4fv(TH_KEYTYPE_BREAKDOWN, inner_col);
549                                 break;
550                         }
551                         case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
552                         {
553                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME_SELECT, inner_col);
554                                 else UI_GetThemeColor4fv(TH_KEYTYPE_EXTREME, inner_col);
555                                 break;
556                         }
557                         case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
558                         {
559                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_JITTER_SELECT, inner_col);
560                                 else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
561                                 break;
562                         }
563                         case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
564                         {
565                                 /* XXX: Should these get their own theme options instead? */
566                                 if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col);
567                                 else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col);
568                                 
569                                 inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */
570                                 break;
571                         }
572                         case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
573                         default:
574                         {
575                                 if (sel) UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME_SELECT, inner_col);
576                                 else UI_GetThemeColor4fv(TH_KEYTYPE_KEYFRAME, inner_col);
577                                 break;
578                         }
579                 }
580                 
581                 /* NOTE: we don't use the straight alpha from the theme, or else effects such as 
582                  * graying out protected/muted channels doesn't work correctly!
583                  */
584                 inner_col[3] *= alpha;
585                 glColor4fv(inner_col);
586                 
587                 /* draw the "filled in" interior poly now */
588                 glCallList(displist2);
589         }
590         
591         if (ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH)) {
592                 float border_col[4];
593                 
594                 /* exterior - black frame */
595                 if (sel)  UI_GetThemeColor4fv(TH_KEYBORDER_SELECT, border_col);
596                 else  UI_GetThemeColor4fv(TH_KEYBORDER, border_col);
597                 
598                 border_col[3] *= alpha;
599                 glColor4fv(border_col);
600                 
601                 glCallList(displist1);
602         }
603         
604         glDisable(GL_LINE_SMOOTH);
605         
606         /* restore view transform */
607         glScalef(xscale / hsize, 1.0f / hsize, 1.0f);
608         glTranslatef(-x, -y, 0.0f);
609 }
610
611 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
612 {
613         ActKeyColumn *ak;
614         ActKeyBlock *ab;
615         float alpha;
616         float xscale;
617         
618         const float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
619         const float mhsize   = iconsize * 0.7f;
620         
621         glEnable(GL_BLEND);
622         
623         /* get View2D scaling factor */
624         UI_view2d_scale_get(v2d, &xscale, NULL);
625         
626         /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
627         /* TODO: allow this opacity factor to be themed? */
628         alpha = (channelLocked) ? 0.25f : 1.0f;
629         
630         /* draw keyblocks */
631         if (blocks) {
632                 float sel_color[4], unsel_color[4];
633                 float sel_mhcol[4], unsel_mhcol[4];
634                 
635                 /* cache colours first */
636                 UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
637                 UI_GetThemeColor4fv(TH_STRIP, unsel_color);
638                 
639                 sel_color[3]   *= alpha;
640                 unsel_color[3] *= alpha;
641                 
642                 copy_v4_v4(sel_mhcol, sel_color);
643                 sel_mhcol[3]   *= 0.8f;
644                 copy_v4_v4(unsel_mhcol, unsel_color);
645                 unsel_mhcol[3] *= 0.8f;
646                 
647                 /* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
648                 for (ab = blocks->first; ab; ab = ab->next) {
649                         if (actkeyblock_is_valid(ab, keys)) {
650                                 if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
651                                         /* draw "moving hold" long-keyframe block - slightly smaller */
652                                         if (ab->sel)
653                                                 glColor4fv(sel_mhcol);
654                                         else
655                                                 glColor4fv(unsel_mhcol);
656                                         
657                                         glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize);
658                                 }
659                                 else {
660                                         /* draw standard long-keyframe block */
661                                         if (ab->sel)
662                                                 glColor4fv(sel_color);
663                                         else
664                                                 glColor4fv(unsel_color);
665                                         
666                                         glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
667                                 }
668                         }
669                 }
670         }
671         
672         /* draw keys */
673         if (keys) {
674                 for (ak = keys->first; ak; ak = ak->next) {
675                         /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
676                          *      - this might give some improvements, since we current have to flip between view/region matrices
677                          */
678                         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax) == 0)
679                                 continue;
680                         
681                         /* draw using OpenGL - uglier but faster */
682                         /* NOTE1: a previous version of this didn't work nice for some intel cards
683                          * NOTE2: if we wanted to go back to icons, these are  icon = (ak->sel & SELECT) ? ICON_SPACE2 : ICON_SPACE3; */
684                         draw_keyframe_shape(ak->cfra, ypos, xscale, iconsize, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha);
685                 }
686         }
687
688         glDisable(GL_BLEND);
689 }
690
691 /* *************************** Channel Drawing Funcs *************************** */
692
693 void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
694 {
695         DLRBT_Tree keys, blocks;
696         
697         BLI_dlrbTree_init(&keys);
698         BLI_dlrbTree_init(&blocks);
699         
700         summary_to_keylist(ac, &keys, &blocks);
701         
702         BLI_dlrbTree_linkedlist_sync(&keys);
703         BLI_dlrbTree_linkedlist_sync(&blocks);
704         
705         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
706         
707         BLI_dlrbTree_free(&keys);
708         BLI_dlrbTree_free(&blocks);
709 }
710
711 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
712 {
713         DLRBT_Tree keys, blocks;
714         
715         BLI_dlrbTree_init(&keys);
716         BLI_dlrbTree_init(&blocks);
717         
718         scene_to_keylist(ads, sce, &keys, &blocks);
719         
720         BLI_dlrbTree_linkedlist_sync(&keys);
721         BLI_dlrbTree_linkedlist_sync(&blocks);
722         
723         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
724         
725         BLI_dlrbTree_free(&keys);
726         BLI_dlrbTree_free(&blocks);
727 }
728
729 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
730 {
731         DLRBT_Tree keys, blocks;
732         
733         BLI_dlrbTree_init(&keys);
734         BLI_dlrbTree_init(&blocks);
735         
736         ob_to_keylist(ads, ob, &keys, &blocks);
737         
738         BLI_dlrbTree_linkedlist_sync(&keys);
739         BLI_dlrbTree_linkedlist_sync(&blocks);
740         
741         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
742         
743         BLI_dlrbTree_free(&keys);
744         BLI_dlrbTree_free(&blocks);
745 }
746
747 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
748 {
749         DLRBT_Tree keys, blocks;
750         
751         bool locked = (fcu->flag & FCURVE_PROTECTED) ||
752                       ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
753                       ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
754         
755         BLI_dlrbTree_init(&keys);
756         BLI_dlrbTree_init(&blocks);
757         
758         fcurve_to_keylist(adt, fcu, &keys, &blocks);
759         
760         BLI_dlrbTree_linkedlist_sync(&keys);
761         BLI_dlrbTree_linkedlist_sync(&blocks);
762         
763         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
764         
765         BLI_dlrbTree_free(&keys);
766         BLI_dlrbTree_free(&blocks);
767 }
768
769 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
770 {
771         DLRBT_Tree keys, blocks;
772         
773         bool locked = (agrp->flag & AGRP_PROTECTED) ||
774                       ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
775         
776         BLI_dlrbTree_init(&keys);
777         BLI_dlrbTree_init(&blocks);
778         
779         agroup_to_keylist(adt, agrp, &keys, &blocks);
780         
781         BLI_dlrbTree_linkedlist_sync(&keys);
782         BLI_dlrbTree_linkedlist_sync(&blocks);
783         
784         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
785         
786         BLI_dlrbTree_free(&keys);
787         BLI_dlrbTree_free(&blocks);
788 }
789
790 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
791 {
792         DLRBT_Tree keys, blocks;
793         
794         bool locked = (act && ID_IS_LINKED_DATABLOCK(act));
795         
796         BLI_dlrbTree_init(&keys);
797         BLI_dlrbTree_init(&blocks);
798         
799         action_to_keylist(adt, act, &keys, &blocks);
800         
801         BLI_dlrbTree_linkedlist_sync(&keys);
802         BLI_dlrbTree_linkedlist_sync(&blocks);
803         
804         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
805         
806         BLI_dlrbTree_free(&keys);
807         BLI_dlrbTree_free(&blocks);
808 }
809
810 void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac)
811 {
812         DLRBT_Tree keys;
813         
814         BLI_dlrbTree_init(&keys);
815         
816         gpencil_to_keylist(ads, gpd, &keys);
817         
818         BLI_dlrbTree_linkedlist_sync(&keys);
819         
820         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, false);
821         
822         BLI_dlrbTree_free(&keys);
823 }
824
825 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac)
826 {
827         DLRBT_Tree keys;
828         
829         bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
830         
831         BLI_dlrbTree_init(&keys);
832         
833         gpl_to_keylist(ads, gpl, &keys);
834         
835         BLI_dlrbTree_linkedlist_sync(&keys);
836         
837         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
838         
839         BLI_dlrbTree_free(&keys);
840 }
841
842 void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac)
843 {
844         DLRBT_Tree keys;
845         
846         bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
847         
848         BLI_dlrbTree_init(&keys);
849         
850         mask_to_keylist(ads, masklay, &keys);
851         
852         BLI_dlrbTree_linkedlist_sync(&keys);
853         
854         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
855         
856         BLI_dlrbTree_free(&keys);
857 }
858
859 /* *************************** Keyframe List Conversions *************************** */
860
861 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
862 {
863         if (ac) {
864                 ListBase anim_data = {NULL, NULL};
865                 bAnimListElem *ale;
866                 int filter;
867                 
868                 /* get F-Curves to take keyframes from */
869                 filter = ANIMFILTER_DATA_VISIBLE;
870                 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
871                 
872                 /* loop through each F-Curve, grabbing the keyframes */
873                 for (ale = anim_data.first; ale; ale = ale->next) {
874                         /* Why not use all #eAnim_KeyType here?
875                          * All of the other key types are actually "summaries" themselves, and will just end up duplicating stuff
876                          * that comes up through standard filtering of just F-Curves.
877                          * Given the way that these work, there isn't really any benefit at all from including them. - Aligorith */
878
879                         switch (ale->datatype) {
880                                 case ALE_FCURVE:
881                                         fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
882                                         break;
883                                 case ALE_MASKLAY:
884                                         mask_to_keylist(ac->ads, ale->data, keys);
885                                         break;
886                                 case ALE_GPFRAME:
887                                         gpl_to_keylist(ac->ads, ale->data, keys);
888                                         break;
889                                 default:
890                                         // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
891                                         break;
892                         }
893                 }
894                 
895                 ANIM_animdata_freelist(&anim_data);
896         }
897 }
898
899 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
900 {
901         bAnimContext ac = {NULL};
902         ListBase anim_data = {NULL, NULL};
903         bAnimListElem *ale;
904         int filter;
905         
906         bAnimListElem dummychan = {NULL};
907         
908         if (sce == NULL)
909                 return;
910         
911         /* create a dummy wrapper data to work with */
912         dummychan.type = ANIMTYPE_SCENE;
913         dummychan.data = sce;
914         dummychan.id = &sce->id;
915         dummychan.adt = sce->adt;
916         
917         ac.ads = ads;
918         ac.data = &dummychan;
919         ac.datatype = ANIMCONT_CHANNEL;
920         
921         /* get F-Curves to take keyframes from */
922         filter = ANIMFILTER_DATA_VISIBLE; // curves only
923         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
924         
925         /* loop through each F-Curve, grabbing the keyframes */
926         for (ale = anim_data.first; ale; ale = ale->next)
927                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
928         
929         ANIM_animdata_freelist(&anim_data);
930 }
931
932 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
933 {       
934         bAnimContext ac = {NULL};
935         ListBase anim_data = {NULL, NULL};
936         bAnimListElem *ale;
937         int filter;
938         
939         bAnimListElem dummychan = {NULL};
940         Base dummybase = {NULL};
941         
942         if (ob == NULL)
943                 return;
944         
945         /* create a dummy wrapper data to work with */
946         dummybase.object = ob;
947         
948         dummychan.type = ANIMTYPE_OBJECT;
949         dummychan.data = &dummybase;
950         dummychan.id = &ob->id;
951         dummychan.adt = ob->adt;
952         
953         ac.ads = ads;
954         ac.data = &dummychan;
955         ac.datatype = ANIMCONT_CHANNEL;
956         
957         /* get F-Curves to take keyframes from */
958         filter = ANIMFILTER_DATA_VISIBLE; // curves only
959         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
960         
961         /* loop through each F-Curve, grabbing the keyframes */
962         for (ale = anim_data.first; ale; ale = ale->next)
963                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
964         
965         ANIM_animdata_freelist(&anim_data);
966 }
967
968 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, DLRBT_Tree *blocks)
969 {
970         BezTriple *bezt;
971         unsigned int v;
972
973         if (fcu && fcu->totvert && fcu->bezt) {
974                 /* apply NLA-mapping (if applicable) */
975                 if (adt)
976                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
977                 
978                 /* loop through beztriples, making ActKeysColumns and ActKeyBlocks */
979                 for (v = 0, bezt = fcu->bezt; v < fcu->totvert; v++, bezt++) {
980                         add_bezt_to_keycolumns_list(keys, bezt);
981                         if (blocks) add_bezt_to_keyblocks_list(blocks, fcu->bezt, bezt);
982                 }
983                 
984                 /* update the number of curves that elements have appeared in  */
985                 if (keys)
986                         set_touched_actkeycolumn(keys->root);
987                 if (blocks)
988                         set_touched_actkeyblock(blocks->root);
989                 
990                 /* unapply NLA-mapping if applicable */
991                 if (adt)
992                         ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
993         }
994 }
995
996 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, DLRBT_Tree *blocks)
997 {
998         FCurve *fcu;
999
1000         if (agrp) {
1001                 /* loop through F-Curves */
1002                 for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
1003                         fcurve_to_keylist(adt, fcu, keys, blocks);
1004                 }
1005         }
1006 }
1007
1008 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, DLRBT_Tree *blocks)
1009 {
1010         FCurve *fcu;
1011
1012         if (act) {
1013                 /* loop through F-Curves */
1014                 for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1015                         fcurve_to_keylist(adt, fcu, keys, blocks);
1016                 }
1017         }
1018 }
1019
1020
1021 void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys)
1022 {
1023         bGPDlayer *gpl;
1024         
1025         if (gpd && keys) {
1026                 /* for now, just aggregate out all the frames, but only for visible layers */
1027                 for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
1028                         if ((gpl->flag & GP_LAYER_HIDE) == 0) {
1029                                 gpl_to_keylist(ads, gpl, keys);
1030                         }
1031                 }
1032         }
1033 }
1034
1035 void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
1036 {
1037         bGPDframe *gpf;
1038         
1039         if (gpl && keys) {
1040                 /* although the frames should already be in an ordered list, they are not suitable for displaying yet */
1041                 for (gpf = gpl->frames.first; gpf; gpf = gpf->next)
1042                         add_gpframe_to_keycolumns_list(keys, gpf);
1043         }
1044 }
1045
1046 void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys)
1047 {
1048         MaskLayerShape *masklay_shape;
1049
1050         if (masklay && keys) {
1051                 for (masklay_shape = masklay->splines_shapes.first;
1052                      masklay_shape;
1053                      masklay_shape = masklay_shape->next)
1054                 {
1055                         add_masklay_to_keycolumns_list(keys, masklay_shape);
1056                 }
1057         }
1058 }
1059