Curve Handle Recalculate (Ctrl+N)

T37799 Patch from Simon Repp
with added option to recalculate handle lengths.
This commit is contained in:
Campbell Barton 2013-12-14 02:32:48 +11:00
parent 52c5365c00
commit c456cd94b2
7 changed files with 109 additions and 0 deletions

@ -2356,6 +2356,7 @@ class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
layout.separator()
layout.operator_menu_enum("curve.handle_type_set", "type")
layout.operator("curve.normals_make_consistent")
layout.separator()

@ -291,6 +291,9 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
row.operator("curve.handle_type_set", text="Align").type = 'ALIGNED'
row.operator("curve.handle_type_set", text="Free").type = 'FREE_ALIGN'
col = layout.column(align=True)
col.operator("curve.normals_make_consistent")
col = layout.column(align=True)
col.label(text="Modeling:")
col.operator("curve.extrude_move", text="Extrude")

@ -113,6 +113,7 @@ int BKE_nurbList_verts_count_without_handles(struct ListBase *nurb);
void BKE_nurbList_free(struct ListBase *lb);
void BKE_nurbList_duplicate(struct ListBase *lb1, struct ListBase *lb2);
void BKE_nurbList_handles_set(struct ListBase *editnurb, short code);
void BKE_nurbList_handles_recalculate(struct ListBase *editnurb, const bool calc_length, const char flag);
void BKE_nurbList_handles_autocalc(ListBase *editnurb, int flag);
void BKE_nurbList_flag_set(ListBase *editnurb, short flag);

@ -3393,6 +3393,72 @@ void BKE_nurbList_handles_set(ListBase *editnurb, short code)
}
}
void BKE_nurbList_handles_recalculate(ListBase *editnurb, const bool calc_length, const char flag)
{
Nurb *nu;
BezTriple *bezt;
int a;
for (nu = editnurb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
bool changed = false;
for (a = nu->pntsu, bezt = nu->bezt; a--; bezt++) {
const bool h1_select = (bezt->f1 & flag) == flag;
const bool h2_select = (bezt->f3 & flag) == flag;
if (h1_select || h2_select) {
/* Override handle types to HD_AUTO and recalculate */
char h1_back, h2_back;
float co1_back[3], co2_back[3];
h1_back = bezt->h1;
h2_back = bezt->h2;
bezt->h1 = HD_AUTO;
bezt->h2 = HD_AUTO;
copy_v3_v3(co1_back, bezt->vec[0]);
copy_v3_v3(co2_back, bezt->vec[2]);
BKE_nurb_handle_calc_simple(nu, bezt);
bezt->h1 = h1_back;
bezt->h2 = h2_back;
if (h1_select) {
if (!calc_length) {
dist_ensure_v3_v3fl(bezt->vec[0], bezt->vec[1], len_v3v3(co1_back, bezt->vec[1]));
}
}
else {
copy_v3_v3(bezt->vec[0], co1_back);
}
if (h2_select) {
if (!calc_length) {
dist_ensure_v3_v3fl(bezt->vec[2], bezt->vec[1], len_v3v3(co2_back, bezt->vec[1]));
}
}
else {
copy_v3_v3(bezt->vec[2], co2_back);
}
changed = true;
}
}
if (changed) {
/* Recalculate the whole curve */
BKE_nurb_handles_calc(nu);
}
}
}
}
void BKE_nurbList_flag_set(ListBase *editnurb, short flag)
{
Nurb *nu;

@ -88,6 +88,7 @@ void CURVE_OT_spline_type_set(struct wmOperatorType *ot);
void CURVE_OT_radius_set(struct wmOperatorType *ot);
void CURVE_OT_spline_weight_set(struct wmOperatorType *ot);
void CURVE_OT_handle_type_set(struct wmOperatorType *ot);
void CURVE_OT_normals_make_consistent(struct wmOperatorType *ot);
void CURVE_OT_shade_smooth(struct wmOperatorType *ot);
void CURVE_OT_shade_flat(struct wmOperatorType *ot);
void CURVE_OT_tilt_clear(struct wmOperatorType *ot);

@ -95,6 +95,7 @@ void ED_operatortypes_curve(void)
WM_operatortype_append(CURVE_OT_radius_set);
WM_operatortype_append(CURVE_OT_spline_weight_set);
WM_operatortype_append(CURVE_OT_handle_type_set);
WM_operatortype_append(CURVE_OT_normals_make_consistent);
WM_operatortype_append(CURVE_OT_shade_smooth);
WM_operatortype_append(CURVE_OT_shade_flat);
WM_operatortype_append(CURVE_OT_tilt_clear);
@ -266,6 +267,8 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
kmi = WM_keymap_add_item(keymap, "CURVE_OT_hide", HKEY, KM_PRESS, KM_SHIFT, 0);
RNA_boolean_set(kmi->ptr, "unselected", TRUE);
WM_keymap_add_item(keymap, "CURVE_OT_normals_make_consistent", NKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "OBJECT_OT_vertex_parent_set", PKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_menu(keymap, "VIEW3D_MT_edit_curve_specials", WKEY, KM_PRESS, 0, 0);

@ -3676,6 +3676,40 @@ void CURVE_OT_handle_type_set(wmOperatorType *ot)
ot->prop = RNA_def_enum(ot->srna, "type", editcurve_handle_type_items, 1, "Type", "Spline type");
}
/***************** recalculate handles operator **********************/
static int curve_normals_make_consistent_exec(bContext *C, wmOperator *op)
{
Object *obedit = CTX_data_edit_object(C);
ListBase *editnurb = object_editcurve_get(obedit);
const bool calc_length = RNA_boolean_get(op->ptr, "calc_length");
BKE_nurbList_handles_recalculate(editnurb, calc_length, SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
DAG_id_tag_update(obedit->data, 0);
return OPERATOR_FINISHED;
}
void CURVE_OT_normals_make_consistent(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Recalc Normals";
ot->description = "Recalculate the direction of selected handles";
ot->idname = "CURVE_OT_normals_make_consistent";
/* api callbacks */
ot->exec = curve_normals_make_consistent_exec;
ot->poll = ED_operator_editcurve;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* props */
RNA_def_boolean(ot->srna, "calc_length", false, "Length", "Recalculate handle length");
}
/***************** make segment operator **********************/
/* ******************** SKINNING LOFTING!!! ******************** */