Curves: add subdivide curves edit mode operator
This commit is contained in:
parent
6c25c66194
commit
548df007a5
@ -5923,6 +5923,7 @@ class VIEW3D_MT_edit_curves_segments(Menu):
|
||||
def draw(self, _context):
|
||||
layout = self.layout
|
||||
|
||||
layout.operator("curves.subdivide")
|
||||
layout.operator("curves.switch_direction")
|
||||
|
||||
|
||||
|
@ -65,6 +65,7 @@
|
||||
|
||||
#include "GEO_reverse_uv_sampler.hh"
|
||||
#include "GEO_set_curve_type.hh"
|
||||
#include "GEO_subdivide_curves.hh"
|
||||
|
||||
/**
|
||||
* The code below uses a suffix naming convention to indicate the coordinate space:
|
||||
@ -1457,6 +1458,73 @@ static void CURVES_OT_switch_direction(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
namespace subdivide {
|
||||
|
||||
static int exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const int number_cuts = RNA_int_get(op->ptr, "number_cuts");
|
||||
|
||||
for (Curves *curves_id : get_unique_editable_curves(*C)) {
|
||||
bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
const int points_num = curves.points_num();
|
||||
IndexMaskMemory memory;
|
||||
const IndexMask points_selection = retrieve_selected_points(*curves_id, memory);
|
||||
if (points_selection.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Array<bool> points_selection_span(points_num);
|
||||
points_selection.to_bools(points_selection_span);
|
||||
|
||||
Array<int> segment_cuts(points_num, number_cuts);
|
||||
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
threading::parallel_for(points_by_curve.index_range(), 512, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
const IndexRange points = points_by_curve[curve_i];
|
||||
if (points.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
for (const int point_i : points.drop_back(1)) {
|
||||
if (!points_selection_span[point_i] || !points_selection_span[point_i + 1]) {
|
||||
segment_cuts[point_i] = 0;
|
||||
}
|
||||
}
|
||||
/* Cyclic segment. Doesn't matter if it is computed even if the curve is not cyclic. */
|
||||
if (!points_selection_span[points.last()] || !points_selection_span[points.first()]) {
|
||||
segment_cuts[points.last()] = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
curves = geometry::subdivide_curves(
|
||||
curves, curves.curves_range(), VArray<int>::ForSpan(segment_cuts), {});
|
||||
|
||||
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 subdivide
|
||||
|
||||
static void CURVES_OT_subdivide(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Subdivide";
|
||||
ot->idname = __func__;
|
||||
ot->description = "Subdivide selected curve segments";
|
||||
|
||||
ot->exec = subdivide::exec;
|
||||
ot->poll = editable_curves_in_edit_mode_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
PropertyRNA *prop;
|
||||
prop = RNA_def_int(ot->srna, "number_cuts", 1, 1, 1000, "Number of Cuts", "", 1, 10);
|
||||
/* Avoid re-using last value because it can cause an unexpectedly high number of subdivisions. */
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
void operatortypes_curves()
|
||||
{
|
||||
WM_operatortype_append(CURVES_OT_attribute_set);
|
||||
@ -1479,6 +1547,7 @@ void operatortypes_curves()
|
||||
WM_operatortype_append(CURVES_OT_cyclic_toggle);
|
||||
WM_operatortype_append(CURVES_OT_curve_type_set);
|
||||
WM_operatortype_append(CURVES_OT_switch_direction);
|
||||
WM_operatortype_append(CURVES_OT_subdivide);
|
||||
}
|
||||
|
||||
void operatormacros_curves()
|
||||
|
Loading…
Reference in New Issue
Block a user