diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 2 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d_toolbar.py | 1 | ||||
-rw-r--r-- | source/blender/editors/curve/curve_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/curve/curve_ops.c | 2 | ||||
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 160 |
5 files changed, 122 insertions, 45 deletions
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 19095df6a14..0ad8cdccca8 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -2197,7 +2197,9 @@ class VIEW3D_MT_edit_curve_specials(Menu): layout.operator("curve.spline_weight_set") layout.operator("curve.radius_set") layout.operator("curve.smooth") + layout.operator("curve.smooth_weight") layout.operator("curve.smooth_radius") + layout.operator("curve.smooth_tilt") class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 1383775042d..f253801f431 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -277,7 +277,6 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel): col.operator("curve.switch_direction") col.operator("curve.spline_type_set") col.operator("curve.radius_set") - col.operator("curve.smooth_radius") col = layout.column(align=True) col.label(text="Handles:") diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index 0521297d049..d197697e60b 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -88,7 +88,9 @@ void CURVE_OT_shade_flat(struct wmOperatorType *ot); void CURVE_OT_tilt_clear(struct wmOperatorType *ot); void CURVE_OT_smooth(struct wmOperatorType *ot); +void CURVE_OT_smooth_weight(struct wmOperatorType *ot); void CURVE_OT_smooth_radius(struct wmOperatorType *ot); +void CURVE_OT_smooth_tilt(struct wmOperatorType *ot); void CURVE_OT_primitive_bezier_curve_add(struct wmOperatorType *ot); void CURVE_OT_primitive_bezier_circle_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 5b525a089b3..2452a5d1a4b 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -112,7 +112,9 @@ void ED_operatortypes_curve(void) WM_operatortype_append(SURFACE_OT_primitive_nurbs_surface_torus_add); WM_operatortype_append(CURVE_OT_smooth); + WM_operatortype_append(CURVE_OT_smooth_weight); WM_operatortype_append(CURVE_OT_smooth_radius); + WM_operatortype_append(CURVE_OT_smooth_tilt); WM_operatortype_append(CURVE_OT_de_select_first); WM_operatortype_append(CURVE_OT_de_select_last); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index a988b2295dc..660f8098a38 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2260,29 +2260,33 @@ void CURVE_OT_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/**************** smooth curve radius operator *************/ +/* -------------------------------------------------------------------- */ +/* Smooth radius/weight/tilt + * + * TODO: make smoothing distance based + * TODO: support cyclic curves + */ -/* TODO, make smoothing distance based */ -static int smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) +static void curve_smooth_value(ListBase *editnurb, + const int bezt_offsetof, const int bp_offset) { - Object *obedit = CTX_data_edit_object(C); - ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu; BezTriple *bezt; BPoint *bp; int a; - + /* use for smoothing */ int last_sel; int start_sel, end_sel; /* selection indices, inclusive */ float start_rad, end_rad, fac, range; - + for (nu = editnurb->first; nu; nu = nu->next) { if (nu->bezt) { - +#define BEZT_VALUE(bezt) (*((float *)((char *)bezt + bezt_offsetof))) + for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { /* loop over selection segments of a curve, smooth each */ - + /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ start_sel = -1; for (bezt = &nu->bezt[last_sel], a = last_sel; a < nu->pntsu; a++, bezt++) { @@ -2299,57 +2303,60 @@ static int smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) } end_sel = a; } - + if (start_sel == -1) { last_sel = nu->pntsu; /* next... */ } else { last_sel = end_sel; /* before we modify it */ - + /* now blend between start and end sel */ - start_rad = end_rad = -1.0; - + start_rad = end_rad = FLT_MAX; + if (start_sel == end_sel) { /* simple, only 1 point selected */ - if (start_sel > 0) start_rad = nu->bezt[start_sel - 1].radius; - if (end_sel != -1 && end_sel < nu->pntsu) end_rad = nu->bezt[start_sel + 1].radius; - - if (start_rad >= 0.0f && end_rad >= 0.0f) nu->bezt[start_sel].radius = (start_rad + end_rad) / 2.0f; - else if (start_rad >= 0.0f) nu->bezt[start_sel].radius = start_rad; - else if (end_rad >= 0.0f) nu->bezt[start_sel].radius = end_rad; + if (start_sel > 0) start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); + if (end_sel != -1 && end_sel < nu->pntsu) end_rad = BEZT_VALUE(&nu->bezt[start_sel + 1]); + + if (start_rad != FLT_MAX && end_rad >= FLT_MAX) BEZT_VALUE(&nu->bezt[start_sel]) = (start_rad + end_rad) / 2.0f; + else if (start_rad != FLT_MAX) BEZT_VALUE(&nu->bezt[start_sel]) = start_rad; + else if (end_rad != FLT_MAX) BEZT_VALUE(&nu->bezt[start_sel]) = end_rad; } else { /* if endpoints selected, then use them */ if (start_sel == 0) { - start_rad = nu->bezt[start_sel].radius; + start_rad = BEZT_VALUE(&nu->bezt[start_sel]); start_sel++; /* we don't want to edit the selected endpoint */ } else { - start_rad = nu->bezt[start_sel - 1].radius; + start_rad = BEZT_VALUE(&nu->bezt[start_sel - 1]); } if (end_sel == nu->pntsu - 1) { - end_rad = nu->bezt[end_sel].radius; + end_rad = BEZT_VALUE(&nu->bezt[end_sel]); end_sel--; /* we don't want to edit the selected endpoint */ } else { - end_rad = nu->bezt[end_sel + 1].radius; + end_rad = BEZT_VALUE(&nu->bezt[end_sel + 1]); } - + /* Now Blend between the points */ range = (float)(end_sel - start_sel) + 2.0f; for (bezt = &nu->bezt[start_sel], a = start_sel; a <= end_sel; a++, bezt++) { fac = (float)(1 + a - start_sel) / range; - bezt->radius = start_rad * (1.0f - fac) + end_rad * fac; + BEZT_VALUE(bezt) = start_rad * (1.0f - fac) + end_rad * fac; } } } } +#undef BEZT_VALUE } else if (nu->bp) { +#define BP_VALUE(bp) (*((float *)((char *)bp + bp_offset))) + /* Same as above, keep these the same! */ for (last_sel = 0; last_sel < nu->pntsu; last_sel++) { /* loop over selection segments of a curve, smooth each */ - + /* Start BezTriple code, this is duplicated below for points, make sure these functions stay in sync */ start_sel = -1; for (bp = &nu->bp[last_sel], a = last_sel; a < nu->pntsu; a++, bp++) { @@ -2366,53 +2373,90 @@ static int smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) } end_sel = a; } - + if (start_sel == -1) { last_sel = nu->pntsu; /* next... */ } else { last_sel = end_sel; /* before we modify it */ - + /* now blend between start and end sel */ - start_rad = end_rad = -1.0; - + start_rad = end_rad = FLT_MAX; + if (start_sel == end_sel) { /* simple, only 1 point selected */ - if (start_sel > 0) start_rad = nu->bp[start_sel - 1].radius; - if (end_sel != -1 && end_sel < nu->pntsu) end_rad = nu->bp[start_sel + 1].radius; - - if (start_rad >= 0.0f && end_rad >= 0.0f) nu->bp[start_sel].radius = (start_rad + end_rad) / 2; - else if (start_rad >= 0.0f) nu->bp[start_sel].radius = start_rad; - else if (end_rad >= 0.0f) nu->bp[start_sel].radius = end_rad; + if (start_sel > 0) start_rad = BP_VALUE(&nu->bp[start_sel - 1]); + if (end_sel != -1 && end_sel < nu->pntsu) end_rad = BP_VALUE(&nu->bp[start_sel + 1]); + + if (start_rad != FLT_MAX && end_rad != FLT_MAX) BP_VALUE(&nu->bp[start_sel]) = (start_rad + end_rad) / 2; + else if (start_rad != FLT_MAX) BP_VALUE(&nu->bp[start_sel]) = start_rad; + else if (end_rad != FLT_MAX) BP_VALUE(&nu->bp[start_sel]) = end_rad; } else { /* if endpoints selected, then use them */ if (start_sel == 0) { - start_rad = nu->bp[start_sel].radius; + start_rad = BP_VALUE(&nu->bp[start_sel]); start_sel++; /* we don't want to edit the selected endpoint */ } else { - start_rad = nu->bp[start_sel - 1].radius; + start_rad = BP_VALUE(&nu->bp[start_sel - 1]); } if (end_sel == nu->pntsu - 1) { - end_rad = nu->bp[end_sel].radius; + end_rad = BP_VALUE(&nu->bp[end_sel]); end_sel--; /* we don't want to edit the selected endpoint */ } else { - end_rad = nu->bp[end_sel + 1].radius; + end_rad = BP_VALUE(&nu->bp[end_sel + 1]); } - + /* Now Blend between the points */ range = (float)(end_sel - start_sel) + 2.0f; for (bp = &nu->bp[start_sel], a = start_sel; a <= end_sel; a++, bp++) { fac = (float)(1 + a - start_sel) / range; - bp->radius = start_rad * (1.0f - fac) + end_rad * fac; + BP_VALUE(bp) = start_rad * (1.0f - fac) + end_rad * fac; } } } } +#undef BP_VALUE } } +} + +static int curve_smooth_weight_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + + curve_smooth_value(editnurb, offsetof(BezTriple, weight), offsetof(BPoint, weight)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DAG_id_tag_update(obedit->data, 0); + + return OPERATOR_FINISHED; +} + +void CURVE_OT_smooth_weight(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Smooth Curve Weight"; + ot->description = "Interpolate weight of selected points"; + ot->idname = "CURVE_OT_smooth_weight"; + + /* api clastbacks */ + ot->exec = curve_smooth_weight_exec; + ot->poll = ED_operator_editsurfcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static int curve_smooth_radius_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + + curve_smooth_value(editnurb, offsetof(BezTriple, radius), offsetof(BPoint, radius)); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); DAG_id_tag_update(obedit->data, 0); @@ -2424,17 +2468,45 @@ void CURVE_OT_smooth_radius(wmOperatorType *ot) { /* identifiers */ ot->name = "Smooth Curve Radius"; - ot->description = "Flatten radii of selected points"; + ot->description = "Interpolate radii of selected points"; ot->idname = "CURVE_OT_smooth_radius"; /* api clastbacks */ - ot->exec = smooth_radius_exec; + ot->exec = curve_smooth_radius_exec; ot->poll = ED_operator_editsurfcurve; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +static int curve_smooth_tilt_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + + curve_smooth_value(editnurb, offsetof(BezTriple, alfa), offsetof(BPoint, alfa)); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DAG_id_tag_update(obedit->data, 0); + + return OPERATOR_FINISHED; +} + +void CURVE_OT_smooth_tilt(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Smooth Curve Tilt"; + ot->description = "Interpolate tilt of selected points"; + ot->idname = "CURVE_OT_smooth_tilt"; + + /* api clastbacks */ + ot->exec = curve_smooth_tilt_exec; + ot->poll = ED_operator_editsurfcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /***************** selection utility *************************/ /* next == 1 -> select next */ |