Refactor: Use FunctionRef for BM_mesh_edgeloops functions

Refactor the BM_mesh_edgeloops functions to use FunctionRef.

Pull Request: https://projects.blender.org/blender/blender/pulls/161354
This commit is contained in:
Tariq-Sulley 2026-07-16 22:12:14 +02:00 • committed by Tariq Sulley
parent 74e09d7579
commit 92f6b2d466
9 changed files with 38 additions and 80 deletions

View file

@ -151,8 +151,7 @@ static bool bm_loop_build(BMEdgeLoopStore *el_store,
int BM_mesh_edgeloops_find(BMesh *bm,
ListBaseT<BMEdgeLoopStore> *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
void *user_data,
FunctionRef<bool(BMEdge *)> test_fn,
const BMEdgeLoopFind_Params *params)
{
BMIter iter;
@ -169,7 +168,7 @@ int BM_mesh_edgeloops_find(BMesh *bm,
BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
BLI_assert(!BM_elem_flag_test(e, BM_ELEM_INTERNAL_TAG));
if (test_fn(e, user_data)) {
if (test_fn(e)) {
BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);
@ -337,8 +336,7 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool,
bool BM_mesh_edgeloops_find_path(BMesh *bm,
ListBaseT<BMEdgeLoopStore> *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
void *user_data,
FunctionRef<bool(BMEdge *)> test_fn,
BMVert *v_src,
BMVert *v_dst)
{
@ -364,7 +362,7 @@ bool BM_mesh_edgeloops_find_path(BMesh *bm,
if (test_fn) {
BLI_Stack *edge_stack = BLI_stack_new(sizeof(BMEdge *), __func__);
BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
if (test_fn(e, user_data)) {
if (test_fn(e)) {
BM_elem_flag_enable(e, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(e->v1, BM_ELEM_INTERNAL_TAG);
BM_elem_flag_enable(e->v2, BM_ELEM_INTERNAL_TAG);

View file

@ -12,6 +12,7 @@
#include "DNA_listBase.h"
#include "BLI_function_ref.hh"
#include "BLI_set.hh"
namespace blender {
@ -35,13 +36,11 @@ struct BMEdgeLoopFind_Params {
*/
int BM_mesh_edgeloops_find(BMesh *bm,
ListBaseT<BMEdgeLoopStore> *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
void *user_data,
FunctionRef<bool(BMEdge *)> test_fn,
const BMEdgeLoopFind_Params *params = nullptr);
bool BM_mesh_edgeloops_find_path(BMesh *bm,
ListBaseT<BMEdgeLoopStore> *r_eloops,
bool (*test_fn)(BMEdge *, void *user_data),
void *user_data,
FunctionRef<bool(BMEdge *)> test_fn,
BMVert *v_src,
BMVert *v_dst);

View file

@ -128,11 +128,6 @@ static void bm_face_edges_tag_out(BMesh *bm, BMFace *f)
} while ((l_iter = l_iter->next) != l_first);
}
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
{
return BMO_edge_flag_test((BMesh *)bm_v, e, EDGE_MARK);
}
static void bridge_loop_pair(BMesh *bm,
BMEdgeLoopStore *el_store_a,
BMEdgeLoopStore *el_store_b,
@ -591,7 +586,8 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op)
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, bm);
count = BM_mesh_edgeloops_find(
bm, &eloops, [&](BMEdge *e) { return BMO_edge_flag_test(bm, e, EDGE_MARK); });
BM_mesh_edgeloops_calc_center(bm, &eloops);

View file

@ -100,17 +100,6 @@ static bool is_valid_boundary_edge(BMEdge *e, const char hflag, const bool check
return true;
}
struct CircularizeEdgeTestParams {
char hflag;
const bool *check_axis;
};
static bool bm_edge_circularize_test_cb(BMEdge *e, void *user_data)
{
const auto *params = static_cast<const CircularizeEdgeTestParams *>(user_data);
return is_valid_boundary_edge(e, params->hflag, params->check_axis);
}
/** Collects all valid boundary edge chains from the current selection. */
static void bm_vert_chain_extract_from_boundary_edges(BMesh *bm,
Vector<VertChain> &r_chains,
@ -121,12 +110,12 @@ static void bm_vert_chain_extract_from_boundary_edges(BMesh *bm,
const BMEdgeLoopFind_Params params = {
.use_vert_junction = true,
};
CircularizeEdgeTestParams test_params = {
.hflag = hflag,
.check_axis = check_axis,
};
BM_mesh_edgeloops_find(bm, &eloops, bm_edge_circularize_test_cb, &test_params, &params);
BM_mesh_edgeloops_find(
bm,
&eloops,
[&](BMEdge *e) { return is_valid_boundary_edge(e, hflag, check_axis); },
&params);
for (BMEdgeLoopStore &el_store : eloops) {
VertChain chain;

View file

@ -574,21 +574,6 @@ static void bm_edgeloop_flag_set(BMEdgeLoopStore *estore, char hflag, bool set)
}
}
static bool bm_edge_test_cb(BMEdge *e, void *bm_v)
{
return BMO_edge_flag_test_bool((BMesh *)bm_v, e, EDGE_MARK);
}
static bool bm_edge_test_rail_cb(BMEdge *e, void * /*bm_v*/)
{
/* Normally operators don't check for hidden state
* but alternative would be to pass slot of rail edges. */
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
return false;
}
return BM_edge_is_wire(e) || BM_edge_is_boundary(e);
}
void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
{
ListBaseT<BMEdgeLoopStore> eloops = {nullptr, nullptr};
@ -604,9 +589,20 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
int count;
bool changed = false;
const auto edge_test_rail_fn = [](BMEdge *e) {
/* Normally operators don't check for hidden state
* but alternative would be to pass slot of rail edges. */
if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
return false;
}
return BM_edge_is_wire(e) || BM_edge_is_boundary(e);
};
BMO_slot_buffer_flag_enable(bm, op->slots_in, "edges", BM_EDGE, EDGE_MARK);
count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, static_cast<void *>(bm));
count = BM_mesh_edgeloops_find(
bm, &eloops, [&](BMEdge *e) { return BMO_edge_flag_test(bm, e, EDGE_MARK); });
if (count != 2) {
/* Note that this error message has been adjusted to make sense when called
@ -644,9 +640,8 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
bm_edgeloop_flag_set(estore_a, BM_ELEM_HIDDEN, true);
bm_edgeloop_flag_set(estore_b, BM_ELEM_HIDDEN, true);
if (BM_mesh_edgeloops_find_path(
bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_first) &&
BM_mesh_edgeloops_find_path(bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_last))
if (BM_mesh_edgeloops_find_path(bm, &eloops_rail, edge_test_rail_fn, v_a_first, v_b_first) &&
BM_mesh_edgeloops_find_path(bm, &eloops_rail, edge_test_rail_fn, v_a_last, v_b_last))
{
estore_rail_a = static_cast<BMEdgeLoopStore *>(eloops_rail.first);
estore_rail_b = static_cast<BMEdgeLoopStore *>(eloops_rail.last);
@ -654,10 +649,8 @@ void bmo_grid_fill_exec(BMesh *bm, BMOperator *op)
else {
BM_mesh_edgeloops_free(&eloops_rail);
if (BM_mesh_edgeloops_find_path(
bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_first, v_b_last) &&
BM_mesh_edgeloops_find_path(
bm, &eloops_rail, bm_edge_test_rail_cb, bm, v_a_last, v_b_first))
if (BM_mesh_edgeloops_find_path(bm, &eloops_rail, edge_test_rail_fn, v_a_first, v_b_last) &&
BM_mesh_edgeloops_find_path(bm, &eloops_rail, edge_test_rail_fn, v_a_last, v_b_first))
{
estore_rail_a = static_cast<BMEdgeLoopStore *>(eloops_rail.first);
estore_rail_b = static_cast<BMEdgeLoopStore *>(eloops_rail.last);

View file

@ -209,18 +209,14 @@ static void build_relax_phases(int verts_num, bool is_closed, Vector<RelaxPhase>
}
}
static bool bm_edge_relax_test_cb(BMEdge *e, void * /*user_data*/)
{
return BM_elem_flag_test(e, BM_ELEM_TAG);
}
static void get_relax_input_chains(BMesh *bm, Vector<RelaxChainData> &r_chains)
{
ListBaseT<BMEdgeLoopStore> eloops = {nullptr};
const BMEdgeLoopFind_Params params = {
.use_vert_junction = true,
};
BM_mesh_edgeloops_find(bm, &eloops, bm_edge_relax_test_cb, nullptr, &params);
BM_mesh_edgeloops_find(
bm, &eloops, [](BMEdge *e) { return BM_elem_flag_test(e, BM_ELEM_TAG); }, &params);
for (BMEdgeLoopStore &el_store : eloops) {
RelaxChainData chain;

View file

@ -73,11 +73,6 @@ struct SplineCoeffs {
float x;
};
static bool bm_edge_space_test_cb(BMEdge *e, void * /*user_data*/)
{
return BM_elem_flag_test(e, BM_ELEM_TAG);
}
/**
* Build vertex chains from selected edges.
*/
@ -87,7 +82,8 @@ static void get_space_input_chains(BMesh *bm, Vector<SpaceChainData> &r_chains)
const BMEdgeLoopFind_Params params = {
.use_vert_junction = true,
};
BM_mesh_edgeloops_find(bm, &eloops, bm_edge_space_test_cb, nullptr, &params);
BM_mesh_edgeloops_find(
bm, &eloops, [](BMEdge *e) { return BM_elem_flag_test(e, BM_ELEM_TAG); }, &params);
for (BMEdgeLoopStore &el_store : eloops) {
SpaceChainData chain;

View file

@ -1077,12 +1077,6 @@ static void bm_edgering_pair_ringsubd(BMesh *bm,
BM_mesh_edgeloops_free(&eloops_ring);
}
static bool bm_edge_rim_test_cb(BMEdge *e, void *bm_v)
{
BMesh *bm = static_cast<BMesh *>(bm_v);
return BMO_edge_flag_test_bool(bm, e, EDGE_RIM);
}
void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
{
/* NOTE: keep this operator fast, its used in a modifier. */
@ -1163,7 +1157,8 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op)
/* -------------------------------------------------------------------- */
/* Execute subdivision on all ring pairs */
count = BM_mesh_edgeloops_find(bm, &eloops_rim, bm_edge_rim_test_cb, static_cast<void *>(bm));
count = BM_mesh_edgeloops_find(
bm, &eloops_rim, [&](BMEdge *e) { return BMO_edge_flag_test_bool(bm, e, EDGE_RIM); });
if (count < 2) {
BMO_error_raise(bm, op, BMO_ERROR_CANCEL, "No edge rings found");

View file

@ -4764,11 +4764,6 @@ void MESH_OT_fill(wmOperatorType *ot)
/** \name Grid Fill Operator
* \{ */
static bool bm_edge_test_fill_grid_cb(BMEdge *e, void * /*bm_v*/)
{
return BM_elem_flag_test_bool(e, BM_ELEM_SELECT);
}
static float edbm_fill_grid_vert_tag_angle(BMVert *v)
{
BMIter iter;
@ -4802,7 +4797,8 @@ static bool edbm_fill_grid_prepare(BMesh *bm, int offset, int *span_p, const boo
BMEdgeLoopStore *el_store;
// LinkData *el_store;
count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm);
count = BM_mesh_edgeloops_find(
bm, &eloops, [](BMEdge *e) { return BM_elem_flag_test_bool(e, BM_ELEM_SELECT); });
el_store = static_cast<BMEdgeLoopStore *>(eloops.first);
if (count != 1) {