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
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
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);
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 rna_Main_meshes_new_from_object(bmain, reports, object);
|
||||
return BKE_object_to_mesh(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(
|
||||
|
||||
Reference in New Issue
Block a user