WIP: Fix #113377: Pass edit mesh pointer through modifiers #120999

Draft
Hans Goudey wants to merge 13 commits from HooglyBoogly/blender:fix-mesh-edit-mapped-extract-edit-mesh into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
8 changed files with 47 additions and 30 deletions

View File

@ -94,8 +94,6 @@ void BKE_mesh_clear_geometry_and_metadata(Mesh *mesh);
Mesh *BKE_mesh_add(Main *bmain, const char *name);
void BKE_mesh_free_editmesh(Mesh *mesh);
/**
* A version of #BKE_mesh_copy_parameters that is intended for evaluated output
* (the modifier stack for example).

View File

@ -165,6 +165,10 @@ static void mesh_copy_data(Main *bmain,
if (mesh_src->id.tag & LIB_TAG_NO_MAIN) {
/* For copies in depsgraph, keep data like #CD_ORIGINDEX and #CD_ORCO. */
CustomData_MeshMasks_update(&mask, &CD_MASK_DERIVEDMESH);
mesh_dst->runtime->edit_mesh = mesh_src->runtime->edit_mesh;
if (const blender::bke::EditMeshData *edit_data = mesh_src->runtime->edit_data.get()) {
mesh_dst->runtime->edit_data = std::make_unique<blender::bke::EditMeshData>(*edit_data);
}
}
mesh_dst->mat = (Material **)MEM_dupallocN(mesh_src->mat);
@ -204,17 +208,10 @@ static void mesh_copy_data(Main *bmain,
}
}
void BKE_mesh_free_editmesh(Mesh *mesh)
{
mesh->runtime->edit_mesh.reset();
}
static void mesh_free_data(ID *id)
{
Mesh *mesh = reinterpret_cast<Mesh *>(id);
BKE_mesh_free_editmesh(mesh);
BKE_mesh_clear_geometry_and_metadata(mesh);
MEM_SAFE_FREE(mesh->mat);
@ -779,6 +776,8 @@ void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)
}
me_dst->mat = (Material **)MEM_dupallocN(me_src->mat);
me_dst->totcol = me_src->totcol;
me_dst->runtime->edit_mesh = me_src->runtime->edit_mesh;
}
Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,

View File

