forked from blender/blender
me-main #1
@ -5628,6 +5628,7 @@ def km_curves(params):
|
||||
("curves.disable_selection", {"type": 'ONE', "value": 'PRESS', "alt": True}, None),
|
||||
("curves.disable_selection", {"type": 'TWO', "value": 'PRESS', "alt": True}, None),
|
||||
*_template_items_select_actions(params, "curves.select_all"),
|
||||
("curves.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
@ -2052,6 +2052,7 @@ class VIEW3D_MT_select_edit_curves(Menu):
|
||||
layout.operator("curves.select_all", text="Invert").action = 'INVERT'
|
||||
layout.operator("curves.select_random", text="Random")
|
||||
layout.operator("curves.select_end", text="Endpoints")
|
||||
layout.operator("curves.select_linked", text="Linked")
|
||||
|
||||
|
||||
class VIEW3D_MT_select_sculpt_curves(Menu):
|
||||
|
@ -157,6 +157,19 @@ bool curves_poll(bContext *C)
|
||||
return curves_poll_impl(C, false, false, false);
|
||||
}
|
||||
|
||||
static bool editable_curves_point_domain_poll(bContext *C)
|
||||
{
|
||||
if (!curves::editable_curves_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
|
||||
if (curves_id->selection_domain != ATTR_DOMAIN_POINT) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Only available in point selection mode");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
using bke::CurvesGeometry;
|
||||
|
||||
namespace convert_to_particle_system {
|
||||
@ -931,19 +944,6 @@ static void CURVES_OT_select_random(wmOperatorType *ot)
|
||||
1.0f);
|
||||
}
|
||||
|
||||
static bool select_end_poll(bContext *C)
|
||||
{
|
||||
if (!curves::editable_curves_poll(C)) {
|
||||
return false;
|
||||
}
|
||||
const Curves *curves_id = static_cast<const Curves *>(CTX_data_active_object(C)->data);
|
||||
if (curves_id->selection_domain != ATTR_DOMAIN_POINT) {
|
||||
CTX_wm_operator_poll_msg_set(C, "Only available in point selection mode");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int select_end_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
VectorSet<Curves *> unique_curves = curves::get_unique_editable_curves(*C);
|
||||
@ -952,7 +952,7 @@ static int select_end_exec(bContext *C, wmOperator *op)
|
||||
|
||||
for (Curves *curves_id : unique_curves) {
|
||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
select_ends(curves, eAttrDomain(curves_id->selection_domain), amount, end_points);
|
||||
select_ends(curves, amount, end_points);
|
||||
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
@ -970,7 +970,7 @@ static void CURVES_OT_select_end(wmOperatorType *ot)
|
||||
ot->description = "Select end points of curves";
|
||||
|
||||
ot->exec = select_end_exec;
|
||||
ot->poll = select_end_poll;
|
||||
ot->poll = editable_curves_point_domain_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
@ -983,6 +983,33 @@ static void CURVES_OT_select_end(wmOperatorType *ot)
|
||||
ot->srna, "amount", 1, 0, INT32_MAX, "Amount", "Number of points to select", 0, INT32_MAX);
|
||||
}
|
||||
|
||||
static int select_linked_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
VectorSet<Curves *> unique_curves = get_unique_editable_curves(*C);
|
||||
for (Curves *curves_id : unique_curves) {
|
||||
CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
select_linked(curves);
|
||||
/* Use #ID_RECALC_GEOMETRY instead of #ID_RECALC_SELECT because it is handled as a generic
|
||||
* attribute for now. */
|
||||
DEG_id_tag_update(&curves_id->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curves_id);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static void CURVES_OT_select_linked(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Select Linked";
|
||||
ot->idname = __func__;
|
||||
ot->description = "Select all points in curves with any point selection";
|
||||
|
||||
ot->exec = select_linked_exec;
|
||||
ot->poll = editable_curves_point_domain_poll;
|
||||
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
namespace surface_set {
|
||||
|
||||
static bool surface_set_poll(bContext *C)
|
||||
@ -1078,6 +1105,7 @@ void ED_operatortypes_curves()
|
||||
WM_operatortype_append(CURVES_OT_select_all);
|
||||
WM_operatortype_append(CURVES_OT_select_random);
|
||||
WM_operatortype_append(CURVES_OT_select_end);
|
||||
WM_operatortype_append(CURVES_OT_select_linked);
|
||||
WM_operatortype_append(CURVES_OT_surface_set);
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,21 @@ bool has_anything_selected(const bke::CurvesGeometry &curves)
|
||||
return !selection || contains(selection, true);
|
||||
}
|
||||
|
||||
bool has_anything_selected(const GSpan selection)
|
||||
{
|
||||
if (selection.type().is<bool>()) {
|
||||
return selection.typed<bool>().contains(true);
|
||||
}
|
||||
else if (selection.type().is<float>()) {
|
||||
for (const float elem : selection.typed<float>()) {
|
||||
if (elem > 0.0f) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void invert_selection(MutableSpan<float> selection)
|
||||
{
|
||||
threading::parallel_for(selection.index_range(), 2048, [&](IndexRange range) {
|
||||
@ -203,14 +218,12 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
|
||||
}
|
||||
}
|
||||
|
||||
void select_ends(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
int amount,
|
||||
bool end_points)
|
||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points)
|
||||
{
|
||||
const bool was_anything_selected = has_anything_selected(curves);
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, selection_domain, CD_PROP_BOOL);
|
||||
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
|
||||
if (!was_anything_selected) {
|
||||
fill_selection_true(selection.span);
|
||||
}
|
||||
@ -223,7 +236,6 @@ void select_ends(bke::CurvesGeometry &curves,
|
||||
MutableSpan<T> selection_typed = selection.span.typed<T>();
|
||||
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
if (end_points) {
|
||||
selection_typed.slice(points_by_curve[curve_i].drop_back(amount)).fill(T(0));
|
||||
}
|
||||
@ -237,6 +249,23 @@ void select_ends(bke::CurvesGeometry &curves,
|
||||
selection.finish();
|
||||
}
|
||||
|
||||
void select_linked(bke::CurvesGeometry &curves)
|
||||
{
|
||||
const OffsetIndices points_by_curve = curves.points_by_curve();
|
||||
bke::GSpanAttributeWriter selection = ensure_selection_attribute(
|
||||
curves, ATTR_DOMAIN_POINT, CD_PROP_BOOL);
|
||||
|
||||
threading::parallel_for(curves.curves_range(), 256, [&](const IndexRange range) {
|
||||
for (const int curve_i : range) {
|
||||
GMutableSpan selection_curve = selection.span.slice(points_by_curve[curve_i]);
|
||||
if (has_anything_selected(selection_curve)) {
|
||||
fill_selection_true(selection_curve);
|
||||
}
|
||||
}
|
||||
});
|
||||
selection.finish();
|
||||
}
|
||||
|
||||
void select_random(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
uint32_t random_seed,
|
||||
|
@ -89,6 +89,11 @@ void fill_selection_true(GMutableSpan span);
|
||||
*/
|
||||
bool has_anything_selected(const bke::CurvesGeometry &curves);
|
||||
|
||||
/**
|
||||
* Return true if any element in the span is selected, on either domain with either type.
|
||||
*/
|
||||
bool has_anything_selected(GSpan selection);
|
||||
|
||||
/**
|
||||
* Find curves that have any point selected (a selection factor greater than zero),
|
||||
* or curves that have their own selection factor greater than zero.
|
||||
@ -123,10 +128,12 @@ void select_all(bke::CurvesGeometry &curves, const eAttrDomain selection_domain,
|
||||
* \param amount: The amount of points to select from the front or back.
|
||||
* \param end_points: If true, select the last point(s), if false, select the first point(s).
|
||||
*/
|
||||
void select_ends(bke::CurvesGeometry &curves,
|
||||
const eAttrDomain selection_domain,
|
||||
int amount,
|
||||
bool end_points);
|
||||
void select_ends(bke::CurvesGeometry &curves, int amount, bool end_points);
|
||||
|
||||
/**
|
||||
* Select the points of all curves that have at least one point selected.
|
||||
*/
|
||||
void select_linked(bke::CurvesGeometry &curves);
|
||||
|
||||
/**
|
||||
* Select random points or curves.
|
||||
|
Loading…
Reference in New Issue
Block a user