Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_action / action_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) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_action/action_draw.c
29  *  \ingroup spaction
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 "BLI_blenlib.h"
41 #include "BLI_utildefines.h"
42
43 /* Types --------------------------------------------------------------- */
44
45 #include "DNA_anim_types.h"
46 #include "DNA_cachefile_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_screen_types.h"
49 #include "DNA_scene_types.h"
50
51 #include "BKE_action.h"
52 #include "BKE_context.h"
53 #include "BKE_pointcache.h"
54
55
56 /* Everything from source (BIF, BDR, BSE) ------------------------------ */
57
58 #include "BIF_gl.h"
59
60 #include "GPU_immediate.h"
61 #include "GPU_matrix.h"
62
63 #include "UI_interface.h"
64 #include "UI_resources.h"
65 #include "UI_view2d.h"
66
67 #include "ED_anim_api.h"
68 #include "ED_keyframes_draw.h"
69
70 #include "action_intern.h"
71
72 /* ************************************************************************* */
73 /* Channel List */
74
75 /* left hand part */
76 void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar)
77 {
78         ListBase anim_data = {NULL, NULL};
79         bAnimListElem *ale;
80         int filter;
81
82         View2D *v2d = &ar->v2d;
83         float y = 0.0f;
84         size_t items;
85         int height;
86
87         /* build list of channels to draw */
88         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
89         items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
90
91         height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
92         if (height > BLI_rcti_size_y(&v2d->mask)) {
93                 /* don't use totrect set, as the width stays the same
94                  * (NOTE: this is ok here, the configuration is pretty straightforward)
95                  */
96                 v2d->tot.ymin = (float)(-height);
97         }
98         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
99         UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
100
101         /* loop through channels, and set up drawing depending on their type  */
102         {   /* first pass: just the standard GL-drawing for backdrop + text */
103                 size_t channel_index = 0;
104
105                 y = (float)ACHANNEL_FIRST(ac);
106
107                 for (ale = anim_data.first; ale; ale = ale->next) {
108                         float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
109                         float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
110
111                         /* check if visible */
112                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
113                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
114                         {
115                                 /* draw all channels using standard channel-drawing API */
116                                 ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
117                         }
118
119                         /* adjust y-position for next one */
120                         y -= ACHANNEL_STEP(ac);
121                         channel_index++;
122                 }
123         }
124         {   /* second pass: widgets */
125                 uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
126                 size_t channel_index = 0;
127
128                 y = (float)ACHANNEL_FIRST(ac);
129
130                 for (ale = anim_data.first; ale; ale = ale->next) {
131                         float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
132                         float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
133
134                         /* check if visible */
135                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
136                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
137                         {
138                                 /* draw all channels using standard channel-drawing API */
139                                 ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
140                         }
141
142                         /* adjust y-position for next one */
143                         y -= ACHANNEL_STEP(ac);
144                         channel_index++;
145                 }
146
147                 UI_block_end(C, block);
148                 UI_block_draw(C, block);
149         }
150
151         /* free tempolary channels */
152         ANIM_animdata_freelist(&anim_data);
153 }
154
155 /* ************************************************************************* */
156 /* Keyframes */
157
158 /* extra padding for lengths (to go under scrollers) */
159 #define EXTRA_SCROLL_PAD    100.0f
160
161 /* draw keyframes in each channel */
162 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
163 {
164         ListBase anim_data = {NULL, NULL};
165         bAnimListElem *ale;
166
167         View2D *v2d = &ar->v2d;
168         bDopeSheet *ads = &saction->ads;
169         AnimData *adt = NULL;
170
171         float act_start, act_end, y;
172
173         unsigned char col1[3], col2[3];
174         unsigned char col1a[3], col2a[3];
175         unsigned char col1b[3], col2b[3];
176
177         const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
178
179
180         /* get theme colors */
181         UI_GetThemeColor3ubv(TH_BACK, col2);
182         UI_GetThemeColor3ubv(TH_HILITE, col1);
183
184         UI_GetThemeColor3ubv(TH_GROUP, col2a);
185         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
186
187         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
188         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
189
190         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
191
192         /* if in NLA there's a strip active, map the view */
193         if (ac->datatype == ANIMCONT_ACTION) {
194                 /* adt = ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */
195
196                 /* start and end of action itself */
197                 calc_action_range(ac->data, &act_start, &act_end, 0);
198         }
199
200         /* build list of channels to draw */
201         int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
202         size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
203
204         int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
205         /* don't use totrect set, as the width stays the same
206          * (NOTE: this is ok here, the configuration is pretty straightforward)
207          */
208         v2d->tot.ymin = (float)(-height);
209
210         /* first backdrop strips */
211         y = (float)(-ACHANNEL_HEIGHT(ac));
212
213         Gwn_VertFormat *format = immVertexFormat();
214         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
215
216         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
217
218         glEnable(GL_BLEND);
219
220         for (ale = anim_data.first; ale; ale = ale->next) {
221                 const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
222                 const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
223
224                 /* check if visible */
225                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
226                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
227                 {
228                         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
229                         int sel = 0;
230
231                         /* determine if any need to draw channel */
232                         if (ale->datatype != ALE_NONE) {
233                                 /* determine if channel is selected */
234                                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
235                                         sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
236
237                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
238                                         switch (ale->type) {
239                                                 case ANIMTYPE_SUMMARY:
240                                                 {
241                                                         /* reddish color from NLA */
242                                                         immUniformThemeColor(TH_ANIM_ACTIVE);
243                                                         break;
244                                                 }
245                                                 case ANIMTYPE_SCENE:
246                                                 case ANIMTYPE_OBJECT:
247                                                 {
248                                                         immUniformColor3ubvAlpha(col1b, sel ? 0x45 : 0x22);
249                                                         break;
250                                                 }
251                                                 case ANIMTYPE_FILLACTD:
252                                                 case ANIMTYPE_DSSKEY:
253                                                 case ANIMTYPE_DSWOR:
254                                                 {
255                                                         immUniformColor3ubvAlpha(col2b, sel ? 0x45 : 0x22);
256                                                         break;
257                                                 }
258                                                 case ANIMTYPE_GROUP:
259                                                 {
260                                                         bActionGroup *agrp = ale->data;
261                                                         if (show_group_colors && agrp->customCol) {
262                                                                 if (sel) {
263                                                                         immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, 0x45);
264                                                                 }
265                                                                 else {
266                                                                         immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, 0x1D);
267                                                                 }
268                                                         }
269                                                         else {
270                                                                 immUniformColor3ubvAlpha(sel ? col1a : col2a, 0x22);
271                                                         }
272                                                         break;
273                                                 }
274                                                 case ANIMTYPE_FCURVE:
275                                                 {
276                                                         FCurve *fcu = ale->data;
277                                                         if (show_group_colors && fcu->grp && fcu->grp->customCol) {
278                                                                 immUniformColor3ubvAlpha((unsigned char *)fcu->grp->cs.active, sel ? 0x65 : 0x0B);
279                                                         }
280                                                         else {
281                                                                 immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
282                                                         }
283                                                         break;
284                                                 }
285                                                 default:
286                                                 {
287                                                         immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
288                                                 }
289                                         }
290
291                                         /* draw region twice: firstly backdrop, then the current range */
292                                         immRectf(pos, v2d->cur.xmin,  (float)y - ACHANNEL_HEIGHT_HALF(ac),  v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
293
294                                         if (ac->datatype == ANIMCONT_ACTION)
295                                                 immRectf(pos, act_start,  (float)y - ACHANNEL_HEIGHT_HALF(ac),  act_end,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
296                                 }
297                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
298                                         /* frames less than one get less saturated background */
299                                         immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
300                                         immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
301
302                                         /* frames one and higher get a saturated background */
303                                         immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44);
304                                         immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
305                                 }
306                                 else if (ac->datatype == ANIMCONT_MASK) {
307                                         /* TODO --- this is a copy of gpencil */
308                                         /* frames less than one get less saturated background */
309                                         immUniformColor3ubvAlpha(sel ? col1 : col2, 0x22);
310                                         immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
311
312                                         /* frames one and higher get a saturated background */
313                                         immUniformColor3ubvAlpha(sel ? col1 : col2, 0x44);
314                                         immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
315                                 }
316                         }
317                 }
318
319                 /*      Increment the step */
320                 y -= ACHANNEL_STEP(ac);
321         }
322         glDisable(GL_BLEND);
323
324         /* black line marking 'current frame' for Time-Slide transform mode */
325         if (saction->flag & SACTION_MOVING) {
326                 immUniformColor3f(0.0f, 0.0f, 0.0f);
327
328                 immBegin(GWN_PRIM_LINES, 2);
329                 immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
330                 immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
331                 immEnd();
332         }
333         immUnbindProgram();
334
335         /* Draw keyframes
336          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
337          *         This is to try to optimize this for heavier data sets
338          *      2) Keyframes which are out of view horizontally are disregarded
339          */
340         y = (float)(-ACHANNEL_HEIGHT(ac));
341
342         for (ale = anim_data.first; ale; ale = ale->next) {
343                 const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
344                 const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
345
346                 /* check if visible */
347                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
348                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
349                 {
350                         /* check if anything to show for this channel */
351                         if (ale->datatype != ALE_NONE) {
352                                 adt = ANIM_nla_mapping_get(ac, ale);
353
354                                 /* draw 'keyframes' for each specific datatype */
355                                 switch (ale->datatype) {
356                                         case ALE_ALL:
357                                                 draw_summary_channel(v2d, ale->data, y, ac->yscale_fac);
358                                                 break;
359                                         case ALE_SCE:
360                                                 draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
361                                                 break;
362                                         case ALE_OB:
363                                                 draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
364                                                 break;
365                                         case ALE_ACT:
366                                                 draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
367                                                 break;
368                                         case ALE_GROUP:
369                                                 draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac);
370                                                 break;
371                                         case ALE_FCURVE:
372                                                 draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
373                                                 break;
374                                         case ALE_GPFRAME:
375                                                 draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac);
376                                                 break;
377                                         case ALE_MASKLAY:
378                                                 draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac);
379                                                 break;
380                                 }
381                         }
382                 }
383
384                 y -= ACHANNEL_STEP(ac);
385         }
386
387         /* free temporary channels used for drawing */
388         ANIM_animdata_freelist(&anim_data);
389 }
390
391 /* ************************************************************************* */
392 /* Timeline - Caches */
393
394 void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
395 {
396         PTCacheID *pid;
397         ListBase pidlist;
398         const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
399         float yoffs = 0.f;
400
401         if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob))
402                 return;
403
404         BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
405
406         unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
407         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
408
409         /* iterate over pointcaches on the active object, and draw each one's range */
410         for (pid = pidlist.first; pid; pid = pid->next) {
411                 float col[4];
412
413                 switch (pid->type) {
414                         case PTCACHE_TYPE_SOFTBODY:
415                                 if (!(saction->cache_display & TIME_CACHE_SOFTBODY)) continue;
416                                 break;
417                         case PTCACHE_TYPE_PARTICLES:
418                                 if (!(saction->cache_display & TIME_CACHE_PARTICLES)) continue;
419                                 break;
420                         case PTCACHE_TYPE_CLOTH:
421                                 if (!(saction->cache_display & TIME_CACHE_CLOTH)) continue;
422                                 break;
423                         case PTCACHE_TYPE_SMOKE_DOMAIN:
424                         case PTCACHE_TYPE_SMOKE_HIGHRES:
425                                 if (!(saction->cache_display & TIME_CACHE_SMOKE)) continue;
426                                 break;
427                         case PTCACHE_TYPE_DYNAMICPAINT:
428                                 if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT)) continue;
429                                 break;
430                         case PTCACHE_TYPE_RIGIDBODY:
431                                 if (!(saction->cache_display & TIME_CACHE_RIGIDBODY)) continue;
432                                 break;
433                 }
434
435                 if (pid->cache->cached_frames == NULL)
436                         continue;
437
438                 gpuPushMatrix();
439                 gpuTranslate2f(0.0, (float)V2D_SCROLL_HEIGHT + yoffs);
440                 gpuScale2f(1.0, cache_draw_height);
441
442                 switch (pid->type) {
443                         case PTCACHE_TYPE_SOFTBODY:
444                                 col[0] = 1.0;   col[1] = 0.4;   col[2] = 0.02;
445                                 col[3] = 0.1;
446                                 break;
447                         case PTCACHE_TYPE_PARTICLES:
448                                 col[0] = 1.0;   col[1] = 0.1;   col[2] = 0.02;
449                                 col[3] = 0.1;
450                                 break;
451                         case PTCACHE_TYPE_CLOTH:
452                                 col[0] = 0.1;   col[1] = 0.1;   col[2] = 0.75;
453                                 col[3] = 0.1;
454                                 break;
455                         case PTCACHE_TYPE_SMOKE_DOMAIN:
456                         case PTCACHE_TYPE_SMOKE_HIGHRES:
457                                 col[0] = 0.2;   col[1] = 0.2;   col[2] = 0.2;
458                                 col[3] = 0.1;
459                                 break;
460                         case PTCACHE_TYPE_DYNAMICPAINT:
461                                 col[0] = 1.0;   col[1] = 0.1;   col[2] = 0.75;
462                                 col[3] = 0.1;
463                                 break;
464                         case PTCACHE_TYPE_RIGIDBODY:
465                                 col[0] = 1.0;   col[1] = 0.6;   col[2] = 0.0;
466                                 col[3] = 0.1;
467                                 break;
468                         default:
469                                 col[0] = 1.0;   col[1] = 0.0;   col[2] = 1.0;
470                                 col[3] = 0.1;
471                                 BLI_assert(0);
472                                 break;
473                 }
474
475                 const int sta = pid->cache->startframe, end = pid->cache->endframe;
476                 const int len = (end - sta + 1) * 6;
477
478                 glEnable(GL_BLEND);
479
480                 immUniformColor4fv(col);
481                 immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
482
483                 col[3] = 0.4f;
484                 if (pid->cache->flag & PTCACHE_BAKED) {
485                         col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
486                 }
487                 else if (pid->cache->flag & PTCACHE_OUTDATED) {
488                         col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
489                 }
490
491                 immUniformColor4fv(col);
492
493                 if (len > 0) {
494                         immBeginAtMost(GWN_PRIM_TRIS, len);
495
496                         /* draw a quad for each cached frame */
497                         for (int i = sta; i <= end; i++) {
498                                 if (pid->cache->cached_frames[i - sta]) {
499                                         immVertex2f(pos, (float)i - 0.5f, 0.0f);
500                                         immVertex2f(pos, (float)i - 0.5f, 1.0f);
501                                         immVertex2f(pos, (float)i + 0.5f, 1.0f);
502
503                                         immVertex2f(pos, (float)i - 0.5f, 0.0f);
504                                         immVertex2f(pos, (float)i + 0.5f, 1.0f);
505                                         immVertex2f(pos, (float)i + 0.5f, 0.0f);
506                                 }
507                         }
508
509                         immEnd();
510                 }
511
512                 glDisable(GL_BLEND);
513
514                 gpuPopMatrix();
515
516                 yoffs += cache_draw_height;
517         }
518
519         immUnbindProgram();
520
521         BLI_freelistN(&pidlist);
522 }
523
524 /* ************************************************************************* */