Added BKE_mesh_clear_geometry() function
authorSybren A. Stüvel <sybren@blender.org>
Tue, 30 Jul 2019 16:38:31 +0000 (18:38 +0200)
committerSybren A. Stüvel <sybren@blender.org>
Wed, 31 Jul 2019 10:23:56 +0000 (12:23 +0200)
This function makes it possible to clear/remove/nuke all the geometry in
a mesh, allowing functions like `Mesh.from_python()` to construct a new
mesh in its place. Without this function, code like in T67627 have to
allocate a new Mesh datablock, fill that, and swap out the old Mesh for
the new one. This introduces issues when exporting, as the new mesh
could be seen by an exporter as unrelated to the old one.

Shape keys are not freed by this function. Freeing those would require
tagging the depsgraph for relations update, which is an expensive
operation. They should be removed explicitly if necessary.

Material slots are also not cleared by this function, in the same way
that they are not cleared when manually removing all geometry from a
mesh.

The `BKE_mesh_clear_geometry()` function is available in Python as
`mesh.clear_geometry()`.

Reviewed by: mont29, brecht

Differential Revision: https://developer.blender.org/D5373

source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh.c
source/blender/makesrna/intern/rna_mesh_api.c

index d6b4fa7228139a292743c041faa5cc71bf828aa6..3b7fe208bb6dd7405dfa71e5022f91dfd3b76167 100644 (file)
@@ -105,6 +105,7 @@ void BKE_mesh_looptri_get_real_edges(const struct Mesh *mesh,
 
 void BKE_mesh_free(struct Mesh *me);
 void BKE_mesh_init(struct Mesh *me);
+void BKE_mesh_clear_geometry(struct Mesh *me);
 struct Mesh *BKE_mesh_add(struct Main *bmain, const char *name);
 void BKE_mesh_copy_data(struct Main *bmain,
                         struct Mesh *me_dst,
index 9e01bfe62d658f011be92ab10258caf14606dac5..f38161546e27f451a5f77949bb1f60ebbb27f082 100644 (file)
@@ -40,6 +40,7 @@
 #include "BKE_idcode.h"
 #include "BKE_main.h"
 #include "BKE_global.h"
+#include "BKE_key.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
 #include "BKE_library.h"
@@ -479,20 +480,38 @@ bool BKE_mesh_has_custom_loop_normals(Mesh *me)
 /** Free (or release) any data used by this mesh (does not free the mesh itself). */
 void BKE_mesh_free(Mesh *me)
 {
-  BKE_animdata_free(&me->id, false);
+  BKE_mesh_clear_geometry(me);
+  MEM_SAFE_FREE(me->mat);
+}
 
-  BKE_mesh_runtime_clear_cache(me);
+void BKE_mesh_clear_geometry(Mesh *mesh)
+{
+  BKE_animdata_free(&mesh->id, false);
+  BKE_mesh_runtime_clear_cache(mesh);
 
-  CustomData_free(&me->vdata, me->totvert);
-  CustomData_free(&me->edata, me->totedge);
-  CustomData_free(&me->fdata, me->totface);
-  CustomData_free(&me->ldata, me->totloop);
-  CustomData_free(&me->pdata, me->totpoly);
+  CustomData_free(&mesh->vdata, mesh->totvert);
+  CustomData_free(&mesh->edata, mesh->totedge);
+  CustomData_free(&mesh->fdata, mesh->totface);
+  CustomData_free(&mesh->ldata, mesh->totloop);
+  CustomData_free(&mesh->pdata, mesh->totpoly);
 
-  MEM_SAFE_FREE(me->mat);
-  MEM_SAFE_FREE(me->bb);
-  MEM_SAFE_FREE(me->mselect);
-  MEM_SAFE_FREE(me->edit_mesh);
+  MEM_SAFE_FREE(mesh->bb);
+  MEM_SAFE_FREE(mesh->mselect);
+  MEM_SAFE_FREE(mesh->edit_mesh);
+
+  /* Note that materials and shape keys are not freed here. This is intentional, as freeing
+   * shape keys requires tagging the depsgraph for updated relations, which is expensive.
+   * Material slots should be kept in sync with the object.*/
+
+  mesh->totvert = 0;
+  mesh->totedge = 0;
+  mesh->totface = 0;
+  mesh->totloop = 0;
+  mesh->totpoly = 0;
+  mesh->act_face = -1;
+  mesh->totselect = 0;
+
+  BKE_mesh_update_customdata_pointers(mesh, false);
 }
 
 static void mesh_tessface_clear_intern(Mesh *mesh, int free_customdata)
index d647c64713635d4e72050e0a1b3f9851be100fc4..283590fc529175fc1fb991882fa49bb507928d97 100644 (file)
@@ -202,6 +202,14 @@ static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3])
   BKE_mesh_count_selected_items(mesh, r_count);
 }
 
+static void rna_Mesh_clear_geometry(Mesh *mesh)
+{
+  BKE_mesh_clear_geometry(mesh);
+
+  DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
+  WM_main_add_notifier(NC_GEOM | ND_DATA, mesh);
+}
+
 #else
 
 void RNA_api_mesh(StructRNA *srna)
@@ -319,6 +327,11 @@ void RNA_api_mesh(StructRNA *srna)
       func, "result", "nothing", 64, "Return value", "String description of result of comparison");
   RNA_def_function_return(func, parm);
 
+  func = RNA_def_function(srna, "clear_geometry", "rna_Mesh_clear_geometry");
+  RNA_def_function_ui_description(
+      func,
+      "Remove all geometry from the mesh. Note that this does not free shape keys or materials");
+
   func = RNA_def_function(srna, "validate", "BKE_mesh_validate");
   RNA_def_function_ui_description(func,
                                   "Validate geometry, return True when the mesh has had "