Curves: add operator to set bezier handle types

This adds an operator to set the handle types of bezier curves. It also
adds the same shortcut that is available in the legacy curve edit mode.

Pull Request: https://projects.blender.org/blender/blender/pulls/120426
This commit is contained in:
Jacques Lucke 2024-04-10 13:08:50 +02:00
parent 554b064214
commit 01ee34ebd1
5 changed files with 96 additions and 0 deletions

@ -6143,6 +6143,7 @@ def km_edit_curves(params):
("transform.transform", {"type": 'S', "value": 'PRESS', "alt": True},
{"properties": [("mode", 'CURVE_SHRINKFATTEN')]}),
("curves.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None),
("curves.handle_type_set", {"type": 'V', "value": 'PRESS'}, None),
])
return keymap

@ -1175,6 +1175,7 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("VIEW3D_MT_edit_curve_ctrlpoints")
layout.menu("VIEW3D_MT_edit_curve_segments")
elif mode_string in {'EDIT_CURVES', 'EDIT_POINT_CLOUD'}:
layout.menu("VIEW3D_MT_edit_curves_control_points")
layout.menu("VIEW3D_MT_edit_curves_segments")
layout.template_node_operator_asset_root_items()
elif mode_string == 'EDIT_GREASE_PENCIL':
@ -5917,6 +5918,15 @@ class VIEW3D_MT_edit_curves(Menu):
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_curves_control_points(Menu):
bl_label = "Control Points"
def draw(self, _context):
layout = self.layout
layout.operator_menu_enum("curves.handle_type_set", "type")
class VIEW3D_MT_edit_curves_segments(Menu):
bl_label = "Segments"
@ -9070,6 +9080,7 @@ classes = (
VIEW3D_MT_edit_gpencil_transform,
VIEW3D_MT_edit_curves,
VIEW3D_MT_edit_curves_segments,
VIEW3D_MT_edit_curves_control_points,
VIEW3D_MT_edit_pointcloud,
VIEW3D_MT_object_mode_pie,
VIEW3D_MT_view_pie,

@ -1525,6 +1525,64 @@ static void CURVES_OT_subdivide(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
namespace set_handle_type {
static int exec(bContext *C, wmOperator *op)
{
const HandleType dst_handle_type = HandleType(RNA_enum_get(op->ptr, "type"));
for (Curves *curves_id : get_unique_editable_curves(*C)) {
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
const bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
const VArraySpan<bool> selection = *attributes.lookup_or_default<bool>(
".selection", bke::AttrDomain::Point, true);
const VArraySpan<bool> selection_left = *attributes.lookup_or_default<bool>(
".selection_handle_left", bke::AttrDomain::Point, true);
const VArraySpan<bool> selection_right = *attributes.lookup_or_default<bool>(
".selection_handle_right", bke::AttrDomain::Point, true);
MutableSpan<int8_t> handle_types_left = curves.handle_types_left_for_write();
MutableSpan<int8_t> handle_types_right = curves.handle_types_right_for_write();
threading::parallel_for(curves.points_range(), 4096, [&](const IndexRange range) {
for (const int point_i : range) {
if (selection_left[point_i] || selection[point_i]) {
handle_types_left[point_i] = int8_t(dst_handle_type);
}
if (selection_right[point_i] || selection[point_i]) {
handle_types_right[point_i] = int8_t(dst_handle_type);
}
}
});
curves.calculate_bezier_auto_handles();
curves.tag_positions_changed();
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
}
return OPERATOR_FINISHED;
}
} // namespace set_handle_type
static void CURVES_OT_handle_type_set(wmOperatorType *ot)
{
ot->name = "Set Handle Type";
ot->idname = __func__;
ot->description = "Set the handle type for bezier curves";
ot->invoke = WM_menu_invoke;
ot->exec = set_handle_type::exec;
ot->poll = editable_curves_in_edit_mode_poll;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
ot->prop = RNA_def_enum(
ot->srna, "type", rna_enum_curves_handle_type_items, CURVE_TYPE_POLY, "Type", nullptr);
}
void operatortypes_curves()
{
WM_operatortype_append(CURVES_OT_attribute_set);
@ -1548,6 +1606,7 @@ void operatortypes_curves()
WM_operatortype_append(CURVES_OT_curve_type_set);
WM_operatortype_append(CURVES_OT_switch_direction);
WM_operatortype_append(CURVES_OT_subdivide);
WM_operatortype_append(CURVES_OT_handle_type_set);
}
void operatormacros_curves()

@ -252,6 +252,7 @@ DEF_ENUM(rna_enum_transform_orientation_items)
DEF_ENUM(rna_enum_velocity_unit_items)
DEF_ENUM(rna_enum_curves_type_items)
DEF_ENUM(rna_enum_curves_handle_type_items)
DEF_ENUM(rna_enum_curve_normal_mode_items)
/* Not available to RNA pre-processing (`makesrna`).

@ -25,6 +25,30 @@ const EnumPropertyItem rna_enum_curves_type_items[] = {
{0, nullptr, 0, nullptr, nullptr},
};
const EnumPropertyItem rna_enum_curves_handle_type_items[] = {
{BEZIER_HANDLE_FREE,
"FREE",
0,
"Free",
"The handle can be moved anywhere, and doesn't influence the point's other handle"},
{BEZIER_HANDLE_AUTO,
"AUTO",
0,
"Auto",
"The location is automatically calculated to be smooth"},
{BEZIER_HANDLE_VECTOR,
"VECTOR",
0,
"Vector",
"The location is calculated to point to the next/previous control point"},
{BEZIER_HANDLE_ALIGN,
"ALIGN",
0,
"Align",
"The location is constrained to point in the opposite direction as the other handleW"},
{0, nullptr, 0, nullptr, nullptr},
};
const EnumPropertyItem rna_enum_curve_normal_mode_items[] = {
{NORMAL_MODE_MINIMUM_TWIST,
"MINIMUM_TWIST",