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-09 12:26:49 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2019-05-16 12:49:21 +0300
commite693918d40741b0839cea84d2e0c386cc262e0c3 (patch)
tree8527faec0d6f9975aa25f0cd011046ff19db8caf /source/blender
parentb679887bd5f77f2cd4611a4dd77e5177de3c2326 (diff)
Dependency graph API changes
Main goal here is to make it obvious and predictable about what is going on. Summary of changes. - Access to dependency graph is now only possible to a fully evaluated graph. This is now done via context.evaluated_depsgraph_get(). The call will ensure both relations and datablocks are updated. This way we don't allow access to some known bad state of the graph, and also making explicit that getting update dependency graph is not cheap. - Access to evaluated ID is now possible via id.evaluated_get(). It was already possible to get evaluated ID via dependency graph, but that was a bit confusing why access to original is done via ID and to evaluated via depsgraph. If datablock is not covered by dependency graph it will be returned as-is. - Similarly, request for original from an ID which is not evaluated will return ID as-is. - Removed scene.update(). This is very expensive to update all the view layers. - Added depsgraph.update(). Now when temporary changes to objects are to be done, this is to happen on original object and then dependency graph is to be updated. - Changed object.to_mesh() to behave the following way: * When is used for original object modifiers are ignored. For meshes this acts similar to mesh-copy, not very useful but allows to keep code paths similar (i.e. for exporter which has Apply Modifiers option it's only matter choosing between original and evaluated object, the to_mesh() part can stay the same). For curves this gives a mesh which is constructed from displist without taking own modifiers and modifiers of bevel/taper objects into account. For metaballs this gives empty mesh. Polygonization of metaball is not possible from a single object. * When is used for evaluated object modifiers are always applied. In fact, no evaluation is happening, the mesh is either copied as-is, or constructed from current state of curve cache. Arguments to apply modifiers and calculate original coordinates (ORCO, aka undeformed coordinates) are removed. The ORCO is to be calculated as part of dependency graph evaluation. File used to regression-test (a packed Python script into .blend): {F7033464} Patch to make addons tests to pass: {F7033466} NOTE: I've included changes to FBX exporter, and those are addressing report T63689. NOTE: All the enabled-by-default addons are to be ported still, but first want to have agreement on this part of changes. NOTE: Also need to work on documentation for Python API, but, again, better be done after having agreement on this work. Reviewers: brecht, campbellbarton, mont29 Differential Revision: https://developer.blender.org/D4834
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_context.h15
-rw-r--r--source/blender/blenkernel/BKE_mesh.h7
-rw-r--r--source/blender/blenkernel/intern/context.c8
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c447
-rw-r--r--source/blender/editors/object/object_bake_api.c15
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp5
-rw-r--r--source/blender/makesrna/intern/rna_ID.c14
-rw-r--r--source/blender/makesrna/intern/rna_context.c29
-rw-r--r--source/blender/makesrna/intern/rna_depsgraph.c15
-rw-r--r--source/blender/makesrna/intern/rna_internal.h5
-rw-r--r--source/blender/makesrna/intern/rna_main_api.c32
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c27
-rw-r--r--source/blender/makesrna/intern/rna_scene_api.c22
13 files changed, 273 insertions, 368 deletions
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 8be43a50be6..0d2998cc51e 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -311,8 +311,23 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+/* Gets pointer to the dependency graph.
+ * If it doesn't exist yet, it will be allocated.
+ *
+ * The result dependency graph is NOT guaranteed to be up-to-date neither from relation nor from
+ * evaluated data points of view.
+ *
+ * NOTE: Can not be used if access to a fully evaluated datablock is needed. */
struct Depsgraph *CTX_data_depsgraph(const bContext *C);
+/* Gets fully updated and evaluated dependency graph.
+ *
+ * All the relations and evaluated objects are guaranteed to be up to date.
+ *
+ * NOTE: Will be expensive if there are relations or objects tagged for update.
+ * NOTE: If there are pending updates depsgraph hooks will be invoked. */
+struct Depsgraph *CTX_data_evaluated_depsgraph(const bContext *C);
+
/* Will Return NULL if depsgraph is not allocated yet.
* Only used by handful of operators which are run on file load.
*/
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index b094dc5f400..8ea54457f38 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -208,12 +208,7 @@ 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 Depsgraph *depsgraph,
- struct Main *bmain,
- struct Scene *sce,
- struct Object *ob,
- const bool apply_modifiers,
- const bool calc_undeformed);
+struct Mesh *BKE_mesh_new_from_object(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/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4383b6a1f9b..dd326ba13db 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1315,6 +1315,14 @@ Depsgraph *CTX_data_depsgraph(const bContext *C)
return BKE_scene_get_depsgraph(scene, view_layer, true);
}
+Depsgraph *CTX_data_evaluated_depsgraph(const bContext *C)
+{
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
+ Main *bmain = CTX_data_main(C);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+ return depsgraph;
+}
+
Depsgraph *CTX_data_depsgraph_on_load(const bContext *C)
{
Scene *scene = CTX_data_scene(C);
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index fe8d053c1df..a5c97cd1182 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -892,302 +892,219 @@ void BKE_mesh_to_curve(Main *bmain, Depsgraph *depsgraph, Scene *UNUSED(scene),
}
}
-/* settings: 1 - preview, 2 - render
+/* Create a temporary object to be used for nurbs-to-mesh conversion.
*
- * The convention goes as following:
- *
- * - Passing original object with apply_modifiers=false will give a
- * non-modified non-deformed mesh.
- * The result mesh will point to datablocks from the original "domain". For
- * example, materials will be original.
- *
- * - Passing original object with apply_modifiers=true will give a mesh which
- * has all modifiers applied.
- * The result mesh will point to datablocks from the original "domain". For
- * example, materials will be original.
- *
- * - Passing evaluated object will ignore apply_modifiers argument, and the
- * result always contains all modifiers applied.
- * The result mesh will point to an evaluated datablocks. For example,
- * materials will be an evaluated IDs from the dependency graph.
- */
-Mesh *BKE_mesh_new_from_object(Depsgraph *depsgraph,
- Main *bmain,
- Scene *sce,
- Object *ob,
- const bool apply_modifiers,
- const bool calc_undeformed)
+ * This is more complex that it should be because BKE_mesh_from_nurbs_displist() will do more than
+ * simply conversion and will attempt to take over ownership of evaluated result and will also
+ * modify the input object. */
+static Object *object_for_curve_to_mesh_create(Object *object)
{
- Mesh *tmpmesh;
- Curve *tmpcu = NULL, *copycu;
- int i;
- const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- bool effective_apply_modifiers = apply_modifiers;
- bool do_mat_id_data_us = true;
-
- Object *object_input = ob;
- Object *object_eval = DEG_get_evaluated_object(depsgraph, object_input);
- Object object_for_eval;
-
- if (object_eval == object_input) {
- /* Evaluated mesh contains all modifiers applied already.
- * The other types of object has them applied, but are stored in other
- * data structures than a mesh. So need to apply modifiers again on a
- * temporary copy before converting result to mesh. */
- if (object_input->type == OB_MESH) {
- effective_apply_modifiers = false;
- }
- else {
- effective_apply_modifiers = true;
- }
- object_for_eval = *object_eval;
+ Curve *curve = (Curve *)object->data;
+
+ /* Create object itself. */
+ Object *temp_object;
+ BKE_id_copy_ex(NULL, &object->id, (ID **)&temp_object, LIB_ID_COPY_LOCALIZE);
+
+ /* Remove all modifiers, since we don't want them to be applied. */
+ BKE_object_free_modifiers(temp_object, LIB_ID_CREATE_NO_USER_REFCOUNT);
+
+ /* Copy relevant evaluated fields of curve cache.
+ *
+ * Note that there are extra fields in there like bevel and path, but those are not needed during
+ * conversion, so they are not copied to save unnecessary allocations. */
+ if (object->runtime.curve_cache != NULL) {
+ temp_object->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
+ "CurveCache for curve types");
+ BKE_displist_copy(&temp_object->runtime.curve_cache->disp, &object->runtime.curve_cache->disp);
}
- else {
- if (apply_modifiers) {
- object_for_eval = *object_eval;
- if (object_for_eval.runtime.mesh_orig != NULL) {
- object_for_eval.data = object_for_eval.runtime.mesh_orig;
- }
- }
- else {
- object_for_eval = *object_input;
- }
+ /* Constructive modifiers will use mesh to store result. */
+ if (object->runtime.mesh_eval != NULL) {
+ BKE_id_copy_ex(NULL,
+ &object->runtime.mesh_eval->id,
+ (ID **)&temp_object->runtime.mesh_eval,
+ LIB_ID_COPY_LOCALIZE);
}
- const bool cage = !effective_apply_modifiers;
+ /* Need to create copy of curve itself as well, it will be freed by underlying conversion
+ * functions.
+ *
+ * NOTE: Copies the data, but not the shapekeys. */
+ BKE_id_copy_ex(NULL, object->data, (ID **)&temp_object->data, LIB_ID_COPY_LOCALIZE);
+ Curve *temp_curve = (Curve *)temp_object->data;
- /* perform the mesh extraction based on type */
- switch (object_for_eval.type) {
- case OB_FONT:
- case OB_CURVE:
- case OB_SURF: {
- ListBase dispbase = {NULL, NULL};
- Mesh *me_eval_final = NULL;
- int uv_from_orco;
-
- /* copies object and modifiers (but not the data) */
- Object *tmpobj;
- BKE_id_copy_ex(NULL, &object_for_eval.id, (ID **)&tmpobj, LIB_ID_COPY_LOCALIZE);
- tmpcu = (Curve *)tmpobj->data;
-
- /* Copy cached display list, it might be needed by the stack evaluation.
- * Ideally stack should be able to use render-time display list, but doing
- * so is quite tricky and not safe so close to the release.
- *
- * TODO(sergey): Look into more proper solution.
- */
- if (object_for_eval.runtime.curve_cache != NULL) {
- if (tmpobj->runtime.curve_cache == NULL) {
- tmpobj->runtime.curve_cache = MEM_callocN(sizeof(CurveCache),
- "CurveCache for curve types");
- }
- BKE_displist_copy(&tmpobj->runtime.curve_cache->disp,
- &object_for_eval.runtime.curve_cache->disp);
- }
+ /* Make sure texture space is calculated for a copy of curve, it will be used for the final
+ * result. */
+ BKE_curve_texspace_calc(temp_curve);
- /* if getting the original caged mesh, delete object modifiers */
- if (cage) {
- BKE_object_free_modifiers(tmpobj, LIB_ID_CREATE_NO_USER_REFCOUNT);
- }
+ /* Temporarily set edit so we get updates from edit mode, but also because for text datablocks
+ * copying it while in edit mode gives invalid data structures. */
+ temp_curve->editfont = curve->editfont;
+ temp_curve->editnurb = curve->editnurb;
- /* copies the data, but *not* the shapekeys. */
- BKE_id_copy_ex(NULL, object_for_eval.data, (ID **)&copycu, LIB_ID_COPY_LOCALIZE);
- tmpobj->data = copycu;
-
- /* make sure texture space is calculated for a copy of curve,
- * it will be used for the final result.
- */
- BKE_curve_texspace_calc(copycu);
-
- /* temporarily set edit so we get updates from edit mode, but
- * also because for text datablocks copying it while in edit
- * mode gives invalid data structures */
- copycu->editfont = tmpcu->editfont;
- copycu->editnurb = tmpcu->editnurb;
-
- /* get updated display list, and convert to a mesh */
- BKE_displist_make_curveTypes_forRender(
- depsgraph, sce, tmpobj, &dispbase, &me_eval_final, false, NULL);
-
- copycu->editfont = NULL;
- copycu->editnurb = NULL;
-
- tmpobj->runtime.mesh_eval = me_eval_final;
-
- /* convert object type to mesh */
- uv_from_orco = (tmpcu->flag & CU_UV_ORCO) != 0;
- BKE_mesh_from_nurbs_displist(
- bmain, tmpobj, &dispbase, uv_from_orco, tmpcu->id.name + 2, true);
- /* Function above also frees copycu (aka tmpobj->data), make this obvious here. */
- copycu = NULL;
-
- tmpmesh = tmpobj->data;
- id_us_min(
- &tmpmesh->id); /* Gets one user from its creation in BKE_mesh_from_nurbs_displist(). */
-
- BKE_displist_free(&dispbase);
-
- /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked.
- * if it didn't the curve did not have any segments or otherwise
- * would have generated an empty mesh */
- if (tmpobj->type != OB_MESH) {
- BKE_id_free(NULL, tmpobj);
- return NULL;
- }
-
- BKE_id_free(NULL, tmpobj);
+ return temp_object;
+}
- /* XXX The curve to mesh conversion is convoluted...
- * But essentially, BKE_mesh_from_nurbs_displist()
- * already transfers the ownership of materials from the temp copy of the Curve ID to the
- * new Mesh ID, so we do not want to increase materials' usercount later. */
- do_mat_id_data_us = false;
+static void curve_to_mesh_eval_ensure(Object *object)
+{
+ if (object->runtime.curve_cache == NULL) {
+ object->runtime.curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
+ }
+ Curve *curve = (Curve *)object->data;
+ Curve remapped_curve = *curve;
+ Object remapped_object = *object;
+ remapped_object.data = &remapped_curve;
- break;
- }
+ /* Clear all modifiers for the bevel object.
+ *
+ * This is because they can not be reliably evaluated for an original object (at least because
+ * the state of dependencies is not know).
+ *
+ * So we create temporary copy of the object which will use same data as the original bevel, but
+ * will have no modifiers. */
+ Object bevel_object = {NULL};
+ if (remapped_curve.bevobj != NULL) {
+ bevel_object = *remapped_curve.bevobj;
+ BLI_listbase_clear(&bevel_object.modifiers);
+ remapped_curve.bevobj = &bevel_object;
+ }
- case OB_MBALL: {
- /* metaballs don't have modifiers, so just convert to mesh */
- Object *basis_ob = BKE_mball_basis_find(sce, object_input);
- /* todo, re-generatre for render-res */
- /* metaball_polygonize(scene, ob) */
+ /* Same thing for taper. */
+ Object taper_object = {NULL};
+ if (remapped_curve.taperobj != NULL) {
+ taper_object = *remapped_curve.taperobj;
+ BLI_listbase_clear(&taper_object.modifiers);
+ remapped_curve.taperobj = &taper_object;
+ }
- if (basis_ob != object_input) {
- /* Only do basis metaball. */
- return NULL;
- }
+ /* NOTE: We don't have dependency graph or scene here, so we pass NULL. This is all fine since
+ * they are only used for modifier stack, which we have explicitly disabled for all objects.
+ *
+ * TODO(sergey): This is a very fragile logic, but proper solution requires re-writing quite a
+ * bit of internal functions (BKE_mesh_from_nurbs_displist, BKE_mesh_nomain_to_mesh) and also
+ * Mesh From Curve operator.
+ * Brecht says hold off with that. */
+ BKE_displist_make_curveTypes_forRender(NULL,
+ NULL,
+ &remapped_object,
+ &remapped_object.runtime.curve_cache->disp,
+ &remapped_object.runtime.mesh_eval,
+ false,
+ NULL);
+
+ BKE_object_free_curve_cache(&bevel_object);
+ BKE_object_free_curve_cache(&taper_object);
+}
- tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
- /* BKE_mesh_add gives us a user count we don't need */
- id_us_min(&tmpmesh->id);
+static Mesh *mesh_new_from_curve_type_object(Main *bmain, Object *object)
+{
+ Curve *curve = object->data;
+ const bool uv_from_orco = (curve->flag & CU_UV_ORCO) != 0;
- if (render) {
- ListBase disp = {NULL, NULL};
- BKE_displist_make_mball_forRender(depsgraph, sce, &object_for_eval, &disp);
- BKE_mesh_from_metaball(&disp, tmpmesh);
- BKE_displist_free(&disp);
- }
- else {
- ListBase disp = {NULL, NULL};
- if (object_for_eval.runtime.curve_cache) {
- disp = object_for_eval.runtime.curve_cache->disp;
- }
- BKE_mesh_from_metaball(&disp, tmpmesh);
- }
+ Object *temp_object = object_for_curve_to_mesh_create(object);
+ Curve *temp_curve = (Curve *)temp_object->data;
- BKE_mesh_texspace_copy_from_object(tmpmesh, &object_for_eval);
+ /* When input object is an original one, we don't have evaluated curve cache yet, so need to
+ * create it in the temporary object. */
+ if (!DEG_is_evaluated_object(object)) {
+ curve_to_mesh_eval_ensure(temp_object);
+ }
- break;
- }
- case OB_MESH:
- /* copies object and modifiers (but not the data) */
- if (cage) {
- /* copies the data (but *not* the shapekeys). */
- Mesh *mesh = object_for_eval.data;
- BKE_id_copy_ex(bmain, &mesh->id, (ID **)&tmpmesh, 0);
- /* XXX BKE_mesh_copy() already handles materials usercount. */
- do_mat_id_data_us = false;
- }
- /* if not getting the original caged mesh, get final derived mesh */
- else {
- /* Make a dummy mesh, saves copying */
- Mesh *me_eval;
- CustomData_MeshMasks mask = CD_MASK_MESH; /* this seems more suitable, exporter,
- * for example, needs CD_MASK_MDEFORMVERT */
+ /* Reset pointers before conversion. */
+ temp_curve->editfont = NULL;
+ temp_curve->editnurb = NULL;
+
+ /* Convert to mesh. */
+ BKE_mesh_from_nurbs_displist(bmain,
+ temp_object,
+ &temp_object->runtime.curve_cache->disp,
+ uv_from_orco,
+ curve->id.name + 2,
+ true);
+
+ /* BKE_mesh_from_nurbs changes the type to a mesh, check it worked. If it didn't the curve did
+ * not have any segments or otherwise would have generated an empty mesh. */
+ if (temp_object->type != OB_MESH) {
+ BKE_id_free(NULL, temp_object);
+ return NULL;
+ }
- if (calc_undeformed) {
- mask.vmask |= CD_MASK_ORCO;
- }
+ Mesh *mesh_result = temp_object->data;
- if (render) {
- me_eval = mesh_create_eval_final_render(depsgraph, sce, &object_for_eval, &mask);
- }
- else {
- me_eval = mesh_create_eval_final_view(depsgraph, sce, &object_for_eval, &mask);
- }
+ BKE_id_free(NULL, temp_object);
- tmpmesh = BKE_mesh_add(bmain, ((ID *)object_for_eval.data)->name + 2);
- BKE_mesh_nomain_to_mesh(me_eval, tmpmesh, &object_for_eval, &mask, true);
+ /* NOTE: Materials are copied in BKE_mesh_from_nurbs_displist(). */
- /* Copy autosmooth settings from original mesh. */
- Mesh *me = (Mesh *)object_for_eval.data;
- tmpmesh->flag |= (me->flag & ME_AUTOSMOOTH);
- tmpmesh->smoothresh = me->smoothresh;
- }
+ return mesh_result;
+}
- /* BKE_mesh_add/copy gives us a user count we don't need */
- id_us_min(&tmpmesh->id);
+static Mesh *mesh_new_from_mball_object(Main *bmain, Object *object)
+{
+ MetaBall *mball = (MetaBall *)object->data;
- break;
- default:
- /* "Object does not have geometry data") */
- return NULL;
+ /* NOTE: We can only create mesh for a polygonized meta ball. This figures out all original meta
+ * balls and all evaluated child meta balls (since polygonization is only stored in the mother
+ * ball).
+ *
+ * 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);
}
- /* Copy materials to new mesh */
- switch (object_for_eval.type) {
- case OB_SURF:
- case OB_FONT:
- case OB_CURVE:
- tmpmesh->totcol = tmpcu->totcol;
-
- /* free old material list (if it exists) and adjust user counts */
- if (tmpcu->mat) {
- for (i = tmpcu->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
+ Mesh *mesh_result = BKE_mesh_add(bmain, ((ID *)object->data)->name + 2);
+ BKE_mesh_from_metaball(&object->runtime.curve_cache->disp, mesh_result);
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
- break;
+ /* Copy materials. */
+ mesh_result->totcol = mball->totcol;
+ mesh_result->mat = MEM_dupallocN(mball->mat);
+ if (mball->mat != NULL) {
+ for (int i = mball->totcol; i-- > 0;) {
+ mesh_result->mat[i] = give_current_material(object, i + 1);
+ }
+ }
- case OB_MBALL: {
- MetaBall *tmpmb = (MetaBall *)object_for_eval.data;
- tmpmesh->mat = MEM_dupallocN(tmpmb->mat);
- tmpmesh->totcol = tmpmb->totcol;
+ return mesh_result;
+}
- /* free old material list (if it exists) and adjust user counts */
- if (tmpmb->mat) {
- for (i = tmpmb->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
+static Mesh *mesh_new_from_mesh_object(Main *bmain, Object *object)
+{
+ Mesh *mesh_input = object->data;
+ Mesh *mesh_result = NULL;
+ BKE_id_copy_ex(bmain, &mesh_input->id, (ID **)&mesh_result, 0);
+ /* NOTE: Materials should already be copied. */
+ return mesh_result;
+}
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
+Mesh *BKE_mesh_new_from_object(Main *bmain, 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);
+ break;
+ case OB_MBALL:
+ new_mesh = mesh_new_from_mball_object(bmain, object);
break;
- }
-
case OB_MESH:
- if (!cage) {
- Mesh *origmesh = object_for_eval.data;
- tmpmesh->flag = origmesh->flag;
- tmpmesh->mat = MEM_dupallocN(origmesh->mat);
- tmpmesh->totcol = origmesh->totcol;
- tmpmesh->smoothresh = origmesh->smoothresh;
- if (origmesh->mat) {
- for (i = origmesh->totcol; i-- > 0;) {
- /* are we an object material or data based? */
- tmpmesh->mat[i] = give_current_material(object_input, i + 1);
-
- if (((object_for_eval.matbits && object_for_eval.matbits[i]) || do_mat_id_data_us) &&
- tmpmesh->mat[i]) {
- id_us_plus(&tmpmesh->mat[i]->id);
- }
- }
- }
- }
+ new_mesh = mesh_new_from_mesh_object(bmain, object);
break;
- } /* end copy materials */
-
- return tmpmesh;
+ default:
+ /* Object does not have geometry data. */
+ return NULL;
+ }
+ if (new_mesh == NULL) {
+ /* 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);
+ return new_mesh;
}
static void add_shapekey_layers(Mesh *mesh_dest, Mesh *mesh_src)
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index da95db92332..4f26ae27d9c 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -705,10 +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(Depsgraph *depsgraph, Main *bmain, Scene *scene, Object *ob)
+static Mesh *bake_mesh_new_from_object(Main *bmain, Object *object)
{
- bool apply_modifiers = (ob->type != OB_MESH);
- Mesh *me = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob, apply_modifiers, false);
+ Mesh *me = BKE_mesh_new_from_object(bmain, object);
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_split_faces(me, true);
@@ -904,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(depsgraph, bmain, scene, ob_low_eval);
+ me_low = bake_mesh_new_from_object(bmain, ob_low_eval);
/* populate the pixel array with the face data */
if ((is_selected_to_active && (ob_cage == NULL) && is_cage) == false) {
@@ -918,7 +917,7 @@ static int bake(Render *re,
/* prepare cage mesh */
if (ob_cage) {
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_cage_eval);
+ me_cage = bake_mesh_new_from_object(bmain, ob_cage_eval);
if ((me_low->totpoly != me_cage->totpoly) || (me_low->totloop != me_cage->totloop)) {
BKE_report(reports,
RPT_ERROR,
@@ -947,7 +946,7 @@ static int bake(Render *re,
md = md_next;
}
- me_cage = bake_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval);
+ me_cage = bake_mesh_new_from_object(bmain, ob_low_eval);
RE_bake_pixels_populate(me_cage, pixel_array_low, num_pixels, &bake_images, uv_layer);
}
@@ -966,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(depsgraph, bmain, scene, highpoly[i].ob_eval);
+ highpoly[i].me = bake_mesh_new_from_object(bmain, highpoly[i].ob_eval);
/* lowpoly to highpoly transformation matrix */
copy_m4_m4(highpoly[i].obmat, highpoly[i].ob->obmat);
@@ -1089,7 +1088,7 @@ static int bake(Render *re,
}
/* Evaluate modifiers again. */
- me_nores = BKE_mesh_new_from_object(depsgraph, bmain, scene, ob_low_eval, true, false);
+ me_nores = BKE_mesh_new_from_object(bmain, 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,
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
index 06a356dd232..ed553c9583c 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderFileLoader.cpp
@@ -98,10 +98,7 @@ NodeGroup *BlenderFileLoader::Load()
continue;
}
- bool apply_modifiers = false;
- bool calc_undeformed = false;
- Mesh *mesh = BKE_mesh_new_from_object(
- _depsgraph, _re->main, _re->scene, ob, apply_modifiers, calc_undeformed);
+ Mesh *mesh = BKE_mesh_new_from_object(_re->main, ob);
if (mesh) {
insertShapeNode(ob, mesh, ++id);
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 149cd7caf84..97d3d03468b 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -435,6 +435,11 @@ StructRNA *rna_PropertyGroup_refine(PointerRNA *ptr)
return ptr->type;
}
+static ID *rna_ID_evaluated_get(ID *id, struct Depsgraph *depsgraph)
+{
+ return DEG_get_evaluated_id(depsgraph, id);
+}
+
static ID *rna_ID_copy(ID *id, Main *bmain)
{
ID *newid;
@@ -1446,6 +1451,15 @@ static void rna_def_ID(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, "rna_IDPreview_get", NULL, NULL, NULL);
/* functions */
+ func = RNA_def_function(srna, "evaluated_get", "rna_ID_evaluated_get");
+ RNA_def_function_ui_description(
+ func, "Get corresponding evaluated ID from the given dependency graph");
+ parm = RNA_def_pointer(
+ func, "depsgraph", "Depsgraph", "", "Dependency graph to perform lookup in");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+ parm = RNA_def_pointer(func, "id", "ID", "", "New copy of the ID");
+ RNA_def_function_return(func, parm);
+
func = RNA_def_function(srna, "copy", "rna_ID_copy");
RNA_def_function_ui_description(
func, "Create a copy of this data-block (not supported for all data-blocks)");
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 75f8b97b99d..a2ac7cb40ba 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -135,12 +135,6 @@ static PointerRNA rna_Context_main_get(PointerRNA *ptr)
return rna_pointer_inherit_refine(ptr, &RNA_BlendData, CTX_data_main(C));
}
-static PointerRNA rna_Context_depsgraph_get(PointerRNA *ptr)
-{
- bContext *C = (bContext *)ptr->data;
- return rna_pointer_inherit_refine(ptr, &RNA_Depsgraph, CTX_data_depsgraph(C));
-}
-
static PointerRNA rna_Context_scene_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
@@ -204,6 +198,11 @@ static int rna_Context_mode_get(PointerRNA *ptr)
return CTX_data_mode_enum(C);
}
+static struct Depsgraph *rna_Context_evaluated_depsgraph_get(bContext *C)
+{
+ return CTX_data_evaluated_depsgraph(C);
+}
+
#else
void RNA_def_context(BlenderRNA *brna)
@@ -211,6 +210,9 @@ void RNA_def_context(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
srna = RNA_def_struct(brna, "Context", NULL);
RNA_def_struct_ui_text(srna, "Context", "Current windowmanager and data context");
RNA_def_struct_sdna(srna, "bContext");
@@ -267,11 +269,6 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "BlendData");
RNA_def_property_pointer_funcs(prop, "rna_Context_main_get", NULL, NULL, NULL);
- prop = RNA_def_property(srna, "depsgraph", PROP_POINTER, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- RNA_def_property_struct_type(prop, "Depsgraph");
- RNA_def_property_pointer_funcs(prop, "rna_Context_depsgraph_get", NULL, NULL, NULL);
-
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "Scene");
@@ -310,6 +307,16 @@ void RNA_def_context(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_context_mode_items);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_Context_mode_get", NULL, NULL);
+
+ func = RNA_def_function(srna, "evaluated_depsgraph_get", "rna_Context_evaluated_depsgraph_get");
+ RNA_def_function_ui_description(
+ func,
+ "Get the dependency graph for the current scene and view layer, to access to data-blocks "
+ "with animation and modifiers applied. If any data-blocks have been edited, the dependency "
+ "graph will be updated. This invalidates all references to evaluated data-blocks from the "
+ "dependency graph.");
+ parm = RNA_def_pointer(func, "depsgraph", "Depsgraph", "", "Evaluated dependency graph");
+ RNA_def_function_return(func, parm);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c
index 447318da744..08f37de26ee 100644
--- a/source/blender/makesrna/intern/rna_depsgraph.c
+++ b/source/blender/makesrna/intern/rna_depsgraph.c
@@ -41,6 +41,7 @@
# include "BKE_anim.h"
# include "BKE_object.h"
+# include "BKE_scene.h"
# include "DEG_depsgraph_build.h"
# include "DEG_depsgraph_debug.h"
@@ -256,6 +257,11 @@ static void rna_Depsgraph_debug_stats(Depsgraph *depsgraph, char *result)
outer);
}
+static void rna_Depsgraph_update(Depsgraph *depsgraph, Main *bmain)
+{
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
+}
+
/* Iteration over objects, simple version */
static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -636,6 +642,15 @@ static void rna_def_depsgraph(BlenderRNA *brna)
RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0); /* needed for string return value */
RNA_def_function_output(func, parm);
+ /* Updates. */
+
+ func = RNA_def_function(srna, "update", "rna_Depsgraph_update");
+ RNA_def_function_ui_description(
+ func,
+ "Re-evaluate any modified data-blocks, for example for animation or modifiers. "
+ "This invalidates all references to evaluated data-blocks from this dependency graph.");
+ RNA_def_function_flag(func, FUNC_USE_MAIN);
+
/* Queries for original datablockls (the ones depsgraph is built for). */
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index fc0950c1bb0..d93f8c4414b 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -550,10 +550,7 @@ int rna_parameter_size(struct PropertyRNA *parm);
struct Mesh *rna_Main_meshes_new_from_object(struct Main *bmain,
struct ReportList *reports,
- struct Depsgraph *depsgraph,
- struct Object *ob,
- bool apply_modifiers,
- bool calc_undeformed);
+ 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 b21cd3324b8..8f48738a27e 100644
--- a/source/blender/makesrna/intern/rna_main_api.c
+++ b/source/blender/makesrna/intern/rna_main_api.c
@@ -317,16 +317,9 @@ 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,
- Depsgraph *depsgraph,
- Object *ob,
- bool apply_modifiers,
- bool calc_undeformed)
+Mesh *rna_Main_meshes_new_from_object(Main *bmain, ReportList *reports, Object *object)
{
- Scene *sce = DEG_get_evaluated_scene(depsgraph);
-
- switch (ob->type) {
+ switch (object->type) {
case OB_FONT:
case OB_CURVE:
case OB_SURF:
@@ -338,7 +331,7 @@ Mesh *rna_Main_meshes_new_from_object(Main *bmain,
return NULL;
}
- return BKE_mesh_new_from_object(depsgraph, bmain, sce, ob, apply_modifiers, calc_undeformed);
+ return BKE_mesh_new_from_object(bmain, object);
}
static Light *rna_Main_lights_new(Main *bmain, const char *name, int type)
@@ -951,24 +944,13 @@ void RNA_def_main_meshes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "new_from_object", "rna_Main_meshes_new_from_object");
- RNA_def_function_ui_description(func,
- "Add a new mesh created from object with modifiers applied");
+ RNA_def_function_ui_description(
+ func,
+ "Add a new mesh created from given object (undeformed geometry if object is original, and "
+ "final evaluated geometry, with all modifiers etc., if object is evaluated)");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
- parm = RNA_def_pointer(func,
- "depsgraph",
- "Depsgraph",
- "Dependency Graph",
- "Evaluated dependency graph within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
parm = RNA_def_pointer(func, "object", "Object", "", "Object to create mesh from");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func,
- "calc_undeformed",
- false,
- "Calculate Undeformed",
- "Calculate undeformed vertex coordinates");
parm = RNA_def_pointer(func,
"mesh",
"Mesh",
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index c997a82f02d..d94abd4066a 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -375,18 +375,11 @@ static void rna_Object_camera_fit_coords(
}
/* copied from Mesh_getFromObject and adapted to RNA interface */
-/* settings: 0 - preview, 1 - render */
-static Mesh *rna_Object_to_mesh(Object *ob,
- bContext *C,
- ReportList *reports,
- Depsgraph *depsgraph,
- bool apply_modifiers,
- bool calc_undeformed)
+static Mesh *rna_Object_to_mesh(Object *object, bContext *C, ReportList *reports)
{
Main *bmain = CTX_data_main(C);
- return rna_Main_meshes_new_from_object(
- bmain, reports, depsgraph, ob, apply_modifiers, calc_undeformed);
+ return rna_Main_meshes_new_from_object(bmain, reports, object);
}
static PointerRNA rna_Object_shape_key_add(
@@ -882,22 +875,10 @@ 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 with modifiers applied");
+ 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,
- "depsgraph",
- "Depsgraph",
- "Dependency Graph",
- "Evaluated dependency graph within which to evaluate modifiers");
- RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
- parm = RNA_def_boolean(func, "apply_modifiers", 0, "", "Apply modifiers");
- RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
- RNA_def_boolean(func,
- "calc_undeformed",
- false,
- "Calculate Undeformed",
- "Calculate undeformed vertex coordinates");
- parm = RNA_def_pointer(func,
"mesh",
"Mesh",
"",
diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c
index e29891b60db..1d4d2e9cdd9 100644
--- a/source/blender/makesrna/intern/rna_scene_api.c
+++ b/source/blender/makesrna/intern/rna_scene_api.c
@@ -116,23 +116,6 @@ static void rna_Scene_uvedit_aspect(Scene *scene, Object *ob, float *aspect)
aspect[0] = aspect[1] = 1.0f;
}
-static void rna_Scene_update_tagged(Scene *scene, Main *bmain)
-{
-# ifdef WITH_PYTHON
- BPy_BEGIN_ALLOW_THREADS;
-# endif
-
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
- BKE_scene_graph_update_tagged(depsgraph, bmain);
- }
-
-# ifdef WITH_PYTHON
- BPy_END_ALLOW_THREADS;
-# endif
-}
-
static void rna_SceneRender_get_frame_path(
RenderData *rd, Main *bmain, int frame, bool preview, const char *view, char *name)
{
@@ -303,11 +286,6 @@ void RNA_api_scene(StructRNA *srna)
func, "subframe", 0.0, 0.0, 1.0, "", "Sub-frame time, between 0.0 and 1.0", 0.0, 1.0);
RNA_def_function_flag(func, FUNC_USE_MAIN);
- func = RNA_def_function(srna, "update", "rna_Scene_update_tagged");
- RNA_def_function_ui_description(
- func, "Update data tagged to be updated from previous access to data or operators");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
-
func = RNA_def_function(srna, "uvedit_aspect", "rna_Scene_uvedit_aspect");
RNA_def_function_ui_description(func, "Get uv aspect for current object");
parm = RNA_def_pointer(func, "object", "Object", "", "Object");