Merge branch 'master' into blender2.8
[blender.git] / source / blender / depsgraph / intern / eval / deg_eval_flush.cc
index daf008ddb7dc63344e25a1365022edc45f23a0b0..74c3cd28455fac68b486dc4ad99df7412c925877 100644 (file)
@@ -51,6 +51,7 @@ extern "C" {
 #include "intern/nodes/deg_node_operation.h"
 
 #include "intern/depsgraph_intern.h"
 #include "intern/nodes/deg_node_operation.h"
 
 #include "intern/depsgraph_intern.h"
+#include "intern/eval/deg_eval_copy_on_write.h"
 #include "util/deg_util_foreach.h"
 
 namespace DEG {
 #include "util/deg_util_foreach.h"
 
 namespace DEG {
@@ -70,19 +71,6 @@ typedef std::deque<OperationDepsNode *> FlushQueue;
 
 namespace {
 
 
 namespace {
 
-// TODO(sergey): De-duplicate with depsgraph_tag,cc
-void lib_id_recalc_tag(Main *bmain, ID *id)
-{
-       id->recalc |= ID_RECALC;
-       DEG_id_type_tag(bmain, GS(id->name));
-}
-
-void lib_id_recalc_data_tag(Main *bmain, ID *id)
-{
-       id->recalc |= ID_RECALC_DATA;
-       DEG_id_type_tag(bmain, GS(id->name));
-}
-
 void flush_init_operation_node_func(
         void *__restrict data_v,
         const int i,
 void flush_init_operation_node_func(
         void *__restrict data_v,
         const int i,
@@ -146,9 +134,10 @@ BLI_INLINE void flush_handle_id_node(IDDepsNode *id_node)
 }
 
 /* TODO(sergey): We can reduce number of arguments here. */
 }
 
 /* TODO(sergey): We can reduce number of arguments here. */
-BLI_INLINE void flush_handle_component_node(Depsgraph * /*graph*/,
+BLI_INLINE void flush_handle_component_node(Depsgraph *graph,
                                             IDDepsNode *id_node,
                                             ComponentDepsNode *comp_node,
                                             IDDepsNode *id_node,
                                             ComponentDepsNode *comp_node,
+                                            bool use_copy_on_write,
                                             FlushQueue *queue)
 {
        /* We only handle component once. */
                                             FlushQueue *queue)
 {
        /* We only handle component once. */
@@ -156,46 +145,27 @@ BLI_INLINE void flush_handle_component_node(Depsgraph * /*graph*/,
                return;
        }
        comp_node->done = COMPONENT_STATE_DONE;
                return;
        }
        comp_node->done = COMPONENT_STATE_DONE;
+       /* Currently this is needed to get object->mesh to be replaced with
+        * original mesh (rather than being evaluated_mesh).
+        *
+        * TODO(sergey): This is something we need to avoid.
+        */
+       if (use_copy_on_write && comp_node->depends_on_cow()) {
+               ComponentDepsNode *cow_comp =
+                       id_node->find_component(DEG_NODE_TYPE_COPY_ON_WRITE);
+               cow_comp->tag_update(graph);
+       }
        /* Tag all required operations in component for update.  */
        foreach (OperationDepsNode *op, comp_node->operations) {
        /* Tag all required operations in component for update.  */
        foreach (OperationDepsNode *op, comp_node->operations) {
-               op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
-       }
-       if (GS(id_node->id->name) == ID_OB) {
-               Object *object = (Object *)id_node->id;
-               /* This code is used to preserve those areas which does
-                * direct object update,
+               /* We don't want to flush tags in "upstream" direction for
+                * certain types of operations.
                 *
                 *
-                * Plus it ensures visibility changes and relations and
-                * layers visibility update has proper flags to work with.
+                * TODO(sergey): Need a more generic solution for this.
                 */
                 */
-               switch (comp_node->type) {
-                       case DEG_NODE_TYPE_UNDEFINED:
-                       case DEG_NODE_TYPE_OPERATION:
-                       case DEG_NODE_TYPE_TIMESOURCE:
-                       case DEG_NODE_TYPE_ID_REF:
-                       case DEG_NODE_TYPE_SEQUENCER:
-                       case NUM_DEG_NODE_TYPES:
-                               /* Ignore, does not translate to object component. */
-                               BLI_assert(!"This should never happen!");
-                               break;
-                       case DEG_NODE_TYPE_ANIMATION:
-                               object->recalc |= OB_RECALC_TIME;
-                               break;
-                       case DEG_NODE_TYPE_TRANSFORM:
-                               object->recalc |= OB_RECALC_OB;
-                               break;
-                       case DEG_NODE_TYPE_GEOMETRY:
-                       case DEG_NODE_TYPE_EVAL_POSE:
-                       case DEG_NODE_TYPE_BONE:
-                       case DEG_NODE_TYPE_EVAL_PARTICLES:
-                       case DEG_NODE_TYPE_SHADING:
-                       case DEG_NODE_TYPE_CACHE:
-                       case DEG_NODE_TYPE_PROXY:
-                               object->recalc |= OB_RECALC_DATA;
-                               break;
-                       case DEG_NODE_TYPE_PARAMETERS:
-                               break;
+               if (op->opcode == DEG_OPCODE_PARTICLE_SETTINGS_EVAL) {
+                       continue;
                }
                }
+               op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
        }
        /* When some target changes bone, we might need to re-run the
         * whole IK solver, otherwise result might be unpredictable.
        }
        /* When some target changes bone, we might need to re-run the
         * whole IK solver, otherwise result might be unpredictable.
@@ -237,19 +207,41 @@ BLI_INLINE OperationDepsNode *flush_schedule_children(
        return result;
 }
 
        return result;
 }
 
+/* NOTE: It will also accumulate flags from changed components. */
 BLI_INLINE void flush_editors_id_update(Main *bmain,
 BLI_INLINE void flush_editors_id_update(Main *bmain,
-                                        Depsgraph *graph)
+                                        Depsgraph *graph,
+                                        const DEGEditorUpdateContext *update_ctx)
 {
        foreach (IDDepsNode *id_node, graph->id_nodes) {
                if (id_node->done != ID_STATE_MODIFIED) {
                        continue;
                }
 {
        foreach (IDDepsNode *id_node, graph->id_nodes) {
                if (id_node->done != ID_STATE_MODIFIED) {
                        continue;
                }
+               DEG_id_type_tag(bmain, GS(id_node->id_orig->name));
                /* TODO(sergey): Do we need to pass original or evaluated ID here? */
                /* TODO(sergey): Do we need to pass original or evaluated ID here? */
-               ID *id = id_node->id;
-               deg_editors_id_update(bmain, id);
-               lib_id_recalc_tag(bmain, id);
-               /* TODO(sergey): For until we've got proper data nodes in the graph. */
-               lib_id_recalc_data_tag(bmain, id);
+               ID *id_orig = id_node->id_orig;
+               ID *id_cow = id_node->id_cow;
+               /* Copy tag from original data to CoW storage.
+                * This is because DEG_id_tag_update() sets tags on original
+                * data.
+                */
+               id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL);
+               /* Gather recalc flags from all changed components. */
+               GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+               {
+                       if (comp_node->done != COMPONENT_STATE_DONE) {
+                               continue;
+                       }
+                       DepsNodeFactory *factory = deg_type_get_factory(comp_node->type);
+                       BLI_assert(factory != NULL);
+                       id_cow->recalc |= factory->id_recalc_tag();
+               }
+               GHASH_FOREACH_END();
+               DEG_DEBUG_PRINTF("Accumulated recalc bits for %s: %u\n",
+                                id_orig->name, (unsigned int)id_cow->recalc);
+               /* Inform editors. */
+               if (deg_copy_on_write_is_expanded(id_cow)) {
+                       deg_editors_id_update(update_ctx, id_cow);
+               }
        }
 }
 
        }
 }
 
@@ -260,6 +252,7 @@ BLI_INLINE void flush_editors_id_update(Main *bmain,
  */
 void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
 {
  */
 void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
 {
+       const bool use_copy_on_write = DEG_depsgraph_use_copy_on_write();
        /* Sanity checks. */
        BLI_assert(bmain != NULL);
        BLI_assert(graph != NULL);
        /* Sanity checks. */
        BLI_assert(bmain != NULL);
        BLI_assert(graph != NULL);
@@ -272,6 +265,11 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
        /* Starting from the tagged "entry" nodes, flush outwards. */
        FlushQueue queue;
        flush_schedule_entrypoints(graph, &queue);
        /* Starting from the tagged "entry" nodes, flush outwards. */
        FlushQueue queue;
        flush_schedule_entrypoints(graph, &queue);
+       /* Prepare update context for editors. */
+       DEGEditorUpdateContext update_ctx;
+       update_ctx.bmain = bmain;
+       update_ctx.scene = graph->scene;
+       update_ctx.view_layer = graph->view_layer;
        /* Do actual flush. */
        while (!queue.empty()) {
                OperationDepsNode *op_node = queue.front();
        /* Do actual flush. */
        while (!queue.empty()) {
                OperationDepsNode *op_node = queue.front();
@@ -286,13 +284,14 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
                        flush_handle_component_node(graph,
                                                    id_node,
                                                    comp_node,
                        flush_handle_component_node(graph,
                                                    id_node,
                                                    comp_node,
+                                                   use_copy_on_write,
                                                    &queue);
                        /* Flush to nodes along links. */
                        op_node = flush_schedule_children(op_node, &queue);
                }
        }
        /* Inform editors about all changes. */
                                                    &queue);
                        /* Flush to nodes along links. */
                        op_node = flush_schedule_children(op_node, &queue);
                }
        }
        /* Inform editors about all changes. */
-       flush_editors_id_update(bmain, graph);
+       flush_editors_id_update(bmain, graph, &update_ctx);
 }
 
 static void graph_clear_func(
 }
 
 static void graph_clear_func(