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:
parent
ee8a2edb96
commit
02a4fc1395
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue