Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / space_clip / clip_dopesheet_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) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation,
23  *                 Sergey Sharybin
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_clip/clip_dopesheet_draw.c
29  *  \ingroup spclip
30  */
31
32 #include "DNA_movieclip_types.h"
33 #include "DNA_scene_types.h"
34
35 #include "BLI_utildefines.h"
36 #include "BLI_math.h"
37 #include "BLI_rect.h"
38
39 #include "BKE_context.h"
40 #include "BKE_movieclip.h"
41
42 #include "ED_screen.h"
43 #include "ED_clip.h"
44
45 #include "WM_types.h"
46
47 #include "UI_interface.h"
48 #include "UI_resources.h"
49 #include "UI_view2d.h"
50
51 #include "BLF_api.h"
52
53 #include "RNA_access.h"
54
55 #include "GPU_draw.h"
56 #include "GPU_immediate.h"
57
58 #include "clip_intern.h"  /* own include */
59
60 static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3])
61 {
62         if (track->flag & TRACK_CUSTOMCOLOR) {
63                 float bg[3];
64                 UI_GetThemeColor3fv(TH_HEADER, bg);
65
66                 interp_v3_v3v3(color, track->color, bg, 0.5);
67         }
68         else {
69                 if (default_color)
70                         copy_v3_v3(color, default_color);
71                 else
72                         UI_GetThemeColor3fv(TH_HEADER, color);
73         }
74 }
75
76 static void draw_keyframe_shape(float x, float y, bool sel, float alpha,
77                                 unsigned int pos_id, unsigned int color_id)
78 {
79         float color[4] = { 0.91f, 0.91f, 0.91f, alpha };
80         if (sel) {
81                 UI_GetThemeColorShadeAlpha4fv(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha), color);
82         }
83
84         immAttrib4fv(color_id, color);
85         immVertex2f(pos_id, x, y);
86 }
87
88 static void clip_draw_dopesheet_background(ARegion *ar, MovieClip *clip, unsigned int pos_id)
89 {
90         View2D *v2d = &ar->v2d;
91         MovieTracking *tracking = &clip->tracking;
92         MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
93         MovieTrackingDopesheetCoverageSegment *coverage_segment;
94
95         for (coverage_segment = dopesheet->coverage_segments.first;
96              coverage_segment;
97              coverage_segment = coverage_segment->next)
98         {
99                 if (coverage_segment->coverage < TRACKING_COVERAGE_OK) {
100                         int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->start_frame);
101                         int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, coverage_segment->end_frame);
102
103                         if (coverage_segment->coverage == TRACKING_COVERAGE_BAD) {
104                                 immUniformColor4f(1.0f, 0.0f, 0.0f, 0.07f);
105                         }
106                         else {
107                                 immUniformColor4f(1.0f, 1.0f, 0.0f, 0.07f);
108                         }
109
110                         immRectf(pos_id, start_frame, v2d->cur.ymin, end_frame, v2d->cur.ymax);
111                 }
112         }
113 }
114
115 void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
116 {
117         MovieClip *clip = ED_space_clip_get_clip(sc);
118         View2D *v2d = &ar->v2d;
119
120         /* frame range */
121         clip_draw_sfra_efra(v2d, scene);
122
123         if (clip) {
124                 MovieTracking *tracking = &clip->tracking;
125                 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
126                 MovieTrackingDopesheetChannel *channel;
127                 float strip[4], selected_strip[4];
128                 float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
129
130                 unsigned int keyframe_ct = 0;
131
132                 Gwn_VertFormat *format = immVertexFormat();
133                 unsigned int pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
134                 immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
135
136                 /* don't use totrect set, as the width stays the same
137                  * (NOTE: this is ok here, the configuration is pretty straightforward)
138                  */
139                 v2d->tot.ymin = (float)(-height);
140
141                 float y = (float) CHANNEL_FIRST;
142
143                 /* setup colors for regular and selected strips */
144                 UI_GetThemeColor3fv(TH_STRIP, strip);
145                 UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);
146
147                 strip[3] = 0.5f;
148                 selected_strip[3] = 1.0f;
149
150                 glEnable(GL_BLEND);
151
152                 clip_draw_dopesheet_background(ar, clip, pos_id);
153
154                 for (channel = dopesheet->channels.first; channel; channel = channel->next) {
155                         float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
156                         float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
157
158                         /* check if visible */
159                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
160                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
161                         {
162                                 MovieTrackingTrack *track = channel->track;
163                                 int i;
164                                 bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
165
166                                 /* selection background */
167                                 if (sel) {
168                                         float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
169                                         float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
170
171                                         track_channel_color(track, default_color, color);
172                                         immUniformColor4fv(color);
173
174                                         immRectf(pos_id, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
175                                                  v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
176                                 }
177
178                                 /* tracked segments */
179                                 for (i = 0; i < channel->tot_segment; i++) {
180                                         int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
181                                         int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
182
183                                         immUniformColor4fv(sel ? selected_strip : strip);
184
185                                         if (start_frame != end_frame) {
186                                                 immRectf(pos_id, start_frame, (float) y - STRIP_HEIGHT_HALF,
187                                                          end_frame, (float) y + STRIP_HEIGHT_HALF);
188                                                 keyframe_ct += 2;
189                                         }
190                                         else {
191                                                 keyframe_ct++;
192                                         }
193                                 }
194
195                                 /* keyframes */
196                                 i = 0;
197                                 while (i < track->markersnr) {
198                                         MovieTrackingMarker *marker = &track->markers[i];
199
200                                         if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
201                                                 keyframe_ct++;
202                                         }
203
204                                         i++;
205                                 }
206                         }
207
208                         /* adjust y-position for next one */
209                         y -= CHANNEL_STEP;
210                 }
211
212                 immUnbindProgram();
213
214                 if (keyframe_ct > 0) {
215                         /* draw keyframe markers */
216                         format = immVertexFormat();
217                         pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
218                         unsigned int size_id = GWN_vertformat_attr_add(format, "size", GWN_COMP_F32, 1, GWN_FETCH_FLOAT);
219                         unsigned int color_id = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 4, GWN_FETCH_FLOAT);
220                         unsigned int outline_color_id = GWN_vertformat_attr_add(format, "outlineColor", GWN_COMP_U8, 4, GWN_FETCH_INT_TO_FLOAT_UNIT);
221
222                         immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
223                         GPU_enable_program_point_size();
224                         immBegin(GWN_PRIM_POINTS, keyframe_ct);
225
226                         /* all same size with black outline */
227                         immAttrib1f(size_id, 2.0f * STRIP_HEIGHT_HALF);
228                         immAttrib4ub(outline_color_id, 0, 0, 0, 255);
229
230                         y = (float) CHANNEL_FIRST; /* start again at the top */
231                         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
232                                 float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
233                                 float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
234
235                                 /* check if visible */
236                                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
237                                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
238                                 {
239                                         MovieTrackingTrack *track = channel->track;
240                                         int i;
241                                         bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
242                                         float alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
243
244                                         /* tracked segments */
245                                         for (i = 0; i < channel->tot_segment; i++) {
246                                                 int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
247                                                 int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
248
249                                                 if (start_frame != end_frame) {
250                                                         draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
251                                                         draw_keyframe_shape(end_frame, y, sel, alpha, pos_id, color_id);
252                                                 }
253                                                 else {
254                                                         draw_keyframe_shape(start_frame, y, sel, alpha, pos_id, color_id);
255                                                 }
256                                         }
257
258                                         /* keyframes */
259                                         i = 0;
260                                         while (i < track->markersnr) {
261                                                 MovieTrackingMarker *marker = &track->markers[i];
262
263                                                 if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
264                                                         int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
265
266                                                         draw_keyframe_shape(framenr, y, sel, alpha, pos_id, color_id);
267                                                 }
268
269                                                 i++;
270                                         }
271                                 }
272
273                                 /* adjust y-position for next one */
274                                 y -= CHANNEL_STEP;
275                         }
276
277                         immEnd();
278                         GPU_disable_program_point_size();
279                         immUnbindProgram();
280                 }
281
282                 glDisable(GL_BLEND);
283         }
284 }
285
286 void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
287 {
288         ScrArea *sa = CTX_wm_area(C);
289         SpaceClip *sc = CTX_wm_space_clip(C);
290         View2D *v2d = &ar->v2d;
291         MovieClip *clip = ED_space_clip_get_clip(sc);
292         uiStyle *style = UI_style_get();
293         int fontid = style->widget.uifont_id;
294
295         if (!clip)
296                 return;
297
298         MovieTracking *tracking = &clip->tracking;
299         MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
300         int height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT);
301
302         if (height > BLI_rcti_size_y(&v2d->mask)) {
303                 /* don't use totrect set, as the width stays the same
304                  * (NOTE: this is ok here, the configuration is pretty straightforward)
305                  */
306                 v2d->tot.ymin = (float)(-height);
307         }
308
309         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
310         UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY);
311
312         /* loop through channels, and set up drawing depending on their type
313          * first pass: just the standard GL-drawing for backdrop + text
314          */
315         float y = (float) CHANNEL_FIRST;
316
317         Gwn_VertFormat *format = immVertexFormat();
318         unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
319
320         immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
321
322         MovieTrackingDopesheetChannel *channel;
323         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
324                 float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
325                 float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
326
327                 /* check if visible */
328                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
329                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
330                 {
331                         MovieTrackingTrack *track = channel->track;
332                         float color[3];
333                         track_channel_color(track, NULL, color);
334                         immUniformColor3fv(color);
335
336                         immRectf(pos, v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
337                                  v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
338                 }
339
340                 /* adjust y-position for next one */
341                 y -= CHANNEL_STEP;
342         }
343         immUnbindProgram();
344
345         /* second pass: text */
346         y = (float) CHANNEL_FIRST;
347
348         BLF_size(fontid, 11.0f * U.pixelsize, U.dpi);
349
350         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
351                 float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
352                 float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
353
354                 /* check if visible */
355                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
356                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
357                 {
358                         MovieTrackingTrack *track = channel->track;
359                         bool sel = (track->flag & TRACK_DOPE_SEL) != 0;
360
361                         UI_FontThemeColor(fontid, sel ? TH_TEXT_HI : TH_TEXT);
362
363                         float font_height = BLF_height(fontid, channel->name, sizeof(channel->name));
364                         BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
365                                      y - font_height / 2.0f, 0.0f);
366                         BLF_draw(fontid, channel->name, strlen(channel->name));
367                 }
368
369                 /* adjust y-position for next one */
370                 y -= CHANNEL_STEP;
371         }
372
373         /* third pass: widgets */
374         uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
375         y = (float) CHANNEL_FIRST;
376
377         /* get RNA properties (once) */
378         PropertyRNA *chan_prop_lock = RNA_struct_type_find_property(&RNA_MovieTrackingTrack, "lock");
379         BLI_assert(chan_prop_lock);
380
381         glEnable(GL_BLEND);
382         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
383                 float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
384                 float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
385
386                 /* check if visible */
387                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
388                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
389                 {
390                         MovieTrackingTrack *track = channel->track;
391                         const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
392                         PointerRNA ptr;
393
394                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
395
396                         UI_block_emboss_set(block, UI_EMBOSS_NONE);
397                         uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 1, icon,
398                                            v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f,
399                                            UI_UNIT_X, UI_UNIT_Y, &ptr, chan_prop_lock, 0, 0, 0, 0, 0, NULL);
400                         UI_block_emboss_set(block, UI_EMBOSS);
401                 }
402
403                 /* adjust y-position for next one */
404                 y -= CHANNEL_STEP;
405         }
406         glDisable(GL_BLEND);
407
408         UI_block_end(C, block);
409         UI_block_draw(C, block);
410 }