Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-09-23 17:38:37 +0300
committerHans Goudey <h.goudey@me.com>2022-09-23 18:45:07 +0300
commit12becbf0dffe06b6f28c4cc444fe0312cf9249b9 (patch)
treefb7b54e30e9144021ba0714e0c2dd78eb8f5e928 /source/blender/editors/space_view3d
parente345686cb7f4a8ccdc10e85d4f05cded45850cf7 (diff)
Mesh: Move selection flags to generic attributes
Using the attribute name semantics from T97452, this patch moves the selection status of mesh elements from the `SELECT` of vertices, and edges, and the `ME_FACE_SEL` of faces to generic boolean attribute Storing this data as generic attributes can significantly simplify and improve code, as described in T95965. The attributes are called `.select_vert`, `.select_edge`, and `.select_poly`. The `.` prefix means they are "UI attributes",so they still contain original data edited by users, but they aren't meant to be accessed procedurally by the user in arbitrary situations. They are also be hidden in the spreadsheet and the attribute list. Until 4.0, the attributes are still written to and read from the mesh in the old way, so neither forward nor backward compatibility are affected. This means memory requirements will be increased by one byte per element when selection is used. When the flags are removed completely, requirements will decrease. Further notes: * The `MVert` flag is empty at runtime now, so it can be ignored. * `BMesh` is unchanged, otherwise the change would be much larger. * Many tests have slightly different results, since the selection attribute uses more generic propagation. Previously you couldn't really rely on edit mode selections being propagated procedurally. Now it mostly works as expected. Similar to 2480b55f216c Ref T95965 Differential Revision: https://developer.blender.org/D15795
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/view3d_select.cc167
1 files changed, 107 insertions, 60 deletions
diff --git a/source/blender/editors/space_view3d/view3d_select.cc b/source/blender/editors/space_view3d/view3d_select.cc
index 447bf99b000..a0b3802076a 100644
--- a/source/blender/editors/space_view3d/view3d_select.cc
+++ b/source/blender/editors/space_view3d/view3d_select.cc
@@ -45,6 +45,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
+#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
@@ -337,28 +338,29 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me,
EditSelectBuf_Cache *esel,
const eSelectOp sel_op)
{
- MVert *verts = BKE_mesh_verts_for_write(me);
- MVert *mv = verts;
+ using namespace blender;
bool changed = false;
const BLI_bitmap *select_bitmap = esel->select_bitmap;
- if (mv) {
- const bool *hide_vert = (const bool *)CustomData_get_layer_named(
- &me->vdata, CD_PROP_BOOL, ".hide_vert");
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT);
+ const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
+ ".hide_vert", ATTR_DOMAIN_POINT, false);
- for (int index = 0; index < me->totvert; index++, mv++) {
- if (!(hide_vert && hide_vert[index])) {
- const bool is_select = mv->flag & SELECT;
- const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
- changed = true;
- }
+ for (int index = 0; index < me->totvert; index++) {
+ if (!hide_vert[index]) {
+ const bool is_select = select_vert.span[index];
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ select_vert.span[index] = sel_op_result == 1;
+ changed = true;
}
}
}
+ select_vert.finish();
return changed;
}
@@ -367,27 +369,29 @@ static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me,
EditSelectBuf_Cache *esel,
const eSelectOp sel_op)
{
- MPoly *polys = BKE_mesh_polys_for_write(me);
+ using namespace blender;
bool changed = false;
const BLI_bitmap *select_bitmap = esel->select_bitmap;
- if (polys) {
- const bool *hide_poly = (const bool *)CustomData_get_layer_named(
- &me->vdata, CD_PROP_BOOL, ".hide_poly");
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::SpanAttributeWriter<bool> select_poly = attributes.lookup_or_add_for_write_span<bool>(
+ ".select_poly", ATTR_DOMAIN_FACE);
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
- for (int index = 0; index < me->totpoly; index++) {
- if (!(hide_poly && hide_poly[index])) {
- const bool is_select = polys[index].flag & ME_FACE_SEL;
- const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(polys[index].flag, sel_op_result, ME_FACE_SEL);
- changed = true;
- }
+ for (int index = 0; index < me->totpoly; index++) {
+ if (!hide_poly[index]) {
+ const bool is_select = select_poly.span[index];
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
+ const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
+ if (sel_op_result != -1) {
+ select_poly.span[index] = sel_op_result == 1;
+ changed = true;
}
}
}
+ select_poly.finish();
return changed;
}
@@ -1154,20 +1158,27 @@ static bool do_lasso_select_meta(ViewContext *vc,
return data.is_changed;
}
+struct LassoSelectUserData_ForMeshVert {
+ LassoSelectUserData lasso_data;
+ blender::MutableSpan<bool> select_vert;
+};
static void do_lasso_select_meshobject__doSelectVert(void *userData,
- MVert *mv,
+ MVert * /*mv*/,
const float screen_co[2],
- int UNUSED(index))
+ int index)
{
- LassoSelectUserData *data = static_cast<LassoSelectUserData *>(userData);
- const bool is_select = mv->flag & SELECT;
+ using namespace blender;
+ LassoSelectUserData_ForMeshVert *mesh_data = static_cast<LassoSelectUserData_ForMeshVert *>(
+ userData);
+ LassoSelectUserData *data = &mesh_data->lasso_data;
+ const bool is_select = mesh_data->select_vert[index];
const bool is_inside =
(BLI_rctf_isect_pt_v(data->rect_fl, screen_co) &&
BLI_lasso_is_point_inside(
data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
+ mesh_data->select_vert[index] = sel_op_result == 1;
data->is_changed = true;
}
}
@@ -1177,6 +1188,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
const int mcoords_len,
const eSelectOp sel_op)
{
+ using namespace blender;
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
Object *ob = vc->obact;
Mesh *me = static_cast<Mesh *>(ob->data);
@@ -1210,16 +1222,22 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
}
}
else {
- LassoSelectUserData data;
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT);
+
+ LassoSelectUserData_ForMeshVert data;
+ data.select_vert = select_vert.span;
- view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op);
+ view3d_userdata_lassoselect_init(&data.lasso_data, vc, &rect, mcoords, mcoords_len, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
meshobject_foreachScreenVert(
vc, do_lasso_select_meshobject__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
+ changed |= data.lasso_data.is_changed;
+ select_vert.finish();
}
if (changed) {
@@ -2825,20 +2843,22 @@ static bool ed_wpaint_vertex_select_pick(bContext *C,
const SelectPick_Params *params,
Object *obact)
{
+ using namespace blender;
View3D *v3d = CTX_wm_view3d(C);
const bool use_zbuf = !XRAY_ENABLED(v3d);
Mesh *me = static_cast<Mesh *>(obact->data); /* already checked for nullptr */
uint index = 0;
- MVert *verts = BKE_mesh_verts_for_write(me);
-
- MVert *mv;
bool changed = false;
bool found = ED_mesh_pick_vert(C, obact, mval, ED_MESH_PICK_DEFAULT_VERT_DIST, use_zbuf, &index);
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::AttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT);
+
if (params->sel_op == SEL_OP_SET) {
- if ((found && params->select_passthrough) && (verts[index].flag & SELECT)) {
+ if ((found && params->select_passthrough) && select_vert.varray[index]) {
found = false;
}
else if (found || params->deselect_all) {
@@ -2848,23 +2868,22 @@ static bool ed_wpaint_vertex_select_pick(bContext *C,
}
if (found) {
- mv = &verts[index];
switch (params->sel_op) {
case SEL_OP_ADD: {
- mv->flag |= SELECT;
+ select_vert.varray.set(index, true);
break;
}
case SEL_OP_SUB: {
- mv->flag &= ~SELECT;
+ select_vert.varray.set(index, false);
break;
}
case SEL_OP_XOR: {
- mv->flag ^= SELECT;
+ select_vert.varray.set(index, !select_vert.varray[index]);
break;
}
case SEL_OP_SET: {
paintvert_deselect_all_visible(obact, SEL_DESELECT, false);
- mv->flag |= SELECT;
+ select_vert.varray.set(index, true);
break;
}
case SEL_OP_AND: {
@@ -2874,13 +2893,15 @@ static bool ed_wpaint_vertex_select_pick(bContext *C,
}
/* update mselect */
- if (mv->flag & SELECT) {
+ if (select_vert.varray[index]) {
BKE_mesh_mselect_active_set(me, index, ME_VSEL);
}
else {
BKE_mesh_mselect_validate(me);
}
+ select_vert.finish();
+
paintvert_flush_flags(obact);
changed = true;
@@ -3117,17 +3138,23 @@ bool edge_inside_circle(const float cent[2],
return (dist_squared_to_line_segment_v2(cent, screen_co_a, screen_co_b) < radius_squared);
}
+struct BoxSelectUserData_ForMeshVert {
+ BoxSelectUserData box_data;
+ blender::MutableSpan<bool> select_vert;
+};
static void do_paintvert_box_select__doSelectVert(void *userData,
- MVert *mv,
+ MVert * /*mv*/,
const float screen_co[2],
- int UNUSED(index))
+ int index)
{
- BoxSelectUserData *data = static_cast<BoxSelectUserData *>(userData);
- const bool is_select = mv->flag & SELECT;
+ BoxSelectUserData_ForMeshVert *mesh_data = static_cast<BoxSelectUserData_ForMeshVert *>(
+ userData);
+ BoxSelectUserData *data = &mesh_data->box_data;
+ const bool is_select = mesh_data->select_vert[index];
const bool is_inside = BLI_rctf_isect_pt_v(data->rect_fl, screen_co);
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
+ mesh_data->select_vert[index] = sel_op_result == 1;
data->is_changed = true;
}
}
@@ -3136,6 +3163,7 @@ static bool do_paintvert_box_select(ViewContext *vc,
const rcti *rect,
const eSelectOp sel_op)
{
+ using namespace blender;
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
Mesh *me = static_cast<Mesh *>(vc->obact->data);
@@ -3164,15 +3192,21 @@ static bool do_paintvert_box_select(ViewContext *vc,
}
}
else {
- BoxSelectUserData data;
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT);
- view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
+ BoxSelectUserData_ForMeshVert data;
+ data.select_vert = select_vert.span;
+
+ view3d_userdata_boxselect_init(&data.box_data, vc, rect, sel_op);
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d);
meshobject_foreachScreenVert(
vc, do_paintvert_box_select__doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
+ changed |= data.box_data.is_changed;
+ select_vert.finish();
}
if (changed) {
@@ -4124,15 +4158,21 @@ static bool paint_facesel_circle_select(ViewContext *vc,
return changed;
}
+struct CircleSelectUserData_ForMeshVert {
+ CircleSelectUserData circle_data;
+ blender::MutableSpan<bool> select_vert;
+};
static void paint_vertsel_circle_select_doSelectVert(void *userData,
- MVert *mv,
+ MVert * /*mv*/,
const float screen_co[2],
- int UNUSED(index))
+ int index)
{
- CircleSelectUserData *data = static_cast<CircleSelectUserData *>(userData);
+ CircleSelectUserData_ForMeshVert *mesh_data = static_cast<CircleSelectUserData_ForMeshVert *>(
+ userData);
+ CircleSelectUserData *data = &mesh_data->circle_data;
if (len_squared_v2v2(data->mval_fl, screen_co) <= data->radius_squared) {
- SET_FLAG_FROM_TEST(mv->flag, data->select, SELECT);
+ mesh_data->select_vert[index] = data->select;
data->is_changed = true;
}
}
@@ -4142,6 +4182,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
const int mval[2],
float rad)
{
+ using namespace blender;
BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
Object *ob = vc->obact;
@@ -4173,14 +4214,20 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
}
}
else {
- CircleSelectUserData data;
+ bke::MutableAttributeAccessor attributes = me->attributes_for_write();
+ bke::SpanAttributeWriter<bool> select_vert = attributes.lookup_or_add_for_write_span<bool>(
+ ".select_vert", ATTR_DOMAIN_POINT);
+
+ CircleSelectUserData_ForMeshVert data;
+ data.select_vert = select_vert.span;
ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); /* for foreach's screen/vert projection */
- view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ view3d_userdata_circleselect_init(&data.circle_data, vc, select, mval, rad);
meshobject_foreachScreenVert(
vc, paint_vertsel_circle_select_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
- changed |= data.is_changed;
+ changed |= data.circle_data.is_changed;
+ select_vert.finish();
}
if (changed) {