Sequencer: fix for wrong color space sequencer effects were working in
[blender.git] / source / blender / editors / mask / mask_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/mask/mask_draw.c
29  *  \ingroup edmask
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "BLI_utildefines.h"
35 #include "BLI_math.h"
36 #include "BLI_rect.h"
37
38 #include "BKE_context.h"
39 #include "BKE_mask.h"
40
41 #include "DNA_mask_types.h"
42 #include "DNA_screen_types.h"
43 #include "DNA_object_types.h"   /* SELECT */
44
45 #include "ED_mask.h"  /* own include */
46 #include "ED_space_api.h"
47 #include "BIF_gl.h"
48
49 #include "UI_resources.h"
50 #include "UI_view2d.h"
51
52 #include "mask_intern.h"  /* own include */
53
54 static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const int is_sel,
55                                   unsigned char r_rgb[4])
56 {
57         if (is_sel) {
58                 if (masklay->act_spline == spline) {
59                         r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
60                 }
61                 else {
62                         r_rgb[0] = 255;
63                         r_rgb[1] = r_rgb[2] = 0;
64                 }
65         }
66         else {
67                 r_rgb[0] = 128;
68                 r_rgb[1] = r_rgb[2] = 0;
69         }
70
71         r_rgb[3] = 255;
72 }
73
74 static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const int is_sel,
75                                           unsigned char r_rgb[4])
76 {
77         if (is_sel) {
78                 r_rgb[1] = 255;
79                 r_rgb[0] = r_rgb[2] = 0;
80         }
81         else {
82                 r_rgb[1] = 128;
83                 r_rgb[0] = r_rgb[2] = 0;
84         }
85
86         r_rgb[3] = 255;
87 }
88
89 #if 0
90 static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
91 {
92         int i;
93         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
94
95         if (!spline->tot_point)
96                 return;
97
98         glColor3ub(0, 0, 0);
99         glEnable(GL_LINE_STIPPLE);
100         glLineStipple(1, 0xAAAA);
101
102         glBegin(GL_LINES);
103
104         for (i = 0; i < spline->tot_point; i++) {
105                 MaskSplinePoint *point = &points_array[i];
106                 BezTriple *bezt = &point->bezt;
107
108                 if (point->parent.id) {
109                         glVertex2f(bezt->vec[1][0],
110                                    bezt->vec[1][1]);
111
112                         glVertex2f(bezt->vec[1][0] - point->parent.offset[0],
113                                    bezt->vec[1][1] - point->parent.offset[1]);
114                 }
115         }
116
117         glEnd();
118
119         glDisable(GL_LINE_STIPPLE);
120 }
121 #endif
122
123 /* return non-zero if spline is selected */
124 static void draw_spline_points(MaskLayer *masklay, MaskSpline *spline,
125                                const char UNUSED(draw_flag), const char draw_type)
126 {
127         const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
128         unsigned char rgb_spline[4];
129         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
130
131         int i, hsize, tot_feather_point;
132         float (*feather_points)[2], (*fp)[2];
133
134         if (!spline->tot_point)
135                 return;
136
137         /* TODO, add this to sequence editor */
138         hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */
139
140         glPointSize(hsize);
141
142         mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
143
144         /* feather points */
145         feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
146         for (i = 0; i < spline->tot_point; i++) {
147
148                 /* watch it! this is intentionally not the deform array, only check for sel */
149                 MaskSplinePoint *point = &spline->points[i];
150
151                 int j;
152
153                 for (j = 0; j < point->tot_uw + 1; j++) {
154                         int sel = FALSE;
155
156                         if (j == 0) {
157                                 sel = MASKPOINT_ISSEL_ANY(point);
158                         }
159                         else {
160                                 sel = point->uw[j - 1].flag & SELECT;
161                         }
162
163                         if (sel) {
164                                 if (point == masklay->act_point)
165                                         glColor3f(1.0f, 1.0f, 1.0f);
166                                 else
167                                         glColor3f(1.0f, 1.0f, 0.0f);
168                         }
169                         else {
170                                 glColor3f(0.5f, 0.5f, 0.0f);
171                         }
172
173                         glBegin(GL_POINTS);
174                         glVertex2fv(*fp);
175                         glEnd();
176
177                         fp++;
178                 }
179         }
180         MEM_freeN(feather_points);
181
182         /* control points */
183         for (i = 0; i < spline->tot_point; i++) {
184
185                 /* watch it! this is intentionally not the deform array, only check for sel */
186                 MaskSplinePoint *point = &spline->points[i];
187                 MaskSplinePoint *point_deform = &points_array[i];
188                 BezTriple *bezt = &point_deform->bezt;
189
190                 float handle[2];
191                 float *vert = bezt->vec[1];
192                 int has_handle = BKE_mask_point_has_handle(point);
193
194                 BKE_mask_point_handle(point_deform, handle);
195
196                 /* draw handle segment */
197                 if (has_handle) {
198
199                         /* this could be split into its own loop */
200                         if (draw_type == MASK_DT_OUTLINE) {
201                                 const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
202                                 glLineWidth(3);
203                                 glColor4ubv(rgb_gray);
204                                 glBegin(GL_LINES);
205                                 glVertex3fv(vert);
206                                 glVertex3fv(handle);
207                                 glEnd();
208                                 glLineWidth(1);
209                         }
210
211                         glColor3ubv(rgb_spline);
212                         glBegin(GL_LINES);
213                         glVertex3fv(vert);
214                         glVertex3fv(handle);
215                         glEnd();
216                 }
217
218                 /* draw CV point */
219                 if (MASKPOINT_ISSEL_KNOT(point)) {
220                         if (point == masklay->act_point)
221                                 glColor3f(1.0f, 1.0f, 1.0f);
222                         else
223                                 glColor3f(1.0f, 1.0f, 0.0f);
224                 }
225                 else
226                         glColor3f(0.5f, 0.5f, 0.0f);
227
228                 glBegin(GL_POINTS);
229                 glVertex3fv(vert);
230                 glEnd();
231
232                 /* draw handle points */
233                 if (has_handle) {
234                         if (MASKPOINT_ISSEL_HANDLE(point)) {
235                                 if (point == masklay->act_point)
236                                         glColor3f(1.0f, 1.0f, 1.0f);
237                                 else
238                                         glColor3f(1.0f, 1.0f, 0.0f);
239                         }
240                         else {
241                                 glColor3f(0.5f, 0.5f, 0.0f);
242                         }
243
244                         glBegin(GL_POINTS);
245                         glVertex3fv(handle);
246                         glEnd();
247                 }
248         }
249
250         glPointSize(1.0f);
251 }
252
253 /* #define USE_XOR */
254
255 static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const short is_active)
256 {
257         if (!is_active) {
258                 r_rgb[0] = (unsigned char)((((int)(rgb[0])) + 128) / 2);
259                 r_rgb[1] = (unsigned char)((((int)(rgb[1])) + 128) / 2);
260                 r_rgb[2] = (unsigned char)((((int)(rgb[2])) + 128) / 2);
261                 r_rgb[3] = rgb[3];
262         }
263         else {
264                 *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
265         }
266 }
267
268 static void mask_draw_curve_type(MaskSpline *spline, float (*points)[2], int tot_point,
269                                  const short is_feather, const short is_smooth, const short is_active,
270                                  const unsigned char rgb_spline[4], const char draw_type)
271 {
272         const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP;
273         const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
274 //      const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff};
275         unsigned char rgb_tmp[4];
276
277         glEnableClientState(GL_VERTEX_ARRAY);
278         glVertexPointer(2, GL_FLOAT, 0, points);
279
280         switch (draw_type) {
281
282                 case MASK_DT_OUTLINE:
283                         glLineWidth(3);
284
285                         mask_color_active_tint(rgb_tmp, rgb_black, is_active);
286                         glColor4ubv(rgb_tmp);
287
288                         glDrawArrays(draw_method, 0, tot_point);
289
290                         glLineWidth(1);
291                         mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
292                         glColor4ubv(rgb_tmp);
293                         glDrawArrays(draw_method, 0, tot_point);
294
295                         break;
296
297                 case MASK_DT_DASH:
298                 default:
299                         glEnable(GL_LINE_STIPPLE);
300
301 #ifdef USE_XOR
302                         glEnable(GL_COLOR_LOGIC_OP);
303                         glLogicOp(GL_OR);
304 #endif
305                         mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
306                         glColor4ubv(rgb_tmp);
307                         glLineStipple(3, 0xaaaa);
308                         glEnableClientState(GL_VERTEX_ARRAY);
309                         glVertexPointer(2, GL_FLOAT, 0, points);
310                         glDrawArrays(draw_method, 0, tot_point);
311
312 #ifdef USE_XOR
313                         glDisable(GL_COLOR_LOGIC_OP);
314 #endif
315                         mask_color_active_tint(rgb_tmp, rgb_black, is_active);
316                         glColor4ubv(rgb_tmp);
317                         glLineStipple(3, 0x5555);
318                         glDrawArrays(draw_method, 0, tot_point);
319
320                         glDisable(GL_LINE_STIPPLE);
321                         break;
322
323
324                 case MASK_DT_BLACK:
325                 case MASK_DT_WHITE:
326                         if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0;   }
327                         else                            { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
328                         /* alpha values seem too low but gl draws many points that compensate for it */
329                         if (is_feather) { rgb_tmp[3] = 64; }
330                         else            { rgb_tmp[3] = 128; }
331
332                         if (is_feather) {
333                                 rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
334                                 rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
335                                 rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
336                         }
337
338                         if (is_smooth == FALSE && is_feather) {
339                                 glEnable(GL_BLEND);
340                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
341                         }
342
343                         mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
344                         glColor4ubv(rgb_tmp);
345
346                         glEnableClientState(GL_VERTEX_ARRAY);
347                         glVertexPointer(2, GL_FLOAT, 0, points);
348                         glDrawArrays(draw_method, 0, tot_point);
349
350                         glDrawArrays(draw_method, 0, tot_point);
351
352                         if (is_smooth == FALSE && is_feather) {
353                                 glDisable(GL_BLEND);
354                         }
355
356                         break;
357         }
358
359         glDisableClientState(GL_VERTEX_ARRAY);
360
361 }
362
363 static void draw_spline_curve(MaskLayer *masklay, MaskSpline *spline,
364                               const char draw_flag, const char draw_type,
365                               const short is_active,
366                               int width, int height)
367 {
368         unsigned char rgb_tmp[4];
369
370         const short is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
371         const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH);
372         const short is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
373
374         int tot_diff_point;
375         float (*diff_points)[2];
376
377         int tot_feather_point;
378         float (*feather_points)[2];
379
380         diff_points = BKE_mask_spline_differentiate_with_resolution(spline, width, height, &tot_diff_point);
381
382         if (!diff_points)
383                 return;
384
385         if (is_smooth) {
386                 glEnable(GL_LINE_SMOOTH);
387                 glEnable(GL_BLEND);
388                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
389         }
390
391         feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution(spline, width, height, &tot_feather_point, (is_fill != FALSE));
392
393         /* draw feather */
394         mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
395         mask_draw_curve_type(spline, feather_points, tot_feather_point,
396                              TRUE, is_smooth, is_active,
397                              rgb_tmp, draw_type);
398
399         if (!is_fill) {
400
401                 float *fp         = &diff_points[0][0];
402                 float *fp_feather = &feather_points[0][0];
403                 float tvec[2];
404                 int i;
405
406                 BLI_assert(tot_diff_point == tot_feather_point);
407
408                 for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
409                         sub_v2_v2v2(tvec, fp, fp_feather);
410                         add_v2_v2v2(fp_feather, fp, tvec);
411                 }
412
413                 /* same as above */
414                 mask_draw_curve_type(spline, feather_points, tot_feather_point,
415                                      TRUE, is_smooth, is_active,
416                                      rgb_tmp, draw_type);
417         }
418
419         MEM_freeN(feather_points);
420
421         /* draw main curve */
422         mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
423         mask_draw_curve_type(spline, diff_points, tot_diff_point,
424                              FALSE, is_smooth, is_active,
425                              rgb_tmp, draw_type);
426         MEM_freeN(diff_points);
427
428         if (draw_flag & MASK_DRAWFLAG_SMOOTH) {
429                 glDisable(GL_LINE_SMOOTH);
430                 glDisable(GL_BLEND);
431         }
432
433         (void)draw_type;
434 }
435
436 static void draw_masklays(Mask *mask, const char draw_flag, const char draw_type,
437                           int width, int height)
438 {
439         MaskLayer *masklay;
440         int i;
441
442         for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
443                 MaskSpline *spline;
444                 const short is_active = (i == mask->masklay_act);
445
446                 if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
447                         continue;
448                 }
449
450                 for (spline = masklay->splines.first; spline; spline = spline->next) {
451
452                         /* draw curve itself first... */
453                         draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height);
454
455 //                      draw_spline_parents(masklay, spline);
456
457                         if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
458                                 /* ...and then handles over the curve so they're nicely visible */
459                                 draw_spline_points(masklay, spline, draw_flag, draw_type);
460                         }
461
462                         /* show undeform for testing */
463                         if (0) {
464                                 void *back = spline->points_deform;
465
466                                 spline->points_deform = NULL;
467                                 draw_spline_curve(masklay, spline, draw_flag, draw_type, is_active, width, height);
468 //                              draw_spline_parents(masklay, spline);
469                                 draw_spline_points(masklay, spline, draw_flag, draw_type);
470                                 spline->points_deform = back;
471                         }
472                 }
473         }
474 }
475
476 void ED_mask_draw(const bContext *C,
477                   const char draw_flag, const char draw_type)
478 {
479         ScrArea *sa = CTX_wm_area(C);
480
481         Mask *mask = CTX_data_edit_mask(C);
482         int width, height;
483
484         if (!mask)
485                 return;
486
487         ED_mask_get_size(sa, &width, &height);
488
489         draw_masklays(mask, draw_flag, draw_type, width, height);
490 }
491
492 /* sets up the opengl context.
493  * width, height are to match the values from ED_mask_get_size() */
494 void ED_mask_draw_region(Mask *mask, ARegion *ar,
495                          const char draw_flag, const char draw_type,
496                          int width, int height,
497                          const short do_scale_applied, const short do_post_draw,
498                          float stabmat[4][4], /* optional - only used by clip */
499                          const bContext *C    /* optional - only used when do_post_draw is set */
500                          )
501 {
502         struct View2D *v2d = &ar->v2d;
503
504         int x, y;
505         /* int w, h; */
506         float zoomx, zoomy;
507
508         /* frame image */
509         float maxdim;
510         float xofs, yofs;
511
512         /* find window pixel coordinates of origin */
513         UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
514
515
516         /* w = BLI_RCT_SIZE_X(&v2d->tot); */
517         /* h = BLI_RCT_SIZE_Y(&v2d->tot);/*/
518
519
520         zoomx = (float)(BLI_RCT_SIZE_X(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_X(&ar->v2d.cur));
521         zoomy = (float)(BLI_RCT_SIZE_Y(&ar->winrct) + 1) / (float)(BLI_RCT_SIZE_Y(&ar->v2d.cur));
522
523         if (do_scale_applied) {
524                 zoomx /= width;
525                 zoomy /= height;
526         }
527
528         x += v2d->tot.xmin * zoomx;
529         y += v2d->tot.ymin * zoomy;
530
531         /* frame the image */
532         maxdim = maxf(width, height);
533         if (width == height) {
534                 xofs = yofs = 0;
535         }
536         else if (width < height) {
537                 xofs = ((height - width) / -2.0f) * zoomx;
538                 yofs = 0.0f;
539         }
540         else { /* (width > height) */
541                 xofs = 0.0f;
542                 yofs = ((width - height) / -2.0f) * zoomy;
543         }
544
545         /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
546         glPushMatrix();
547         glTranslatef(x + xofs, y + yofs, 0);
548         glScalef(maxdim * zoomx, maxdim * zoomy, 0);
549
550         if (stabmat) {
551                 glMultMatrixf(stabmat);
552         }
553
554         /* draw! */
555         draw_masklays(mask, draw_flag, draw_type, width, height);
556
557         if (do_post_draw) {
558                 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
559         }
560
561         glPopMatrix();
562 }
563
564 void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
565 {
566         const float framelen = ar->winx / (float)(efra - sfra + 1);
567
568         MaskLayer *masklay = BKE_mask_layer_active(mask);
569
570         glBegin(GL_LINES);
571         glColor4ub(255, 175, 0, 255);
572
573         if (masklay) {
574                 MaskLayerShape *masklay_shape;
575
576                 for (masklay_shape = masklay->splines_shapes.first;
577                      masklay_shape;
578                      masklay_shape = masklay_shape->next)
579                 {
580                         int frame = masklay_shape->frame;
581
582                         /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
583                         int height = (frame == cfra) ? 22 : 10;
584                         int x = (frame - sfra) * framelen;
585                         glVertex2i(x, 0);
586                         glVertex2i(x, height);
587                 }
588         }
589
590         glEnd();
591 }