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_screen_types.h"
47
48 #include "BKE_action.h"
49 #include "BKE_context.h"
50
51
52 /* Everything from source (BIF, BDR, BSE) ------------------------------ */ 
53
54 #include "BIF_gl.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58 #include "UI_view2d.h"
59
60 #include "ED_anim_api.h"
61 #include "ED_keyframes_draw.h"
62
63 #include "action_intern.h"
64 #include "GPU_immediate.h"
65
66 /* ************************************************************************* */
67 /* Channel List */
68
69 /* left hand part */
70 void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *ar) 
71 {
72         ListBase anim_data = {NULL, NULL};
73         bAnimListElem *ale;
74         int filter;
75         
76         View2D *v2d = &ar->v2d;
77         float y = 0.0f;
78         size_t items;
79         int height;
80         
81         /* build list of channels to draw */
82         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
83         items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
84         
85         height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
86         if (height > BLI_rcti_size_y(&v2d->mask)) {
87                 /* don't use totrect set, as the width stays the same 
88                  * (NOTE: this is ok here, the configuration is pretty straightforward) 
89                  */
90                 v2d->tot.ymin = (float)(-height);
91         }
92         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
93         UI_view2d_sync(NULL, ac->sa, v2d, V2D_LOCK_COPY);
94         
95         /* loop through channels, and set up drawing depending on their type  */
96         {   /* first pass: just the standard GL-drawing for backdrop + text */
97                 size_t channel_index = 0;
98                 
99                 y = (float)ACHANNEL_FIRST(ac);
100                 
101                 for (ale = anim_data.first; ale; ale = ale->next) {
102                         float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
103                         float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
104                         
105                         /* check if visible */
106                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
107                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
108                         {
109                                 /* draw all channels using standard channel-drawing API */
110                                 ANIM_channel_draw(ac, ale, yminc, ymaxc, channel_index);
111                         }
112                         
113                         /* adjust y-position for next one */
114                         y -= ACHANNEL_STEP(ac);
115                         channel_index++;
116                 }
117         }
118         {   /* second pass: widgets */
119                 uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
120                 size_t channel_index = 0;
121                 
122                 y = (float)ACHANNEL_FIRST(ac);
123                 
124                 for (ale = anim_data.first; ale; ale = ale->next) {
125                         float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
126                         float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
127                         
128                         /* check if visible */
129                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
130                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
131                         {
132                                 /* draw all channels using standard channel-drawing API */
133                                 ANIM_channel_draw_widgets(C, ac, ale, block, yminc, ymaxc, channel_index);
134                         }
135                         
136                         /* adjust y-position for next one */
137                         y -= ACHANNEL_STEP(ac);
138                         channel_index++;
139                 }
140                 
141                 UI_block_end(C, block);
142                 UI_block_draw(C, block);
143         }
144         
145         /* free tempolary channels */
146         ANIM_animdata_freelist(&anim_data);
147 }
148
149 /* ************************************************************************* */
150 /* Keyframes */
151
152 /* extra padding for lengths (to go under scrollers) */
153 #define EXTRA_SCROLL_PAD    100.0f
154
155 /* draw keyframes in each channel */
156 void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
157 {
158         ListBase anim_data = {NULL, NULL};
159         bAnimListElem *ale;
160         int filter;
161         
162         View2D *v2d = &ar->v2d;
163         bDopeSheet *ads = &saction->ads;
164         AnimData *adt = NULL;
165         
166         float act_start, act_end, y;
167         size_t items;
168         int height;
169         
170         unsigned char col1[3], col2[3];
171         unsigned char col1a[3], col2a[3];
172         unsigned char col1b[3], col2b[3];
173         
174         const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
175         
176         
177         /* get theme colors */
178         UI_GetThemeColor3ubv(TH_BACK, col2);
179         UI_GetThemeColor3ubv(TH_HILITE, col1);
180         
181         UI_GetThemeColor3ubv(TH_GROUP, col2a);
182         UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
183         
184         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
185         UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
186         
187         /* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
188
189         /* if in NLA there's a strip active, map the view */
190         if (ac->datatype == ANIMCONT_ACTION) {
191                 /* adt = ANIM_nla_mapping_get(ac, NULL); */ /* UNUSED */
192                 
193                 /* start and end of action itself */
194                 calc_action_range(ac->data, &act_start, &act_end, 0);
195         }
196         
197         /* build list of channels to draw */
198         filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
199         items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
200         
201         height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
202         /* don't use totrect set, as the width stays the same 
203          * (NOTE: this is ok here, the configuration is pretty straightforward) 
204          */
205         v2d->tot.ymin = (float)(-height);
206         
207         /* first backdrop strips */
208         y = (float)(-ACHANNEL_HEIGHT(ac));
209
210         VertexFormat* format = immVertexFormat();
211         unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
212
213         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
214
215         glEnable(GL_BLEND);
216         
217         for (ale = anim_data.first; ale; ale = ale->next) {
218                 const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
219                 const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
220                 
221                 /* check if visible */
222                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
223                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
224                 {
225                         const bAnimChannelType *acf = ANIM_channel_get_typeinfo(ale);
226                         int sel = 0;
227                         
228                         /* determine if any need to draw channel */
229                         if (ale->datatype != ALE_NONE) {
230                                 /* determine if channel is selected */
231                                 if (acf->has_setting(ac, ale, ACHANNEL_SETTING_SELECT))
232                                         sel = ANIM_channel_setting_get(ac, ale, ACHANNEL_SETTING_SELECT);
233
234                                 if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_SHAPEKEY)) {
235                                         switch (ale->type) {
236                                                 case ANIMTYPE_SUMMARY:
237                                                 {
238                                                         /* reddish color from NLA */
239                                                         UI_ThemeColor4(TH_ANIM_ACTIVE);
240                                                         break;
241                                                 }
242                                                 case ANIMTYPE_SCENE:
243                                                 case ANIMTYPE_OBJECT:
244                                                 {
245                                                         if (sel) immUniformColor4ub(col1b[0], col1b[1], col1b[2], 0x45);
246                                                         else immUniformColor4ub(col1b[0], col1b[1], col1b[2], 0x22);
247                                                         break;
248                                                 }
249                                                 case ANIMTYPE_FILLACTD:
250                                                 case ANIMTYPE_DSSKEY:
251                                                 case ANIMTYPE_DSWOR:
252                                                 {
253                                                         if (sel) immUniformColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
254                                                         else immUniformColor4ub(col2b[0], col2b[1], col2b[2], 0x22);
255                                                         break;
256                                                 }
257                                                 case ANIMTYPE_GROUP:
258                                                 {
259                                                         bActionGroup *agrp = ale->data;
260                                                         if (show_group_colors && agrp->customCol) {
261                                                                 if (sel) {
262                                                                         unsigned char *cp = agrp->cs.select;
263                                                                         immUniformColor4ub(cp[0], cp[1], cp[2], 0x45);
264                                                                 }
265                                                                 else {
266                                                                         unsigned char *cp = agrp->cs.solid;
267                                                                         immUniformColor4ub(cp[0], cp[1], cp[2], 0x1D);
268                                                                 }
269                                                         }
270                                                         else {
271                                                                 if (sel) immUniformColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
272                                                                 else immUniformColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
273                                                         }
274                                                         break;
275                                                 }
276                                                 case ANIMTYPE_FCURVE:
277                                                 {
278                                                         FCurve *fcu = ale->data;
279                                                         if (show_group_colors && fcu->grp && fcu->grp->customCol) {
280                                                                 unsigned char *cp = (unsigned char *)fcu->grp->cs.active;
281                                                                 
282                                                                 if (sel) immUniformColor4ub(cp[0], cp[1], cp[2], 0x65);
283                                                                 else immUniformColor4ub(cp[0], cp[1], cp[2], 0x0B);
284                                                         }
285                                                         else {
286                                                                 if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x22);
287                                                                 else immUniformColor4ub(col2[0], col2[1], col2[2], 0x22);
288                                                         }
289                                                         break;
290                                                 }
291                                                 default:
292                                                 {
293                                                         if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x22);
294                                                         else immUniformColor4ub(col2[0], col2[1], col2[2], 0x22);
295                                                         break;
296                                                 }
297                                         }
298                                         
299                                         /* draw region twice: firstly backdrop, then the current range */
300                                         immRectf(pos, v2d->cur.xmin,  (float)y - ACHANNEL_HEIGHT_HALF(ac),  v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
301                                         
302                                         if (ac->datatype == ANIMCONT_ACTION)
303                                                 immRectf(pos, act_start,  (float)y - ACHANNEL_HEIGHT_HALF(ac),  act_end,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
304                                 }
305                                 else if (ac->datatype == ANIMCONT_GPENCIL) {
306                                         /* frames less than one get less saturated background */
307                                         if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x22);
308                                         else immUniformColor4ub(col2[0], col2[1], col2[2], 0x22);
309                                         immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
310                                         
311                                         /* frames one and higher get a saturated background */
312                                         if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x44);
313                                         else immUniformColor4ub(col2[0], col2[1], col2[2], 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                                 else if (ac->datatype == ANIMCONT_MASK) {
317                                         /* TODO --- this is a copy of gpencil */
318                                         /* frames less than one get less saturated background */
319                                         if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x22);
320                                         else immUniformColor4ub(col2[0], col2[1], col2[2], 0x22);
321                                         immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
322
323                                         /* frames one and higher get a saturated background */
324                                         if (sel) immUniformColor4ub(col1[0], col1[1], col1[2], 0x44);
325                                         else immUniformColor4ub(col2[0], col2[1], col2[2], 0x44);
326                                         immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD,  (float)y + ACHANNEL_HEIGHT_HALF(ac));
327                                 }
328                         }
329                 }
330                 
331                 /*      Increment the step */
332                 y -= ACHANNEL_STEP(ac);
333         }
334         glDisable(GL_BLEND);
335         
336         /* Draw keyframes 
337          *      1) Only channels that are visible in the Action Editor get drawn/evaluated.
338          *         This is to try to optimize this for heavier data sets
339          *      2) Keyframes which are out of view horizontally are disregarded 
340          */
341         y = (float)(-ACHANNEL_HEIGHT(ac));
342         
343         for (ale = anim_data.first; ale; ale = ale->next) {
344                 const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
345                 const float ymaxc = (float)(y + ACHANNEL_HEIGHT_HALF(ac));
346                 
347                 /* check if visible */
348                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
349                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax) )
350                 {
351                         /* check if anything to show for this channel */
352                         if (ale->datatype != ALE_NONE) {
353                                 adt = ANIM_nla_mapping_get(ac, ale);
354                                 
355                                 /* draw 'keyframes' for each specific datatype */
356                                 switch (ale->datatype) {
357                                         case ALE_ALL:
358                                                 draw_summary_channel(v2d, ale->data, y, ac->yscale_fac);
359                                                 break;
360                                         case ALE_SCE:
361                                                 draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
362                                                 break;
363                                         case ALE_OB:
364                                                 draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
365                                                 break;
366                                         case ALE_ACT:
367                                                 draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
368                                                 break;
369                                         case ALE_GROUP:
370                                                 draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac);
371                                                 break;
372                                         case ALE_FCURVE:
373                                                 draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
374                                                 break;
375                                         case ALE_GPFRAME:
376                                                 draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac);
377                                                 break;
378                                         case ALE_MASKLAY:
379                                                 draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac);
380                                                 break;
381                                 }
382                         }
383                 }
384                 
385                 y -= ACHANNEL_STEP(ac);
386         }
387         
388         /* free tempolary channels used for drawing */
389         ANIM_animdata_freelist(&anim_data);
390
391         /* black line marking 'current frame' for Time-Slide transform mode */
392         if (saction->flag & SACTION_MOVING) {
393                 immUniformColor3f(0.0f, 0.0f, 0.0f);
394
395                 immBegin(GL_LINES, 2);
396                 immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
397                 immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
398                 immEnd();
399         }
400         immUnbindProgram();
401 }