Blender V5.0
mask_ops.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_listbase.h"
14#include "BLI_math_matrix.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_context.hh"
18#include "BKE_mask.h"
19
20#include "BLT_translation.hh"
21
22#include "DEG_depsgraph.hh"
24
25#include "DNA_mask_types.h"
26#include "DNA_object_types.h" /* SELECT */
27#include "DNA_scene_types.h"
28
29#include "WM_api.hh"
30#include "WM_types.hh"
31
32#include "ED_clip.hh"
33#include "ED_image.hh"
34#include "ED_mask.hh"
35#include "ED_select_utils.hh"
36
37#include "ANIM_keyframing.hh"
38
39#include "UI_interface_icons.hh"
40
41#include "RNA_access.hh"
42#include "RNA_define.hh"
43
44#include "mask_intern.hh" /* own include */
45
46/******************** create new mask *********************/
47
49{
50 ScrArea *area = CTX_wm_area(C);
51 Main *bmain = CTX_data_main(C);
52 Mask *mask;
53
54 mask = BKE_mask_new(bmain, name);
55
56 if (area && area->spacedata.first) {
57 switch (area->spacetype) {
58 case SPACE_CLIP: {
59 SpaceClip *sc = static_cast<SpaceClip *>(area->spacedata.first);
61 break;
62 }
63 case SPACE_SEQ: {
64 /* do nothing */
65 break;
66 }
67 case SPACE_IMAGE: {
68 SpaceImage *sima = static_cast<SpaceImage *>(area->spacedata.first);
70 break;
71 }
72 }
73 }
74
75 return mask;
76}
77
79{
81 MaskLayer *mask_layer;
82
83 if (mask == nullptr) {
84 /* If there's no active mask, create one. */
85 mask = ED_mask_new(C, nullptr);
86 *r_added_mask = true;
87 }
88
89 mask_layer = BKE_mask_layer_active(mask);
90 if (mask_layer == nullptr) {
91 /* If there's no active mask layer, create one. */
92 mask_layer = BKE_mask_layer_new(mask, "");
93 }
94
95 return mask_layer;
96}
97
99{
100 char name[MAX_ID_NAME - 2];
101
102 RNA_string_get(op->ptr, "name", name);
103
105
107
108 return OPERATOR_FINISHED;
109}
110
112{
113 /* identifiers */
114 ot->name = "New Mask";
115 ot->description = "Create new mask";
116 ot->idname = "MASK_OT_new";
117
118 /* flags */
120
121 /* API callbacks. */
122 ot->exec = mask_new_exec;
123 ot->poll = ED_maskedit_poll;
124
125 /* properties */
126 RNA_def_string(ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Name of new mask");
127}
128
129/******************** create new mask layer *********************/
130
132{
134 char name[MAX_ID_NAME - 2];
135
136 RNA_string_get(op->ptr, "name", name);
137
139 mask->masklay_act = mask->masklay_tot - 1;
140
143
144 return OPERATOR_FINISHED;
145}
146
148{
149 /* identifiers */
150 ot->name = "Add Mask Layer";
151 ot->description = "Add new mask layer for masking";
152 ot->idname = "MASK_OT_layer_new";
153
154 /* API callbacks. */
155 ot->exec = mask_layer_new_exec;
157
158 /* flags */
160
161 /* properties */
162 RNA_def_string(ot->srna, "name", nullptr, MAX_ID_NAME - 2, "Name", "Name of new mask layer");
163}
164
165/******************** remove mask layer *********************/
166
168{
170 MaskLayer *mask_layer = BKE_mask_layer_active(mask);
171
172 if (mask_layer) {
173 BKE_mask_layer_remove(mask, mask_layer);
174
177 }
178
179 return OPERATOR_FINISHED;
180}
181
183{
184 /* identifiers */
185 ot->name = "Remove Mask Layer";
186 ot->description = "Remove mask layer";
187 ot->idname = "MASK_OT_layer_remove";
188
189 /* API callbacks. */
192
193 /* flags */
195}
196
197/******************** slide *********************/
198
199enum {
205};
206
208 /* Generic fields. */
218
220
221 /* Previous clip coordinate which was resolved from mouse position (0, 0).
222 * Is used to compensate for view offset moving in-between of mouse events when
223 * lock-to-selection is enabled. */
225
226 float no[2];
227
229
231
232 /* Data needed to restore the state. */
233 float vec[3][3];
235
236 /* Point sliding. */
237
238 /* Handle sliding. */
240
241 /* Feather sliding. */
244};
245
246static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
247{
248 BKE_mask_coord_to_movieclip(sc->clip, &sc->user, r_co, co);
249 ED_clip_point_undistorted_pos(sc, r_co, r_co);
250 BKE_mask_coord_from_movieclip(sc->clip, &sc->user, r_co, r_co);
251}
252
254 Mask *mask_orig,
255 const float co[2],
256 MaskLayer **r_mask_layer,
257 MaskSpline **r_mask_spline)
258{
259 const float threshold = 19.0f;
260 ScrArea *area = CTX_wm_area(C);
262 float closest_dist_squared = 0.0f;
263 MaskLayer *closest_layer = nullptr;
264 MaskSpline *closest_spline = nullptr;
265 bool undistort = false;
266 *r_mask_layer = nullptr;
267 *r_mask_spline = nullptr;
268
270 Mask *mask_eval = DEG_get_evaluated(depsgraph, mask_orig);
271
272 int width, height;
273 ED_mask_get_size(area, &width, &height);
274 float pixel_co[2];
275 pixel_co[0] = co[0] * width;
276 pixel_co[1] = co[1] * height;
277 if (sc != nullptr) {
278 undistort = (sc->clip != nullptr) &&
280 }
281
282 for (MaskLayer *mask_layer_orig = static_cast<MaskLayer *>(mask_orig->masklayers.first),
283 *mask_layer_eval = static_cast<MaskLayer *>(mask_eval->masklayers.first);
284 mask_layer_orig != nullptr;
285 mask_layer_orig = mask_layer_orig->next, mask_layer_eval = mask_layer_eval->next)
286 {
287 if (mask_layer_orig->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
288 continue;
289 }
290 for (MaskSpline *spline_orig = static_cast<MaskSpline *>(mask_layer_orig->splines.first),
291 *spline_eval = static_cast<MaskSpline *>(mask_layer_eval->splines.first);
292 spline_orig != nullptr;
293 spline_orig = spline_orig->next, spline_eval = spline_eval->next)
294 {
295 if ((spline_orig->flag & SELECT) == 0) {
296 continue;
297 }
298 MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline_eval);
299 float min[2], max[2], center[2];
301 for (int i = 0; i < spline_orig->tot_point; i++) {
302 MaskSplinePoint *point_deform = &points_array[i];
303 BezTriple *bezt = &point_deform->bezt;
304
305 float vert[2];
306
307 copy_v2_v2(vert, bezt->vec[1]);
308
309 if (undistort) {
310 mask_point_undistort_pos(sc, vert, vert);
311 }
312
313 minmax_v2v2_v2(min, max, vert);
314 }
315
316 center[0] = (min[0] + max[0]) / 2.0f * width;
317 center[1] = (min[1] + max[1]) / 2.0f * height;
318 float dist_squared = len_squared_v2v2(pixel_co, center);
319 float max_bb_side = min_ff((max[0] - min[0]) * width, (max[1] - min[1]) * height);
320 if (dist_squared <= max_bb_side * max_bb_side * 0.5f &&
321 (closest_spline == nullptr || dist_squared < closest_dist_squared))
322 {
323 closest_layer = mask_layer_orig;
324 closest_spline = spline_orig;
325 closest_dist_squared = dist_squared;
326 }
327 }
328 }
329 if (closest_dist_squared < square_f(threshold) && closest_spline != nullptr) {
330 float diff_score;
332 mask_orig,
333 co,
334 threshold,
335 false,
336 nullptr,
337 true,
338 false,
339 nullptr,
340 nullptr,
341 nullptr,
342 nullptr,
343 &diff_score))
344 {
345 if (square_f(diff_score) < closest_dist_squared) {
346 return false;
347 }
348 }
349
350 *r_mask_layer = closest_layer;
351 *r_mask_spline = closest_spline;
352 return true;
353 }
354 return false;
355}
356
358{
359 for (int i = 0; i < spline->tot_point; i++) {
360 MaskSplinePoint *point = &spline->points[i];
361
362 if (point->bezt.weight != 0.0f) {
363 return false;
364 }
365 }
366
367 return true;
368}
369
371 MaskLayer *mask_layer,
372 MaskSpline *spline,
373 MaskSplinePoint *point,
374 eMaskWhichHandle which_handle)
375{
377
378 switch (which_handle) {
380 BKE_mask_point_select_set(point, true);
381 break;
383 point->bezt.f1 |= SELECT;
384 break;
386 point->bezt.f3 |= SELECT;
387 break;
389 point->bezt.f1 |= SELECT;
390 point->bezt.f3 |= SELECT;
391 break;
392 default:
393 BLI_assert_msg(0, "Unexpected situation in select_sliding_point()");
394 }
395
396 mask_layer->act_spline = spline;
397 mask_layer->act_point = point;
399}
400
402{
403 BezTriple *bezt = &point->bezt;
404
405 if (which_handle == MASK_WHICH_HANDLE_LEFT) {
406 if (bezt->h1 == HD_VECT) {
407 bezt->h1 = HD_FREE;
408 }
409 else if (bezt->h1 == HD_AUTO) {
410 bezt->h1 = HD_ALIGN_DOUBLESIDE;
411 bezt->h2 = HD_ALIGN_DOUBLESIDE;
412 }
413 }
414 else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
415 if (bezt->h2 == HD_VECT) {
416 bezt->h2 = HD_FREE;
417 }
418 else if (bezt->h2 == HD_AUTO) {
419 bezt->h1 = HD_ALIGN_DOUBLESIDE;
420 bezt->h2 = HD_ALIGN_DOUBLESIDE;
421 }
422 }
423}
424
426{
427 ScrArea *area = CTX_wm_area(C);
428 ARegion *region = CTX_wm_region(C);
429
431 SlidePointData *customdata = nullptr;
432 MaskLayer *mask_layer, *cv_mask_layer, *feather_mask_layer;
433 MaskSpline *spline, *cv_spline, *feather_spline;
434 MaskSplinePoint *point, *cv_point, *feather_point;
435 MaskSplinePointUW *uw = nullptr;
436 int width, height, action = SLIDE_ACTION_NONE;
437 const bool slide_feather = RNA_boolean_get(op->ptr, "slide_feather");
438 float co[2], cv_score, feather_score;
439 const float threshold = 19;
440 eMaskWhichHandle which_handle;
441
442 MaskViewLockState lock_state;
443 ED_mask_view_lock_state_store(C, &lock_state);
444
445 ED_mask_mouse_pos(area, region, event->mval, co);
446 ED_mask_get_size(area, &width, &height);
447
449 C, mask, co, threshold, &cv_mask_layer, &cv_spline, &which_handle, &cv_score);
450
452 mask,
453 co,
454 threshold,
455 &feather_mask_layer,
456 &feather_spline,
457 &feather_point,
458 &uw,
459 &feather_score))
460 {
461 if (slide_feather || !cv_point || feather_score < cv_score) {
462 action = SLIDE_ACTION_FEATHER;
463
464 mask_layer = feather_mask_layer;
465 spline = feather_spline;
466 point = feather_point;
467 }
468 }
469
470 if (cv_point && action == SLIDE_ACTION_NONE) {
471 if (which_handle != MASK_WHICH_HANDLE_NONE) {
472 action = SLIDE_ACTION_HANDLE;
473 }
474 else {
475 action = SLIDE_ACTION_POINT;
476 }
477
478 mask_layer = cv_mask_layer;
479 spline = cv_spline;
480 point = cv_point;
481 }
482
483 if (action == SLIDE_ACTION_NONE) {
484 if (spline_under_mouse_get(C, mask, co, &mask_layer, &spline)) {
485 action = SLIDE_ACTION_SPLINE;
486 point = nullptr;
487 }
488 }
489
490 if (action != SLIDE_ACTION_NONE) {
491 customdata = MEM_callocN<SlidePointData>("mask slide point data");
492 customdata->event_invoke_type = event->type;
493 customdata->mask = mask;
494 customdata->mask_layer = mask_layer;
495 customdata->spline = spline;
496 customdata->point = point;
497 customdata->width = width;
498 customdata->height = height;
499 customdata->action = action;
500 customdata->uw = uw;
501
502 customdata->is_sliding_new_point = RNA_boolean_get(op->ptr, "is_new_point");
503
504 if (customdata->action != SLIDE_ACTION_SPLINE) {
505 customdata->old_h1 = point->bezt.h1;
506 customdata->old_h2 = point->bezt.h2;
507 select_sliding_point(mask, mask_layer, spline, point, which_handle);
508 check_sliding_handle_type(point, which_handle);
509 }
510
511 if (uw) {
512 float co_uw[2];
513 float weight_scalar = BKE_mask_point_weight_scalar(spline, point, uw->u);
514
515 customdata->weight = uw->w;
516 customdata->weight_scalar = weight_scalar;
517 BKE_mask_point_segment_co(spline, point, uw->u, co_uw);
518 BKE_mask_point_normal(spline, point, uw->u, customdata->no);
519
520 madd_v2_v2v2fl(customdata->prev_feather_coord, co_uw, customdata->no, uw->w * weight_scalar);
521 }
522 else if (customdata->action != SLIDE_ACTION_SPLINE) {
523 BezTriple *bezt = &point->bezt;
524
525 customdata->weight = bezt->weight;
526 customdata->weight_scalar = 1.0f;
527 BKE_mask_point_normal(spline, point, 0.0f, customdata->no);
528
529 madd_v2_v2v2fl(customdata->prev_feather_coord, bezt->vec[1], customdata->no, bezt->weight);
530 }
531
532 if (customdata->action == SLIDE_ACTION_FEATHER) {
534 }
535
536 if (customdata->action != SLIDE_ACTION_SPLINE) {
537 copy_m3_m3(customdata->vec, point->bezt.vec);
538 if (which_handle != MASK_WHICH_HANDLE_NONE) {
539 BKE_mask_point_handle(point, which_handle, customdata->orig_handle_coord);
540 copy_v2_v2(customdata->prev_handle_coord, customdata->orig_handle_coord);
541 }
542 }
543 customdata->which_handle = which_handle;
544
545 {
547 DEG_id_tag_update(&mask->id, 0);
548
550 }
551
552 ED_mask_mouse_pos(area, region, event->mval, customdata->prev_mouse_coord);
553
554 const int zero_mouse[2] = {0, 0};
555 ED_mask_mouse_pos(area, region, zero_mouse, customdata->prev_zero_coord);
556 }
557
558 return customdata;
559}
560
562{
564 SlidePointData *slidedata;
565
566 if (mask == nullptr) {
568 }
569
570 slidedata = slide_point_customdata(C, op, event);
571
572 if (slidedata) {
573 op->customdata = slidedata;
574
576
577 slidedata->mask_layer->act_spline = slidedata->spline;
578 slidedata->mask_layer->act_point = slidedata->point;
579
581
583 }
584
586}
587
589{
590 for (int i = 0; i < data->spline->tot_point; i++) {
591 MaskSplinePoint *point = &data->spline->points[i];
592 MaskSplinePoint *orig_point = &data->orig_spline->points[i];
593
594 point->bezt.weight = orig_point->bezt.weight + delta;
595 point->bezt.weight = std::max(point->bezt.weight, 0.0f);
596 }
597}
598
600{
601 for (int i = 0; i < data->spline->tot_point; i++) {
602 MaskSplinePoint *point = &data->spline->points[i];
603 MaskSplinePoint *orig_point = &data->orig_spline->points[i];
604
605 point->bezt = orig_point->bezt;
606
607 for (int j = 0; j < point->tot_uw; j++) {
608 point->uw[j] = orig_point->uw[j];
609 }
610 }
611}
612
614{
615 /* cancel sliding */
616
617 if (data->orig_spline) {
619 }
620 else {
621 if (data->action == SLIDE_ACTION_FEATHER) {
622 if (data->uw) {
623 data->uw->w = data->weight;
624 }
625 else {
626 data->point->bezt.weight = data->weight;
627 }
628 }
629 else if (data->action != SLIDE_ACTION_SPLINE) {
630 copy_m3_m3(data->point->bezt.vec, data->vec);
631 data->point->bezt.h1 = data->old_h1;
632 data->point->bezt.h2 = data->old_h2;
633 }
634 }
635}
636
638{
639 if (data->orig_spline) {
640 BKE_mask_spline_free(data->orig_spline);
641 }
642
644}
645
647{
649 BezTriple *bezt = &data->point->bezt;
650 float co[2];
651
652 switch (event->type) {
653 case EVT_LEFTALTKEY:
654 case EVT_RIGHTALTKEY:
655 case EVT_LEFTSHIFTKEY:
657 if (ELEM(event->type, EVT_LEFTALTKEY, EVT_RIGHTALTKEY)) {
658 if (data->action == SLIDE_ACTION_FEATHER) {
659 data->is_overall_feather = (event->val == KM_PRESS);
660 }
661 else {
662 data->is_curvature_only = (event->val == KM_PRESS);
663 }
664 }
665
667 data->is_accurate = (event->val == KM_PRESS);
668 }
669
670 ATTR_FALLTHROUGH; /* update CV position */
671 case MOUSEMOVE: {
672 ScrArea *area = CTX_wm_area(C);
673 ARegion *region = CTX_wm_region(C);
674 blender::float2 delta;
675
676 ED_mask_mouse_pos(area, region, event->mval, co);
677 sub_v2_v2v2(delta, co, data->prev_mouse_coord);
678 copy_v2_v2(data->prev_mouse_coord, co);
679
680 /* Compensate for possibly moved view offset since the last event.
681 * The idea is to see how mapping of a fixed and known position did change. */
682 {
683 const int zero_mouse[2] = {0, 0};
684 float zero_coord[2];
685 ED_mask_mouse_pos(area, region, zero_mouse, zero_coord);
686
687 float zero_delta[2];
688 sub_v2_v2v2(zero_delta, zero_coord, data->prev_zero_coord);
689 sub_v2_v2(delta, zero_delta);
690
691 copy_v2_v2(data->prev_zero_coord, zero_coord);
692 }
693
694 if (data->is_accurate) {
695 mul_v2_fl(delta, 0.2f);
696 }
697
698 if (data->action == SLIDE_ACTION_HANDLE) {
699 float new_handle[2];
700
701 if (data->is_sliding_new_point && data->which_handle == MASK_WHICH_HANDLE_STICK) {
702 if (ELEM(data->point,
703 &data->spline->points[0],
704 &data->spline->points[data->spline->tot_point - 1]))
705 {
706 std::swap(delta[0], delta[1]);
707 delta[1] *= -1;
708
709 /* flip last point */
710 if (data->point != &data->spline->points[0]) {
711 delta *= -1.0f;
712 }
713 }
714 }
715
716 add_v2_v2v2(new_handle, data->prev_handle_coord, delta);
717
719 data->which_handle,
720 new_handle,
721 data->is_curvature_only,
722 data->orig_handle_coord,
723 data->vec);
724 BKE_mask_point_handle(data->point, data->which_handle, data->prev_handle_coord);
725
726 if (data->is_sliding_new_point) {
728 float vec[2];
729 short self_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 0 : 2;
730 short other_handle = (data->which_handle == MASK_WHICH_HANDLE_LEFT) ? 2 : 0;
731
732 sub_v2_v2v2(vec, bezt->vec[1], bezt->vec[self_handle]);
733 add_v2_v2v2(bezt->vec[other_handle], bezt->vec[1], vec);
734 }
735 }
736 }
737 else if (data->action == SLIDE_ACTION_POINT) {
738 add_v2_v2(bezt->vec[0], delta);
739 add_v2_v2(bezt->vec[1], delta);
740 add_v2_v2(bezt->vec[2], delta);
741 }
742 else if (data->action == SLIDE_ACTION_FEATHER) {
743 float vec[2], no[2], p[2], c[2], w, offco[2];
744 float *weight = nullptr;
745 float weight_scalar = 1.0f;
746 bool is_overall_feather = data->is_overall_feather || data->is_initial_feather;
747
748 add_v2_v2v2(offco, data->prev_feather_coord, delta);
749
750 if (data->uw) {
751 /* project on both sides and find the closest one,
752 * prevents flickering when projecting onto both sides can happen */
753 const float u_pos = BKE_mask_spline_project_co(
754 data->spline, data->point, data->uw->u, offco, MASK_PROJ_NEG);
755 const float u_neg = BKE_mask_spline_project_co(
756 data->spline, data->point, data->uw->u, offco, MASK_PROJ_POS);
757 float dist_pos = FLT_MAX;
758 float dist_neg = FLT_MAX;
759 float co_pos[2];
760 float co_neg[2];
761 float u;
762
763 if (u_pos > 0.0f && u_pos < 1.0f) {
764 BKE_mask_point_segment_co(data->spline, data->point, u_pos, co_pos);
765 dist_pos = len_squared_v2v2(offco, co_pos);
766 }
767
768 if (u_neg > 0.0f && u_neg < 1.0f) {
769 BKE_mask_point_segment_co(data->spline, data->point, u_neg, co_neg);
770 dist_neg = len_squared_v2v2(offco, co_neg);
771 }
772
773 u = dist_pos < dist_neg ? u_pos : u_neg;
774
775 if (u > 0.0f && u < 1.0f) {
776 data->uw->u = u;
777
778 data->uw = BKE_mask_point_sort_uw(data->point, data->uw);
779 weight = &data->uw->w;
780 weight_scalar = BKE_mask_point_weight_scalar(data->spline, data->point, u);
781 if (weight_scalar != 0.0f) {
782 weight_scalar = 1.0f / weight_scalar;
783 }
784
785 BKE_mask_point_normal(data->spline, data->point, data->uw->u, no);
786 BKE_mask_point_segment_co(data->spline, data->point, data->uw->u, p);
787 }
788 }
789 else {
790 weight = &bezt->weight;
791 /* weight_scalar = 1.0f; keep as is */
792 copy_v2_v2(no, data->no);
793 copy_v2_v2(p, bezt->vec[1]);
794 }
795
796 if (weight) {
797 sub_v2_v2v2(c, offco, p);
798 project_v2_v2v2_normalized(vec, c, no);
799
800 w = len_v2(vec);
801
802 if (is_overall_feather) {
803 float w_delta;
804
805 if (dot_v2v2(no, vec) <= 0.0f) {
806 w = -w;
807 }
808
809 w_delta = w - data->weight * data->weight_scalar;
810
811 if (data->orig_spline == nullptr) {
812 /* restore weight for currently sliding point, so orig_spline would be created
813 * with original weights used
814 */
815 *weight = data->weight;
816
817 data->orig_spline = BKE_mask_spline_copy(data->spline);
818 }
819
820 if (data->is_initial_feather) {
821 *weight = w * weight_scalar;
822 }
823
825 }
826 else {
827 if (dot_v2v2(no, vec) <= 0.0f) {
828 w = 0.0f;
829 }
830
831 if (data->orig_spline) {
832 /* restore possible overall feather changes */
834
835 BKE_mask_spline_free(data->orig_spline);
836 data->orig_spline = nullptr;
837 }
838
839 if (weight_scalar != 0.0f) {
840 *weight = w * weight_scalar;
841 }
842 }
843
844 copy_v2_v2(data->prev_feather_coord, offco);
845 }
846 }
847 else if (data->action == SLIDE_ACTION_SPLINE) {
848 if (data->orig_spline == nullptr) {
849 data->orig_spline = BKE_mask_spline_copy(data->spline);
850 }
851
852 for (int i = 0; i < data->spline->tot_point; i++) {
853 MaskSplinePoint *point = &data->spline->points[i];
854 add_v2_v2(point->bezt.vec[0], delta);
855 add_v2_v2(point->bezt.vec[1], delta);
856 add_v2_v2(point->bezt.vec[2], delta);
857 }
858 }
859
861 DEG_id_tag_update(&data->mask->id, 0);
862
863 break;
864 }
865
866 case LEFTMOUSE:
867 case RIGHTMOUSE:
868 if (event->type == data->event_invoke_type && event->val == KM_RELEASE) {
869 Scene *scene = CTX_data_scene(C);
870
871 /* Don't key sliding feather UW's. */
872 if ((data->action == SLIDE_ACTION_FEATHER && data->uw) == false) {
874 ED_mask_layer_shape_auto_key(data->mask_layer, scene->r.cfra);
875 }
876 }
877
878 if (data->is_sliding_new_point) {
879 if (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) < FLT_EPSILON) {
880 bezt->h1 = HD_VECT;
881 }
882 if (len_squared_v2v2(bezt->vec[2], bezt->vec[1]) < FLT_EPSILON) {
883 bezt->h2 = HD_VECT;
884 }
885 }
886
888 DEG_id_tag_update(&data->mask->id, 0);
889
890 free_slide_point_data(data); /* keep this last! */
891 return OPERATOR_FINISHED;
892 }
893 else if (event->type != data->event_invoke_type && event->val == KM_PRESS) {
894 /* pass to ESCKEY */
896 }
897 else {
898 break;
899 }
900
901 case EVT_ESCKEY:
903
905 DEG_id_tag_update(&data->mask->id, 0);
906
907 free_slide_point_data(data); /* keep this last! */
908 return OPERATOR_CANCELLED;
909 default: {
910 break;
911 }
912 }
913
915}
916
918{
919 PropertyRNA *prop;
920
921 /* identifiers */
922 ot->name = "Slide Point";
923 ot->description = "Slide control points";
924 ot->idname = "MASK_OT_slide_point";
925
926 /* API callbacks. */
927 ot->invoke = slide_point_invoke;
928 ot->modal = slide_point_modal;
930
931 /* flags */
933
934 RNA_def_boolean(ot->srna,
935 "slide_feather",
936 false,
937 "Slide Feather",
938 "First try to slide feather instead of vertex");
939
940 prop = RNA_def_boolean(
941 ot->srna, "is_new_point", false, "Slide New Point", "Newly created vertex is being slid");
943}
944
945/******************** slide spline curvature *********************/
946
965
967{
968 *slide_data->adjust_bezt = slide_data->bezt_backup;
969 *slide_data->other_bezt = slide_data->other_bezt_backup;
970}
971
973{
974 MEM_freeN(slide_data);
975}
976
978{
980 float co[2];
981 const float threshold = 19.0f;
982
984
985 if (ED_mask_point_find_nearest(C, mask, co, threshold, nullptr, nullptr, nullptr, nullptr)) {
986 return false;
987 }
988
990 C, mask, co, threshold, nullptr, nullptr, nullptr, nullptr, nullptr))
991 {
992 return false;
993 }
994
995 return true;
996}
997
999 const wmEvent *event)
1000{
1001 const float threshold = 19.0f;
1002
1004 SlideSplineCurvatureData *slide_data;
1005 MaskLayer *mask_layer;
1006 MaskSpline *spline;
1007 MaskSplinePoint *point;
1008 float u, co[2];
1009 BezTriple *next_bezt;
1010
1011 MaskViewLockState lock_state;
1012 ED_mask_view_lock_state_store(C, &lock_state);
1013
1015
1017 mask,
1018 co,
1019 threshold,
1020 false,
1021 nullptr,
1022 true,
1023 false,
1024 &mask_layer,
1025 &spline,
1026 &point,
1027 &u,
1028 nullptr))
1029 {
1030 return nullptr;
1031 }
1032
1033 next_bezt = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
1034 if (next_bezt == nullptr) {
1035 return nullptr;
1036 }
1037
1038 slide_data = MEM_callocN<SlideSplineCurvatureData>("slide curvature slide");
1039 slide_data->event_invoke_type = event->type;
1040 slide_data->mask = mask;
1041 slide_data->mask_layer = mask_layer;
1042 slide_data->spline = spline;
1043 slide_data->point = point;
1044 slide_data->u = u;
1045
1046 copy_v2_v2(slide_data->prev_mouse_coord, co);
1047 BKE_mask_point_segment_co(spline, point, u, slide_data->prev_spline_coord);
1048
1049 copy_v2_v2(slide_data->P0, point->bezt.vec[1]);
1050 copy_v2_v2(slide_data->P1, point->bezt.vec[2]);
1051 copy_v2_v2(slide_data->P2, next_bezt->vec[0]);
1052 copy_v2_v2(slide_data->P3, next_bezt->vec[1]);
1053
1054 /* Depending to which end we're closer to adjust either left or right side of the spline. */
1055 if (u <= 0.5f) {
1056 slide_data->adjust_bezt = &point->bezt;
1057 slide_data->other_bezt = next_bezt;
1058 }
1059 else {
1060 slide_data->adjust_bezt = next_bezt;
1061 slide_data->other_bezt = &point->bezt;
1062 }
1063
1064 /* Data needed for restoring state. */
1065 slide_data->bezt_backup = *slide_data->adjust_bezt;
1066 slide_data->other_bezt_backup = *slide_data->other_bezt;
1067
1068 /* Let's don't touch other side of the point for now, so set handle to FREE. */
1069 if (u < 0.5f) {
1070 if (slide_data->adjust_bezt->h2 <= HD_VECT) {
1071 slide_data->adjust_bezt->h2 = HD_FREE;
1072 }
1073 }
1074 else {
1075 if (slide_data->adjust_bezt->h1 <= HD_VECT) {
1076 slide_data->adjust_bezt->h1 = HD_FREE;
1077 }
1078 }
1079
1080 /* Change selection */
1082 slide_data->adjust_bezt->f2 |= SELECT;
1083 slide_data->other_bezt->f2 |= SELECT;
1084 if (u < 0.5f) {
1085 slide_data->adjust_bezt->f3 |= SELECT;
1086 slide_data->other_bezt->f1 |= SELECT;
1087 }
1088 else {
1089 slide_data->adjust_bezt->f1 |= SELECT;
1090 slide_data->other_bezt->f3 |= SELECT;
1091 }
1092 mask_layer->act_spline = spline;
1093 mask_layer->act_point = point;
1095
1096 DEG_id_tag_update(&mask->id, 0);
1098
1099 return slide_data;
1100}
1101
1103 wmOperator *op,
1104 const wmEvent *event)
1105{
1107 SlideSplineCurvatureData *slide_data;
1108
1109 if (mask == nullptr) {
1110 return OPERATOR_PASS_THROUGH;
1111 }
1112
1113 /* Be sure we don't conflict with point slide here. */
1114 if (!slide_spline_curvature_check(C, event)) {
1115 return OPERATOR_PASS_THROUGH;
1116 }
1117
1118 slide_data = slide_spline_curvature_customdata(C, event);
1119 if (slide_data != nullptr) {
1120 op->customdata = slide_data;
1124 }
1125
1126 return OPERATOR_PASS_THROUGH;
1127}
1128
1129static void slide_spline_solve_P1(const float u,
1130 const float B[2],
1131 const float P0[2],
1132 const float P2[2],
1133 const float P3[2],
1134 float solution[2])
1135{
1136 const float u2 = u * u, u3 = u * u * u;
1137 const float v = 1.0f - u;
1138 const float v2 = v * v, v3 = v * v * v;
1139 const float inv_divider = 1.0f / (3.0f * v2 * u);
1140 const float t = 3.0f * v * u2;
1141 solution[0] = -(v3 * P0[0] + t * P2[0] + u3 * P3[0] - B[0]) * inv_divider;
1142 solution[1] = -(v3 * P0[1] + t * P2[1] + u3 * P3[1] - B[1]) * inv_divider;
1143}
1144
1145static void slide_spline_solve_P2(const float u,
1146 const float B[2],
1147 const float P0[2],
1148 const float P1[2],
1149 const float P3[2],
1150 float solution[2])
1151{
1152 const float u2 = u * u, u3 = u * u * u;
1153 const float v = 1.0f - u;
1154 const float v2 = v * v, v3 = v * v * v;
1155 const float inv_divider = 1.0f / (3.0f * v * u2);
1156 const float t = 3.0f * v2 * u;
1157 solution[0] = -(v3 * P0[0] + t * P1[0] + u3 * P3[0] - B[0]) * inv_divider;
1158 solution[1] = -(v3 * P0[1] + t * P1[1] + u3 * P3[1] - B[1]) * inv_divider;
1159}
1160
1162 wmOperator *op,
1163 const wmEvent *event)
1164{
1165 Scene *scene = CTX_data_scene(C);
1166 const float margin = 0.2f;
1168 float u = slide_data->u;
1169
1170 switch (event->type) {
1171 case EVT_LEFTSHIFTKEY:
1172 case EVT_RIGHTSHIFTKEY:
1173 case EVT_LEFTCTRLKEY:
1174 case EVT_RIGHTCTRLKEY:
1176 slide_data->accurate = (event->val == KM_PRESS);
1177 }
1178
1179 if (ELEM(event->type, EVT_LEFTCTRLKEY, EVT_RIGHTCTRLKEY)) {
1180 if (event->val == KM_PRESS) {
1181 slide_data->adjust_bezt->h1 = slide_data->adjust_bezt->h2 = HD_FREE;
1182 if ((u > margin && u < 0.5f) || (u >= 0.5f && u < 1.0f - margin)) {
1183 slide_data->other_bezt->h1 = slide_data->other_bezt->h2 = HD_FREE;
1184 }
1185 }
1186 else if (event->val == KM_RELEASE) {
1187 slide_data->adjust_bezt->h1 = slide_data->bezt_backup.h1;
1188 slide_data->adjust_bezt->h2 = slide_data->bezt_backup.h2;
1189 slide_data->other_bezt->h1 = slide_data->other_bezt_backup.h1;
1190 slide_data->other_bezt->h2 = slide_data->other_bezt_backup.h2;
1191 }
1192
1193 if (u < 0.5f) {
1194 copy_v2_v2(slide_data->adjust_bezt->vec[0], slide_data->bezt_backup.vec[0]);
1195 copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->other_bezt_backup.vec[2]);
1196 }
1197 else {
1198 copy_v2_v2(slide_data->adjust_bezt->vec[2], slide_data->bezt_backup.vec[2]);
1199 copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->other_bezt_backup.vec[0]);
1200 }
1201 }
1202
1203 ATTR_FALLTHROUGH; /* update CV position */
1204 case MOUSEMOVE: {
1205 float B[2], mouse_coord[2], delta[2];
1206
1207 /* Get coordinate spline is expected to go through. */
1208 ED_mask_mouse_pos(CTX_wm_area(C), CTX_wm_region(C), event->mval, mouse_coord);
1209 sub_v2_v2v2(delta, mouse_coord, slide_data->prev_mouse_coord);
1210 if (slide_data->accurate) {
1211 mul_v2_fl(delta, 0.2f);
1212 }
1213 add_v2_v2v2(B, slide_data->prev_spline_coord, delta);
1214 copy_v2_v2(slide_data->prev_spline_coord, B);
1215 copy_v2_v2(slide_data->prev_mouse_coord, mouse_coord);
1216
1217 if (u < 0.5f) {
1218 float oldP2[2];
1219 bool need_restore_P2 = false;
1220
1221 if (u > margin) {
1222 float solution[2];
1223 float x = (u - margin) * 0.5f / (0.5f - margin);
1224 float weight = (3 * x * x - 2 * x * x * x);
1225
1226 slide_spline_solve_P2(u, B, slide_data->P0, slide_data->P1, slide_data->P3, solution);
1227
1228 copy_v2_v2(oldP2, slide_data->P2);
1229 interp_v2_v2v2(slide_data->P2, slide_data->P2, solution, weight);
1230 copy_v2_v2(slide_data->other_bezt->vec[0], slide_data->P2);
1231 need_restore_P2 = true;
1232
1233 /* Tweak handle type in order to be able to apply the delta. */
1234 if (weight > 0.0f) {
1235 if (slide_data->other_bezt->h1 <= HD_VECT) {
1236 slide_data->other_bezt->h1 = HD_FREE;
1237 }
1238 }
1239 }
1240
1242 u, B, slide_data->P0, slide_data->P2, slide_data->P3, slide_data->adjust_bezt->vec[2]);
1243
1244 if (need_restore_P2) {
1245 copy_v2_v2(slide_data->P2, oldP2);
1246 }
1247 }
1248 else {
1249 float oldP1[2];
1250 bool need_restore_P1 = false;
1251
1252 if (u < 1.0f - margin) {
1253 float solution[2];
1254 float x = ((1.0f - u) - margin) * 0.5f / (0.5f - margin);
1255 float weight = 3 * x * x - 2 * x * x * x;
1256
1257 slide_spline_solve_P1(u, B, slide_data->P0, slide_data->P2, slide_data->P3, solution);
1258
1259 copy_v2_v2(oldP1, slide_data->P1);
1260 interp_v2_v2v2(slide_data->P1, slide_data->P1, solution, weight);
1261 copy_v2_v2(slide_data->other_bezt->vec[2], slide_data->P1);
1262 need_restore_P1 = true;
1263
1264 /* Tweak handle type in order to be able to apply the delta. */
1265 if (weight > 0.0f) {
1266 if (slide_data->other_bezt->h2 <= HD_VECT) {
1267 slide_data->other_bezt->h2 = HD_FREE;
1268 }
1269 }
1270 }
1271
1273 u, B, slide_data->P0, slide_data->P1, slide_data->P3, slide_data->adjust_bezt->vec[0]);
1274
1275 if (need_restore_P1) {
1276 copy_v2_v2(slide_data->P1, oldP1);
1277 }
1278 }
1279
1280 WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
1281 DEG_id_tag_update(&slide_data->mask->id, 0);
1282
1283 break;
1284 }
1285
1286 case LEFTMOUSE:
1287 case RIGHTMOUSE:
1288 if (event->type == slide_data->event_invoke_type && event->val == KM_RELEASE) {
1289 /* Don't key sliding feather UW's. */
1291 ED_mask_layer_shape_auto_key(slide_data->mask_layer, scene->r.cfra);
1292 }
1293
1294 WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
1295 DEG_id_tag_update(&slide_data->mask->id, 0);
1296
1297 free_slide_spline_curvature_data(slide_data); /* keep this last! */
1298 return OPERATOR_FINISHED;
1299 }
1300
1301 break;
1302
1303 case EVT_ESCKEY:
1305
1306 WM_event_add_notifier(C, NC_MASK | NA_EDITED, slide_data->mask);
1307 DEG_id_tag_update(&slide_data->mask->id, 0);
1308
1309 free_slide_spline_curvature_data(slide_data); /* keep this last! */
1310 return OPERATOR_CANCELLED;
1311 default: {
1312 break;
1313 }
1314 }
1315
1317}
1318
1320{
1321 /* identifiers */
1322 ot->name = "Slide Spline Curvature";
1323 ot->description = "Slide a point on the spline to define its curvature";
1324 ot->idname = "MASK_OT_slide_spline_curvature";
1325
1326 /* API callbacks. */
1330
1331 /* flags */
1332 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1333}
1334
1335/******************** toggle cyclic *********************/
1336
1338{
1340
1341 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1342 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
1343 continue;
1344 }
1345
1346 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1347 if (ED_mask_spline_select_check(spline)) {
1348 spline->flag ^= MASK_SPLINE_CYCLIC;
1349 }
1350 }
1351 }
1352
1353 DEG_id_tag_update(&mask->id, 0);
1355
1356 return OPERATOR_FINISHED;
1357}
1358
1360{
1361 /* identifiers */
1362 ot->name = "Toggle Cyclic";
1363 ot->description = "Toggle cyclic for selected splines";
1364 ot->idname = "MASK_OT_cyclic_toggle";
1365
1366 /* API callbacks. */
1367 ot->exec = cyclic_toggle_exec;
1369
1370 /* flags */
1371 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1372}
1373
1374/******************** delete *********************/
1375
1377{
1378 int count = 0;
1379
1380 if (!point->tot_uw) {
1381 return;
1382 }
1383
1384 for (int i = 0; i < point->tot_uw; i++) {
1385 if ((point->uw[i].flag & SELECT) == 0) {
1386 count++;
1387 }
1388 }
1389
1390 if (count == 0) {
1391 MEM_freeN(point->uw);
1392 point->uw = nullptr;
1393 point->tot_uw = 0;
1394 }
1395 else {
1396 MaskSplinePointUW *new_uw;
1397 int j = 0;
1398
1399 new_uw = MEM_calloc_arrayN<MaskSplinePointUW>(count, "new mask uw points");
1400
1401 for (int i = 0; i < point->tot_uw; i++) {
1402 if ((point->uw[i].flag & SELECT) == 0) {
1403 new_uw[j++] = point->uw[i];
1404 }
1405 }
1406
1407 MEM_freeN(point->uw);
1408
1409 point->uw = new_uw;
1410 point->tot_uw = count;
1411 }
1412}
1413
1415{
1417 bool changed = false;
1418
1419 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1420 MaskSpline *spline;
1421 int mask_layer_shape_ofs = 0;
1422
1423 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
1424 continue;
1425 }
1426
1427 spline = static_cast<MaskSpline *>(mask_layer->splines.first);
1428
1429 while (spline) {
1430 const int tot_point_orig = spline->tot_point;
1431 int count = 0;
1432 MaskSpline *next_spline = spline->next;
1433
1434 /* count unselected points */
1435 for (int i = 0; i < spline->tot_point; i++) {
1436 MaskSplinePoint *point = &spline->points[i];
1437
1438 if (!MASKPOINT_ISSEL_ANY(point)) {
1439 count++;
1440 }
1441 }
1442
1443 if (count == 0) {
1444
1445 /* Update active. */
1446 if (mask_layer->act_point) {
1447 if (ARRAY_HAS_ITEM(mask_layer->act_point, spline->points, spline->tot_point)) {
1448 mask_layer->act_point = nullptr;
1449 }
1450 }
1451 if (spline == mask_layer->act_spline) {
1452 mask_layer->act_spline = nullptr;
1453 }
1454
1455 /* delete the whole spline */
1456 BLI_remlink(&mask_layer->splines, spline);
1457 BKE_mask_spline_free(spline);
1458
1459 BKE_mask_layer_shape_changed_remove(mask_layer, mask_layer_shape_ofs, tot_point_orig);
1460 }
1461 else {
1462 MaskSplinePoint *new_points;
1463
1464 new_points = MEM_calloc_arrayN<MaskSplinePoint>(count, "deleteMaskPoints");
1465
1466 for (int i = 0, j = 0; i < tot_point_orig; i++) {
1467 MaskSplinePoint *point = &spline->points[i];
1468
1469 if (!MASKPOINT_ISSEL_ANY(point)) {
1470 if (point == mask_layer->act_point) {
1471 mask_layer->act_point = &new_points[j];
1472 }
1473
1474 delete_feather_points(point);
1475
1476 new_points[j] = *point;
1477 j++;
1478 }
1479 else {
1480 if (point == mask_layer->act_point) {
1481 mask_layer->act_point = nullptr;
1482 }
1483
1484 BKE_mask_point_free(point);
1485 spline->tot_point--;
1486
1487 BKE_mask_layer_shape_changed_remove(mask_layer, mask_layer_shape_ofs + j, 1);
1488 }
1489 }
1490
1491 mask_layer_shape_ofs += spline->tot_point;
1492
1493 MEM_freeN(spline->points);
1494 spline->points = new_points;
1495
1497 }
1498
1499 changed = true;
1500 spline = next_spline;
1501 }
1502
1503 /* Not essential but confuses users when there are keys with no data!
1504 * Assume if they delete all data from the layer they also don't care about keys. */
1505 if (BLI_listbase_is_empty(&mask_layer->splines)) {
1506 BKE_mask_layer_free_shapes(mask_layer);
1507 }
1508 }
1509
1510 if (!changed) {
1511 return OPERATOR_CANCELLED;
1512 }
1513
1515
1517
1518 return OPERATOR_FINISHED;
1519}
1520
1522{
1523 if (RNA_boolean_get(op->ptr, "confirm")) {
1525 op,
1526 IFACE_("Delete selected control points and splines?"),
1527 nullptr,
1528 IFACE_("Delete"),
1530 false);
1531 }
1532 return delete_exec(C, op);
1533}
1534
1536{
1537 /* identifiers */
1538 ot->name = "Delete";
1539 ot->description = "Delete selected control points or splines";
1540 ot->idname = "MASK_OT_delete";
1541
1542 /* API callbacks. */
1543 ot->invoke = delete_invoke;
1544 ot->exec = delete_exec;
1546
1547 /* flags */
1548 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1550}
1551
1552/* *** switch direction *** */
1554{
1555 Scene *scene = CTX_data_scene(C);
1557
1558 bool changed = false;
1559
1560 /* do actual selection */
1561 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1562 bool changed_layer = false;
1563
1564 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
1565 continue;
1566 }
1567
1568 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1569 if (ED_mask_spline_select_check(spline)) {
1570 BKE_mask_spline_direction_switch(mask_layer, spline);
1571 changed = true;
1572 changed_layer = true;
1573 }
1574 }
1575
1576 if (changed_layer) {
1578 ED_mask_layer_shape_auto_key(mask_layer, scene->r.cfra);
1579 }
1580 }
1581 }
1582
1583 if (changed) {
1585
1588
1589 return OPERATOR_FINISHED;
1590 }
1591
1592 return OPERATOR_CANCELLED;
1593}
1594
1596{
1597 /* identifiers */
1598 ot->name = "Switch Direction";
1599 ot->description = "Switch direction of selected splines";
1600 ot->idname = "MASK_OT_switch_direction";
1601
1602 /* API callbacks. */
1605
1606 /* flags */
1607 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1608}
1609
1610/* *** recalc normals *** */
1612{
1613 Scene *scene = CTX_data_scene(C);
1615
1616 bool changed = false;
1617
1618 /* do actual selection */
1619 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1620 bool changed_layer = false;
1621
1622 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
1623 continue;
1624 }
1625
1626 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1627 for (int i = 0; i < spline->tot_point; i++) {
1628 MaskSplinePoint *point = &spline->points[i];
1629
1630 if (MASKPOINT_ISSEL_ANY(point)) {
1631 BKE_mask_calc_handle_point_auto(spline, point, false);
1632 changed = true;
1633 changed_layer = true;
1634 }
1635 }
1636 }
1637
1638 if (changed_layer) {
1640 ED_mask_layer_shape_auto_key(mask_layer, scene->r.cfra);
1641 }
1642 }
1643 }
1644
1645 if (changed) {
1647
1650
1651 return OPERATOR_FINISHED;
1652 }
1653
1654 return OPERATOR_CANCELLED;
1655}
1656
1658{
1659 /* identifiers */
1660 ot->name = "Recalculate Handles";
1661 ot->description = "Recalculate the direction of selected handles";
1662 ot->idname = "MASK_OT_normals_make_consistent";
1663
1664 /* API callbacks. */
1667
1668 /* flags */
1669 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1670}
1671
1672/******************** set handle type *********************/
1673
1675{
1677 int handle_type = RNA_enum_get(op->ptr, "type");
1678
1679 bool changed = false;
1680
1681 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1682 if (mask_layer->visibility_flag & (MASK_HIDE_VIEW | MASK_HIDE_SELECT)) {
1683 continue;
1684 }
1685
1686 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1687 for (int i = 0; i < spline->tot_point; i++) {
1688 MaskSplinePoint *point = &spline->points[i];
1689
1690 if (MASKPOINT_ISSEL_ANY(point)) {
1691 BezTriple *bezt = &point->bezt;
1692
1693 if (bezt->f2 & SELECT) {
1694 bezt->h1 = handle_type;
1695 bezt->h2 = handle_type;
1696 }
1697 else {
1698 if (bezt->f1 & SELECT) {
1699 bezt->h1 = handle_type;
1700 }
1701 if (bezt->f3 & SELECT) {
1702 bezt->h2 = handle_type;
1703 }
1704 }
1705
1706 if (handle_type == HD_ALIGN) {
1707 float vec[3];
1708 sub_v3_v3v3(vec, bezt->vec[0], bezt->vec[1]);
1709 add_v3_v3v3(bezt->vec[2], bezt->vec[1], vec);
1710 }
1711
1712 changed = true;
1713 }
1714 }
1715 }
1716 }
1717
1718 if (changed) {
1720 DEG_id_tag_update(&mask->id, 0);
1721
1722 return OPERATOR_FINISHED;
1723 }
1724 return OPERATOR_CANCELLED;
1725}
1726
1728{
1729 static const EnumPropertyItem editcurve_handle_type_items[] = {
1730 {HD_AUTO, "AUTO", 0, "Auto", ""},
1731 {HD_VECT, "VECTOR", 0, "Vector", ""},
1732 {HD_ALIGN, "ALIGNED", 0, "Aligned Single", ""},
1733 {HD_ALIGN_DOUBLESIDE, "ALIGNED_DOUBLESIDE", 0, "Aligned", ""},
1734 {HD_FREE, "FREE", 0, "Free", ""},
1735 {0, nullptr, 0, nullptr, nullptr},
1736 };
1737
1738 /* identifiers */
1739 ot->name = "Set Handle Type";
1740 ot->description = "Set type of handles for selected control points";
1741 ot->idname = "MASK_OT_handle_type_set";
1742
1743 /* API callbacks. */
1744 ot->invoke = WM_menu_invoke;
1745 ot->exec = set_handle_type_exec;
1747
1748 /* flags */
1749 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1750
1751 /* properties */
1752 ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
1753}
1754
1755/* ********* clear/set restrict view *********/
1757{
1759 bool changed = false;
1760 const bool select = RNA_boolean_get(op->ptr, "select");
1761
1762 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1763
1764 if (mask_layer->visibility_flag & OB_HIDE_VIEWPORT) {
1765 ED_mask_layer_select_set(mask_layer, select);
1766 mask_layer->visibility_flag &= ~OB_HIDE_VIEWPORT;
1767 changed = true;
1768 }
1769 }
1770
1771 if (changed) {
1773 DEG_id_tag_update(&mask->id, 0);
1774
1775 return OPERATOR_FINISHED;
1776 }
1777 return OPERATOR_CANCELLED;
1778}
1779
1781{
1782
1783 /* identifiers */
1784 ot->name = "Clear Restrict View";
1785 ot->description = "Reveal temporarily hidden mask layers";
1786 ot->idname = "MASK_OT_hide_view_clear";
1787
1788 /* API callbacks. */
1790 ot->poll = ED_maskedit_mask_poll;
1791
1792 /* flags */
1793 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1794
1795 RNA_def_boolean(ot->srna, "select", true, "Select", "");
1796}
1797
1799{
1801 const bool unselected = RNA_boolean_get(op->ptr, "unselected");
1802 bool changed = false;
1803
1804 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1805
1806 if (mask_layer->visibility_flag & MASK_HIDE_SELECT) {
1807 continue;
1808 }
1809
1810 if (!unselected) {
1811 if (ED_mask_layer_select_check(mask_layer)) {
1812 ED_mask_layer_select_set(mask_layer, false);
1813
1814 mask_layer->visibility_flag |= OB_HIDE_VIEWPORT;
1815 changed = true;
1816 if (mask_layer == BKE_mask_layer_active(mask)) {
1818 }
1819 }
1820 }
1821 else {
1822 if (!ED_mask_layer_select_check(mask_layer)) {
1823 mask_layer->visibility_flag |= OB_HIDE_VIEWPORT;
1824 changed = true;
1825 if (mask_layer == BKE_mask_layer_active(mask)) {
1827 }
1828 }
1829 }
1830 }
1831
1832 if (changed) {
1834 DEG_id_tag_update(&mask->id, 0);
1835
1836 return OPERATOR_FINISHED;
1837 }
1838 return OPERATOR_CANCELLED;
1839}
1840
1842{
1843 /* identifiers */
1844 ot->name = "Set Restrict View";
1845 ot->description = "Temporarily hide mask layers";
1846 ot->idname = "MASK_OT_hide_view_set";
1847
1848 /* API callbacks. */
1850 ot->poll = ED_maskedit_mask_poll;
1851
1852 /* flags */
1853 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1854
1856 ot->srna, "unselected", false, "Unselected", "Hide unselected rather than selected layers");
1857}
1858
1860{
1862 bool changed = false;
1863
1864 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1865 if (mask_layer->visibility_flag & (MASK_HIDE_SELECT | MASK_HIDE_VIEW)) {
1866 continue;
1867 }
1868
1869 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1870 for (int i = 0; i < spline->tot_point; i++) {
1871 MaskSplinePoint *point = &spline->points[i];
1872
1873 if (MASKPOINT_ISSEL_ANY(point)) {
1874 BezTriple *bezt = &point->bezt;
1875 bezt->weight = 0.0f;
1876 changed = true;
1877 }
1878 }
1879 }
1880 }
1881
1882 if (changed) {
1884
1886 DEG_id_tag_update(&mask->id, 0);
1887
1888 return OPERATOR_FINISHED;
1889 }
1890 return OPERATOR_CANCELLED;
1891}
1892
1894{
1895 /* identifiers */
1896 ot->name = "Clear Feather Weight";
1897 ot->description = "Reset the feather weight to zero";
1898 ot->idname = "MASK_OT_feather_weight_clear";
1899
1900 /* API callbacks. */
1903
1904 /* flags */
1905 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1906}
1907
1908/******************** move mask layer operator *********************/
1909
1911{
1912 if (ED_maskedit_mask_poll(C)) {
1914
1915 return mask->masklay_tot > 0;
1916 }
1917
1918 return false;
1919}
1920
1922{
1924 MaskLayer *mask_layer = static_cast<MaskLayer *>(
1925 BLI_findlink(&mask->masklayers, mask->masklay_act));
1926 MaskLayer *mask_layer_other;
1927 int direction = RNA_enum_get(op->ptr, "direction");
1928
1929 if (!mask_layer) {
1930 return OPERATOR_CANCELLED;
1931 }
1932
1933 if (direction == -1) {
1934 mask_layer_other = mask_layer->prev;
1935
1936 if (!mask_layer_other) {
1937 return OPERATOR_CANCELLED;
1938 }
1939
1940 BLI_remlink(&mask->masklayers, mask_layer);
1941 BLI_insertlinkbefore(&mask->masklayers, mask_layer_other, mask_layer);
1942 mask->masklay_act--;
1943 }
1944 else if (direction == 1) {
1945 mask_layer_other = mask_layer->next;
1946
1947 if (!mask_layer_other) {
1948 return OPERATOR_CANCELLED;
1949 }
1950
1951 BLI_remlink(&mask->masklayers, mask_layer);
1952 BLI_insertlinkafter(&mask->masklayers, mask_layer_other, mask_layer);
1953 mask->masklay_act++;
1954 }
1955
1958
1959 return OPERATOR_FINISHED;
1960}
1961
1963{
1964 static const EnumPropertyItem direction_items[] = {
1965 {-1, "UP", 0, "Up", ""},
1966 {1, "DOWN", 0, "Down", ""},
1967 {0, nullptr, 0, nullptr, nullptr},
1968 };
1969
1970 /* identifiers */
1971 ot->name = "Move Layer";
1972 ot->description = "Move the active layer up/down in the list";
1973 ot->idname = "MASK_OT_layer_move";
1974
1975 /* API callbacks. */
1976 ot->exec = mask_layer_move_exec;
1977 ot->poll = mask_layer_move_poll;
1978
1979 /* flags */
1980 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1981
1982 /* properties */
1983 RNA_def_enum(ot->srna,
1984 "direction",
1985 direction_items,
1986 0,
1987 "Direction",
1988 "Direction to move the active layer");
1989}
1990
1991/******************** duplicate *********************/
1992
1994{
1996
1997 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
1998 LISTBASE_FOREACH_BACKWARD (MaskSpline *, spline, &mask_layer->splines) {
1999 const bool act_point_in_spline = mask_layer->act_point &&
2000 ARRAY_HAS_ITEM(mask_layer->act_point,
2001 spline->points,
2002 spline->tot_point);
2003 const void *act_point_prev = mask_layer->act_point;
2004
2005 MaskSplinePoint *point = spline->points;
2006 int i = 0;
2007 while (i < spline->tot_point) {
2008 int start = i, end = -1;
2009 /* Find next selected segment. */
2010 while (MASKPOINT_ISSEL_ANY(point)) {
2011 BKE_mask_point_select_set(point, false);
2012 end = i;
2013 if (i >= spline->tot_point - 1) {
2014 break;
2015 }
2016 i++;
2017 point++;
2018 }
2019 if (end >= start) {
2020 int tot_point;
2021 int tot_point_shape_start = 0;
2022 MaskSpline *new_spline = BKE_mask_spline_add(mask_layer);
2023 MaskSplinePoint *new_point;
2024 int b;
2025
2026 /* BKE_mask_spline_add might allocate the points,
2027 * need to free them in this case. */
2028 if (new_spline->points) {
2029 MEM_freeN(new_spline->points);
2030 }
2031
2032 /* Copy options from old spline. */
2033 new_spline->flag = spline->flag;
2034 new_spline->offset_mode = spline->offset_mode;
2035 new_spline->weight_interp = spline->weight_interp;
2036 new_spline->parent = spline->parent;
2037
2038 /* Allocate new points and copy them from old spline. */
2039 new_spline->tot_point = end - start + 1;
2040 new_spline->points = MEM_calloc_arrayN<MaskSplinePoint>(new_spline->tot_point,
2041 "duplicated mask points");
2042
2043 memcpy(new_spline->points,
2044 spline->points + start,
2045 new_spline->tot_point * sizeof(MaskSplinePoint));
2046
2047 tot_point = new_spline->tot_point;
2048
2049 /* Update the active. */
2050 if (mask_layer->act_point) {
2051 ptrdiff_t act_index = mask_layer->act_point - &spline->points[start];
2052 if (size_t(act_index) < new_spline->tot_point) {
2053 mask_layer->act_point = &new_spline->points[act_index];
2054 }
2055 }
2056 if (mask_layer->act_spline) {
2057 if (mask_layer->act_spline == spline) {
2058 mask_layer->act_spline = new_spline;
2059 }
2060 }
2061
2062 /* animation requires points added one by one */
2063 if (mask_layer->splines_shapes.first) {
2064 new_spline->tot_point = 0;
2065 tot_point_shape_start = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
2066 }
2067
2068 /* Select points and duplicate their UWs (if needed). */
2069 for (b = 0, new_point = new_spline->points; b < tot_point; b++, new_point++) {
2070 if (new_point->uw) {
2071 new_point->uw = static_cast<MaskSplinePointUW *>(MEM_dupallocN(new_point->uw));
2072 }
2073 BKE_mask_point_select_set(new_point, true);
2074
2075 if (mask_layer->splines_shapes.first) {
2076 new_spline->tot_point++;
2077 BKE_mask_layer_shape_changed_add(mask_layer, tot_point_shape_start + b, true, false);
2078 }
2079 }
2080
2081 /* Clear cyclic flag if we didn't copy the whole spline. */
2082 if (new_spline->flag & MASK_SPLINE_CYCLIC) {
2083 if (start != 0 || end != spline->tot_point - 1) {
2084 new_spline->flag &= ~MASK_SPLINE_CYCLIC;
2085 }
2086 }
2087
2088 /* Flush selection to splines. */
2089 new_spline->flag |= SELECT;
2090 spline->flag &= ~SELECT;
2091 }
2092 i++;
2093 point++;
2094 }
2095
2096 if (act_point_in_spline && (mask_layer->act_point == act_point_prev)) {
2097 /* The active point was part of this spline but not copied,
2098 * clear it to avoid confusion with the active spline & point getting out of sync. */
2099 mask_layer->act_point = nullptr;
2100 }
2101 }
2102 }
2103
2105
2107
2108 return OPERATOR_FINISHED;
2109}
2110
2112{
2113 /* identifiers */
2114 ot->name = "Duplicate Mask";
2115 ot->description = "Duplicate selected control points and segments between them";
2116 ot->idname = "MASK_OT_duplicate";
2117
2118 /* API callbacks. */
2119 ot->exec = mask_duplicate_exec;
2121
2122 /* flags */
2123 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2124}
2125
2126/********************** copy splines to clipboard operator *********************/
2127
2129{
2131 MaskLayer *mask_layer = BKE_mask_layer_active(mask);
2132
2133 if (mask_layer == nullptr) {
2134 return OPERATOR_CANCELLED;
2135 }
2136
2138
2139 return OPERATOR_FINISHED;
2140}
2141
2143{
2144 /* identifiers */
2145 ot->name = "Copy Splines";
2146 ot->description = "Copy the selected splines to the internal clipboard";
2147 ot->idname = "MASK_OT_copy_splines";
2148
2149 /* API callbacks. */
2150 ot->exec = copy_splines_exec;
2151 ot->poll = ED_maskedit_mask_poll;
2152
2153 /* flags */
2154 ot->flag = OPTYPE_REGISTER;
2155}
2156
2157/********************** paste tracks from clipboard operator *********************/
2158
2160{
2162 return BKE_mask_clipboard_is_empty() == false;
2163 }
2164
2165 return false;
2166}
2167
2169{
2171 MaskLayer *mask_layer = BKE_mask_layer_active(mask);
2172
2173 if (mask_layer == nullptr) {
2174 mask_layer = BKE_mask_layer_new(mask, "");
2175 }
2176
2178
2180
2182
2183 return OPERATOR_FINISHED;
2184}
2185
2187{
2188 /* identifiers */
2189 ot->name = "Paste Splines";
2190 ot->description = "Paste splines from the internal clipboard";
2191 ot->idname = "MASK_OT_paste_splines";
2192
2193 /* API callbacks. */
2194 ot->exec = paste_splines_exec;
2195 ot->poll = paste_splines_poll;
2196
2197 /* flags */
2198 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
2199}
Functions to insert, delete or modify keyframes.
Mask * CTX_data_edit_mask(const bContext *C)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
SpaceClip * CTX_wm_space_clip(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
struct Mask * BKE_mask_new(struct Main *bmain, const char *name)
#define MASKPOINT_ISSEL_ANY(p)
Definition BKE_mask.h:292
void BKE_mask_layer_shape_changed_add(struct MaskLayer *masklay, int index, bool do_init, bool do_init_interpolate)
struct MaskSplinePointUW * BKE_mask_point_sort_uw(struct MaskSplinePoint *point, struct MaskSplinePointUW *uw)
void BKE_mask_layer_remove(struct Mask *mask, struct MaskLayer *masklay)
void BKE_mask_point_select_set(struct MaskSplinePoint *point, bool do_select)
void BKE_mask_calc_handle_point_auto(struct MaskSpline *spline, struct MaskSplinePoint *point, bool do_recalc_length)
Resets auto handles even for non-auto bezier points.
eMaskWhichHandle
Definition BKE_mask.h:28
@ MASK_WHICH_HANDLE_NONE
Definition BKE_mask.h:29
@ MASK_WHICH_HANDLE_RIGHT
Definition BKE_mask.h:32
@ MASK_WHICH_HANDLE_LEFT
Definition BKE_mask.h:31
@ MASK_WHICH_HANDLE_STICK
Definition BKE_mask.h:30
struct MaskSpline * BKE_mask_spline_add(struct MaskLayer *masklay)
struct MaskSpline * BKE_mask_spline_copy(const struct MaskSpline *spline)
void BKE_mask_spline_free(struct MaskSpline *spline)
void BKE_mask_point_free(struct MaskSplinePoint *point)
void BKE_mask_layer_active_set(struct Mask *mask, struct MaskLayer *masklay)
struct BezTriple * BKE_mask_spline_point_next_bezt(struct MaskSpline *spline, struct MaskSplinePoint *points_array, struct MaskSplinePoint *point)
struct MaskLayer * BKE_mask_layer_new(struct Mask *mask, const char *name)
float BKE_mask_point_weight_scalar(struct MaskSpline *spline, struct MaskSplinePoint *point, float u)
void BKE_mask_point_set_handle(struct MaskSplinePoint *point, eMaskWhichHandle which_handle, float loc[2], bool keep_direction, float orig_handle[2], float orig_vec[3][3])
@ MASK_PROJ_NEG
Definition BKE_mask.h:91
@ MASK_PROJ_POS
Definition BKE_mask.h:93
void BKE_mask_clipboard_paste_to_layer(struct Main *bmain, struct MaskLayer *mask_layer)
void BKE_mask_coord_to_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2])
void BKE_mask_layer_free_shapes(struct MaskLayer *masklay)
Free all animation keys for a mask layer.
void BKE_mask_point_handle(const struct MaskSplinePoint *point, eMaskWhichHandle which_handle, float r_handle[2])
void BKE_mask_point_normal(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float n[2])
void BKE_mask_point_segment_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float u, float co[2])
int BKE_mask_layer_shape_spline_to_index(struct MaskLayer *masklay, struct MaskSpline *spline)
void BKE_mask_coord_from_movieclip(struct MovieClip *clip, struct MovieClipUser *user, float r_co[2], const float co[2])
void BKE_mask_layer_shape_changed_remove(struct MaskLayer *masklay, int index, int count)
bool BKE_mask_clipboard_is_empty(void)
float BKE_mask_spline_project_co(struct MaskSpline *spline, struct MaskSplinePoint *point, float start_u, const float co[2], eMaskSign sign)
struct MaskLayer * BKE_mask_layer_active(struct Mask *mask)
void BKE_mask_clipboard_copy_from_layer(struct MaskLayer *mask_layer)
void BKE_mask_spline_direction_switch(struct MaskLayer *masklay, struct MaskSpline *spline)
struct MaskSplinePoint * BKE_mask_spline_point_array(struct MaskSpline *spline)
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define ATTR_FALLTHROUGH
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
MINLINE float min_ff(float a, float b)
MINLINE float square_f(float a)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void project_v2_v2v2_normalized(float out[2], const float p[2], const float v_proj[2])
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f)
void interp_v2_v2v2(float r[2], const float a[2], const float b[2], float t)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void minmax_v2v2_v2(float min[2], float max[2], const float vec[2])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
#define INIT_MINMAX2(min, max)
#define ARRAY_HAS_ITEM(arr_item, arr_start, arr_len)
#define ELEM(...)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1118
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define MAX_ID_NAME
Definition DNA_ID.h:373
@ HD_VECT
@ HD_FREE
@ HD_AUTO
@ HD_ALIGN_DOUBLESIDE
@ HD_ALIGN
@ MASK_HIDE_SELECT
@ MASK_HIDE_VIEW
@ MASK_SPLINE_CYCLIC
@ MCLIP_PROXY_RENDER_UNDISTORT
Object is a sort of wrapper for general info.
@ OB_HIDE_VIEWPORT
@ SPACE_CLIP
@ SPACE_SEQ
@ SPACE_IMAGE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void ED_space_clip_set_mask(bContext *C, SpaceClip *sc, Mask *mask)
void ED_clip_point_undistorted_pos(const SpaceClip *sc, const float co[2], float r_co[2])
void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask)
void ED_mask_mouse_pos(ScrArea *area, ARegion *region, const int mval[2], float r_co[2])
void ED_mask_layer_shape_auto_key(MaskLayer *mask_layer, int frame)
void ED_mask_get_size(ScrArea *area, int *r_width, int *r_height)
bool ED_maskedit_mask_poll(bContext *C)
Definition mask_edit.cc:60
bool ED_maskedit_poll(bContext *C)
Definition mask_edit.cc:28
bool ED_maskedit_mask_visible_splines_poll(bContext *C)
Definition mask_edit.cc:76
@ SEL_DESELECT
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition RNA_types.hh:344
#define C
Definition RandGen.cpp:29
@ ALERT_ICON_NONE
#define ND_DRAW
Definition WM_types.hh:461
#define ND_DATA
Definition WM_types.hh:509
@ KM_PRESS
Definition WM_types.hh:311
@ KM_RELEASE
Definition WM_types.hh:312
#define NA_ADDED
Definition WM_types.hh:586
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NA_EDITED
Definition WM_types.hh:584
#define ND_SELECT
Definition WM_types.hh:508
#define NC_MASK
Definition WM_types.hh:398
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define SELECT
static wmOperatorStatus set_handle_type_exec(bContext *C, wmOperator *op)
static wmOperatorStatus delete_exec(bContext *C, wmOperator *op)
Definition editfont.cc:1717
#define select(A, B, C)
int count
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void ED_mask_view_lock_state_restore_no_jump(const bContext *C, const MaskViewLockState *state)
Definition mask_edit.cc:215
void ED_mask_view_lock_state_store(const bContext *C, MaskViewLockState *state)
Definition mask_edit.cc:207
bool ED_mask_spline_select_check(const MaskSpline *spline)
MaskSplinePoint * ED_mask_point_find_nearest(const bContext *C, Mask *mask_orig, const float normal_co[2], float threshold, MaskLayer **r_mask_layer, MaskSpline **r_spline, eMaskWhichHandle *r_which_handle, float *r_score)
bool ED_mask_layer_select_check(const MaskLayer *mask_layer)
bool ED_mask_feather_find_nearest(const bContext *C, Mask *mask_orig, const float normal_co[2], float threshold, MaskLayer **r_mask_layer, MaskSpline **r_spline, MaskSplinePoint **r_point, MaskSplinePointUW **r_uw, float *r_score)
void ED_mask_select_flush_all(Mask *mask)
void ED_mask_select_toggle_all(Mask *mask, int action)
void ED_mask_layer_select_set(MaskLayer *mask_layer, bool do_select)
bool ED_mask_find_nearest_diff_point(const bContext *C, Mask *mask_orig, const float normal_co[2], int threshold, bool feather, float tangent[2], bool use_deform, bool use_project, MaskLayer **r_mask_layer, MaskSpline **r_spline, MaskSplinePoint **r_point, float *r_u, float *r_score)
Definition mask_query.cc:36
static wmOperatorStatus mask_feather_weight_clear_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1859
static void cancel_slide_point(SlidePointData *data)
Definition mask_ops.cc:613
static bool paste_splines_poll(bContext *C)
Definition mask_ops.cc:2159
static SlideSplineCurvatureData * slide_spline_curvature_customdata(bContext *C, const wmEvent *event)
Definition mask_ops.cc:998
static wmOperatorStatus mask_duplicate_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1993
static void cancel_slide_spline_curvature(SlideSplineCurvatureData *slide_data)
Definition mask_ops.cc:966
static SlidePointData * slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event)
Definition mask_ops.cc:425
void MASK_OT_slide_spline_curvature(wmOperatorType *ot)
Definition mask_ops.cc:1319
void MASK_OT_copy_splines(wmOperatorType *ot)
Definition mask_ops.cc:2142
static wmOperatorStatus slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition mask_ops.cc:646
static void check_sliding_handle_type(MaskSplinePoint *point, eMaskWhichHandle which_handle)
Definition mask_ops.cc:401
static wmOperatorStatus slide_spline_curvature_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition mask_ops.cc:1161
void MASK_OT_layer_move(wmOperatorType *ot)
Definition mask_ops.cc:1962
void MASK_OT_feather_weight_clear(wmOperatorType *ot)
Definition mask_ops.cc:1893
void MASK_OT_layer_remove(wmOperatorType *ot)
Definition mask_ops.cc:182
static bool slide_point_check_initial_feather(MaskSpline *spline)
Definition mask_ops.cc:357
static wmOperatorStatus mask_hide_view_clear_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:1756
static wmOperatorStatus delete_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1414
void MASK_OT_paste_splines(wmOperatorType *ot)
Definition mask_ops.cc:2186
static wmOperatorStatus paste_splines_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:2168
static wmOperatorStatus mask_layer_remove_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:167
void MASK_OT_layer_new(wmOperatorType *ot)
Definition mask_ops.cc:147
static wmOperatorStatus copy_splines_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:2128
static bool slide_spline_curvature_check(bContext *C, const wmEvent *event)
Definition mask_ops.cc:977
static void select_sliding_point(Mask *mask, MaskLayer *mask_layer, MaskSpline *spline, MaskSplinePoint *point, eMaskWhichHandle which_handle)
Definition mask_ops.cc:370
static wmOperatorStatus mask_switch_direction_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1553
static void mask_point_undistort_pos(SpaceClip *sc, float r_co[2], const float co[2])
Definition mask_ops.cc:246
static wmOperatorStatus slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition mask_ops.cc:561
static void free_slide_spline_curvature_data(SlideSplineCurvatureData *slide_data)
Definition mask_ops.cc:972
MaskLayer * ED_mask_layer_ensure(bContext *C, bool *r_added_mask)
Definition mask_ops.cc:78
Mask * ED_mask_new(bContext *C, const char *name)
Definition mask_ops.cc:48
static wmOperatorStatus cyclic_toggle_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1337
static void slide_spline_solve_P1(const float u, const float B[2], const float P0[2], const float P2[2], const float P3[2], float solution[2])
Definition mask_ops.cc:1129
static wmOperatorStatus mask_new_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:98
void MASK_OT_hide_view_clear(wmOperatorType *ot)
Definition mask_ops.cc:1780
static bool mask_layer_move_poll(bContext *C)
Definition mask_ops.cc:1910
static wmOperatorStatus mask_layer_move_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:1921
void MASK_OT_new(wmOperatorType *ot)
Definition mask_ops.cc:111
static wmOperatorStatus mask_layer_new_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:131
static void slide_point_delta_all_feather(SlidePointData *data, float delta)
Definition mask_ops.cc:588
static wmOperatorStatus mask_normals_make_consistent_exec(bContext *C, wmOperator *)
Definition mask_ops.cc:1611
void MASK_OT_handle_type_set(wmOperatorType *ot)
Definition mask_ops.cc:1727
void MASK_OT_duplicate(wmOperatorType *ot)
Definition mask_ops.cc:2111
void MASK_OT_cyclic_toggle(wmOperatorType *ot)
Definition mask_ops.cc:1359
static wmOperatorStatus delete_invoke(bContext *C, wmOperator *op, const wmEvent *)
Definition mask_ops.cc:1521
static wmOperatorStatus mask_hide_view_set_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:1798
static void slide_spline_solve_P2(const float u, const float B[2], const float P0[2], const float P1[2], const float P3[2], float solution[2])
Definition mask_ops.cc:1145
static wmOperatorStatus slide_spline_curvature_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition mask_ops.cc:1102
static void free_slide_point_data(SlidePointData *data)
Definition mask_ops.cc:637
void MASK_OT_delete(wmOperatorType *ot)
Definition mask_ops.cc:1535
static void delete_feather_points(MaskSplinePoint *point)
Definition mask_ops.cc:1376
static wmOperatorStatus set_handle_type_exec(bContext *C, wmOperator *op)
Definition mask_ops.cc:1674
static bool spline_under_mouse_get(const bContext *C, Mask *mask_orig, const float co[2], MaskLayer **r_mask_layer, MaskSpline **r_mask_spline)
Definition mask_ops.cc:253
void MASK_OT_hide_view_set(wmOperatorType *ot)
Definition mask_ops.cc:1841
@ SLIDE_ACTION_NONE
Definition mask_ops.cc:200
@ SLIDE_ACTION_POINT
Definition mask_ops.cc:201
@ SLIDE_ACTION_SPLINE
Definition mask_ops.cc:204
@ SLIDE_ACTION_HANDLE
Definition mask_ops.cc:202
@ SLIDE_ACTION_FEATHER
Definition mask_ops.cc:203
void MASK_OT_slide_point(wmOperatorType *ot)
Definition mask_ops.cc:917
void MASK_OT_switch_direction(wmOperatorType *ot)
Definition mask_ops.cc:1595
void MASK_OT_normals_make_consistent(wmOperatorType *ot)
Definition mask_ops.cc:1657
static void slide_point_restore_spline(SlidePointData *data)
Definition mask_ops.cc:599
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define B
bool is_autokey_on(const Scene *scene)
VecBase< float, 2 > float2
const char * name
std::string RNA_string_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_string(StructOrFunctionRNA *cont_, const char *identifier, const char *default_value, const int maxlen, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
#define min(a, b)
Definition sort.cc:36
#define FLT_MAX
Definition stdcycles.h:14
float vec[3][3]
void * first
struct MaskLayer * next
struct MaskLayer * prev
struct MaskSplinePoint * act_point
struct MaskSpline * act_spline
char parent[64]
MaskSplinePointUW * uw
MaskParent parent
struct MaskSpline * next
MaskSplinePoint * points
ListBase masklayers
struct RenderData r
ListBase spacedata
float vec[3][3]
Definition mask_ops.cc:233
short event_invoke_type
Definition mask_ops.cc:209
float orig_handle_coord[2]
Definition mask_ops.cc:239
float prev_zero_coord[2]
Definition mask_ops.cc:224
float prev_handle_coord[2]
Definition mask_ops.cc:239
float prev_feather_coord[2]
Definition mask_ops.cc:242
eMaskWhichHandle which_handle
Definition mask_ops.cc:216
MaskSpline * spline
Definition mask_ops.cc:213
float weight_scalar
Definition mask_ops.cc:243
bool is_sliding_new_point
Definition mask_ops.cc:230
MaskLayer * mask_layer
Definition mask_ops.cc:212
bool is_curvature_only
Definition mask_ops.cc:228
MaskSplinePoint * point
Definition mask_ops.cc:214
MaskSpline * orig_spline
Definition mask_ops.cc:213
bool is_overall_feather
Definition mask_ops.cc:228
float no[2]
Definition mask_ops.cc:226
MaskSplinePointUW * uw
Definition mask_ops.cc:215
float prev_mouse_coord[2]
Definition mask_ops.cc:219
bool is_initial_feather
Definition mask_ops.cc:228
MaskSplinePoint * point
Definition mask_ops.cc:953
struct MovieClipUser user
struct MovieClip * clip
wmEventType type
Definition WM_types.hh:757
short val
Definition WM_types.hh:759
int mval[2]
Definition WM_types.hh:763
struct PointerRNA * ptr
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_RIGHTCTRLKEY
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ EVT_RIGHTALTKEY
@ LEFTMOUSE
@ EVT_LEFTALTKEY
@ EVT_ESCKEY
@ EVT_RIGHTSHIFTKEY
@ EVT_LEFTSHIFTKEY
wmOperatorType * ot
Definition wm_files.cc:4237
void WM_operator_properties_confirm_or_exec(wmOperatorType *ot)
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)
wmOperatorStatus WM_operator_confirm_ex(bContext *C, wmOperator *op, const char *title, const char *message, const char *confirm_text, int icon, bool cancel_default)