UV: remove per-UV-map selection data

Replace per UV map selection with a single UV selection for all UV's.
This uses the same data as UV sync select, meaning that it's no longer
possible to keep a different selection when sync-select is disabled.

There is a minor improvement to functionality - previously not possible
to de-select a single face surrounding by selected faces.
Now this is possible because true face selection is supported.

The selection from the active UV-map is converted to use the shared
selection data.

Ref !147523

Co-authored-by: Hans Goudey <hans@blender.org>
This commit is contained in:
Campbell Barton
2025-10-08 15:03:06 +11:00
parent 377e3cfca5
commit f4308aa2d0
33 changed files with 535 additions and 856 deletions

View File

@@ -161,9 +161,5 @@ bool BKE_color_attribute_supported(const struct Mesh &mesh, blender::StringRef n
std::string BKE_attribute_calc_unique_name(const AttributeOwner &owner, blender::StringRef name);
[[nodiscard]] blender::StringRef BKE_uv_map_vert_select_name_get(blender::StringRef uv_map_name,
char *buffer);
[[nodiscard]] blender::StringRef BKE_uv_map_edge_select_name_get(blender::StringRef uv_map_name,
char *buffer);
[[nodiscard]] blender::StringRef BKE_uv_map_pin_name_get(blender::StringRef uv_map_name,
char *buffer);

View File

@@ -27,7 +27,7 @@
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 104
#define BLENDER_FILE_SUBVERSION 105
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -41,9 +41,7 @@ enum class AttrDomain : int8_t;
* has 4 extra bytes above what can be used for the base layer name, and these
* prefixes are placed between 2 '.'s at the start of the layer name.
* For example The uv vert selection layer of a layer named `UVMap.001`
* will be called `.vs.UVMap.001`. */
#define UV_VERTSEL_NAME "vs"
#define UV_EDGESEL_NAME "es"
* will be called `.pn.UVMap.001`. */
#define UV_PINNED_NAME "pn"
/**
@@ -53,13 +51,11 @@ enum class AttrDomain : int8_t;
*/
struct BMUVOffsets {
int uv;
int select_vert;
int select_edge;
int pin;
};
/** All values reference none layers. */
#define BMUVOFFSETS_NONE {-1, -1, -1, -1}
#define BMUVOFFSETS_NONE {-1, -1}
/* A data type large enough to hold 1 element from any custom-data layer type. */
struct CDBlockBytes {

View File

@@ -20,6 +20,8 @@ struct CustomDataLayer;
namespace blender::bke {
void mesh_uv_select_to_single_attribute(Mesh &mesh);
void mesh_custom_normals_to_generic(Mesh &mesh);
void mesh_sculpt_mask_to_generic(Mesh &mesh);

View File

@@ -324,14 +324,6 @@ bool BKE_attribute_rename(AttributeOwner &owner,
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_attribute_rename_if_exists(owner,
BKE_uv_map_vert_select_name_get(layer->name, buffer_src),
BKE_uv_map_vert_select_name_get(result_name, buffer_dst),
reports);
bke_attribute_rename_if_exists(owner,
BKE_uv_map_edge_select_name_get(layer->name, buffer_src),
BKE_uv_map_edge_select_name_get(result_name, buffer_dst),
reports);
bke_attribute_rename_if_exists(owner,
BKE_uv_map_pin_name_get(layer->name, buffer_src),
BKE_uv_map_pin_name_get(result_name, buffer_dst),
@@ -489,13 +481,6 @@ CustomDataLayer *BKE_attribute_duplicate(AttributeOwner &owner,
/* Duplicate UV sub-attributes. */
char buffer_src[MAX_CUSTOMDATA_LAYER_NAME];
char buffer_dst[MAX_CUSTOMDATA_LAYER_NAME];
bke_attribute_copy_if_exists(owner,
BKE_uv_map_vert_select_name_get(name, buffer_src),
BKE_uv_map_vert_select_name_get(uniquename, buffer_dst));
bke_attribute_copy_if_exists(owner,
BKE_uv_map_edge_select_name_get(name, buffer_src),
BKE_uv_map_edge_select_name_get(uniquename, buffer_dst));
bke_attribute_copy_if_exists(owner,
BKE_uv_map_pin_name_get(name, buffer_src),
BKE_uv_map_pin_name_get(uniquename, buffer_dst));
@@ -575,10 +560,6 @@ bool BKE_attribute_remove(AttributeOwner &owner, const StringRef name, ReportLis
if (type == CD_PROP_FLOAT2 && domain == int(AttrDomain::Corner)) {
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_vert_select_name_get(name_copy, buffer));
BM_data_layer_free_named(
em->bm, data, BKE_uv_map_edge_select_name_get(name_copy, buffer));
BM_data_layer_free_named(em->bm, data, BKE_uv_map_pin_name_get(name_copy, buffer));
}
return true;
@@ -622,8 +603,6 @@ bool BKE_attribute_remove(AttributeOwner &owner, const StringRef name, ReportLis
if (metadata->data_type == AttrType::Float2 && metadata->domain == AttrDomain::Corner) {
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
attributes->remove(BKE_uv_map_vert_select_name_get(name_copy, buffer));
attributes->remove(BKE_uv_map_edge_select_name_get(name_copy, buffer));
attributes->remove(BKE_uv_map_pin_name_get(name_copy, buffer));
}
return true;
@@ -1070,24 +1049,6 @@ bool BKE_color_attribute_supported(const Mesh &mesh, const StringRef name)
return true;
}
StringRef BKE_uv_map_vert_select_name_get(const StringRef uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_VERTSEL_NAME) == 2);
BLI_assert(uv_map_name.size() < MAX_CUSTOMDATA_LAYER_NAME - 4);
const auto result = fmt::format_to_n(
buffer, MAX_CUSTOMDATA_LAYER_NAME, ".{}.{}", UV_VERTSEL_NAME, uv_map_name);
return StringRef(buffer, result.size);
}
StringRef BKE_uv_map_edge_select_name_get(const StringRef uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_EDGESEL_NAME) == 2);
BLI_assert(uv_map_name.size() < MAX_CUSTOMDATA_LAYER_NAME - 4);
const auto result = fmt::format_to_n(
buffer, MAX_CUSTOMDATA_LAYER_NAME, ".{}.{}", UV_EDGESEL_NAME, uv_map_name);
return StringRef(buffer, result.size);
}
StringRef BKE_uv_map_pin_name_get(const StringRef uv_map_name, char *buffer)
{
BLI_assert(strlen(UV_PINNED_NAME) == 2);

View File

@@ -219,12 +219,6 @@ bool allow_procedural_attribute_access(StringRef attribute_name)
if (attribute_name == ".reference_index") {
return false;
}
if (attribute_name.startswith("." UV_VERTSEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_EDGESEL_NAME ".")) {
return false;
}
if (attribute_name.startswith("." UV_PINNED_NAME ".")) {
return false;
}

View File

@@ -4272,9 +4272,7 @@ int CustomData_name_maxncpy_calc(const blender::StringRef name)
if (name.startswith(".")) {
return MAX_CUSTOMDATA_LAYER_NAME_NO_PREFIX;
}
for (const blender::StringRef prefix :
{"." UV_VERTSEL_NAME, UV_EDGESEL_NAME ".", UV_PINNED_NAME "."})
{
for (const blender::StringRef prefix : {UV_PINNED_NAME "."}) {
if (name.startswith(prefix)) {
return MAX_CUSTOMDATA_LAYER_NAME;
}

View File

@@ -526,8 +526,8 @@ static bool sort_faces_based_on_corners(const IndexMapping &corners,
return true;
}
/*
* The uv selection / pin layers are ignored in the comparisons because
/**
* The UV selection & pin layers are ignored in the comparisons because
* the original flags they replace were ignored as well. Because of the
* lazy creation of these layers it would need careful handling of the
* test files to compare these layers. For now it has been decided to
@@ -535,8 +535,8 @@ static bool sort_faces_based_on_corners(const IndexMapping &corners,
*/
static bool ignored_attribute(const StringRef id)
{
return attribute_name_is_anonymous(id) || id.startswith(".vs.") || id.startswith(".es.") ||
id.startswith(".pn.");
return attribute_name_is_anonymous(id) || id.startswith(".pn.") ||
ELEM(id, ".uv_select_vert", ".uv_select_edge", ".uv_select_face");
}
/**

View File

@@ -1710,15 +1710,7 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
[](const uint32_t a, const uint32_t b) { return a | b; });
float2 *coords = MEM_malloc_arrayN<float2>(size_t(mesh->corners_num), __func__);
bool *vert_selection = nullptr;
bool *edge_selection = nullptr;
bool *pin = nullptr;
if (needed_boolean_attributes & MLOOPUV_VERTSEL) {
vert_selection = MEM_malloc_arrayN<bool>(size_t(mesh->corners_num), __func__);
}
if (needed_boolean_attributes & MLOOPUV_EDGESEL) {
edge_selection = MEM_malloc_arrayN<bool>(size_t(mesh->corners_num), __func__);
}
if (needed_boolean_attributes & MLOOPUV_PINNED) {
pin = MEM_malloc_arrayN<bool>(size_t(mesh->corners_num), __func__);
}
@@ -1727,16 +1719,6 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
for (const int i : range) {
coords[i] = mloopuv[i].uv;
}
if (vert_selection) {
for (const int i : range) {
vert_selection[i] = mloopuv[i].flag & MLOOPUV_VERTSEL;
}
}
if (edge_selection) {
for (const int i : range) {
edge_selection[i] = mloopuv[i].flag & MLOOPUV_EDGESEL;
}
}
if (pin) {
for (const int i : range) {
pin[i] = mloopuv[i].flag & MLOOPUV_PINNED;
@@ -1753,22 +1735,6 @@ void BKE_mesh_legacy_convert_uvs_to_generic(Mesh *mesh)
CustomData_add_layer_named_with_data(
&mesh->corner_data, CD_PROP_FLOAT2, coords, mesh->corners_num, new_name, nullptr);
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
if (vert_selection) {
CustomData_add_layer_named_with_data(&mesh->corner_data,
CD_PROP_BOOL,
vert_selection,
mesh->corners_num,
BKE_uv_map_vert_select_name_get(new_name, buffer),
nullptr);
}
if (edge_selection) {
CustomData_add_layer_named_with_data(&mesh->corner_data,
CD_PROP_BOOL,
edge_selection,
mesh->corners_num,
BKE_uv_map_edge_select_name_get(new_name, buffer),
nullptr);
}
if (pin) {
CustomData_add_layer_named_with_data(&mesh->corner_data,
CD_PROP_BOOL,
@@ -2621,7 +2587,78 @@ void mesh_custom_normals_to_generic(Mesh &mesh)
}
}
//
void mesh_uv_select_to_single_attribute(Mesh &mesh)
{
const char *name = CustomData_get_active_layer_name(&mesh.corner_data, CD_PROP_FLOAT2);
if (!name) {
return;
}
const std::string uv_select_vert_name_shared = ".uv_select_vert";
const std::string uv_select_edge_name_shared = ".uv_select_edge";
const std::string uv_select_face_name_shared = ".uv_select_face";
const std::string uv_select_vert_prefix = ".vs.";
const std::string uv_select_edge_prefix = ".es.";
const std::string uv_select_vert_name = uv_select_vert_prefix + name;
const std::string uv_select_edge_name = uv_select_edge_prefix + name;
const int uv_select_vert = CustomData_get_named_layer_index(
&mesh.corner_data, CD_PROP_BOOL, uv_select_vert_name);
const int uv_select_edge = CustomData_get_named_layer_index(
&mesh.corner_data, CD_PROP_BOOL, uv_select_edge_name);
if (uv_select_vert != -1 && uv_select_edge != -1) {
/* Unlikely either exist but ensure there are no duplicate names. */
CustomData_free_layer_named(&mesh.corner_data, uv_select_vert_name_shared);
CustomData_free_layer_named(&mesh.corner_data, uv_select_edge_name_shared);
CustomData_free_layer_named(&mesh.face_data, uv_select_face_name_shared);
STRNCPY_UTF8(mesh.corner_data.layers[uv_select_vert].name, uv_select_vert_name_shared.c_str());
STRNCPY_UTF8(mesh.corner_data.layers[uv_select_edge].name, uv_select_edge_name_shared.c_str());
bool *uv_select_face = MEM_malloc_arrayN<bool>(mesh.faces_num, __func__);
CustomData_add_layer_named_with_data(&mesh.face_data,
CD_PROP_BOOL,
uv_select_face,
mesh.faces_num,
uv_select_face_name_shared,
nullptr);
/* Create a face selection layer (flush from edges). */
if (mesh.faces_num > 0) {
const OffsetIndices<int> faces = mesh.faces();
const Span<bool> uv_select_edge_data(
static_cast<bool *>(mesh.corner_data.layers[uv_select_edge].data), mesh.corners_num);
threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
for (const int face : range) {
uv_select_face[face] = !uv_select_edge_data.slice(faces[face]).contains(false);
}
});
}
}
/* Logically a set as names are expected to be unique.
* If there are duplicates, this will remove those too. */
Vector<std::string> attributes_to_remove;
for (const int i : IndexRange(mesh.corner_data.totlayer)) {
const CustomDataLayer &layer = mesh.corner_data.layers[i];
if (layer.type != CD_PROP_BOOL) {
continue;
}
StringRef layer_name = StringRef(layer.name);
if (layer_name.startswith(uv_select_vert_prefix) ||
layer_name.startswith(uv_select_edge_prefix))
{
attributes_to_remove.append(layer.name);
}
}
for (const StringRef name_to_remove : attributes_to_remove) {
CustomData_free_layer_named(&mesh.corner_data, name_to_remove);
}
}
} // namespace blender::bke
/** \} */

View File

@@ -335,7 +335,7 @@ void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
mesh->runtime->subsurf_face_dot_tags.clear_and_shrink();
mesh->runtime->subsurf_optimal_display_edges.clear_and_shrink();
mesh->runtime->spatial_groups.reset();
mesh->flag &= ~ME_NO_OVERLAPPING_TOPOLOGY;
mesh->flag &= ~(ME_NO_OVERLAPPING_TOPOLOGY | ME_FLAG_UV_SELECT_SYNC_VALID);
}
void Mesh::tag_edges_split()

