curve only supported radius smoothing, add smooth for tilt and weight.
authorCampbell Barton <ideasman42@gmail.com>
Wed, 24 Jul 2013 14:30:45 +0000 (14:30 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 24 Jul 2013 14:30:45 +0000 (14:30 +0000)
release/scripts/startup/bl_ui/space_view3d.py
release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/editors/curve/curve_intern.h
source/blender/editors/curve/curve_ops.c
source/blender/editors/curve/editcurve.c

index 19095df6a14147e4e1e416d338c7ff50adbd4d43..0ad8cdccca892a616b3b61007780216d324fd380 100644 (file)
@@ -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):
index 1383775042d97532594a8c8b5f4df2447901495c..f253801f431363db8c50c3888d61a6497c6700d4 100644 (file)
@@ -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:")
index 0521297d0496f0de6167abc8ab4ee23920bb0e6c..d197697e60b5f027c7f1fcc479c4bb34facd81e8 100644 (file)
@@ -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);
index 5b525a089b31138fb86a71ed7aa7da8f0b8c883c..2452a5d1a4bb6b7d5321a21467d3ff36d8f9695f 100644 (file)
@@ -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);
index a988b2295dc9e4b9e85fa88cc8eb0b44bbf6ad8e..660f8098a38fae73876dfc9a0a89da09f9f6baf1 100644 (file)
@@ -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         */