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