From 143f6c4bb24a88f76fe9823d6ad461896f3a76af Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 2 May 2016 18:11:09 +1000 Subject: Curve: new dissolve tool removes vertices, re-fitting the surrounding handles. --- release/scripts/startup/bl_ui/space_view3d.py | 15 +++- source/blender/editors/curve/curve_intern.h | 1 + source/blender/editors/curve/curve_ops.c | 9 ++- source/blender/editors/curve/editcurve.c | 105 ++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 3 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 374bc983d42..b4525d4f498 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2633,7 +2633,7 @@ def draw_curve(self, context): layout.operator("curve.separate") layout.operator("curve.make_segment") layout.operator("curve.cyclic_toggle") - layout.operator("curve.delete", text="Delete...") + layout.menu("VIEW3D_MT_edit_curve_delete") layout.separator() @@ -2704,6 +2704,19 @@ class VIEW3D_MT_edit_curve_specials(Menu): layout.operator("curve.smooth_tilt") +class VIEW3D_MT_edit_curve_delete(Menu): + bl_label = "Delete" + + def draw(self, context): + layout = self.layout + + layout.operator_enum("curve.delete", "type") + + layout.separator() + + layout.operator("curve.dissolve_verts") + + class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, Menu): _operator_name = "curve" diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index d63616e4f43..856573ffab0 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -102,6 +102,7 @@ void CURVE_OT_separate(struct wmOperatorType *ot); void CURVE_OT_split(struct wmOperatorType *ot); void CURVE_OT_duplicate(struct wmOperatorType *ot); void CURVE_OT_delete(struct wmOperatorType *ot); +void CURVE_OT_dissolve_verts(struct wmOperatorType *ot); void CURVE_OT_spline_type_set(struct wmOperatorType *ot); void CURVE_OT_radius_set(struct wmOperatorType *ot); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index d1994c8fc15..fce6425b9be 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -87,6 +87,7 @@ void ED_operatortypes_curve(void) WM_operatortype_append(CURVE_OT_split); WM_operatortype_append(CURVE_OT_duplicate); WM_operatortype_append(CURVE_OT_delete); + WM_operatortype_append(CURVE_OT_dissolve_verts); WM_operatortype_append(CURVE_OT_spline_type_set); WM_operatortype_append(CURVE_OT_radius_set); @@ -262,8 +263,12 @@ void ED_keymap_curve(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "CURVE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CURVE_OT_cyclic_toggle", CKEY, KM_PRESS, KM_ALT, 0); - WM_keymap_add_item(keymap, "CURVE_OT_delete", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "CURVE_OT_delete", DELKEY, KM_PRESS, 0, 0); + + WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_delete", DELKEY, KM_PRESS, 0, 0); + + WM_keymap_add_item(keymap, "CURVE_OT_dissolve_verts", XKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "CURVE_OT_dissolve_verts", DELKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "CURVE_OT_tilt_clear", TKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "TRANSFORM_OT_tilt", TKEY, KM_PRESS, KM_CTRL, 0); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 395da2cd2f1..354530ddd6b 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -36,6 +36,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_array_utils.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_ghash.h" @@ -70,6 +71,8 @@ #include "curve_intern.h" +#include "curve_fit_nd.h" + #include "UI_interface.h" #include "UI_resources.h" @@ -5776,6 +5779,108 @@ void CURVE_OT_delete(wmOperatorType *ot) ot->prop = prop; } +static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data) +{ + Curve *cu = user_data; + const BezTriple *bezt = bezt_v; + return BEZT_ISSEL_ANY_HIDDENHANDLES(cu, bezt); +} + +static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + Curve *cu = (Curve *)obedit->data; + + { + ListBase *editnurb = object_editcurve_get(obedit); + Nurb *nu; + + for (nu = editnurb->first; nu; nu = nu->next) { + if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) { + unsigned int span_step[2] = {nu->pntsu, nu->pntsu}; + unsigned int span_len; + + while (BLI_array_iter_span( + nu->bezt, nu->pntsu, + (nu->flagu & CU_NURB_CYCLIC) != 0, false, + test_bezt_is_sel_any, cu, + span_step, &span_len)) + { + BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)]; + BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)]; + + int i_span_edge_len = span_len + 1; + const unsigned int dims = 3; + + const unsigned int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1; + float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__); + float *points_stride = points; + const int points_stride_len = (cu->resolu - 1); + + for (int segment = 0; segment < i_span_edge_len; segment++) { + BezTriple *bezt_a = &nu->bezt[mod_i((span_step[0] + segment) - 1, nu->pntsu)]; + BezTriple *bezt_b = &nu->bezt[mod_i((span_step[0] + segment), nu->pntsu)]; + + for (int axis = 0; axis < dims; axis++) { + BKE_curve_forward_diff_bezier( + bezt_a->vec[1][axis], bezt_a->vec[2][axis], + bezt_b->vec[0][axis], bezt_b->vec[1][axis], + points_stride + axis, points_stride_len, dims * sizeof(float)); + } + + points_stride += dims * points_stride_len; + } + + BLI_assert(points_stride + dims == points + (points_len * dims)); + + float tan_l[3], tan_r[3], error_sq_dummy; + + sub_v3_v3v3(tan_l, bezt_prev->vec[1], bezt_prev->vec[2]); + normalize_v3(tan_l); + sub_v3_v3v3(tan_r, bezt_next->vec[0], bezt_next->vec[1]); + normalize_v3(tan_r); + + curve_fit_cubic_to_points_single_fl( + points, points_len, dims, FLT_EPSILON, + tan_l, tan_r, + bezt_prev->vec[2], bezt_next->vec[0], + &error_sq_dummy); + + MEM_freeN(points); + } + } + } + } + + ed_curve_delete_selected(obedit); + + { + cu->actnu = cu->actvert = CU_ACT_NONE; + + if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DAG_id_tag_update(obedit->data, 0); + } + + return OPERATOR_FINISHED; +} + +void CURVE_OT_dissolve_verts(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Dissolve Vertices"; + ot->description = "Delete selected control points, correcting surrounding handles"; + ot->idname = "CURVE_OT_dissolve_verts"; + + /* api callbacks */ + ot->exec = curve_dissolve_exec; + ot->poll = ED_operator_editcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /********************** shade smooth/flat operator *********************/ static int shade_smooth_exec(bContext *C, wmOperator *op) -- cgit v1.2.3