BMesh: remove BMEditMesh.ob pointer
Remove this pointer since it's linking Mesh data back to the object, where a single edit-mesh may have multiple object users, causing incorrect assumptions in the code. Resolves dangling pointer part of the T72667 crash, although there are other issues which still need to be fixed. In EDBM_op_finish and EDBM_update_generic, full Main lookups have been added which should be replaced with mesh argument or the update tagging moved elsewhere.
This commit is contained in:
@@ -35,6 +35,7 @@ struct Depsgraph;
|
||||
struct EditMeshData;
|
||||
struct Mesh;
|
||||
struct MeshStatVis;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
/**
|
||||
@@ -70,9 +71,6 @@ typedef struct BMEditMesh {
|
||||
short selectmode;
|
||||
short mat_nr;
|
||||
|
||||
/* Object this editmesh came from (if it came from one) */
|
||||
struct Object *ob;
|
||||
|
||||
/*temp variables for x-mirror editing*/
|
||||
int mirror_cdlayer; /* -1 is invalid */
|
||||
|
||||
|
||||
@@ -1839,7 +1839,7 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph,
|
||||
BMEditMesh *em,
|
||||
CustomData_MeshMasks *dataMask)
|
||||
{
|
||||
BLI_assert(em->ob->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
||||
BLI_assert(obedit->id.tag & LIB_TAG_COPIED_ON_WRITE);
|
||||
|
||||
BKE_object_free_derived_caches(obedit);
|
||||
if (DEG_is_active(depsgraph)) {
|
||||
|
||||
@@ -163,9 +163,6 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
|
||||
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
|
||||
#else
|
||||
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? ((Mesh *)ob->data)->edit_mesh : NULL;
|
||||
if (em && em->ob != ob) {
|
||||
em = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
CustomData_MeshMasks cddata_masks = scene->customdata_mask;
|
||||
|
||||
@@ -610,7 +610,7 @@ void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
|
||||
lt_cow->editlatt = lt_orig->editlatt;
|
||||
}
|
||||
|
||||
void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
|
||||
void update_mesh_edit_mode_pointers(const ID *id_orig, ID *id_cow)
|
||||
{
|
||||
/* For meshes we need to update edit_mesh to make it to point
|
||||
* to the CoW version of object.
|
||||
@@ -624,7 +624,6 @@ void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_ori
|
||||
return;
|
||||
}
|
||||
mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh);
|
||||
mesh_cow->edit_mesh->ob = (Object *)depsgraph->get_cow_id(&mesh_orig->edit_mesh->ob->id);
|
||||
mesh_cow->edit_mesh->mesh_eval_cage = NULL;
|
||||
mesh_cow->edit_mesh->mesh_eval_final = NULL;
|
||||
}
|
||||
@@ -639,7 +638,7 @@ void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID
|
||||
update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
|
||||
break;
|
||||
case ID_ME:
|
||||
update_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow);
|
||||
update_mesh_edit_mode_pointers(id_orig, id_cow);
|
||||
break;
|
||||
case ID_CU:
|
||||
update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
|
||||
|
||||
@@ -605,7 +605,6 @@ static void undomesh_to_editmesh(UndoMesh *um, Object *ob, BMEditMesh *em, Key *
|
||||
|
||||
em->selectmode = um->selectmode;
|
||||
bm->selectmode = um->selectmode;
|
||||
em->ob = ob;
|
||||
|
||||
bm->spacearr_dirty = BM_SPACEARR_DIRTY_ALL;
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_editmesh_bvh.h"
|
||||
#include "BKE_global.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
@@ -166,8 +167,15 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
|
||||
BKE_editmesh_looptri_calc(em);
|
||||
}
|
||||
|
||||
if (em->ob) {
|
||||
DEG_id_tag_update(&((Mesh *)em->ob->data)->id, ID_RECALC_COPY_ON_WRITE);
|
||||
{
|
||||
/* FIXME: pass in mesh. */
|
||||
Main *bmain = G_MAIN;
|
||||
for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
|
||||
if (mesh->edit_mesh == em) {
|
||||
DEG_id_tag_update(&mesh->id, ID_RECALC_COPY_ON_WRITE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -316,7 +324,6 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
|
||||
|
||||
me->edit_mesh->selectmode = me->edit_mesh->bm->selectmode = select_mode;
|
||||
me->edit_mesh->mat_nr = (ob->actcol > 0) ? ob->actcol - 1 : 0;
|
||||
me->edit_mesh->ob = ob;
|
||||
|
||||
/* we need to flush selection because the mode may have changed from when last in editmode */
|
||||
EDBM_selectmode_flush(me->edit_mesh);
|
||||
@@ -1416,10 +1423,16 @@ void EDBM_stats_update(BMEditMesh *em)
|
||||
*/
|
||||
void EDBM_update_generic(BMEditMesh *em, const bool do_tessellation, const bool is_destructive)
|
||||
{
|
||||
Object *ob = em->ob;
|
||||
/* order of calling isn't important */
|
||||
DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
|
||||
/* FIXME: pass in mesh. */
|
||||
Main *bmain = G_MAIN;
|
||||
for (Mesh *mesh = bmain->meshes.first; mesh; mesh = mesh->id.next) {
|
||||
if (mesh->edit_mesh == em) {
|
||||
/* Order of calling isn't important. */
|
||||
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
|
||||
WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_tessellation) {
|
||||
BKE_editmesh_looptri_calc(em);
|
||||
|
||||
Reference in New Issue
Block a user