Cleanup: Simplify BKE_mesh_nomain_to_mesh

- Remove "take ownership" argument which was confusing and always true
  - The argument made ownership very confusing
  - Better to avoid boolean arguments that switch a function's purpose
- Remove "mask" argument which was basically wrong and not used properly
  - "EVERYTHING" was used because developers are wary of removing data
  - Instead use `CD_MASK_MESH` for its purpose of original mesh data
- Remove use of shallow copied temporary mesh, which is unnecessary now
- Split shape key processing into separate functions and use C++ types
- Copy fields explicitly rather than using memcpy for the whole struct
- Use higher level functions and avoid redundant code
  - The whole idea is pretty simple and can be built from standard logic
- Adjust `CustomData` logic to be consistent with "assign" expectations
  - Clear the layer data from the source, and moves the anonymous ID

Differential Revision: https://developer.blender.org/D15857
This commit is contained in:
2022-09-09 08:24:31 -05:00
parent 12c235a1c5
commit 21f2bacad9
17 changed files with 122 additions and 237 deletions

View File

@@ -95,6 +95,9 @@ struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index);
* Get the appropriate #KeyBlock given a name to search for.
*/
struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]);
struct KeyBlock *BKE_keyblock_find_uid(struct Key *key, int uid);
/**
* \brief copy shape-key attributes, but not key data or name/UID.
*/

View File

@@ -292,13 +292,10 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
bool build_shapekey_layers);
/**
* Copies a nomain-Mesh into an existing Mesh.
* Move data from a mesh outside of the main data-base into a mesh in the data-base.
* Takes ownership of the source mesh.
*/
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src,
struct Mesh *mesh_dst,
struct Object *ob,
const struct CustomData_MeshMasks *mask,
bool take_ownership);
void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct Object *ob);
void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct KeyBlock *kb);
/* vertex level transformations & checks (no derived mesh) */

View File

@@ -2353,8 +2353,16 @@ bool CustomData_merge(const CustomData *source,
changed = true;
if (layer->anonymous_id != nullptr) {
BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id);
newlayer->anonymous_id = layer->anonymous_id;
if (alloctype == CD_ASSIGN) {
layer->anonymous_id = nullptr;
}
else {
BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id);
}
}
if (alloctype == CD_ASSIGN) {
layer->data = nullptr;
}
}
}

View File

@@ -1938,6 +1938,16 @@ KeyBlock *BKE_keyblock_find_name(Key *key, const char name[])
return BLI_findstring(&key->block, name, offsetof(KeyBlock, name));
}
KeyBlock *BKE_keyblock_find_uid(Key *key, const int uid)
{
LISTBASE_FOREACH (KeyBlock *, kb, &key->block) {
if (kb->uid == uid) {
return kb;
}
}
return NULL;
}
void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
{
kb_dst->pos = kb_src->pos;

View File

@@ -881,11 +881,12 @@ static void mesh_clear_geometry(Mesh *mesh)
mesh->totpoly = 0;
mesh->act_face = -1;
mesh->totselect = 0;
BLI_freelistN(&mesh->vertex_group_names);
}
void BKE_mesh_clear_geometry(Mesh *mesh)
{
BKE_animdata_free(&mesh->id, false);
BKE_mesh_runtime_clear_cache(mesh);
mesh_clear_geometry(mesh);
}
@@ -975,6 +976,7 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src)
copy_v3_v3(me_dst->size, me_src->size);
me_dst->vertex_group_active_index = me_src->vertex_group_active_index;
me_dst->attributes_active_index = me_src->attributes_active_index;
}
void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src)

View File

