Fix T76872: Mask created after existing keyframe gets broken handles

The issue was caused by handles not being written to the new mask
spline shape: it was always written as (0, 0), which was making the
handle calculation go wrong later on.

Solved by allocating a temporary array of bezier points and calculating
handles for them. While this is an extra array allocation it is only
done for a small amount of points and it is not in the critical code
path. Having this as an extra array helps to overcome a limitation of
the current mask shape API.

Additionally, disable the interpolation for the shape change:
the spline is brand new, there is nothing to be interpolated there.
This commit is contained in:
Sergey Sharybin 2021-03-29 16:11:33 +02:00
parent 51f8dbe081
commit 2e7e13442c
Notes: blender-bot 2023-02-14 02:27:56 +01:00
Referenced by issue #76872, 2nd Mask (created after existing keyframe) gets broken handles
1 changed files with 34 additions and 6 deletions

View File

@ -26,6 +26,7 @@
#include "BLI_math.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_mask.h"
#include "DEG_depsgraph.h"
@ -692,6 +693,33 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot)
/******************** common primitive functions *********************/
static BezTriple *points_to_bezier(const float (*points)[2],
const int num_points,
const char handle_type,
const float scale,
const float location[2])
{
BezTriple *bezier_points = MEM_calloc_arrayN(num_points, sizeof(BezTriple), __func__);
for (int i = 0; i < num_points; i++) {
copy_v2_v2(bezier_points[i].vec[1], points[i]);
mul_v2_fl(bezier_points[i].vec[1], scale);
add_v2_v2(bezier_points[i].vec[1], location);
bezier_points[i].h1 = handle_type;
bezier_points[i].h2 = handle_type;
}
for (int i = 0; i < num_points; i++) {
BKE_nurb_handle_calc(&bezier_points[i],
&bezier_points[(i - 1 + num_points) % num_points],
&bezier_points[(i + 1) % num_points],
false,
false);
}
return bezier_points;
}
static int create_primitive_from_points(
bContext *C, wmOperator *op, const float (*points)[2], int num_points, char handle_type)
{
@ -734,25 +762,25 @@ static int create_primitive_from_points(
const int spline_index = BKE_mask_layer_shape_spline_to_index(mask_layer, new_spline);
BezTriple *bezier_points = points_to_bezier(points, num_points, handle_type, scale, location);
for (int i = 0; i < num_points; i++) {
new_spline->tot_point = i + 1;
MaskSplinePoint *new_point = &new_spline->points[i];
BKE_mask_parent_init(&new_point->parent);
copy_v2_v2(new_point->bezt.vec[1], points[i]);
mul_v2_fl(new_point->bezt.vec[1], scale);
add_v2_v2(new_point->bezt.vec[1], location);
new_point->bezt = bezier_points[i];
new_point->bezt.h1 = handle_type;
new_point->bezt.h2 = handle_type;
BKE_mask_point_select_set(new_point, true);
if (mask_layer->splines_shapes.first) {
BKE_mask_layer_shape_changed_add(mask_layer, spline_index + i, true, true);
BKE_mask_layer_shape_changed_add(mask_layer, spline_index + i, true, false);
}
}
MEM_freeN(bezier_points);
if (added_mask) {
WM_event_add_notifier(C, NC_MASK | NA_ADDED, NULL);
}