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:
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.1.py60
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.2.py45
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.3.py42
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.4.py62
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.5.py61
-rw-r--r--intern/cycles/blender/addon/__init__.py8
-rw-r--r--intern/cycles/blender/blender_util.h8
-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
-rw-r--r--tests/python/bl_alembic_import_test.py24
21 files changed, 568 insertions, 383 deletions
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.1.py b/doc/python_api/examples/bpy.types.Depsgraph.1.py
new file mode 100644
index 00000000000..d972c076c97
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.1.py
@@ -0,0 +1,60 @@
+"""
+Dependency graph: Evaluated ID example
+++++++++++++++++++++++++++++++++++++++
+
+This example demonstrates access to the evaluated ID (such as object, material, etc.) state from
+an original ID.
+This is needed every time one needs to access state with animation, constraints, and modifiers
+taken into account.
+"""
+import bpy
+
+
+class OBJECT_OT_evaluated_example(bpy.types.Operator):
+ """Access evaluated object state and do something with it"""
+ bl_label = "DEG Access Evaluated Object"
+ bl_idname = "object.evaluated_example"
+
+ def execute(self, context):
+ # This is an original object. Its data does not have any modifiers applied.
+ object = context.object
+ if object is None or object.type != 'MESH':
+ self.report({'INFO'}, "No active mesh object to get info from")
+ return {'CANCELLED'}
+ # Evaluated object exists within a specific dependency graph.
+ # We will request evaluated object from the dependency graph which corresponds to the
+ # current scene and view layer.
+ #
+ # NOTE: This call ensure the dependency graph is fully evaluated. This might be expensive
+ # if changes were made made to the scene, but is needed to ensure no dangling or incorrect
+ # pointers are exposed.
+ depsgraph = context.evaluated_depsgraph_get()
+ # Actually request evaluated object.
+ #
+ # This object has animation and drivers applied on it, together with constraints and
+ # modifiers.
+ #
+ # For mesh objects the object.data will be a mesh with all modifiers applied.
+ # This means that in access to vertices or faces after modifier stack happens via fields of
+ # object_eval.object.
+ #
+ # For other types of objects the object_eval.data does not have modifiers applied on it,
+ # but has animation applied.
+ #
+ # NOTE: All ID types have `evaluated_get()`, including materials, node trees, worlds.
+ object_eval = object.evaluated_get(depsgraph)
+ mesh_eval = object_eval.data
+ self.report({'INFO'}, f"Number of evaluated vertices: {len(mesh_eval.vertices)}")
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_evaluated_example)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_evaluated_example)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.2.py b/doc/python_api/examples/bpy.types.Depsgraph.2.py
new file mode 100644
index 00000000000..8639ffc0267
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.2.py
@@ -0,0 +1,45 @@
+"""
+Dependency graph: Original object example
++++++++++++++++++++++++++++++++++++++++++
+
+This example demonstrates access to the original ID.
+Such access is needed to check whether object is selected, or to compare pointers.
+"""
+import bpy
+
+
+class OBJECT_OT_original_example(bpy.types.Operator):
+ """Access original object and do something with it"""
+ bl_label = "DEG Access Original Object"
+ bl_idname = "object.original_example"
+
+ def check_object_selected(self, object_eval):
+ # Selection depends on a context and is only valid for original objects. This means we need
+ # to request the original object from the known evaluated one.
+ #
+ # NOTE: All ID types have an `original` field.
+ object = object_eval.original
+ return object.select_get()
+
+ def execute(self, context):
+ # NOTE: It seems redundant to iterate over original objects to request evaluated ones
+ # just to get original back. But we want to keep example as short as possible, but in real
+ # world there are cases when evaluated object is coming from a more meaningful source.
+ depsgraph = context.evaluated_depsgraph_get()
+ for object in context.editable_objects:
+ object_eval = object.evaluated_get(depsgraph)
+ if self.check_object_selected(object_eval):
+ self.report({'INFO'}, f"Object is selected: {object_eval.name}")
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_original_example)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_original_example)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.3.py b/doc/python_api/examples/bpy.types.Depsgraph.3.py
new file mode 100644
index 00000000000..25411597dd3
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.3.py
@@ -0,0 +1,42 @@
+"""
+Dependency graph: Iterate over all object instances
++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+Sometimes it is needed to know all the instances with their matrices (for example, when writing an
+exporter or a custom render engine).
+This example shows how to access all objects and instances in the scene.
+"""
+import bpy
+
+
+class OBJECT_OT_object_instances(bpy.types.Operator):
+ """Access original object and do something with it"""
+ bl_label = "DEG Iterate Object Instances"
+ bl_idname = "object.object_instances"
+
+ def execute(self, context):
+ depsgraph = context.evaluated_depsgraph_get()
+ for object_instance in depsgraph.object_instances:
+ # This is an object which is being instanced.
+ object = object_instance.object
+ # `is_instance` denotes whether the object is coming from instances (as an opposite of
+ # being an emitting object. )
+ if not object_instance.is_instance:
+ print(f"Object {object.name} at {object_instance.matrix_world}")
+ else:
+ # Instanced will additionally have fields like uv, random_id and others which are
+ # specific for instances. See Python API for DepsgraphObjectInstance for details,
+ print(f"Instance of {object.name} at {object_instance.matrix_world}")
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_object_instances)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_object_instances)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.4.py b/doc/python_api/examples/bpy.types.Depsgraph.4.py
new file mode 100644
index 00000000000..5c7b76edab6
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.4.py
@@ -0,0 +1,62 @@
+"""
+Dependency graph: Object.to_mesh()
++++++++++++++++++++++++++++++++++++
+
+Object.to_mesh() (and bpy.data.meshes.new_from_object()) are closely interacting with dependency
+graph: their behavior depends on whether they are used on original or evaluated object.
+
+When is used on original object, the result mesh is calculated from the object without taking
+animation or modifiers into account:
+
+- For meshes this is similar to duplicating the source mesh.
+- For curves this disables own modifiers, and modifiers of objects used as bevel and taper.
+- For metaballs this produces an empty mesh since polygonization is done as a modifier evaluation.
+
+When is used on evaluated object all modifiers are taken into account.
+
+.. note:: The result mesh is added to the main database.
+.. note:: If object does not have geometry (i.e. camera) the functions returns None.
+"""
+import bpy
+
+
+class OBJECT_OT_object_to_mesh(bpy.types.Operator):
+ """Convert selected object to mesh and show number of vertices"""
+ bl_label = "DEG Object to Mesh"
+ bl_idname = "object.object_to_mesh"
+
+ def execute(self, context):
+ # Access input original object.
+ object = context.object
+ if object is None:
+ self.report({'INFO'}, "No active mesh object to convert to mesh")
+ return {'CANCELLED'}
+ # Avoid annoying None checks later on.
+ if object.type not in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META'}:
+ self.report({'INFO'}, "Object can not be converted to mesh")
+ return {'CANCELLED'}
+ depsgraph = context.evaluated_depsgraph_get()
+ # Invoke to_mesh() for original object.
+ mesh_from_orig = object.to_mesh()
+ self.report({'INFO'}, f"{len(mesh_from_orig.vertices)} in new mesh without modifiers.")
+ # Remove temporary mesh.
+ bpy.data.meshes.remove(mesh_from_orig)
+ # Invoke to_mesh() for evaluated object.
+ object_eval = object.evaluated_get(depsgraph)
+ mesh_from_eval = object_eval.to_mesh()
+ self.report({'INFO'}, f"{len(mesh_from_eval.vertices)} in new mesh with modifiers.")
+ # Remove temporary mesh.
+ bpy.data.meshes.remove(mesh_from_eval)
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_object_to_mesh)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_object_to_mesh)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.5.py b/doc/python_api/examples/bpy.types.Depsgraph.5.py
new file mode 100644
index 00000000000..781d0202931
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.5.py
@@ -0,0 +1,61 @@
+"""
+Dependency graph: Simple exporter
++++++++++++++++++++++++++++++++++
+
+This example is a combination of all previous ones, and shows how to write a simple exporter
+script.
+"""
+import bpy
+
+
+class OBJECT_OT_simple_exporter(bpy.types.Operator):
+ """Simple (fake) exporter of selected objects"""
+ bl_label = "DEG Export Selected"
+ bl_idname = "object.simple_exporter"
+
+ apply_modifiers: bpy.props.BoolProperty(name="Apply Modifiers")
+
+ def execute(self, context):
+ depsgraph = context.evaluated_depsgraph_get()
+ for object_instance in depsgraph.object_instances:
+ if not self.is_object_instance_from_selected(object_instance):
+ # We only export selected objects
+ continue
+ # NOTE: This will create a mesh for every instance, which is not ideal at all. In
+ # reality destination format will support some sort of instancing mechanism, so the
+ # code here will simply say "instance this object at object_instance.matrix_world".
+ mesh = self.create_mesh_for_object_instance(object_instance)
+ if mesh is None:
+ # Happens for non-geometry objects.
+ continue
+ print(f"Exporting mesh with {len(mesh.vertices)} vertices "
+ f"at {object_instance.matrix_world}")
+ bpy.data.meshes.remove(mesh)
+
+ return {'FINISHED'}
+
+ def is_object_instance_from_selected(self, object_instance):
+ # For instanced objects we check selection of their instancer (more accurately: check
+ # selection status of the original object corresponding to the instancer).
+ if object_instance.parent:
+ return object_instance.parent.original.select_get()
+ # For non-instanced objects we check selection state of the original object.
+ return object_instance.object.original.select_get()
+
+ def create_mesh_for_object_instance(self, object_instance):
+ if self.apply_modifiers:
+ return object_instance.object.to_mesh()
+ else:
+ return object_instance.object.original.to_mesh()
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_simple_exporter)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_simple_exporter)
+
+
+if __name__ == "__main__":
+ register()
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py
index 93a1271b4b4..a8e7428a50f 100644
--- a/intern/cycles/blender/addon/__init__.py
+++ b/intern/cycles/blender/addon/__init__.py
@@ -88,15 +88,17 @@ class CyclesRender(bpy.types.RenderEngine):
# viewport render
def view_update(self, context):
+ depsgraph = context.evaluated_depsgraph_get()
if not self.session:
engine.create(self, context.blend_data,
context.region, context.space_data, context.region_data)
- engine.reset(self, context.blend_data, context.depsgraph)
- engine.sync(self, context.depsgraph, context.blend_data)
+ engine.reset(self, context.blend_data, depsgraph)
+ engine.sync(self, depsgraph, context.blend_data)
def view_draw(self, context):
- engine.draw(self, context.depsgraph, context.region, context.space_data, context.region_data)
+ depsgraph = context.evaluated_depsgraph_get()
+ engine.draw(self, depsgraph, context.region, context.space_data, context.region_data)
def update_script_node(self, node):
if engine.with_osl():
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index 500634e7526..2a964d0e4d0 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -45,8 +45,8 @@ void python_thread_state_restore(void **python_thread_state);
static inline BL::Mesh object_to_mesh(BL::BlendData &data,
BL::Object &object,
- BL::Depsgraph &depsgraph,
- bool calc_undeformed,
+ BL::Depsgraph & /*depsgraph*/,
+ bool /*calc_undeformed*/,
Mesh::SubdivisionType subdivision_type)
{
/* TODO: make this work with copy-on-write, modifiers are already evaluated. */
@@ -75,11 +75,11 @@ static inline BL::Mesh object_to_mesh(BL::BlendData &data,
* UV are not empty. */
if (mesh.is_editmode() ||
(mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) {
- mesh = data.meshes.new_from_object(depsgraph, object, false, false);
+ mesh = data.meshes.new_from_object(object);
}
}
else {
- mesh = data.meshes.new_from_object(depsgraph, object, true, calc_undeformed);
+ mesh = data.meshes.new_from_object(object);
}
#if 0
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");
diff --git a/tests/python/bl_alembic_import_test.py b/tests/python/bl_alembic_import_test.py
index 2cde6d57a7f..63624270bd8 100644
--- a/tests/python/bl_alembic_import_test.py
+++ b/tests/python/bl_alembic_import_test.py
@@ -92,8 +92,10 @@ class SimpleImportTest(AbstractAlembicTest):
# translates to "no parent" in Blender.
self.assertIsNone(objects['locator2'].parent)
+ depsgraph = bpy.context.evaluated_depsgraph_get()
+
# Shouldn't have inherited the ABC parent's transform.
- loc2 = bpy.context.depsgraph.id_eval_get(objects['locator2'])
+ loc2 = depsgraph.id_eval_get(objects['locator2'])
x, y, z = objects['locator2'].matrix_world.to_translation()
self.assertAlmostEqual(0, x)
self.assertAlmostEqual(0, y)
@@ -103,7 +105,7 @@ class SimpleImportTest(AbstractAlembicTest):
self.assertEqual(objects['locator2'], objects['locatorShape2'].parent)
# Should have inherited its ABC parent's transform.
- locshp2 = bpy.context.depsgraph.id_eval_get(objects['locatorShape2'])
+ locshp2 = depsgraph.id_eval_get(objects['locatorShape2'])
x, y, z = locshp2.matrix_world.to_translation()
self.assertAlmostEqual(0, x)
self.assertAlmostEqual(0, y)
@@ -142,9 +144,11 @@ class SimpleImportTest(AbstractAlembicTest):
self.assertEqual({'FINISHED'}, res)
cube = bpy.context.active_object
+ depsgraph = bpy.context.evaluated_depsgraph_get()
+
# Check that the file loaded ok.
bpy.context.scene.frame_set(10)
- cube = bpy.context.depsgraph.id_eval_get(cube)
+ cube = depsgraph.id_eval_get(cube)
x, y, z = cube.matrix_world.to_euler('XYZ')
self.assertAlmostEqual(x, 0)
self.assertAlmostEqual(y, 0)
@@ -155,7 +159,7 @@ class SimpleImportTest(AbstractAlembicTest):
bpy.data.cache_files[fname].filepath = relpath
bpy.context.scene.frame_set(10)
- cube = bpy.context.depsgraph.id_eval_get(cube)
+ cube = depsgraph.id_eval_get(cube)
x, y, z = cube.matrix_world.to_euler('XYZ')
self.assertAlmostEqual(x, 0)
self.assertAlmostEqual(y, 0)
@@ -163,9 +167,9 @@ class SimpleImportTest(AbstractAlembicTest):
# Replace the Alembic file; this should apply new animation.
bpy.data.cache_files[fname].filepath = relpath.replace('1.abc', '2.abc')
- bpy.context.scene.update()
+ depsgraph.update()
- cube = bpy.context.depsgraph.id_eval_get(cube)
+ cube = depsgraph.id_eval_get(cube)
x, y, z = cube.matrix_world.to_euler('XYZ')
self.assertAlmostEqual(x, math.pi / 2, places=5)
self.assertAlmostEqual(y, 0)
@@ -180,10 +184,13 @@ class SimpleImportTest(AbstractAlembicTest):
self.assertEqual({'FINISHED'}, res)
plane = bpy.context.active_object
+ depsgraph = bpy.context.evaluated_depsgraph_get()
+
# Check that the file loaded ok.
bpy.context.scene.frame_set(6)
scene = bpy.context.scene
- mesh = plane.to_mesh(bpy.context.depsgraph, apply_modifiers=True, calc_undeformed=False)
+ plane_eval = plane.evaluated_get(depsgraph)
+ mesh = plane_eval.to_mesh()
self.assertAlmostEqual(-1, mesh.vertices[0].co.x)
self.assertAlmostEqual(-1, mesh.vertices[0].co.y)
self.assertAlmostEqual(0.5905638933181763, mesh.vertices[0].co.z)
@@ -193,7 +200,8 @@ class SimpleImportTest(AbstractAlembicTest):
bpy.data.cache_files[fname].filepath = relpath
scene.frame_set(6)
- mesh = plane.to_mesh(bpy.context.depsgraph, apply_modifiers=True, calc_undeformed=False)
+ plane_eval = plane.evaluated_get(depsgraph)
+ mesh = plane_eval.to_mesh()
self.assertAlmostEqual(1, mesh.vertices[3].co.x)
self.assertAlmostEqual(1, mesh.vertices[3].co.y)
self.assertAlmostEqual(0.5905638933181763, mesh.vertices[3].co.z)