[Bf-blender-cvs] [489457e326c] soc-2021-curves: Added feature to alter a segment using curve pen
dilithjay
noreply at git.blender.org
Thu Jul 29 11:27:12 CEST 2021
Commit: 489457e326c845d31bf222d3ea1dcef3358fa6e5
Author: dilithjay
Date: Wed Jul 28 17:41:44 2021 +0530
Branches: soc-2021-curves
https://developer.blender.org/rB489457e326c845d31bf222d3ea1dcef3358fa6e5
Added feature to alter a segment using curve pen
===================================================================
M source/blender/editors/curve/editcurve_pen.c
===================================================================
diff --git a/source/blender/editors/curve/editcurve_pen.c b/source/blender/editors/curve/editcurve_pen.c
index a49e02f3608..9f05f4e792c 100644
--- a/source/blender/editors/curve/editcurve_pen.c
+++ b/source/blender/editors/curve/editcurve_pen.c
@@ -86,6 +86,11 @@ struct TempBeztData {
float mval[2];
} TempBeztData;
+struct MoveSegmentData {
+ Nurb *nu;
+ int bezt_index;
+} MoveSegmentData;
+
/* Convert mouse location to worldspace coordinates. */
static void mouse_location_to_worldspace(const int mouse_loc[2],
const float depth[3],
@@ -634,6 +639,94 @@ static void add_point_connected_to_selected_point(ViewContext *vc,
}
}
+/* Check if a spline segment is nearby. */
+static bool is_curve_nearby(ViewContext *vc, wmOperator *op, const wmEvent *event)
+{
+ Curve *cu = vc->obedit->data;
+ ListBase *nurbs = BKE_curve_editNurbs_get(cu);
+ float mouse_point[2] = {(float)event->mval[0], (float)event->mval[1]};
+
+ struct TempBeztData data = {.bezt_index = 0,
+ .min_dist = 10000,
+ .parameter = 0.5f,
+ .has_prev = false,
+ .has_next = false,
+ .mval[0] = event->mval[0],
+ .mval[1] = event->mval[1]};
+
+ update_data_for_all_nurbs(nurbs, vc, &data);
+
+ struct MoveSegmentData *seg_data;
+ op->customdata = seg_data = MEM_callocN(sizeof(MoveSegmentData), "MoveSegmentData");
+ seg_data->bezt_index = data.bezt_index;
+ seg_data->nu = data.nurb;
+
+ float threshold_distance = get_view_zoom(data.cut_loc, vc);
+
+ return data.min_dist < threshold_distance;
+}
+
+/* Move segment to mouse pointer. */
+static void move_segment(struct MoveSegmentData *seg_data, const wmEvent *event, ViewContext *vc)
+{
+ Nurb *nu = seg_data->nu;
+ BezTriple *bezt1 = nu->bezt + seg_data->bezt_index;
+ BezTriple *bezt2;
+
+ /* Define the next BezTriple based on cyclicity. */
+ if ((nu->flagu & CU_NURB_CYCLIC) && (nu->pntsu == seg_data->bezt_index + 1)) {
+ bezt2 = nu->bezt;
+ }
+ else {
+ bezt2 = bezt1 + 1;
+ }
+
+ float mouse_point[2] = {(float)event->mval[0], (float)event->mval[1]};
+ float mouse_3d[3];
+ mouse_location_to_worldspace(event->mval, bezt1->vec[1], vc, mouse_3d);
+
+ /*
+ * Equation of Bezier Curve
+ * => B(t) = (1-t)^3 * P0 + 3(1-t)^2 * t * P1 + 3(1-t) * t^2 * P2 + t^3 * P3
+ * Mouse location (Say Pm) should satisfy this equation.
+ * Substituting t = 0.5 => Pm = 0.5^3 * (P0 + 3P1 + 3P2 + P3)
+ * Therefore => P1 + P2 = (8 * Pm - P0 - P3) / 3
+ *
+ * Another constraint is required to identify P1 and P2.
+ * The constraint is to minimize the distance between new points and initial points.
+ * The minima can be found by differentiating the total distance.
+ */
+
+ float p1_plus_p2_div_2[3];
+ p1_plus_p2_div_2[0] = (8 * mouse_3d[0] - bezt1->vec[1][0] - bezt2->vec[1][0]) / 6;
+ p1_plus_p2_div_2[1] = (8 * mouse_3d[1] - bezt1->vec[1][1] - bezt2->vec[1][1]) / 6;
+ p1_plus_p2_div_2[2] = (8 * mouse_3d[2] - bezt1->vec[1][2] - bezt2->vec[1][2]) / 6;
+
+ float p1_minus_p2_div_2[3];
+ sub_v3_v3v3(p1_minus_p2_div_2, bezt1->vec[2], bezt2->vec[0]);
+ mul_v3_fl(p1_minus_p2_div_2, 0.5f);
+
+ add_v3_v3v3(bezt1->vec[2], p1_plus_p2_div_2, p1_minus_p2_div_2);
+ sub_v3_v3v3(bezt2->vec[0], p1_plus_p2_div_2, p1_minus_p2_div_2);
+
+ free_up_handles_for_movement(bezt1, true, true);
+ free_up_handles_for_movement(bezt2, true, true);
+
+ /* Move opposite handle as well if type is align. */
+ if (bezt1->h1 == HD_ALIGN) {
+ float handle_vec[3];
+ sub_v3_v3v3(handle_vec, bezt1->vec[1], bezt1->vec[2]);
+ normalize_v3_length(handle_vec, len_v3v3(bezt1->vec[1], bezt1->vec[0]));
+ add_v3_v3v3(bezt1->vec[0], bezt1->vec[1], handle_vec);
+ }
+ if (bezt2->h2 == HD_ALIGN) {
+ float handle_vec[3];
+ sub_v3_v3v3(handle_vec, bezt2->vec[1], bezt2->vec[0]);
+ normalize_v3_length(handle_vec, len_v3v3(bezt2->vec[1], bezt2->vec[2]));
+ add_v3_v3v3(bezt2->vec[2], bezt2->vec[1], handle_vec);
+ }
+}
+
enum {
PEN_MODAL_CANCEL = 1,
PEN_MODAL_FREE_MOVE_HANDLE,
@@ -686,6 +779,7 @@ static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
bool dragging = RNA_boolean_get(op->ptr, "dragging");
bool cut_or_delete = RNA_boolean_get(op->ptr, "cut_or_delete");
bool is_new_point = RNA_boolean_get(op->ptr, "new");
+ bool moving_segment = RNA_boolean_get(op->ptr, "moving_segment");
bool picked = false;
if (event->type == EVT_MODAL_MAP) {
@@ -706,8 +800,13 @@ static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
dragging = true;
}
if (dragging) {
+ if (moving_segment) {
+ struct MoveSegmentData *seg_data = op->customdata;
+ nu = seg_data->nu;
+ move_segment(seg_data, event, &vc);
+ }
/* Move handle point with mouse cursor if dragging a new control point. */
- if (is_new_point) {
+ else if (is_new_point) {
if (!picked) {
select_and_get_point(&vc, &nu, &bezt, &bp, event->mval, event->prevval != KM_PRESS);
}
@@ -767,13 +866,23 @@ static int curve_pen_modal(bContext *C, wmOperator *op, const wmEvent *event)
RNA_boolean_set(op->ptr, "new", !retval);
if (!retval) {
- add_point_connected_to_selected_point(&vc, obedit, event);
+ if (is_curve_nearby(&vc, op, event)) {
+ RNA_boolean_set(op->ptr, "moving_segment", true);
+ moving_segment = true;
+ }
+ else {
+ add_point_connected_to_selected_point(&vc, obedit, event);
+ }
}
}
}
if (event->val == KM_RELEASE) {
RNA_boolean_set(op->ptr, "dragging", false);
RNA_boolean_set(op->ptr, "new", false);
+ if (moving_segment) {
+ MEM_freeN(op->customdata);
+ }
+ RNA_boolean_set(op->ptr, "moving_segment", false);
ret = OPERATOR_FINISHED;
}
}
@@ -820,6 +929,8 @@ void CURVE_OT_pen(wmOperatorType *ot)
prop = RNA_def_boolean(
ot->srna, "new", 0, "New Point Drag", "The point was added with the press before drag");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "moving_segment", 0, "Moving Segment", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_boolean(
More information about the Bf-blender-cvs
mailing list