Texture Paint: implement efficient face selection updates.

Fix the old code that propagates selection changes to the
evaluated mesh directly without rebuilding, and avoid tagging
DEG_TAG_COPY_ON_WRITE if it succeeds.
This commit is contained in:
Alexander Gavrilov 2018-12-01 15:40:48 +03:00
parent ee8a2edb96
commit 02a4fc1395
5 changed files with 61 additions and 47 deletions

View File

@ -2328,6 +2328,10 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
GPU_BATCH_DISCARD_SAFE(cache->facedot_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->edges_with_select_id);
GPU_BATCH_DISCARD_SAFE(cache->verts_with_select_id);
/* Paint mode selection */
GPU_BATCH_DISCARD_SAFE(cache->overlay_paint_edges);
GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_faces);
GPU_BATCH_DISCARD_SAFE(cache->overlay_weight_verts);
/* Because visible UVs depends on edit mode selection, discard everything. */
mesh_batch_cache_discard_uvedit(cache);
break;

View File

@ -242,16 +242,15 @@ void EDBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEd
/* editface.c */
void paintface_flush_flags(struct Object *ob, short flag);
void paintface_tag_select_update(struct bContext *C, struct Object *ob);
void paintface_flush_flags(struct bContext *C, struct Object *ob, short flag);
bool paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], bool extend, bool deselect, bool toggle);
int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int sel_op);
void paintface_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
void paintface_deselect_all_visible(struct bContext *C, struct Object *ob, int action, bool flush_flags);
void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], const bool select);
bool paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]);
void paintface_hide(struct Object *ob, const bool unselected);
void paintface_reveal(struct Object *ob, const bool select);
void paintface_hide(struct bContext *C, struct Object *ob, const bool unselected);
void paintface_reveal(struct bContext *C, struct Object *ob, const bool select);
void paintvert_deselect_all_visible(struct Object *ob, int action, bool flush_flags);
void paintvert_select_ungrouped(struct Object *ob, bool extend, bool flush_flags);

View File

@ -55,15 +55,15 @@
#include "GPU_draw.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
/* own include */
/* copy the face flags, most importantly selection from the mesh to the final derived mesh,
* use in object mode when selecting faces (while painting) */
void paintface_flush_flags(Object *ob, short flag)
void paintface_flush_flags(struct bContext *C, Object *ob, short flag)
{
Mesh *me = BKE_mesh_from_object(ob);
Mesh *me_eval = ob->runtime.mesh_eval;
MPoly *polys, *mp_orig;
const int *index_array = NULL;
int totpoly;
@ -82,36 +82,55 @@ void paintface_flush_flags(Object *ob, short flag)
BKE_mesh_flush_select_from_polys(me);
}
if (me_eval == NULL)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
if (ob_eval == NULL) {
return;
}
/* Mesh polys => Final derived polys */
Mesh *me_eval = ob_eval->runtime.mesh_eval;
bool updated = false;
if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
if (me_eval != NULL) {
/* Mesh polys => Final derived polys */
/* loop over final derived polys */
for (i = 0; i < totpoly; i++) {
if (index_array[i] != ORIGINDEX_NONE) {
/* Copy flags onto the final derived poly from the original mesh poly */
mp_orig = me->mpoly + index_array[i];
polys[i].flag = mp_orig->flag;
if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) {
polys = me_eval->mpoly;
totpoly = me_eval->totpoly;
/* loop over final derived polys */
for (i = 0; i < totpoly; i++) {
if (index_array[i] != ORIGINDEX_NONE) {
/* Copy flags onto the final derived poly from the original mesh poly */
mp_orig = me->mpoly + index_array[i];
polys[i].flag = mp_orig->flag;
}
}
updated = true;
}
}
BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL);
}
if (updated) {
if (flag & ME_HIDE) {
BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL);
}
else {
BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_SELECT);
}
DEG_id_tag_update(ob->data, DEG_TAG_SELECT_UPDATE);
}
else {
DEG_id_tag_update(ob->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
}
void paintface_tag_select_update(struct bContext *C, struct Object *ob)
{
DEG_id_tag_update(ob->data, DEG_TAG_COPY_ON_WRITE | DEG_TAG_SELECT_UPDATE);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
}
void paintface_hide(Object *ob, const bool unselected)
void paintface_hide(bContext *C, Object *ob, const bool unselected)
{
Mesh *me;
MPoly *mpoly;
@ -138,11 +157,11 @@ void paintface_hide(Object *ob, const bool unselected)
BKE_mesh_flush_hidden_from_polys(me);
paintface_flush_flags(ob, SELECT | ME_HIDE);
paintface_flush_flags(C, ob, SELECT | ME_HIDE);
}
void paintface_reveal(Object *ob, const bool select)
void paintface_reveal(bContext *C, Object *ob, const bool select)
{
Mesh *me;
MPoly *mpoly;
@ -163,7 +182,7 @@ void paintface_reveal(Object *ob, const bool select)
BKE_mesh_flush_hidden_from_polys(me);
paintface_flush_flags(ob, SELECT | ME_HIDE);
paintface_flush_flags(C, ob, SELECT | ME_HIDE);
}
/* Set tface seams based on edge data, uses hash table to find seam edges. */
@ -257,11 +276,10 @@ 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(ob, SELECT);
paintface_tag_select_update(C, ob);
paintface_flush_flags(C, ob, SELECT);
}
void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
void paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags)
{
Mesh *me;
MPoly *mpoly;
@ -304,7 +322,7 @@ void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
}
if (flush_flags) {
paintface_flush_flags(ob, SELECT);
paintface_flush_flags(C, ob, SELECT);
}
}
@ -392,8 +410,7 @@ bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], b
/* image window redraw */
paintface_flush_flags(ob, SELECT);
paintface_tag_select_update(C, ob);
paintface_flush_flags(C, ob, SELECT);
ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
return true;
}
@ -420,7 +437,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int sel_op)
selar = MEM_callocN(me->totpoly + 1, "selar");
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
paintface_deselect_all_visible(vc->obact, SEL_DESELECT, false);
paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
}
ED_view3d_backbuf_validate(vc);
@ -463,8 +480,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int sel_op)
glReadBuffer(GL_BACK);
#endif
paintface_flush_flags(vc->obact, SELECT);
paintface_tag_select_update(vc->C, vc->obact);
paintface_flush_flags(vc->C, vc->obact, SELECT);
return OPERATOR_FINISHED;
}

