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