Cleanup: Sort node type definitions alphabetically
[blender.git] / source / blender / editors / space_action / action_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) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup spaction
22  */
23
24 /* System includes ----------------------------------------------------- */
25
26 #include <float.h>
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "BLI_blenlib.h"
32 #include "BLI_math.h"
33 #include "BLI_utildefines.h"
34
35 /* Types --------------------------------------------------------------- */
36
37 #include "DNA_anim_types.h"
38 #include "DNA_cachefile_types.h"
39 #include "DNA_gpencil_types.h"
40 #include "DNA_object_types.h"
41 #include "DNA_scene_types.h"
42 #include "DNA_screen_types.h"
43
44 #include "BKE_action.h"
45 #include "BKE_context.h"
46 #include "BKE_pointcache.h"
47
48 /* Everything from source (BIF, BDR, BSE) ------------------------------ */
49
50 #include "GPU_immediate.h"
51 #include "GPU_matrix.h"
52 #include "GPU_state.h"
53
54 #include "UI_interface.h"
55 #include "UI_resources.h"
56 #include "UI_view2d.h"
57
58 #include "ED_anim_api.h"
59 #include "ED_keyframes_draw.h"
60
61 #include "action_intern.h"
62
63 /* ************************************************************************* */
64 /* Channel List */
65
66 /* left hand part */
67 void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
68 {
69   ListBase anim_data = {NULL, NULL};
70   bAnimListElem *ale;
71   int filter;
72
73   View2D *v2d = &region->v2d;
74   size_t items;
75
76   /* build list of channels to draw */
77   filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
78   items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
79
80   int height = ACHANNEL_TOT_HEIGHT(ac, items);
81   v2d->tot.ymin = -height;
82
83   /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
84   UI_view2d_sync(NULL, ac->area, v2d, V2D_LOCK_COPY);
85
86   /* loop through channels, and set up drawing depending on their type  */
87   { /* first pass: just the standard GL-drawing for backdrop + text */
88     size_t channel_index = 0;
89     float ymax = ACHANNEL_FIRST_TOP(ac);
90
91     for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
92       float ymin = ymax - ACHANNEL_HEIGHT(ac);
93
94       /* check if visible */
95       if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
96           IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
97         /* draw all channels using standard channel-drawing API */
98         ANIM_channel_draw(ac, ale, ymin, ymax, channel_index);
99       }
100     }
101   }
102   { /* second pass: widgets */
103     uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS);
104     size_t channel_index = 0;
105     float ymax = ACHANNEL_FIRST_TOP(ac);
106
107     for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac), channel_index++) {
108       float ymin = ymax - ACHANNEL_HEIGHT(ac);
109
110       /* check if visible */
111       if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
112           IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
113         /* draw all channels using standard channel-drawing API */
114         rctf channel_rect;
115         BLI_rctf_init(&channel_rect, 0, v2d->cur.xmax, ymin, ymax);
116         ANIM_channel_draw_widgets(C, ac, ale, block, &channel_rect, channel_index);
117       }
118     }
119
120     UI_block_end(C, block);
121     UI_block_draw(C, block);
122   }
123
124   /* free tempolary channels */
125   ANIM_animdata_freelist(&anim_data);
126 }
127
128 /* ************************************************************************* */
129 /* Keyframes */
130
131 /* extra padding for lengths (to go under scrollers) */
132 #define EXTRA_SCROLL_PAD 100.0f
133
134 /* draw keyframes in each channel */
135 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *region)
136 {
137   ListBase anim_data = {NULL, NULL};
138   bAnimListElem *ale;
139
140   View2D *v2d = &region->v2d;
141   bDopeSheet *ads = &saction->ads;
142   AnimData *adt = NULL;
143
144   uchar col1[4], col2[4];
145   uchar col1a[4], col2a[4];
146   uchar col1b[4], col2b[4];
147
148   const bool show_group_colors = U.animation_flag & USER_ANIM_SHOW_CHANNEL_GROUP_COLORS;
149
150   /* get theme colors */
151   UI_GetThemeColor4ubv(TH_SHADE2, col2);
152   UI_GetThemeColor4ubv(TH_HILITE, col1);
153
154   UI_GetThemeColor4ubv(TH_GROUP, col2a);
155   UI_GetThemeColor4ubv(TH_GROUP_ACTIVE, col1a);
156
157   UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
158   UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
159
160   /* build list of channels to draw */
161   int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
162   size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
163
164   int height = ACHANNEL_TOT_HEIGHT(ac, items);
165   v2d->tot.ymin = -height;
166
167   GPUVertFormat *format = immVertexFormat();
168   uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
169
170   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
171
172   GPU_blend(GPU_BLEND_ALPHA);
173
174   /* first backdrop strips */
175   float ymax = ACHANNEL_FIRST_TOP(ac);
176
177   for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
178     float ymin = ymax - ACHANNEL_HEIGHT(ac);
179
180     /* check if visible */
181     if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
182         IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
183       const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
184       int sel = 0;
185
186       /* determine if any need to draw channel */
187       if (ale->datatype != ALE_NONE) {
188         /* determine if channel is selected */
189         if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT)) {
190           sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
191         }
192
193         if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
194           switch (ale->type) {
195             case ANIMTYPE_SUMMARY: {
196               /* reddish color from NLA */
197               immUniformThemeColor(TH_ANIM_ACTIVE);
198               break;
199             }
200             case ANIMTYPE_SCENE:
201             case ANIMTYPE_OBJECT: {
202               immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
203               break;
204             }
205             case ANIMTYPE_FILLACTD:
206             case ANIMTYPE_DSSKEY:
207             case ANIMTYPE_DSWOR: {
208               immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
209               break;
210             }
211             case ANIMTYPE_GROUP: {
212               bActionGroup *agrp = ale->data;
213               if (show_group_colors && agrp->customCol) {
214                 if (sel) {
215                   immUniformColor3ubvAlpha((uchar *)agrp->cs.select, col1a[3]);
216                 }
217                 else {
218                   immUniformColor3ubvAlpha((uchar *)agrp->cs.solid, col2a[3]);
219                 }
220               }
221               else {
222                 immUniformColor4ubv(sel ? col1a : col2a);
223               }
224               break;
225             }
226             case ANIMTYPE_FCURVE: {
227               FCurve *fcu = ale->data;
228               if (show_group_colors && fcu->grp && fcu->grp->customCol) {
229                 immUniformColor3ubvAlpha((uchar *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
230               }
231               else {
232                 immUniformColor4ubv(sel ? col1 : col2);
233               }
234               break;
235             }
236             default: {
237               immUniformColor4ubv(sel ? col1 : col2);
238             }
239           }
240
241           /* draw region twice: firstly backdrop, then the current range */
242           immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
243         }
244         else if (ac->datatype == ANIMCONT_GPENCIL) {
245           uchar *color;
246           uchar gpl_col[4];
247           if ((show_group_colors) && (ale->type == ANIMTYPE_GPLAYER)) {
248             bGPDlayer *gpl = (bGPDlayer *)ale->data;
249             rgb_float_to_uchar(gpl_col, gpl->color);
250             gpl_col[3] = col1[3];
251
252             color = sel ? col1 : gpl_col;
253           }
254           else {
255             color = sel ? col1 : col2;
256           }
257           /* frames less than one get less saturated background */
258           immUniformColor4ubv(color);
259           immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
260
261           /* frames one and higher get a saturated background */
262           immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
263           immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
264         }
265         else if (ac->datatype == ANIMCONT_MASK) {
266           /* TODO --- this is a copy of gpencil */
267           /* frames less than one get less saturated background */
268           uchar *color = sel ? col1 : col2;
269           immUniformColor4ubv(color);
270           immRectf(pos, 0.0f, ymin, v2d->cur.xmin, ymax);
271
272           /* frames one and higher get a saturated background */
273           immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
274           immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax + EXTRA_SCROLL_PAD, ymax);
275         }
276       }
277     }
278   }
279   GPU_blend(GPU_BLEND_NONE);
280
281   /* black line marking 'current frame' for Time-Slide transform mode */
282   if (saction->flag & SACTION_MOVING) {
283     immUniformColor3f(0.0f, 0.0f, 0.0f);
284
285     immBegin(GPU_PRIM_LINES, 2);
286     immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
287     immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
288     immEnd();
289   }
290   immUnbindProgram();
291
292   /* Draw keyframes
293    * 1) Only channels that are visible in the Action Editor get drawn/evaluated.
294    *    This is to try to optimize this for heavier data sets
295    * 2) Keyframes which are out of view horizontally are disregarded
296    */
297   int action_flag = saction->flag;
298
299   if (saction->mode == SACTCONT_TIMELINE) {
300     action_flag &= ~(SACTION_SHOW_INTERPOLATION | SACTION_SHOW_EXTREMES);
301   }
302
303   ymax = ACHANNEL_FIRST_TOP(ac);
304
305   for (ale = anim_data.first; ale; ale = ale->next, ymax -= ACHANNEL_STEP(ac)) {
306     float ymin = ymax - ACHANNEL_HEIGHT(ac);
307     float ycenter = (ymin + ymax) / 2.0f;
308
309     /* check if visible */
310     if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
311         IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
312       /* check if anything to show for this channel */
313       if (ale->datatype != ALE_NONE) {
314         adt = ANIM_nla_mapping_get(ac, ale);
315
316         /* draw 'keyframes' for each specific datatype */
317         switch (ale->datatype) {
318           case ALE_ALL:
319             draw_summary_channel(v2d, ale->data, ycenter, ac->yscale_fac, action_flag);
320             break;
321           case ALE_SCE:
322             draw_scene_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
323             break;
324           case ALE_OB:
325             draw_object_channel(v2d, ads, ale->key_data, ycenter, ac->yscale_fac, action_flag);
326             break;
327           case ALE_ACT:
328             draw_action_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
329             break;
330           case ALE_GROUP:
331             draw_agroup_channel(v2d, adt, ale->data, ycenter, ac->yscale_fac, action_flag);
332             break;
333           case ALE_FCURVE:
334             draw_fcurve_channel(v2d, adt, ale->key_data, ycenter, ac->yscale_fac, action_flag);
335             break;
336           case ALE_GPFRAME:
337             draw_gpl_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
338             break;
339           case ALE_MASKLAY:
340             draw_masklay_channel(v2d, ads, ale->data, ycenter, ac->yscale_fac, action_flag);
341             break;
342         }
343       }
344     }
345   }
346
347   /* free temporary channels used for drawing */
348   ANIM_animdata_freelist(&anim_data);
349 }
350
351 /* ************************************************************************* */
352 /* Timeline - Caches */
353
354 static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID *pid)
355 {
356   switch (pid->type) {
357     case PTCACHE_TYPE_SOFTBODY:
358       if ((saction->cache_display & TIME_CACHE_SOFTBODY) == 0) {
359         return true;
360       }
361       break;
362     case PTCACHE_TYPE_PARTICLES:
363     case PTCACHE_TYPE_SIM_PARTICLES:
364       if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) {
365         return true;
366       }
367       break;
368     case PTCACHE_TYPE_CLOTH:
369       if ((saction->cache_display & TIME_CACHE_CLOTH) == 0) {
370         return true;
371       }
372       break;
373     case PTCACHE_TYPE_SMOKE_DOMAIN:
374     case PTCACHE_TYPE_SMOKE_HIGHRES:
375       if ((saction->cache_display & TIME_CACHE_SMOKE) == 0) {
376         return true;
377       }
378       break;
379     case PTCACHE_TYPE_DYNAMICPAINT:
380       if ((saction->cache_display & TIME_CACHE_DYNAMICPAINT) == 0) {
381         return true;
382       }
383       break;
384     case PTCACHE_TYPE_RIGIDBODY:
385       if ((saction->cache_display & TIME_CACHE_RIGIDBODY) == 0) {
386         return true;
387       }
388       break;
389   }
390   return false;
391 }
392
393 static void timeline_cache_color_get(PTCacheID *pid, float color[4])
394 {
395   switch (pid->type) {
396     case PTCACHE_TYPE_SOFTBODY:
397       color[0] = 1.0;
398       color[1] = 0.4;
399       color[2] = 0.02;
400       color[3] = 0.1;
401       break;
402     case PTCACHE_TYPE_PARTICLES:
403     case PTCACHE_TYPE_SIM_PARTICLES:
404       color[0] = 1.0;
405       color[1] = 0.1;
406       color[2] = 0.02;
407       color[3] = 0.1;
408       break;
409     case PTCACHE_TYPE_CLOTH:
410       color[0] = 0.1;
411       color[1] = 0.1;
412       color[2] = 0.75;
413       color[3] = 0.1;
414       break;
415     case PTCACHE_TYPE_SMOKE_DOMAIN:
416     case PTCACHE_TYPE_SMOKE_HIGHRES:
417       color[0] = 0.2;
418       color[1] = 0.2;
419       color[2] = 0.2;
420       color[3] = 0.1;
421       break;
422     case PTCACHE_TYPE_DYNAMICPAINT:
423       color[0] = 1.0;
424       color[1] = 0.1;
425       color[2] = 0.75;
426       color[3] = 0.1;
427       break;
428     case PTCACHE_TYPE_RIGIDBODY:
429       color[0] = 1.0;
430       color[1] = 0.6;
431       color[2] = 0.0;
432       color[3] = 0.1;
433       break;
434     default:
435       color[0] = 1.0;
436       color[1] = 0.0;
437       color[2] = 1.0;
438       color[3] = 0.1;
439       BLI_assert(0);
440       break;
441   }
442 }
443
444 static void timeline_cache_modify_color_based_on_state(PointCache *cache, float color[4])
445 {
446   if (cache->flag & PTCACHE_BAKED) {
447     color[0] -= 0.4f;
448     color[1] -= 0.4f;
449     color[2] -= 0.4f;
450   }
451   else if (cache->flag & PTCACHE_OUTDATED) {
452     color[0] += 0.4f;
453     color[1] += 0.4f;
454     color[2] += 0.4f;
455   }
456 }
457
458 static bool timeline_cache_find_next_cached_segment(PointCache *cache,
459                                                     int search_start_frame,
460                                                     int *r_segment_start,
461                                                     int *r_segment_end)
462 {
463   int offset = cache->startframe;
464   int current = search_start_frame;
465
466   /* Find segment start frame. */
467   while (true) {
468     if (current > cache->endframe) {
469       return false;
470     }
471     if (cache->cached_frames[current - offset]) {
472       *r_segment_start = current;
473       break;
474     }
475     current++;
476   }
477
478   /* Find segment end frame. */
479   while (true) {
480     if (current > cache->endframe) {
481       *r_segment_end = current - 1;
482       return true;
483     }
484     if (!cache->cached_frames[current - offset]) {
485       *r_segment_end = current - 1;
486       return true;
487     }
488     current++;
489   }
490 }
491
492 static uint timeline_cache_segments_count(PointCache *cache)
493 {
494   uint count = 0;
495
496   int current = cache->startframe;
497   int segment_start;
498   int segment_end;
499   while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
500     count++;
501     current = segment_end + 1;
502   }
503
504   return count;
505 }
506
507 static void timeline_cache_draw_cached_segments(PointCache *cache, uint pos_id)
508 {
509   uint segments_count = timeline_cache_segments_count(cache);
510   if (segments_count == 0) {
511     return;
512   }
513
514   immBeginAtMost(GPU_PRIM_TRIS, segments_count * 6);
515
516   int current = cache->startframe;
517   int segment_start;
518   int segment_end;
519   while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
520     immRectf_fast(pos_id, segment_start - 0.5f, 0, segment_end + 0.5f, 1.0f);
521     current = segment_end + 1;
522   }
523
524   immEnd();
525 }
526
527 static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id)
528 {
529   GPU_matrix_push();
530   GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + y_offset);
531   GPU_matrix_scale_2f(1.0, height);
532
533   float color[4];
534   timeline_cache_color_get(pid, color);
535
536   immUniformColor4fv(color);
537   immRectf(pos_id, (float)pid->cache->startframe, 0.0, (float)pid->cache->endframe, 1.0);
538
539   color[3] = 0.4f;
540   timeline_cache_modify_color_based_on_state(pid->cache, color);
541   immUniformColor4fv(color);
542
543   timeline_cache_draw_cached_segments(pid->cache, pos_id);
544
545   GPU_matrix_pop();
546 }
547
548 void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
549 {
550   if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == NULL) {
551     return;
552   }
553
554   ListBase pidlist;
555   BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
556
557   uint pos_id = GPU_vertformat_attr_add(
558       immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
559   immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
560
561   GPU_blend(GPU_BLEND_ALPHA);
562
563   /* Iterate over pointcaches on the active object, and draw each one's range. */
564   float y_offset = 0.0f;
565   const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize;
566   LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
567     if (timeline_cache_is_hidden_by_setting(saction, pid)) {
568       continue;
569     }
570
571     if (pid->cache->cached_frames == NULL) {
572       continue;
573     }
574
575     timeline_cache_draw_single(pid, y_offset, cache_draw_height, pos_id);
576
577     y_offset += cache_draw_height;
578   }
579
580   GPU_blend(GPU_BLEND_NONE);
581   immUnbindProgram();
582
583   BLI_freelistN(&pidlist);
584 }
585
586 /* ************************************************************************* */