View File

@@ -4662,8 +4662,9 @@ void blo_do_versions_280(FileData *fd, Library * /*lib*/, Main *bmain)
}
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
me->flag &= ~(ME_FLAG_UNUSED_0 | ME_FLAG_UNUSED_1 | ME_FLAG_UNUSED_3 | ME_FLAG_UNUSED_4 |
ME_FLAG_UNUSED_6 | ME_FLAG_UNUSED_7 | ME_REMESH_REPROJECT_ATTRIBUTES);
me->flag &= ~(ME_FLAG_UNUSED_0 | ME_FLAG_UNUSED_1 | ME_FLAG_UV_SELECT_SYNC_VALID |
ME_FLAG_UNUSED_4 | ME_FLAG_UNUSED_6 | ME_FLAG_UNUSED_7 |
ME_REMESH_REPROJECT_ATTRIBUTES);
}
LISTBASE_FOREACH (Material *, mat, &bmain->materials) {

View File

@@ -3935,6 +3935,12 @@ void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 105)) {
LISTBASE_FOREACH (Mesh *, mesh, &bmain->meshes) {
bke::mesh_uv_select_to_single_attribute(*mesh);
}
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View File

@@ -878,25 +878,13 @@ void BM_data_layer_ensure_named(BMesh *bm, CustomData *data, int type, const Str
}
}
void BM_uv_map_attr_select_and_pin_ensure(BMesh *bm)
void BM_uv_map_attr_pin_ensure_for_all_layers(BMesh *bm)
{
const int nr_uv_layers = CustomData_number_of_layers(&bm->ldata, CD_PROP_FLOAT2);
for (int l = 0; l < nr_uv_layers; l++) {
/* NOTE: you can't re-use the return-value of #CustomData_get_layer_name()
* because adding layers can invalidate that. */
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm,
&bm->ldata,
CD_PROP_BOOL,
BKE_uv_map_vert_select_name_get(CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, l),
name));
BM_data_layer_ensure_named(
bm,
&bm->ldata,
CD_PROP_BOOL,
BKE_uv_map_edge_select_name_get(CustomData_get_layer_name(&bm->ldata, CD_PROP_FLOAT2, l),
name));
BM_data_layer_ensure_named(
bm,
&bm->ldata,
@@ -905,34 +893,13 @@ void BM_uv_map_attr_select_and_pin_ensure(BMesh *bm)
}
}
void BM_uv_map_attr_vert_select_ensure(BMesh *bm, const StringRef uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(uv_map_name, name));
}
void BM_uv_map_attr_edge_select_ensure(BMesh *bm, const StringRef uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(uv_map_name, name));
}
void BM_uv_map_attr_pin_ensure(BMesh *bm, const StringRef uv_map_name)
void BM_uv_map_attr_pin_ensure_named(BMesh *bm, const StringRef uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
BM_data_layer_ensure_named(
bm, &bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(uv_map_name, name));
}
bool BM_uv_map_attr_vert_select_exists(const BMesh *bm, const StringRef uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];
return (CustomData_get_named_layer_index(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(uv_map_name, name)) != -1);
}
bool BM_uv_map_attr_pin_exists(const BMesh *bm, const StringRef uv_map_name)
{
char name[MAX_CUSTOMDATA_LAYER_NAME];

View File

@@ -77,13 +77,9 @@ bool BM_data_layer_has_named(const BMesh *bm,
void BM_data_layer_free(BMesh *bm, CustomData *data, int type);
/** Ensure the dependent boolean layers exist for all face corner #CD_PROP_FLOAT2 layers. */
void BM_uv_map_attr_select_and_pin_ensure(BMesh *bm);
void BM_uv_map_attr_pin_ensure_for_all_layers(BMesh *bm);
void BM_uv_map_attr_vert_select_ensure(BMesh *bm, blender::StringRef uv_map_name);
void BM_uv_map_attr_edge_select_ensure(BMesh *bm, blender::StringRef uv_map_name);
void BM_uv_map_attr_pin_ensure(BMesh *bm, blender::StringRef uv_map_name);
bool BM_uv_map_attr_vert_select_exists(const BMesh *bm, blender::StringRef uv_map_name);
void BM_uv_map_attr_pin_ensure_named(BMesh *bm, blender::StringRef uv_map_name);
bool BM_uv_map_attr_pin_exists(const BMesh *bm, blender::StringRef uv_map_name);
/**

View File

@@ -243,24 +243,6 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *
IndexRange(CustomData_number_of_layers(&mesh_ldata, CD_PROP_FLOAT2)))
{
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
{
const StringRef name = BKE_uv_map_vert_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), buffer);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->corners_num, name);
temporary_layers_to_delete.append(std::string(name));
}
}
{
const StringRef name = BKE_uv_map_edge_select_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), buffer);
if (CustomData_get_named_layer_index(&mesh_ldata, CD_PROP_BOOL, name) < 0) {
CustomData_add_layer_named(
&mesh_ldata, CD_PROP_BOOL, CD_SET_DEFAULT, mesh->corners_num, name);
temporary_layers_to_delete.append(std::string(name));
}
}
{
const StringRef name = BKE_uv_map_pin_name_get(
CustomData_get_layer_name(&mesh_ldata, CD_PROP_FLOAT2, layer_index), buffer);
@@ -596,7 +578,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *mesh, const BMeshFromMeshParams *
bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP); /* Added in order, clear dirty flag. */
}
bm->uv_select_sync_valid = need_uv_select;
bm->uv_select_sync_valid = (need_uv_select && (mesh->flag & ME_FLAG_UV_SELECT_SYNC_VALID)) != 0;
/* -------------------------------------------------------------------- */
/* MSelect clears the array elements (to avoid adding multiple times).
@@ -1187,8 +1169,6 @@ static void bm_face_loop_table_build(BMesh &bm,
Vector<int> &loop_layers_not_to_copy)
{
const CustomData &ldata = bm.ldata;
Vector<int> vert_sel_layers;
Vector<int> edge_sel_layers;
Vector<int> pin_layers;
for (const int i : IndexRange(CustomData_number_of_layers(&ldata, CD_PROP_FLOAT2))) {
char const *layer_name = CustomData_get_layer_name(&ldata, CD_PROP_FLOAT2, i);
@@ -1199,25 +1179,13 @@ static void bm_face_loop_table_build(BMesh &bm,
layers.append(layer_index);
}
};
add_bool_layer(vert_sel_layers, BKE_uv_map_vert_select_name_get(layer_name, sub_layer_name));
add_bool_layer(edge_sel_layers, BKE_uv_map_edge_select_name_get(layer_name, sub_layer_name));
add_bool_layer(pin_layers, BKE_uv_map_pin_name_get(layer_name, sub_layer_name));
}
Array<int> vert_sel_offsets(vert_sel_layers.size());
Array<int> edge_sel_offsets(edge_sel_layers.size());
Array<int> pin_offsets(pin_layers.size());
for (const int i : vert_sel_layers.index_range()) {
vert_sel_offsets[i] = ldata.layers[vert_sel_layers[i]].offset;
}
for (const int i : edge_sel_layers.index_range()) {
edge_sel_offsets[i] = ldata.layers[edge_sel_layers[i]].offset;
}
for (const int i : pin_layers.index_range()) {
pin_offsets[i] = ldata.layers[pin_layers[i]].offset;
}
Array<bool> need_vert_sel(vert_sel_layers.size(), false);
Array<bool> need_edge_sel(edge_sel_layers.size(), false);
Array<bool> need_pin(pin_layers.size(), false);
char hflag = 0;
BMIter iter;
@@ -1235,16 +1203,6 @@ static void bm_face_loop_table_build(BMesh &bm,
for ([[maybe_unused]] const int i : IndexRange(face->len)) {
BM_elem_index_set(loop, loop_i); /* set_inline */
loop_table[loop_i] = loop;
for (const int i : vert_sel_offsets.index_range()) {
if (BM_ELEM_CD_GET_BOOL(loop, vert_sel_offsets[i])) {
need_vert_sel[i] = true;
}
}
for (const int i : edge_sel_offsets.index_range()) {
if (BM_ELEM_CD_GET_BOOL(loop, edge_sel_offsets[i])) {
need_edge_sel[i] = true;
}
}
for (const int i : pin_offsets.index_range()) {
if (BM_ELEM_CD_GET_BOOL(loop, pin_offsets[i])) {
need_pin[i] = true;
@@ -1257,16 +1215,6 @@ static void bm_face_loop_table_build(BMesh &bm,
need_select_poly = (hflag & BM_ELEM_SELECT) != 0;
need_hide_poly = (hflag & BM_ELEM_HIDDEN) != 0;
for (const int i : vert_sel_layers.index_range()) {
if (!need_vert_sel[i]) {
loop_layers_not_to_copy.append(vert_sel_layers[i]);
}
}
for (const int i : edge_sel_layers.index_range()) {
if (!need_edge_sel[i]) {
loop_layers_not_to_copy.append(edge_sel_layers[i]);
}
}
for (const int i : pin_layers.index_range()) {
if (!need_pin[i]) {
loop_layers_not_to_copy.append(pin_layers[i]);
@@ -1477,6 +1425,12 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParam
mesh->faces_num = bm->totface;
mesh->act_face = -1;
/* Will have been cleared when clearing geometry. */
const bool need_uv_select = CustomData_has_layer(&bm->ldata, CD_PROP_FLOAT2);
if (need_uv_select & bm->uv_select_sync_valid) {
mesh->flag |= ME_FLAG_UV_SELECT_SYNC_VALID;
}
bool need_select_vert = false;
bool need_select_edge = false;
bool need_select_poly = false;
@@ -1487,11 +1441,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *mesh, const BMeshToMeshParam
bool need_sharp_edge = false;
bool need_sharp_face = false;
bool need_uv_seams = false;
const bool need_uv_select = (bm->uv_select_sync_valid &&
/* Avoid redundant layer creation if there is no selection,
* although a "Select All" / "De-select All" clears
* #BMesh::uv_select_sync_valid so it's often not needed. */
(bm->totvertsel != 0));
Array<const BMVert *> vert_table;
Array<const BMEdge *> edge_table;
Array<const BMFace *> face_table;
@@ -1716,6 +1665,12 @@ void BM_mesh_bm_to_me_compact(BMesh &bm,
mesh.corners_num = bm.totloop;
mesh.faces_num = bm.totface;
/* Will have been cleared when clearing geometry. */
const bool need_uv_select = CustomData_has_layer(&bm.ldata, CD_PROP_FLOAT2);
if (need_uv_select && bm.uv_select_sync_valid) {
mesh.flag |= ME_FLAG_UV_SELECT_SYNC_VALID;
}
mesh.runtime->deformed_only = true;
const bool use_threading = (mesh.faces_num + mesh.edges_num) > 1024;
@@ -1733,7 +1688,6 @@ void BM_mesh_bm_to_me_compact(BMesh &bm,
bool need_sharp_edge = false;
bool need_sharp_face = false;
bool need_uv_seams = false;
const bool need_uv_select = bm.uv_select_sync_valid;
Array<const BMVert *> vert_table;
Array<const BMEdge *> edge_table;

View File

@@ -31,10 +31,6 @@ BMUVOffsets BM_uv_map_offsets_from_layer(const BMesh *bm, const int layer)
BMUVOffsets offsets;
offsets.uv = bm->ldata.layers[layer_index].offset;
offsets.select_vert = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_vert_select_name_get(name, buffer));
offsets.select_edge = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_edge_select_name_get(name, buffer));
offsets.pin = CustomData_get_offset_named(
&bm->ldata, CD_PROP_BOOL, BKE_uv_map_pin_name_get(name, buffer));

View File

@@ -38,7 +38,7 @@ void mesh_render_data_face_flag(const MeshRenderData &mr,
eattr.v_flag |= VFLAG_FACE_UV_ACTIVE;
}
if ((offsets.uv != -1) && (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) &&
uvedit_face_select_test_ex(mr.toolsettings, mr.bm, efa, offsets))
uvedit_face_select_test_ex(mr.toolsettings, mr.bm, efa))
{
eattr.v_flag |= VFLAG_FACE_UV_SELECT;
}

View File

@@ -520,13 +520,7 @@ void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count);
void ED_mesh_geometry_clear(Mesh *mesh);
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_vert_select_layer_ensure(Mesh *mesh,
int uv_index);
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_edge_select_layer_ensure(Mesh *mesh,
int uv_index);
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_pin_layer_ensure(Mesh *mesh, int uv_index);
blender::VArray<bool> ED_mesh_uv_map_vert_select_layer_get(const Mesh *mesh, int uv_index);
blender::VArray<bool> ED_mesh_uv_map_edge_select_layer_get(const Mesh *mesh, int uv_index);
blender::VArray<bool> ED_mesh_uv_map_pin_layer_get(const Mesh *mesh, int uv_index);
void ED_mesh_uv_ensure(Mesh *mesh, const char *name);

View File

@@ -46,7 +46,7 @@ void ED_keymap_uvedit(wmKeyConfig *keyconf);
/**
* Be careful when using this, it bypasses all synchronization options.
*/
void ED_uvedit_select_all(BMesh *bm);
void ED_uvedit_select_all(const ToolSettings *ts, BMesh *bm);
void ED_uvedit_foreach_uv(const Scene *scene,
BMesh *bm,
@@ -149,10 +149,7 @@ void ED_uvedit_sync_uvselect_ensure_if_needed(const ToolSettings *ts, BMesh *bm)
/* Visibility and selection tests. */
bool uvedit_face_visible_test_ex(const ToolSettings *ts, const BMFace *efa);
bool uvedit_face_select_test_ex(const ToolSettings *ts,
const BMesh *bm,
const BMFace *efa,
const BMUVOffsets &offsets);
bool uvedit_face_select_test_ex(const ToolSettings *ts, const BMesh *bm, const BMFace *efa);
bool uvedit_edge_select_test_ex(const ToolSettings *ts,
const BMesh *bm,
@@ -164,10 +161,7 @@ bool uvedit_uv_select_test_ex(const ToolSettings *ts,
const BMUVOffsets &offsets);
bool uvedit_face_visible_test(const Scene *scene, const BMFace *efa);
bool uvedit_face_select_test(const Scene *scene,
const BMesh *bm,
const BMFace *efa,
const BMUVOffsets &offsets);
bool uvedit_face_select_test(const Scene *scene, const BMesh *bm, const BMFace *efa);
bool uvedit_edge_select_test(const Scene *scene,
const BMesh *bm,
const BMLoop *l,
@@ -179,24 +173,16 @@ bool uvedit_uv_select_test(const Scene *scene,
/* Low level loop selection, this ignores the selection modes. */
bool uvedit_loop_vert_select_get(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
bool uvedit_loop_edge_select_get(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets);
bool uvedit_loop_vert_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l);
bool uvedit_loop_edge_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l);
void uvedit_loop_vert_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets);
const bool select);
void uvedit_loop_edge_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets);
const bool select);
/* Individual UV element selection functions. */
@@ -205,49 +191,31 @@ void uvedit_loop_edge_select_set(const ToolSettings *ts,
*
* Changes selection state of a single UV Face.
*/
void uvedit_face_select_set(
const Scene *scene, BMesh *bm, BMFace *efa, bool select, const BMUVOffsets &offsets);
void uvedit_face_select_set(const Scene *scene, BMesh *bm, BMFace *efa, bool select);
/**
* \brief Select UV Edge
*
* Changes selection state of a single UV Edge.
*/
void uvedit_edge_select_set(
const Scene *scene, BMesh *bm, BMLoop *l, bool select, const BMUVOffsets &offsets);
void uvedit_edge_select_set(const Scene *scene, BMesh *bm, BMLoop *l, bool select);
/**
* \brief Select UV Vertex
*
* Changes selection state of a single UV vertex.
*/
void uvedit_uv_select_set(
const Scene *scene, BMesh *bm, BMLoop *l, bool select, const BMUVOffsets &offsets);
void uvedit_uv_select_set(const Scene *scene, BMesh *bm, BMLoop *l, bool select);
/* Low level functions for (de)selecting individual UV elements. Ensure UV face visibility before
* use. */
void uvedit_face_select_enable(const Scene *scene,
BMesh *bm,
BMFace *efa,
const BMUVOffsets &offsets);
void uvedit_face_select_disable(const Scene *scene,
BMesh *bm,
BMFace *efa,
const BMUVOffsets &offsets);
void uvedit_face_select_enable(const Scene *scene, BMesh *bm, BMFace *efa);
void uvedit_face_select_disable(const Scene *scene, BMesh *bm, BMFace *efa);
void uvedit_edge_select_enable(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets);
void uvedit_edge_select_disable(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets);
void uvedit_edge_select_enable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_edge_select_disable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l, const BMUVOffsets &offsets);
void uvedit_uv_select_disable(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets);
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l);
void uvedit_uv_select_disable(const Scene *scene, BMesh *bm, BMLoop *l);
/* Sticky mode UV element selection functions. */

View File

@@ -238,7 +238,7 @@ int ED_mesh_uv_add(
}
BM_data_layer_add_named(em->bm, &em->bm->ldata, CD_PROP_FLOAT2, unique_name.c_str());
BM_uv_map_attr_select_and_pin_ensure(em->bm);
BM_uv_map_attr_pin_ensure_for_all_layers(em->bm);
/* copy data from active UV */
if (layernum_dst && do_init) {
const int layernum_src = CustomData_get_active_layer(&em->bm->ldata, CD_PROP_FLOAT2);
@@ -295,24 +295,6 @@ static blender::VArray<bool> get_corner_boolean_attribute(const Mesh &mesh, cons
return *attributes.lookup_or_default<bool>(name, blender::bke::AttrDomain::Corner, false);
}
blender::VArray<bool> ED_mesh_uv_map_vert_select_layer_get(const Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->corner_data, CD_PROP_FLOAT2, uv_index);
return get_corner_boolean_attribute(*mesh, BKE_uv_map_vert_select_name_get(uv_name, buffer));
}
blender::VArray<bool> ED_mesh_uv_map_edge_select_layer_get(const Mesh *mesh, const int uv_index)
{
/* UV map edge selections are stored on face corners (loops) and not on edges
* because we need selections per face edge, even when the edge is split in UV space. */
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->corner_data, CD_PROP_FLOAT2, uv_index);
return get_corner_boolean_attribute(*mesh, BKE_uv_map_edge_select_name_get(uv_name, buffer));
}
blender::VArray<bool> ED_mesh_uv_map_pin_layer_get(const Mesh *mesh, const int uv_index)
{
using namespace blender::bke;
@@ -329,22 +311,6 @@ static blender::bke::AttributeWriter<bool> ensure_corner_boolean_attribute(Mesh
name, blender::bke::AttrDomain::Corner, blender::bke::AttributeInitDefaultValue());
}
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_vert_select_layer_ensure(Mesh *mesh,
const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->corner_data, CD_PROP_FLOAT2, uv_index);
return ensure_corner_boolean_attribute(*mesh, BKE_uv_map_vert_select_name_get(uv_name, buffer));
}
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_edge_select_layer_ensure(Mesh *mesh,
const int uv_index)
{
using namespace blender::bke;
char buffer[MAX_CUSTOMDATA_LAYER_NAME];
const char *uv_name = CustomData_get_layer_name(&mesh->corner_data, CD_PROP_FLOAT2, uv_index);
return ensure_corner_boolean_attribute(*mesh, BKE_uv_map_edge_select_name_get(uv_name, buffer));
}
blender::bke::AttributeWriter<bool> ED_mesh_uv_map_pin_layer_ensure(Mesh *mesh, const int uv_index)
{
using namespace blender::bke;

View File

@@ -104,6 +104,29 @@ bool uvedit_vert_is_all_other_faces_selected(const ToolSettings *ts,
const BMLoop *l,
const BMUVOffsets &offsets);
[[nodiscard]] bool uvedit_vert_select_get_no_sync(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l);
[[nodiscard]] bool uvedit_edge_select_get_no_sync(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l);
[[nodiscard]] bool uvedit_face_select_get_no_sync(const ToolSettings *ts,
const BMesh *bm,
const BMFace *f);
void uvedit_vert_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
bool select);
void uvedit_edge_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
bool select);
void uvedit_face_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMFace *f,
bool select);
/* utility tool functions */
void uvedit_live_unwrap_update(SpaceImage *sima, Scene *scene, Object *obedit);