@ -856,12 +856,7 @@ static void editbmesh_calc_modifiers(Depsgraph &depsgraph,
* cage mesh isn't modified anymore. */
mesh = BKE_mesh_copy_for_eval(*mesh);
if (mesh_cage->runtime->edit_mesh) {
mesh->runtime->edit_mesh = mesh_cage->runtime->edit_mesh;
mesh->runtime->is_original_bmesh = true;
if (mesh_cage->runtime->edit_data) {
mesh->runtime->edit_data = std::make_unique<EditMeshData>(
*mesh_cage->runtime->edit_data);
}
}
}
@ -1052,12 +1047,6 @@ static void editbmesh_build_data(Depsgraph &depsgraph,
editbmesh_calc_modifiers(
depsgraph, scene, obedit, dataMask, &me_cage, &me_final, &non_mesh_components);
/* The modifier stack result is expected to share edit mesh pointer with the input.
* This is similar `mesh_calc_finalize()`. */
BKE_mesh_free_editmesh(me_final);
BKE_mesh_free_editmesh(me_cage);
me_final->runtime->edit_mesh = me_cage->runtime->edit_mesh = mesh->runtime->edit_mesh;
/* Object has edit_mesh but is not in edit mode (object shares mesh datablock with another object
* with is in edit mode).
* Convert edit mesh to mesh until the draw manager can draw mesh wrapper which is not in the

View File

@ -198,7 +198,7 @@ void select_id_draw_object(void *vedata,
switch (ob->type) {
case OB_MESH:
if (ob->mode & OB_MODE_EDIT) {
if (DRW_object_is_in_edit_mode(ob)) {
bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
draw_select_id_edit_mesh(stl,
ob,

View File

@ -26,6 +26,8 @@
#include "BKE_object.hh"
#include "BKE_paint.hh"
#include "DEG_depsgraph_query.hh"
#include "GPU_batch.hh"
#include "GPU_batch_utils.hh"
#include "GPU_capabilities.hh"
@ -3401,8 +3403,13 @@ void drw_batch_cache_generate_requested(Object *ob)
switch (ob->type) {
case OB_MESH:
DRW_mesh_batch_cache_create_requested(
DST.task_graph, ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
DRW_mesh_batch_cache_create_requested(DST.task_graph,
ob,
(Mesh *)ob->data,
DEG_get_original_object(ob),
scene,
is_paint_mode,
use_hide);
break;
case OB_CURVES_LEGACY:
case OB_FONT:
@ -3445,7 +3452,7 @@ void drw_batch_cache_generate_requested_evaluated_mesh_or_curve(Object *ob)
*/
if (mesh != nullptr) {
DRW_mesh_batch_cache_create_requested(
DST.task_graph, ob, mesh, scene, is_paint_mode, use_hide);
DST.task_graph, ob, mesh, nullptr, scene, is_paint_mode, use_hide);
}
else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_FONT, OB_SURF)) {
DRW_curve_batch_cache_create_requested(ob, scene);

View File

@ -186,6 +186,7 @@ blender::gpu::Batch *DRW_volume_batch_cache_get_selection_surface(Volume *volume
void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
Object *ob,
Mesh *mesh,
const Object *object_orig,
const Scene *scene,
bool is_paint_mode,
bool use_hide);

View File

@ -1333,6 +1333,7 @@ static void drw_mesh_batch_cache_check_available(TaskGraph *task_graph, Mesh *me
void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
Object *ob,
Mesh *mesh,
const Object *object_orig,
const Scene *scene,
const bool is_paint_mode,
const bool use_hide)
@ -1376,12 +1377,34 @@ void DRW_mesh_batch_cache_create_requested(TaskGraph *task_graph,
BLI_assert(BKE_object_get_editmesh_eval_final(ob) != nullptr);
}
const bool is_editmode = (mesh->runtime->edit_mesh != nullptr) &&
(BKE_object_get_editmesh_eval_final(ob) != nullptr) &&
DRW_object_is_in_edit_mode(ob);
const bool is_editmode = [&]() {
if (!mesh->runtime->edit_mesh) {
return false;
}
if (!BKE_object_get_editmesh_eval_final(ob)) {
return false;
}
if (!DRW_object_is_in_edit_mode(ob)) {
return false;
}
return true;
}();
/* This could be set for paint mode too, currently it's only used for edit-mode. */
const bool edit_mode_active = is_editmode && DRW_object_is_in_edit_mode(ob);
/* In order to properly extract edit mode data, the edit mode data of the evaluated mesh has to
* match the edit mode data from the original object. */
const bool edit_mode_active = [&]() {
if (!object_orig) {
return false;
}
if (object_orig->type != OB_MESH) {
return false;
}
const Mesh &mesh_orig = *static_cast<const Mesh *>(object_orig->data);
if (mesh_orig.runtime->edit_mesh.get() != mesh->runtime->edit_mesh.get()) {
return false;
}
return true;
}();
DRWBatchFlag batch_requested = cache.batch_requested;
cache.batch_requested = (DRWBatchFlag)0;

View File

@ -2889,7 +2889,7 @@ void DRW_draw_depth_object(
batch = DRW_mesh_batch_cache_get_surface(mesh);
}
TaskGraph *task_graph = BLI_task_graph_create();
DRW_mesh_batch_cache_create_requested(task_graph, object, mesh, scene, false, true);
DRW_mesh_batch_cache_create_requested(task_graph, object, mesh, nullptr, scene, false, true);
BLI_task_graph_work_and_wait(task_graph);
BLI_task_graph_free(task_graph);