@@ -54,9 +54,11 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::Span;
using blender::StringRefNull;
/* Define for cases when you want extra validation of mesh
* after certain modifications.
@@ -1081,7 +1083,7 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain,
mesh_in_bmain->smoothresh = mesh->smoothresh;
mesh->mat = nullptr;
BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr);
/* Anonymous attributes shouldn't exist on original data. */
mesh_in_bmain->attributes_for_write().remove_anonymous();
@@ -1235,239 +1237,113 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
return result;
}
/* This is a Mesh-based copy of the same function in DerivedMesh.cc */
static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid)
static KeyBlock *keyblock_ensure_from_uid(Key &key, const int uid, const StringRefNull name)
{
KeyBlock *kb;
int i, j, tot;
if (!mesh_dst->key) {
return;
if (KeyBlock *kb = BKE_keyblock_find_uid(&key, uid)) {
return kb;
}
KeyBlock *kb = BKE_keyblock_add(&key, name.c_str());
kb->uid = uid;
return kb;
}
tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY);
for (i = 0; i < tot; i++) {
CustomDataLayer *layer =
&mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)];
float(*kbcos)[3];
static int find_object_active_key_uid(const Key &key, const Object &object)
{
const int active_kb_index = object.shapenr - 1;
const KeyBlock *kb = (const KeyBlock *)BLI_findlink(&key.block, active_kb_index);
if (!kb) {
CLOG_ERROR(&LOG, "Could not find object's active shapekey %d", active_kb_index);
return -1;
}
return kb->uid;
}
for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) {
if (kb->uid == layer->uid) {
break;
}
}
static void move_shapekey_layers_to_keyblocks(Mesh &mesh, Key &key_dst, const int actshape_uid)
{
using namespace blender::bke;
for (const int i : IndexRange(CustomData_number_of_layers(&mesh.vdata, CD_SHAPEKEY))) {
const int layer_index = CustomData_get_layer_index_n(&mesh.vdata, CD_SHAPEKEY, i);
CustomDataLayer &layer = mesh.vdata.layers[layer_index];
if (!kb) {
kb = BKE_keyblock_add(mesh_dst->key, layer->name);
kb->uid = layer->uid;
}
KeyBlock *kb = keyblock_ensure_from_uid(key_dst, layer.uid, layer.name);
MEM_SAFE_FREE(kb->data);
if (kb->data) {
MEM_freeN(kb->data);
}
kb->totelem = mesh.totvert;
const float(*cos)[3] = (const float(*)[3])CustomData_get_layer_n(
&mesh_src->vdata, CD_SHAPEKEY, i);
kb->totelem = mesh_src->totvert;
kb->data = kbcos = (float(*)[3])MEM_malloc_arrayN(kb->totelem, sizeof(float[3]), __func__);
if (kb->uid == actshape_uid) {
const Span<MVert> verts = mesh_src->verts();
for (j = 0; j < mesh_src->totvert; j++, kbcos++) {
copy_v3_v3(*kbcos, verts[j].co);
}
kb->data = MEM_malloc_arrayN(kb->totelem, sizeof(float3), __func__);
MutableSpan<float3> kb_coords(static_cast<float3 *>(kb->data), kb->totelem);
mesh.attributes().lookup<float3>("position").materialize(kb_coords);
}
else {
for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
copy_v3_v3(*kbcos, *cos);
}
kb->data = layer.data;
layer.data = nullptr;
}
}
for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) {
if (kb->totelem != mesh_src->totvert) {
if (kb->data) {
MEM_freeN(kb->data);
}
kb->totelem = mesh_src->totvert;
kb->data = MEM_calloc_arrayN(kb->totelem, sizeof(float[3]), __func__);
CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name);
LISTBASE_FOREACH (KeyBlock *, kb, &key_dst.block) {
if (kb->totelem != mesh.totvert) {
MEM_SAFE_FREE(kb->data);
}
kb->totelem = mesh.totvert;
kb->data = MEM_cnew_array<float3>(kb->totelem, __func__);
CLOG_ERROR(&LOG, "Data for shape key '%s' on mesh missing from evaluated mesh ", kb->name);
}
}
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
Mesh *mesh_dst,
Object *ob,
const CustomData_MeshMasks *mask,
bool take_ownership)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
{
using namespace blender::bke;
BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN);
/* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
/* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh);
* check whether it is still true with Mesh */
Mesh tmp = blender::dna::shallow_copy(*mesh_dst);
int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
bool did_shapekeys = false;
eCDAllocType alloctype = CD_DUPLICATE;
if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) {
bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) ||
CustomData_has_referenced(&mesh_src->edata) ||
CustomData_has_referenced(&mesh_src->ldata) ||
CustomData_has_referenced(&mesh_src->fdata) ||
CustomData_has_referenced(&mesh_src->pdata);
if (!has_any_referenced_layers) {
alloctype = CD_ASSIGN;
}
}
CustomData_reset(&tmp.vdata);
CustomData_reset(&tmp.edata);
CustomData_reset(&tmp.fdata);
CustomData_reset(&tmp.ldata);
CustomData_reset(&tmp.pdata);
totvert = tmp.totvert = mesh_src->totvert;
totedge = tmp.totedge = mesh_src->totedge;
totloop = tmp.totloop = mesh_src->totloop;
totpoly = tmp.totpoly = mesh_src->totpoly;
tmp.totface = 0;
CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert);
CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge);
CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop);
CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly);
tmp.cd_flag = mesh_src->cd_flag;
tmp.runtime.deformed_only = mesh_src->runtime.deformed_only;
/* Clear the normals completely, since the new vertex / polygon count might be different. */
BKE_mesh_clear_derived_normals(&tmp);
if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
KeyBlock *kb;
int uid;
if (ob) {
kb = (KeyBlock *)BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1);
if (kb) {
uid = kb->uid;
}
else {
CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);
uid = INT_MAX;
}
}
else {
/* if no object, set to INT_MAX so we don't mess up any shapekey layers */
uid = INT_MAX;
}
shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid);
did_shapekeys = true;
}
/* copy texture space */
if (ob) {
BKE_mesh_texspace_copy_from_object(&tmp, ob);
BLI_assert(mesh_dst == ob->data);
}
/* not all DerivedMeshes store their verts/edges/faces in CustomData, so
* we set them here in case they are missing */
/* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and
* always directly pass mesh_src->mxxx, instead of using a ternary operator. */
if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
CustomData_add_layer(&tmp.vdata,
CD_MVERT,
CD_ASSIGN,
(alloctype == CD_ASSIGN) ? mesh_src->verts_for_write().data() :
MEM_dupallocN(mesh_src->verts().data()),
totvert);
}
if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
CustomData_add_layer(&tmp.edata,
CD_MEDGE,
CD_ASSIGN,
(alloctype == CD_ASSIGN) ? mesh_src->edges_for_write().data() :
MEM_dupallocN(mesh_src->edges().data()),
totedge);
}
if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
CustomData_add_layer(&tmp.ldata,
CD_MLOOP,
CD_ASSIGN,
(alloctype == CD_ASSIGN) ? mesh_src->loops_for_write().data() :
MEM_dupallocN(mesh_src->loops().data()),
tmp.totloop);
CustomData_add_layer(&tmp.pdata,
CD_MPOLY,
CD_ASSIGN,
(alloctype == CD_ASSIGN) ? mesh_src->polys_for_write().data() :
MEM_dupallocN(mesh_src->polys().data()),
tmp.totpoly);
}
BKE_mesh_clear_geometry(mesh_dst);
/* object had got displacement layer, should copy this layer to save sculpted data */
/* NOTE(nazgul): maybe some other layers should be copied? */
if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) {
if (totloop == mesh_dst->totloop) {
MDisps *mdisps = (MDisps *)CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS);
CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
if (alloctype == CD_ASSIGN) {
/* Assign nullptr to prevent double-free. */
CustomData_set_layer(&mesh_dst->ldata, CD_MDISPS, nullptr);
}
}
}
/* Make sure referenced layers have a single user so assigning them to the mesh in main doesn't
* share them. "Referenced" layers are not expected to be shared between original meshes. */
CustomData_duplicate_referenced_layers(&mesh_src->vdata, mesh_src->totvert);
CustomData_duplicate_referenced_layers(&mesh_src->edata, mesh_src->totedge);
CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly);
CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop);
CustomData_free(&mesh_dst->vdata, mesh_dst->totvert);
CustomData_free(&mesh_dst->edata, mesh_dst->totedge);
CustomData_free(&mesh_dst->fdata, mesh_dst->totface);
CustomData_free(&mesh_dst->ldata, mesh_dst->totloop);
CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly);
mesh_dst->totvert = mesh_src->totvert;
mesh_dst->totedge = mesh_src->totedge;
mesh_dst->totpoly = mesh_src->totpoly;
mesh_dst->totloop = mesh_src->totloop;
/* ok, this should now use new CD shapekey data,
* which should be fed through the modifier
* stack */
if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) {
CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
id_us_min(&tmp.key->id);
}
tmp.key = nullptr;
}
/* Clear selection history */
MEM_SAFE_FREE(tmp.mselect);
tmp.totselect = 0;
tmp.texflag &= ~ME_AUTOSPACE_EVALUATED;
/* Clear any run-time data.
* Even though this mesh won't typically have run-time data, the Python API can for e.g.
* create loop-triangle cache here, which is confusing when left in the mesh, see: T81136. */
BKE_mesh_runtime_clear_geometry(&tmp);
/* skip the listbase */
MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev);
/* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */
const CustomData_MeshMasks mask = CD_MASK_MESH;
CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, CD_ASSIGN, mesh_src->totvert);
CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge);
CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly);
CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop);
BLI_freelistN(&mesh_dst->vertex_group_names);
BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names);
mesh_dst->vertex_group_active_index = mesh_src->vertex_group_active_index;
mesh_dst->vertex_group_names = mesh_src->vertex_group_names;
BLI_listbase_clear(&mesh_src->vertex_group_names);
if (take_ownership) {
if (alloctype == CD_ASSIGN) {
CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask);
CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask);
CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask);
CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask);
BKE_mesh_copy_parameters(mesh_dst, mesh_src);
mesh_dst->cd_flag = mesh_src->cd_flag;
/* For original meshes, shape key data is stored in the #Key data-block, so it
* must be moved from the storage in #CustomData layers used for evaluation. */
if (Key *key_dst = mesh_dst->key) {
if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) {
/* If no object, set to -1 so we don't mess up any shapekey layers. */
const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1;
move_shapekey_layers_to_keyblocks(*mesh_src, *key_dst, uid_active);
}
else if (mesh_src->totvert != mesh_dst->totvert) {
CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name);
if (mesh_src->key) {
id_us_min(&mesh_src->key->id);
}
}
BKE_id_free(nullptr, mesh_src);
}
BKE_mesh_assert_normals_dirty_or_calculated(mesh_dst);
BKE_id_free(nullptr, mesh_src);
}
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)

