Merge remote-tracking branch 'origin/blender-v4.5-release'
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
#include "ED_numinput.hh"
|
||||
@@ -732,6 +733,60 @@ struct TransDataContainer {
|
||||
* \see #sort_trans_data_dist Sorts by selection state and distance.
|
||||
*/
|
||||
int *sorted_index_map;
|
||||
|
||||
/**
|
||||
* Call the given function for each index in the data. This index can then be
|
||||
* used to access the `data`, `data_ext`, and `data_2d` arrays.
|
||||
*
|
||||
* If there is a `sorted_index_map` (see above), this will be used. Otherwise
|
||||
* it is assumed that the arrays can be iterated in their natural array order.
|
||||
*
|
||||
* \param fn: function that's called for each index. The function should
|
||||
* return whether to keep looping (true) or break out of the loop (false).
|
||||
*
|
||||
* \return whether the end of the loop was reached.
|
||||
*/
|
||||
bool foreach_index(FunctionRef<bool(int)> fn) const
|
||||
{
|
||||
if (this->sorted_index_map) {
|
||||
for (const int i : Span(this->sorted_index_map, this->data_len)) {
|
||||
if (!fn(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (const int i : IndexRange(this->data_len)) {
|
||||
if (!fn(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call \a fn only for indices of selected items.
|
||||
* Apart from that, this is the same as `index_map()` above.
|
||||
*
|
||||
* \param fn: function that's called for each index. Contrary to the `index_map()` function, it
|
||||
* is assumed that all selected items should be visited, and so for simplicity there is no `bool`
|
||||
* to return.
|
||||
*/
|
||||
void foreach_index_selected(FunctionRef<void(int)> fn) const
|
||||
{
|
||||
this->foreach_index([&](const int i) {
|
||||
const bool is_selected = (this->data[i].flag & TD_SELECTED);
|
||||
if (!is_selected) {
|
||||
/* Selected items are sorted first. Either this is trivially true
|
||||
* (proportional editing off, so the only transformed data is the
|
||||
* selected data) or it's handled by `sorted_index_map`. */
|
||||
return false;
|
||||
}
|
||||
fn(i);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
struct TransInfo {
|
||||
|
||||
@@ -215,8 +215,6 @@ static float3 prop_dist_loc_get(const TransDataContainer *tc,
|
||||
*/
|
||||
static void set_prop_dist(TransInfo *t, const bool with_dist)
|
||||
{
|
||||
int a;
|
||||
|
||||
float _proj_vec[3];
|
||||
const float *proj_vec = nullptr;
|
||||
|
||||
@@ -235,16 +233,7 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
|
||||
int td_table_len = 0;
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (td->flag & TD_SELECTED) {
|
||||
td_table_len++;
|
||||
}
|
||||
else {
|
||||
/* By definition transform-data has selected items in beginning. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
tc->foreach_index_selected([&](const int /*i*/) { td_table_len++; });
|
||||
}
|
||||
|
||||
/* Pointers to selected's #TransData.
|
||||
@@ -257,23 +246,16 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
|
||||
|
||||
int td_table_index = 0;
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (td->flag & TD_SELECTED) {
|
||||
/* Initialize, it was malloced. */
|
||||
td->rdist = 0.0f;
|
||||
/* Initialize, it was malloced. */
|
||||
td->rdist = 0.0f;
|
||||
|
||||
const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
|
||||
const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
|
||||
|
||||
BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
|
||||
td_table[td_table_index++] = td;
|
||||
}
|
||||
else {
|
||||
/* By definition transform-data has selected items in beginning. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
|
||||
td_table[td_table_index++] = td;
|
||||
});
|
||||
}
|
||||
BLI_assert(td_table_index == td_table_len);
|
||||
|
||||
@@ -281,29 +263,32 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
|
||||
|
||||
/* For each non-selected vertex, find distance to the nearest selected vertex. */
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
TransData *td = tc->data;
|
||||
for (a = 0; a < tc->data_len; a++, td++) {
|
||||
if ((td->flag & TD_SELECTED) == 0) {
|
||||
const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
|
||||
tc->foreach_index([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (td->flag & TD_SELECTED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
KDTreeNearest_3d nearest;
|
||||
const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
|
||||
const float3 vec = prop_dist_loc_get(tc, td, use_island, proj_vec);
|
||||
|
||||
td->rdist = -1.0f;
|
||||
if (td_index != -1) {
|
||||
td->rdist = nearest.dist;
|
||||
if (use_island) {
|
||||
/* Use center and axismtx of closest point found. */
|
||||
copy_v3_v3(td->center, td_table[td_index]->center);
|
||||
copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
|
||||
}
|
||||
}
|
||||
KDTreeNearest_3d nearest;
|
||||
const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
|
||||
|
||||
if (with_dist) {
|
||||
td->dist = td->rdist;
|
||||
td->rdist = -1.0f;
|
||||
if (td_index != -1) {
|
||||
td->rdist = nearest.dist;
|
||||
if (use_island) {
|
||||
/* Use center and axismtx of closest point found. */
|
||||
copy_v3_v3(td->center, td_table[td_index]->center);
|
||||
copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (with_dist) {
|
||||
td->dist = td->rdist;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
BLI_kdtree_3d_free(td_tree);
|
||||
|
||||
@@ -2161,25 +2161,13 @@ Array<TransDataVertSlideVert> transform_mesh_vert_slide_data_create(
|
||||
const TransDataContainer *tc, Vector<float3> &r_loc_dst_buffer)
|
||||
{
|
||||
int td_selected_len = 0;
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
/* The selected ones are sorted at the beginning. */
|
||||
break;
|
||||
}
|
||||
td_selected_len++;
|
||||
}
|
||||
tc->foreach_index_selected([&](const int /*i*/) { td_selected_len++; });
|
||||
|
||||
Array<TransDataVertSlideVert> r_sv(td_selected_len);
|
||||
|
||||
r_loc_dst_buffer.reserve(r_sv.size() * 4);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
/* The selected ones are sorted at the beginning. */
|
||||
break;
|
||||
}
|
||||
const int size_prev = r_loc_dst_buffer.size();
|
||||
|
||||
BMVert *v = static_cast<BMVert *>(td->extra);
|
||||
@@ -2205,7 +2193,7 @@ Array<TransDataVertSlideVert> transform_mesh_vert_slide_data_create(
|
||||
|
||||
/* Store the buffer size temporarily in `target_curr`. */
|
||||
sv.co_link_curr = r_loc_dst_buffer.size() - size_prev;
|
||||
}
|
||||
});
|
||||
|
||||
int start = 0;
|
||||
for (TransDataVertSlideVert &sv : r_sv) {
|
||||
@@ -2297,20 +2285,21 @@ Array<TransDataEdgeSlideVert> transform_mesh_edge_slide_data_create(const TransD
|
||||
/* Ensure valid selection. */
|
||||
BMIter iter;
|
||||
BMVert *v;
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
bool found_invalid_edge_selection = false;
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
/* The selected ones are sorted at the beginning. */
|
||||
break;
|
||||
}
|
||||
v = static_cast<BMVert *>(td->extra);
|
||||
int numsel = BM_iter_elem_count_flag(BM_EDGES_OF_VERT, v, BM_ELEM_SELECT, true);
|
||||
if (numsel == 0 || numsel > 2) {
|
||||
/* Invalid edge selection. */
|
||||
return {};
|
||||
found_invalid_edge_selection = true;
|
||||
return;
|
||||
}
|
||||
td_selected_len++;
|
||||
});
|
||||
|
||||
if (found_invalid_edge_selection) {
|
||||
return {};
|
||||
}
|
||||
|
||||
BMEdge *e;
|
||||
@@ -2334,11 +2323,9 @@ Array<TransDataEdgeSlideVert> transform_mesh_edge_slide_data_create(const TransD
|
||||
Array<TransDataEdgeSlideVert> r_sv(td_selected_len);
|
||||
TransDataEdgeSlideVert *sv = r_sv.data();
|
||||
int sv_index = 0;
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sv->td = td;
|
||||
sv->loop_nr = -1;
|
||||
sv->dir_side[0] = float3(0);
|
||||
@@ -2349,7 +2336,7 @@ Array<TransDataEdgeSlideVert> transform_mesh_edge_slide_data_create(const TransD
|
||||
BM_elem_index_set(v, sv_index);
|
||||
sv_index++;
|
||||
sv++;
|
||||
}
|
||||
});
|
||||
|
||||
/* Map indicating the indexes of #TransData connected by edge. */
|
||||
Array<int2> td_connected(tc->data_len, int2(-1, -1));
|
||||
|
||||
@@ -502,18 +502,13 @@ struct UVGroups {
|
||||
|
||||
/* Now, count and set the index for the corners being transformed. */
|
||||
this->sd_len = 0;
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
/* The selected ones are sorted at the beginning. */
|
||||
break;
|
||||
}
|
||||
this->sd_len++;
|
||||
|
||||
BMLoop *l = static_cast<BMLoop *>(td->extra);
|
||||
BM_elem_index_set(l, i);
|
||||
}
|
||||
});
|
||||
bm->elem_index_dirty |= BM_LOOP;
|
||||
|
||||
/* Create the groups. */
|
||||
@@ -840,17 +835,12 @@ Array<TransDataEdgeSlideVert> transform_mesh_uv_edge_slide_data_create(const Tra
|
||||
|
||||
/* First we just need to "clean up" the neighboring loops.
|
||||
* This way we can identify where a group of sliding edges starts and where it ends. */
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
/* The selected ones are sorted at the beginning. */
|
||||
break;
|
||||
}
|
||||
BMLoop *l = static_cast<BMLoop *>(td->extra);
|
||||
BM_elem_index_set(l->prev, -1);
|
||||
BM_elem_index_set(l->next, -1);
|
||||
}
|
||||
});
|
||||
|
||||
/* Now set the group indexes. */
|
||||
for (const int group_index : uv_groups->groups().index_range()) {
|
||||
|
||||
@@ -1377,14 +1377,7 @@ void tranform_snap_target_median_calc(const TransInfo *t, float r_median[3])
|
||||
float v[3];
|
||||
zero_v3(v);
|
||||
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
break;
|
||||
}
|
||||
add_v3_v3(v, td->center);
|
||||
}
|
||||
tc->foreach_index_selected([&](const int i) { add_v3_v3(v, tc->data[i].center); });
|
||||
|
||||
if (tc->data_len == 0) {
|
||||
/* Is this possible? */
|
||||
@@ -1468,11 +1461,8 @@ static void snap_source_closest_fn(TransInfo *t)
|
||||
if (t->options & CTX_OBJECT) {
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::optional<Bounds<float3>> bounds;
|
||||
|
||||
@@ -1520,17 +1510,14 @@ static void snap_source_closest_fn(TransInfo *t)
|
||||
closest = td;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
|
||||
BLI_assert(tc->sorted_index_map);
|
||||
for (const int i : Span(tc->sorted_index_map, tc->data_len)) {
|
||||
tc->foreach_index_selected([&](const int i) {
|
||||
TransData *td = &tc->data[i];
|
||||
if (!(td->flag & TD_SELECTED)) {
|
||||
break;
|
||||
}
|
||||
|
||||
float loc[3];
|
||||
float dist;
|
||||
@@ -1550,7 +1537,7 @@ static void snap_source_closest_fn(TransInfo *t)
|
||||
closest = td;
|
||||
dist_closest = dist;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user