Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / animation / keyframes_draw.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation, Joshua Leung
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup edanimation
22  */
23
24 /* System includes ----------------------------------------------------- */
25
26 #include <math.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <float.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_dlrbTree.h"
34 #include "BLI_math.h"
35 #include "BLI_utildefines.h"
36 #include "BLI_rect.h"
37
38 #include "DNA_anim_types.h"
39 #include "DNA_cachefile_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_gpencil_types.h"
43 #include "DNA_brush_types.h"
44 #include "DNA_mask_types.h"
45
46 #include "BKE_fcurve.h"
47
48 #include "GPU_draw.h"
49 #include "GPU_immediate.h"
50 #include "GPU_state.h"
51
52 #include "UI_resources.h"
53 #include "UI_view2d.h"
54
55 #include "ED_anim_api.h"
56 #include "ED_keyframes_draw.h"
57
58 /* *************************** Keyframe Processing *************************** */
59
60 /* ActKeyColumns (Keyframe Columns) ------------------------------------------ */
61
62 BLI_INLINE bool is_cfra_eq(float a, float b)
63 {
64   return IS_EQT(a, b, BEZT_BINARYSEARCH_THRESH);
65 }
66
67 BLI_INLINE bool is_cfra_lt(float a, float b)
68 {
69   return (b - a) > BEZT_BINARYSEARCH_THRESH;
70 }
71
72 /* Comparator callback used for ActKeyColumns and cframe float-value pointer */
73 /* NOTE: this is exported to other modules that use the ActKeyColumns for finding keyframes */
74 short compare_ak_cfraPtr(void *node, void *data)
75 {
76   ActKeyColumn *ak = (ActKeyColumn *)node;
77   const float *cframe = data;
78   float val = *cframe;
79
80   if (is_cfra_eq(val, ak->cfra)) {
81     return 0;
82   }
83
84   if (val < ak->cfra) {
85     return -1;
86   }
87   else {
88     return 1;
89   }
90 }
91
92 /* --------------- */
93
94 /* Set of references to three logically adjacent keys. */
95 typedef struct BezTripleChain {
96   /* Current keyframe. */
97   BezTriple *cur;
98
99   /* Logical neighbors. May be NULL. */
100   BezTriple *prev, *next;
101 } BezTripleChain;
102
103 /* Categorize the interpolation & handle type of the keyframe. */
104 static eKeyframeHandleDrawOpts bezt_handle_type(BezTriple *bezt)
105 {
106   if (bezt->h1 == HD_AUTO_ANIM && bezt->h2 == HD_AUTO_ANIM) {
107     return KEYFRAME_HANDLE_AUTO_CLAMP;
108   }
109   else if (ELEM(bezt->h1, HD_AUTO_ANIM, HD_AUTO) && ELEM(bezt->h2, HD_AUTO_ANIM, HD_AUTO)) {
110     return KEYFRAME_HANDLE_AUTO;
111   }
112   else if (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) {
113     return KEYFRAME_HANDLE_VECTOR;
114   }
115   else if (ELEM(HD_FREE, bezt->h1, bezt->h2)) {
116     return KEYFRAME_HANDLE_FREE;
117   }
118   else {
119     return KEYFRAME_HANDLE_ALIGNED;
120   }
121 }
122
123 /* Determine if the keyframe is an extreme by comparing with neighbors.
124  * Ends of fixed-value sections and of the whole curve are also marked.
125  */
126 static eKeyframeExtremeDrawOpts bezt_extreme_type(BezTripleChain *chain)
127 {
128   if (chain->prev == NULL && chain->next == NULL) {
129     return KEYFRAME_EXTREME_NONE;
130   }
131
132   /* Keyframe values for the current one and neighbors. */
133   float cur_y = chain->cur->vec[1][1];
134   float prev_y = cur_y, next_y = cur_y;
135
136   if (chain->prev && !IS_EQF(cur_y, chain->prev->vec[1][1])) {
137     prev_y = chain->prev->vec[1][1];
138   }
139   if (chain->next && !IS_EQF(cur_y, chain->next->vec[1][1])) {
140     next_y = chain->next->vec[1][1];
141   }
142
143   /* Static hold. */
144   if (prev_y == cur_y && next_y == cur_y) {
145     return KEYFRAME_EXTREME_FLAT;
146   }
147
148   /* Middle of an incline. */
149   if ((prev_y < cur_y && next_y > cur_y) || (prev_y > cur_y && next_y < cur_y)) {
150     return KEYFRAME_EXTREME_NONE;
151   }
152
153   /* Bezier handle values for the overshoot check. */
154   bool l_bezier = chain->prev && chain->prev->ipo == BEZT_IPO_BEZ;
155   bool r_bezier = chain->next && chain->cur->ipo == BEZT_IPO_BEZ;
156   float handle_l = l_bezier ? chain->cur->vec[0][1] : cur_y;
157   float handle_r = r_bezier ? chain->cur->vec[2][1] : cur_y;
158
159   /* Detect extremes. One of the neighbors is allowed to be equal to current. */
160   if (prev_y < cur_y || next_y < cur_y) {
161     bool is_overshoot = (handle_l > cur_y || handle_r > cur_y);
162
163     return KEYFRAME_EXTREME_MAX | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
164   }
165
166   if (prev_y > cur_y || next_y > cur_y) {
167     bool is_overshoot = (handle_l < cur_y || handle_r < cur_y);
168
169     return KEYFRAME_EXTREME_MIN | (is_overshoot ? KEYFRAME_EXTREME_MIXED : 0);
170   }
171
172   return KEYFRAME_EXTREME_NONE;
173 }
174
175 /* Comparator callback used for ActKeyColumns and BezTripleChain */
176 static short compare_ak_bezt(void *node, void *data)
177 {
178   BezTripleChain *chain = data;
179
180   return compare_ak_cfraPtr(node, &chain->cur->vec[1][0]);
181 }
182
183 /* New node callback used for building ActKeyColumns from BezTripleChain */
184 static DLRBT_Node *nalloc_ak_bezt(void *data)
185 {
186   ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumn");
187   BezTripleChain *chain = data;
188   BezTriple *bezt = chain->cur;
189
190   /* store settings based on state of BezTriple */
191   ak->cfra = bezt->vec[1][0];
192   ak->sel = BEZT_ISSEL_ANY(bezt) ? SELECT : 0;
193   ak->key_type = BEZKEYTYPE(bezt);
194   ak->handle_type = bezt_handle_type(bezt);
195   ak->extreme_type = bezt_extreme_type(chain);
196
197   /* count keyframes in this column */
198   ak->totkey = 1;
199
200   return (DLRBT_Node *)ak;
201 }
202
203 /* Node updater callback used for building ActKeyColumns from BezTripleChain */
204 static void nupdate_ak_bezt(void *node, void *data)
205 {
206   ActKeyColumn *ak = node;
207   BezTripleChain *chain = data;
208   BezTriple *bezt = chain->cur;
209
210   /* set selection status and 'touched' status */
211   if (BEZT_ISSEL_ANY(bezt)) {
212     ak->sel = SELECT;
213   }
214
215   /* count keyframes in this column */
216   ak->totkey++;
217
218   /* For keyframe type, 'proper' keyframes have priority over breakdowns
219    * (and other types for now). */
220   if (BEZKEYTYPE(bezt) == BEZT_KEYTYPE_KEYFRAME) {
221     ak->key_type = BEZT_KEYTYPE_KEYFRAME;
222   }
223
224   /* For interpolation type, select the highest value (enum is sorted). */
225   ak->handle_type = MAX2(ak->handle_type, bezt_handle_type(bezt));
226
227   /* For extremes, detect when combining different states. */
228   char new_extreme = bezt_extreme_type(chain);
229
230   if (new_extreme != ak->extreme_type) {
231     /* Replace the flat status without adding mixed. */
232     if (ak->extreme_type == KEYFRAME_EXTREME_FLAT) {
233       ak->extreme_type = new_extreme;
234     }
235     else if (new_extreme != KEYFRAME_EXTREME_FLAT) {
236       ak->extreme_type |= (new_extreme | KEYFRAME_EXTREME_MIXED);
237     }
238   }
239 }
240
241 /* ......... */
242
243 /* Comparator callback used for ActKeyColumns and GPencil frame */
244 static short compare_ak_gpframe(void *node, void *data)
245 {
246   bGPDframe *gpf = (bGPDframe *)data;
247
248   float frame = gpf->framenum;
249   return compare_ak_cfraPtr(node, &frame);
250 }
251
252 /* New node callback used for building ActKeyColumns from GPencil frames */
253 static DLRBT_Node *nalloc_ak_gpframe(void *data)
254 {
255   ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
256   bGPDframe *gpf = (bGPDframe *)data;
257
258   /* store settings based on state of BezTriple */
259   ak->cfra = gpf->framenum;
260   ak->sel = (gpf->flag & GP_FRAME_SELECT) ? SELECT : 0;
261   ak->key_type = gpf->key_type;
262
263   /* count keyframes in this column */
264   ak->totkey = 1;
265
266   return (DLRBT_Node *)ak;
267 }
268
269 /* Node updater callback used for building ActKeyColumns from GPencil frames */
270 static void nupdate_ak_gpframe(void *node, void *data)
271 {
272   ActKeyColumn *ak = (ActKeyColumn *)node;
273   bGPDframe *gpf = (bGPDframe *)data;
274
275   /* set selection status and 'touched' status */
276   if (gpf->flag & GP_FRAME_SELECT) {
277     ak->sel = SELECT;
278   }
279
280   /* count keyframes in this column */
281   ak->totkey++;
282
283   /* for keyframe type, 'proper' keyframes have priority over breakdowns
284    * (and other types for now). */
285   if (gpf->key_type == BEZT_KEYTYPE_KEYFRAME) {
286     ak->key_type = BEZT_KEYTYPE_KEYFRAME;
287   }
288 }
289
290 /* ......... */
291
292 /* Comparator callback used for ActKeyColumns and GPencil frame */
293 static short compare_ak_masklayshape(void *node, void *data)
294 {
295   MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
296
297   float frame = masklay_shape->frame;
298   return compare_ak_cfraPtr(node, &frame);
299 }
300
301 /* New node callback used for building ActKeyColumns from GPencil frames */
302 static DLRBT_Node *nalloc_ak_masklayshape(void *data)
303 {
304   ActKeyColumn *ak = MEM_callocN(sizeof(ActKeyColumn), "ActKeyColumnGPF");
305   MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
306
307   /* store settings based on state of BezTriple */
308   ak->cfra = masklay_shape->frame;
309   ak->sel = (masklay_shape->flag & MASK_SHAPE_SELECT) ? SELECT : 0;
310
311   /* count keyframes in this column */
312   ak->totkey = 1;
313
314   return (DLRBT_Node *)ak;
315 }
316
317 /* Node updater callback used for building ActKeyColumns from GPencil frames */
318 static void nupdate_ak_masklayshape(void *node, void *data)
319 {
320   ActKeyColumn *ak = (ActKeyColumn *)node;
321   MaskLayerShape *masklay_shape = (MaskLayerShape *)data;
322
323   /* set selection status and 'touched' status */
324   if (masklay_shape->flag & MASK_SHAPE_SELECT) {
325     ak->sel = SELECT;
326   }
327
328   /* count keyframes in this column */
329   ak->totkey++;
330 }
331
332 /* --------------- */
333
334 /* Add the given BezTriple to the given 'list' of Keyframes */
335 static void add_bezt_to_keycolumns_list(DLRBT_Tree *keys, BezTripleChain *bezt)
336 {
337   if (ELEM(NULL, keys, bezt)) {
338     return;
339   }
340   else {
341     BLI_dlrbTree_add(keys, compare_ak_bezt, nalloc_ak_bezt, nupdate_ak_bezt, bezt);
342   }
343 }
344
345 /* Add the given GPencil Frame to the given 'list' of Keyframes */
346 static void add_gpframe_to_keycolumns_list(DLRBT_Tree *keys, bGPDframe *gpf)
347 {
348   if (ELEM(NULL, keys, gpf)) {
349     return;
350   }
351   else {
352     BLI_dlrbTree_add(keys, compare_ak_gpframe, nalloc_ak_gpframe, nupdate_ak_gpframe, gpf);
353   }
354 }
355
356 /* Add the given MaskLayerShape Frame to the given 'list' of Keyframes */
357 static void add_masklay_to_keycolumns_list(DLRBT_Tree *keys, MaskLayerShape *masklay_shape)
358 {
359   if (ELEM(NULL, keys, masklay_shape)) {
360     return;
361   }
362   else {
363     BLI_dlrbTree_add(keys,
364                      compare_ak_masklayshape,
365                      nalloc_ak_masklayshape,
366                      nupdate_ak_masklayshape,
367                      masklay_shape);
368   }
369 }
370
371 /* ActKeyBlocks (Long Keyframes) ------------------------------------------ */
372
373 static const ActKeyBlockInfo dummy_keyblock = {0};
374
375 static void compute_keyblock_data(ActKeyBlockInfo *info, BezTriple *prev, BezTriple *beztn)
376 {
377   memset(info, 0, sizeof(ActKeyBlockInfo));
378
379   if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
380     /* Animator tagged a "moving hold"
381      *   - Previous key must also be tagged as a moving hold, otherwise
382      *     we're just dealing with the first of a pair, and we don't
383      *     want to be creating any phantom holds...
384      */
385     if (BEZKEYTYPE(prev) == BEZT_KEYTYPE_MOVEHOLD) {
386       info->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
387     }
388   }
389
390   /* Check for same values...
391    *  - Handles must have same central value as each other
392    *  - Handles which control that section of the curve must be constant
393    */
394   if (IS_EQF(beztn->vec[1][1], prev->vec[1][1])) {
395     bool hold;
396
397     /* Only check handles in case of actual bezier interpolation. */
398     if (prev->ipo == BEZT_IPO_BEZ) {
399       hold = IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) &&
400              IS_EQF(prev->vec[1][1], prev->vec[2][1]);
401     }
402     /* This interpolation type induces movement even between identical keys. */
403     else {
404       hold = !ELEM(prev->ipo, BEZT_IPO_ELASTIC);
405     }
406
407     if (hold) {
408       info->flag |= ACTKEYBLOCK_FLAG_STATIC_HOLD | ACTKEYBLOCK_FLAG_ANY_HOLD;
409     }
410   }
411
412   /* Remember non-bezier interpolation info. */
413   if (prev->ipo != BEZT_IPO_BEZ) {
414     info->flag |= ACTKEYBLOCK_FLAG_NON_BEZIER;
415   }
416
417   info->sel = BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn);
418 }
419
420 static void add_keyblock_info(ActKeyColumn *col, const ActKeyBlockInfo *block)
421 {
422   /* New curve and block. */
423   if (col->totcurve <= 1 && col->totblock == 0) {
424     memcpy(&col->block, block, sizeof(ActKeyBlockInfo));
425   }
426   /* Existing curve. */
427   else {
428     col->block.conflict |= (col->block.flag ^ block->flag);
429     col->block.flag |= block->flag;
430     col->block.sel |= block->sel;
431   }
432
433   if (block->flag) {
434     col->totblock++;
435   }
436 }
437
438 static void add_bezt_to_keyblocks_list(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len)
439 {
440   ActKeyColumn *col = keys->first;
441
442   if (bezt && bezt_len >= 2) {
443     ActKeyBlockInfo block;
444
445     /* Find the first key column while inserting dummy blocks. */
446     for (; col != NULL && is_cfra_lt(col->cfra, bezt[0].vec[1][0]); col = col->next) {
447       add_keyblock_info(col, &dummy_keyblock);
448     }
449
450     BLI_assert(col != NULL);
451
452     /* Insert real blocks. */
453     for (int v = 1; col != NULL && v < bezt_len; v++, bezt++) {
454       /* Wrong order of bezier keys: resync position. */
455       if (is_cfra_lt(bezt[1].vec[1][0], bezt[0].vec[1][0])) {
456         /* Backtrack to find the right location. */
457         if (is_cfra_lt(bezt[1].vec[1][0], col->cfra)) {
458           ActKeyColumn *newcol = (ActKeyColumn *)BLI_dlrbTree_search_exact(
459               keys, compare_ak_cfraPtr, &bezt[1].vec[1][0]);
460
461           if (newcol != NULL) {
462             col = newcol;
463
464             /* The previous keyblock is garbage too. */
465             if (col->prev != NULL) {
466               add_keyblock_info(col->prev, &dummy_keyblock);
467             }
468           }
469           else {
470             BLI_assert(false);
471           }
472         }
473
474         continue;
475       }
476
477       /* Normal sequence */
478       BLI_assert(is_cfra_eq(col->cfra, bezt[0].vec[1][0]));
479
480       compute_keyblock_data(&block, bezt, bezt + 1);
481
482       for (; col != NULL && is_cfra_lt(col->cfra, bezt[1].vec[1][0]); col = col->next) {
483         add_keyblock_info(col, &block);
484       }
485
486       BLI_assert(col != NULL);
487     }
488   }
489
490   /* Insert dummy blocks at the end. */
491   for (; col != NULL; col = col->next) {
492     add_keyblock_info(col, &dummy_keyblock);
493   }
494 }
495
496 /* Walk through columns and propagate blocks and totcurve.
497  *
498  * This must be called even by animation sources that don't generate
499  * keyblocks to keep the data structure consistent after adding columns.
500  */
501 static void update_keyblocks(DLRBT_Tree *keys, BezTriple *bezt, int bezt_len)
502 {
503   /* Recompute the prev/next linked list. */
504   BLI_dlrbTree_linkedlist_sync(keys);
505
506   /* Find the curve count */
507   int max_curve = 0;
508
509   for (ActKeyColumn *col = keys->first; col; col = col->next) {
510     max_curve = MAX2(max_curve, col->totcurve);
511   }
512
513   /* Propagate blocks to inserted keys */
514   ActKeyColumn *prev_ready = NULL;
515
516   for (ActKeyColumn *col = keys->first; col; col = col->next) {
517     /* Pre-existing column. */
518     if (col->totcurve > 0) {
519       prev_ready = col;
520     }
521     /* Newly inserted column, so copy block data from previous. */
522     else if (prev_ready != NULL) {
523       col->totblock = prev_ready->totblock;
524       memcpy(&col->block, &prev_ready->block, sizeof(ActKeyBlockInfo));
525     }
526
527     col->totcurve = max_curve + 1;
528   }
529
530   /* Add blocks on top */
531   add_bezt_to_keyblocks_list(keys, bezt, bezt_len);
532 }
533
534 /* --------- */
535
536 bool actkeyblock_is_valid(ActKeyColumn *ac)
537 {
538   return ac != NULL && ac->next != NULL && ac->totblock > 0;
539 }
540
541 /* Checks if ActKeyBlock should exist... */
542 int actkeyblock_get_valid_hold(ActKeyColumn *ac)
543 {
544   /* check that block is valid */
545   if (!actkeyblock_is_valid(ac)) {
546     return 0;
547   }
548
549   const int hold_mask = (ACTKEYBLOCK_FLAG_ANY_HOLD | ACTKEYBLOCK_FLAG_STATIC_HOLD |
550                          ACTKEYBLOCK_FLAG_ANY_HOLD);
551   return (ac->block.flag & ~ac->block.conflict) & hold_mask;
552 }
553
554 /* *************************** Keyframe Drawing *************************** */
555
556 void draw_keyframe_shape(float x,
557                          float y,
558                          float size,
559                          bool sel,
560                          short key_type,
561                          short mode,
562                          float alpha,
563                          unsigned int pos_id,
564                          unsigned int size_id,
565                          unsigned int color_id,
566                          unsigned int outline_color_id,
567                          unsigned int flags_id,
568                          short handle_type,
569                          short extreme_type)
570 {
571   bool draw_fill = ELEM(mode, KEYFRAME_SHAPE_INSIDE, KEYFRAME_SHAPE_BOTH);
572   bool draw_outline = ELEM(mode, KEYFRAME_SHAPE_FRAME, KEYFRAME_SHAPE_BOTH);
573
574   BLI_assert(draw_fill || draw_outline);
575
576   /* tweak size of keyframe shape according to type of keyframe
577    * - 'proper' keyframes have key_type = 0, so get drawn at full size
578    */
579   switch (key_type) {
580     case BEZT_KEYTYPE_KEYFRAME: /* must be full size */
581       break;
582
583     case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
584       size *= 0.85f;
585       break;
586
587     case BEZT_KEYTYPE_MOVEHOLD: /* Slightly smaller than normal keyframes
588                                  * (but by less than for breakdowns). */
589       size *= 0.925f;
590       break;
591
592     case BEZT_KEYTYPE_EXTREME: /* slightly larger */
593       size *= 1.2f;
594       break;
595
596     default:
597       size -= 0.8f * key_type;
598   }
599
600   unsigned char fill_col[4];
601   unsigned char outline_col[4];
602   unsigned int flags = 0;
603
604   /* draw! */
605   if (draw_fill) {
606     /* get interior colors from theme (for selected and unselected only) */
607     switch (key_type) {
608       case BEZT_KEYTYPE_BREAKDOWN: /* bluish frames (default theme) */
609         UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_BREAKDOWN_SELECT : TH_KEYTYPE_BREAKDOWN, fill_col);
610         break;
611       case BEZT_KEYTYPE_EXTREME: /* reddish frames (default theme) */
612         UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_EXTREME_SELECT : TH_KEYTYPE_EXTREME, fill_col);
613         break;
614       case BEZT_KEYTYPE_JITTER: /* greenish frames (default theme) */
615         UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_JITTER_SELECT : TH_KEYTYPE_JITTER, fill_col);
616         break;
617       case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
618         UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_MOVEHOLD_SELECT : TH_KEYTYPE_MOVEHOLD, fill_col);
619         break;
620       case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
621       default:
622         UI_GetThemeColor4ubv(sel ? TH_KEYTYPE_KEYFRAME_SELECT : TH_KEYTYPE_KEYFRAME, fill_col);
623     }
624
625     /* NOTE: we don't use the straight alpha from the theme, or else effects such as
626      * graying out protected/muted channels doesn't work correctly!
627      */
628     fill_col[3] *= alpha;
629
630     if (!draw_outline) {
631       /* force outline color to match */
632       outline_col[0] = fill_col[0];
633       outline_col[1] = fill_col[1];
634       outline_col[2] = fill_col[2];
635       outline_col[3] = fill_col[3];
636     }
637   }
638
639   if (draw_outline) {
640     /* exterior - black frame */
641     UI_GetThemeColor4ubv(sel ? TH_KEYBORDER_SELECT : TH_KEYBORDER, outline_col);
642     outline_col[3] *= alpha;
643
644     if (!draw_fill) {
645       /* fill color needs to be (outline.rgb, 0) */
646       fill_col[0] = outline_col[0];
647       fill_col[1] = outline_col[1];
648       fill_col[2] = outline_col[2];
649       fill_col[3] = 0;
650     }
651
652     /* Handle type to outline shape. */
653     switch (handle_type) {
654       case KEYFRAME_HANDLE_AUTO_CLAMP:
655         flags = 0x2;
656         break; /* circle */
657       case KEYFRAME_HANDLE_AUTO:
658         flags = 0x12;
659         break; /* circle with dot */
660       case KEYFRAME_HANDLE_VECTOR:
661         flags = 0xC;
662         break; /* square */
663       case KEYFRAME_HANDLE_ALIGNED:
664         flags = 0x5;
665         break; /* clipped diamond */
666
667       case KEYFRAME_HANDLE_FREE:
668       default:
669         flags = 1; /* diamond */
670     }
671
672     /* Extreme type to arrow-like shading. */
673     if (extreme_type & KEYFRAME_EXTREME_MAX) {
674       flags |= 0x100;
675     }
676     if (extreme_type & KEYFRAME_EXTREME_MIN) {
677       flags |= 0x200;
678     }
679     if (extreme_type & KEYFRAME_EXTREME_MIXED) {
680       flags |= 0x400;
681     }
682   }
683
684   immAttr1f(size_id, size);
685   immAttr4ubv(color_id, fill_col);
686   immAttr4ubv(outline_color_id, outline_col);
687   immAttr1u(flags_id, flags);
688   immVertex2f(pos_id, x, y);
689 }
690
691 static void draw_keylist(View2D *v2d,
692                          DLRBT_Tree *keys,
693                          float ypos,
694                          float yscale_fac,
695                          bool channelLocked,
696                          int saction_flag)
697 {
698   const float icon_sz = U.widget_unit * 0.5f * yscale_fac;
699   const float half_icon_sz = 0.5f * icon_sz;
700   const float smaller_sz = 0.35f * icon_sz;
701   const float ipo_sz = 0.1f * icon_sz;
702
703   GPU_blend(true);
704
705   /* locked channels are less strongly shown, as feedback for locked channels in DopeSheet */
706   /* TODO: allow this opacity factor to be themed? */
707   float alpha = channelLocked ? 0.25f : 1.0f;
708
709   /* Show interpolation and handle type? */
710   bool show_ipo = (saction_flag & SACTION_SHOW_INTERPOLATION) != 0;
711
712   /* draw keyblocks */
713   if (keys) {
714     float sel_color[4], unsel_color[4];
715     float sel_mhcol[4], unsel_mhcol[4];
716     float ipo_color[4], ipo_color_mix[4];
717
718     /* cache colours first */
719     UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
720     UI_GetThemeColor4fv(TH_STRIP, unsel_color);
721     UI_GetThemeColor4fv(TH_DOPESHEET_IPOLINE, ipo_color);
722
723     sel_color[3] *= alpha;
724     unsel_color[3] *= alpha;
725     ipo_color[3] *= alpha;
726
727     copy_v4_v4(sel_mhcol, sel_color);
728     sel_mhcol[3] *= 0.8f;
729     copy_v4_v4(unsel_mhcol, unsel_color);
730     unsel_mhcol[3] *= 0.8f;
731     copy_v4_v4(ipo_color_mix, ipo_color);
732     ipo_color_mix[3] *= 0.5f;
733
734     uint block_len = 0;
735     for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
736       if (actkeyblock_get_valid_hold(ab)) {
737         block_len++;
738       }
739       if (show_ipo && actkeyblock_is_valid(ab) && (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
740         block_len++;
741       }
742     }
743
744     if (block_len > 0) {
745       GPUVertFormat *format = immVertexFormat();
746       uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
747       uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
748       immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
749
750       immBegin(GPU_PRIM_TRIS, 6 * block_len);
751       for (ActKeyColumn *ab = keys->first; ab; ab = ab->next) {
752         int valid_hold = actkeyblock_get_valid_hold(ab);
753         if (valid_hold != 0) {
754           if ((valid_hold & ACTKEYBLOCK_FLAG_STATIC_HOLD) == 0) {
755             /* draw "moving hold" long-keyframe block - slightly smaller */
756             immRectf_fast_with_color(pos_id,
757                                      color_id,
758                                      ab->cfra,
759                                      ypos - smaller_sz,
760                                      ab->next->cfra,
761                                      ypos + smaller_sz,
762                                      (ab->block.sel) ? sel_mhcol : unsel_mhcol);
763           }
764           else {
765             /* draw standard long-keyframe block */
766             immRectf_fast_with_color(pos_id,
767                                      color_id,
768                                      ab->cfra,
769                                      ypos - half_icon_sz,
770                                      ab->next->cfra,
771                                      ypos + half_icon_sz,
772                                      (ab->block.sel) ? sel_color : unsel_color);
773           }
774         }
775         if (show_ipo && actkeyblock_is_valid(ab) &&
776             (ab->block.flag & ACTKEYBLOCK_FLAG_NON_BEZIER)) {
777           /* draw an interpolation line */
778           immRectf_fast_with_color(
779               pos_id,
780               color_id,
781               ab->cfra,
782               ypos - ipo_sz,
783               ab->next->cfra,
784               ypos + ipo_sz,
785               (ab->block.conflict & ACTKEYBLOCK_FLAG_NON_BEZIER) ? ipo_color_mix : ipo_color);
786         }
787       }
788       immEnd();
789       immUnbindProgram();
790     }
791   }
792
793   if (keys) {
794     /* count keys */
795     uint key_len = 0;
796     for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
797       /* Optimization: if keyframe doesn't appear within 5 units (screenspace)
798        * in visible area, don't draw.
799        * This might give some improvements,
800        * since we current have to flip between view/region matrices.
801        */
802       if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
803         key_len++;
804       }
805     }
806
807     if (key_len > 0) {
808       /* draw keys */
809       GPUVertFormat *format = immVertexFormat();
810       uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
811       uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
812       uint color_id = GPU_vertformat_attr_add(
813           format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
814       uint outline_color_id = GPU_vertformat_attr_add(
815           format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
816       uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
817       immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
818       GPU_enable_program_point_size();
819       immUniform2f(
820           "ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
821       immBegin(GPU_PRIM_POINTS, key_len);
822
823       short handle_type = KEYFRAME_HANDLE_NONE, extreme_type = KEYFRAME_EXTREME_NONE;
824
825       for (ActKeyColumn *ak = keys->first; ak; ak = ak->next) {
826         if (IN_RANGE_INCL(ak->cfra, v2d->cur.xmin, v2d->cur.xmax)) {
827           if (show_ipo) {
828             handle_type = ak->handle_type;
829           }
830           if (saction_flag & SACTION_SHOW_EXTREMES) {
831             extreme_type = ak->extreme_type;
832           }
833
834           draw_keyframe_shape(ak->cfra,
835                               ypos,
836                               icon_sz,
837                               (ak->sel & SELECT),
838                               ak->key_type,
839                               KEYFRAME_SHAPE_BOTH,
840                               alpha,
841                               pos_id,
842                               size_id,
843                               color_id,
844                               outline_color_id,
845                               flags_id,
846                               handle_type,
847                               extreme_type);
848         }
849       }
850
851       immEnd();
852       GPU_disable_program_point_size();
853       immUnbindProgram();
854     }
855   }
856
857   GPU_blend(false);
858 }
859
860 /* *************************** Channel Drawing Funcs *************************** */
861
862 void draw_summary_channel(
863     View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac, int saction_flag)
864 {
865   DLRBT_Tree keys;
866
867   saction_flag &= ~SACTION_SHOW_EXTREMES;
868
869   BLI_dlrbTree_init(&keys);
870
871   summary_to_keylist(ac, &keys, saction_flag);
872
873   draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
874
875   BLI_dlrbTree_free(&keys);
876 }
877
878 void draw_scene_channel(
879     View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac, int saction_flag)
880 {
881   DLRBT_Tree keys;
882
883   saction_flag &= ~SACTION_SHOW_EXTREMES;
884
885   BLI_dlrbTree_init(&keys);
886
887   scene_to_keylist(ads, sce, &keys, saction_flag);
888
889   draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
890
891   BLI_dlrbTree_free(&keys);
892 }
893
894 void draw_object_channel(
895     View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac, int saction_flag)
896 {
897   DLRBT_Tree keys;
898
899   saction_flag &= ~SACTION_SHOW_EXTREMES;
900
901   BLI_dlrbTree_init(&keys);
902
903   ob_to_keylist(ads, ob, &keys, saction_flag);
904
905   draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
906
907   BLI_dlrbTree_free(&keys);
908 }
909
910 void draw_fcurve_channel(
911     View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac, int saction_flag)
912 {
913   DLRBT_Tree keys;
914
915   bool locked = (fcu->flag & FCURVE_PROTECTED) ||
916                 ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
917                 ((adt && adt->action) && ID_IS_LINKED(adt->action));
918
919   BLI_dlrbTree_init(&keys);
920
921   fcurve_to_keylist(adt, fcu, &keys, saction_flag);
922
923   draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
924
925   BLI_dlrbTree_free(&keys);
926 }
927
928 void draw_agroup_channel(
929     View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac, int saction_flag)
930 {
931   DLRBT_Tree keys;
932
933   bool locked = (agrp->flag & AGRP_PROTECTED) ||
934                 ((adt && adt->action) && ID_IS_LINKED(adt->action));
935
936   BLI_dlrbTree_init(&keys);
937
938   agroup_to_keylist(adt, agrp, &keys, saction_flag);
939
940   draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
941
942   BLI_dlrbTree_free(&keys);
943 }
944
945 void draw_action_channel(
946     View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac, int saction_flag)
947 {
948   DLRBT_Tree keys;
949
950   bool locked = (act && ID_IS_LINKED(act));
951
952   saction_flag &= ~SACTION_SHOW_EXTREMES;
953
954   BLI_dlrbTree_init(&keys);
955
956   action_to_keylist(adt, act, &keys, saction_flag);
957
958   draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
959
960   BLI_dlrbTree_free(&keys);
961 }
962
963 void draw_gpencil_channel(
964     View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac, int saction_flag)
965 {
966   DLRBT_Tree keys;
967
968   saction_flag &= ~SACTION_SHOW_EXTREMES;
969
970   BLI_dlrbTree_init(&keys);
971
972   gpencil_to_keylist(ads, gpd, &keys, false);
973
974   draw_keylist(v2d, &keys, ypos, yscale_fac, false, saction_flag);
975
976   BLI_dlrbTree_free(&keys);
977 }
978
979 void draw_gpl_channel(
980     View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac, int saction_flag)
981 {
982   DLRBT_Tree keys;
983
984   bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
985
986   BLI_dlrbTree_init(&keys);
987
988   gpl_to_keylist(ads, gpl, &keys);
989
990   draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
991
992   BLI_dlrbTree_free(&keys);
993 }
994
995 void draw_masklay_channel(View2D *v2d,
996                           bDopeSheet *ads,
997                           MaskLayer *masklay,
998                           float ypos,
999                           float yscale_fac,
1000                           int saction_flag)
1001 {
1002   DLRBT_Tree keys;
1003
1004   bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
1005
1006   BLI_dlrbTree_init(&keys);
1007
1008   mask_to_keylist(ads, masklay, &keys);
1009
1010   draw_keylist(v2d, &keys, ypos, yscale_fac, locked, saction_flag);
1011
1012   BLI_dlrbTree_free(&keys);
1013 }
1014
1015 /* *************************** Keyframe List Conversions *************************** */
1016
1017 void summary_to_keylist(bAnimContext *ac, DLRBT_Tree *keys, int saction_flag)
1018 {
1019   if (ac) {
1020     ListBase anim_data = {NULL, NULL};
1021     bAnimListElem *ale;
1022     int filter;
1023
1024     /* get F-Curves to take keyframes from */
1025     filter = ANIMFILTER_DATA_VISIBLE;
1026     ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
1027
1028     /* loop through each F-Curve, grabbing the keyframes */
1029     for (ale = anim_data.first; ale; ale = ale->next) {
1030       /* Why not use all #eAnim_KeyType here?
1031        * All of the other key types are actually "summaries" themselves,
1032        * and will just end up duplicating stuff that comes up through
1033        * standard filtering of just F-Curves. Given the way that these work,
1034        * there isn't really any benefit at all from including them. - Aligorith */
1035
1036       switch (ale->datatype) {
1037         case ALE_FCURVE:
1038           fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
1039           break;
1040         case ALE_MASKLAY:
1041           mask_to_keylist(ac->ads, ale->data, keys);
1042           break;
1043         case ALE_GPFRAME:
1044           gpl_to_keylist(ac->ads, ale->data, keys);
1045           break;
1046         default:
1047           // printf("%s: datatype %d unhandled\n", __func__, ale->datatype);
1048           break;
1049       }
1050     }
1051
1052     ANIM_animdata_freelist(&anim_data);
1053   }
1054 }
1055
1056 void scene_to_keylist(bDopeSheet *ads, Scene *sce, DLRBT_Tree *keys, int saction_flag)
1057 {
1058   bAnimContext ac = {NULL};
1059   ListBase anim_data = {NULL, NULL};
1060   bAnimListElem *ale;
1061   int filter;
1062
1063   bAnimListElem dummychan = {NULL};
1064
1065   if (sce == NULL) {
1066     return;
1067   }
1068
1069   /* create a dummy wrapper data to work with */
1070   dummychan.type = ANIMTYPE_SCENE;
1071   dummychan.data = sce;
1072   dummychan.id = &sce->id;
1073   dummychan.adt = sce->adt;
1074
1075   ac.ads = ads;
1076   ac.data = &dummychan;
1077   ac.datatype = ANIMCONT_CHANNEL;
1078
1079   /* get F-Curves to take keyframes from */
1080   filter = ANIMFILTER_DATA_VISIBLE;  // curves only
1081   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1082
1083   /* loop through each F-Curve, grabbing the keyframes */
1084   for (ale = anim_data.first; ale; ale = ale->next) {
1085     fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
1086   }
1087
1088   ANIM_animdata_freelist(&anim_data);
1089 }
1090
1091 void ob_to_keylist(bDopeSheet *ads, Object *ob, DLRBT_Tree *keys, int saction_flag)
1092 {
1093   bAnimContext ac = {NULL};
1094   ListBase anim_data = {NULL, NULL};
1095   bAnimListElem *ale;
1096   int filter;
1097
1098   bAnimListElem dummychan = {NULL};
1099   Base dummybase = {NULL};
1100
1101   if (ob == NULL) {
1102     return;
1103   }
1104
1105   /* create a dummy wrapper data to work with */
1106   dummybase.object = ob;
1107
1108   dummychan.type = ANIMTYPE_OBJECT;
1109   dummychan.data = &dummybase;
1110   dummychan.id = &ob->id;
1111   dummychan.adt = ob->adt;
1112
1113   ac.ads = ads;
1114   ac.data = &dummychan;
1115   ac.datatype = ANIMCONT_CHANNEL;
1116
1117   /* get F-Curves to take keyframes from */
1118   filter = ANIMFILTER_DATA_VISIBLE;  // curves only
1119   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1120
1121   /* loop through each F-Curve, grabbing the keyframes */
1122   for (ale = anim_data.first; ale; ale = ale->next) {
1123     fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
1124   }
1125
1126   ANIM_animdata_freelist(&anim_data);
1127 }
1128
1129 void cachefile_to_keylist(bDopeSheet *ads,
1130                           CacheFile *cache_file,
1131                           DLRBT_Tree *keys,
1132                           int saction_flag)
1133 {
1134   if (cache_file == NULL) {
1135     return;
1136   }
1137
1138   /* create a dummy wrapper data to work with */
1139   bAnimListElem dummychan = {NULL};
1140   dummychan.type = ANIMTYPE_DSCACHEFILE;
1141   dummychan.data = cache_file;
1142   dummychan.id = &cache_file->id;
1143   dummychan.adt = cache_file->adt;
1144
1145   bAnimContext ac = {NULL};
1146   ac.ads = ads;
1147   ac.data = &dummychan;
1148   ac.datatype = ANIMCONT_CHANNEL;
1149
1150   /* get F-Curves to take keyframes from */
1151   ListBase anim_data = {NULL, NULL};
1152   int filter = ANIMFILTER_DATA_VISIBLE;  // curves only
1153   ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
1154
1155   /* loop through each F-Curve, grabbing the keyframes */
1156   for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
1157     fcurve_to_keylist(ale->adt, ale->data, keys, saction_flag);
1158   }
1159
1160   ANIM_animdata_freelist(&anim_data);
1161 }
1162
1163 void fcurve_to_keylist(AnimData *adt, FCurve *fcu, DLRBT_Tree *keys, int saction_flag)
1164 {
1165   if (fcu && fcu->totvert && fcu->bezt) {
1166     /* apply NLA-mapping (if applicable) */
1167     if (adt) {
1168       ANIM_nla_mapping_apply_fcurve(adt, fcu, 0, 0);
1169     }
1170
1171     /* Check if the curve is cyclic. */
1172     bool is_cyclic = BKE_fcurve_is_cyclic(fcu) && (fcu->totvert >= 2);
1173     bool do_extremes = (saction_flag & SACTION_SHOW_EXTREMES) != 0;
1174
1175     /* loop through beztriples, making ActKeysColumns */
1176     BezTripleChain chain = {0};
1177
1178     for (int v = 0; v < fcu->totvert; v++) {
1179       chain.cur = &fcu->bezt[v];
1180
1181       /* Neighbor keys, accounting for being cyclic. */
1182       if (do_extremes) {
1183         chain.prev = (v > 0) ? &fcu->bezt[v - 1] : is_cyclic ? &fcu->bezt[fcu->totvert - 2] : NULL;
1184         chain.next = (v + 1 < fcu->totvert) ? &fcu->bezt[v + 1] : is_cyclic ? &fcu->bezt[1] : NULL;
1185       }
1186
1187       add_bezt_to_keycolumns_list(keys, &chain);
1188     }
1189
1190     /* Update keyblocks. */
1191     update_keyblocks(keys, fcu->bezt, fcu->totvert);
1192
1193     /* unapply NLA-mapping if applicable */
1194     if (adt) {
1195       ANIM_nla_mapping_apply_fcurve(adt, fcu, 1, 0);
1196     }
1197   }
1198 }
1199
1200 void agroup_to_keylist(AnimData *adt, bActionGroup *agrp, DLRBT_Tree *keys, int saction_flag)
1201 {
1202   FCurve *fcu;
1203
1204   if (agrp) {
1205     /* loop through F-Curves */
1206     for (fcu = agrp->channels.first; fcu && fcu->grp == agrp; fcu = fcu->next) {
1207       fcurve_to_keylist(adt, fcu, keys, saction_flag);
1208     }
1209   }
1210 }
1211
1212 void action_to_keylist(AnimData *adt, bAction *act, DLRBT_Tree *keys, int saction_flag)
1213 {
1214   FCurve *fcu;
1215
1216   if (act) {
1217     /* loop through F-Curves */
1218     for (fcu = act->curves.first; fcu; fcu = fcu->next) {
1219       fcurve_to_keylist(adt, fcu, keys, saction_flag);
1220     }
1221   }
1222 }
1223
1224 void gpencil_to_keylist(bDopeSheet *ads, bGPdata *gpd, DLRBT_Tree *keys, const bool active)
1225 {
1226   bGPDlayer *gpl;
1227
1228   if (gpd && keys) {
1229     /* for now, just aggregate out all the frames, but only for visible layers */
1230     for (gpl = gpd->layers.last; gpl; gpl = gpl->prev) {
1231       if ((gpl->flag & GP_LAYER_HIDE) == 0) {
1232         if ((!active) || ((active) && (gpl->flag & GP_LAYER_SELECT))) {
1233           gpl_to_keylist(ads, gpl, keys);
1234         }
1235       }
1236     }
1237   }
1238 }
1239
1240 void gpl_to_keylist(bDopeSheet *UNUSED(ads), bGPDlayer *gpl, DLRBT_Tree *keys)
1241 {
1242   bGPDframe *gpf;
1243
1244   if (gpl && keys) {
1245     /* Although the frames should already be in an ordered list,
1246      * they are not suitable for displaying yet. */
1247     for (gpf = gpl->frames.first; gpf; gpf = gpf->next) {
1248       add_gpframe_to_keycolumns_list(keys, gpf);
1249     }
1250
1251     update_keyblocks(keys, NULL, 0);
1252   }
1253 }
1254
1255 void mask_to_keylist(bDopeSheet *UNUSED(ads), MaskLayer *masklay, DLRBT_Tree *keys)
1256 {
1257   MaskLayerShape *masklay_shape;
1258
1259   if (masklay && keys) {
1260     for (masklay_shape = masklay->splines_shapes.first; masklay_shape;
1261          masklay_shape = masklay_shape->next) {
1262       add_masklay_to_keycolumns_list(keys, masklay_shape);
1263     }
1264
1265     update_keyblocks(keys, NULL, 0);
1266   }
1267 }