View File

@ -655,8 +655,7 @@ void PAINT_OT_face_select_linked_pick(wmOperatorType *ot)
static int face_select_all_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
paintface_deselect_all_visible(ob, RNA_enum_get(op->ptr, "action"), true);
paintface_tag_select_update(C, ob);
paintface_deselect_all_visible(C, ob, RNA_enum_get(op->ptr, "action"), true);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
@ -739,8 +738,7 @@ static int face_select_hide_exec(bContext *C, wmOperator *op)
{
const bool unselected = RNA_boolean_get(op->ptr, "unselected");
Object *ob = CTX_data_active_object(C);
paintface_hide(ob, unselected);
paintface_tag_select_update(C, ob);
paintface_hide(C, ob, unselected);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}
@ -763,8 +761,7 @@ static int face_select_reveal_exec(bContext *C, wmOperator *op)
{
const bool select = RNA_boolean_get(op->ptr, "select");
Object *ob = CTX_data_active_object(C);
paintface_reveal(ob, select);
paintface_tag_select_update(C, ob);
paintface_reveal(C, ob, select);
ED_region_tag_redraw(CTX_wm_region(C));
return OPERATOR_FINISHED;
}

View File

@ -925,7 +925,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
return;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
paintface_deselect_all_visible(ob, SEL_DESELECT, false); /* flush selection at the end */
paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); /* flush selection at the end */
}
bm_vertoffs = me->totpoly + 1; /* max index array */
@ -937,8 +937,7 @@ static void do_lasso_select_paintface(ViewContext *vc, const int mcords[][2], sh
EDBM_backbuf_free();
paintface_flush_flags(ob, SELECT);
paintface_tag_select_update(vc->C, ob);
paintface_flush_flags(vc->C, ob, SELECT);
}
#if 0
@ -2905,8 +2904,7 @@ static void paint_facesel_circle_select(ViewContext *vc, const bool select, cons
if (bbsel) {
edbm_backbuf_check_and_select_tfaces(me, select ? SEL_OP_ADD : SEL_OP_SUB);
EDBM_backbuf_free();
paintface_flush_flags(ob, SELECT);
paintface_tag_select_update(vc->C, ob);
paintface_flush_flags(vc->C, ob, SELECT);
}
}