Curves: Add edit mode tilt control
Adds support for the tilt transform operator and a "Clear Tilt" operator to mirror the functionality from the legacy curve type.
This commit is contained in:
parent
3ddba82716
commit
0e8c874166
|
@ -6084,6 +6084,10 @@ def km_edit_curves(params):
|
|||
("curves.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None),
|
||||
*_template_items_proportional_editing(
|
||||
params, connected=True, toggle_data_path='tool_settings.use_proportional_edit'),
|
||||
("curves.tilt_clear", {"type": 'T', "value": 'PRESS', "alt": True}, None),
|
||||
op_tool_optional(
|
||||
("transform.tilt", {"type": 'T', "value": 'PRESS', "ctrl": True}, None),
|
||||
(op_tool_cycle, "builtin.tilt"), params),
|
||||
("transform.transform", {"type": 'S', "value": 'PRESS', "alt": True},
|
||||
{"properties": [("mode", 'CURVE_SHRINKFATTEN')]}),
|
||||
])
|
||||
|
|
|
@ -3026,8 +3026,10 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
'EDIT_CURVES': [
|
||||
*_tools_default,
|
||||
None,
|
||||
_defs_edit_curve.curve_radius,
|
||||
_defs_edit_curves.draw,
|
||||
None,
|
||||
_defs_edit_curve.curve_radius,
|
||||
_defs_edit_curve.tilt,
|
||||
],
|
||||
'EDIT_SURFACE': [
|
||||
*_tools_default,
|
||||
|
|
|
@ -1282,6 +1282,46 @@ static void CURVES_OT_duplicate(wmOperatorType *ot)
|
|||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
namespace clear_tilt {
|
||||
|
||||
static int exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
for (Curves *curves_id : get_unique_editable_curves(*C)) {
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask selection = retrieve_selected_points(*curves_id, memory);
|
||||
if (selection.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (selection.size() == curves.points_num()) {
|
||||
curves.attributes_for_write().remove("tilt");
|
||||
}
|
||||
else {
|
||||
index_mask::masked_fill(curves.tilt_for_write(), 0.0f, selection);
|
||||
}
|
||||
|
||||
curves.tag_normals_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 clear_tilt
|
||||
|
||||
static void CURVES_OT_tilt_clear(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Clear Tilt";
|
||||
ot->idname = __func__;
|
||||
ot->description = "Clear the tilt of selected control points";
|
||||
|
||||
ot->exec = clear_tilt::exec;
|
||||
ot->poll = editable_curves_in_edit_mode_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::curves
|
||||
|
||||
void ED_operatortypes_curves()
|
||||
|
@ -1302,6 +1342,7 @@ void ED_operatortypes_curves()
|
|||
WM_operatortype_append(CURVES_OT_surface_set);
|
||||
WM_operatortype_append(CURVES_OT_delete);
|
||||
WM_operatortype_append(CURVES_OT_duplicate);
|
||||
WM_operatortype_append(CURVES_OT_tilt_clear);
|
||||
}
|
||||
|
||||
void ED_operatormacros_curves()
|
||||
|
|
|
@ -105,7 +105,11 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
|
|||
"radius",
|
||||
ATTR_DOMAIN_POINT,
|
||||
bke::AttributeInitVArray(VArray<float>::ForSingle(0.01f, curves.points_num())));
|
||||
|
||||
value_attribute = attribute_writer.span;
|
||||
}
|
||||
else if (t->mode == TFM_TILT) {
|
||||
bke::MutableAttributeAccessor attributes = curves.attributes_for_write();
|
||||
attribute_writer = attributes.lookup_or_add_for_write_span<float>("tilt", ATTR_DOMAIN_POINT);
|
||||
value_attribute = attribute_writer.span;
|
||||
}
|
||||
|
||||
|
@ -117,6 +121,8 @@ static void createTransCurvesVerts(bContext * /*C*/, TransInfo *t)
|
|||
curves.curves_range(),
|
||||
use_connected_only,
|
||||
0 /* No data offset for curves. */);
|
||||
|
||||
/* TODO: This is wrong. The attribute writer should live at least as long as the span. */
|
||||
attribute_writer.finish();
|
||||
}
|
||||
}
|
||||
|
@ -127,9 +133,16 @@ static void recalcData_curves(TransInfo *t)
|
|||
for (const TransDataContainer &tc : trans_data_contrainers) {
|
||||
Curves *curves_id = static_cast<Curves *>(tc.obedit->data);
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
|
||||
curves.calculate_bezier_auto_handles();
|
||||
curves.tag_positions_changed();
|
||||
if (t->mode == TFM_CURVE_SHRINKFATTEN) {
|
||||
/* No cache to update currently. */
|
||||
}
|
||||
else if (t->mode == TFM_TILT) {
|
||||
curves.tag_normals_changed();
|
||||
}
|
||||
else {
|
||||
curves.tag_positions_changed();
|
||||
curves.calculate_bezier_auto_handles();
|
||||
}
|
||||
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
|
@ -960,6 +961,22 @@ static void TRANSFORM_OT_rotate(wmOperatorType *ot)
|
|||
P_GEO_SNAP | P_GPENCIL_EDIT | P_CENTER);
|
||||
}
|
||||
|
||||
static bool tilt_poll(bContext *C)
|
||||
{
|
||||
Object *obedit = CTX_data_edit_object(C);
|
||||
if (!obedit) {
|
||||
return false;
|
||||
}
|
||||
if (obedit->type == OB_CURVES_LEGACY) {
|
||||
Curve *cu = (Curve *)obedit->data;
|
||||
return (cu->flag & CU_3D) && (nullptr != cu->editnurb);
|
||||
}
|
||||
if (obedit->type == OB_CURVES) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void TRANSFORM_OT_tilt(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
|
@ -976,7 +993,7 @@ static void TRANSFORM_OT_tilt(wmOperatorType *ot)
|
|||
ot->exec = transform_exec;
|
||||
ot->modal = transform_modal;
|
||||
ot->cancel = transform_cancel;
|
||||
ot->poll = ED_operator_editcurve_3d;
|
||||
ot->poll = tilt_poll;
|
||||
ot->poll_property = transform_poll_property;
|
||||
|
||||
RNA_def_float_rotation(
|
||||
|
|
Loading…
Reference in New Issue