View File

@@ -1252,7 +1252,7 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
}
/* Copy the new base mesh to the original mesh. */
BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object);
Mesh *base_mesh = object->data;
multires_create_grids_in_unsubdivided_base_mesh(&unsubdiv_context, base_mesh);

View File

@@ -204,7 +204,7 @@ static int geometry_extract_apply(bContext *C,
local_view_bits = v3d->local_view_uuid;
}
Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits);
BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true);
BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob);
/* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object.
* TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */
@@ -548,7 +548,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
/* Remove the mask from the new object so it can be sculpted directly after slicing. */
CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert);
BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob);
BKE_mesh_copy_parameters_for_eval(new_ob->data, mesh);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob);
BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL);
@@ -557,7 +557,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, new_ob->data);
}
BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob);
if (ob->mode == OB_MODE_SCULPT) {
SculptSession *ss = ob->sculpt;

View File

@@ -3151,7 +3151,7 @@ static int object_convert_exec(bContext *C, wmOperator *op)
BKE_mesh_edges_set_draw_render(me_eval);
BKE_object_material_from_eval_data(bmain, newob, &me_eval->id);
Mesh *new_mesh = (Mesh *)newob->data;
BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob);
if (do_merge_customdata) {
BKE_mesh_merge_customdata_for_apply_modifier(new_mesh);

View File

@@ -763,7 +763,7 @@ static bool modifier_apply_obdata(
Main *bmain = DEG_get_bmain(depsgraph);
BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id);
BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(mesh_applied, me, ob);
/* Anonymous attributes shouldn't be available on the applied geometry. */
me->attributes_for_write().remove_anonymous();

View File

@@ -179,7 +179,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
BKE_remesh_reproject_vertex_paint(new_mesh, mesh);
}
BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob);
if (smooth_normals) {
BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true);
@@ -905,7 +905,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update
BKE_mesh_remesh_reproject_paint_mask(new_mesh, mesh);
}
BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob);
if (qj->smooth_normals) {
BKE_mesh_smooth_flag_set(static_cast<Mesh *>(ob->data), true);

View File

@@ -1315,8 +1315,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext)
}),
sculpt_mesh);
BM_mesh_free(bm);
BKE_mesh_nomain_to_mesh(
result, sgcontext->vc.obact->data, sgcontext->vc.obact, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(result, sgcontext->vc.obact->data, sgcontext->vc.obact);
}
static void sculpt_gesture_trim_begin(bContext *C, SculptGestureContext *sgcontext)

