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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/mesh')
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editface.cc173
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c2
-rw-r--r--source/blender/editors/mesh/editmesh_mask_extract.c2
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c2
-rw-r--r--source/blender/editors/mesh/editmesh_undo.c4
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c448
-rw-r--r--source/blender/editors/mesh/mesh_data.cc245
-rw-r--r--source/blender/editors/mesh/mesh_intern.h4
-rw-r--r--source/blender/editors/mesh/mesh_ops.c4
-rw-r--r--source/blender/editors/mesh/meshtools.cc23
11 files changed, 396 insertions, 512 deletions
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 28ac913a3e3..218564eaf30 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -17,7 +17,6 @@ set(INC
../../render
../../windowmanager
../../../../intern/clog
- ../../../../intern/glew-mx
../../../../intern/guardedalloc
# RNA_prototypes.h
${CMAKE_BINARY_DIR}/source/blender/makesrna
diff --git a/source/blender/editors/mesh/editface.cc b/source/blender/editors/mesh/editface.cc
index b69cd8b8606..c55d96bac55 100644
--- a/source/blender/editors/mesh/editface.cc
+++ b/source/blender/editors/mesh/editface.cc
@@ -17,6 +17,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
@@ -36,14 +37,18 @@
/* own include */
-void paintface_flush_flags(bContext *C, Object *ob, short flag)
+void paintface_flush_flags(bContext *C,
+ Object *ob,
+ const bool flush_selection,
+ const bool flush_hidden)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
MPoly *polys, *mp_orig;
const int *index_array = nullptr;
int totpoly;
- BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0);
+ BLI_assert(flush_selection || flush_hidden);
if (me == nullptr) {
return;
@@ -53,7 +58,7 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
/* we could call this directly in all areas that change selection,
* since this could become slow for realtime updates (circle-select for eg) */
- if (flag & SELECT) {
+ if (flush_selection) {
BKE_mesh_flush_select_from_polys(me);
}
@@ -64,8 +69,11 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
return;
}
+ bke::AttributeAccessor attributes_me = bke::mesh_attributes(*me);
Mesh *me_orig = (Mesh *)ob_eval->runtime.data_orig;
+ bke::MutableAttributeAccessor attributes_orig = bke::mesh_attributes_for_write(*me_orig);
Mesh *me_eval = (Mesh *)ob_eval->runtime.data_eval;
+ bke::MutableAttributeAccessor attributes_eval = bke::mesh_attributes_for_write(*me_eval);
bool updated = false;
if (me_orig != nullptr && me_eval != nullptr && me_orig->totpoly == me->totpoly) {
@@ -73,13 +81,17 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
for (int i = 0; i < me->totpoly; i++) {
me_orig->mpoly[i].flag = me->mpoly[i].flag;
}
-
- /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */
- if (me_eval->mpoly == me_orig->mpoly) {
- updated = true;
+ if (flush_hidden) {
+ const VArray<bool> hide_poly_me = attributes_me.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+ bke::SpanAttributeWriter<bool> hide_poly_orig =
+ attributes_orig.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
+ hide_poly_me.materialize(hide_poly_orig.span);
+ hide_poly_orig.finish();
}
+
/* Mesh polys => Final derived polys */
- else if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
+ if ((index_array = (const int *)CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
@@ -91,13 +103,24 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
polys[i].flag = mp_orig->flag;
}
}
+ const VArray<bool> hide_poly_orig = attributes_orig.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+ bke::SpanAttributeWriter<bool> hide_poly_eval =
+ attributes_eval.lookup_or_add_for_write_only_span<bool>(".hide_poly", ATTR_DOMAIN_FACE);
+ for (const int i : IndexRange(me_eval->totpoly)) {
+ const int orig_poly_index = index_array[i];
+ if (orig_poly_index != ORIGINDEX_NONE) {
+ hide_poly_eval.span[i] = hide_poly_orig[orig_poly_index];
+ }
+ }
+ hide_poly_eval.finish();
updated = true;
}
}
if (updated) {
- if (flag & ME_HIDE) {
+ if (flush_hidden) {
BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL);
}
else {
@@ -115,59 +138,79 @@ void paintface_flush_flags(bContext *C, Object *ob, short flag)
void paintface_hide(bContext *C, Object *ob, const bool unselected)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totpoly == 0) {
return;
}
+ bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
+ bke::SpanAttributeWriter<bool> hide_poly = attributes.lookup_or_add_for_write_span<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE);
+
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
- if ((mpoly->flag & ME_HIDE) == 0) {
+ if (!hide_poly.span[i]) {
if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
- mpoly->flag |= ME_HIDE;
+ hide_poly.span[i] = true;
}
}
- if (mpoly->flag & ME_HIDE) {
+ if (hide_poly.span[i]) {
mpoly->flag &= ~ME_FACE_SEL;
}
}
+ hide_poly.finish();
+
BKE_mesh_flush_hidden_from_polys(me);
- paintface_flush_flags(C, ob, SELECT | ME_HIDE);
+ paintface_flush_flags(C, ob, true, true);
}
void paintface_reveal(bContext *C, Object *ob, const bool select)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->totpoly == 0) {
return;
}
- for (int i = 0; i < me->totpoly; i++) {
- MPoly *mpoly = &me->mpoly[i];
- if (mpoly->flag & ME_HIDE) {
- SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL);
- mpoly->flag &= ~ME_HIDE;
+ bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
+
+ if (select) {
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+ for (int i = 0; i < me->totpoly; i++) {
+ MPoly *mpoly = &me->mpoly[i];
+ if (hide_poly[i]) {
+ mpoly->flag |= ME_FACE_SEL;
+ }
}
}
+ attributes.remove(".hide_poly");
+
BKE_mesh_flush_hidden_from_polys(me);
- paintface_flush_flags(C, ob, SELECT | ME_HIDE);
+ paintface_flush_flags(C, ob, true, true);
}
/* Set object-mode face selection seams based on edge data, uses hash table to find seam edges. */
static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bool select)
{
+ using namespace blender;
bool do_it = true;
bool mark = false;
BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+
if (index != (uint)-1) {
/* only put face under cursor in array */
MPoly *mp = &me->mpoly[index];
@@ -178,7 +221,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
/* fill array by selection */
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
- if (mp->flag & ME_HIDE) {
+ if (hide_poly[i]) {
/* pass */
}
else if (mp->flag & ME_FACE_SEL) {
@@ -194,7 +237,7 @@ static void select_linked_tfaces_with_seams(Mesh *me, const uint index, const bo
/* expand selection */
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
- if (mp->flag & ME_HIDE) {
+ if (hide_poly[i]) {
continue;
}
@@ -249,22 +292,27 @@ void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const b
select_linked_tfaces_with_seams(me, index, select);
- paintface_flush_flags(C, ob, SELECT);
+ paintface_flush_flags(C, ob, true, false);
}
bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr) {
return false;
}
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
- if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) {
+ if (!hide_poly[i] && mpoly->flag & ME_FACE_SEL) {
action = SEL_DESELECT;
break;
}
@@ -275,7 +323,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
for (int i = 0; i < me->totpoly; i++) {
MPoly *mpoly = &me->mpoly[i];
- if ((mpoly->flag & ME_HIDE) == 0) {
+ if (!hide_poly[i]) {
switch (action) {
case SEL_SELECT:
if ((mpoly->flag & ME_FACE_SEL) == 0) {
@@ -299,7 +347,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
if (changed) {
if (flush_flags) {
- paintface_flush_flags(C, ob, SELECT);
+ paintface_flush_flags(C, ob, true, false);
}
}
return changed;
@@ -307,6 +355,7 @@ bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool fl
bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
{
+ using namespace blender;
bool ok = false;
float vec[3], bmat[3][3];
@@ -318,9 +367,13 @@ bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
copy_m3_m4(bmat, ob->obmat);
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+
for (int i = 0; i < me->totpoly; i++) {
MPoly *mp = &me->mpoly[i];
- if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) {
+ if (hide_poly[i] || !(mp->flag & ME_FACE_SEL)) {
continue;
}
@@ -342,6 +395,7 @@ bool paintface_mouse_select(bContext *C,
const SelectPick_Params *params,
Object *ob)
{
+ using namespace blender;
MPoly *mpoly_sel = nullptr;
uint index;
bool changed = false;
@@ -350,10 +404,14 @@ bool paintface_mouse_select(bContext *C,
/* Get the face under the cursor */
Mesh *me = BKE_mesh_from_object(ob);
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_poly = attributes.lookup_or_default<bool>(
+ ".hide_poly", ATTR_DOMAIN_FACE, false);
+
if (ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) {
if (index < me->totpoly) {
mpoly_sel = me->mpoly + index;
- if ((mpoly_sel->flag & ME_HIDE) == 0) {
+ if (!hide_poly[index]) {
found = true;
}
}
@@ -402,7 +460,7 @@ bool paintface_mouse_select(bContext *C,
/* image window redraw */
- paintface_flush_flags(C, ob, SELECT);
+ paintface_flush_flags(C, ob, true, false);
ED_region_tag_redraw(CTX_wm_region(C)); /* XXX: should redraw all 3D views. */
changed = true;
}
@@ -463,17 +521,22 @@ void paintvert_tag_select_update(bContext *C, Object *ob)
bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr) {
return false;
}
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
+ ".hide_vert", ATTR_DOMAIN_POINT, false);
+
if (action == SEL_TOGGLE) {
action = SEL_SELECT;
for (int i = 0; i < me->totvert; i++) {
MVert *mvert = &me->mvert[i];
- if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) {
+ if (!hide_vert[i] && mvert->flag & SELECT) {
action = SEL_DESELECT;
break;
}
@@ -483,7 +546,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
bool changed = false;
for (int i = 0; i < me->totvert; i++) {
MVert *mvert = &me->mvert[i];
- if ((mvert->flag & ME_HIDE) == 0) {
+ if (!hide_vert[i]) {
switch (action) {
case SEL_SELECT:
if ((mvert->flag & SELECT) == 0) {
@@ -526,6 +589,7 @@ bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
{
+ using namespace blender;
Mesh *me = BKE_mesh_from_object(ob);
if (me == nullptr || me->dvert == nullptr) {
@@ -536,10 +600,14 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
}
+ bke::AttributeAccessor attributes = bke::mesh_attributes(*me);
+ const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
+ ".hide_vert", ATTR_DOMAIN_POINT, false);
+
for (int i = 0; i < me->totvert; i++) {
MVert *mv = &me->mvert[i];
MDeformVert *dv = &me->dvert[i];
- if ((mv->flag & ME_HIDE) == 0) {
+ if (!hide_vert[i]) {
if (dv->dw == nullptr) {
/* if null weight then not grouped */
mv->flag |= SELECT;
@@ -554,25 +622,30 @@ void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
void paintvert_hide(bContext *C, Object *ob, const bool unselected)
{
- Mesh *const me = BKE_mesh_from_object(ob);
-
+ using namespace blender;
+ Mesh *me = BKE_mesh_from_object(ob);
if (me == NULL || me->totvert == 0) {
return;
}
- for (int i = 0; i < me->totvert; i++) {
- MVert *const mvert = &me->mvert[i];
+ bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
+ bke::SpanAttributeWriter<bool> hide_vert = attributes.lookup_or_add_for_write_span<bool>(
+ ".hide_vert", ATTR_DOMAIN_POINT);
+ MutableSpan<MVert> verts(me->mvert, me->totvert);
- if ((mvert->flag & ME_HIDE) == 0) {
- if (((mvert->flag & SELECT) == 0) == unselected) {
- mvert->flag |= ME_HIDE;
+ for (const int i : verts.index_range()) {
+ MVert &vert = verts[i];
+ if (!hide_vert.span[i]) {
+ if (((vert.flag & SELECT) == 0) == unselected) {
+ hide_vert.span[i] = true;
}
}
- if (mvert->flag & ME_HIDE) {
- mvert->flag &= ~SELECT;
+ if (hide_vert.span[i]) {
+ vert.flag &= ~SELECT;
}
}
+ hide_vert.finish();
BKE_mesh_flush_hidden_from_verts(me);
@@ -582,21 +655,27 @@ void paintvert_hide(bContext *C, Object *ob, const bool unselected)
void paintvert_reveal(bContext *C, Object *ob, const bool select)
{
- Mesh *const me = BKE_mesh_from_object(ob);
-
+ using namespace blender;
+ Mesh *me = BKE_mesh_from_object(ob);
if (me == NULL || me->totvert == 0) {
return;
}
- for (int i = 0; i < me->totvert; i++) {
- MVert *const mvert = &me->mvert[i];
+ bke::MutableAttributeAccessor attributes = bke::mesh_attributes_for_write(*me);
+ const VArray<bool> hide_vert = attributes.lookup_or_default<bool>(
+ ".hide_vert", ATTR_DOMAIN_POINT, false);
+ MutableSpan<MVert> verts(me->mvert, me->totvert);
- if (mvert->flag & ME_HIDE) {
- SET_FLAG_FROM_TEST(mvert->flag, select, SELECT);
- mvert->flag &= ~ME_HIDE;
+ for (const int i : verts.index_range()) {
+ MVert &vert = verts[i];
+ if (hide_vert[i]) {
+ SET_FLAG_FROM_TEST(vert.flag, select, SELECT);
}
}
+ /* Remove the hide attribute to reveal all vertices. */
+ attributes.remove(".hide_vert");
+
BKE_mesh_flush_hidden_from_verts(me);
paintvert_flush_flags(ob);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 5680865ae67..d4c5504615a 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -4300,7 +4300,7 @@ static void knifetool_finish_single_pre(KnifeTool_OpData *kcd, Object *ob)
}
/**
- * A post version is needed to to delay recalculating tessellation after making cuts.
+ * A post version is needed to delay recalculating tessellation after making cuts.
* Without this, knife-project can't use the BVH tree to select geometry after a cut, see: T98349.
*/
static void knifetool_finish_single_post(KnifeTool_OpData *UNUSED(kcd), Object *ob)
diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c
index 7634ce6af9e..6a080e78086 100644
--- a/source/blender/editors/mesh/editmesh_mask_extract.c
+++ b/source/blender/editors/mesh/editmesh_mask_extract.c
@@ -486,7 +486,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
Mesh *new_mesh = (Mesh *)BKE_id_copy(bmain, &mesh->id);
if (ob->mode == OB_MODE_SCULPT) {
- ED_sculpt_undo_geometry_begin(ob, "mask slice");
+ ED_sculpt_undo_geometry_begin(ob, op);
}
BMesh *bm;
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index c5add97fb00..7de5ad9f151 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -936,7 +936,7 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op)
Object *obedit = objects[ob_index];
BMEditMesh *em = BKE_editmesh_from_object(obedit);
- if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totvertsel == 0)) {
+ if ((em->bm->totvertsel == 0) && (em->bm->totedgesel == 0) && (em->bm->totfacesel == 0)) {
continue;
}
diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c
index d75c92f963f..af8084e16c4 100644
--- a/source/blender/editors/mesh/editmesh_undo.c
+++ b/source/blender/editors/mesh/editmesh_undo.c
@@ -594,6 +594,10 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key, Undo
/* Uncomment for troubleshooting. */
// BM_mesh_validate(em->bm);
+ /* Copy the ID name characters to the mesh so code that depends on accessing the ID type can work
+ * on it. Necessary to use the attribute API. */
+ strcpy(um->me.id.name, "MEundomesh_from_editmesh");
+
BM_mesh_bm_to_me(
NULL,
em->bm,
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index ac5530c8ea9..a6a6b095c31 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -593,6 +593,32 @@ UvMapVert *BM_uv_vert_map_at_index(UvVertMap *vmap, uint v)
return vmap->vert[v];
}
+struct UvElement **BM_uv_element_map_ensure_head_table(struct UvElementMap *element_map)
+{
+ if (element_map->head_table) {
+ return element_map->head_table;
+ }
+
+ /* For each UvElement, locate the "separate" UvElement that precedes it in the linked list. */
+ element_map->head_table = MEM_mallocN(sizeof(*element_map->head_table) * element_map->total_uvs,
+ "uv_element_map_head_table");
+ UvElement **head_table = element_map->head_table;
+ for (int i = 0; i < element_map->total_uvs; i++) {
+ UvElement *head = element_map->storage + i;
+ if (head->separate) {
+ UvElement *element = head;
+ while (element) {
+ head_table[element - element_map->storage] = head;
+ element = element->next;
+ if (element && element->separate) {
+ break;
+ }
+ }
+ }
+ }
+ return element_map->head_table;
+}
+
#define INVALID_ISLAND ((unsigned int)-1)
static void bm_uv_assign_island(UvElementMap *element_map,
@@ -603,7 +629,7 @@ static void bm_uv_assign_island(UvElementMap *element_map,
int islandbufsize)
{
element->island = nisland;
- map[element - element_map->buf] = islandbufsize;
+ map[element - element_map->storage] = islandbufsize;
/* Copy *element to islandbuf[islandbufsize]. */
islandbuf[islandbufsize].l = element->l;
@@ -618,35 +644,21 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
UvElement *islandbuf,
uint *map,
bool uv_selected,
- int cd_loop_uv_offset)
+ const int cd_loop_uv_offset)
{
- int totuv = element_map->totalUVs;
+ BM_uv_element_map_ensure_head_table(element_map);
- /* For each UvElement, locate the "separate" UvElement that precedes it in the linked list. */
- UvElement **head_table = MEM_mallocN(sizeof(*head_table) * totuv, "uv_island_head_table");
- for (int i = 0; i < totuv; i++) {
- UvElement *head = element_map->buf + i;
- if (head->separate) {
- UvElement *element = head;
- while (element) {
- head_table[element - element_map->buf] = head;
- element = element->next;
- if (element && element->separate) {
- break;
- }
- }
- }
- }
+ int total_uvs = element_map->total_uvs;
/* Depth first search the graph, building islands as we go. */
int nislands = 0;
int islandbufsize = 0;
- int stack_upper_bound = totuv;
+ int stack_upper_bound = total_uvs;
UvElement **stack_uv = MEM_mallocN(sizeof(*stack_uv) * stack_upper_bound,
"uv_island_element_stack");
int stacksize_uv = 0;
- for (int i = 0; i < totuv; i++) {
- UvElement *element = element_map->buf + i;
+ for (int i = 0; i < total_uvs; i++) {
+ UvElement *element = element_map->storage + i;
if (element->island != INVALID_ISLAND) {
/* Unique UV (element and all it's children) are already part of an island. */
continue;
@@ -676,7 +688,7 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
if (!uv_selected || uvedit_edge_select_test(scene, element->l, cd_loop_uv_offset)) {
UvElement *next = BM_uv_element_get(element_map, element->l->next->f, element->l->next);
if (next->island == INVALID_ISLAND) {
- UvElement *tail = head_table[next - element_map->buf];
+ UvElement *tail = element_map->head_table[next - element_map->storage];
stack_uv[stacksize_uv++] = tail;
while (tail) {
bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++);
@@ -692,7 +704,7 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
if (!uv_selected || uvedit_edge_select_test(scene, element->l->prev, cd_loop_uv_offset)) {
UvElement *prev = BM_uv_element_get(element_map, element->l->prev->f, element->l->prev);
if (prev->island == INVALID_ISLAND) {
- UvElement *tail = head_table[prev - element_map->buf];
+ UvElement *tail = element_map->head_table[prev - element_map->storage];
stack_uv[stacksize_uv++] = tail;
while (tail) {
bm_uv_assign_island(element_map, tail, nislands, map, islandbuf, islandbufsize++);
@@ -713,14 +725,132 @@ static int bm_uv_edge_select_build_islands(UvElementMap *element_map,
}
nislands++;
}
- BLI_assert(islandbufsize == totuv);
+ BLI_assert(islandbufsize == total_uvs);
MEM_SAFE_FREE(stack_uv);
- MEM_SAFE_FREE(head_table);
+ MEM_SAFE_FREE(element_map->head_table);
return nislands;
}
+static void bm_uv_build_islands(UvElementMap *element_map,
+ BMesh *bm,
+ const Scene *scene,
+ bool uv_selected)
+{
+ int totuv = element_map->total_uvs;
+ int nislands = 0;
+ int islandbufsize = 0;
+
+ /* map holds the map from current vmap->buf to the new, sorted map */
+ uint *map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
+ BMFace **stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
+ UvElement *islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
+ /* Island number for BMFaces. */
+ int *island_number = MEM_callocN(sizeof(*island_number) * bm->totface, "uv_island_number_face");
+ copy_vn_i(island_number, bm->totface, INVALID_ISLAND);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+
+ const bool use_uv_edge_connectivity = scene->toolsettings->uv_flag & UV_SYNC_SELECTION ?
+ scene->toolsettings->selectmode & SCE_SELECT_EDGE :
+ scene->toolsettings->uv_selectmode & UV_SELECT_EDGE;
+ if (use_uv_edge_connectivity) {
+ nislands = bm_uv_edge_select_build_islands(
+ element_map, scene, islandbuf, map, uv_selected, cd_loop_uv_offset);
+ islandbufsize = totuv;
+ }
+
+ for (int i = 0; i < totuv; i++) {
+ if (element_map->storage[i].island == INVALID_ISLAND) {
+ int stacksize = 0;
+ element_map->storage[i].island = nislands;
+ stack[0] = element_map->storage[i].l->f;
+ island_number[BM_elem_index_get(stack[0])] = nislands;
+ stacksize = 1;
+
+ while (stacksize > 0) {
+ BMFace *efa = stack[--stacksize];
+
+ BMLoop *l;
+ BMIter liter;
+ BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
+ if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
+ continue;
+ }
+
+ UvElement *initelement = element_map->vertex[BM_elem_index_get(l->v)];
+
+ for (UvElement *element = initelement; element; element = element->next) {
+ if (element->separate) {
+ initelement = element;
+ }
+
+ if (element->l->f == efa) {
+ /* found the uv corresponding to our face and vertex.
+ * Now fill it to the buffer */
+ bm_uv_assign_island(element_map, element, nislands, map, islandbuf, islandbufsize++);
+
+ for (element = initelement; element; element = element->next) {
+ if (element->separate && element != initelement) {
+ break;
+ }
+
+ if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
+ stack[stacksize++] = element->l->f;
+ island_number[BM_elem_index_get(element->l->f)] = nislands;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ nislands++;
+ }
+ }
+
+ MEM_SAFE_FREE(island_number);
+
+ /* remap */
+ for (int i = 0; i < bm->totvert; i++) {
+ /* important since we may do selection only. Some of these may be NULL */
+ if (element_map->vertex[i]) {
+ element_map->vertex[i] = &islandbuf[map[element_map->vertex[i] - element_map->storage]];
+ }
+ }
+
+ element_map->island_indices = MEM_callocN(sizeof(*element_map->island_indices) * nislands,
+ __func__);
+ element_map->island_total_uvs = MEM_callocN(sizeof(*element_map->island_total_uvs) * nislands,
+ __func__);
+ element_map->island_total_unique_uvs = MEM_callocN(
+ sizeof(*element_map->island_total_unique_uvs) * nislands, __func__);
+ int j = 0;
+ for (int i = 0; i < totuv; i++) {
+ UvElement *next = element_map->storage[i].next;
+ islandbuf[map[i]].next = next ? &islandbuf[map[next - element_map->storage]] : NULL;
+
+ if (islandbuf[i].island != j) {
+ j++;
+ element_map->island_indices[j] = i;
+ }
+ BLI_assert(islandbuf[i].island == j);
+ element_map->island_total_uvs[j]++;
+ if (islandbuf[i].separate) {
+ element_map->island_total_unique_uvs[j]++;
+ }
+ }
+
+ MEM_SAFE_FREE(element_map->storage);
+ element_map->storage = islandbuf;
+ islandbuf = NULL;
+ element_map->total_islands = nislands;
+ MEM_SAFE_FREE(stack);
+ MEM_SAFE_FREE(map);
+}
+
UvElementMap *BM_uv_element_map_create(BMesh *bm,
const Scene *scene,
const bool uv_selected,
@@ -732,26 +862,18 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
BMVert *ev;
BMFace *efa;
- BMLoop *l;
BMIter iter, liter;
- /* vars from original func */
- UvElementMap *element_map;
- UvElement *buf;
- bool *winding = NULL;
BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE);
-
MLoopUV *luv;
- int totverts, totfaces, i, totuv, j;
-
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ if (cd_loop_uv_offset < 0) {
+ return NULL;
+ }
BM_mesh_elem_index_ensure(bm, BM_VERT | BM_FACE);
- totfaces = bm->totface;
- totverts = bm->totvert;
- totuv = 0;
-
- /* generate UvElement array */
+ /* Count total uvs. */
+ int totuv = 0;
BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
continue;
@@ -765,6 +887,7 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
totuv += efa->len;
}
else {
+ BMLoop *l;
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
totuv++;
@@ -777,17 +900,17 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
return NULL;
}
- element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
- element_map->totalUVs = totuv;
- element_map->vert = (UvElement **)MEM_callocN(sizeof(*element_map->vert) * totverts,
- "UvElementVerts");
- buf = element_map->buf = (UvElement *)MEM_callocN(sizeof(*element_map->buf) * totuv,
- "UvElement");
+ UvElementMap *element_map = (UvElementMap *)MEM_callocN(sizeof(*element_map), "UvElementMap");
+ element_map->total_uvs = totuv;
+ element_map->vertex = (UvElement **)MEM_callocN(sizeof(*element_map->vertex) * bm->totvert,
+ "UvElementVerts");
+ element_map->storage = (UvElement *)MEM_callocN(sizeof(*element_map->storage) * totuv,
+ "UvElement");
- if (use_winding) {
- winding = MEM_callocN(sizeof(*winding) * totfaces, "winding");
- }
+ bool *winding = use_winding ? MEM_callocN(sizeof(*winding) * bm->totface, "winding") : NULL;
+ UvElement *buf = element_map->storage;
+ int j;
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, j) {
if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
@@ -804,18 +927,20 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
tf_uv = (float(*)[2])BLI_buffer_reinit_data(&tf_uv_buf, vec2f, efa->len);
}
+ int i;
+ BMLoop *l;
BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) {
if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
continue;
}
buf->l = l;
- buf->separate = 0;
buf->island = INVALID_ISLAND;
buf->loop_of_poly_index = i;
- buf->next = element_map->vert[BM_elem_index_get(l->v)];
- element_map->vert[BM_elem_index_get(l->v)] = buf;
+ /* Insert to head of linked list associated with BMVert. */
+ buf->next = element_map->vertex[BM_elem_index_get(l->v)];
+ element_map->vertex[BM_elem_index_get(l->v)] = buf;
if (use_winding) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
@@ -829,43 +954,54 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
winding[j] = cross_poly_v2(tf_uv, efa->len) > 0;
}
}
+ BLI_buffer_free(&tf_uv_buf);
- /* sort individual uvs for each vert */
- BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, i) {
- UvElement *newvlist = NULL, *vlist = element_map->vert[i];
- UvElement *iterv, *v, *lastv, *next;
- const float *uv, *uv2;
- bool uv_vert_sel, uv2_vert_sel;
-
+ /* For each BMVert, sort associated linked list into unique uvs. */
+ int ev_index;
+ BM_ITER_MESH_INDEX (ev, &iter, bm, BM_VERTS_OF_MESH, ev_index) {
+ UvElement *newvlist = NULL;
+ UvElement *vlist = element_map->vertex[ev_index];
while (vlist) {
- v = vlist;
+
+ /* Detach head from unsorted list. */
+ UvElement *v = vlist;
vlist = vlist->next;
v->next = newvlist;
newvlist = v;
- l = v->l;
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv = luv->uv;
- uv_vert_sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ luv = BM_ELEM_CD_GET_VOID_P(v->l, cd_loop_uv_offset);
+ const float *uv = luv->uv;
+ bool uv_vert_sel = uvedit_uv_select_test(scene, v->l, cd_loop_uv_offset);
- lastv = NULL;
- iterv = vlist;
+ UvElement *lastv = NULL;
+ UvElement *iterv = vlist;
+ /* Scan through unsorted list, finding UvElements which are connected to `v`. */
while (iterv) {
- next = iterv->next;
+ UvElement *next = iterv->next;
+ luv = BM_ELEM_CD_GET_VOID_P(iterv->l, cd_loop_uv_offset);
- l = iterv->l;
- luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
- uv2 = luv->uv;
- uv2_vert_sel = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
+ bool connected = true; /* Assume connected unless we can prove otherwise. */
+
+ if (connected) {
+ /* Are the two UVs close together? */
+ const float *uv2 = luv->uv;
+ connected = compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT);
+ }
+
+ if (connected) {
+ /* Check if the uv loops share the same selection state (if not, they are not connected
+ * as they have been ripped or other edit commands have separated them). */
+ const bool uv2_vert_sel = uvedit_uv_select_test(scene, iterv->l, cd_loop_uv_offset);
+ connected = (uv_vert_sel == uv2_vert_sel);
+ }
- /* Check if the uv loops share the same selection state (if not, they are not connected as
- * they have been ripped or other edit commands have separated them). */
- const bool connected = (uv_vert_sel == uv2_vert_sel) &&
- compare_v2v2(uv2, uv, STD_UV_CONNECT_LIMIT);
+ if (connected && use_winding) {
+ connected = winding[BM_elem_index_get(iterv->l->f)] ==
+ winding[BM_elem_index_get(v->l->f)];
+ }
- if (connected && (!use_winding || winding[BM_elem_index_get(iterv->l->f)] ==
- winding[BM_elem_index_get(v->l->f)])) {
+ if (connected) {
if (lastv) {
lastv->next = next;
}
@@ -882,130 +1018,30 @@ UvElementMap *BM_uv_element_map_create(BMesh *bm,
iterv = next;
}
- newvlist->separate = 1;
+ element_map->total_unique_uvs++;
+ newvlist->separate = true;
}
- element_map->vert[i] = newvlist;
+ /* Write back sorted list. */
+ element_map->vertex[ev_index] = newvlist;
}
- if (use_winding) {
- MEM_freeN(winding);
- }
+ MEM_SAFE_FREE(winding);
+ /* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
+ * Now we should sort uv's in islands. */
if (do_islands) {
- uint *map;
- BMFace **stack;
- int stacksize = 0;
- UvElement *islandbuf;
- /* island number for faces */
- int *island_number = NULL;
-
- int nislands = 0, islandbufsize = 0;
-
- /* map holds the map from current vmap->buf to the new, sorted map */
- map = MEM_mallocN(sizeof(*map) * totuv, "uvelement_remap");
- stack = MEM_mallocN(sizeof(*stack) * bm->totface, "uv_island_face_stack");
- islandbuf = MEM_callocN(sizeof(*islandbuf) * totuv, "uvelement_island_buffer");
- island_number = MEM_mallocN(sizeof(*island_number) * totfaces, "uv_island_number_face");
- copy_vn_i(island_number, totfaces, INVALID_ISLAND);
-
- const bool use_uv_edge_connectivity = scene->toolsettings->uv_flag & UV_SYNC_SELECTION ?
- scene->toolsettings->selectmode & SCE_SELECT_EDGE :
- scene->toolsettings->uv_selectmode & UV_SELECT_EDGE;
- if (use_uv_edge_connectivity) {
- nislands = bm_uv_edge_select_build_islands(
- element_map, scene, islandbuf, map, uv_selected, cd_loop_uv_offset);
- islandbufsize = totuv;
- }
-
- /* at this point, every UvElement in vert points to a UvElement sharing the same vertex.
- * Now we should sort uv's in islands. */
- for (i = 0; i < totuv; i++) {
- if (element_map->buf[i].island == INVALID_ISLAND) {
- element_map->buf[i].island = nislands;
- stack[0] = element_map->buf[i].l->f;
- island_number[BM_elem_index_get(stack[0])] = nislands;
- stacksize = 1;
-
- while (stacksize > 0) {
- efa = stack[--stacksize];
-
- BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
- if (uv_selected && !uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
- continue;
- }
-
- UvElement *element, *initelement = element_map->vert[BM_elem_index_get(l->v)];
-
- for (element = initelement; element; element = element->next) {
- if (element->separate) {
- initelement = element;
- }
-
- if (element->l->f == efa) {
- /* found the uv corresponding to our face and vertex.
- * Now fill it to the buffer */
- bm_uv_assign_island(
- element_map, element, nislands, map, islandbuf, islandbufsize++);
-
- for (element = initelement; element; element = element->next) {
- if (element->separate && element != initelement) {
- break;
- }
-
- if (island_number[BM_elem_index_get(element->l->f)] == INVALID_ISLAND) {
- stack[stacksize++] = element->l->f;
- island_number[BM_elem_index_get(element->l->f)] = nislands;
- }
- }
- break;
- }
- }
- }
- }
-
- nislands++;
- }
- }
-
- MEM_freeN(island_number);
-
- /* remap */
- for (i = 0; i < bm->totvert; i++) {
- /* important since we may do selection only. Some of these may be NULL */
- if (element_map->vert[i]) {
- element_map->vert[i] = &islandbuf[map[element_map->vert[i] - element_map->buf]];
- }
- }
-
- element_map->islandIndices = MEM_callocN(sizeof(*element_map->islandIndices) * nislands,
- "UvElementMap_island_indices");
- j = 0;
- for (i = 0; i < totuv; i++) {
- UvElement *element = element_map->buf[i].next;
- if (element == NULL) {
- islandbuf[map[i]].next = NULL;
- }
- else {
- islandbuf[map[i]].next = &islandbuf[map[element - element_map->buf]];
- }
+ bm_uv_build_islands(element_map, bm, scene, uv_selected);
+ }
- if (islandbuf[i].island != j) {
- j++;
- element_map->islandIndices[j] = i;
- }
+ /* TODO: Confirm element_map->total_unique_uvs doesn't require recalculating. */
+ element_map->total_unique_uvs = 0;
+ for (int i = 0; i < element_map->total_uvs; i++) {
+ if (element_map->storage[i].separate) {
+ element_map->total_unique_uvs++;
}
-
- MEM_freeN(element_map->buf);
-
- element_map->buf = islandbuf;
- element_map->totalIslands = nislands;
- MEM_freeN(stack);
- MEM_freeN(map);
}
- BLI_buffer_free(&tf_uv_buf);
-
return element_map;
}
@@ -1025,30 +1061,38 @@ void BM_uv_vert_map_free(UvVertMap *vmap)
void BM_uv_element_map_free(UvElementMap *element_map)
{
if (element_map) {
- if (element_map->vert) {
- MEM_freeN(element_map->vert);
- }
- if (element_map->buf) {
- MEM_freeN(element_map->buf);
- }
- if (element_map->islandIndices) {
- MEM_freeN(element_map->islandIndices);
- }
- MEM_freeN(element_map);
+ MEM_SAFE_FREE(element_map->storage);
+ MEM_SAFE_FREE(element_map->vertex);
+ MEM_SAFE_FREE(element_map->head_table);
+ MEM_SAFE_FREE(element_map->island_indices);
+ MEM_SAFE_FREE(element_map->island_total_uvs);
+ MEM_SAFE_FREE(element_map->island_total_unique_uvs);
+ MEM_SAFE_FREE(element_map);
}
}
-UvElement *BM_uv_element_get(UvElementMap *map, BMFace *efa, BMLoop *l)
+UvElement *BM_uv_element_get(const UvElementMap *element_map, const BMFace *efa, const BMLoop *l)
{
- for (UvElement *element = map->vert[BM_elem_index_get(l->v)]; element; element = element->next) {
+ UvElement *element = element_map->vertex[BM_elem_index_get(l->v)];
+ while (element) {
if (element->l->f == efa) {
return element;
}
+ element = element->next;
}
return NULL;
}
+UvElement *BM_uv_element_get_head(UvElementMap *element_map, UvElement *child)
+{
+ if (!child) {
+ return NULL;
+ }
+
+ return element_map->vertex[BM_elem_index_get(child->l->v)];
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -1518,7 +1562,7 @@ void EDBM_update(Mesh *mesh, const struct EDBMUpdate_Params *params)
}
if (params->is_destructive) {
- /* TODO(campbell): we may be able to remove this now! */
+ /* TODO(@campbellbarton): we may be able to remove this now! */
// BM_mesh_elem_table_free(em->bm, BM_ALL_NOLOOP);
}
else {
diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc
index 67834bf05ce..ea29d07feaf 100644
--- a/source/blender/editors/mesh/mesh_data.cc
+++ b/source/blender/editors/mesh/mesh_data.cc
@@ -208,7 +208,7 @@ void ED_mesh_uv_loop_reset_ex(Mesh *me, const int layernum)
BMFace *efa;
BMIter iter;
- BLI_assert(cd_loop_uv_offset != -1);
+ BLI_assert(cd_loop_uv_offset >= 0);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
@@ -444,44 +444,6 @@ bool ED_mesh_color_ensure(Mesh *me, const char *name)
return (layer != nullptr);
}
-bool ED_mesh_color_remove_index(Mesh *me, const int n)
-{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- CustomDataLayer *cdl;
- int index;
-
- index = CustomData_get_layer_index_n(ldata, CD_PROP_BYTE_COLOR, n);
- cdl = (index == -1) ? nullptr : &ldata->layers[index];
-
- if (!cdl) {
- return false;
- }
-
- delete_customdata_layer(me, cdl);
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
-
- return true;
-}
-bool ED_mesh_color_remove_active(Mesh *me)
-{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR);
- if (n != -1) {
- return ED_mesh_color_remove_index(me, n);
- }
- return false;
-}
-bool ED_mesh_color_remove_named(Mesh *me, const char *name)
-{
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int n = CustomData_get_named_layer(ldata, CD_PROP_BYTE_COLOR, name);
- if (n != -1) {
- return ED_mesh_color_remove_index(me, n);
- }
- return false;
-}
-
/*********************** General poll ************************/
static bool layers_poll(bContext *C)
@@ -494,25 +456,7 @@ static bool layers_poll(bContext *C)
/*********************** Sculpt Vertex colors operators ************************/
-static bool sculpt_vertex_color_remove_poll(bContext *C)
-{
- if (!layers_poll(C)) {
- return false;
- }
-
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
- CustomData *vdata = GET_CD_DATA(me, vdata);
- const int active = CustomData_get_active_layer(vdata, CD_PROP_COLOR);
- if (active != -1) {
- return true;
- }
-
- return false;
-}
-
-int ED_mesh_sculpt_color_add(
- Mesh *me, const char *name, const bool active_set, const bool do_init, ReportList *reports)
+int ED_mesh_sculpt_color_add(Mesh *me, const char *name, const bool do_init, ReportList *reports)
{
/* NOTE: keep in sync with #ED_mesh_uv_add. */
@@ -536,7 +480,7 @@ int ED_mesh_sculpt_color_add(
const int layernum_dst = CustomData_get_active_layer(&em->bm->vdata, CD_PROP_COLOR);
BM_data_layer_copy(em->bm, &em->bm->vdata, CD_PROP_COLOR, layernum_dst, layernum);
}
- if (active_set || layernum == 0) {
+ if (layernum == 0) {
CustomData_set_layer_active(&em->bm->vdata, CD_PROP_COLOR, layernum);
}
}
@@ -559,7 +503,7 @@ int ED_mesh_sculpt_color_add(
&me->vdata, CD_PROP_COLOR, CD_DEFAULT, nullptr, me->totvert, name);
}
- if (active_set || layernum == 0) {
+ if (layernum == 0) {
CustomData_set_layer_active(&me->vdata, CD_PROP_COLOR, layernum);
}
@@ -572,58 +516,6 @@ int ED_mesh_sculpt_color_add(
return layernum;
}
-bool ED_mesh_sculpt_color_ensure(Mesh *me, const char *name)
-{
- BLI_assert(me->edit_mesh == nullptr);
-
- if (me->totvert && !CustomData_has_layer(&me->vdata, CD_PROP_COLOR)) {
- CustomData_add_layer_named(&me->vdata, CD_PROP_COLOR, CD_DEFAULT, nullptr, me->totvert, name);
- BKE_mesh_update_customdata_pointers(me, true);
- }
-
- DEG_id_tag_update(&me->id, 0);
-
- return (me->mloopcol != nullptr);
-}
-
-bool ED_mesh_sculpt_color_remove_index(Mesh *me, const int n)
-{
- CustomData *vdata = GET_CD_DATA(me, vdata);
- CustomDataLayer *cdl;
- int index;
-
- index = CustomData_get_layer_index_n(vdata, CD_PROP_COLOR, n);
- cdl = (index == -1) ? nullptr : &vdata->layers[index];
-
- if (!cdl) {
- return false;
- }
-
- delete_customdata_layer(me, cdl);
- DEG_id_tag_update(&me->id, 0);
- WM_main_add_notifier(NC_GEOM | ND_DATA, me);
-
- return true;
-}
-bool ED_mesh_sculpt_color_remove_active(Mesh *me)
-{
- CustomData *vdata = GET_CD_DATA(me, vdata);
- const int n = CustomData_get_active_layer(vdata, CD_PROP_COLOR);
- if (n != -1) {
- return ED_mesh_sculpt_color_remove_index(me, n);
- }
- return false;
-}
-bool ED_mesh_sculpt_color_remove_named(Mesh *me, const char *name)
-{
- CustomData *vdata = GET_CD_DATA(me, vdata);
- const int n = CustomData_get_named_layer(vdata, CD_PROP_COLOR, name);
- if (n != -1) {
- return ED_mesh_sculpt_color_remove_index(me, n);
- }
- return false;
-}
-
/*********************** UV texture operators ************************/
static bool uv_texture_remove_poll(bContext *C)
@@ -709,135 +601,6 @@ void MESH_OT_uv_texture_remove(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/*********************** vertex color operators ************************/
-
-static bool vertex_color_remove_poll(bContext *C)
-{
- if (!layers_poll(C)) {
- return false;
- }
-
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
- CustomData *ldata = GET_CD_DATA(me, ldata);
- const int active = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR);
- if (active != -1) {
- return true;
- }
-
- return false;
-}
-
-static int mesh_vertex_color_add_exec(bContext *C, wmOperator *op)
-{
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
-
- if (ED_mesh_color_add(me, nullptr, true, true, op->reports) == -1) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertex_color_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Vertex Color";
- ot->description = "Add vertex color layer";
- ot->idname = "MESH_OT_vertex_color_add";
-
- /* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_vertex_color_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int mesh_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
-
- if (!ED_mesh_color_remove_active(me)) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_vertex_color_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Vertex Color";
- ot->description = "Remove vertex color layer";
- ot->idname = "MESH_OT_vertex_color_remove";
-
- /* api callbacks */
- ot->exec = mesh_vertex_color_remove_exec;
- ot->poll = vertex_color_remove_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-/*********************** Sculpt Vertex Color Operators ************************/
-
-static int mesh_sculpt_vertex_color_add_exec(bContext *C, wmOperator *op)
-{
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
-
- if (ED_mesh_sculpt_color_add(me, nullptr, true, true, op->reports) == -1) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_sculpt_vertex_color_add(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Add Sculpt Vertex Color";
- ot->description = "Add vertex color layer";
- ot->idname = "MESH_OT_sculpt_vertex_color_add";
-
- /* api callbacks */
- ot->poll = layers_poll;
- ot->exec = mesh_sculpt_vertex_color_add_exec;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
-static int mesh_sculpt_vertex_color_remove_exec(bContext *C, wmOperator *UNUSED(op))
-{
- Object *ob = ED_object_context(C);
- Mesh *me = static_cast<Mesh *>(ob->data);
-
- if (!ED_mesh_sculpt_color_remove_active(me)) {
- return OPERATOR_CANCELLED;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void MESH_OT_sculpt_vertex_color_remove(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Remove Sculpt Vertex Color";
- ot->description = "Remove vertex color layer";
- ot->idname = "MESH_OT_sculpt_vertex_color_remove";
-
- /* api callbacks */
- ot->exec = mesh_sculpt_vertex_color_remove_exec;
- ot->poll = sculpt_vertex_color_remove_poll;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* *** CustomData clear functions, we need an operator for each *** */
static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int type)
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 303234df48c..7c8dbffeb31 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -308,10 +308,6 @@ void MESH_OT_mark_freestyle_face(struct wmOperatorType *ot);
void MESH_OT_uv_texture_add(struct wmOperatorType *ot);
void MESH_OT_uv_texture_remove(struct wmOperatorType *ot);
-void MESH_OT_vertex_color_add(struct wmOperatorType *ot);
-void MESH_OT_vertex_color_remove(struct wmOperatorType *ot);
-void MESH_OT_sculpt_vertex_color_add(struct wmOperatorType *ot);
-void MESH_OT_sculpt_vertex_color_remove(struct wmOperatorType *ot);
void MESH_OT_customdata_mask_clear(struct wmOperatorType *ot);
void MESH_OT_customdata_skin_add(struct wmOperatorType *ot);
void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index be7f60b0da0..b9e78740e3c 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -134,10 +134,6 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_uv_texture_add);
WM_operatortype_append(MESH_OT_uv_texture_remove);
- WM_operatortype_append(MESH_OT_vertex_color_add);
- WM_operatortype_append(MESH_OT_vertex_color_remove);
- WM_operatortype_append(MESH_OT_sculpt_vertex_color_add);
- WM_operatortype_append(MESH_OT_sculpt_vertex_color_remove);
WM_operatortype_append(MESH_OT_customdata_mask_clear);
WM_operatortype_append(MESH_OT_customdata_skin_add);
WM_operatortype_append(MESH_OT_customdata_skin_clear);
diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc
index 9e28e1bafdd..b1004b23a21 100644
--- a/source/blender/editors/mesh/meshtools.cc
+++ b/source/blender/editors/mesh/meshtools.cc
@@ -1329,6 +1329,7 @@ bool ED_mesh_pick_face_vert(
*/
struct VertPickData {
const MVert *mvert;
+ const bool *hide_vert;
const float *mval_f; /* [2] */
ARegion *region;
@@ -1343,16 +1344,16 @@ static void ed_mesh_pick_vert__mapFunc(void *userData,
const float UNUSED(no[3]))
{
VertPickData *data = static_cast<VertPickData *>(userData);
- if ((data->mvert[index].flag & ME_HIDE) == 0) {
- float sco[2];
-
- if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
- V3D_PROJ_RET_OK) {
- const float len = len_manhattan_v2v2(data->mval_f, sco);
- if (len < data->len_best) {
- data->len_best = len;
- data->v_idx_best = index;
- }
+ if (data->hide_vert && data->hide_vert[index]) {
+ return;
+ }
+ float sco[2];
+ if (ED_view3d_project_float_object(data->region, co, sco, V3D_PROJ_TEST_CLIP_DEFAULT) ==
+ V3D_PROJ_RET_OK) {
+ const float len = len_manhattan_v2v2(data->mval_f, sco);
+ if (len < data->len_best) {
+ data->len_best = len;
+ data->v_idx_best = index;
}
}
}
@@ -1416,6 +1417,8 @@ bool ED_mesh_pick_vert(
data.mval_f = mval_f;
data.len_best = FLT_MAX;
data.v_idx_best = -1;
+ data.hide_vert = (const bool *)CustomData_get_layer_named(
+ &me_eval->vdata, CD_PROP_BOOL, ".hide_vert");
BKE_mesh_foreach_mapped_vert(me_eval, ed_mesh_pick_vert__mapFunc, &data, MESH_FOREACH_NOP);