From 2e7e13442c914a4e9610def67eb199ab40f6b2b1 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 29 Mar 2021 16:11:33 +0200 Subject: 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. --- source/blender/editors/mask/mask_add.c | 40 +++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'source/blender/editors/mask/mask_add.c') diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 1226cc57359..36edbbe31d6 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -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); } -- cgit v1.2.3