View File

@@ -619,11 +619,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr);
if (read_mesh != mesh) {
/* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */
/* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */
uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH);
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true);
mesh->flag |= autosmooth;
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object);
}
if (m_settings->validate_meshes) {
@@ -1003,7 +999,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec
Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr);
if (read_mesh != mesh) {
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true);
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object);
}
ISubDSchema::Sample sample;

View File

@@ -69,7 +69,7 @@ void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSel
Mesh *read_mesh = this->read_mesh(mesh, sample_sel, 0, "", 0.0f, nullptr);
if (read_mesh != mesh) {
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true);
BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object);
}
if (m_settings->validate_meshes) {

View File

@@ -248,11 +248,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime)
is_initial_load_ = false;
if (read_mesh != mesh) {
/* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */
/* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */
uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH);
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true);
mesh->flag |= autosmooth;
BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_);
}
readFaceSetsSample(bmain, mesh, motionSampleTime);

View File

@@ -69,11 +69,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain,
}
transform_object(obj, import_params);
/* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */
const uint16_t autosmooth = (mesh->flag & ME_AUTOSMOOTH);
Mesh *dst = static_cast<Mesh *>(obj->data);
BKE_mesh_nomain_to_mesh(mesh, dst, obj, &CD_MASK_EVERYTHING, true);
dst->flag |= autosmooth;
BKE_mesh_nomain_to_mesh(mesh, static_cast<Mesh *>(obj->data), obj);
/* NOTE: vertex groups have to be created after final mesh is assigned to the object. */
create_vertex_groups(obj);

View File

@@ -22,6 +22,7 @@
# include "DNA_mesh_types.h"
# include "BKE_anim_data.h"
# include "BKE_mesh.h"
# include "BKE_mesh_mapping.h"
# include "BKE_mesh_runtime.h"
@@ -192,6 +193,7 @@ static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3])
static void rna_Mesh_clear_geometry(Mesh *mesh)
{
BKE_mesh_clear_geometry(mesh);
BKE_animdata_free(&mesh->id, false);
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY_ALL_MODES);
WM_main_add_notifier(NC_GEOM | ND_DATA, mesh);