Merge branch 'master' into blender2.8
[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_cachefile_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_scene_types.h"
50 #include "DNA_gpencil_types.h"
51 #include "DNA_mask_types.h"
52
53 #include "BKE_fcurve.h"
54
55 #include "GPU_draw.h"
56 #include "GPU_immediate.h"
57
58 #include "UI_resources.h"
59 #include "UI_view2d.h"
60
61 #include "ED_anim_api.h"
62 #include "ED_keyframes_draw.h"
63
64 /* *************************** Keyframe Processing *************************** */
65
66 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
67
68 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
69 /* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
70 short compare_ak_cfraPtr(void *node, void *data)
71 {
72         ActKeyColumn *ak = (ActKeyColumn *)node;
73         const float *cframe = data;
74         float val = *cframe;
75
76         if (IS_EQT(val, ak->cfra, BEZT_BINARYSEARCH_THRESH))
77                 return 0;
78
79         if (val < ak->cfra)
80                 return -1;
81         else if (val > ak->cfra)
82                 return 1;
83         else
84                 return 0;
85 }
86
87 /* --------------- */
88
89 /* Comparator callback used for ActKeyColumns and BezTriple */
90 static short compare_ak_bezt(void *node, void *data)
91 {
92         ActKeyColumn *ak = (ActKeyColumn *)node;
93         BezTriple *bezt = (BezTriple *)data;
94
95         if (bezt->vec[1][0] < ak->cfra)
96                 return -1;
97         else if (bezt->vec[1][0] > ak->cfra)
98                 return 1;
99         else
100                 return 0;
101 }
102
103 /* New node callback used for building ActKeyColumns from BezTriples */
104 static DLRBT_Node *nalloc_ak_bezt(void *data)
105 {
106         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
107         BezTriple *bezt = (BezTriple *)data;
108
109         /* store settings based on state of BezTriple */
110         ak->cfra = bezt->vec[1][0];
111         ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
112         ak->key_type = BEZKEYTYPE(bezt);
113
114         /* set 'modified', since this is used to identify long keyframes */
115         ak->modified = 1;
116
117         return (DLRBT_Node *)ak;
118 }
119
120 /* Node updater callback used for building ActKeyColumns from BezTriples */
121 static void nupdate_ak_bezt(void *node, void *data)
122 {
123         ActKeyColumn *ak = (ActKeyColumn *)node;
124         BezTriple *bezt = (BezTriple *)data;
125
126         /* set selection status and 'touched' status */
127         if (BEZT_ISSEL_ANY(bezt)) ak->sel = SELECT;
128         ak->modified += 1;
129
130         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
131         if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME)
132                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
133 }
134
135 /* ......... */
136
137 /* Comparator callback used for ActKeyColumns and GPencil frame */
138 static short compare_ak_gpframe(void *node, void *data)
139 {
140         ActKeyColumn *ak = (ActKeyColumn *)node;
141         bGPDframe *gpf = (bGPDframe *)data;
142
143         if (gpf->framenum < ak->cfra)
144                 return -1;
145         else if (gpf->framenum > ak->cfra)
146                 return 1;
147         else
148                 return 0;
149 }
150
151 /* New node callback used for building ActKeyColumns from GPencil frames */
152 static DLRBT_Node *nalloc_ak_gpframe(void *data)
153 {
154         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
155         bGPDframe *gpf = (bGPDframe *)data;
156
157         /* store settings based on state of BezTriple */
158         ak->cfra = gpf->framenum;
159         ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
160         ak->key_type = gpf->key_type;
161
162         /* set 'modified', since this is used to identify long keyframes */
163         ak->modified = 1;
164
165         return (DLRBT_Node *)ak;
166 }
167
168 /* Node updater callback used for building ActKeyColumns from GPencil frames */
169 static void nupdate_ak_gpframe(void *node, void *data)
170 {
171         ActKeyColumn *ak = (ActKeyColumn *)node;
172         bGPDframe *gpf = (bGPDframe *)data;
173
174         /* set selection status and 'touched' status */
175         if (gpf->flag & GP_FRAME_SELECT) ak->sel = SELECT;
176         ak->modified += 1;
177
178         /* for keyframe type, 'proper' keyframes have priority over breakdowns (and other types for now) */
179         if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME)
180                 ak->key_type = BEZT_KEYTYPE_KEYFRAME;
181 }
182
183 /* ......... */
184
185 /* Comparator callback used for ActKeyColumns and GPencil frame */
186 static short compare_ak_masklayshape(void *node, void *data)
187 {
188         ActKeyColumn *ak = (ActKeyColumn *)node;
189         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
190
191         if (masklay_shape->frame < ak->cfra)
192                 return -1;
193         else if (masklay_shape->frame > ak->cfra)
194                 return 1;
195         else
196                 return 0;
197 }
198
199 /* New node callback used for building ActKeyColumns from GPencil frames */
200 static DLRBT_Node *nalloc_ak_masklayshape(void *data)
201 {
202         ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
203         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
204
205         /* store settings based on state of BezTriple */
206         ak->cfra = masklay_shape->frame;
207         ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
208
209         /* set 'modified', since this is used to identify long keyframes */
210         ak->modified = 1;
211
212         return (DLRBT_Node *)ak;
213 }
214
215 /* Node updater callback used for building ActKeyColumns from GPencil frames */
216 static void nupdate_ak_masklayshape(void *node, void *data)
217 {
218         ActKeyColumn *ak = (ActKeyColumn *)node;
219         MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
220
221         /* set selection status and 'touched' status */
222         if (masklay_shape->flag & MASK_SHAPE_SELECT) ak->sel = SELECT;
223         ak->modified += 1;
224 }
225
226
227 /* --------------- */
228
229 /* Add the given BezTriple to the given 'list' of Keyframes */
230 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTriple *bezt)
231 {
232         if (ELEM(NULL, keys, bezt))
233                 return;
234         else
235                 BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
236 }
237
238 /* Add the given GPencil Frame to the given 'list' of Keyframes */
239 static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
240 {
241         if (ELEM(NULL, keys, gpf))
242                 return;
243         else
244                 BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
245 }
246
247 /* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
248 static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape)
249 {
250         if (ELEM(NULL, keys, masklay_shape))
251                 return;
252         else
253                 BLI_dlrbTree_add(keys, compare_ak_masklayshape, nalloc_ak_masklayshape, nupdate_ak_masklayshape, masklay_shape);
254 }
255
256 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
257
258 /* Comparator callback used for ActKeyBlock and cframe float-value pointer */
259 /* NOTE: this is exported to other modules that use the ActKeyBlocks for finding long-keyframes */
260 short compare_ab_cfraPtr(void *node, void *data)
261 {
262         ActKeyBlock *ab = (ActKeyBlock *)node;
263         const float *cframe = data;
264         float val = *cframe;
265
266         if (val < ab->start)
267                 return -1;
268         else if (val > ab->start)
269                 return 1;
270         else
271                 return 0;
272 }
273
274 /* --------------- */
275
276 /* Create a ActKeyColumn for a pair of BezTriples */
277 static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
278 {
279         ActKeyBlock *ab = MEM_callocN(sizeof(ActKeyBlock), "ActKeyBlock");
280
281         ab->start = prev->vec[1][0];
282         ab->end = beztn->vec[1][0];
283         ab->val = beztn->vec[1][1];
284
285         ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
286         ab->modified = 1;
287
288         if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
289                 ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
290
291         return ab;
292 }
293
294 static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt, BezTriple *beztn)
295 {
296         ActKeyBlock *new_ab = NULL;
297         BezTriple *prev = NULL;
298
299         /* get the BezTriple immediately before the given one which has the same value */
300         if (beztn != first_bezt) {
301                 /* XXX: Unless I'm overlooking some details from the past, this should be sufficient?
302                  *      The old code did some elaborate stuff trying to find keyframe columns for
303                  *      the given BezTriple, then step backwards to the column before that, and find
304                  *      an appropriate BezTriple with matching values there. Maybe that was warranted
305                  *      in the past, but now, that list is only ever filled with keyframes from the
306                  *      current FCurve.
307                  *
308                  *      -- Aligorith (20140415)
309                  */
310                 prev = beztn - 1;
311         }
312
313
314         /* check if block needed */
315         if (prev == NULL) return;
316
317         if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
318                 /* Animator tagged a "moving hold"
319                  *   - Previous key must also be tagged as a moving hold, otherwise
320                  *     we're just dealing with the first of a pair, and we don't
321                  *     want to be creating any phantom holds...
322                  */
323                 if (BEZKEYTYPE(prev) != BEZT_KEYTYPE_MOVEHOLD)
324                         return;
325         }
326         else {
327                 /* Check for same values...
328                  *  - Handles must have same central value as each other
329                  *  - Handles which control that section of the curve must be constant
330                  */
331                 if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
332
333                 if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
334                 if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
335         }
336
337         /* if there are no blocks already, just add as root */
338         if (blocks->root == NULL) {
339                 /* just add this as the root, then call the tree-balancing functions to validate */
340                 new_ab = bezts_to_new_actkeyblock(prev, beztn);
341                 blocks->root = (DLRBT_Node *)new_ab;
342         }
343         else {
344                 ActKeyBlock *ab, *abn = NULL;
345
346                 /* try to find a keyblock that starts on the previous beztriple, and add a new one if none start there
347                  * Note: we perform a tree traversal here NOT a standard linked-list traversal...
348                  * Note: we can't search from end to try to optimize this as it causes errors there's
349                  *      an A ___ B |---| B situation
350                  */
351                 // FIXME: here there is a bug where we are trying to get the summary for the following channels
352                 //              A|--------------|A ______________ B|--------------|B
353                 //              A|------------------------------------------------|A
354                 //              A|----|A|---|A|-----------------------------------|A
355                 for (ab = blocks->root; ab; ab = abn) {
356                         /* check if this is a match, or whether we go left or right
357                          * NOTE: we now use a float threshold to prevent precision errors causing problems with summaries
358                          */
359                         if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
360                                 /* set selection status and 'touched' status */
361                                 if (BEZT_ISSEL_ANY(beztn))
362                                         ab->sel = SELECT;
363
364                                 /* XXX: only when the first one was a moving hold? */
365                                 if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
366                                         ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
367
368                                 ab->modified++;
369
370                                 /* done... no need to insert */
371                                 return;
372                         }
373                         else {
374                                 ActKeyBlock **abnp = NULL; /* branch to go down - used to hook new blocks to parents */
375
376                                 /* check if go left or right, but if not available, add new node */
377                                 if (ab->start < prev->vec[1][0])
378                                         abnp = &ab->right;
379                                 else
380                                         abnp = &ab->left;
381
382                                 /* if this does not exist, add a new node, otherwise continue... */
383                                 if (*abnp == NULL) {
384                                         /* add a new node representing this, and attach it to the relevant place */
385                                         new_ab = bezts_to_new_actkeyblock(prev, beztn);
386                                         new_ab->parent = ab;
387                                         *abnp = new_ab;
388                                         break;
389                                 }
390                                 else
391                                         abn = *abnp;
392                         }
393                 }
394         }
395
396         /* now, balance the tree taking into account this newly added node */
397         BLI_dlrbTree_insert(blocks, (DLRBT_Node *)new_ab);
398 }
399
400 /* --------- */
401
402 /* Handle the 'touched' status of ActKeyColumn tree nodes */
403 static void set_touched_actkeycolumn(ActKeyColumn *ak)
404 {
405         /* sanity check */
406         if (ak == NULL)
407                 return;
408
409         /* deal with self first */
410         if (ak->modified) {
411                 ak->modified = 0;
412                 ak->totcurve++;
413         }
414
415         /* children */
416         set_touched_actkeycolumn(ak->left);
417         set_touched_actkeycolumn(ak->right);
418 }
419
420 /* Handle the 'touched' status of ActKeyBlock tree nodes */
421 static void set_touched_actkeyblock(ActKeyBlock *ab)
422 {
423         /* sanity check */
424         if (ab == NULL)
425                 return;
426
427         /* deal with self first */
428         if (ab->modified) {
429                 ab->modified = 0;
430                 ab->totcurve++;
431         }
432
433         /* children */
434         set_touched_actkeyblock(ab->left);
435         set_touched_actkeyblock(ab->right);
436 }
437
438 /* --------- */
439
440 /* Checks if ActKeyBlock should exist... */
441 bool actkeyblock_is_valid(ActKeyBlock *ab, DLRBT_Tree *keys)
442 {
443         ActKeyColumn *ak;
444         short startCurves, endCurves, totCurves;
445
446         /* check that block is valid */
447         if (ab == NULL)
448                 return 0;
449
450         /* find out how many curves occur at each keyframe */
451         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->start);
452         startCurves = (ak) ? ak->totcurve : 0;
453
454         ak = (ActKeyColumn *)BLI_dlrbTree_search_exact(keys, compare_ak_cfraPtr, &ab->end);
455         endCurves = (ak) ? ak->totcurve : 0;
456
457         /* only draw keyblock if it appears in at all of the keyframes at lowest end */
458         if (!startCurves && !endCurves)
459                 return 0;
460
461         totCurves = (startCurves > endCurves) ? endCurves : startCurves;
462         return (ab->totcurve >= totCurves);
463 }
464
465 /* *************************** Keyframe Drawing *************************** */
466
467 void draw_keyframe_shape(float x, float y, float size, bool sel, short key_type, short mode, float alpha,
468                          unsigned int pos_id, unsigned int size_id, unsigned int color_id, unsigned int outline_color_id)
469 {
470         bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
471         bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
472
473         BLI_assert(draw_fill || draw_outline);
474
475         /* tweak size of keyframe shape according to type of keyframe
476          * - 'proper' keyframes have key_type = 0, so get drawn at full size
477          */
478         switch (key_type) {
479                 case BEZT_KEYTYPE_KEYFRAME:  /* must be full size */
480                         break;
481
482                 case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
483                         size *= 0.85f;
484                         break;
485
486                 case BEZT_KEYTYPE_MOVEHOLD:  /* slightly smaller than normal keyframes (but by less than for breakdowns) */
487                         size *= 0.925f;
488                         break;
489
490                 case BEZT_KEYTYPE_EXTREME:   /* slightly larger */
491                         size *= 1.2f;
492                         break;
493
494                 default:
495                         size -= 0.8f * key_type;
496         }
497
498         unsigned char fill_col[4];
499         unsigned char outline_col[4];
500
501         /* draw! */
502         if (draw_fill) {
503                 /* get interior colors from theme (for selected and unselected only) */
504                 switch (key_type) {
505                         case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
506                                 UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
507                                 break;
508                         case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
509                                 UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
510                                 break;
511                         case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
512                                 UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
513                                 break;
514                         case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
515                                 /* XXX: Should these get their own theme options instead? */
516                                 if (sel) UI_GetThemeColorShade3ubv(TH_STRIP_SELECT, 35, fill_col);
517                                 else UI_GetThemeColorShade3ubv(TH_STRIP, 50, fill_col);
518                                 fill_col[3] = 255; /* full opacity, to avoid problems with visual glitches */
519                                 break;
520                         case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
521                         default:
522                                 UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
523                 }
524
525                 /* NOTE: we don't use the straight alpha from the theme, or else effects such as
526                  * graying out protected/muted channels doesn't work correctly!
527                  */
528                 fill_col[3] *= alpha;
529
530                 if (!draw_outline) {
531                         /* force outline color to match */
532                         outline_col[0] = fill_col[0];
533                         outline_col[1] = fill_col[1];
534                         outline_col[2] = fill_col[2];
535                         outline_col[3] = fill_col[3];
536                 }
537         }
538
539         if (draw_outline) {
540                 /* exterior - black frame */
541                 UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
542                 outline_col[3] *= alpha;
543
544                 if (!draw_fill) {
545                         /* fill color needs to be (outline.rgb, 0) */
546                         fill_col[0] = outline_col[0];
547                         fill_col[1] = outline_col[1];
548                         fill_col[2] = outline_col[2];
549                         fill_col[3] = 0;
550                 }
551         }
552
553         immAttrib1f(size_id, size);
554         immAttrib4ubv(color_id, fill_col);
555         immAttrib4ubv(outline_color_id, outline_col);
556         immVertex2f(pos_id, x, y);
557 }
558
559 static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
560 {
561         const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
562         const float half_icon_sz = 0.5f * icon_sz;
563
564         glEnable(GL_BLEND);
565
566         /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
567         /* TODO: allow this opacity factor to be themed? */
568         float alpha = channelLocked ? 0.25f : 1.0f;
569
570         /* draw keyblocks */
571         if (blocks) {
572                 float sel_color[4], unsel_color[4];
573                 float sel_mhcol[4], unsel_mhcol[4];
574
575                 /* cache colours first */
576                 UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
577                 UI_GetThemeColor4fv(TH_STRIP, unsel_color);
578
579                 sel_color[3]   *= alpha;
580                 unsel_color[3] *= alpha;
581
582                 copy_v4_v4(sel_mhcol, sel_color);
583                 sel_mhcol[3]   *= 0.8f;
584                 copy_v4_v4(unsel_mhcol, unsel_color);
585                 unsel_mhcol[3] *= 0.8f;
586
587                 unsigned int block_ct = 0;
588                 for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
589                         if (actkeyblock_is_valid(ab, keys)) {
590                                 block_ct++;
591                         }
592                 }
593
594                 if (block_ct > 0) {
595                         Gwn_VertFormat *format = immVertexFormat();
596                         unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
597                         unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
598                         immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
599
600                         immBegin(GWN_PRIM_TRIS, 6 * block_ct);
601                         for (ActKeyBlock *ab = blocks->first; ab; ab = ab->next) {
602                                 if (actkeyblock_is_valid(ab, keys)) {
603                                         if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
604                                                 /* draw "moving hold" long-keyframe block - slightly smaller */
605                                                 immRectf_fast_with_color(pos_id, color_id,
606                                                                          ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
607                                                                          (ab->sel) ? sel_mhcol : unsel_mhcol);
608                                         }
609                                         else {
610                                                 /* draw standard long-keyframe block */
611                                                 immRectf_fast_with_color(pos_id, color_id,
612                                                                          ab->start, ypos - half_icon_sz, ab->end, ypos + half_icon_sz,
613                                                                          (ab->sel) ? sel_color : unsel_color);
614                                         }
615                                 }
616                         }
617                         immEnd();
618                         immUnbindProgram();
619                 }
620         }
621
622         if (keys) {
623                 /* count keys */
624                 unsigned int key_ct = 0;
625                 for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
626                         /* optimization: if keyframe doesn't appear within 5 units (screenspace) in visible area, don't draw
627                          *      - this might give some improvements, since we current have to flip between view/region matrices
628                          */
629                         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax))
630                                 key_ct++;
631                 }
632
633                 if (key_ct > 0) {
634                         /* draw keys */
635                         Gwn_VertFormat *format = immVertexFormat();
636                         unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
637                         unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
638                         unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
639                         unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
640                         immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
641                         GPU_enable_program_point_size();
642                         immBegin(GWN_PRIM_POINTS, key_ct);
643
644                         for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
645                                 if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
646                                         draw_keyframe_shape(ak->cfra, ypos, icon_sz, (ak->sel & SELECT), ak->key_type, KEYFRAME_SHAPE_BOTH, alpha,
647                                                             pos_id, size_id, color_id, outline_color_id);
648                                 }
649                         }
650
651                         immEnd();
652                         GPU_disable_program_point_size();
653                         immUnbindProgram();
654                 }
655         }
656
657         glDisable(GL_BLEND);
658 }
659
660 /* *************************** Channel Drawing Funcs *************************** */
661
662 void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
663 {
664         DLRBT_Tree keys, blocks;
665
666         BLI_dlrbTree_init(&keys);
667         BLI_dlrbTree_init(&blocks);
668
669         summary_to_keylist(ac, &keys, &blocks);
670
671         BLI_dlrbTree_linkedlist_sync(&keys);
672         BLI_dlrbTree_linkedlist_sync(&blocks);
673
674         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
675
676         BLI_dlrbTree_free(&keys);
677         BLI_dlrbTree_free(&blocks);
678 }
679
680 void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
681 {
682         DLRBT_Tree keys, blocks;
683
684         BLI_dlrbTree_init(&keys);
685         BLI_dlrbTree_init(&blocks);
686
687         scene_to_keylist(ads, sce, &keys, &blocks);
688
689         BLI_dlrbTree_linkedlist_sync(&keys);
690         BLI_dlrbTree_linkedlist_sync(&blocks);
691
692         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
693
694         BLI_dlrbTree_free(&keys);
695         BLI_dlrbTree_free(&blocks);
696 }
697
698 void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
699 {
700         DLRBT_Tree keys, blocks;
701
702         BLI_dlrbTree_init(&keys);
703         BLI_dlrbTree_init(&blocks);
704
705         ob_to_keylist(ads, ob, &keys, &blocks);
706
707         BLI_dlrbTree_linkedlist_sync(&keys);
708         BLI_dlrbTree_linkedlist_sync(&blocks);
709
710         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
711
712         BLI_dlrbTree_free(&keys);
713         BLI_dlrbTree_free(&blocks);
714 }
715
716 void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
717 {
718         DLRBT_Tree keys, blocks;
719
720         bool locked = (fcu->flag & FCURVE_PROTECTED) ||
721                       ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
722                       ((adt && adt->action) && ID_IS_LINKED(adt->action));
723
724         BLI_dlrbTree_init(&keys);
725         BLI_dlrbTree_init(&blocks);
726
727         fcurve_to_keylist(adt, fcu, &keys, &blocks);
728
729         BLI_dlrbTree_linkedlist_sync(&keys);
730         BLI_dlrbTree_linkedlist_sync(&blocks);
731
732         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
733
734         BLI_dlrbTree_free(&keys);
735         BLI_dlrbTree_free(&blocks);
736 }
737
738 void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
739 {
740         DLRBT_Tree keys, blocks;
741
742         bool locked = (agrp->flag & AGRP_PROTECTED) ||
743                       ((adt && adt->action) && ID_IS_LINKED(adt->action));
744
745         BLI_dlrbTree_init(&keys);
746         BLI_dlrbTree_init(&blocks);
747
748         agroup_to_keylist(adt, agrp, &keys, &blocks);
749
750         BLI_dlrbTree_linkedlist_sync(&keys);
751         BLI_dlrbTree_linkedlist_sync(&blocks);
752
753         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
754
755         BLI_dlrbTree_free(&keys);
756         BLI_dlrbTree_free(&blocks);
757 }
758
759 void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
760 {
761         DLRBT_Tree keys, blocks;
762
763         bool locked = (act && ID_IS_LINKED(act));
764
765         BLI_dlrbTree_init(&keys);
766         BLI_dlrbTree_init(&blocks);
767
768         action_to_keylist(adt, act, &keys, &blocks);
769
770         BLI_dlrbTree_linkedlist_sync(&keys);
771         BLI_dlrbTree_linkedlist_sync(&blocks);
772
773         draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
774
775         BLI_dlrbTree_free(&keys);
776         BLI_dlrbTree_free(&blocks);
777 }
778
779 void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac)
780 {
781         DLRBT_Tree keys;
782
783         BLI_dlrbTree_init(&keys);
784
785         gpencil_to_keylist(ads, gpd, &keys);
786
787         BLI_dlrbTree_linkedlist_sync(&keys);
788
789         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, false);
790
791         BLI_dlrbTree_free(&keys);
792 }
793
794 void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac)
795 {
796         DLRBT_Tree keys;
797
798         bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
799
800         BLI_dlrbTree_init(&keys);
801
802         gpl_to_keylist(ads, gpl, &keys);
803
804         BLI_dlrbTree_linkedlist_sync(&keys);
805
806         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
807
808         BLI_dlrbTree_free(&keys);
809 }
810
811 void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac)
812 {
813         DLRBT_Tree keys;
814
815         bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
816
817         BLI_dlrbTree_init(&keys);
818
819         mask_to_keylist(ads, masklay, &keys);
820
821         BLI_dlrbTree_linkedlist_sync(&keys);
822
823         draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
824
825         BLI_dlrbTree_free(&keys);
826 }
827
828 /* *************************** Keyframe List Conversions *************************** */
829
830 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, DLRBT_Tree *blocks)
831 {
832         if (ac) {
833                 ListBase anim_data = {NULL, NULL};
834                 bAnimListElem *ale;
835                 int filter;
836
837                 /* get F-Curves to take keyframes from */
838                 filter = ANIMFILTER_DATA_VISIBLE;
839                 ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
840
841                 /* loop through each F-Curve, grabbing the keyframes */
842                 for (ale = anim_data.first; ale; ale = ale->next) {
843                         /* Why not use all #eAnim_KeyType here?
844                          * All of the other key types are actually "summaries" themselves, and will just end up duplicating stuff
845                          * that comes up through standard filtering of just F-Curves.
846                          * Given the way that these work, there isn't really any benefit at all from including them. - Aligorith */
847
848                         switch (ale->datatype) {
849                                 case ALE_FCURVE:
850                                         fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
851                                         break;
852                                 case ALE_MASKLAY:
853                                         mask_to_keylist(ac->ads, ale->data, keys);
854                                         break;
855                                 case ALE_GPFRAME:
856                                         gpl_to_keylist(ac->ads, ale->data, keys);
857                                         break;
858                                 default:
859                                         // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
860                                         break;
861                         }
862                 }
863
864                 ANIM_animdata_freelist(&anim_data);
865         }
866 }
867
868 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, DLRBT_Tree *blocks)
869 {
870         bAnimContext ac = {NULL};
871         ListBase anim_data = {NULL, NULL};
872         bAnimListElem *ale;
873         int filter;
874
875         bAnimListElem dummychan = {NULL};
876
877         if (sce == NULL)
878                 return;
879
880         /* create a dummy wrapper data to work with */
881         dummychan.type = ANIMTYPE_SCENE;
882         dummychan.data = sce;
883         dummychan.id = &sce->id;
884         dummychan.adt = sce->adt;
885
886         ac.ads = ads;
887         ac.data = &dummychan;
888         ac.datatype = ANIMCONT_CHANNEL;
889
890         /* get F-Curves to take keyframes from */
891         filter = ANIMFILTER_DATA_VISIBLE; // curves only
892         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
893
894         /* loop through each F-Curve, grabbing the keyframes */
895         for (ale = anim_data.first; ale; ale = ale->next)
896                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
897
898         ANIM_animdata_freelist(&anim_data);
899 }
900
901 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, DLRBT_Tree *blocks)
902 {
903         bAnimContext ac = {NULL};
904         ListBase anim_data = {NULL, NULL};
905         bAnimListElem *ale;
906         int filter;
907
908         bAnimListElem dummychan = {NULL};
909         Base dummybase = {NULL};
910
911         if (ob == NULL)
912                 return;
913
914         /* create a dummy wrapper data to work with */
915         dummybase.object = ob;
916
917         dummychan.type = ANIMTYPE_OBJECT;
918         dummychan.data = &dummybase;
919         dummychan.id = &ob->id;
920         dummychan.adt = ob->adt;
921
922         ac.ads = ads;
923         ac.data = &dummychan;
924         ac.datatype = ANIMCONT_CHANNEL;
925
926         /* get F-Curves to take keyframes from */
927         filter = ANIMFILTER_DATA_VISIBLE; // curves only
928         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
929
930         /* loop through each F-Curve, grabbing the keyframes */
931         for (ale = anim_data.first; ale; ale = ale->next)
932                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
933
934         ANIM_animdata_freelist(&anim_data);
935 }
936
937 void cachefile_to_keylist(bDopeSheet *ads, CacheFile *cache_file, DLRBT_Tree *keys, DLRBT_Tree *blocks)
938 {
939         if (cache_file == NULL) {
940                 return;
941         }
942
943         /* create a dummy wrapper data to work with */
944         bAnimListElem dummychan = {NULL};
945         dummychan.type = ANIMTYPE_DSCACHEFILE;
946         dummychan.data = cache_file;
947         dummychan.id = &cache_file->id;
948         dummychan.adt = cache_file->adt;
949
950         bAnimContext ac = {NULL};
951         ac.ads = ads;
952         ac.data = &dummychan;
953         ac.datatype = ANIMCONT_CHANNEL;
954
955         /* get F-Curves to take keyframes from */
956         ListBase anim_data = { NULL, NULL };
957         int filter = ANIMFILTER_DATA_VISIBLE; // curves only
958         ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
959
960         /* loop through each F-Curve, grabbing the keyframes */
961         for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
962                 fcurve_to_keylist(ale->adt, ale->data, keys, blocks);
963         }
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