2 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
18 * The Original Code is Copyright (C) 2012 Blender Foundation.
19 * All rights reserved.
22 * Contributor(s): Blender Foundation,
26 * ***** END GPL LICENSE BLOCK *****
29 /** \file blender/editors/mask/mask_draw.c
33 #include "MEM_guardedalloc.h"
35 #include "BLI_utildefines.h"
39 #include "BKE_context.h"
42 #include "DNA_mask_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_object_types.h" /* SELECT */
45 #include "DNA_space_types.h"
48 #include "ED_mask.h" /* own include */
49 #include "ED_space_api.h"
52 #include "UI_resources.h"
53 #include "UI_view2d.h"
55 #include "mask_intern.h" /* own include */
57 static void mask_spline_color_get(MaskLayer *masklay, MaskSpline *spline, const int is_sel,
58 unsigned char r_rgb[4])
61 if (masklay->act_spline == spline) {
62 r_rgb[0] = r_rgb[1] = r_rgb[2] = 255;
66 r_rgb[1] = r_rgb[2] = 0;
71 r_rgb[1] = r_rgb[2] = 0;
77 static void mask_spline_feather_color_get(MaskLayer *UNUSED(masklay), MaskSpline *UNUSED(spline), const int is_sel,
78 unsigned char r_rgb[4])
82 r_rgb[0] = r_rgb[2] = 0;
86 r_rgb[0] = r_rgb[2] = 0;
93 static void draw_spline_parents(MaskLayer *UNUSED(masklay), MaskSpline *spline)
96 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
98 if (!spline->tot_point)
102 glEnable(GL_LINE_STIPPLE);
103 glLineStipple(1, 0xAAAA);
107 for (i = 0; i < spline->tot_point; i++) {
108 MaskSplinePoint *point = &points_array[i];
109 BezTriple *bezt = &point->bezt;
111 if (point->parent.id) {
112 glVertex2f(bezt->vec[1][0],
115 glVertex2f(bezt->vec[1][0] - point->parent.offset[0],
116 bezt->vec[1][1] - point->parent.offset[1]);
122 glDisable(GL_LINE_STIPPLE);
126 static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], float co[2])
128 BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
129 ED_clip_point_undistorted_pos(sc, r_co, r_co);
130 BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
133 /* return non-zero if spline is selected */
134 static void draw_spline_points(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
135 const char UNUSED(draw_flag), const char draw_type)
137 const int is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
138 unsigned char rgb_spline[4];
139 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
140 SpaceClip *sc = CTX_wm_space_clip(C);
141 int undistort = FALSE;
143 int i, hsize, tot_feather_point;
144 float (*feather_points)[2], (*fp)[2];
146 if (!spline->tot_point)
150 undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
152 /* TODO, add this to sequence editor */
153 hsize = 4; /* UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); */
157 mask_spline_color_get(masklay, spline, is_spline_sel, rgb_spline);
160 feather_points = fp = BKE_mask_spline_feather_points(spline, &tot_feather_point);
161 for (i = 0; i < spline->tot_point; i++) {
163 /* watch it! this is intentionally not the deform array, only check for sel */
164 MaskSplinePoint *point = &spline->points[i];
168 for (j = 0; j < point->tot_uw + 1; j++) {
169 float feather_point[2];
172 copy_v2_v2(feather_point, *fp);
175 mask_point_undistort_pos(sc, feather_point, feather_point);
178 sel = MASKPOINT_ISSEL_ANY(point);
181 sel = point->uw[j - 1].flag & SELECT;
185 if (point == masklay->act_point)
186 glColor3f(1.0f, 1.0f, 1.0f);
188 glColor3f(1.0f, 1.0f, 0.0f);
191 glColor3f(0.5f, 0.5f, 0.0f);
195 glVertex2fv(feather_point);
201 MEM_freeN(feather_points);
204 for (i = 0; i < spline->tot_point; i++) {
206 /* watch it! this is intentionally not the deform array, only check for sel */
207 MaskSplinePoint *point = &spline->points[i];
208 MaskSplinePoint *point_deform = &points_array[i];
209 BezTriple *bezt = &point_deform->bezt;
213 int has_handle = BKE_mask_point_has_handle(point);
215 copy_v2_v2(vert, bezt->vec[1]);
216 BKE_mask_point_handle(point_deform, handle);
219 mask_point_undistort_pos(sc, vert, vert);
220 mask_point_undistort_pos(sc, handle, handle);
223 /* draw handle segment */
226 /* this could be split into its own loop */
227 if (draw_type == MASK_DT_OUTLINE) {
228 const unsigned char rgb_gray[4] = {0x60, 0x60, 0x60, 0xff};
230 glColor4ubv(rgb_gray);
238 glColor3ubv(rgb_spline);
246 if (MASKPOINT_ISSEL_KNOT(point)) {
247 if (point == masklay->act_point)
248 glColor3f(1.0f, 1.0f, 1.0f);
250 glColor3f(1.0f, 1.0f, 0.0f);
253 glColor3f(0.5f, 0.5f, 0.0f);
259 /* draw handle points */
261 if (MASKPOINT_ISSEL_HANDLE(point)) {
262 if (point == masklay->act_point)
263 glColor3f(1.0f, 1.0f, 1.0f);
265 glColor3f(1.0f, 1.0f, 0.0f);
268 glColor3f(0.5f, 0.5f, 0.0f);
280 /* #define USE_XOR */
282 static void mask_color_active_tint(unsigned char r_rgb[4], const unsigned char rgb[4], const short is_active)
285 r_rgb[0] = (unsigned char)((((int)(rgb[0])) + 128) / 2);
286 r_rgb[1] = (unsigned char)((((int)(rgb[1])) + 128) / 2);
287 r_rgb[2] = (unsigned char)((((int)(rgb[2])) + 128) / 2);
291 *(unsigned int *)r_rgb = *(const unsigned int *)rgb;
295 static void mask_draw_curve_type(const bContext *C, MaskSpline *spline, float (*orig_points)[2], int tot_point,
296 const short is_feather, const short is_smooth, const short is_active,
297 const unsigned char rgb_spline[4], const char draw_type)
299 const int draw_method = (spline->flag & MASK_SPLINE_CYCLIC) ? GL_LINE_LOOP : GL_LINE_STRIP;
300 const unsigned char rgb_black[4] = {0x00, 0x00, 0x00, 0xff};
301 // const unsigned char rgb_white[4] = {0xff, 0xff, 0xff, 0xff};
302 unsigned char rgb_tmp[4];
303 SpaceClip *sc = CTX_wm_space_clip(C);
304 float (*points)[2] = orig_points;
307 int undistort = sc->clip && sc->user.render_flag & MCLIP_PROXY_RENDER_UNDISTORT;
312 points = MEM_callocN(2 * tot_point * sizeof(float), "undistorthed mask curve");
314 for (i = 0; i < tot_point; i++) {
315 mask_point_undistort_pos(sc, points[i], orig_points[i]);
320 glEnableClientState(GL_VERTEX_ARRAY);
321 glVertexPointer(2, GL_FLOAT, 0, points);
325 case MASK_DT_OUTLINE:
328 mask_color_active_tint(rgb_tmp, rgb_black, is_active);
329 glColor4ubv(rgb_tmp);
331 glDrawArrays(draw_method, 0, tot_point);
334 mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
335 glColor4ubv(rgb_tmp);
336 glDrawArrays(draw_method, 0, tot_point);
342 glEnable(GL_LINE_STIPPLE);
345 glEnable(GL_COLOR_LOGIC_OP);
348 mask_color_active_tint(rgb_tmp, rgb_spline, is_active);
349 glColor4ubv(rgb_tmp);
350 glLineStipple(3, 0xaaaa);
351 glEnableClientState(GL_VERTEX_ARRAY);
352 glVertexPointer(2, GL_FLOAT, 0, points);
353 glDrawArrays(draw_method, 0, tot_point);
356 glDisable(GL_COLOR_LOGIC_OP);
358 mask_color_active_tint(rgb_tmp, rgb_black, is_active);
359 glColor4ubv(rgb_tmp);
360 glLineStipple(3, 0x5555);
361 glDrawArrays(draw_method, 0, tot_point);
363 glDisable(GL_LINE_STIPPLE);
369 if (draw_type == MASK_DT_BLACK) { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 0; }
370 else { rgb_tmp[0] = rgb_tmp[1] = rgb_tmp[2] = 255; }
371 /* alpha values seem too low but gl draws many points that compensate for it */
372 if (is_feather) { rgb_tmp[3] = 64; }
373 else { rgb_tmp[3] = 128; }
376 rgb_tmp[0] = (unsigned char)(((short)rgb_tmp[0] + (short)rgb_spline[0]) / 2);
377 rgb_tmp[1] = (unsigned char)(((short)rgb_tmp[1] + (short)rgb_spline[1]) / 2);
378 rgb_tmp[2] = (unsigned char)(((short)rgb_tmp[2] + (short)rgb_spline[2]) / 2);
381 if (is_smooth == FALSE && is_feather) {
383 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
386 mask_color_active_tint(rgb_tmp, rgb_tmp, is_active);
387 glColor4ubv(rgb_tmp);
389 glEnableClientState(GL_VERTEX_ARRAY);
390 glVertexPointer(2, GL_FLOAT, 0, points);
391 glDrawArrays(draw_method, 0, tot_point);
393 if (is_smooth == FALSE && is_feather) {
400 glDisableClientState(GL_VERTEX_ARRAY);
402 if (points != orig_points)
406 static void draw_spline_curve(const bContext *C, MaskLayer *masklay, MaskSpline *spline,
407 const char draw_flag, const char draw_type,
408 const short is_active,
409 int width, int height)
411 const unsigned int resol = max_ii(BKE_mask_spline_feather_resolution(spline, width, height),
412 BKE_mask_spline_resolution(spline, width, height));
414 unsigned char rgb_tmp[4];
416 const short is_spline_sel = (spline->flag & SELECT) && (masklay->restrictflag & MASK_RESTRICT_SELECT) == 0;
417 const short is_smooth = (draw_flag & MASK_DRAWFLAG_SMOOTH);
418 const short is_fill = (spline->flag & MASK_SPLINE_NOFILL) == 0;
421 float (*diff_points)[2];
423 int tot_feather_point;
424 float (*feather_points)[2];
426 diff_points = BKE_mask_spline_differentiate_with_resolution_ex(spline, &tot_diff_point, resol);
432 glEnable(GL_LINE_SMOOTH);
434 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
437 feather_points = BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, &tot_feather_point, resol, (is_fill != FALSE));
440 mask_spline_feather_color_get(masklay, spline, is_spline_sel, rgb_tmp);
441 mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
442 TRUE, is_smooth, is_active,
447 float *fp = &diff_points[0][0];
448 float *fp_feather = &feather_points[0][0];
452 BLI_assert(tot_diff_point == tot_feather_point);
454 for (i = 0; i < tot_diff_point; i++, fp += 2, fp_feather += 2) {
455 sub_v2_v2v2(tvec, fp, fp_feather);
456 add_v2_v2v2(fp_feather, fp, tvec);
460 mask_draw_curve_type(C, spline, feather_points, tot_feather_point,
461 TRUE, is_smooth, is_active,
465 MEM_freeN(feather_points);
467 /* draw main curve */
468 mask_spline_color_get(masklay, spline, is_spline_sel, rgb_tmp);
469 mask_draw_curve_type(C, spline, diff_points, tot_diff_point,
470 FALSE, is_smooth, is_active,
472 MEM_freeN(diff_points);
474 if (draw_flag & MASK_DRAWFLAG_SMOOTH) {
475 glDisable(GL_LINE_SMOOTH);
482 static void draw_masklays(const bContext *C, Mask *mask, const char draw_flag, const char draw_type,
483 int width, int height)
488 for (masklay = mask->masklayers.first, i = 0; masklay; masklay = masklay->next, i++) {
490 const short is_active = (i == mask->masklay_act);
492 if (masklay->restrictflag & MASK_RESTRICT_VIEW) {
496 for (spline = masklay->splines.first; spline; spline = spline->next) {
498 /* draw curve itself first... */
499 draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
501 // draw_spline_parents(masklay, spline);
503 if (!(masklay->restrictflag & MASK_RESTRICT_SELECT)) {
504 /* ...and then handles over the curve so they're nicely visible */
505 draw_spline_points(C, masklay, spline, draw_flag, draw_type);
508 /* show undeform for testing */
510 void *back = spline->points_deform;
512 spline->points_deform = NULL;
513 draw_spline_curve(C, masklay, spline, draw_flag, draw_type, is_active, width, height);
514 // draw_spline_parents(masklay, spline);
515 draw_spline_points(C, masklay, spline, draw_flag, draw_type);
516 spline->points_deform = back;
522 void ED_mask_draw(const bContext *C,
523 const char draw_flag, const char draw_type)
525 ScrArea *sa = CTX_wm_area(C);
527 Mask *mask = CTX_data_edit_mask(C);
533 ED_mask_get_size(sa, &width, &height);
535 draw_masklays(C, mask, draw_flag, draw_type, width, height);
538 /* sets up the opengl context.
539 * width, height are to match the values from ED_mask_get_size() */
540 void ED_mask_draw_region(Mask *mask, ARegion *ar,
541 const char draw_flag, const char draw_type,
542 const int width_i, const int height_i, /* convert directly into aspect corrected vars */
543 const float aspx, const float aspy,
544 const short do_scale_applied, const short do_post_draw,
545 float stabmat[4][4], /* optional - only used by clip */
546 const bContext *C /* optional - only used when do_post_draw is set or called from clip editor */
549 struct View2D *v2d = &ar->v2d;
551 /* aspect always scales vertically in movie and image spaces */
552 const float width = width_i, height = (float)height_i * (aspy / aspx);
562 /* find window pixel coordinates of origin */
563 UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y);
566 /* w = BLI_rctf_size_x(&v2d->tot); */
567 /* h = BLI_rctf_size_y(&v2d->tot);/*/
570 zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / BLI_rctf_size_x(&ar->v2d.cur);
571 zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / BLI_rctf_size_y(&ar->v2d.cur);
573 if (do_scale_applied) {
578 x += v2d->tot.xmin * zoomx;
579 y += v2d->tot.ymin * zoomy;
581 /* frame the image */
582 maxdim = max_ff(width, height);
583 if (width == height) {
586 else if (width < height) {
587 xofs = ((height - width) / -2.0f) * zoomx;
590 else { /* (width > height) */
592 yofs = ((width - height) / -2.0f) * zoomy;
595 /* apply transformation so mask editing tools will assume drawing from the origin in normalized space */
597 glTranslatef(x + xofs, y + yofs, 0);
598 glScalef(maxdim * zoomx, maxdim * zoomy, 0);
601 glMultMatrixf(stabmat);
605 draw_masklays(C, mask, draw_flag, draw_type, width, height);
608 ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW);
614 void ED_mask_draw_frames(Mask *mask, ARegion *ar, const int cfra, const int sfra, const int efra)
616 const float framelen = ar->winx / (float)(efra - sfra + 1);
618 MaskLayer *masklay = BKE_mask_layer_active(mask);
621 glColor4ub(255, 175, 0, 255);
624 MaskLayerShape *masklay_shape;
626 for (masklay_shape = masklay->splines_shapes.first;
628 masklay_shape = masklay_shape->next)
630 int frame = masklay_shape->frame;
632 /* draw_keyframe(i, CFRA, sfra, framelen, 1); */
633 int height = (frame == cfra) ? 22 : 10;
634 int x = (frame - sfra) * framelen;
636 glVertex2i(x, height);