Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2019-05-16 14:49:21 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-05-16 17:42:16 +0300
commit32d5d127cb49743578e8e1e9882d8a707a4e848e (patch)
tree72c18410ca6f3d503d8790bd936bc73273efb658 /source/blender
parent22a91bb0bd6ac76142f832e0e07df0b5f9e8ead2 (diff)
Tweak API to support adding evaluated meshes to main database
One of the usecases is to create mesh from an object is a manner similar to how Apply Modifiers does it, and have it in the bmain so it can be referenced by other objects. This usecase is something what went unnoticed in the previous API changes, so here is a followup. Summary of changes: * bpy.meshes.new_from_object() behaves almost the same as before this change. The difference now is that it now ensures all referenced data-blocks are original (for example, materials referenced by the mesh). * object.to_mesh() now creates free-standing Mesh data-block which is outside of any bmain. The object owns it, which guarantees the memory never leaks. It is possible to force free memory by calling object.to_mesh_clear(). Reviewers: brecht Reviewed By: brecht Differential Revision: https://developer.blender.org/D4875
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_mesh.h8
-rw-r--r--source/blender/blenkernel/BKE_object.h9
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c114
-rw-r--r--source/blender/blenkernel/intern/object.c19
-rw-r--r--source/blender/editors/object/object_bake_api.c22
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp5
-rw-r--r--source/blender/makesdna/DNA_object_types.h5
-rw-r--r--source/blender/makesrna/intern/rna_internal.h3
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c4
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c40
10 files changed, 171 insertions, 58 deletions
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 8ea54457f38..c410946f438 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -208,7 +208,13 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
-struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Object *object);
+/* Create new mesh from the given object at its current state.
+ * The owner of this mesh is unknown, it is up to the caller to decide. */
+struct Mesh *BKE_mesh_new_from_object(struct Object *object);
+
+/* This is a version of BKE_mesh_new_from_object() which stores mesh in the given main database. */
+struct Mesh *BKE_mesh_new_from_object_to_bmain(struct Main *bmain, struct Object *object);
+
struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob_eval,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index c373fbfe478..aa4d9696527 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -396,6 +396,15 @@ bool BKE_object_empty_image_frame_is_visible_in_view3d(const struct Object *ob,
bool BKE_object_empty_image_data_is_visible_in_view3d(const struct Object *ob,
const struct RegionView3D *rv3d);
+/* This is an utility function for Python's object.to_mesh() (the naming is not very clear though).
+ * The result is owned by the object.
+ *
+ * The mesh will be freed when object is re-evaluated or is destroyed. It is possible to force to
+ * clear memory sued by this mesh by calling BKE_object_to_mesh_clear(). */
+struct Mesh *BKE_object_to_mesh(struct Object *object);
+
+void BKE_object_to_mesh_clear(struct Object *object);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index a5c97cd1182..6d0245cbc88 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -38,6 +38,7 @@
#include "BKE_main.h"
#include "BKE_DerivedMesh.h"
#include "BKE_key.h"
+#include "BKE_library_query.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
@@ -612,7 +613,13 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
}
/* make mesh */
- me = BKE_mesh_add(bmain, obdata_name);
+ if (bmain != NULL) {
+ me = BKE_mesh_add(bmain, obdata_name);
+ }
+ else {
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
+ }
+
me->totvert = totvert;
me->totedge = totedge;
me->totloop = totloop;
@@ -632,7 +639,13 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
BKE_mesh_calc_normals(me);
}
else {
- me = BKE_mesh_add(bmain, obdata_name);
+ if (bmain != NULL) {
+ me = BKE_mesh_add(bmain, obdata_name);
+ }
+ else {
+ me = BKE_id_new_nomain(ID_ME, obdata_name);
+ }
+
ob->runtime.mesh_eval = NULL;
BKE_mesh_nomain_to_mesh(me_eval, me, ob, &CD_MASK_MESH, true);
}
@@ -662,16 +675,18 @@ void BKE_mesh_from_nurbs_displist(Main *bmain,
ob->type = OB_MESH;
/* other users */
- ob1 = bmain->objects.first;
- while (ob1) {
- if (ob1->data == cu) {
- ob1->type = OB_MESH;
-
- id_us_min((ID *)ob1->data);
- ob1->data = ob->data;
- id_us_plus((ID *)ob1->data);
+ if (bmain != NULL) {
+ ob1 = bmain->objects.first;
+ while (ob1) {
+ if (ob1->data == cu) {
+ ob1->type = OB_MESH;
+
+ id_us_min((ID *)ob1->data);
+ ob1->data = ob->data;
+ id_us_plus((ID *)ob1->data);
+ }
+ ob1 = ob1->id.next;
}
- ob1 = ob1->id.next;
}
if (temporary) {
@@ -995,7 +1010,7 @@ static void curve_to_mesh_eval_ensure(Object *object)
BKE_object_free_curve_cache(&taper_object);
}
-static Mesh *mesh_new_from_curve_type_object(Main *bmain, Object *object)
+static Mesh *mesh_new_from_curve_type_object(Object *object)
{
Curve *curve = object->data;
const bool uv_from_orco = (curve->flag & CU_UV_ORCO) != 0;
@@ -1014,7 +1029,7 @@ static Mesh *mesh_new_from_curve_type_object(Main *bmain, Object *object)
temp_curve->editnurb = NULL;
/* Convert to mesh. */
- BKE_mesh_from_nurbs_displist(bmain,
+ BKE_mesh_from_nurbs_displist(NULL,
temp_object,
&temp_object->runtime.curve_cache->disp,
uv_from_orco,
@@ -1037,7 +1052,7 @@ static Mesh *mesh_new_from_curve_type_object(Main *bmain, Object *object)
return mesh_result;
}
-static Mesh *mesh_new_from_mball_object(Main *bmain, Object *object)
+static Mesh *mesh_new_from_mball_object(Object *object)
{
MetaBall *mball = (MetaBall *)object->data;
@@ -1048,10 +1063,10 @@ static Mesh *mesh_new_from_mball_object(Main *bmain, Object *object)
* We create empty mesh so scripters don't run into None objects. */
if (!DEG_is_evaluated_object(object) || object->runtime.curve_cache == NULL ||
BLI_listbase_is_empty(&object->runtime.curve_cache->disp)) {
- return BKE_mesh_add(bmain, mball->id.name + 2);
+ return BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
}
- Mesh *mesh_result = BKE_mesh_add(bmain, ((ID *)object->data)->name + 2);
+ Mesh *mesh_result = BKE_id_new_nomain(ID_ME, ((ID *)object->data)->name + 2);
BKE_mesh_from_metaball(&object->runtime.curve_cache->disp, mesh_result);
/* Copy materials. */
@@ -1066,29 +1081,32 @@ static Mesh *mesh_new_from_mball_object(Main *bmain, Object *object)
return mesh_result;
}
-static Mesh *mesh_new_from_mesh_object(Main *bmain, Object *object)
+static Mesh *mesh_new_from_mesh_object(Object *object)
{
Mesh *mesh_input = object->data;
Mesh *mesh_result = NULL;
- BKE_id_copy_ex(bmain, &mesh_input->id, (ID **)&mesh_result, 0);
+ BKE_id_copy_ex(NULL,
+ &mesh_input->id,
+ (ID **)&mesh_result,
+ LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT);
/* NOTE: Materials should already be copied. */
return mesh_result;
}
-Mesh *BKE_mesh_new_from_object(Main *bmain, Object *object)
+Mesh *BKE_mesh_new_from_object(Object *object)
{
Mesh *new_mesh = NULL;
switch (object->type) {
case OB_FONT:
case OB_CURVE:
case OB_SURF:
- new_mesh = mesh_new_from_curve_type_object(bmain, object);
+ new_mesh = mesh_new_from_curve_type_object(object);
break;
case OB_MBALL:
- new_mesh = mesh_new_from_mball_object(bmain, object);
+ new_mesh = mesh_new_from_mball_object(object);
break;
case OB_MESH:
- new_mesh = mesh_new_from_mesh_object(bmain, object);
+ new_mesh = mesh_new_from_mesh_object(object);
break;
default:
/* Object does not have geometry data. */
@@ -1098,15 +1116,55 @@ Mesh *BKE_mesh_new_from_object(Main *bmain, Object *object)
/* Happens in special cases like request of mesh for non-mother meta ball. */
return NULL;
}
- /* The result must have 0 users, since it's just a mesh which is free-dangling in the main
- * database. All the copy and allocation functions to manipulate new Mesh datablock are ensuring
- * an user.
- * Here we control that user management went the way it's expected, and cancel out the user. */
- BLI_assert(new_mesh->id.us == 1);
- id_us_min(&new_mesh->id);
+ /* The result must have 0 users, since it's just a mesh which is free-dangling data-block.
+ * All the conversion functions are supposed to ensure mesh is not counted. */
+ BLI_assert(new_mesh->id.us == 0);
return new_mesh;
}
+static int foreach_libblock_make_original_and_usercount_callback(void *user_data_v,
+ ID *id_self,
+ ID **id_p,
+ int cb_flag)
+{
+ UNUSED_VARS(user_data_v, id_self, cb_flag);
+ if (*id_p == NULL) {
+ return IDWALK_RET_NOP;
+ }
+ *id_p = DEG_get_original_id(*id_p);
+ id_us_plus(*id_p);
+ return IDWALK_RET_NOP;
+}
+
+Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, Object *object)
+{
+ Mesh *mesh = BKE_mesh_new_from_object(object);
+
+ /* Make sure mesh only points original datablocks, also increase users of materials and other
+ * possibly referenced data-blocks.
+ *
+ * Going to original data-blocks is required to have bmain in a consistent state, where
+ * everything is only allowed to reference original data-blocks.
+ *
+ * user-count is required is because so far mesh was in a limbo, where library management does
+ * not perform any user management (i.e. copy of a mesh will not increase users of materials). */
+ BKE_library_foreach_ID_link(
+ NULL, &mesh->id, foreach_libblock_make_original_and_usercount_callback, NULL, IDWALK_NOP);
+
+ /* Append the mesh to bmain.
+ * We do it a bit longer way since there is no simple and clear way of adding existing datablock
+ * to the bmain. So we allocate new empty mesh in the bmain (which guarantess all the naming and
+ * orders and flags) and move the temporary mesh in place there. */
+ Mesh *mesh_in_bmain = BKE_mesh_add(bmain, mesh->id.name + 2);
+ BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, NULL, &CD_MASK_MESH, true);
+
+ /* Make sure user count from BKE_mesh_add() is the one we expect here and bring it down to 0. */
+ BLI_assert(mesh_in_bmain->id.us == 1);
+ id_us_min(&mesh_in_bmain->id);
+
+ return mesh_in_bmain;
+}
+
static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
{
KeyBlock *kb;
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 78f2b10305e..95be7f8f51f 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -469,6 +469,7 @@ void BKE_object_free_derived_caches(Object *ob)
ob->runtime.mesh_deform_eval = NULL;
}
+ BKE_object_to_mesh_clear(ob);
BKE_object_free_curve_cache(ob);
/* clear grease pencil data */
@@ -4497,3 +4498,21 @@ void BKE_object_update_select_id(struct Main *bmain)
ob = ob->id.next;
}
}
+
+Mesh *BKE_object_to_mesh(Object *object)
+{
+ BKE_object_to_mesh_clear(object);
+
+ Mesh *mesh = BKE_mesh_new_from_object(object);
+ object->runtime.object_as_temp_mesh = mesh;
+ return mesh;
+}
+
+void BKE_object_to_mesh_clear(Object *object)
+{
+ if (object->runtime.object_as_temp_mesh == NULL) {
+ return;
+ }
+ BKE_id_free(NULL, object->runtime.object_as_temp_mesh);
+ object->runtime.object_as_temp_mesh = NULL;
+}
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index 4f26ae27d9c..f87342a14ad 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -705,9 +705,9 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re
}
/* create new mesh with edit mode changes and modifiers applied */
-static Mesh *bake_mesh_new_from_object(Main *bmain, Object *object)
+static Mesh *bake_mesh_new_from_object(Object *object)
{
- Mesh *me = BKE_mesh_new_from_object(bmain, object);
+ Mesh *me = BKE_object_to_mesh(object);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -903,7 +903,7 @@ static int bake(Render *re,
ob_low_eval = DEG_get_evaluated_object(depsgraph, ob_low);
/* get the mesh as it arrives in the renderer */
- me_low = bake_mesh_new_from_object(bmain, ob_low_eval);
+ me_low = bake_mesh_new_from_object(ob_low_eval);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) {
@@ -917,7 +917,7 @@ static int bake(Render *re,
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(bmain, ob_cage_eval);
+ me_cage = bake_mesh_new_from_object(ob_cage_eval);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports,
RPT_ERROR,
@@ -946,7 +946,7 @@ static int bake(Render *re,
md = md_next;
}
- me_cage = bake_mesh_new_from_object(bmain, ob_low_eval);
+ me_cage = BKE_object_to_mesh(ob_low_eval);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -965,7 +965,7 @@ static int bake(Render *re,
highpoly[i].ob_eval = DEG_get_evaluated_object(depsgraph, ob_iter);
highpoly[i].ob_eval->restrictflag &= ~OB_RESTRICT_RENDER;
highpoly[i].ob_eval->base_flag |= (BASE_VISIBLE | BASE_ENABLED_RENDER);
- highpoly[i].me = bake_mesh_new_from_object(bmain, highpoly[i].ob_eval);
+ highpoly[i].me = BKE_object_to_mesh(highpoly[i].ob_eval);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1088,7 +1088,7 @@ static int bake(Render *re,
}
/* Evaluate modifiers again. */
- me_nores = BKE_mesh_new_from_object(bmain, ob_low_eval);
+ me_nores = BKE_object_to_mesh(ob_low_eval);
RE_bake_pixels_populate(me_nores, pixel_array_low, num_pixels, &bake_images, uv_layer);
RE_bake_normal_world_to_tangent(pixel_array_low,
@@ -1098,7 +1098,7 @@ static int bake(Render *re,
me_nores,
normal_swizzle,
ob_low_eval->obmat);
- BKE_id_free(bmain, me_nores);
+ BKE_object_to_mesh_clear(ob_low_eval);
if (md) {
md->mode = mode;
@@ -1222,7 +1222,7 @@ cleanup:
int i;
for (i = 0; i < tot_highpoly; i++) {
if (highpoly[i].me) {
- BKE_id_free(bmain, highpoly[i].me);
+ BKE_object_to_mesh_clear(highpoly[i].ob_eval);
}
}
MEM_freeN(highpoly);
@@ -1253,11 +1253,11 @@ cleanup:
}
if (me_low) {
- BKE_id_free(bmain, me_low);
+ BKE_object_to_mesh_clear(ob_low_eval);
}
if (me_cage) {
- BKE_id_free(bmain, me_cage);
+ BKE_object_to_mesh_clear(ob_cage_eval);
}
DEG_graph_free(depsgraph);
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index ed553c9583c..ee13583e67a 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -23,6 +23,7 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
+#include "BKE_object.h"
#include <sstream>
@@ -98,11 +99,11 @@ NodeGroup *BlenderFileLoader::Load()
continue;
}
- Mesh *mesh = BKE_mesh_new_from_object(_re->main, ob);
+ Mesh *mesh = BKE_object_to_mesh(ob);
if (mesh) {
insertShapeNode(ob, mesh, ++id);
- BKE_id_free_ex(_re->main, &mesh->id, LIB_ID_FREE_NO_UI_USER, true);
+ BKE_object_to_mesh_clear(ob);
}
}
DEG_OBJECT_ITER_END;
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index a73c762e3bf..0b2f3d69bd2 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -43,6 +43,7 @@ struct DerivedMesh;
struct FluidsimSettings;
struct GpencilBatchCache;
struct Ipo;
+struct Mesh;
struct Material;
struct Object;
struct PartDeflect;
@@ -160,6 +161,10 @@ typedef struct Object_Runtime {
*/
struct Mesh *mesh_deform_eval;
+ /* This is a mesh representation of corresponding object.
+ * It created when Python calls `object.to_mesh()`. */
+ struct Mesh *object_as_temp_mesh;
+
/** Runtime evaluated curve-specific data, not stored in the file. */
struct CurveCache *curve_cache;
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index d93f8c4414b..64024166c50 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -548,9 +548,6 @@ PointerRNA rna_pointer_inherit_refine(struct PointerRNA *ptr, struct StructRNA *
int rna_parameter_size(struct PropertyRNA *parm);
-struct Mesh *rna_Main_meshes_new_from_object(struct Main *bmain,
- struct ReportList *reports,
- struct Object *object);
/* XXX, these should not need to be defined here~! */
struct MTex *rna_mtex_texture_slots_add(struct ID *self,
diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c
index 8f48738a27e..f6fee2580b8 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -317,7 +317,7 @@ static Mesh *rna_Main_meshes_new(Main *bmain, const char *name)
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object)
+static Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object)
{
switch (object->type) {
case OB_FONT:
@@ -331,7 +331,7 @@ Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *
return NULL;
}
- return BKE_mesh_new_from_object(bmain, object);
+ return BKE_mesh_new_from_object_to_bmain(bmain, object);
}
static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index d94abd4066a..da00e1f155d 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -375,11 +375,28 @@ static void rna_Object_camera_fit_coords(
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-static Mesh *rna_Object_to_mesh(Object *object, bContext *C, ReportList *reports)
+static Mesh *rna_Object_to_mesh(Object *object, ReportList *reports)
{
- Main *bmain = CTX_data_main(C);
+ /* TODO(sergey): Make it more re-usable function, de-duplicate with
+ * rna_Main_meshes_new_from_object. */
+ switch (object->type) {
+ case OB_FONT:
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_MESH:
+ break;
+ default:
+ BKE_report(reports, RPT_ERROR, "Object does not have geometry data");
+ return NULL;
+ }
+
+ return BKE_object_to_mesh(object);
+}
- return rna_Main_meshes_new_from_object(bmain, reports, object);
+static void rna_Object_to_mesh_clear(Object *object)
+{
+ BKE_object_to_mesh_clear(object);
}
static PointerRNA rna_Object_shape_key_add(
@@ -875,16 +892,17 @@ void RNA_api_object(StructRNA *srna)
/* mesh */
func = RNA_def_function(srna, "to_mesh", "rna_Object_to_mesh");
- RNA_def_function_ui_description(func,
- "Create a Mesh data-block from the current state of the object");
- RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT);
- parm = RNA_def_pointer(func,
- "mesh",
- "Mesh",
- "",
- "Mesh created from object, remove it if it is only used for export");
+ RNA_def_function_ui_description(
+ func,
+ "Create a Mesh data-block from the current state of the object. The object owns the "
+ "data-block. To force free it use to_mesh_clear()");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(func, "mesh", "Mesh", "", "Mesh created from object");
RNA_def_function_return(func, parm);
+ func = RNA_def_function(srna, "to_mesh_clear", "rna_Object_to_mesh_clear");
+ RNA_def_function_ui_description(func, "Clears mesh data-block created by to_mesh()");
+
/* Armature */
func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature");
RNA_def_function_ui_description(