View File

@@ -92,16 +92,14 @@ static bool uvedit_is_face_affected_for_calc_uv_islands(const Scene *scene,
const BMesh *bm,
BMFace *efa,
const bool only_selected_faces,
const bool only_selected_uvs,
const BMUVOffsets &uv_offsets)
const bool only_selected_uvs)
{
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
return false;
}
if (only_selected_faces) {
if (only_selected_uvs) {
return BM_elem_flag_test(efa, BM_ELEM_SELECT) &&
uvedit_face_select_test(scene, bm, efa, uv_offsets);
return BM_elem_flag_test(efa, BM_ELEM_SELECT) && uvedit_face_select_test(scene, bm, efa);
}
return BM_elem_flag_test(efa, BM_ELEM_SELECT);
}
@@ -130,7 +128,7 @@ int bm_mesh_calc_uv_islands(const Scene *scene,
BMIter iter;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
const bool face_affected = uvedit_is_face_affected_for_calc_uv_islands(
scene, bm, f, only_selected_faces, only_selected_uvs, uv_offsets);
scene, bm, f, only_selected_faces, only_selected_uvs);
BM_elem_flag_set(f, BM_ELEM_TAG, face_affected);
}

View File

@@ -257,17 +257,17 @@ bool ED_uvedit_minmax_multi(const Scene *scene,
return changed;
}
void ED_uvedit_select_all(BMesh *bm)
void ED_uvedit_select_all(const ToolSettings *ts, BMesh *bm)
{
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
uvedit_face_select_set_no_sync(ts, bm, efa, true);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
uvedit_vert_select_set_no_sync(ts, bm, l, true);
uvedit_edge_select_set_no_sync(ts, bm, l, true);
}
}
}
@@ -1724,10 +1724,8 @@ static wmOperatorStatus uv_pin_exec(bContext *C, wmOperator *op)
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
const ToolSettings *ts = scene->toolsettings;
const bool clear = RNA_boolean_get(op->ptr, "clear");
const bool invert = RNA_boolean_get(op->ptr, "invert");
const bool synced_selection = (ts->uv_flag & UV_FLAG_SELECT_SYNC) != 0;
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
scene, view_layer, nullptr);
@@ -1741,20 +1739,12 @@ static wmOperatorStatus uv_pin_exec(bContext *C, wmOperator *op)
if (em->bm->totvertsel == 0) {
continue;
}
if (synced_selection) {
/* Pass. */
}
else {
if (!BM_uv_map_attr_vert_select_exists(em->bm, active_uv_name)) {
continue;
}
}
if (clear && !BM_uv_map_attr_pin_exists(em->bm, active_uv_name)) {
continue;
}
BM_uv_map_attr_pin_ensure(em->bm, active_uv_name);
BM_uv_map_attr_pin_ensure_named(em->bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
@@ -1820,19 +1810,24 @@ static void UV_OT_pin(wmOperatorType *ot)
/* check if we are selected or unselected based on 'bool_test' arg,
* needed for select swap support */
#define UV_VERT_SEL_TEST(l, bool_test) (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) == bool_test)
#define UV_VERT_SEL_TEST(ts, bm, l, bool_test) \
(uvedit_vert_select_get_no_sync(ts, bm, l) == bool_test)
#define UV_EDGE_SEL_TEST(l, bool_test) (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge) == bool_test)
#define UV_EDGE_SEL_TEST(ts, bm, l, bool_test) \
(uvedit_edge_select_get_no_sync(ts, bm, l) == bool_test)
/* is every UV vert selected or unselected depending on bool_test */
static bool bm_face_is_all_uv_sel(BMFace *f, bool select_test, const BMUVOffsets &offsets)
static bool bm_face_is_all_uv_sel(const ToolSettings *ts,
const BMesh *bm,
BMFace *f,
bool select_test)
{
BMLoop *l_iter;
BMLoop *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
do {
if (!UV_EDGE_SEL_TEST(l_iter, select_test)) {
if (!UV_EDGE_SEL_TEST(ts, bm, l_iter, select_test)) {
return false;
}
} while ((l_iter = l_iter->next) != l_first);
@@ -1979,17 +1974,6 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
BMLoop *l;
BMIter iter, liter;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
/* Pass. */
}
else {
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata,
CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(em->bm, active_uv_name);
BM_uv_map_attr_edge_select_ensure(em->bm, active_uv_name);
}
const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
uv_mesh_hide_sync_select(ts, ob, em, swap);
continue;
@@ -2004,7 +1988,7 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (UV_VERT_SEL_TEST(l, !swap) || UV_EDGE_SEL_TEST(l, !swap)) {
if (UV_VERT_SEL_TEST(ts, em->bm, l, !swap) || UV_EDGE_SEL_TEST(ts, em->bm, l, !swap)) {
hide = 1;
break;
}
@@ -2014,26 +1998,29 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
if (use_face_center) {
if (em->selectmode == SCE_SELECT_FACE) {
/* Deselect BMesh face if UV face is (de)selected depending on #swap. */
if (bm_face_is_all_uv_sel(efa, !swap, offsets)) {
if (bm_face_is_all_uv_sel(ts, em->bm, efa, !swap)) {
BM_face_select_set(em->bm, efa, false);
}
uvedit_face_select_disable(scene, em->bm, efa, offsets);
uvedit_face_select_disable(scene, em->bm, efa);
}
else {
if (bm_face_is_all_uv_sel(efa, true, offsets) == !swap) {
if (bm_face_is_all_uv_sel(ts, em->bm, efa, true) == !swap) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* For both cases rely on edge sel tests, since all vert sel tests are invalid in
* case of sticky selections. */
if (UV_EDGE_SEL_TEST(l, !swap) && (em->selectmode == SCE_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(ts, em->bm, l, !swap) && (em->selectmode == SCE_SELECT_EDGE))
{
BM_edge_select_set(em->bm, l->e, false);
}
else if (UV_EDGE_SEL_TEST(l, !swap) && (em->selectmode == SCE_SELECT_VERTEX)) {
else if (UV_EDGE_SEL_TEST(ts, em->bm, l, !swap) &&
(em->selectmode == SCE_SELECT_VERTEX))
{
BM_vert_select_set(em->bm, l->v, false);
}
}
}
if (!swap) {
uvedit_face_select_disable(scene, em->bm, efa, offsets);
uvedit_face_select_disable(scene, em->bm, efa);
}
}
}
@@ -2041,11 +2028,11 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
/* Deselect BMesh face depending on the type of UV selectmode and the type of UV element
* being considered. */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (UV_EDGE_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(ts, em->bm, l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
BM_face_select_set(em->bm, efa, false);
break;
}
if (UV_VERT_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_VERT)) {
if (UV_VERT_SEL_TEST(ts, em->bm, l, !swap) && (ts->uv_selectmode == UV_SELECT_VERT)) {
BM_face_select_set(em->bm, efa, false);
break;
}
@@ -2054,11 +2041,11 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
break;
}
}
uvedit_face_select_disable(scene, em->bm, efa, offsets);
uvedit_face_select_disable(scene, em->bm, efa);
}
else {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (UV_EDGE_SEL_TEST(l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (UV_EDGE_SEL_TEST(ts, em->bm, l, !swap) && (ts->uv_selectmode == UV_SELECT_EDGE)) {
if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
}
@@ -2067,7 +2054,9 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
BM_vert_select_set(em->bm, l->next->v, false);
}
}
else if (UV_VERT_SEL_TEST(l, !swap) && (ts->uv_selectmode != UV_SELECT_EDGE)) {
else if (UV_VERT_SEL_TEST(ts, em->bm, l, !swap) &&
(ts->uv_selectmode != UV_SELECT_EDGE))
{
if (em->selectmode == SCE_SELECT_EDGE) {
BM_edge_select_set(em->bm, l->e, false);
}
@@ -2077,7 +2066,7 @@ static wmOperatorStatus uv_hide_exec(bContext *C, wmOperator *op)
}
}
if (!swap) {
uvedit_face_select_disable(scene, em->bm, efa, offsets);
uvedit_face_select_disable(scene, em->bm, efa);
}
}
}
@@ -2145,17 +2134,6 @@ static wmOperatorStatus uv_reveal_exec(bContext *C, wmOperator *op)
BMLoop *l;
BMIter iter, liter;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
/* Pass. */
}
else {
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata,
CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(em->bm, active_uv_name);
BM_uv_map_attr_edge_select_ensure(em->bm, active_uv_name);
}
const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
/* NOTE: Selecting faces is delayed so that it doesn't select verts/edges and confuse certain
* UV selection checks.
* This creates a temporary state which breaks certain UV selection functions that do face
@@ -2184,9 +2162,10 @@ static wmOperatorStatus uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_vert_select_set_no_sync(ts, em->bm, l, select);
uvedit_edge_select_set_no_sync(ts, em->bm, l, select);
}
uvedit_face_select_set_no_sync(ts, em->bm, efa, select);
// BM_face_select_set(em->bm, efa, true);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
@@ -2209,10 +2188,11 @@ static wmOperatorStatus uv_reveal_exec(bContext *C, wmOperator *op)
if (!totsel) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_vert_select_set_no_sync(ts, em->bm, l, select);
uvedit_edge_select_set_no_sync(ts, em->bm, l, select);
}
}
uvedit_face_select_set_no_sync(ts, em->bm, efa, select);
// BM_face_select_set(em->bm, efa, true);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
@@ -2224,9 +2204,10 @@ static wmOperatorStatus uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_vert_select_set_no_sync(ts, em->bm, l, select);
uvedit_edge_select_set_no_sync(ts, em->bm, l, select);
}
uvedit_face_select_set_no_sync(ts, em->bm, efa, select);
// BM_face_select_set(em->bm, efa, true);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
@@ -2237,9 +2218,10 @@ static wmOperatorStatus uv_reveal_exec(bContext *C, wmOperator *op)
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN) && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_vert_select_set_no_sync(ts, em->bm, l, select);
uvedit_edge_select_set_no_sync(ts, em->bm, l, select);
}
uvedit_face_select_set_no_sync(ts, em->bm, efa, select);
// BM_face_select_set(em->bm, efa, true);
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
@@ -2553,6 +2535,7 @@ static bool uv_copy_mirrored_faces(
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BLI_assert(offsets.uv != -1);
UNUSED_VARS_NDEBUG(offsets);
BMVert *v;
BMIter iter;
@@ -2632,9 +2615,7 @@ static bool uv_copy_mirrored_faces(
for (const auto &[f_dst, f_src] : face_map.items()) {
/* Skip unless both faces have all their UVs selected. */
if (!uvedit_face_select_test(scene, bm, f_dst, offsets) ||
!uvedit_face_select_test(scene, bm, f_src, offsets))
{
if (!uvedit_face_select_test(scene, bm, f_dst) || !uvedit_face_select_test(scene, bm, f_src)) {
continue;
}

View File

@@ -150,7 +150,7 @@ static void verttag_set_cb(BMLoop *l, bool val, void *user_data_v)
if (verttag_filter_cb(l_iter, user_data)) {
const float *luv_iter = BM_ELEM_CD_GET_FLOAT_P(l_iter, cd_loop_uv_offset);
if (equals_v2v2(luv, luv_iter)) {
uvedit_uv_select_set(scene, bm, l_iter, val, user_data->offsets);
uvedit_uv_select_set(scene, bm, l_iter, val);
}
}
}

View File

@@ -776,11 +776,11 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
bool is_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_loop_vert_select_get(ts, bm, l, offsets)) {
if (uvedit_loop_edge_select_get(ts, bm, l, offsets)) {
if (uvedit_loop_vert_select_get(ts, bm, l)) {
if (uvedit_loop_edge_select_get(ts, bm, l)) {
UL(l)->is_select_edge = true;
}
else if (!uvedit_loop_edge_select_get(ts, bm, l->prev, offsets)) {
else if (!uvedit_loop_edge_select_get(ts, bm, l->prev)) {
/* #bm_loop_uv_select_single_vert_validate validates below. */
UL(l)->is_select_vert_single = true;
is_all = false;
@@ -824,12 +824,12 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!UL(l)->is_select_all) {
if (uvedit_loop_vert_select_get(ts, bm, l, offsets)) {
uvedit_loop_vert_select_set(ts, bm, l, false, offsets);
if (uvedit_loop_vert_select_get(ts, bm, l)) {
uvedit_loop_vert_select_set(ts, bm, l, false);
changed = true;
}
if (uvedit_loop_edge_select_get(ts, bm, l, offsets)) {
uvedit_loop_edge_select_set(ts, bm, l, false, offsets);
if (uvedit_loop_edge_select_get(ts, bm, l)) {
uvedit_loop_edge_select_set(ts, bm, l, false);
changed = true;
}
}
@@ -862,7 +862,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = static_cast<BMLoop *>(BLI_gsetIterator_getKey(&gs_iter));
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
uvedit_uv_select_disable(scene, bm, l_iter, offsets);
uvedit_uv_select_disable(scene, bm, l_iter);
changed = true;
}
/* Ensure we don't operate on these again. */
@@ -880,7 +880,7 @@ static bool uv_rip_object(Scene *scene, Object *obedit, const float co[2], const
BMLoop *l_iter = static_cast<BMLoop *>(BLI_gsetIterator_getKey(&gs_iter));
ULData *ul = UL(l_iter);
if (ul->side == side_from_cursor) {
uvedit_uv_select_disable(scene, bm, l_iter, offsets);
uvedit_uv_select_disable(scene, bm, l_iter);
changed = true;
}
/* Ensure we don't operate on these again. */

View File

@@ -382,10 +382,7 @@ void ED_uvedit_select_sync_flush(const ToolSettings *ts, BMesh *bm, const bool s
}
}
static void uvedit_vertex_select_tagged(BMesh *bm,
Scene *scene,
bool select,
const BMUVOffsets &offsets)
static void uvedit_vertex_select_tagged(BMesh *bm, Scene *scene, bool select)
{
BMFace *efa;
BMLoop *l;
@@ -394,7 +391,7 @@ static void uvedit_vertex_select_tagged(BMesh *bm,
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
}
}
}
@@ -412,13 +409,8 @@ bool uvedit_face_visible_test(const Scene *scene, const BMFace *efa)
return uvedit_face_visible_test_ex(scene->toolsettings, efa);
}
bool uvedit_face_select_test_ex(const ToolSettings *ts,
const BMesh *bm,
const BMFace *efa,
const BMUVOffsets &offsets)
bool uvedit_face_select_test_ex(const ToolSettings *ts, const BMesh *bm, const BMFace *efa)
{
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if (bm->uv_select_sync_valid == false || ED_uvedit_sync_uvselect_ignore(ts)) {
return BM_elem_flag_test(efa, BM_ELEM_SELECT);
@@ -428,23 +420,26 @@ bool uvedit_face_select_test_ex(const ToolSettings *ts,
return BM_elem_flag_test(efa, BM_ELEM_SELECT_UV);
}
const int cd_offset = (ts->uv_selectmode & UV_SELECT_VERT) ? offsets.select_vert :
offsets.select_edge;
if (ts->uv_selectmode == UV_SELECT_FACE) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT_UV)) {
return false;
}
return true;
}
const char hflag_test = (ts->uv_selectmode & UV_SELECT_VERT) ? BM_ELEM_SELECT_UV :
BM_ELEM_SELECT_UV_EDGE;
const BMLoop *l_first = BM_FACE_FIRST_LOOP(efa);
const BMLoop *l_iter = l_first;
do {
if (!BM_ELEM_CD_GET_BOOL(l_iter, cd_offset)) {
if (!BM_elem_flag_test(l_iter, hflag_test)) {
return false;
}
} while ((l_iter = l_iter->next) != l_first);
return true;
}
bool uvedit_face_select_test(const Scene *scene,
const BMesh *bm,
const BMFace *efa,
const BMUVOffsets &offsets)
bool uvedit_face_select_test(const Scene *scene, const BMesh *bm, const BMFace *efa)
{
return uvedit_face_select_test_ex(scene->toolsettings, bm, efa, offsets);
return uvedit_face_select_test_ex(scene->toolsettings, bm, efa);
}
void uvedit_face_select_set_with_sticky(
@@ -454,7 +449,7 @@ void uvedit_face_select_set_with_sticky(
const char sticky = ts->uv_sticky;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if (ED_uvedit_sync_uvselect_ignore(ts)) {
uvedit_face_select_set(scene, bm, efa, select, offsets);
uvedit_face_select_set(scene, bm, efa, select);
return;
}
BLI_assert(ED_uvedit_sync_uvselect_is_valid_or_ignore(ts, bm));
@@ -466,7 +461,7 @@ void uvedit_face_select_set_with_sticky(
* (not part of any face selections). This now uses the sticky location mode logic instead. */
switch (sticky) {
case UV_STICKY_DISABLE: {
uvedit_face_select_set(scene, bm, efa, select, offsets);
uvedit_face_select_set(scene, bm, efa, select);
break;
}
default: {
@@ -530,8 +525,9 @@ void uvedit_face_select_shared_vert(const Scene *scene,
return;
}
uvedit_face_select_set_no_sync(ts, bm, efa, select);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_edge_select_set_no_sync(ts, bm, l, select);
if (select) {
uvedit_uv_select_shared_vert(scene, bm, l, select, UV_STICKY_LOCATION, offsets);
@@ -544,24 +540,18 @@ void uvedit_face_select_shared_vert(const Scene *scene,
}
}
void uvedit_face_select_set(
const Scene *scene, BMesh *bm, BMFace *efa, const bool select, const BMUVOffsets &offsets)
void uvedit_face_select_set(const Scene *scene, BMesh *bm, BMFace *efa, const bool select)
{
if (select) {
uvedit_face_select_enable(scene, bm, efa, offsets);
uvedit_face_select_enable(scene, bm, efa);
}
else {
uvedit_face_select_disable(scene, bm, efa, offsets);
uvedit_face_select_disable(scene, bm, efa);
}
}
void uvedit_face_select_enable(const Scene *scene,
BMesh *bm,
BMFace *efa,
const BMUVOffsets &offsets)
void uvedit_face_select_enable(const Scene *scene, BMesh *bm, BMFace *efa)
{
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
@@ -576,20 +566,16 @@ void uvedit_face_select_enable(const Scene *scene,
BMLoop *l;
BMIter liter;
uvedit_face_select_set_no_sync(ts, bm, efa, true);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
uvedit_vert_select_set_no_sync(ts, bm, l, true);
uvedit_edge_select_set_no_sync(ts, bm, l, true);
}
}
}
void uvedit_face_select_disable(const Scene *scene,
BMesh *bm,
BMFace *efa,
const BMUVOffsets &offsets)
void uvedit_face_select_disable(const Scene *scene, BMesh *bm, BMFace *efa)
{
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
@@ -604,9 +590,10 @@ void uvedit_face_select_disable(const Scene *scene,
BMLoop *l;
BMIter liter;
uvedit_face_select_set_no_sync(ts, bm, efa, false);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
uvedit_vert_select_set_no_sync(ts, bm, l, false);
uvedit_edge_select_set_no_sync(ts, bm, l, false);
}
}
}
@@ -616,8 +603,6 @@ bool uvedit_edge_select_test_ex(const ToolSettings *ts,
const BMLoop *l,
const BMUVOffsets &offsets)
{
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if ((bm->uv_select_sync_valid == false) && (ts->selectmode == SCE_SELECT_FACE)) {
/* Face only is a special case that can respect sticky modes. */
@@ -657,10 +642,10 @@ bool uvedit_edge_select_test_ex(const ToolSettings *ts,
}
if (ts->uv_selectmode & UV_SELECT_VERT) {
return BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) &&
BM_ELEM_CD_GET_BOOL(l->next, offsets.select_vert);
return uvedit_vert_select_get_no_sync(ts, bm, l) &&
uvedit_vert_select_get_no_sync(ts, bm, l->next);
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_edge);
return uvedit_edge_select_get_no_sync(ts, bm, l);
}
bool uvedit_edge_select_test(const Scene *scene,
@@ -681,7 +666,7 @@ void uvedit_edge_select_set_with_sticky(const Scene *scene,
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if (ED_uvedit_sync_uvselect_ignore(ts)) {
uvedit_edge_select_set(scene, bm, l, select, offsets);
uvedit_edge_select_set(scene, bm, l, select);
return;
}
BLI_assert(ED_uvedit_sync_uvselect_is_valid_or_ignore(ts, bm));
@@ -691,7 +676,7 @@ void uvedit_edge_select_set_with_sticky(const Scene *scene,
switch (sticky) {
case UV_STICKY_DISABLE: {
if (uvedit_face_visible_test(scene, l->f)) {
uvedit_edge_select_set(scene, bm, l, select, offsets);
uvedit_edge_select_set(scene, bm, l, select);
}
break;
}
@@ -709,8 +694,7 @@ void uvedit_edge_select_set_with_sticky(const Scene *scene,
static bool UNUSED_FUNCTION(bm_loop_select_vert_check_internal)(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets)
BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
@@ -722,13 +706,10 @@ static bool UNUSED_FUNCTION(bm_loop_select_vert_check_internal)(const Scene *sce
BLI_assert(!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN));
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV);
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_vert);
return uvedit_vert_select_get_no_sync(ts, bm, l);
}
static bool bm_loop_select_edge_check_internal(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets)
static bool bm_loop_select_edge_check_internal(const Scene *scene, BMesh *bm, BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
@@ -740,7 +721,7 @@ static bool bm_loop_select_edge_check_internal(const Scene *scene,
BLI_assert(!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN));
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV_EDGE);
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_edge);
return uvedit_edge_select_get_no_sync(ts, bm, l);
}
void uvedit_edge_select_shared_vert(const Scene *scene,
@@ -758,13 +739,13 @@ void uvedit_edge_select_shared_vert(const Scene *scene,
BMLoop *l_iter = l;
do {
if (select) {
if (bm_loop_select_edge_check_internal(scene, bm, l_iter, offsets)) {
if (bm_loop_select_edge_check_internal(scene, bm, l_iter)) {
uvedit_uv_select_shared_vert(scene, bm, l_iter, true, UV_STICKY_LOCATION, offsets);
uvedit_uv_select_shared_vert(scene, bm, l_iter->next, true, UV_STICKY_LOCATION, offsets);
}
}
else {
if (!bm_loop_select_edge_check_internal(scene, bm, l_iter, offsets)) {
if (!bm_loop_select_edge_check_internal(scene, bm, l_iter)) {
if (!uvedit_vert_is_edge_select_any_other(scene->toolsettings, bm, l, offsets)) {
uvedit_uv_select_shared_vert(scene, bm, l_iter, false, UV_STICKY_LOCATION, offsets);
}
@@ -787,7 +768,6 @@ void uvedit_edge_select_set_noflush(const Scene *scene,
const ToolSettings *ts = scene->toolsettings;
if ((ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0) {
BLI_assert(offsets.uv >= 0);
BLI_assert(offsets.select_edge >= 0);
}
BMLoop *l_iter = l;
do {
@@ -797,38 +777,27 @@ void uvedit_edge_select_set_noflush(const Scene *scene,
BM_loop_edge_uvselect_set_noflush(bm, l_iter, select);
}
else {
BM_ELEM_CD_SET_BOOL(l_iter, offsets.select_edge, select);
uvedit_edge_select_set_no_sync(ts, bm, l, select);
}
}
}
} while (((l_iter = l_iter->radial_next) != l) && (sticky_flag != UV_STICKY_DISABLE));
}
void uvedit_edge_select_set(const Scene *scene,
BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets)
void uvedit_edge_select_set(const Scene *scene, BMesh *bm, BMLoop *l, const bool select)
{
if (select) {
uvedit_edge_select_enable(scene, bm, l, offsets);
uvedit_edge_select_enable(scene, bm, l);
}
else {
uvedit_edge_select_disable(scene, bm, l, offsets);
uvedit_edge_select_disable(scene, bm, l);
}
}
void uvedit_edge_select_enable(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets)
void uvedit_edge_select_enable(const Scene *scene, BMesh *bm, BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if (ED_uvedit_sync_uvselect_ignore(ts)) {
if (ts->selectmode & SCE_SELECT_FACE) {
@@ -847,16 +816,13 @@ void uvedit_edge_select_enable(const Scene *scene,
}
}
else {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
BM_ELEM_CD_SET_BOOL(l->next, offsets.select_vert, true);
uvedit_vert_select_set_no_sync(ts, bm, l, true);
uvedit_vert_select_set_no_sync(ts, bm, l->next, true);
uvedit_edge_select_set_no_sync(ts, bm, l, true);
}
}
void uvedit_edge_select_disable(const Scene *scene,
BMesh *bm,
BMLoop *l,
const BMUVOffsets &offsets)
void uvedit_edge_select_disable(const Scene *scene, BMesh *bm, BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
@@ -891,22 +857,19 @@ void uvedit_edge_select_disable(const Scene *scene,
}
}
else {
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.select_edge >= 0);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
uvedit_edge_select_set_no_sync(ts, bm, l, false);
if ((ts->uv_selectmode & UV_SELECT_VERT) == 0) {
/* Deselect UV vertex if not part of another edge selection */
if (!BM_ELEM_CD_GET_BOOL(l->next, offsets.select_edge)) {
BM_ELEM_CD_SET_BOOL(l->next, offsets.select_vert, false);
if (!uvedit_edge_select_get_no_sync(ts, bm, l->next)) {
uvedit_vert_select_set_no_sync(ts, bm, l->next, false);
}
if (!BM_ELEM_CD_GET_BOOL(l->prev, offsets.select_edge)) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
if (!uvedit_edge_select_get_no_sync(ts, bm, l->prev)) {
uvedit_vert_select_set_no_sync(ts, bm, l, false);
}
}
else {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
BM_ELEM_CD_SET_BOOL(l->next, offsets.select_vert, false);
uvedit_vert_select_set_no_sync(ts, bm, l, false);
uvedit_vert_select_set_no_sync(ts, bm, l->next, false);
}
}
}
@@ -916,7 +879,6 @@ bool uvedit_uv_select_test_ex(const ToolSettings *ts,
const BMLoop *l,
const BMUVOffsets &offsets)
{
BLI_assert(offsets.select_vert >= 0);
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if ((bm->uv_select_sync_valid == false) && (ts->selectmode == SCE_SELECT_FACE)) {
@@ -989,7 +951,7 @@ bool uvedit_uv_select_test_ex(const ToolSettings *ts,
/* Are you looking for `uvedit_edge_select_test(...)` instead? */
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_vert);
return uvedit_vert_select_get_no_sync(ts, bm, l);
}
bool uvedit_uv_select_test(const Scene *scene,
@@ -1006,7 +968,7 @@ void uvedit_uv_select_set_with_sticky(
const ToolSettings *ts = scene->toolsettings;
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
if (ED_uvedit_sync_uvselect_ignore(ts)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
return;
}
}
@@ -1015,7 +977,7 @@ void uvedit_uv_select_set_with_sticky(
switch (sticky) {
case UV_STICKY_DISABLE: {
if (uvedit_face_visible_test(scene, l->f)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
}
break;
}
@@ -1061,7 +1023,7 @@ void uvedit_uv_select_shared_vert(const Scene *scene,
}
if (do_select) {
uvedit_uv_select_set(scene, bm, l_radial_iter, select, offsets);
uvedit_uv_select_set(scene, bm, l_radial_iter, select);
}
}
}
@@ -1069,22 +1031,17 @@ void uvedit_uv_select_shared_vert(const Scene *scene,
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, l->v)) != e_first);
}
void uvedit_uv_select_set(const Scene *scene,
BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets)
void uvedit_uv_select_set(const Scene *scene, BMesh *bm, BMLoop *l, const bool select)
{
if (select) {
uvedit_uv_select_enable(scene, bm, l, offsets);
uvedit_uv_select_enable(scene, bm, l);
}
else {
uvedit_uv_select_disable(scene, bm, l, offsets);
uvedit_uv_select_disable(scene, bm, l);
}
}
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l, const BMUVOffsets &offsets)
void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
@@ -1106,12 +1063,11 @@ void uvedit_uv_select_enable(const Scene *scene, BMesh *bm, BMLoop *l, const BMU
}
}
else {
BLI_assert(offsets.select_vert >= 0);
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
uvedit_vert_select_set_no_sync(ts, bm, l, true);
}
}
void uvedit_uv_select_disable(const Scene *scene, BMesh *bm, BMLoop *l, const BMUVOffsets &offsets)
void uvedit_uv_select_disable(const Scene *scene, BMesh *bm, BMLoop *l)
{
const ToolSettings *ts = scene->toolsettings;
@@ -1129,8 +1085,7 @@ void uvedit_uv_select_disable(const Scene *scene, BMesh *bm, BMLoop *l, const BM
}
}
else {
BLI_assert(offsets.select_vert >= 0);
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
uvedit_vert_select_set_no_sync(ts, bm, l, false);
}
}
@@ -1195,23 +1150,17 @@ static BMLoop *uvedit_loop_find_other_boundary_loop_with_visible_face(const Scen
/** \name Low Level Selection API
* \{ */
bool uvedit_loop_vert_select_get(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets)
bool uvedit_loop_vert_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l)
{
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
BLI_assert(bm->uv_select_sync_valid);
UNUSED_VARS_NDEBUG(bm);
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV);
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_vert);
return uvedit_vert_select_get_no_sync(ts, bm, l);
}
bool uvedit_loop_edge_select_get(const ToolSettings *ts,
const BMesh *bm,
const BMLoop *l,
const BMUVOffsets &offsets)
bool uvedit_loop_edge_select_get(const ToolSettings *ts, const BMesh *bm, const BMLoop *l)
{
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
BLI_assert(bm->uv_select_sync_valid);
@@ -1220,14 +1169,13 @@ bool uvedit_loop_edge_select_get(const ToolSettings *ts,
BLI_assert(!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN));
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV_EDGE);
}
return BM_ELEM_CD_GET_BOOL(l, offsets.select_edge);
return uvedit_edge_select_get_no_sync(ts, bm, l);
}
void uvedit_loop_vert_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets)
const bool select)
{
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
BLI_assert(bm->uv_select_sync_valid);
@@ -1235,14 +1183,13 @@ void uvedit_loop_vert_select_set(const ToolSettings *ts,
BM_elem_flag_set(l, BM_ELEM_SELECT_UV, select);
return;
}
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select);
uvedit_vert_select_set_no_sync(ts, bm, l, select);
}
void uvedit_loop_edge_select_set(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
const bool select,
const BMUVOffsets &offsets)
const bool select)
{
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
BLI_assert(bm->uv_select_sync_valid);
@@ -1250,7 +1197,7 @@ void uvedit_loop_edge_select_set(const ToolSettings *ts,
BM_elem_flag_set(l, BM_ELEM_SELECT_UV_EDGE, select);
return;
}
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select);
uvedit_edge_select_set_no_sync(ts, bm, l, select);
}
/** \} */
@@ -1650,8 +1597,8 @@ void uvedit_select_prepare_custom_data(const Scene *scene, BMesh *bm)
BLI_assert((ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
UNUSED_VARS_NDEBUG(ts);
const char *active_uv_name = CustomData_get_active_layer_name(&bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(bm, active_uv_name);
BM_uv_map_attr_edge_select_ensure(bm, active_uv_name);
BLI_assert(active_uv_name);
UNUSED_VARS_NDEBUG(active_uv_name);
}
void uvedit_select_prepare_sync_select(const Scene *scene, BMesh *bm)
@@ -1716,7 +1663,7 @@ bool uvedit_edge_is_face_select_any_other(const ToolSettings *ts,
continue;
}
if (BM_loop_uv_share_edge_check(l, l_radial_iter, offsets.uv) &&
uvedit_face_select_test_ex(ts, bm, l_radial_iter->f, offsets))
uvedit_face_select_test_ex(ts, bm, l_radial_iter->f))
{
return true;
}
@@ -1738,7 +1685,7 @@ bool uvedit_vert_is_face_select_any_other(const ToolSettings *ts,
continue;
}
if (BM_loop_uv_share_vert_check(l, l_iter, offsets.uv) &&
uvedit_face_select_test_ex(ts, bm, l_iter->f, offsets))
uvedit_face_select_test_ex(ts, bm, l_iter->f))
{
return true;
}
@@ -1759,7 +1706,7 @@ bool uvedit_vert_is_all_other_faces_selected(const ToolSettings *ts,
continue;
}
if (BM_loop_uv_share_vert_check(l, l_iter, offsets.uv) &&
!uvedit_face_select_test_ex(ts, bm, l_iter->f, offsets))
!uvedit_face_select_test_ex(ts, bm, l_iter->f))
{
return false;
}
@@ -1767,11 +1714,9 @@ bool uvedit_vert_is_all_other_faces_selected(const ToolSettings *ts,
return true;
}
static void bm_clear_uv_vert_selection(const Scene *scene, BMesh *bm, const BMUVOffsets &offsets)
static void bm_clear_uv_vert_selection(const Scene *scene, BMesh *bm)
{
if (offsets.select_vert == -1) {
return;
}
const ToolSettings *ts = scene->toolsettings;
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -1780,13 +1725,75 @@ static void bm_clear_uv_vert_selection(const Scene *scene, BMesh *bm, const BMUV
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
uvedit_vert_select_set_no_sync(ts, bm, l, false);
}
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UV Selection Non-Sync API
*
* \note this is for non-sync selection,
* where different rules apply and there is no expectation a selected UV
* implies it's base mesh selection flag also be set.
*
* \{ */
bool uvedit_vert_select_get_no_sync(const ToolSettings *ts, const BMesh *bm, const BMLoop *l)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV);
}
bool uvedit_edge_select_get_no_sync(const ToolSettings *ts, const BMesh *bm, const BMLoop *l)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
return BM_elem_flag_test_bool(l, BM_ELEM_SELECT_UV_EDGE);
}
bool uvedit_face_select_get_no_sync(const ToolSettings *ts, const BMesh *bm, const BMFace *f)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
return BM_elem_flag_test_bool(f, BM_ELEM_SELECT_UV);
}
void uvedit_vert_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
bool select)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
BLI_assert(BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
BM_elem_flag_set(l, BM_ELEM_SELECT_UV, select);
}
void uvedit_edge_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMLoop *l,
bool select)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
BLI_assert(BM_elem_flag_test(l->f, BM_ELEM_HIDDEN) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
BM_elem_flag_set(l, BM_ELEM_SELECT_UV_EDGE, select);
}
void uvedit_face_select_set_no_sync(const ToolSettings *ts,
const BMesh *bm,
BMFace *f,
bool select)
{
BLI_assert(bm && (ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
BLI_assert(BM_elem_flag_test(f, BM_ELEM_HIDDEN) == 0);
UNUSED_VARS_NDEBUG(ts, bm);
BM_elem_flag_set(f, BM_ELEM_SELECT_UV, select);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name UV Select Abstraction API
*
@@ -1909,7 +1916,6 @@ void ED_uvedit_selectmode_flush(const Scene *scene, BMesh *bm)
UNUSED_VARS_NDEBUG(ts);
uvedit_select_prepare_custom_data(scene, bm);
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
/* Vertex Mode only. */
if (ts->uv_selectmode & UV_SELECT_VERT) {
@@ -1920,11 +1926,34 @@ void ED_uvedit_selectmode_flush(const Scene *scene, BMesh *bm)
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
bool edge_selected = BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) &&
BM_ELEM_CD_GET_BOOL(l->next, offsets.select_vert);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, edge_selected);
bool edge_selected = uvedit_vert_select_get_no_sync(ts, bm, l) &&
uvedit_vert_select_get_no_sync(ts, bm, l->next);
uvedit_edge_select_set_no_sync(ts, bm, l, edge_selected);
if (!edge_selected) {
select_all = false;
}
}
uvedit_face_select_set_no_sync(ts, bm, efa, select_all);
}
}
else if (ts->uv_selectmode & UV_SELECT_EDGE) {
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!uvedit_edge_select_get_no_sync(ts, bm, l)) {
select_all = false;
break;
}
}
uvedit_face_select_set_no_sync(ts, bm, efa, select_all);
}
}
}
@@ -1941,7 +1970,6 @@ void uvedit_select_flush_from_verts(const Scene *scene, BMesh *bm, const bool se
BLI_assert((ts->uv_flag & UV_FLAG_SELECT_SYNC) == 0);
UNUSED_VARS_NDEBUG(ts);
uvedit_select_prepare_custom_data(scene, bm);
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
if (select) {
/* Careful when using this in face select mode.
@@ -1953,12 +1981,19 @@ void uvedit_select_flush_from_verts(const Scene *scene, BMesh *bm, const bool se
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) &&
BM_ELEM_CD_GET_BOOL(l->next, offsets.select_vert))
if (uvedit_vert_select_get_no_sync(ts, bm, l) &&
uvedit_vert_select_get_no_sync(ts, bm, l->next))
{
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
uvedit_edge_select_set_no_sync(ts, bm, l, true);
}
else {
select_all = false;
}
}
if (select_all) {
uvedit_face_select_set_no_sync(ts, bm, efa, true);
}
}
}
@@ -1970,13 +2005,18 @@ void uvedit_select_flush_from_verts(const Scene *scene, BMesh *bm, const bool se
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (!BM_ELEM_CD_GET_BOOL(l, offsets.select_vert) ||
!BM_ELEM_CD_GET_BOOL(l->next, offsets.select_vert))
if (!uvedit_vert_select_get_no_sync(ts, bm, l) ||
!uvedit_vert_select_get_no_sync(ts, bm, l->next))
{
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
uvedit_edge_select_set_no_sync(ts, bm, l, false);
select_all = false;
}
}
if (select_all == false) {
uvedit_face_select_set_no_sync(ts, bm, efa, false);
}
}
}
}
@@ -2157,9 +2197,6 @@ static int uv_select_edgeloop(Scene *scene, Object *obedit, UvNearestHit *hit, c
/* NOTE: this is a special case, even when sync select is enabled,
* the flags are used then flushed to the vertices.
* So these need to be ensured even though the layers aren't used afterwards. */
const char *active_uv_name = CustomData_get_active_layer_name(&bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(bm, active_uv_name);
BM_uv_map_attr_edge_select_ensure(bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
if (extend) {
@@ -2268,7 +2305,7 @@ static int uv_select_faceloop(Scene *scene, Object *obedit, UvNearestHit *hit, c
BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
if (extend) {
select = !uvedit_face_select_test(scene, bm, hit->l->f, offsets);
select = !uvedit_face_select_test(scene, bm, hit->l->f);
}
else {
select = true;
@@ -2505,7 +2542,7 @@ static void uv_select_linked_multi(Scene *scene,
* - There are no connected fully selected faces UV-connected to this loop.
*/
BLI_assert(!select_faces);
if (uvedit_face_select_test(scene, bm, l->f, offsets)) {
if (uvedit_face_select_test(scene, bm, l->f)) {
/* pass */
}
else {
@@ -2513,7 +2550,7 @@ static void uv_select_linked_multi(Scene *scene,
BMLoop *l_other;
BM_ITER_ELEM (l_other, &liter_other, l->v, BM_LOOPS_OF_VERT) {
if ((l != l_other) && !BM_loop_uv_share_vert_check(l, l_other, offsets.uv) &&
uvedit_face_select_test(scene, bm, l_other->f, offsets))
uvedit_face_select_test(scene, bm, l_other->f))
{
add_to_stack = false;
break;
@@ -2622,7 +2659,7 @@ static void uv_select_linked_multi(Scene *scene,
} \
} \
else { \
uvedit_face_select_set(scene, bm, efa, value, offsets); \
uvedit_face_select_set(scene, bm, efa, value); \
} \
(void)0
@@ -2815,14 +2852,14 @@ static wmOperatorStatus uv_select_more_less(bContext *C, const bool select)
int sel_state = 0;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_loop_vert_select_get(ts, bm, l, offsets)) {
if (uvedit_loop_vert_select_get(ts, bm, l)) {
sel_state |= NEIGHBORING_FACE_IS_SEL;
}
else {
sel_state |= CURR_FACE_IS_UNSEL;
}
if (!uvedit_loop_edge_select_get(ts, bm, l, offsets)) {
if (!uvedit_loop_edge_select_get(ts, bm, l)) {
sel_state |= CURR_FACE_IS_UNSEL;
}
@@ -2839,7 +2876,7 @@ static wmOperatorStatus uv_select_more_less(bContext *C, const bool select)
#undef CURR_FACE_IS_UNSEL
}
else {
if (!uvedit_face_select_test(scene, bm, efa, offsets)) {
if (!uvedit_face_select_test(scene, bm, efa)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
@@ -2868,7 +2905,7 @@ static wmOperatorStatus uv_select_more_less(bContext *C, const bool select)
if (uvedit_face_visible_test(scene, efa)) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_loop_vert_select_get(ts, bm, l, offsets) == select) {
if (uvedit_loop_vert_select_get(ts, bm, l) == select) {
BM_elem_flag_enable(l->next, BM_ELEM_TAG);
BM_elem_flag_enable(l->prev, BM_ELEM_TAG);
changed = true;
@@ -2967,14 +3004,12 @@ bool uvedit_select_is_any_selected(const Scene *scene, BMesh *bm)
return (bm->totvertsel || bm->totedgesel || bm->totfacesel);
}
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_vert)) {
if (uvedit_vert_select_get_no_sync(ts, bm, l)) {
return true;
}
}
@@ -3018,15 +3053,15 @@ static void uv_select_all(const Scene *scene, BMEditMesh *em, bool select_all)
BMIter iter, liter;
uvedit_select_prepare_custom_data(scene, bm);
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
uvedit_face_select_set_no_sync(ts, bm, efa, select_all);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, select_all);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, select_all);
uvedit_vert_select_set_no_sync(ts, bm, l, select_all);
uvedit_edge_select_set_no_sync(ts, bm, l, select_all);
}
}
}
@@ -3134,7 +3169,6 @@ static void uv_select_invert(const Scene *scene, BMEditMesh *em)
}
uvedit_select_prepare_custom_data(scene, bm);
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BMFace *efa;
BMLoop *l;
BMIter iter, liter;
@@ -3143,21 +3177,29 @@ static void uv_select_invert(const Scene *scene, BMEditMesh *em)
if (!uvedit_face_visible_test(scene, efa)) {
continue;
}
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uv_selectmode & (UV_SELECT_EDGE | UV_SELECT_FACE)) {
/* Use UV edge selection to find vertices and edges that must be selected. */
bool es = BM_ELEM_CD_GET_BOOL(l, offsets.select_edge);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, !es);
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, false);
bool es = !uvedit_edge_select_get_no_sync(ts, bm, l);
uvedit_edge_select_set_no_sync(ts, bm, l, es);
uvedit_vert_select_set_no_sync(ts, bm, l, false);
if (es == false) {
select_all = false;
}
}
/* Use UV vertex selection to find vertices and edges that must be selected. */
else {
BLI_assert(uv_selectmode & UV_SELECT_VERT);
bool vs = BM_ELEM_CD_GET_BOOL(l, offsets.select_vert);
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, !vs);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, false);
bool vs = !uvedit_vert_select_get_no_sync(ts, bm, l);
uvedit_vert_select_set_no_sync(ts, bm, l, vs);
uvedit_edge_select_set_no_sync(ts, bm, l, false);
if (vs == false) {
select_all = false;
}
}
}
uvedit_face_select_set_no_sync(ts, bm, efa, select_all);
}
/* Flush based on uv vert/edge flags and current UV select mode */
@@ -3373,7 +3415,7 @@ static bool uv_mouse_select_multi(bContext *C,
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
if (selectmode == UV_SELECT_FACE) {
is_selected = uvedit_face_select_test(scene, bm, hit.efa, offsets);
is_selected = uvedit_face_select_test(scene, bm, hit.efa);
}
else if (selectmode == UV_SELECT_EDGE) {
is_selected = uvedit_edge_select_test(scene, bm, hit.l, offsets);
@@ -3385,7 +3427,7 @@ static bool uv_mouse_select_multi(bContext *C,
is_selected = uvedit_uv_select_test(scene, bm, hit.l, offsets);
}
else {
is_selected = uvedit_face_select_test(scene, bm, hit.efa, offsets);
is_selected = uvedit_face_select_test(scene, bm, hit.efa);
}
}
}
@@ -4042,7 +4084,6 @@ static wmOperatorStatus uv_select_split_exec(bContext *C, wmOperator *op)
else {
uvedit_select_prepare_custom_data(scene, bm);
}
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
bool is_sel = false;
@@ -4054,8 +4095,8 @@ static wmOperatorStatus uv_select_split_exec(bContext *C, wmOperator *op)
/* are we all selected? */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
const bool select_vert = uvedit_loop_vert_select_get(ts, bm, l, offsets);
const bool select_edge = uvedit_loop_edge_select_get(ts, bm, l, offsets);
const bool select_vert = uvedit_loop_vert_select_get(ts, bm, l);
const bool select_edge = uvedit_loop_edge_select_get(ts, bm, l);
if (select_vert || select_edge) {
is_sel = true;
@@ -4074,8 +4115,8 @@ static wmOperatorStatus uv_select_split_exec(bContext *C, wmOperator *op)
/* No need to deselect the face (with sync-select) as it wont be selected,
* since it already has a mixed selection. */
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
uvedit_loop_vert_select_set(ts, bm, l, false, offsets);
uvedit_loop_edge_select_set(ts, bm, l, false, offsets);
uvedit_loop_vert_select_set(ts, bm, l, false);
uvedit_loop_edge_select_set(ts, bm, l, false);
}
changed = true;
@@ -4136,7 +4177,7 @@ static void uv_select_tag_update_for_object(Depsgraph *depsgraph,
static void uvedit_uv_select_flush_from_tag_sticky_loc_internal(
const Scene *scene, BMesh *bm, BMLoop *l, const bool select, const BMUVOffsets &offsets)
{
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
BMVert *v = l->v;
BLI_assert(v->e);
@@ -4156,7 +4197,7 @@ static void uvedit_uv_select_flush_from_tag_sticky_loc_internal(
continue;
}
if (BM_loop_uv_share_vert_check(l, l_iter, offsets.uv)) {
uvedit_uv_select_set(scene, bm, l_iter, select, offsets);
uvedit_uv_select_set(scene, bm, l_iter, select);
}
} while ((l_iter = l_iter->radial_next) != l_first);
} while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v)) != e_first);
@@ -4215,9 +4256,12 @@ static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, co
if (ts->uv_flag & UV_FLAG_SELECT_SYNC) {
BM_face_uvselect_set_noflush(bm, efa, select);
}
else {
uvedit_face_select_set_no_sync(ts, bm, efa, select);
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
uvedit_loop_edge_select_set(ts, bm, l, select, offsets);
uvedit_loop_edge_select_set(ts, bm, l, select);
if (select) {
uvedit_uv_select_flush_from_tag_sticky_loc_internal(scene, bm, l, select, offsets);
@@ -4235,7 +4279,7 @@ static void uv_select_flush_from_tag_face(const Scene *scene, Object *obedit, co
if (!BM_elem_flag_test(efa, BM_ELEM_TAG)) {
continue;
}
uvedit_face_select_set(scene, bm, efa, select, offsets);
uvedit_face_select_set(scene, bm, efa, select);
}
}
}
@@ -4290,18 +4334,50 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co
/* now select tagged verts */
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
bool tag_all = true;
bool tag_any = false;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
tag_any = true;
}
else {
tag_all = false;
}
}
if (select) {
if (tag_all && uvedit_face_visible_test(scene, efa)) {
uvedit_face_select_set_no_sync(ts, bm, efa, true);
}
}
else {
if (tag_any && uvedit_face_visible_test(scene, efa)) {
uvedit_face_select_set_no_sync(ts, bm, efa, false);
}
}
}
}
else if ((use_mesh_select == false) && (ts->uv_sticky == UV_STICKY_LOCATION)) {
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
bool tag_all = true;
bool tag_any = false;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
uvedit_uv_select_flush_from_tag_sticky_loc_internal(scene, bm, l, select, offsets);
tag_any = true;
}
else {
tag_all = false;
}
}
if (select) {
if (tag_all && uvedit_face_visible_test(scene, efa)) {
uvedit_face_select_set_no_sync(ts, bm, efa, true);
}
}
else {
if (tag_any && uvedit_face_visible_test(scene, efa)) {
uvedit_face_select_set_no_sync(ts, bm, efa, false);
}
}
}
@@ -4310,7 +4386,7 @@ static void uv_select_flush_from_tag_loop(const Scene *scene, Object *obedit, co
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_elem_flag_test(l, BM_ELEM_TAG)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
}
}
}
@@ -4358,7 +4434,7 @@ static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMesh *bm)
/* Use UV edge selection to identify which verts must to be selected */
/* Clear UV vert flags */
bm_clear_uv_vert_selection(scene, bm, offsets);
bm_clear_uv_vert_selection(scene, bm);
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
@@ -4368,7 +4444,7 @@ static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMesh *bm)
}
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* Select verts based on UV edge flag. */
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) {
if (uvedit_edge_select_get_no_sync(ts, bm, l)) {
uvedit_uv_select_flush_from_tag_sticky_loc_internal(scene, bm, l, true, offsets);
uvedit_uv_select_flush_from_tag_sticky_loc_internal(scene, bm, l->next, true, offsets);
}
@@ -4381,16 +4457,18 @@ static void uv_select_flush_from_loop_edge_flag(const Scene *scene, BMesh *bm)
}
else {
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
bool select_all = true;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.select_edge)) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l->next, offsets.select_vert, true);
if (uvedit_edge_select_get_no_sync(ts, bm, l)) {
uvedit_vert_select_set_no_sync(ts, bm, l, true);
uvedit_vert_select_set_no_sync(ts, bm, l->next, true);
}
else if (!BM_ELEM_CD_GET_BOOL(l->prev, offsets.select_edge)) {
BM_ELEM_CD_SET_BOOL(l->next, offsets.select_vert, false);
else if (!uvedit_edge_select_get_no_sync(ts, bm, l->prev)) {
uvedit_vert_select_set_no_sync(ts, bm, l->next, false);
select_all = false;
}
}
uvedit_face_select_set_no_sync(ts, bm, efa, select_all);
}
}
}
@@ -4455,7 +4533,7 @@ static wmOperatorStatus uv_box_select_exec(bContext *C, wmOperator *op)
uvedit_select_prepare_custom_data(scene, bm);
if (pinned) {
const char *active_uv_name = CustomData_get_active_layer_name(&bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_attr_pin_ensure(bm, active_uv_name);
BM_uv_map_attr_pin_ensure_named(bm, active_uv_name);
}
}
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
@@ -4570,14 +4648,14 @@ static wmOperatorStatus uv_box_select_exec(bContext *C, wmOperator *op)
if (!pinned || (ts->uv_flag & UV_FLAG_SELECT_SYNC)) {
/* UV_FLAG_SELECT_SYNC - can't do pinned selection */
if (BLI_rctf_isect_pt_v(&rectf, luv)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
}
}
else if (pinned) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.pin) && BLI_rctf_isect_pt_v(&rectf, luv)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
}
}
@@ -4590,7 +4668,7 @@ static wmOperatorStatus uv_box_select_exec(bContext *C, wmOperator *op)
}
if (ts->uv_sticky == UV_STICKY_VERT) {
uvedit_vertex_select_tagged(bm, scene, select, offsets);
uvedit_vertex_select_tagged(bm, scene, select);
}
}
@@ -4749,7 +4827,7 @@ static wmOperatorStatus uv_circle_select_exec(bContext *C, wmOperator *op)
}
else {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (select == uvedit_face_select_test(scene, bm, efa, offsets)) {
if (select == uvedit_face_select_test(scene, bm, efa)) {
continue;
}
}
@@ -4813,7 +4891,7 @@ static wmOperatorStatus uv_circle_select_exec(bContext *C, wmOperator *op)
luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
if (uv_circle_select_is_point_inside(luv, offset, ellipse)) {
changed = true;
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
}
@@ -4826,7 +4904,7 @@ static wmOperatorStatus uv_circle_select_exec(bContext *C, wmOperator *op)
}
if (ts->uv_sticky == UV_STICKY_VERT) {
uvedit_vertex_select_tagged(bm, scene, select, offsets);
uvedit_vertex_select_tagged(bm, scene, select);
}
}
@@ -4968,7 +5046,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const Span<int2> mcoords, const
}
else {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (select == uvedit_face_select_test(scene, bm, efa, offsets)) {
if (select == uvedit_face_select_test(scene, bm, efa)) {
continue;
}
}
@@ -5062,7 +5140,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const Span<int2> mcoords, const
if (select != uvedit_uv_select_test(scene, bm, l, offsets)) {
float *luv = BM_ELEM_CD_GET_FLOAT_P(l, offsets.uv);
if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, luv)) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
changed = true;
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
has_selected = true;
@@ -5076,7 +5154,7 @@ static bool do_lasso_select_mesh_uv(bContext *C, const Span<int2> mcoords, const
}
if (ts->uv_sticky == UV_STICKY_VERT) {
uvedit_vertex_select_tagged(bm, scene, select, offsets);
uvedit_vertex_select_tagged(bm, scene, select);
}
}
@@ -5182,7 +5260,7 @@ static wmOperatorStatus uv_select_pinned_exec(bContext *C, wmOperator *op)
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (BM_ELEM_CD_GET_BOOL(l, offsets.pin)) {
uvedit_uv_select_enable(scene, bm, l, offsets);
uvedit_uv_select_enable(scene, bm, l);
changed = true;
}
}
@@ -5446,20 +5524,9 @@ static wmOperatorStatus uv_select_overlap(bContext *C, const bool extend)
if (scene->toolsettings->uv_flag & UV_FLAG_SELECT_SYNC) {
/* Pass. */
}
else {
const char *uv_a_name = CustomData_get_active_layer_name(&bm_a->ldata, CD_PROP_FLOAT2);
const char *uv_b_name = CustomData_get_active_layer_name(&bm_b->ldata, CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(bm_a, uv_a_name);
BM_uv_map_attr_vert_select_ensure(bm_b, uv_b_name);
BM_uv_map_attr_edge_select_ensure(bm_a, uv_a_name);
BM_uv_map_attr_edge_select_ensure(bm_b, uv_b_name);
}
const BMUVOffsets offsets_a = BM_uv_map_offsets_get(bm_a);
const BMUVOffsets offsets_b = BM_uv_map_offsets_get(bm_b);
/* Skip if both faces are already selected. */
if (uvedit_face_select_test(scene, bm_a, face_a, offsets_a) &&
uvedit_face_select_test(scene, bm_b, face_b, offsets_b))
if (uvedit_face_select_test(scene, bm_a, face_a) &&
uvedit_face_select_test(scene, bm_b, face_b))
{
continue;
}
@@ -5467,8 +5534,8 @@ static wmOperatorStatus uv_select_overlap(bContext *C, const bool extend)
/* Main tri-tri overlap test. */
const float endpoint_bias = -1e-4f;
if (overlap_tri_tri_uv_test(o_a->tri, o_b->tri, endpoint_bias)) {
uvedit_face_select_enable(scene, bm_a, face_a, offsets_a);
uvedit_face_select_enable(scene, bm_b, face_b, offsets_b);
uvedit_face_select_enable(scene, bm_a, face_a);
uvedit_face_select_enable(scene, bm_b, face_b);
}
}
@@ -5786,7 +5853,7 @@ static wmOperatorStatus uv_select_similar_vert_exec(bContext *C, wmOperator *op)
const float needle = get_uv_vert_needle(type, l->v, ob_m3, l, offsets);
bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare);
if (select) {
uvedit_uv_select_set(scene, bm, l, select, offsets);
uvedit_uv_select_set(scene, bm, l, select);
changed = true;
}
}
@@ -5913,7 +5980,7 @@ static wmOperatorStatus uv_select_similar_edge_exec(bContext *C, wmOperator *op)
float needle = get_uv_edge_needle(type, l->e, ob_m3, l, l->next, offsets);
bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare);
if (select) {
uvedit_edge_select_set(scene, bm, l, select, offsets);
uvedit_edge_select_set(scene, bm, l, select);
changed = true;
}
}
@@ -5981,7 +6048,7 @@ static wmOperatorStatus uv_select_similar_face_exec(bContext *C, wmOperator *op)
if (!uvedit_face_visible_test(scene, face)) {
continue;
}
if (!uvedit_face_select_test(scene, bm, face, offsets)) {
if (!uvedit_face_select_test(scene, bm, face)) {
continue;
}
@@ -6023,7 +6090,7 @@ static wmOperatorStatus uv_select_similar_face_exec(bContext *C, wmOperator *op)
if (!uvedit_face_visible_test(scene, face)) {
continue;
}
if (uvedit_face_select_test(scene, bm, face, offsets)) {
if (uvedit_face_select_test(scene, bm, face)) {
continue;
}
@@ -6031,7 +6098,7 @@ static wmOperatorStatus uv_select_similar_face_exec(bContext *C, wmOperator *op)
bool select = ED_select_similar_compare_float_tree(tree_1d, needle, threshold, compare);
if (select) {
uvedit_face_select_set(scene, bm, face, select, offsets);
uvedit_face_select_set(scene, bm, face, select);
changed = true;
}
}
@@ -6059,7 +6126,7 @@ static wmOperatorStatus uv_select_similar_face_exec(bContext *C, wmOperator *op)
static bool uv_island_selected(const Scene *scene, const BMesh *bm, FaceIsland *island)
{
BLI_assert(island && island->faces_len);
return uvedit_face_select_test(scene, bm, island->faces[0], island->offsets);
return uvedit_face_select_test(scene, bm, island->faces[0]);
}
static wmOperatorStatus uv_select_similar_island_exec(bContext *C, wmOperator *op)
@@ -6146,7 +6213,7 @@ static wmOperatorStatus uv_select_similar_island_exec(bContext *C, wmOperator *o
continue;
}
for (int j = 0; j < island->faces_len; j++) {
uvedit_face_select_set(scene, bm, island->faces[j], select, island->offsets);
uvedit_face_select_set(scene, bm, island->faces[j], select);
}
changed = true;
}
@@ -6312,8 +6379,6 @@ void UV_OT_select_similar(wmOperatorType *ot)
BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, int *r_faces_len)
{
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
CLAMP_MAX(len_max, bm->totface);
int faces_len = 0;
BMFace **faces = MEM_malloc_arrayN<BMFace *>(len_max, __func__);
@@ -6322,7 +6387,7 @@ BMFace **ED_uvedit_selected_faces(const Scene *scene, BMesh *bm, int len_max, in
BMFace *f;
BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
if (uvedit_face_visible_test(scene, f)) {
if (uvedit_face_select_test(scene, bm, f, offsets)) {
if (uvedit_face_select_test(scene, bm, f)) {
faces[faces_len++] = f;
if (faces_len == len_max) {
goto finally;
@@ -6399,8 +6464,8 @@ finally:
BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, int *r_verts_len)
{
const ToolSettings *ts = scene->toolsettings;
const BMUVOffsets offsets = BM_uv_map_offsets_get(bm);
BLI_assert(offsets.select_vert >= 0);
BLI_assert(offsets.uv >= 0);
CLAMP_MAX(len_max, bm->totloop);
@@ -6425,7 +6490,7 @@ BMLoop **ED_uvedit_selected_verts(const Scene *scene, BMesh *bm, int len_max, in
BMLoop *l_iter;
BM_ITER_ELEM (l_iter, &liter, f, BM_LOOPS_OF_FACE) {
if (!BM_elem_flag_test(l_iter, BM_ELEM_TAG)) {
if (BM_ELEM_CD_GET_BOOL(l_iter, offsets.select_vert)) {
if (uvedit_vert_select_get_no_sync(ts, bm, l_iter)) {
BM_elem_flag_enable(l_iter->v, BM_ELEM_TAG);
verts[verts_len++] = l_iter;
@@ -6514,10 +6579,10 @@ void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit)
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
BM_elem_flag_disable(efa, BM_ELEM_TAG);
if (uvedit_face_visible_test(scene, efa)) {
if (uvedit_face_select_test(scene, bm, efa, offsets)) {
if (uvedit_face_select_test(scene, bm, efa)) {
BM_elem_flag_enable(efa, BM_ELEM_TAG);
}
uvedit_face_select_set(scene, bm, efa, false, offsets);
uvedit_face_select_set(scene, bm, efa, false);
}
}
uv_select_flush_from_tag_face(scene, obedit, true);
@@ -6525,7 +6590,6 @@ void ED_uvedit_selectmode_clean(const Scene *scene, Object *obedit)
ED_uvedit_selectmode_flush(scene, bm);
}
void ED_uvedit_selectmode_clean_multi(bContext *C)
{
Scene *scene = CTX_data_scene(C);

View File

@@ -920,7 +920,7 @@ static void stitch_propagate_uv_final_position(Scene *scene,
if (final) {
copy_v2_v2(luv, final_position[index].uv);
uvedit_uv_select_enable(scene, state->em->bm, l, offsets);
uvedit_uv_select_enable(scene, state->em->bm, l);
}
else {
int face_preview_pos =

View File

@@ -104,19 +104,16 @@ static bool uvedit_ensure_uvs(Object *obedit)
return false;
}
const char *active_uv_name = CustomData_get_active_layer_name(&em->bm->ldata, CD_PROP_FLOAT2);
BM_uv_map_attr_vert_select_ensure(em->bm, active_uv_name);
BM_uv_map_attr_edge_select_ensure(em->bm, active_uv_name);
const BMUVOffsets offsets = BM_uv_map_offsets_get(em->bm);
/* select new UVs (ignore UV_FLAG_SELECT_SYNC in this case) */
em->bm->uv_select_sync_valid = false;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
BMIter liter;
BMLoop *l;
BM_elem_flag_enable(l->f, BM_ELEM_SELECT_UV);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
BM_ELEM_CD_SET_BOOL(l, offsets.select_vert, true);
BM_ELEM_CD_SET_BOOL(l, offsets.select_edge, true);
BM_elem_flag_enable(l, BM_ELEM_SELECT_UV);
BM_elem_flag_enable(l, BM_ELEM_SELECT_UV_EDGE);
}
}
@@ -2667,7 +2664,7 @@ static void uv_map_clip_correct(const Scene *scene,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa, offsets)) {
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa)) {
continue;
}
@@ -2684,7 +2681,7 @@ static void uv_map_clip_correct(const Scene *scene,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa, offsets)) {
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa)) {
continue;
}
@@ -2722,7 +2719,7 @@ static void uv_map_clip_correct(const Scene *scene,
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa, offsets)) {
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa)) {
continue;
}
@@ -3258,8 +3255,8 @@ static wmOperatorStatus smart_project_exec(bContext *C, wmOperator *op)
}
if (only_selected_uvs) {
if (!uvedit_face_select_test(scene, em->bm, efa, offsets)) {
uvedit_face_select_disable(scene, em->bm, efa, offsets);
if (!uvedit_face_select_test(scene, em->bm, efa)) {
uvedit_face_select_disable(scene, em->bm, efa);
continue;
}
}
@@ -3851,8 +3848,8 @@ static float uv_sphere_project(const Scene *scene,
}
if (only_selected_uvs) {
if (!uvedit_face_select_test(scene, bm, efa, offsets)) {
uvedit_face_select_disable(scene, bm, efa, offsets);
if (!uvedit_face_select_test(scene, bm, efa)) {
uvedit_face_select_disable(scene, bm, efa);
continue; /* Unselected UV, ignore. */
}
}
@@ -4027,8 +4024,8 @@ static float uv_cylinder_project(const Scene *scene,
}
if (only_selected_uvs) {
if (!uvedit_face_select_test(scene, bm, efa, offsets)) {
uvedit_face_select_disable(scene, bm, efa, offsets);
if (!uvedit_face_select_test(scene, bm, efa)) {
uvedit_face_select_disable(scene, bm, efa);
continue; /* Unselected UV, ignore. */
}
}
@@ -4123,8 +4120,8 @@ static wmOperatorStatus cylinder_project_exec(bContext *C, wmOperator *op)
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa, offsets)) {
uvedit_face_select_disable(scene, em->bm, efa, offsets);
if (only_selected_uvs && !uvedit_face_select_test(scene, em->bm, efa)) {
uvedit_face_select_disable(scene, em->bm, efa);
continue;
}
@@ -4208,8 +4205,8 @@ static void uvedit_unwrap_cube_project(const Scene *scene,
if (use_select && !BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
continue;
}
if (only_selected_uvs && !uvedit_face_select_test(scene, bm, efa, offsets)) {
uvedit_face_select_disable(scene, bm, efa, offsets);
if (only_selected_uvs && !uvedit_face_select_test(scene, bm, efa)) {
uvedit_face_select_disable(scene, bm, efa);
continue;
}
@@ -4340,7 +4337,7 @@ void ED_uvedit_add_simple_uvs(Main *bmain, const Scene *scene, Object *ob)
BM_mesh_bm_from_me(bm, mesh, &bm_from_me_params);
/* Select all UVs for cube_project. */
ED_uvedit_select_all(bm);
ED_uvedit_select_all(scene->toolsettings, bm);
/* A cube size of 2.0 maps [-1..1] vertex coords to [0.0..1.0] in UV coords. */
uvedit_unwrap_cube_project(scene, bm, 2.0, false, false, nullptr);

View File

@@ -514,7 +514,11 @@ enum {
ME_FLAG_UNUSED_0 = 1 << 0, /* cleared */
ME_FLAG_UNUSED_1 = 1 << 1, /* cleared */
ME_FLAG_DEPRECATED_2 = 1 << 2, /* deprecated */
ME_FLAG_UNUSED_3 = 1 << 3, /* cleared */
/**
* The UV selection is marked as synchronized.
* See #BMesh::uv_select_sync_valid for details.
*/
ME_FLAG_UV_SELECT_SYNC_VALID = 1 << 3,
ME_FLAG_UNUSED_4 = 1 << 4, /* cleared */
ME_AUTOSMOOTH_LEGACY = 1 << 5, /* deprecated */
ME_FLAG_UNUSED_6 = 1 << 6, /* cleared */

View File

@@ -951,54 +951,6 @@ static PointerRNA bool_layer_ensure(PointerRNA *ptr,
return RNA_pointer_create_discrete(&mesh->id, &RNA_BoolAttribute, bool_layer);
}
/* Collection accessors for vert_select. */
static void rna_MeshUVLoopLayer_vert_select_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
bool_layer_begin(iter, ptr, BKE_uv_map_vert_select_name_get);
}
static bool rna_MeshUVLoopLayer_vert_select_lookup_int(PointerRNA *ptr,
int index,
PointerRNA *r_ptr)
{
return bool_layer_lookup_int(ptr, index, r_ptr, BKE_uv_map_vert_select_name_get);
}
static int rna_MeshUVLoopLayer_vert_select_length(PointerRNA *ptr)
{
return bool_layer_length(ptr, BKE_uv_map_vert_select_name_get);
}
static PointerRNA rna_MeshUVLoopLayer_vert_select_ensure(PointerRNA ptr)
{
return bool_layer_ensure(&ptr, BKE_uv_map_vert_select_name_get);
}
/* Collection accessors for edge_select. */
static void rna_MeshUVLoopLayer_edge_select_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
bool_layer_begin(iter, ptr, BKE_uv_map_edge_select_name_get);
}
static bool rna_MeshUVLoopLayer_edge_select_lookup_int(PointerRNA *ptr,
int index,
PointerRNA *r_ptr)
{
return bool_layer_lookup_int(ptr, index, r_ptr, BKE_uv_map_edge_select_name_get);
}
static int rna_MeshUVLoopLayer_edge_select_length(PointerRNA *ptr)
{
return bool_layer_length(ptr, BKE_uv_map_edge_select_name_get);
}
static PointerRNA rna_MeshUVLoopLayer_edge_selection_ensure(PointerRNA ptr)
{
return bool_layer_ensure(&ptr, BKE_uv_map_edge_select_name_get);
}
/* Collection accessors for pin. */
static void rna_MeshUVLoopLayer_pin_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
@@ -1722,56 +1674,6 @@ static bool get_uv_index_and_layer(const PointerRNA *ptr,
return false;
}
static bool rna_MeshUVLoop_select_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
int uv_map_index;
int loop_index;
blender::VArray<bool> select;
if (get_uv_index_and_layer(ptr, &uv_map_index, &loop_index)) {
select = ED_mesh_uv_map_vert_select_layer_get(mesh, uv_map_index);
}
return select ? select[loop_index] : false;
}
static void rna_MeshUVLoop_select_set(PointerRNA *ptr, const bool value)
{
Mesh *mesh = rna_mesh(ptr);
int uv_map_index;
int loop_index;
if (get_uv_index_and_layer(ptr, &uv_map_index, &loop_index)) {
blender::bke::AttributeWriter<bool> select = ED_mesh_uv_map_vert_select_layer_ensure(
mesh, uv_map_index);
select.varray.set(loop_index, value);
select.finish();
}
}
static bool rna_MeshUVLoop_select_edge_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
int uv_map_index;
int loop_index;
blender::VArray<bool> select_edge;
if (get_uv_index_and_layer(ptr, &uv_map_index, &loop_index)) {
select_edge = ED_mesh_uv_map_edge_select_layer_get(mesh, uv_map_index);
}
return select_edge ? select_edge[loop_index] : false;
}
static void rna_MeshUVLoop_select_edge_set(PointerRNA *ptr, const bool value)
{
Mesh *mesh = rna_mesh(ptr);
int uv_map_index;
int loop_index;
if (get_uv_index_and_layer(ptr, &uv_map_index, &loop_index)) {
blender::bke::AttributeWriter<bool> select_edge = ED_mesh_uv_map_edge_select_layer_ensure(
mesh, uv_map_index);
select_edge.varray.set(loop_index, value);
select_edge.finish();
}
}
static bool rna_MeshUVLoop_pin_uv_get(PointerRNA *ptr)
{
const Mesh *mesh = rna_mesh(ptr);
@@ -2400,52 +2302,6 @@ static void rna_def_mloopuv(BlenderRNA *brna)
nullptr,
nullptr);
prop = RNA_def_property(srna, "vertex_selection", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "UV Vertex Selection", "Selection state of the face corner the UV editor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_vert_select_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_MeshUVLoopLayer_vert_select_length",
"rna_MeshUVLoopLayer_vert_select_lookup_int",
nullptr,
nullptr);
func = RNA_def_function(
srna, "vertex_selection_ensure", "rna_MeshUVLoopLayer_vert_select_ensure");
RNA_def_function_flag(func, FUNC_SELF_AS_RNA);
parm = RNA_def_pointer(func, "layer", "BoolAttribute", "", "The boolean attribute");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
prop = RNA_def_property(srna, "edge_selection", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(
prop, "UV Edge Selection", "Selection state of the edge in the UV editor");
RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE);
RNA_def_property_collection_funcs(prop,
"rna_MeshUVLoopLayer_edge_select_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_MeshUVLoopLayer_edge_select_length",
"rna_MeshUVLoopLayer_edge_select_lookup_int",
nullptr,
nullptr);
func = RNA_def_function(
srna, "edge_selection_ensure", "rna_MeshUVLoopLayer_edge_selection_ensure");
RNA_def_function_flag(func, FUNC_SELF_AS_RNA);
parm = RNA_def_pointer(func, "layer", "BoolAttribute", "", "The boolean attribute");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_RNAPTR);
RNA_def_function_return(func, parm);
prop = RNA_def_property(srna, "pin", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "BoolAttributeValue");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
@@ -2481,17 +2337,6 @@ static void rna_def_mloopuv(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_MeshUVLoop_pin_uv_get", "rna_MeshUVLoop_pin_uv_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "UV Pinned", "");
prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(prop, "rna_MeshUVLoop_select_get", "rna_MeshUVLoop_select_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "UV Select", "");
prop = RNA_def_property(srna, "select_edge", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_funcs(
prop, "rna_MeshUVLoop_select_edge_get", "rna_MeshUVLoop_select_edge_set");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "UV Edge Select", "");
}
static void rna_def_mloopcol(BlenderRNA *brna)

View File

@@ -84,7 +84,7 @@ static Mesh *create_ico_sphere_mesh(const int subdivisions,
/* Make sure the associated boolean layers exists as well. Normally this would be done when
* adding a UV layer via python or when copying from Mesh, but when we 'manually' create the UV
* layer we need to make sure the boolean layers exist as well. */
BM_uv_map_attr_select_and_pin_ensure(bm);
BM_uv_map_attr_pin_ensure_for_all_layers(bm);
BMO_op_callf(bm,
BMO_FLAG_DEFAULTS,

View File

@@ -493,7 +493,7 @@ static PyObject *bpy_bmlayercollection_verify(BPy_BMLayerCollection *self)
/* Because adding CustomData layers to a bmesh will invalidate any existing pointers
* in Py objects we can't lazily add the associated bool layers. So add them all right
* now. */
BM_uv_map_attr_select_and_pin_ensure(self->bm);
BM_uv_map_attr_pin_ensure_for_all_layers(self->bm);
}
BLI_assert(index >= 0);
@@ -544,7 +544,7 @@ static PyObject *bpy_bmlayercollection_new(BPy_BMLayerCollection *self, PyObject
/* Because adding CustomData layers to a bmesh will invalidate any existing pointers
* in Py objects we can't lazily add the associated bool layers. So add them all right
* now. */
BM_uv_map_attr_select_and_pin_ensure(self->bm);
BM_uv_map_attr_pin_ensure_for_all_layers(self->bm);
}
index = CustomData_number_of_layers(data, eCustomDataType(self->type)) - 1;

View File

@@ -52,8 +52,6 @@ struct BPy_BMLoopUV {
* datablocks (adding a layer re-generates all blocks). But eventually the plan is to lazily
* allocate the bool layers 'on demand'. Therefore the code tries to handle all cases where
* the layers don't exist. */
bool *vert_select;
bool *edge_select;
bool *pin;
BMLoop *loop;
};
@@ -124,46 +122,6 @@ static int bpy_bmloopuv_pin_uv_set(BPy_BMLoopUV *self, PyObject *value, void * /
return 0;
}
static PyObject *bpy_bmloopuv_select_get(BPy_BMLoopUV *self, void * /*closure*/)
{
/* A non existing vert_select layer means nothing is currently selected */
return self->vert_select ? PyBool_FromLong(*self->vert_select) : nullptr;
}
static int bpy_bmloopuv_select_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
{
/* TODO: see comment above on bpy_bmloopuv_pin_uv_set(), the same applies here. */
BLI_assert(self->vert_select);
if (self->vert_select) {
*self->vert_select = PyC_Long_AsBool(value);
}
else {
PyErr_SetString(PyExc_RuntimeError,
"active uv layer has no associated vertex selection layer. This is a bug!");
return -1;
}
return 0;
}
static PyObject *bpy_bmloopuv_select_edge_get(BPy_BMLoopUV *self, void * /*closure*/)
{
/* A non existing edge_select layer means nothing is currently selected */
return self->edge_select ? PyBool_FromLong(*self->edge_select) : nullptr;
}
static int bpy_bmloopuv_select_edge_set(BPy_BMLoopUV *self, PyObject *value, void * /*closure*/)
{
/* TODO: see comment above on bpy_bmloopuv_pin_uv_set(), the same applies here. */
BLI_assert(self->edge_select);
if (self->edge_select) {
*self->edge_select = PyC_Long_AsBool(value);
}
else {
PyErr_SetString(PyExc_RuntimeError,
"active uv layer has no associated edge selection layer. This is a bug!");
return -1;
}
return 0;
}
static PyGetSetDef bpy_bmloopuv_getseters[] = {
/* attributes match rna_def_mloopuv. */
{"uv", (getter)bpy_bmloopuv_uv_get, (setter)bpy_bmloopuv_uv_set, bpy_bmloopuv_uv_doc, nullptr},
@@ -172,17 +130,6 @@ static PyGetSetDef bpy_bmloopuv_getseters[] = {
(setter)bpy_bmloopuv_pin_uv_set,
bpy_bmloopuv_pin_uv_doc,
nullptr},
{"select",
(getter)bpy_bmloopuv_select_get,
(setter)bpy_bmloopuv_select_set,
bpy_bmloopuv_select_doc,
nullptr},
{"select_edge",
(getter)bpy_bmloopuv_select_edge_get,
(setter)bpy_bmloopuv_select_edge_set,
bpy_bmloopuv_select_edge_doc,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
};
@@ -215,14 +162,6 @@ int BPy_BMLoopUV_AssignPyObject(BMesh *bm, BMLoop *loop, PyObject *value)
float *luv = BM_ELEM_CD_GET_FLOAT_P(loop, offsets.uv);
copy_v2_v2(luv, src->uv);
if (src->vert_select) {
BM_ELEM_CD_SET_BOOL(loop, offsets.select_vert, *src->vert_select);
}
if (src->edge_select) {
BM_ELEM_CD_SET_BOOL(loop, offsets.select_edge, *src->edge_select);
}
if (src->pin) {
BM_ELEM_CD_SET_BOOL(loop, offsets.pin, *src->pin);
}
@@ -236,10 +175,6 @@ PyObject *BPy_BMLoopUV_CreatePyObject(BMesh *bm, BMLoop *loop, int layer)
const BMUVOffsets offsets = BM_uv_map_offsets_from_layer(bm, layer);
self->uv = BM_ELEM_CD_GET_FLOAT_P(loop, offsets.uv);
self->vert_select = offsets.select_vert >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.select_vert) :
nullptr;
self->edge_select = offsets.select_edge >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.select_edge) :
nullptr;
self->pin = offsets.pin >= 0 ? BM_ELEM_CD_GET_BOOL_P(loop, offsets.pin) : nullptr;
return (PyObject *)self;