Changes in clip editor's public api to make it's more clear
[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_object_types.h"   /* SELECT */
34 #include "DNA_scene_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BKE_context.h"
39 #include "BKE_movieclip.h"
40 #include "BKE_tracking.h"
41
42 #include "BLI_utildefines.h"
43 #include "BLI_math.h"
44 #include "BLI_string.h"
45 #include "BLI_listbase.h"
46 #include "BLI_math.h"
47
48 #include "ED_screen.h"
49 #include "ED_clip.h"
50
51 #include "BIF_gl.h"
52 #include "BIF_glutil.h"
53
54 #include "WM_types.h"
55
56 #include "UI_interface.h"
57 #include "UI_resources.h"
58 #include "UI_view2d.h"
59
60 #include "BLF_api.h"
61
62 #include "RNA_access.h"
63
64 #include "clip_intern.h"  /* own include */
65
66 static void track_channel_color(MovieTrackingTrack *track, float default_color[3], float color[3])
67 {
68         if (track->flag & TRACK_CUSTOMCOLOR) {
69                 float bg[3];
70                 UI_GetThemeColor3fv(TH_HEADER, bg);
71
72                 interp_v3_v3v3(color, track->color, bg, 0.5);
73         }
74         else {
75                 if (default_color)
76                         copy_v3_v3(color, default_color);
77                 else
78                         UI_GetThemeColor3fv(TH_HEADER, color);
79         }
80 }
81
82 static void draw_keyframe_shape(float x, float y, float xscale, float yscale, short sel, float alpha)
83 {
84         /* coordinates for diamond shape */
85         static const float _unit_diamond_shape[4][2] = {
86                 {0.0f, 1.0f},   /* top vert */
87                 {1.0f, 0.0f},   /* mid-right */
88                 {0.0f, -1.0f},  /* bottom vert */
89                 {-1.0f, 0.0f}   /* mid-left */
90         };
91         static GLuint displist1 = 0;
92         static GLuint displist2 = 0;
93         int hsize = STRIP_HEIGHT_HALF;
94
95         /* initialize 2 display lists for diamond shape - one empty, one filled */
96         if (displist1 == 0) {
97                 displist1 = glGenLists(1);
98                 glNewList(displist1, GL_COMPILE);
99
100                 glBegin(GL_LINE_LOOP);
101                 glVertex2fv(_unit_diamond_shape[0]);
102                 glVertex2fv(_unit_diamond_shape[1]);
103                 glVertex2fv(_unit_diamond_shape[2]);
104                 glVertex2fv(_unit_diamond_shape[3]);
105                 glEnd();
106                 glEndList();
107         }
108         if (displist2 == 0) {
109                 displist2 = glGenLists(1);
110                 glNewList(displist2, GL_COMPILE);
111
112                 glBegin(GL_QUADS);
113                 glVertex2fv(_unit_diamond_shape[0]);
114                 glVertex2fv(_unit_diamond_shape[1]);
115                 glVertex2fv(_unit_diamond_shape[2]);
116                 glVertex2fv(_unit_diamond_shape[3]);
117                 glEnd();
118                 glEndList();
119         }
120
121         glPushMatrix();
122
123         /* adjust view transform before starting */
124         glTranslatef(x, y, 0.0f);
125         glScalef(1.0f / xscale * hsize, 1.0f / yscale * hsize, 1.0f);
126
127         /* anti-aliased lines for more consistent appearance */
128         glEnable(GL_LINE_SMOOTH);
129
130         if (sel)
131                 UI_ThemeColorShadeAlpha(TH_STRIP_SELECT, 50, -255 * (1.0f - alpha));
132         else
133                 glColor4f(0.91f, 0.91f, 0.91f, alpha);
134
135         glCallList(displist2);
136
137         /* exterior - black frame */
138         glColor4f(0.0f, 0.0f, 0.0f, alpha);
139         glCallList(displist1);
140
141         glDisable(GL_LINE_SMOOTH);
142
143         /* restore view transform */
144         glPopMatrix();
145 }
146
147 void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
148 {
149         MovieClip *clip = ED_space_clip_get_clip(sc);
150         View2D *v2d = &ar->v2d;
151
152         /* frame range */
153         clip_draw_sfra_efra(v2d, scene);
154
155         if (clip) {
156                 MovieTracking *tracking = &clip->tracking;
157                 MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
158                 MovieTrackingDopesheetChannel *channel;
159                 float y, xscale, yscale;
160                 float strip[4], selected_strip[4];
161                 float height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
162
163                 /* don't use totrect set, as the width stays the same
164                  * (NOTE: this is ok here, the configuration is pretty straightforward)
165                  */
166                 v2d->tot.ymin = (float)(-height);
167
168                 y = (float) CHANNEL_FIRST;
169
170                 UI_view2d_getscale(v2d, &xscale, &yscale);
171
172                 /* setup colors for regular and selected strips */
173                 UI_GetThemeColor3fv(TH_STRIP, strip);
174                 UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);
175
176                 strip[3] = 0.5f;
177                 selected_strip[3] = 1.0f;
178
179                 glEnable(GL_BLEND);
180
181                 for (channel = dopesheet->channels.first; channel; channel = channel->next) {
182                         float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
183                         float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
184
185                         /* check if visible */
186                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
187                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
188                         {
189                                 MovieTrackingTrack *track = channel->track;
190                                 float alpha;
191                                 int i, sel = track->flag & TRACK_DOPE_SEL;
192
193                                 /* selection background */
194                                 if (sel) {
195                                         float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
196                                         float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
197
198                                         track_channel_color(track, default_color, color);
199                                         glColor4fv(color);
200
201                                         glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
202                                                 v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
203                                 }
204
205                                 alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
206
207                                 /* tracked segments */
208                                 for (i = 0; i < channel->tot_segment; i++) {
209                                         int start_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i]);
210                                         int end_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, channel->segments[2 * i + 1]);
211
212                                         if (sel)
213                                                 glColor4fv(selected_strip);
214                                         else
215                                                 glColor4fv(strip);
216
217                                         if (start_frame != end_frame) {
218                                                 glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF,
219                                                         end_frame, (float) y + STRIP_HEIGHT_HALF);
220                                                 draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
221                                                 draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha);
222                                         }
223                                         else {
224                                                 draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
225                                         }
226                                 }
227
228                                 /* keyframes */
229                                 i = 0;
230                                 while (i < track->markersnr) {
231                                         MovieTrackingMarker *marker = &track->markers[i];
232
233                                         if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0) {
234                                                 int framenr = BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
235
236                                                 draw_keyframe_shape(framenr, y, xscale, yscale, sel, alpha);
237                                         }
238
239                                         i++;
240                                 }
241                         }
242
243                         /* adjust y-position for next one */
244                         y -= CHANNEL_STEP;
245                 }
246
247                 glDisable(GL_BLEND);
248         }
249
250         /* current frame */
251         clip_draw_cfra(sc, ar, scene);
252 }
253
254 void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
255 {
256         ScrArea *sa = CTX_wm_area(C);
257         SpaceClip *sc = CTX_wm_space_clip(C);
258         View2D *v2d = &ar->v2d;
259         MovieClip *clip = ED_space_clip_get_clip(sc);
260         MovieTracking *tracking;
261         MovieTrackingDopesheet *dopesheet;
262         MovieTrackingDopesheetChannel *channel;
263         uiStyle *style = UI_GetStyle();
264         uiBlock *block;
265         int fontid = style->widget.uifont_id;
266         int height;
267         float y;
268
269         if (!clip)
270                 return;
271
272         tracking = &clip->tracking;
273         dopesheet = &tracking->dopesheet;
274         height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
275
276         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
277                 /* don't use totrect set, as the width stays the same
278                  * (NOTE: this is ok here, the configuration is pretty straightforward)
279                  */
280                 v2d->tot.ymin = (float)(-height);
281         }
282
283         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
284         UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY);
285
286         /* loop through channels, and set up drawing depending on their type
287          * first pass: just the standard GL-drawing for backdrop + text
288          */
289         y = (float) CHANNEL_FIRST;
290
291         BLF_size(fontid, 11.0f, U.dpi);
292
293         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
294                 float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
295                 float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
296
297                 /* check if visible */
298                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
299                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
300                 {
301                         MovieTrackingTrack *track = channel->track;
302                         float font_height, color[3];
303                         int sel = track->flag & TRACK_DOPE_SEL;
304
305                         track_channel_color(track, NULL, color);
306                         glColor3fv(color);
307
308                         glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
309                                 v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
310
311                         if (sel)
312                                 UI_ThemeColor(TH_TEXT_HI);
313                         else
314                                 UI_ThemeColor(TH_TEXT);
315
316                         font_height = BLF_height(fontid, channel->name);
317                         BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
318                                      y - font_height / 2.0f, 0.0f);
319                         BLF_draw(fontid, channel->name, strlen(channel->name));
320                 }
321
322                 /* adjust y-position for next one */
323                 y -= CHANNEL_STEP;
324         }
325
326         /* second pass: widgets */
327         block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
328         y = (float) CHANNEL_FIRST;
329
330         glEnable(GL_BLEND);
331         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
332                 float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
333                 float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
334
335                 /* check if visible */
336                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
337                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
338                 {
339                         MovieTrackingTrack *track = channel->track;
340                         const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
341                         PointerRNA ptr;
342
343                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
344
345                         uiBlockSetEmboss(block, UI_EMBOSSN);
346                         uiDefIconButR(block, ICONTOG, 1, icon,
347                                       v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f,
348                                       UI_UNIT_X, UI_UNIT_Y, &ptr, "lock", 0, 0, 0, 0, 0, NULL);
349                         uiBlockSetEmboss(block, UI_EMBOSS);
350                 }
351
352                 /* adjust y-position for next one */
353                 y -= CHANNEL_STEP;
354         }
355         glDisable(GL_BLEND);
356
357         uiEndBlock(C, block);
358         uiDrawBlock(C, block);
359 }