63148c2b69d5fb51608640e978ebe18ccd93f101
[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(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
162                 y = (float) CHANNEL_FIRST;
163
164                 UI_view2d_getscale(v2d, &xscale, &yscale);
165
166                 /* setup colors for regular and selected strips */
167                 UI_GetThemeColor3fv(TH_STRIP, strip);
168                 UI_GetThemeColor3fv(TH_STRIP_SELECT, selected_strip);
169
170                 strip[3] = 0.5f;
171                 selected_strip[3] = 1.0f;
172
173                 glEnable(GL_BLEND);
174
175                 for (channel = dopesheet->channels.first; channel; channel = channel->next) {
176                         float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
177                         float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
178
179                         /* check if visible */
180                         if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
181                             IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
182                         {
183                                 MovieTrackingTrack *track = channel->track;
184                                 float alpha;
185                                 int i, sel = track->flag & TRACK_DOPE_SEL;
186
187                                 /* selection background */
188                                 if (sel) {
189                                         float color[4] = {0.0f, 0.0f, 0.0f, 0.3f};
190                                         float default_color[4] = {0.8f, 0.93f, 0.8f, 0.3f};
191
192                                         track_channel_color(track, default_color, color);
193                                         glColor4fv(color);
194
195                                         glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
196                                                 v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
197                                 }
198
199                                 alpha = (track->flag & TRACK_LOCKED) ? 0.5f : 1.0f;
200
201                                 /* tracked segments */
202                                 for (i = 0; i < channel->tot_segment; i++) {
203                                         int start_frame = channel->segments[2 * i];
204                                         int end_frame = channel->segments[2 * i + 1];
205
206                                         if (sel)
207                                                 glColor4fv(selected_strip);
208                                         else
209                                                 glColor4fv(strip);
210
211                                         if (start_frame != end_frame) {
212                                                 glRectf(start_frame, (float) y - STRIP_HEIGHT_HALF,
213                                                                 end_frame, (float) y + STRIP_HEIGHT_HALF);
214                                                 draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
215                                                 draw_keyframe_shape(end_frame, y, xscale, yscale, sel, alpha);
216                                         }
217                                         else {
218                                                 draw_keyframe_shape(start_frame, y, xscale, yscale, sel, alpha);
219                                         }
220                                 }
221
222                                 /* keyframes */
223                                 i = 0;
224                                 while (i < track->markersnr) {
225                                         MovieTrackingMarker *marker = &track->markers[i];
226
227                                         if ((marker->flag & (MARKER_DISABLED | MARKER_TRACKED)) == 0)
228                                                 draw_keyframe_shape(marker->framenr, y, xscale, yscale, sel, alpha);
229
230                                         i++;
231                                 }
232                         }
233
234                         /* adjust y-position for next one */
235                         y -= CHANNEL_STEP;
236                 }
237
238                 glDisable(GL_BLEND);
239         }
240
241         /* current frame */
242         clip_draw_cfra(sc, ar, scene);
243 }
244
245 void clip_draw_dopesheet_channels(const bContext *C, ARegion *ar)
246 {
247         ScrArea *sa = CTX_wm_area(C);
248         SpaceClip *sc = CTX_wm_space_clip(C);
249         View2D *v2d = &ar->v2d;
250         MovieClip *clip = ED_space_clip(sc);
251         MovieTracking *tracking;
252         MovieTrackingDopesheet *dopesheet;
253         MovieTrackingDopesheetChannel *channel;
254         uiStyle *style = UI_GetStyle();
255         uiBlock *block;
256         int fontid = style->widget.uifont_id;
257         int height;
258         float y;
259
260         if (!clip)
261                 return;
262
263         tracking = &clip->tracking;
264         dopesheet = &tracking->dopesheet;
265         height = (dopesheet->tot_channel * CHANNEL_STEP) + (CHANNEL_HEIGHT * 2);
266
267         if (height > (v2d->mask.ymax - v2d->mask.ymin)) {
268                 /* don't use totrect set, as the width stays the same
269                  * (NOTE: this is ok here, the configuration is pretty straightforward)
270                  */
271                 v2d->tot.ymin = (float)(-height);
272         }
273
274         /* need to do a view-sync here, so that the keys area doesn't jump around (it must copy this) */
275         UI_view2d_sync(NULL, sa, v2d, V2D_LOCK_COPY);
276
277         /* loop through channels, and set up drawing depending on their type
278          * first pass: just the standard GL-drawing for backdrop + text
279          */
280         y = (float) CHANNEL_FIRST;
281
282         BLF_size(fontid, 11.0f, U.dpi);
283
284         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
285                 float yminc = (float) (y - CHANNEL_HEIGHT_HALF);
286                 float ymaxc = (float) (y + CHANNEL_HEIGHT_HALF);
287
288                 /* check if visible */
289                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
290                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
291                 {
292                         MovieTrackingTrack *track = channel->track;
293                         float font_height, color[3];
294                         int sel = track->flag & TRACK_DOPE_SEL;
295
296                         track_channel_color(track, NULL, color);
297                         glColor3fv(color);
298
299                         glRectf(v2d->cur.xmin, (float) y - CHANNEL_HEIGHT_HALF,
300                                 v2d->cur.xmax + EXTRA_SCROLL_PAD, (float) y + CHANNEL_HEIGHT_HALF);
301
302                         if (sel)
303                                 UI_ThemeColor(TH_TEXT_HI);
304                         else
305                                 UI_ThemeColor(TH_TEXT);
306
307                         font_height = BLF_height(fontid, track->name);
308                         BLF_position(fontid, v2d->cur.xmin + CHANNEL_PAD,
309                                              y - font_height / 2.0f, 0.0f);
310                         BLF_draw(fontid, track->name, strlen(track->name));
311                 }
312
313                 /* adjust y-position for next one */
314                 y -= CHANNEL_STEP;
315         }
316
317         /* second pass: widgets */
318         block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
319         y = (float) CHANNEL_FIRST;
320
321         glEnable(GL_BLEND);
322         for (channel = dopesheet->channels.first; channel; channel = channel->next) {
323                 float yminc = (float)(y - CHANNEL_HEIGHT_HALF);
324                 float ymaxc = (float)(y + CHANNEL_HEIGHT_HALF);
325
326                 /* check if visible */
327                 if (IN_RANGE(yminc, v2d->cur.ymin, v2d->cur.ymax) ||
328                     IN_RANGE(ymaxc, v2d->cur.ymin, v2d->cur.ymax))
329                 {
330                         MovieTrackingTrack *track = channel->track;
331                         const int icon = (track->flag & TRACK_LOCKED) ? ICON_LOCKED : ICON_UNLOCKED;
332                         PointerRNA ptr;
333
334                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingTrack, track, &ptr);
335
336                         uiBlockSetEmboss(block, UI_EMBOSSN);
337                         uiDefIconButR(block, ICONTOG, 1, icon,
338                                       v2d->cur.xmax - UI_UNIT_X - CHANNEL_PAD, y - UI_UNIT_Y / 2.0f,
339                                       UI_UNIT_X, UI_UNIT_Y, &ptr, "lock", 0, 0, 0, 0, 0, NULL);
340                         uiBlockSetEmboss(block, UI_EMBOSS);
341                 }
342
343                 /* adjust y-position for next one */
344                 y -= CHANNEL_STEP;
345         }
346         glDisable(GL_BLEND);
347
348         uiEndBlock(C, block);
349         uiDrawBlock(C, block);
350 }