Fix T81511: Loop-cut overlay doesn't follow deformed cage
With constructive + deform modifiers, loop-cut visualization wasn't following the displayed mesh. This now gets the coordinates from the cage when available.
This commit is contained in:
parent
deca7c7954
commit
862b5b1842
Notes:
blender-bot
2023-02-14 15:35:25 +01:00
Referenced by issue #91444, Edge Loop Preview fails with two Mirror Modifiers Referenced by issue #81511, Overlays broken on Curve Modifier (crazyspace with "On Cage" option) Referenced by issue #26050, Loopcut proposal is shown in wrong place when using curve modifier Referenced by issue #25324, loopcuts do not respect armature modifier
|
@ -99,6 +99,13 @@ float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
|
|||
struct Object *ob,
|
||||
int *r_vert_len))[3];
|
||||
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3];
|
||||
const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph,
|
||||
struct BMEditMesh *em,
|
||||
struct Scene *scene,
|
||||
struct Object *obedit,
|
||||
int *r_vert_len,
|
||||
bool *r_is_alloc))[3];
|
||||
|
||||
void BKE_editmesh_lnorspace_update(BMEditMesh *em, struct Mesh *me);
|
||||
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em, struct Mesh *me);
|
||||
struct BoundBox *BKE_editmesh_cage_boundbox_get(BMEditMesh *em);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_iterators.h"
|
||||
// #include "BKE_jesh_runtime.h"
|
||||
#include "BKE_mesh_wrapper.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
|
@ -228,6 +229,34 @@ float (*BKE_editmesh_vert_coords_alloc(struct Depsgraph *depsgraph,
|
|||
return cos_cage;
|
||||
}
|
||||
|
||||
const float (*BKE_editmesh_vert_coords_when_deformed(struct Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
struct Scene *scene,
|
||||
Object *ob,
|
||||
int *r_vert_len,
|
||||
bool *r_is_alloc))[3]
|
||||
{
|
||||
const float(*coords)[3] = NULL;
|
||||
*r_is_alloc = false;
|
||||
|
||||
Mesh *me = ob->data;
|
||||
|
||||
if ((me->runtime.edit_data != NULL) && (me->runtime.edit_data->vertexCos != NULL)) {
|
||||
/* Deformed, and we have deformed coords already. */
|
||||
coords = me->runtime.edit_data->vertexCos;
|
||||
}
|
||||
else if ((em->mesh_eval_final != NULL) &&
|
||||
(em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH)) {
|
||||
/* If this is an edit-mesh type, leave NULL as we can use the vertex coords. . */
|
||||
}
|
||||
else {
|
||||
/* Constructive modifiers have been used, we need to allocate coordinates. */
|
||||
*r_is_alloc = true;
|
||||
coords = BKE_editmesh_vert_coords_alloc(depsgraph, em, scene, ob, r_vert_len);
|
||||
}
|
||||
return coords;
|
||||
}
|
||||
|
||||
float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
|
||||
{
|
||||
return BM_mesh_vert_coords_alloc(em->bm, r_vert_len);
|
||||
|
|
|
@ -64,6 +64,11 @@
|
|||
|
||||
/* ringsel operator */
|
||||
|
||||
struct MeshCoordsCache {
|
||||
bool is_init, is_alloc;
|
||||
const float (*coords)[3];
|
||||
};
|
||||
|
||||
/* struct for properties used while drawing */
|
||||
typedef struct RingSelOpData {
|
||||
ARegion *region; /* region that ringsel was activated in */
|
||||
|
@ -78,6 +83,8 @@ typedef struct RingSelOpData {
|
|||
Base **bases;
|
||||
uint bases_len;
|
||||
|
||||
struct MeshCoordsCache *geom_cache;
|
||||
|
||||
/* These values switch objects based on the object under the cursor. */
|
||||
uint base_index;
|
||||
Object *ob;
|
||||
|
@ -138,15 +145,18 @@ static void edgering_select(RingSelOpData *lcd)
|
|||
static void ringsel_find_edge(RingSelOpData *lcd, const int previewlines)
|
||||
{
|
||||
if (lcd->eed) {
|
||||
const float(*coords)[3] = NULL;
|
||||
{
|
||||
Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(lcd->depsgraph, lcd->ob->data);
|
||||
if (me_eval->runtime.edit_data) {
|
||||
coords = me_eval->runtime.edit_data->vertexCos;
|
||||
}
|
||||
struct MeshCoordsCache *gcache = &lcd->geom_cache[lcd->base_index];
|
||||
if (gcache->is_init == false) {
|
||||
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(lcd->vc.depsgraph, &lcd->vc.scene->id);
|
||||
Object *ob_eval = DEG_get_evaluated_object(lcd->vc.depsgraph, lcd->ob);
|
||||
BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
|
||||
gcache->coords = BKE_editmesh_vert_coords_when_deformed(
|
||||
lcd->vc.depsgraph, em_eval, scene_eval, ob_eval, NULL, &gcache->is_alloc);
|
||||
gcache->is_init = true;
|
||||
}
|
||||
|
||||
EDBM_preselect_edgering_update_from_edge(
|
||||
lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, coords);
|
||||
lcd->presel_edgering, lcd->em->bm, lcd->eed, previewlines, gcache->coords);
|
||||
}
|
||||
else {
|
||||
EDBM_preselect_edgering_clear(lcd->presel_edgering);
|
||||
|
@ -250,6 +260,14 @@ static void ringsel_exit(bContext *UNUSED(C), wmOperator *op)
|
|||
|
||||
EDBM_preselect_edgering_destroy(lcd->presel_edgering);
|
||||
|
||||
for (uint i = 0; i < lcd->bases_len; i++) {
|
||||
struct MeshCoordsCache *gcache = &lcd->geom_cache[i];
|
||||
if (gcache->is_alloc) {
|
||||
MEM_freeN((void *)gcache->coords);
|
||||
}
|
||||
}
|
||||
MEM_freeN(lcd->geom_cache);
|
||||
|
||||
MEM_freeN(lcd->bases);
|
||||
|
||||
ED_region_tag_redraw(lcd->region);
|
||||
|
@ -415,6 +433,7 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
|
||||
lcd->bases = bases;
|
||||
lcd->bases_len = bases_len;
|
||||
lcd->geom_cache = MEM_callocN(sizeof(*lcd->geom_cache) * bases_len, __func__);
|
||||
|
||||
if (is_interactive) {
|
||||
copy_v2_v2_int(lcd->vc.mval, event->mval);
|
||||
|
|
|
@ -364,16 +364,19 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
|
|||
}
|
||||
else {
|
||||
if (best.eed) {
|
||||
const float(*coords)[3] = NULL;
|
||||
{
|
||||
Object *ob = gz_ring->bases[gz_ring->base_index]->object;
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
|
||||
if (me_eval->runtime.edit_data) {
|
||||
coords = me_eval->runtime.edit_data->vertexCos;
|
||||
}
|
||||
}
|
||||
Object *ob = gz_ring->bases[gz_ring->base_index]->object;
|
||||
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc.depsgraph, &vc.scene->id);
|
||||
Object *ob_eval = DEG_get_evaluated_object(vc.depsgraph, ob);
|
||||
BMEditMesh *em_eval = BKE_editmesh_from_object(ob_eval);
|
||||
/* Re-allocate coords each update isn't ideal, however we can't be sure
|
||||
* the mesh hasn't been edited since last update. */
|
||||
bool is_alloc = false;
|
||||
const float(*coords)[3] = BKE_editmesh_vert_coords_when_deformed(
|
||||
vc.depsgraph, em_eval, scene_eval, ob_eval, NULL, &is_alloc);
|
||||
EDBM_preselect_edgering_update_from_edge(gz_ring->psel, bm, best.eed, 1, coords);
|
||||
if (is_alloc) {
|
||||
MEM_freeN((void *)coords);
|
||||
}
|
||||
}
|
||||
else {
|
||||
EDBM_preselect_edgering_clear(gz_ring->psel);
|
||||
|
|
Loading…
Reference in New Issue