Blender V4.5
blenkernel/intern/mask.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 <cstddef>
10#include <cstring>
11#include <optional>
12
13#include "CLG_log.h"
14
15#include "MEM_guardedalloc.h"
16
17#include "BLI_ghash.h"
18#include "BLI_listbase.h"
19#include "BLI_math_geom.h"
20#include "BLI_math_matrix.h"
21#include "BLI_math_vector.h"
22#include "BLI_string.h"
23#include "BLI_string_utils.hh"
24#include "BLI_utildefines.h"
25
26#include "BLT_translation.hh"
27
28#include "DNA_defaults.h"
29#include "DNA_mask_types.h"
30
31#include "BKE_animsys.h"
32#include "BKE_curve.hh"
33#include "BKE_idtype.hh"
34
35#include "BKE_anim_data.hh"
36#include "BKE_image.hh"
37#include "BKE_lib_id.hh"
38#include "BKE_lib_query.hh"
39#include "BKE_main.hh"
40#include "BKE_mask.h"
41#include "BKE_movieclip.h"
42#include "BKE_tracking.h"
43
45
46#include "DRW_engine.hh"
47
48#include "BLO_read_write.hh"
49
50static CLG_LogRef LOG = {"bke.mask"};
51
54{
55 mask->runtime.last_update = 0;
56}
57
58static void mask_copy_data(Main * /*bmain*/,
59 std::optional<Library *> /*owner_library*/,
60 ID *id_dst,
61 const ID *id_src,
62 const int /*flag*/)
63{
64 Mask *mask_dst = (Mask *)id_dst;
65 const Mask *mask_src = (const Mask *)id_src;
66
68
69 /* TODO: add unused flag to those as well. */
70 BKE_mask_layer_copy_list(&mask_dst->masklayers, &mask_src->masklayers);
71
72 /* enable fake user by default */
73 id_fake_user_set(&mask_dst->id);
74}
75
76static void mask_free_data(ID *id)
77{
78 Mask *mask = (Mask *)id;
79
80 /* free mask data */
81 BKE_mask_layer_free_list(&mask->masklayers);
82}
83
85{
86 Mask *mask = (Mask *)id;
87
88 LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) {
89 LISTBASE_FOREACH (MaskSpline *, mask_spline, &mask_layer->splines) {
90 BKE_LIB_FOREACHID_PROCESS_ID(data, mask_spline->parent.id, IDWALK_CB_USER);
91 for (int i = 0; i < mask_spline->tot_point; i++) {
92 MaskSplinePoint *point = &mask_spline->points[i];
94 }
95 }
96 }
97}
98
99static void mask_blend_write(BlendWriter *writer, ID *id, const void *id_address)
100{
101 Mask *mask = (Mask *)id;
102
103 BLO_write_id_struct(writer, Mask, id_address, &mask->id);
104 BKE_id_blend_write(writer, &mask->id);
105
106 LISTBASE_FOREACH (MaskLayer *, masklay, &mask->masklayers) {
107 BLO_write_struct(writer, MaskLayer, masklay);
108
109 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
110 int i;
111
112 MaskSplinePoint *points_deform = spline->points_deform;
113 spline->points_deform = nullptr;
114
115 BLO_write_struct(writer, MaskSpline, spline);
116 BLO_write_struct_array(writer, MaskSplinePoint, spline->tot_point, spline->points);
117
118 spline->points_deform = points_deform;
119
120 for (i = 0; i < spline->tot_point; i++) {
121 MaskSplinePoint *point = &spline->points[i];
122
123 if (point->tot_uw) {
124 BLO_write_struct_array(writer, MaskSplinePointUW, point->tot_uw, point->uw);
125 }
126 }
127 }
128
129 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
130 BLO_write_struct(writer, MaskLayerShape, masklay_shape);
132 writer, masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, masklay_shape->data);
133 }
134 }
135}
136
137static void mask_blend_read_data(BlendDataReader *reader, ID *id)
138{
139 Mask *mask = (Mask *)id;
140
141 BLO_read_struct_list(reader, MaskLayer, &mask->masklayers);
142
143 LISTBASE_FOREACH (MaskLayer *, masklay, &mask->masklayers) {
144 /* Can't use #newdataadr since it's a pointer within an array. */
145 MaskSplinePoint *act_point_search = nullptr;
146
147 BLO_read_struct_list(reader, MaskSpline, &masklay->splines);
148
149 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
150 MaskSplinePoint *points_old = spline->points;
151
152 BLO_read_struct_array(reader, MaskSplinePoint, spline->tot_point, &spline->points);
153
154 for (int i = 0; i < spline->tot_point; i++) {
155 MaskSplinePoint *point = &spline->points[i];
156
157 if (point->tot_uw) {
158 BLO_read_struct_array(reader, MaskSplinePointUW, point->tot_uw, &point->uw);
159 }
160 }
161
162 /* detect active point */
163 if ((act_point_search == nullptr) && (masklay->act_point >= points_old) &&
164 (masklay->act_point < points_old + spline->tot_point))
165 {
166 act_point_search = &spline->points[masklay->act_point - points_old];
167 }
168 }
169
170 BLO_read_struct_list(reader, MaskLayerShape, &masklay->splines_shapes);
171
172 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
174 reader, masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, &masklay_shape->data);
175 }
176
177 BLO_read_struct(reader, MaskSpline, &masklay->act_spline);
178 masklay->act_point = act_point_search;
179 }
180
182}
183
185 /*id_code*/ Mask::id_type,
186 /*id_filter*/ FILTER_ID_MSK,
187 /*dependencies_id_types*/ FILTER_ID_MC, /* WARNING! mask->parent.id, not typed. */
188 /*main_listbase_index*/ INDEX_ID_MSK,
189 /*struct_size*/ sizeof(Mask),
190 /*name*/ "Mask",
191 /*name_plural*/ N_("masks"),
192 /*translation_context*/ BLT_I18NCONTEXT_ID_MASK,
194 /*asset_type_info*/ nullptr,
195
196 /*init_data*/ nullptr,
197 /*copy_data*/ mask_copy_data,
198 /*free_data*/ mask_free_data,
199 /*make_local*/ nullptr,
200 /*foreach_id*/ mask_foreach_id,
201 /*foreach_cache*/ nullptr,
202 /*foreach_path*/ nullptr,
203 /*owner_pointer_get*/ nullptr,
204
205 /*blend_write*/ mask_blend_write,
206 /*blend_read_data*/ mask_blend_read_data,
207 /*blend_read_after_liblink*/ nullptr,
208
209 /*blend_read_undo_preserve*/ nullptr,
210
211 /*lib_override_apply_post*/ nullptr,
212};
213
214static struct {
217} mask_clipboard = {{nullptr}};
218
220 MaskSplinePoint *points_array,
221 MaskSplinePoint *point)
222{
223 if (point == &points_array[spline->tot_point - 1]) {
224 if (spline->flag & MASK_SPLINE_CYCLIC) {
225 return &points_array[0];
226 }
227
228 return nullptr;
229 }
230
231 return point + 1;
232}
233
235 MaskSplinePoint *points_array,
236 MaskSplinePoint *point)
237{
238 if (point == points_array) {
239 if (spline->flag & MASK_SPLINE_CYCLIC) {
240 return &points_array[spline->tot_point - 1];
241 }
242
243 return nullptr;
244 }
245
246 return point - 1;
247}
248
250 MaskSplinePoint *points_array,
251 MaskSplinePoint *point)
252{
253 if (point == &points_array[spline->tot_point - 1]) {
254 if (spline->flag & MASK_SPLINE_CYCLIC) {
255 return &(points_array[0].bezt);
256 }
257
258 return nullptr;
259 }
260
261 return &(point + 1)->bezt;
262}
263
265{
266 return spline->points_deform ? spline->points_deform : spline->points;
267}
268
270 const MaskSplinePoint *point_ref)
271{
272 if ((point_ref >= spline->points) && (point_ref < &spline->points[spline->tot_point])) {
273 return spline->points;
274 }
275
276 if ((point_ref >= spline->points_deform) &&
277 (point_ref < &spline->points_deform[spline->tot_point]))
278 {
279 return spline->points_deform;
280 }
281
282 BLI_assert_msg(0, "wrong array");
283 return nullptr;
284}
285
286/* mask layers */
287
289{
290 MaskLayer *masklay = MEM_callocN<MaskLayer>(__func__);
291
292 STRNCPY(masklay->name, name && name[0] ? name : DATA_("MaskLayer"));
293
294 BLI_addtail(&mask->masklayers, masklay);
295
297
298 mask->masklay_tot++;
299
300 masklay->blend = MASK_BLEND_MERGE_ADD;
301 masklay->alpha = 1.0f;
303
304 return masklay;
305}
306
308{
309 return static_cast<MaskLayer *>(BLI_findlink(&mask->masklayers, mask->masklay_act));
310}
311
313{
314 mask->masklay_act = BLI_findindex(&mask->masklayers, masklay);
315}
316
318{
319 BLI_remlink(&mask->masklayers, masklay);
320 BKE_mask_layer_free(masklay);
321
322 mask->masklay_tot--;
323
324 if (mask->masklay_act >= mask->masklay_tot) {
325 mask->masklay_act = mask->masklay_tot - 1;
326 }
327}
328
330{
331 BLI_uniquename(&mask->masklayers,
332 masklay,
333 DATA_("MaskLayer"),
334 '.',
335 offsetof(MaskLayer, name),
336 sizeof(masklay->name));
337}
338
340 MaskLayer *masklay,
341 const char *oldname,
342 const char *newname)
343{
344 STRNCPY(masklay->name, newname);
345
347
348 /* now fix animation paths */
349 BKE_animdata_fix_paths_rename_all(&mask->id, "layers", oldname, masklay->name);
350}
351
353{
354 MaskLayer *masklay_new = MEM_callocN<MaskLayer>("new mask layer");
355
356 STRNCPY(masklay_new->name, masklay->name);
357
358 masklay_new->alpha = masklay->alpha;
359 masklay_new->blend = masklay->blend;
360 masklay_new->blend_flag = masklay->blend_flag;
361 masklay_new->flag = masklay->flag;
362 masklay_new->falloff = masklay->falloff;
363 masklay_new->visibility_flag = masklay->visibility_flag;
364
365 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
366 MaskSpline *spline_new = BKE_mask_spline_copy(spline);
367
368 BLI_addtail(&masklay_new->splines, spline_new);
369
370 if (spline == masklay->act_spline) {
371 masklay_new->act_spline = spline_new;
372 }
373
374 if (masklay->act_point >= spline->points &&
375 masklay->act_point < spline->points + spline->tot_point)
376 {
377 const size_t point_index = masklay->act_point - spline->points;
378 masklay_new->act_point = spline_new->points + point_index;
379 }
380 }
381
382 /* correct animation */
383 if (masklay->splines_shapes.first) {
384 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
385 MaskLayerShape *masklay_shape_new = MEM_callocN<MaskLayerShape>("new mask layer shape");
386
387 masklay_shape_new->data = static_cast<float *>(MEM_dupallocN(masklay_shape->data));
388 masklay_shape_new->tot_vert = masklay_shape->tot_vert;
389 masklay_shape_new->flag = masklay_shape->flag;
390 masklay_shape_new->frame = masklay_shape->frame;
391
392 BLI_addtail(&masklay_new->splines_shapes, masklay_shape_new);
393 }
394 }
395
396 return masklay_new;
397}
398
399void BKE_mask_layer_copy_list(ListBase *masklayers_new, const ListBase *masklayers)
400{
401 LISTBASE_FOREACH (MaskLayer *, layer, masklayers) {
402 MaskLayer *layer_new = BKE_mask_layer_copy(layer);
403
404 BLI_addtail(masklayers_new, layer_new);
405 }
406}
407
408/* splines */
409
411{
412 MaskSpline *spline = MEM_callocN<MaskSpline>("new mask spline");
413
414 BLI_addtail(&masklay->splines, spline);
415
416 /* spline shall have one point at least */
417 spline->points = MEM_callocN<MaskSplinePoint>("new mask spline point");
418 spline->tot_point = 1;
419
420 /* cyclic shapes are more usually used */
421 /* Disable because its not so nice for drawing. could be done differently. */
422#if 0
423 spline->flag |= MASK_SPLINE_CYCLIC;
424#endif
425
427
429
430 return spline;
431}
432
434{
435 if (BLI_remlink_safe(&mask_layer->splines, spline) == false) {
436 return false;
437 }
438
439 BKE_mask_spline_free(spline);
440
441 return true;
442}
443
445{
446 const int tot_uw = point->tot_uw;
447 const int tot_uw_half = tot_uw / 2;
448
449 float co_tmp[2];
450
451 /* swap handles */
452 copy_v2_v2(co_tmp, point->bezt.vec[0]);
453 copy_v2_v2(point->bezt.vec[0], point->bezt.vec[2]);
454 copy_v2_v2(point->bezt.vec[2], co_tmp);
455 /* in this case the flags are unlikely to be different but swap anyway */
456 std::swap(point->bezt.f1, point->bezt.f3);
457 std::swap(point->bezt.h1, point->bezt.h2);
458
459 /* swap UW's */
460 if (tot_uw > 1) {
461 /* count */
462 for (int i = 0; i < tot_uw_half; i++) {
463 MaskSplinePointUW *uw_a = &point->uw[i];
464 MaskSplinePointUW *uw_b = &point->uw[tot_uw - (i + 1)];
465 std::swap(*uw_a, *uw_b);
466 }
467 }
468
469 for (int i = 0; i < tot_uw; i++) {
470 MaskSplinePointUW *uw = &point->uw[i];
471 uw->u = 1.0f - uw->u;
472 }
473}
474
476{
477 const int tot_point = spline->tot_point;
478 const int tot_point_half = tot_point / 2;
479 int i, i_prev;
480
481 if (tot_point < 2) {
482 return;
483 }
484
485 /* count */
486 for (i = 0; i < tot_point_half; i++) {
487 MaskSplinePoint *point_a = &spline->points[i];
488 MaskSplinePoint *point_b = &spline->points[tot_point - (i + 1)];
489 std::swap(*point_a, *point_b);
490 }
491
492 /* correct UW's */
493 i_prev = tot_point - 1;
494 for (i = 0; i < tot_point; i++) {
495
497
498 std::swap(spline->points[i].uw, spline->points[i_prev].uw);
499 std::swap(spline->points[i].tot_uw, spline->points[i_prev].tot_uw);
500
501 i_prev = i;
502 }
503
504 /* correct animation */
505 if (masklay->splines_shapes.first) {
506 const int spline_index = BKE_mask_layer_shape_spline_to_index(masklay, spline);
507
508 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
509 MaskLayerShapeElem *fp_arr = (MaskLayerShapeElem *)masklay_shape->data;
510
511 for (i = 0; i < tot_point_half; i++) {
512 MaskLayerShapeElem *fp_a = &fp_arr[spline_index + (i)];
513 MaskLayerShapeElem *fp_b = &fp_arr[spline_index + (tot_point - (i + 1))];
514 std::swap(*fp_a, *fp_b);
515 }
516 }
517 }
518}
519
521 MaskSplinePoint *point,
522 float start_u,
523 const float co[2],
524 const eMaskSign sign)
525{
526 const float proj_eps = 1e-3;
527 const float proj_eps_sq = proj_eps * proj_eps;
528 const int N = 1000;
529 float u = -1.0f, du = 1.0f / N, u1 = start_u, u2 = start_u;
530 float ang = -1.0f;
531
532 BLI_assert(abs(sign) <= 1); /* (-1, 0, 1) */
533
534 while (u1 > 0.0f || u2 < 1.0f) {
535 float n1[2], n2[2], co1[2], co2[2];
536 float v1[2], v2[2];
537 float ang1, ang2;
538
539 if (u1 >= 0.0f) {
540 BKE_mask_point_segment_co(spline, point, u1, co1);
541 BKE_mask_point_normal(spline, point, u1, n1);
542 sub_v2_v2v2(v1, co, co1);
543
544 if ((sign == MASK_PROJ_ANY) || ((sign == MASK_PROJ_NEG) && (dot_v2v2(v1, n1) <= 0.0f)) ||
545 ((sign == MASK_PROJ_POS) && (dot_v2v2(v1, n1) >= 0.0f)))
546 {
547
548 if (len_squared_v2(v1) > proj_eps_sq) {
549 ang1 = angle_v2v2(v1, n1);
550 if (ang1 > float(M_PI_2)) {
551 ang1 = float(M_PI) - ang1;
552 }
553
554 if (ang < 0.0f || ang1 < ang) {
555 ang = ang1;
556 u = u1;
557 }
558 }
559 else {
560 u = u1;
561 break;
562 }
563 }
564 }
565
566 if (u2 <= 1.0f) {
567 BKE_mask_point_segment_co(spline, point, u2, co2);
568 BKE_mask_point_normal(spline, point, u2, n2);
569 sub_v2_v2v2(v2, co, co2);
570
571 if ((sign == MASK_PROJ_ANY) || ((sign == MASK_PROJ_NEG) && (dot_v2v2(v2, n2) <= 0.0f)) ||
572 ((sign == MASK_PROJ_POS) && (dot_v2v2(v2, n2) >= 0.0f)))
573 {
574
575 if (len_squared_v2(v2) > proj_eps_sq) {
576 ang2 = angle_v2v2(v2, n2);
577 if (ang2 > float(M_PI_2)) {
578 ang2 = float(M_PI) - ang2;
579 }
580
581 if (ang2 < ang) {
582 ang = ang2;
583 u = u2;
584 }
585 }
586 else {
587 u = u2;
588 break;
589 }
590 }
591 }
592
593 u1 -= du;
594 u2 += du;
595 }
596
597 return u;
598}
599
600/* point */
601
603{
604 const BezTriple *bezt = &point->bezt;
605
606 if (bezt->h1 == bezt->h2 && bezt->h1 == HD_ALIGN) {
608 }
609
611}
612
614 eMaskWhichHandle which_handle,
615 float r_handle[2])
616{
617 const BezTriple *bezt = &point->bezt;
618
619 if (which_handle == MASK_WHICH_HANDLE_STICK) {
620 float vec[2];
621
622 sub_v2_v2v2(vec, bezt->vec[0], bezt->vec[1]);
623
624 r_handle[0] = (bezt->vec[1][0] + vec[1]);
625 r_handle[1] = (bezt->vec[1][1] - vec[0]);
626 }
627 else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
628 copy_v2_v2(r_handle, bezt->vec[0]);
629 }
630 else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
631 copy_v2_v2(r_handle, bezt->vec[2]);
632 }
633 else {
634 BLI_assert_msg(0, "Unknown handle passed to BKE_mask_point_handle");
635 }
636}
637
639 eMaskWhichHandle which_handle,
640 float loc[2],
641 bool keep_direction,
642 float orig_handle[2],
643 float orig_vec[3][3])
644{
645 BezTriple *bezt = &point->bezt;
646
647 if (which_handle == MASK_WHICH_HANDLE_STICK) {
648 float v1[2], v2[2], vec[2];
649 if (keep_direction) {
650 sub_v2_v2v2(v1, loc, orig_vec[1]);
651 sub_v2_v2v2(v2, orig_handle, orig_vec[1]);
652
653 project_v2_v2v2(vec, v1, v2);
654
655 if (dot_v2v2(v2, vec) > 0) {
656 float len = len_v2(vec);
657
658 sub_v2_v2v2(v1, orig_vec[0], orig_vec[1]);
659
660 mul_v2_fl(v1, len / len_v2(v1));
661
662 add_v2_v2v2(bezt->vec[0], bezt->vec[1], v1);
663 sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v1);
664 }
665 else {
666 copy_v3_v3(bezt->vec[0], bezt->vec[1]);
667 copy_v3_v3(bezt->vec[2], bezt->vec[1]);
668 }
669 }
670 else {
671 sub_v2_v2v2(v1, loc, bezt->vec[1]);
672
673 v2[0] = -v1[1];
674 v2[1] = v1[0];
675
676 add_v2_v2v2(bezt->vec[0], bezt->vec[1], v2);
677 sub_v2_v2v2(bezt->vec[2], bezt->vec[1], v2);
678 }
679 }
680 else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
681 copy_v2_v2(bezt->vec[0], loc);
682 }
683 else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
684 copy_v2_v2(bezt->vec[2], loc);
685 }
686 else {
687 BLI_assert_msg(0, "unknown handle passed to BKE_mask_point_set_handle");
688 }
689}
690
691void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2])
692{
693 MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
694
695 BezTriple *bezt = &point->bezt, *bezt_next;
696
697 bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
698
699 if (!bezt_next) {
700 copy_v2_v2(co, bezt->vec[1]);
701 return;
702 }
703
705 co, bezt->vec[1], bezt->vec[2], bezt_next->vec[0], bezt_next->vec[1], u);
706}
707
708BLI_INLINE void orthogonal_direction_get(const float vec[2], float result[2])
709{
710 result[0] = -vec[1];
711 result[1] = vec[0];
713}
714
715void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2])
716{
717 /* TODO(sergey): This function will re-calculate loads of stuff again and again
718 * when differentiating feather points. This might be easily cached
719 * in the callee function for this case. */
720
721 MaskSplinePoint *point_prev, *point_next;
722
723 /* TODO(sergey): This actually depends on a resolution. */
724 const float du = 0.05f;
725
726 BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next);
727
728 if (u - du < 0.0f && point_prev == nullptr) {
729 float co[2], dir[2];
730 BKE_mask_point_segment_co(spline, point, u + du, co);
731 sub_v2_v2v2(dir, co, point->bezt.vec[1]);
733 }
734 else if (u + du > 1.0f && point_next == nullptr) {
735 float co[2], dir[2];
736 BKE_mask_point_segment_co(spline, point, u - du, co);
737 sub_v2_v2v2(dir, point->bezt.vec[1], co);
739 }
740 else {
741 float prev_co[2], next_co[2], co[2];
742 float dir1[2], dir2[2], dir[2];
743
744 if (u - du < 0.0f) {
745 BKE_mask_point_segment_co(spline, point_prev, 1.0f + (u - du), prev_co);
746 }
747 else {
748 BKE_mask_point_segment_co(spline, point, u - du, prev_co);
749 }
750
751 BKE_mask_point_segment_co(spline, point, u, co);
752
753 if (u + du > 1.0f) {
754 BKE_mask_point_segment_co(spline, point_next, u + du - 1.0f, next_co);
755 }
756 else {
757 BKE_mask_point_segment_co(spline, point, u + du, next_co);
758 }
759
760 sub_v2_v2v2(dir1, co, prev_co);
761 sub_v2_v2v2(dir2, next_co, co);
762
763 normalize_v2(dir1);
764 normalize_v2(dir2);
765 add_v2_v2v2(dir, dir1, dir2);
766
768 }
769}
770
771static float mask_point_interp_weight(BezTriple *bezt, BezTriple *bezt_next, const float u)
772{
773 return (bezt->weight * (1.0f - u)) + (bezt_next->weight * u);
774}
775
776float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, const float u)
777{
778 MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
779 BezTriple *bezt = &point->bezt, *bezt_next;
780
781 bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
782
783 if (!bezt_next) {
784 return bezt->weight;
785 }
786 if (u <= 0.0f) {
787 return bezt->weight;
788 }
789 if (u >= 1.0f) {
790 return bezt_next->weight;
791 }
792
793 return mask_point_interp_weight(bezt, bezt_next, u);
794}
795
796float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const float u)
797{
798 MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
799 BezTriple *bezt = &point->bezt, *bezt_next;
800
801 bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
802
803 if (!bezt_next) {
804 return bezt->weight;
805 }
806 if (u <= 0.0f) {
807 return bezt->weight;
808 }
809 if (u >= 1.0f) {
810 return bezt_next->weight;
811 }
812
813 float cur_u = 0.0f, cur_w = 0.0f, next_u = 0.0f, next_w = 0.0f, fac; /* Quite warnings */
814
815 for (int i = 0; i <= point->tot_uw; i++) {
816 if (i == 0) {
817 cur_u = 0.0f;
818 cur_w = 1.0f; /* mask_point_interp_weight will scale it */
819 }
820 else {
821 cur_u = point->uw[i - 1].u;
822 cur_w = point->uw[i - 1].w;
823 }
824
825 if (i == point->tot_uw) {
826 next_u = 1.0f;
827 next_w = 1.0f; /* mask_point_interp_weight will scale it */
828 }
829 else {
830 next_u = point->uw[i].u;
831 next_w = point->uw[i].w;
832 }
833
834 if (u >= cur_u && u <= next_u) {
835 break;
836 }
837 }
838
839 fac = (u - cur_u) / (next_u - cur_u);
840
841 cur_w *= mask_point_interp_weight(bezt, bezt_next, cur_u);
842 next_w *= mask_point_interp_weight(bezt, bezt_next, next_u);
843
844 if (spline->weight_interp == MASK_SPLINE_INTERP_EASE) {
845 return cur_w + (next_w - cur_w) * (3.0f * fac * fac - 2.0f * fac * fac * fac);
846 }
847
848 return (1.0f - fac) * cur_w + fac * next_w;
849}
850
852{
853 if (point->tot_uw > 1) {
854 int idx = uw - point->uw;
855
856 if (idx > 0 && point->uw[idx - 1].u > uw->u) {
857 while (idx > 0 && point->uw[idx - 1].u > point->uw[idx].u) {
858 std::swap(point->uw[idx - 1], point->uw[idx]);
859 idx--;
860 }
861 }
862
863 if (idx < point->tot_uw - 1 && point->uw[idx + 1].u < uw->u) {
864 while (idx < point->tot_uw - 1 && point->uw[idx + 1].u < point->uw[idx].u) {
865 std::swap(point->uw[idx + 1], point->uw[idx]);
866 idx++;
867 }
868 }
869
870 return &point->uw[idx];
871 }
872
873 return uw;
874}
875
876void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w)
877{
878 if (!point->uw) {
879 point->uw = MEM_callocN<MaskSplinePointUW>("mask point uw");
880 }
881 else {
882 point->uw = static_cast<MaskSplinePointUW *>(
883 MEM_reallocN(point->uw, (point->tot_uw + 1) * sizeof(*point->uw)));
884 }
885
886 point->uw[point->tot_uw].u = u;
887 point->uw[point->tot_uw].w = w;
888 point->uw[point->tot_uw].flag = 0;
889
890 point->tot_uw++;
891
892 BKE_mask_point_sort_uw(point, &point->uw[point->tot_uw - 1]);
893}
894
895void BKE_mask_point_select_set(MaskSplinePoint *point, const bool do_select)
896{
897 if (do_select) {
898 MASKPOINT_SEL_ALL(point);
899 }
900 else {
901 MASKPOINT_DESEL_ALL(point);
902 }
903
904 for (int i = 0; i < point->tot_uw; i++) {
905 if (do_select) {
906 point->uw[i].flag |= SELECT;
907 }
908 else {
909 point->uw[i].flag &= ~SELECT;
910 }
911 }
912}
913
915 const eMaskWhichHandle which_handle,
916 const bool do_select)
917{
918 if (do_select) {
920 point->bezt.f1 |= SELECT;
921 point->bezt.f3 |= SELECT;
922 }
923 else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
924 point->bezt.f1 |= SELECT;
925 }
926 else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
927 point->bezt.f3 |= SELECT;
928 }
929 else {
930 BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle");
931 }
932 }
933 else {
935 point->bezt.f1 &= ~SELECT;
936 point->bezt.f3 &= ~SELECT;
937 }
938 else if (which_handle == MASK_WHICH_HANDLE_LEFT) {
939 point->bezt.f1 &= ~SELECT;
940 }
941 else if (which_handle == MASK_WHICH_HANDLE_RIGHT) {
942 point->bezt.f3 &= ~SELECT;
943 }
944 else {
945 BLI_assert_msg(0, "Wrong which_handle passed to BKE_mask_point_select_set_handle");
946 }
947 }
948}
949
950/* only mask block itself */
951static Mask *mask_alloc(Main *bmain, const char *name)
952{
953 Mask *mask = static_cast<Mask *>(BKE_libblock_alloc(bmain, ID_MSK, name, 0));
954
956
957 return mask;
958}
959
960Mask *BKE_mask_new(Main *bmain, const char *name)
961{
962 Mask *mask;
963 char mask_name[MAX_ID_NAME - 2];
964
965 STRNCPY(mask_name, (name && name[0]) ? name : DATA_("Mask"));
966
967 mask = mask_alloc(bmain, mask_name);
968
969 /* arbitrary defaults */
970 mask->sfra = 1;
971 mask->efra = 100;
972
974
975 return mask;
976}
977
979{
980 if (point->uw) {
981 MEM_freeN(point->uw);
982 }
983}
984
986{
987 int i = 0;
988
989 for (i = 0; i < spline->tot_point; i++) {
990 MaskSplinePoint *point;
991 point = &spline->points[i];
992 BKE_mask_point_free(point);
993
994 if (spline->points_deform) {
995 point = &spline->points_deform[i];
996 BKE_mask_point_free(point);
997 }
998 }
999
1000 MEM_freeN(spline->points);
1001
1002 if (spline->points_deform) {
1003 MEM_freeN(spline->points_deform);
1004 }
1005
1006 MEM_freeN(spline);
1007}
1008
1010{
1011 MaskSpline *spline = static_cast<MaskSpline *>(splines->first);
1012 while (spline) {
1013 MaskSpline *next_spline = spline->next;
1014
1015 BLI_remlink(splines, spline);
1016 BKE_mask_spline_free(spline);
1017
1018 spline = next_spline;
1019 }
1020}
1021
1022static MaskSplinePoint *mask_spline_points_copy(const MaskSplinePoint *points, int tot_point)
1023{
1024 MaskSplinePoint *npoints = static_cast<MaskSplinePoint *>(MEM_dupallocN(points));
1025
1026 for (int i = 0; i < tot_point; i++) {
1027 MaskSplinePoint *point = &npoints[i];
1028
1029 if (point->uw) {
1030 point->uw = static_cast<MaskSplinePointUW *>(MEM_dupallocN(point->uw));
1031 }
1032 }
1033
1034 return npoints;
1035}
1036
1038{
1039 MaskSpline *nspline = MEM_callocN<MaskSpline>("new spline");
1040
1041 *nspline = *spline;
1042
1043 nspline->points_deform = nullptr;
1044 nspline->points = mask_spline_points_copy(spline->points, spline->tot_point);
1045
1046 if (spline->points_deform) {
1047 nspline->points_deform = mask_spline_points_copy(spline->points_deform, spline->tot_point);
1048 }
1049
1050 return nspline;
1051}
1052
1054{
1055 MaskLayerShape *masklay_shape;
1056 int tot_vert = BKE_mask_layer_shape_totvert(masklay);
1057
1058 masklay_shape = MEM_callocN<MaskLayerShape>(__func__);
1059 masklay_shape->frame = frame;
1060 masklay_shape->tot_vert = tot_vert;
1061 masklay_shape->data = MEM_calloc_arrayN<float>(tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__);
1062
1063 return masklay_shape;
1064}
1065
1067{
1068 if (masklay_shape->data) {
1069 MEM_freeN(masklay_shape->data);
1070 }
1071
1072 MEM_freeN(masklay_shape);
1073}
1074
1076{
1077 MaskLayerShape *masklay_shape;
1078
1079 /* free animation data */
1080 masklay_shape = static_cast<MaskLayerShape *>(masklay->splines_shapes.first);
1081 while (masklay_shape) {
1082 MaskLayerShape *next_masklay_shape = masklay_shape->next;
1083
1084 BLI_remlink(&masklay->splines_shapes, masklay_shape);
1085 BKE_mask_layer_shape_free(masklay_shape);
1086
1087 masklay_shape = next_masklay_shape;
1088 }
1089}
1090
1092{
1093 /* free splines */
1095
1096 /* free animation data */
1098
1099 MEM_freeN(masklay);
1100}
1101
1103{
1104 MaskLayer *masklay = static_cast<MaskLayer *>(masklayers->first);
1105
1106 while (masklay) {
1107 MaskLayer *masklay_next = masklay->next;
1108
1109 BLI_remlink(masklayers, masklay);
1110 BKE_mask_layer_free(masklay);
1111
1112 masklay = masklay_next;
1113 }
1114}
1115
1116void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2])
1117{
1118 if (frame_size[0] == frame_size[1]) {
1119 r_co[0] = co[0];
1120 r_co[1] = co[1];
1121 }
1122 else if (frame_size[0] < frame_size[1]) {
1123 r_co[0] = ((co[0] - 0.5f) * (frame_size[0] / frame_size[1])) + 0.5f;
1124 r_co[1] = co[1];
1125 }
1126 else { /* (frame_size[0] > frame_size[1]) */
1127 r_co[0] = co[0];
1128 r_co[1] = ((co[1] - 0.5f) * (frame_size[1] / frame_size[0])) + 0.5f;
1129 }
1130}
1131
1133 MovieClipUser *user,
1134 float r_co[2],
1135 const float co[2])
1136{
1137 float aspx, aspy;
1138 float frame_size[2];
1139
1140 /* scaling for the clip */
1141 BKE_movieclip_get_size_fl(clip, user, frame_size);
1142 BKE_movieclip_get_aspect(clip, &aspx, &aspy);
1143
1144 frame_size[1] *= (aspy / aspx);
1145
1146 BKE_mask_coord_from_frame(r_co, co, frame_size);
1147}
1148
1149void BKE_mask_coord_from_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2])
1150{
1151 float aspx, aspy;
1152 float frame_size[2];
1153
1154 BKE_image_get_size_fl(image, iuser, frame_size);
1155 BKE_image_get_aspect(image, &aspx, &aspy);
1156
1157 frame_size[1] *= (aspy / aspx);
1158
1159 BKE_mask_coord_from_frame(r_co, co, frame_size);
1160}
1161
1162void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame_size[2])
1163{
1164 if (frame_size[0] == frame_size[1]) {
1165 r_co[0] = co[0];
1166 r_co[1] = co[1];
1167 }
1168 else if (frame_size[0] < frame_size[1]) {
1169 r_co[0] = ((co[0] - 0.5f) / (frame_size[0] / frame_size[1])) + 0.5f;
1170 r_co[1] = co[1];
1171 }
1172 else { /* (frame_size[0] > frame_size[1]) */
1173 r_co[0] = co[0];
1174 r_co[1] = ((co[1] - 0.5f) / (frame_size[1] / frame_size[0])) + 0.5f;
1175 }
1176}
1177
1179 MovieClipUser *user,
1180 float r_co[2],
1181 const float co[2])
1182{
1183 float aspx, aspy;
1184 float frame_size[2];
1185
1186 /* scaling for the clip */
1187 BKE_movieclip_get_size_fl(clip, user, frame_size);
1188 BKE_movieclip_get_aspect(clip, &aspx, &aspy);
1189
1190 frame_size[1] *= (aspy / aspx);
1191
1192 BKE_mask_coord_to_frame(r_co, co, frame_size);
1193}
1194
1195void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2])
1196{
1197 float aspx, aspy;
1198 float frame_size[2];
1199
1200 /* scaling for the clip */
1201 BKE_image_get_size_fl(image, iuser, frame_size);
1202 BKE_image_get_aspect(image, &aspx, &aspy);
1203
1204 frame_size[1] *= (aspy / aspx);
1205
1206 BKE_mask_coord_to_frame(r_co, co, frame_size);
1207}
1208
1210 float ctime,
1211 float parent_matrix[3][3])
1212{
1213 MaskParent *parent = &point->parent;
1214
1215 unit_m3(parent_matrix);
1216
1217 if (!parent) {
1218 return;
1219 }
1220
1221 if (parent->id_type == ID_MC) {
1222 if (parent->id) {
1223 MovieClip *clip = (MovieClip *)parent->id;
1224 MovieTracking *tracking = (MovieTracking *)&clip->tracking;
1226
1227 if (ob) {
1229 float clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime);
1230 BKE_movieclip_user_set_frame(&user, ctime);
1231
1232 if (parent->type == MASK_PARENT_POINT_TRACK) {
1234 parent->sub_parent);
1235
1236 if (track) {
1237 float marker_position[2], parent_co[2];
1238 BKE_tracking_marker_get_subframe_position(track, clip_framenr, marker_position);
1239 BKE_mask_coord_from_movieclip(clip, &user, parent_co, marker_position);
1240 sub_v2_v2v2(parent_matrix[2], parent_co, parent->parent_orig);
1241 }
1242 }
1243 else /* if (parent->type == MASK_PARENT_PLANE_TRACK) */ {
1245 ob, parent->sub_parent);
1246
1247 if (plane_track) {
1248 float corners[4][2];
1249 float aspx, aspy;
1250 float frame_size[2], H[3][3], mask_from_clip_matrix[3][3], mask_to_clip_matrix[3][3];
1251
1252 BKE_tracking_plane_marker_get_subframe_corners(plane_track, ctime, corners);
1254
1255 unit_m3(mask_from_clip_matrix);
1256
1257 BKE_movieclip_get_size_fl(clip, &user, frame_size);
1258 BKE_movieclip_get_aspect(clip, &aspx, &aspy);
1259
1260 frame_size[1] *= (aspy / aspx);
1261 if (frame_size[0] == frame_size[1]) {
1262 /* pass */
1263 }
1264 else if (frame_size[0] < frame_size[1]) {
1265 mask_from_clip_matrix[0][0] = frame_size[1] / frame_size[0];
1266 mask_from_clip_matrix[2][0] = -0.5f * (frame_size[1] / frame_size[0]) + 0.5f;
1267 }
1268 else { /* (frame_size[0] > frame_size[1]) */
1269 mask_from_clip_matrix[1][1] = frame_size[1] / frame_size[0];
1270 mask_from_clip_matrix[2][1] = -0.5f * (frame_size[1] / frame_size[0]) + 0.5f;
1271 }
1272
1273 invert_m3_m3(mask_to_clip_matrix, mask_from_clip_matrix);
1274 mul_m3_series(parent_matrix, mask_from_clip_matrix, H, mask_to_clip_matrix);
1275 }
1276 }
1277 }
1278 }
1279 }
1280}
1281
1283 MaskSplinePoint *point_prev,
1284 MaskSplinePoint *point_next)
1285{
1286 BezTriple *bezt = &point->bezt;
1287 BezTriple *bezt_prev = nullptr, *bezt_next = nullptr;
1288 // int handle_type = bezt->h1;
1289
1290 if (point_prev) {
1291 bezt_prev = &point_prev->bezt;
1292 }
1293
1294 if (point_next) {
1295 bezt_next = &point_next->bezt;
1296 }
1297
1298#if 1
1299 if (bezt_prev || bezt_next) {
1300 BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, false, 0);
1301 }
1302#else
1303 if (handle_type == HD_VECT) {
1304 BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
1305 }
1306 else if (handle_type == HD_AUTO) {
1307 BKE_nurb_handle_calc(bezt, bezt_prev, bezt_next, 0, 0);
1308 }
1309 else if (ELEM(handle_type, HD_ALIGN, HD_ALIGN_DOUBLESIDE)) {
1310 float v1[3], v2[3];
1311 float vec[3], h[3];
1312
1313 sub_v3_v3v3(v1, bezt->vec[0], bezt->vec[1]);
1314 sub_v3_v3v3(v2, bezt->vec[2], bezt->vec[1]);
1315 add_v3_v3v3(vec, v1, v2);
1316
1317 if (len_squared_v3(vec) > (1e-3f * 1e-3f)) {
1318 h[0] = vec[1];
1319 h[1] = -vec[0];
1320 h[2] = 0.0f;
1321 }
1322 else {
1323 copy_v3_v3(h, v1);
1324 }
1325
1326 add_v3_v3v3(bezt->vec[0], bezt->vec[1], h);
1327 sub_v3_v3v3(bezt->vec[2], bezt->vec[1], h);
1328 }
1329#endif
1330}
1331
1333 MaskSplinePoint *point,
1334 MaskSplinePoint **r_point_prev,
1335 MaskSplinePoint **r_point_next)
1336{
1337 /* TODO: could avoid calling this at such low level. */
1338 MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
1339
1340 *r_point_prev = mask_spline_point_prev(spline, points_array, point);
1341 *r_point_next = mask_spline_point_next(spline, points_array, point);
1342}
1343
1345{
1346 float tvec_a[2], tvec_b[2];
1347
1348 MaskSplinePoint *point_prev, *point_next;
1349
1350 BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next);
1351
1352 if (point_prev) {
1353 sub_v2_v2v2(tvec_a, point->bezt.vec[1], point_prev->bezt.vec[1]);
1354 normalize_v2(tvec_a);
1355 }
1356 else {
1357 zero_v2(tvec_a);
1358 }
1359
1360 if (point_next) {
1361 sub_v2_v2v2(tvec_b, point_next->bezt.vec[1], point->bezt.vec[1]);
1362 normalize_v2(tvec_b);
1363 }
1364 else {
1365 zero_v2(tvec_b);
1366 }
1367
1368 add_v2_v2v2(t, tvec_a, tvec_b);
1369 normalize_v2(t);
1370}
1371
1373{
1374 MaskSplinePoint *point_prev, *point_next;
1375
1376 BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next);
1377
1378 mask_calc_point_handle(point, point_prev, point_next);
1379}
1380
1382 MaskSplinePoint *point,
1383 const float u)
1384{
1385 /* TODO: make this interpolate between siblings - not always midpoint! */
1386 int length_tot = 0;
1387 float length_average = 0.0f;
1388 float weight_average = 0.0f;
1389
1390 MaskSplinePoint *point_prev, *point_next;
1391
1392 BLI_assert(u >= 0.0f && u <= 1.0f);
1393
1394 BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next);
1395
1396 if (point_prev && point_next) {
1397 length_average = ((len_v2v2(point_prev->bezt.vec[0], point_prev->bezt.vec[1]) * (1.0f - u)) +
1398 (len_v2v2(point_next->bezt.vec[2], point_next->bezt.vec[1]) * u));
1399
1400 weight_average = (point_prev->bezt.weight * (1.0f - u) + point_next->bezt.weight * u);
1401 length_tot = 1;
1402 }
1403 else {
1404 if (point_prev) {
1405 length_average += len_v2v2(point_prev->bezt.vec[0], point_prev->bezt.vec[1]);
1406 weight_average += point_prev->bezt.weight;
1407 length_tot++;
1408 }
1409
1410 if (point_next) {
1411 length_average += len_v2v2(point_next->bezt.vec[2], point_next->bezt.vec[1]);
1412 weight_average += point_next->bezt.weight;
1413 length_tot++;
1414 }
1415 }
1416
1417 if (length_tot) {
1418 length_average /= float(length_tot);
1419 weight_average /= float(length_tot);
1420
1421 dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
1422 dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
1423 point->bezt.weight = weight_average;
1424 }
1425}
1426
1428 MaskSplinePoint *point,
1429 const bool do_recalc_length)
1430{
1431 MaskSplinePoint *point_prev, *point_next;
1432 const char h_back[2] = {point->bezt.h1, point->bezt.h2};
1433 const float length_average = (do_recalc_length) ?
1434 0.0f /* dummy value */ :
1435 (len_v3v3(point->bezt.vec[0], point->bezt.vec[1]) +
1436 len_v3v3(point->bezt.vec[1], point->bezt.vec[2])) /
1437 2.0f;
1438
1439 BKE_mask_get_handle_point_adjacent(spline, point, &point_prev, &point_next);
1440
1441 point->bezt.h1 = HD_AUTO;
1442 point->bezt.h2 = HD_AUTO;
1443 mask_calc_point_handle(point, point_prev, point_next);
1444
1445 point->bezt.h1 = h_back[0];
1446 point->bezt.h2 = h_back[1];
1447
1448 /* preserve length by applying it back */
1449 if (do_recalc_length == false) {
1450 dist_ensure_v2_v2fl(point->bezt.vec[0], point->bezt.vec[1], length_average);
1451 dist_ensure_v2_v2fl(point->bezt.vec[2], point->bezt.vec[1], length_average);
1452 }
1453}
1454
1456{
1457 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1458 for (int i = 0; i < spline->tot_point; i++) {
1459 BKE_mask_calc_handle_point(spline, &spline->points[i]);
1460 }
1461 }
1462}
1463
1465{
1466 int allocated_points = (MEM_allocN_len(spline->points_deform) / sizeof(*spline->points_deform));
1467 // printf("SPLINE ALLOC %p %d\n", spline->points_deform, allocated_points);
1468
1469 if (spline->points_deform == nullptr || allocated_points != spline->tot_point) {
1470 // printf("alloc new deform spline\n");
1471
1472 if (spline->points_deform) {
1473 for (int i = 0; i < allocated_points; i++) {
1474 MaskSplinePoint *point = &spline->points_deform[i];
1475 BKE_mask_point_free(point);
1476 }
1477
1478 MEM_freeN(spline->points_deform);
1479 }
1480
1481 spline->points_deform = MEM_calloc_arrayN<MaskSplinePoint>(spline->tot_point, __func__);
1482 }
1483 else {
1484 // printf("alloc spline done\n");
1485 }
1486}
1487
1488void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool do_newframe)
1489{
1490 /* Animation if available. */
1491 if (do_newframe) {
1492 BKE_mask_layer_evaluate_animation(masklay, ctime);
1493 }
1494 /* Update deform. */
1495 BKE_mask_layer_evaluate_deform(masklay, ctime);
1496}
1497
1498void BKE_mask_evaluate(Mask *mask, const float ctime, const bool do_newframe)
1499{
1500 LISTBASE_FOREACH (MaskLayer *, masklay, &mask->masklayers) {
1501 BKE_mask_layer_evaluate(masklay, ctime, do_newframe);
1502 }
1503}
1504
1506{
1507 parent->id_type = ID_MC;
1508}
1509
1510/* *** animation/shape-key implementation ***
1511 * BKE_mask_layer_shape_XXX */
1512
1514{
1515 int tot = 0;
1516
1517 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1518 tot += spline->tot_point;
1519 }
1520
1521 return tot;
1522}
1523
1526{
1527 copy_v2_v2(&fp[0], bezt->vec[0]);
1528 copy_v2_v2(&fp[2], bezt->vec[1]);
1529 copy_v2_v2(&fp[4], bezt->vec[2]);
1530 fp[6] = bezt->weight;
1531 fp[7] = bezt->radius;
1532}
1533
1535 const float fp[MASK_OBJECT_SHAPE_ELEM_SIZE])
1536{
1537 copy_v2_v2(bezt->vec[0], &fp[0]);
1538 copy_v2_v2(bezt->vec[1], &fp[2]);
1539 copy_v2_v2(bezt->vec[2], &fp[4]);
1540 bezt->weight = fp[6];
1541 bezt->radius = fp[7];
1542}
1543
1545{
1546 int tot = BKE_mask_layer_shape_totvert(masklay);
1547
1548 if (masklay_shape->tot_vert == tot) {
1549 float *fp = masklay_shape->data;
1550
1551 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1552 for (int i = 0; i < spline->tot_point; i++) {
1553 mask_layer_shape_from_mask_point(&spline->points[i].bezt, fp);
1555 }
1556 }
1557 }
1558 else {
1559 CLOG_ERROR(&LOG,
1560 "vert mismatch %d != %d (frame %d)",
1561 masklay_shape->tot_vert,
1562 tot,
1563 masklay_shape->frame);
1564 }
1565}
1566
1568{
1569 int tot = BKE_mask_layer_shape_totvert(masklay);
1570
1571 if (masklay_shape->tot_vert == tot) {
1572 float *fp = masklay_shape->data;
1573
1574 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1575 for (int i = 0; i < spline->tot_point; i++) {
1576 mask_layer_shape_to_mask_point(&spline->points[i].bezt, fp);
1578 }
1579 }
1580 }
1581 else {
1582 CLOG_ERROR(&LOG,
1583 "vert mismatch %d != %d (frame %d)",
1584 masklay_shape->tot_vert,
1585 tot,
1586 masklay_shape->frame);
1587 }
1588}
1589
1591 float target[2], const float a[2], const float b[2], const float t, const float s)
1592{
1593 target[0] = s * a[0] + t * b[0];
1594 target[1] = s * a[1] + t * b[1];
1595}
1596
1598 MaskLayerShape *masklay_shape_a,
1599 MaskLayerShape *masklay_shape_b,
1600 const float fac)
1601{
1602 int tot = BKE_mask_layer_shape_totvert(masklay);
1603 if (masklay_shape_a->tot_vert == tot && masklay_shape_b->tot_vert == tot) {
1604 const float *fp_a = masklay_shape_a->data;
1605 const float *fp_b = masklay_shape_b->data;
1606 const float ifac = 1.0f - fac;
1607
1608 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1609 for (int i = 0; i < spline->tot_point; i++) {
1610 BezTriple *bezt = &spline->points[i].bezt;
1611 /* *** BKE_mask_layer_shape_from_mask - swapped *** */
1612 interp_v2_v2v2_flfl(bezt->vec[0], fp_a, fp_b, fac, ifac);
1613 fp_a += 2;
1614 fp_b += 2;
1615 interp_v2_v2v2_flfl(bezt->vec[1], fp_a, fp_b, fac, ifac);
1616 fp_a += 2;
1617 fp_b += 2;
1618 interp_v2_v2v2_flfl(bezt->vec[2], fp_a, fp_b, fac, ifac);
1619 fp_a += 2;
1620 fp_b += 2;
1621 bezt->weight = (fp_a[0] * ifac) + (fp_b[0] * fac);
1622 bezt->radius = (fp_a[1] * ifac) + (fp_b[1] * fac);
1623 fp_a += 2;
1624 fp_b += 2;
1625 }
1626 }
1627 }
1628 else {
1629 CLOG_ERROR(&LOG,
1630 "vert mismatch %d != %d != %d (frame %d - %d)",
1631 masklay_shape_a->tot_vert,
1632 masklay_shape_b->tot_vert,
1633 tot,
1634 masklay_shape_a->frame,
1635 masklay_shape_b->frame);
1636 }
1637}
1638
1640{
1641 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
1642 if (frame == masklay_shape->frame) {
1643 return masklay_shape;
1644 }
1645 if (frame < masklay_shape->frame) {
1646 break;
1647 }
1648 }
1649
1650 return nullptr;
1651}
1652
1654 const float frame,
1655 MaskLayerShape **r_masklay_shape_a,
1656 MaskLayerShape **r_masklay_shape_b)
1657{
1658 MaskLayerShape *masklay_shape;
1659
1660 for (masklay_shape = static_cast<MaskLayerShape *>(masklay->splines_shapes.first); masklay_shape;
1661 masklay_shape = masklay_shape->next)
1662 {
1663 if (frame == masklay_shape->frame) {
1664 *r_masklay_shape_a = masklay_shape;
1665 *r_masklay_shape_b = nullptr;
1666 return 1;
1667 }
1668 if (frame < masklay_shape->frame) {
1669 if (masklay_shape->prev) {
1670 *r_masklay_shape_a = masklay_shape->prev;
1671 *r_masklay_shape_b = masklay_shape;
1672 return 2;
1673 }
1674
1675 *r_masklay_shape_a = masklay_shape;
1676 *r_masklay_shape_b = nullptr;
1677 return 1;
1678 }
1679 }
1680
1681 masklay_shape = static_cast<MaskLayerShape *>(masklay->splines_shapes.last);
1682 if (masklay_shape) {
1683 *r_masklay_shape_a = masklay_shape;
1684 *r_masklay_shape_b = nullptr;
1685 return 1;
1686 }
1687
1688 *r_masklay_shape_a = nullptr;
1689 *r_masklay_shape_b = nullptr;
1690
1691 return 0;
1692}
1693
1695{
1696 MaskLayerShape *masklay_shape;
1697
1698 masklay_shape = BKE_mask_layer_shape_find_frame(masklay, frame);
1699
1700 if (masklay_shape == nullptr) {
1701 masklay_shape = BKE_mask_layer_shape_alloc(masklay, frame);
1702 BLI_addtail(&masklay->splines_shapes, masklay_shape);
1704 }
1705
1706 return masklay_shape;
1707}
1708
1710{
1711 MaskLayerShape *masklay_shape_copy = static_cast<MaskLayerShape *>(MEM_dupallocN(masklay_shape));
1712
1713 if (LIKELY(masklay_shape_copy->data)) {
1714 masklay_shape_copy->data = static_cast<float *>(MEM_dupallocN(masklay_shape_copy->data));
1715 }
1716
1717 return masklay_shape_copy;
1718}
1719
1721{
1722 BLI_remlink(&masklay->splines_shapes, masklay_shape);
1723
1724 BKE_mask_layer_shape_free(masklay_shape);
1725}
1726
1727static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr,
1728 const void *masklay_shape_b_ptr)
1729{
1730 const MaskLayerShape *masklay_shape_a = static_cast<const MaskLayerShape *>(masklay_shape_a_ptr);
1731 const MaskLayerShape *masklay_shape_b = static_cast<const MaskLayerShape *>(masklay_shape_b_ptr);
1732
1733 if (masklay_shape_a->frame < masklay_shape_b->frame) {
1734 return -1;
1735 }
1736 if (masklay_shape_a->frame > masklay_shape_b->frame) {
1737 return 1;
1738 }
1739
1740 return 0;
1741}
1742
1747
1749 int index,
1750 MaskSpline **r_masklay_shape,
1751 int *r_index)
1752{
1753 LISTBASE_FOREACH (MaskSpline *, spline, &masklay->splines) {
1754 if (index < spline->tot_point) {
1755 *r_masklay_shape = spline;
1756 *r_index = index;
1757 return true;
1758 }
1759 index -= spline->tot_point;
1760 }
1761
1762 return false;
1763}
1764
1766{
1767 MaskSpline *spline_iter;
1768 int i_abs = 0;
1769 for (spline_iter = static_cast<MaskSpline *>(masklay->splines.first);
1770 spline_iter && spline_iter != spline;
1771 i_abs += spline_iter->tot_point, spline_iter = spline_iter->next)
1772 {
1773 /* pass */
1774 }
1775
1776 return i_abs;
1777}
1778
1779/* basic 2D interpolation functions, could make more comprehensive later */
1780static void interp_weights_uv_v2_calc(float r_uv[2],
1781 const float pt[2],
1782 const float pt_a[2],
1783 const float pt_b[2])
1784{
1785 const float segment_len = len_v2v2(pt_a, pt_b);
1786 if (segment_len == 0.0f) {
1787 r_uv[0] = 1.0f;
1788 r_uv[1] = 0.0f;
1789 return;
1790 }
1791
1792 float pt_on_line[2];
1793 r_uv[0] = closest_to_line_v2(pt_on_line, pt, pt_a, pt_b);
1794
1795 r_uv[1] = (len_v2v2(pt_on_line, pt) / segment_len) *
1796 /* This line only sets the sign. */
1797 ((line_point_side_v2(pt_a, pt_b, pt) < 0.0f) ? -1.0f : 1.0f);
1798}
1799
1800static void interp_weights_uv_v2_apply(const float uv[2],
1801 float r_pt[2],
1802 const float pt_a[2],
1803 const float pt_b[2])
1804{
1805 const float dvec[2] = {pt_b[0] - pt_a[0], pt_b[1] - pt_a[1]};
1806
1807 /* u */
1808 madd_v2_v2v2fl(r_pt, pt_a, dvec, uv[0]);
1809
1810 /* v */
1811 r_pt[0] += -dvec[1] * uv[1];
1812 r_pt[1] += dvec[0] * uv[1];
1813}
1814
1816 int index,
1817 bool do_init,
1818 bool do_init_interpolate)
1819{
1820 /* spline index from masklay */
1821 MaskSpline *spline;
1822 int spline_point_index;
1823
1824 if (BKE_mask_layer_shape_spline_from_index(masklay, index, &spline, &spline_point_index)) {
1825 /* sanity check */
1826 /* The point has already been removed in this array
1827 * so subtract one when comparing with the shapes. */
1828 int tot = BKE_mask_layer_shape_totvert(masklay) - 1;
1829
1830 /* for interpolation */
1831 /* TODO: assumes closed curve for now. */
1832 float uv[3][2]; /* 3x 2D handles */
1833 const int pi_curr = spline_point_index;
1834 const int pi_prev = ((spline_point_index - 1) + spline->tot_point) % spline->tot_point;
1835 const int pi_next = (spline_point_index + 1) % spline->tot_point;
1836
1837 const int index_offset = index - spline_point_index;
1838 // const int pi_curr_abs = index;
1839 const int pi_prev_abs = pi_prev + index_offset;
1840 const int pi_next_abs = pi_next + index_offset;
1841
1842 if (do_init_interpolate) {
1843 for (int i = 0; i < 3; i++) {
1845 spline->points[pi_curr].bezt.vec[i],
1846 spline->points[pi_prev].bezt.vec[i],
1847 spline->points[pi_next].bezt.vec[i]);
1848 }
1849 }
1850
1851 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
1852 if (tot == masklay_shape->tot_vert) {
1853 float *data_resized;
1854
1855 masklay_shape->tot_vert++;
1856 data_resized = MEM_calloc_arrayN<float>(
1857 masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__);
1858 if (index > 0) {
1859 memcpy(data_resized,
1860 masklay_shape->data,
1861 index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE);
1862 }
1863
1864 if (index != masklay_shape->tot_vert - 1) {
1865 memcpy(&data_resized[(index + 1) * MASK_OBJECT_SHAPE_ELEM_SIZE],
1866 masklay_shape->data + (index * MASK_OBJECT_SHAPE_ELEM_SIZE),
1867 (masklay_shape->tot_vert - (index + 1)) * sizeof(float) *
1869 }
1870
1871 if (do_init) {
1872 float *fp = &data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE];
1873
1874 mask_layer_shape_from_mask_point(&spline->points[spline_point_index].bezt, fp);
1875
1876 if (do_init_interpolate && spline->tot_point > 2) {
1877 for (int i = 0; i < 3; i++) {
1879 uv[i],
1880 &fp[i * 2],
1881 &data_resized[(pi_prev_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)],
1882 &data_resized[(pi_next_abs * MASK_OBJECT_SHAPE_ELEM_SIZE) + (i * 2)]);
1883 }
1884 }
1885 }
1886 else {
1887 memset(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE],
1888 0,
1889 sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE);
1890 }
1891
1892 MEM_freeN(masklay_shape->data);
1893 masklay_shape->data = data_resized;
1894 }
1895 else {
1896 CLOG_ERROR(&LOG,
1897 "vert mismatch %d != %d (frame %d)",
1898 masklay_shape->tot_vert,
1899 tot,
1900 masklay_shape->frame);
1901 }
1902 }
1903 }
1904}
1905
1907{
1908 /* the point has already been removed in this array so add one when comparing with the shapes */
1909 int tot = BKE_mask_layer_shape_totvert(masklay);
1910
1911 LISTBASE_FOREACH (MaskLayerShape *, masklay_shape, &masklay->splines_shapes) {
1912 if (tot == masklay_shape->tot_vert - count) {
1913 float *data_resized;
1914
1915 masklay_shape->tot_vert -= count;
1916 data_resized = MEM_calloc_arrayN<float>(
1917 masklay_shape->tot_vert * MASK_OBJECT_SHAPE_ELEM_SIZE, __func__);
1918 if (index > 0) {
1919 memcpy(data_resized,
1920 masklay_shape->data,
1921 index * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE);
1922 }
1923
1924 if (index != masklay_shape->tot_vert) {
1925 memcpy(&data_resized[index * MASK_OBJECT_SHAPE_ELEM_SIZE],
1926 masklay_shape->data + ((index + count) * MASK_OBJECT_SHAPE_ELEM_SIZE),
1927 (masklay_shape->tot_vert - index) * sizeof(float) * MASK_OBJECT_SHAPE_ELEM_SIZE);
1928 }
1929
1930 MEM_freeN(masklay_shape->data);
1931 masklay_shape->data = data_resized;
1932 }
1933 else {
1934 CLOG_ERROR(&LOG,
1935 "vert mismatch %d != %d (frame %d)",
1936 masklay_shape->tot_vert - count,
1937 tot,
1938 masklay_shape->frame);
1939 }
1940 }
1941}
1942
1944{
1945 return max_ii(1, mask->efra - mask->sfra);
1946}
1947
1948/*********************** clipboard *************************/
1949
1950static void mask_clipboard_free_ex(bool final_free)
1951{
1954 if (mask_clipboard.id_hash) {
1955 if (final_free) {
1956 BLI_ghash_free(mask_clipboard.id_hash, nullptr, MEM_freeN);
1957 }
1958 else {
1959 BLI_ghash_clear(mask_clipboard.id_hash, nullptr, MEM_freeN);
1960 }
1961 }
1962}
1963
1968
1970{
1971 /* Nothing to do if selection if disabled for the given layer. */
1972 if (mask_layer->visibility_flag & MASK_HIDE_SELECT) {
1973 return;
1974 }
1975
1977 if (mask_clipboard.id_hash == nullptr) {
1978 mask_clipboard.id_hash = BLI_ghash_ptr_new("mask clipboard ID hash");
1979 }
1980
1981 LISTBASE_FOREACH (MaskSpline *, spline, &mask_layer->splines) {
1982 if (spline->flag & SELECT) {
1983 MaskSpline *spline_new = BKE_mask_spline_copy(spline);
1984 for (int i = 0; i < spline_new->tot_point; i++) {
1985 MaskSplinePoint *point = &spline_new->points[i];
1986 if (point->parent.id) {
1987 if (!BLI_ghash_lookup(mask_clipboard.id_hash, point->parent.id)) {
1988 int len = strlen(point->parent.id->name);
1989 char *name_copy = MEM_malloc_arrayN<char>(size_t(len) + 1, "mask clipboard ID name");
1990 memcpy(name_copy, point->parent.id->name, len + 1);
1991 BLI_ghash_insert(mask_clipboard.id_hash, point->parent.id, name_copy);
1992 }
1993 }
1994 }
1995
1996 BLI_addtail(&mask_clipboard.splines, spline_new);
1997 }
1998 }
1999}
2000
2002{
2003 return BLI_listbase_is_empty(&mask_clipboard.splines);
2004}
2005
2007{
2008 LISTBASE_FOREACH (MaskSpline *, spline, &mask_clipboard.splines) {
2009 MaskSpline *spline_new = BKE_mask_spline_copy(spline);
2010
2011 for (int i = 0; i < spline_new->tot_point; i++) {
2012 MaskSplinePoint *point = &spline_new->points[i];
2013 if (point->parent.id) {
2014 const char *id_name = static_cast<const char *>(
2015 BLI_ghash_lookup(mask_clipboard.id_hash, point->parent.id));
2016 ListBase *listbase;
2017
2018 BLI_assert(id_name != nullptr);
2019
2020 listbase = which_libbase(bmain, GS(id_name));
2021 point->parent.id = static_cast<ID *>(
2022 BLI_findstring(listbase, id_name + 2, offsetof(ID, name) + 2));
2023 }
2024 }
2025
2026 BLI_addtail(&mask_layer->splines, spline_new);
2027 }
2028}
void BKE_animdata_fix_paths_rename_all(struct ID *ref_id, const char *prefix, const char *oldName, const char *newName)
void BKE_nurb_handle_calc(BezTriple *bezt, BezTriple *prev, BezTriple *next, bool is_fcurve, char smoothing)
Definition curve.cc:3944
IDTypeInfo IDType_ID_MSK
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:44
void BKE_image_get_size_fl(Image *image, ImageUser *iuser, float r_size[2])
void BKE_image_get_aspect(Image *image, float *r_aspx, float *r_aspy)
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1428
void id_fake_user_set(ID *id)
Definition lib_id.cc:391
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
@ IDWALK_CB_USER
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
ListBase * which_libbase(Main *bmain, short type)
Definition main.cc:887
eMaskhandleMode
Definition BKE_mask.h:36
@ MASK_HANDLE_MODE_INDIVIDUAL_HANDLES
Definition BKE_mask.h:38
@ MASK_HANDLE_MODE_STICK
Definition BKE_mask.h:37
void BKE_mask_layer_evaluate_deform(struct MaskLayer *masklay, float ctime)
eMaskWhichHandle
Definition BKE_mask.h:28
@ MASK_WHICH_HANDLE_BOTH
Definition BKE_mask.h:33
@ 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
#define MASKPOINT_SEL_ALL(p)
Definition BKE_mask.h:301
eMaskSign
Definition BKE_mask.h:90
@ MASK_PROJ_ANY
Definition BKE_mask.h:92
@ MASK_PROJ_NEG
Definition BKE_mask.h:91
@ MASK_PROJ_POS
Definition BKE_mask.h:93
#define MASKPOINT_DESEL_ALL(p)
Definition BKE_mask.h:308
void BKE_mask_layer_evaluate_animation(struct MaskLayer *masklay, float ctime)
void BKE_movieclip_get_aspect(struct MovieClip *clip, float *aspx, float *aspy)
float BKE_movieclip_remap_scene_to_clip_frame(const struct MovieClip *clip, float framenr)
void BKE_movieclip_user_set_frame(struct MovieClipUser *user, int framenr)
void BKE_movieclip_get_size_fl(struct MovieClip *clip, const struct MovieClipUser *user, float r_size[2])
struct MovieTrackingPlaneTrack * BKE_tracking_object_find_plane_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:2004
struct MovieTrackingObject * BKE_tracking_object_get_named(struct MovieTracking *tracking, const char *name)
Definition tracking.cc:1965
void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track, float framenr, float corners[4][2])
Definition tracking.cc:1865
struct MovieTrackingTrack * BKE_tracking_object_find_track_with_name(struct MovieTrackingObject *tracking_object, const char *name)
Definition tracking.cc:1992
void BKE_tracking_marker_get_subframe_position(struct MovieTrackingTrack *track, float framenr, float pos[2])
Definition tracking.cc:1506
void BKE_tracking_homography_between_two_quads(float reference_corners[4][2], float corners[4][2], float H[3][3])
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define BLI_INLINE
void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:855
GHash * BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
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 void BLI_listbase_clear(ListBase *lb)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
bool BLI_remlink_safe(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:154
MINLINE int max_ii(int a, int b)
#define M_PI_2
#define M_PI
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
void unit_m3(float m[3][3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
#define mul_m3_series(...)
MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v2_v2v2fl(float r[2], const float a[2], const float b[2], float f)
float angle_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
void interp_v2_v2v2v2v2_cubic(float p[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2], float u)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float len_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void mul_v2_fl(float r[2], float f)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void dist_ensure_v2_v2fl(float v1[2], const float v2[2], float dist)
MINLINE void copy_v3_v3(float r[3], const float a[3])
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 line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v2(float n[2])
void project_v2_v2v2(float out[2], const float p[2], const float v_proj[2])
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
#define ELEM(...)
#define LIKELY(x)
void BLO_write_float_array(BlendWriter *writer, int64_t num, const float *data_ptr)
void BLO_read_float_array(BlendDataReader *reader, int64_t array_size, float **ptr_p)
Definition readfile.cc:5326
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_write_struct_array(writer, struct_name, array_size, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct_array(reader, struct_name, array_size, ptr_p)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define DATA_(msgid)
#define BLT_I18NCONTEXT_ID_MASK
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
void DEG_relations_tag_update(Main *bmain)
@ INDEX_ID_MSK
Definition DNA_ID.h:1215
@ ID_MC
@ ID_MSK
@ HD_VECT
@ HD_AUTO
@ HD_ALIGN_DOUBLESIDE
@ HD_ALIGN
#define DNA_struct_default_get(struct_name)
@ MASK_SPLINE_CYCLIC
@ MASK_HIDE_SELECT
#define MASK_OBJECT_SHAPE_ELEM_SIZE
@ MASK_BLEND_MERGE_ADD
@ MASK_SPLINE_INTERP_EASE
@ MASK_PARENT_POINT_TRACK
@ MASK_LAYERFLAG_FILL_OVERLAP
@ MASK_LAYERFLAG_FILL_DISCRETE
Read Guarded memory(de)allocation.
static void mask_blend_write(BlendWriter *writer, ID *id, const void *id_address)
void BKE_mask_clipboard_free()
void BKE_mask_layer_shape_unlink(MaskLayer *masklay, MaskLayerShape *masklay_shape)
void BKE_mask_coord_from_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2])
void BKE_mask_calc_handle_point(MaskSpline *spline, MaskSplinePoint *point)
void BKE_mask_layer_calc_handles(MaskLayer *masklay)
void BKE_mask_layer_shape_from_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape)
float BKE_mask_point_weight(MaskSpline *spline, MaskSplinePoint *point, const float u)
MaskLayerShape * BKE_mask_layer_shape_verify_frame(MaskLayer *masklay, const int frame)
static void mask_layer_shape_to_mask_point(BezTriple *bezt, const float fp[MASK_OBJECT_SHAPE_ELEM_SIZE])
static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr, const void *masklay_shape_b_ptr)
void BKE_mask_calc_handle_adjacent_interp(MaskSpline *spline, MaskSplinePoint *point, const float u)
static Mask * mask_alloc(Main *bmain, const char *name)
static void mask_runtime_reset(Mask *mask)
MaskSplinePoint * BKE_mask_spline_point_array_from_point(MaskSpline *spline, const MaskSplinePoint *point_ref)
static void mask_foreach_id(ID *id, LibraryForeachIDData *data)
void BKE_mask_get_handle_point_adjacent(MaskSpline *spline, MaskSplinePoint *point, MaskSplinePoint **r_point_prev, MaskSplinePoint **r_point_next)
void BKE_mask_layer_unique_name(Mask *mask, MaskLayer *masklay)
ListBase splines
void BKE_mask_point_add_uw(MaskSplinePoint *point, float u, float w)
void BKE_mask_clipboard_paste_to_layer(Main *bmain, MaskLayer *mask_layer)
static MaskSplinePoint * mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
BLI_INLINE void interp_v2_v2v2_flfl(float target[2], const float a[2], const float b[2], const float t, const float s)
MaskLayer * BKE_mask_layer_new(Mask *mask, const char *name)
Mask * BKE_mask_new(Main *bmain, const char *name)
void BKE_mask_point_normal(MaskSpline *spline, MaskSplinePoint *point, float u, float n[2])
void BKE_mask_layer_shape_changed_remove(MaskLayer *masklay, int index, int count)
void BKE_mask_layer_free_list(ListBase *masklayers)
MaskSpline * BKE_mask_spline_add(MaskLayer *masklay)
void BKE_mask_spline_direction_switch(MaskLayer *masklay, MaskSpline *spline)
bool BKE_mask_spline_remove(MaskLayer *mask_layer, MaskSpline *spline)
static void interp_weights_uv_v2_apply(const float uv[2], float r_pt[2], const float pt_a[2], const float pt_b[2])
void BKE_mask_point_select_set_handle(MaskSplinePoint *point, const eMaskWhichHandle which_handle, const bool do_select)
static struct @253233223023110366005072374002124067261276234025 mask_clipboard
int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay, const float frame, MaskLayerShape **r_masklay_shape_a, MaskLayerShape **r_masklay_shape_b)
void BKE_mask_layer_shape_sort(MaskLayer *masklay)
MaskLayer * BKE_mask_layer_active(Mask *mask)
void BKE_mask_point_select_set(MaskSplinePoint *point, const bool do_select)
void BKE_mask_parent_init(MaskParent *parent)
eMaskhandleMode BKE_mask_point_handles_mode_get(const MaskSplinePoint *point)
void BKE_mask_point_handle(const MaskSplinePoint *point, eMaskWhichHandle which_handle, float r_handle[2])
static void mask_blend_read_data(BlendDataReader *reader, ID *id)
void BKE_mask_layer_copy_list(ListBase *masklayers_new, const ListBase *masklayers)
bool BKE_mask_clipboard_is_empty()
void BKE_mask_layer_shape_to_mask_interp(MaskLayer *masklay, MaskLayerShape *masklay_shape_a, MaskLayerShape *masklay_shape_b, const float fac)
void BKE_mask_point_segment_co(MaskSpline *spline, MaskSplinePoint *point, float u, float co[2])
void BKE_mask_layer_rename(Mask *mask, MaskLayer *masklay, const char *oldname, const char *newname)
MaskSpline * BKE_mask_spline_copy(const MaskSpline *spline)
void BKE_mask_coord_to_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2])
bool BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index, MaskSpline **r_masklay_shape, int *r_index)
static MaskSplinePoint * mask_spline_point_prev(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
void BKE_mask_point_set_handle(MaskSplinePoint *point, eMaskWhichHandle which_handle, float loc[2], bool keep_direction, float orig_handle[2], float orig_vec[3][3])
void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float parent_matrix[3][3])
static void mask_layer_shape_from_mask_point(BezTriple *bezt, float fp[MASK_OBJECT_SHAPE_ELEM_SIZE])
float BKE_mask_point_weight_scalar(MaskSpline *spline, MaskSplinePoint *point, const float u)
void BKE_mask_coord_to_frame(float r_co[2], const float co[2], const float frame_size[2])
void BKE_mask_layer_free(MaskLayer *masklay)
void BKE_mask_coord_to_movieclip(MovieClip *clip, MovieClipUser *user, float r_co[2], const float co[2])
void BKE_mask_layer_shape_to_mask(MaskLayer *masklay, MaskLayerShape *masklay_shape)
MaskSplinePoint * BKE_mask_spline_point_array(MaskSpline *spline)
float BKE_mask_spline_project_co(MaskSpline *spline, MaskSplinePoint *point, float start_u, const float co[2], const eMaskSign sign)
static MaskSplinePoint * mask_spline_points_copy(const MaskSplinePoint *points, int tot_point)
static float mask_point_interp_weight(BezTriple *bezt, BezTriple *bezt_next, const float u)
static void mask_copy_data(Main *, std::optional< Library * >, ID *id_dst, const ID *id_src, const int)
void BKE_mask_coord_from_image(Image *image, ImageUser *iuser, float r_co[2], const float co[2])
void BKE_mask_layer_remove(Mask *mask, MaskLayer *masklay)
int BKE_mask_layer_shape_totvert(MaskLayer *masklay)
MaskLayerShape * BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int frame)
BezTriple * BKE_mask_spline_point_next_bezt(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
static void mask_free_data(ID *id)
BLI_INLINE void orthogonal_direction_get(const float vec[2], float result[2])
void BKE_mask_layer_shape_free(MaskLayerShape *masklay_shape)
void BKE_mask_spline_ensure_deform(MaskSpline *spline)
void BKE_mask_spline_free(MaskSpline *spline)
void BKE_mask_layer_free_shapes(MaskLayer *masklay)
Free all animation keys for a mask layer.
int BKE_mask_layer_shape_spline_to_index(MaskLayer *masklay, MaskSpline *spline)
static void mask_calc_point_handle(MaskSplinePoint *point, MaskSplinePoint *point_prev, MaskSplinePoint *point_next)
int BKE_mask_get_duration(Mask *mask)
MaskLayerShape * BKE_mask_layer_shape_alloc(MaskLayer *masklay, const int frame)
static void mask_clipboard_free_ex(bool final_free)
void BKE_mask_point_free(MaskSplinePoint *point)
void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool do_newframe)
void BKE_mask_layer_active_set(Mask *mask, MaskLayer *masklay)
void BKE_mask_point_direction_switch(MaskSplinePoint *point)
void BKE_mask_clipboard_copy_from_layer(MaskLayer *mask_layer)
void BKE_mask_spline_free_list(ListBase *splines)
GHash * id_hash
static void interp_weights_uv_v2_calc(float r_uv[2], const float pt[2], const float pt_a[2], const float pt_b[2])
MaskLayerShape * BKE_mask_layer_shape_duplicate(MaskLayerShape *masklay_shape)
void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2])
MaskLayer * BKE_mask_layer_copy(const MaskLayer *masklay)
void BKE_mask_calc_tangent_polyline(MaskSpline *spline, MaskSplinePoint *point, float t[2])
void BKE_mask_layer_shape_changed_add(MaskLayer *masklay, int index, bool do_init, bool do_init_interpolate)
void BKE_mask_evaluate(Mask *mask, const float ctime, const bool do_newframe)
void BKE_mask_calc_handle_point_auto(MaskSpline *spline, MaskSplinePoint *point, const bool do_recalc_length)
Resets auto handles even for non-auto bezier points.
MaskSplinePointUW * BKE_mask_point_sort_uw(MaskSplinePoint *point, MaskSplinePointUW *uw)
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
std::string id_name(void *id)
#define SELECT
#define offsetof(t, d)
constexpr T sign(T) RET
#define abs
#define FILTER_ID_MC
#define MAX_ID_NAME
#define FILTER_ID_MSK
#define MEM_reallocN(vmemh, len)
#define GS(a)
int count
#define LOG(severity)
Definition log.h:32
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_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
size_t(* MEM_allocN_len)(const void *vmemh)
Definition mallocn.cc:36
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
#define N
#define H(x, y, z)
float vec[3][3]
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * last
void * first
struct MaskLayerShape * prev
struct MaskLayerShape * next
struct MaskLayer * next
ListBase splines_shapes
char visibility_flag
ListBase splines
struct MaskSplinePoint * act_point
char name[64]
struct MaskSpline * act_spline
char parent[64]
float parent_orig[2]
float parent_corners_orig[4][2]
char sub_parent[64]
MaskSplinePointUW * uw
MaskParent parent
MaskParent parent
MaskSplinePoint * points_deform
struct MaskSpline * next
MaskSplinePoint * points
ListBase masklayers
struct MovieTracking tracking
i
Definition text_draw.cc:230
uint len
#define N_(msgid)