Merge branch 'master' into blender2.8
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations.cc
index f44d8f2c02972a9482d33f4cce0377b450f69d83..077bdd94f562f5d73815d5241663dbc67d813848 100644 (file)
@@ -61,6 +61,7 @@ extern "C" {
 #include "DNA_movieclip_types.h"
 #include "DNA_node_types.h"
 #include "DNA_particle_types.h"
+#include "DNA_lightprobe_types.h"
 #include "DNA_object_types.h"
 #include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
@@ -103,7 +104,9 @@ extern "C" {
 
 #include "intern/nodes/deg_node.h"
 #include "intern/nodes/deg_node_component.h"
+#include "intern/nodes/deg_node_id.h"
 #include "intern/nodes/deg_node_operation.h"
+#include "intern/nodes/deg_node_time.h"
 
 #include "intern/depsgraph_intern.h"
 #include "intern/depsgraph_types.h"
@@ -125,7 +128,7 @@ void modifier_walk(void *user_data,
 {
        BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
        if (*obpoin) {
-               data->builder->build_object(*obpoin);
+               data->builder->build_object(NULL, *obpoin);
        }
 }
 
@@ -138,7 +141,7 @@ void constraint_walk(bConstraint * /*con*/,
        if (*idpoin) {
                ID *id = *idpoin;
                if (GS(id->name) == ID_OB) {
-                       data->builder->build_object((Object *)id);
+                       data->builder->build_object(NULL, (Object *)id);
                }
        }
 }
@@ -309,19 +312,16 @@ void DepsgraphRelationBuilder::add_collision_relations(
         Scene *scene,
         Object *object,
         Group *group,
-        int layer,
         bool dupli,
         const char *name)
 {
        unsigned int numcollobj;
-       Object **collobjs = get_collisionobjects_ext(
-               scene,
-               object,
-               group,
-               layer,
-               &numcollobj,
-               eModifierType_Collision,
-               dupli);
+       Object **collobjs = get_collisionobjects_ext(scene,
+                                                    object,
+                                                    group,
+                                                    &numcollobj,
+                                                    eModifierType_Collision,
+                                                    dupli);
        for (unsigned int i = 0; i < numcollobj; i++) {
                Object *ob1 = collobjs[i];
 
@@ -345,7 +345,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
         bool add_absorption,
         const char *name)
 {
-       ListBase *effectors = pdInitEffectors(scene, object, psys, eff, false);
+       ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false);
        if (effectors != NULL) {
                LINKLIST_FOREACH(EffectorCache *, eff, effectors) {
                        if (eff->ob != object) {
@@ -385,7 +385,6 @@ void DepsgraphRelationBuilder::add_forcefield_relations(
                                                        scene,
                                                        object,
                                                        NULL,
-                                                       eff->ob->lay,
                                                        true,
                                                        "Force Absorption");
                        }
@@ -417,7 +416,7 @@ void DepsgraphRelationBuilder::begin_build()
                        nodetree->id.tag &= ~LIB_TAG_DOIT;
                }
        }
-       FOREACH_NODETREE_END;
+       FOREACH_NODETREE_END
 }
 
 void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
@@ -427,19 +426,26 @@ void DepsgraphRelationBuilder::build_group(Object *object, Group *group)
        OperationKey object_local_transform_key(&object->id,
                                                DEG_NODE_TYPE_TRANSFORM,
                                                DEG_OPCODE_TRANSFORM_LOCAL);
-       LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
-               if (!group_done) {
-                       build_object(go->ob);
+
+       if (!group_done) {
+               LINKLIST_FOREACH(Base *, base, &group->view_layer->object_bases) {
+                       build_object(NULL, base->object);
                }
-               ComponentKey dupli_transform_key(&go->ob->id, DEG_NODE_TYPE_TRANSFORM);
+               group_id->tag |= LIB_TAG_DOIT;
+       }
+
+       LINKLIST_FOREACH (Base *, base, &group->view_layer->object_bases) {
+               ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM);
                add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup");
        }
-       group_id->tag |= LIB_TAG_DOIT;
 }
 
-void DepsgraphRelationBuilder::build_object(Object *object)
+void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
 {
        if (object->id.tag & LIB_TAG_DOIT) {
+               if (base != NULL) {
+                       build_object_flags(base, object);
+               }
                return;
        }
        object->id.tag |= LIB_TAG_DOIT;
@@ -459,6 +465,8 @@ void DepsgraphRelationBuilder::build_object(Object *object)
        OperationKey ob_ubereval_key(&object->id,
                                     DEG_NODE_TYPE_TRANSFORM,
                                     DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
+       /* Various flags, flushing from bases/collections. */
+       build_object_flags(base, object);
        /* Parenting. */
        if (object->parent != NULL) {
                /* Parent relationship. */
@@ -526,7 +534,7 @@ void DepsgraphRelationBuilder::build_object(Object *object)
        /* Object that this is a proxy for. */
        if (object->proxy != NULL) {
                object->proxy->proxy_from = object;
-               build_object(object->proxy);
+               build_object(NULL, object->proxy);
                /* TODO(sergey): This is an inverted relation, matches old depsgraph
                 * behavior and need to be investigated if it still need to be inverted.
                 */
@@ -540,6 +548,20 @@ void DepsgraphRelationBuilder::build_object(Object *object)
        }
 }
 
+void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
+{
+       if (base == NULL) {
+               return;
+       }
+       OperationKey view_layer_done_key(&scene_->id,
+                                        DEG_NODE_TYPE_LAYER_COLLECTIONS,
+                                        DEG_OPCODE_VIEW_LAYER_DONE);
+       OperationKey object_flags_key(&object->id,
+                                     DEG_NODE_TYPE_LAYER_COLLECTIONS,
+                                     DEG_OPCODE_OBJECT_BASE_FLAGS);
+       add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
+}
+
 void DepsgraphRelationBuilder::build_object_data(Object *object)
 {
        if (object->data == NULL) {
@@ -574,6 +596,9 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
                case OB_CAMERA:
                        build_camera(object);
                        break;
+               case OB_LIGHTPROBE:
+                       build_lightprobe(object);
+                       break;
        }
        Key *key = BKE_key_from_object(object);
        if (key != NULL) {
@@ -898,7 +923,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
        /* Animation curves and NLA. */
        build_animdata_curves(id);
        /* Drivers. */
-       build_animdata_drievrs(id);
+       build_animdata_drivers(id);
 }
 
 void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
@@ -967,7 +992,7 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
        }
 }
 
-void DepsgraphRelationBuilder::build_animdata_drievrs(ID *id)
+void DepsgraphRelationBuilder::build_animdata_drivers(ID *id)
 {
        AnimData *adt = BKE_animdata_from_id(id);
        if (adt == NULL) {
@@ -1078,18 +1103,18 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
                 */
                IDDepsNode *arm_node = graph_->find_id_node(id);
                char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
-               if (arm_node && bone_name) {
+               if (arm_node != NULL && bone_name != NULL) {
                        /* Find objects which use this, and make their eval callbacks
                         * depend on this.
                         */
                        foreach (DepsRelation *rel, arm_node->outlinks) {
                                IDDepsNode *to_node = (IDDepsNode *)rel->to;
                                /* We only care about objects with pose data which use this. */
-                               if (GS(to_node->id->name) == ID_OB) {
-                                       Object *object = (Object *)to_node->id;
-                                       /* NOTE: object->pose may be NULL. */
-                                       bPoseChannel *pchan = BKE_pose_channel_find_name(
-                                               object->pose, bone_name);
+                               if (GS(to_node->id_orig->name) == ID_OB) {
+                                       Object *object = (Object *)to_node->id_orig;
+                                       // NOTE: object->pose may be NULL
+                                       bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose,
+                                                                                        bone_name);
                                        if (pchan != NULL) {
                                                OperationKey bone_key(&object->id,
                                                                      DEG_NODE_TYPE_BONE,
@@ -1148,9 +1173,9 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
                                        continue;
                                }
                                OperationKey variable_key(dtar->id,
-                                                       DEG_NODE_TYPE_BONE,
-                                                       target_pchan->name,
-                                                       DEG_OPCODE_BONE_DONE);
+                                                         DEG_NODE_TYPE_BONE,
+                                                         target_pchan->name,
+                                                         DEG_OPCODE_BONE_DONE);
                                if (is_same_bone_dependency(variable_key, self_key)) {
                                        continue;
                                }
@@ -1175,10 +1200,13 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
                                if (RNA_pointer_is_null(&variable_key.ptr)) {
                                        continue;
                                }
-                               if (is_same_bone_dependency(variable_key, self_key)) {
+                               if (is_same_bone_dependency(variable_key, self_key) ||
+                                   is_same_nodetree_node_dependency(variable_key, self_key) ||
+                                   is_same_shapekey_dependency(variable_key, self_key))
+                               {
                                        continue;
                                }
-                               add_relation(variable_key, driver_key, "RNA Bone -> Driver");
+                               add_relation(variable_key, driver_key, "RNA Target -> Driver");
                        }
                        else {
                                if (dtar->id == id) {
@@ -1216,9 +1244,9 @@ void DepsgraphRelationBuilder::build_world(World *world)
        /* world's nodetree */
        if (world->nodetree != NULL) {
                build_nodetree(world->nodetree);
-               ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
-               ComponentKey world_key(world_id, DEG_NODE_TYPE_PARAMETERS);
-               add_relation(ntree_key, world_key, "NTree->World Parameters");
+               ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_SHADING);
+               ComponentKey world_key(world_id, DEG_NODE_TYPE_SHADING);
+               add_relation(ntree_key, world_key, "NTree->World Shading Update");
        }
 }
 
@@ -1240,8 +1268,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* objects - simulation participants */
        if (rbw->group) {
-               LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
-                       Object *object = go->ob;
+               LINKLIST_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) {
+                       Object *object = base->object;
                        if (object == NULL || object->type != OB_MESH) {
                                continue;
                        }
@@ -1294,8 +1322,8 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* constraints */
        if (rbw->constraints) {
-               LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
-                       Object *object = go->ob;
+               LINKLIST_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) {
+                       Object *object = base->object;
                        if (object == NULL || !object->rigidbody_constraint) {
                                continue;
                        }
@@ -1328,19 +1356,40 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
        OperationKey eval_init_key(&object->id,
                                   DEG_NODE_TYPE_EVAL_PARTICLES,
                                   DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT);
-       if (object_particles_depends_on_time(object)) {
-               add_relation(time_src_key, eval_init_key, "TimeSrc -> PSys");
-       }
 
        /* particle systems */
        LINKLIST_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
                ParticleSettings *part = psys->part;
 
-               /* particle settings */
-               build_animdata(&part->id);
-
-               /* this particle system */
-               OperationKey psys_key(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name);
+               /* Build particle settings relations.
+                *
+                * NOTE: The call itself ensures settings are only build once.
+                */
+               build_particle_settings(part);
+
+               /* This particle system. */
+               OperationKey psys_key(&object->id,
+                                     DEG_NODE_TYPE_EVAL_PARTICLES,
+                                     DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+                                     psys->name);
+
+               /* Update particle system when settings changes. */
+               OperationKey particle_settings_key(&part->id,
+                                                  DEG_NODE_TYPE_PARAMETERS,
+                                                  DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+               OperationKey particle_settings_recalc_clear_key(
+                       &part->id,
+                       DEG_NODE_TYPE_PARAMETERS,
+                       DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+               OperationKey psys_settings_key(&object->id,
+                                              DEG_NODE_TYPE_EVAL_PARTICLES,
+                                              DEG_OPCODE_PARTICLE_SETTINGS_EVAL,
+                                              psys->name);
+               add_relation(particle_settings_key, psys_settings_key, "Particle Settings Change");
+               add_relation(psys_settings_key, psys_key, "Particle Settings Update");
+               add_relation(psys_key,
+                            particle_settings_recalc_clear_key,
+                            "Particle Settings Recalc Clear");
 
                /* XXX: if particle system is later re-enabled, we must do full rebuild? */
                if (!psys_check_enabled(object, psys, G.is_rendering))
@@ -1356,14 +1405,33 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
 
                /* collisions */
                if (part->type != PART_HAIR) {
-                       add_collision_relations(psys_key, scene_, object, part->collision_group, object->lay, true, "Particle Collision");
+                       add_collision_relations(psys_key,
+                                               scene_,
+                                               object,
+                                               part->collision_group,
+                                               true,
+                                               "Particle Collision");
                }
-               else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
-                       add_collision_relations(psys_key, scene_, object, psys->clmd->coll_parms->group, object->lay | scene_->lay, true, "Hair Collision");
+               else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
+                        psys->clmd != NULL &&
+                        psys->clmd->coll_parms != NULL)
+               {
+                       add_collision_relations(psys_key,
+                                               scene_,
+                                               object,
+                                               psys->clmd->coll_parms->group,
+                                               true,
+                                               "Hair Collision");
                }
 
                /* effectors */
-               add_forcefield_relations(psys_key, scene_, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+               add_forcefield_relations(psys_key,
+                                        scene_,
+                                        object,
+                                        psys,
+                                        part->effector_weights,
+                                        part->type == PART_HAIR,
+                                        "Particle Field");
 
                /* boids */
                if (part->boids) {
@@ -1386,6 +1454,13 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
                if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
                        ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM);
                        add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
+                       if (part->dup_ob->type == OB_MBALL) {
+                               ComponentKey dup_geometry_key(&part->dup_ob->id,
+                                                             DEG_NODE_TYPE_GEOMETRY);
+                               add_relation(obdata_ubereval_key,
+                                            dup_geometry_key,
+                                            "Particle MBall Visualization");
+                       }
                }
        }
 
@@ -1398,8 +1473,27 @@ void DepsgraphRelationBuilder::build_particles(Object *object)
        ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM);
        add_relation(transform_key, obdata_ubereval_key, "Partcile Eval");
 
-       /* pointcache */
-       // TODO...
+       /* TODO(sergey): Do we need a point cache operations here? */
+}
+
+void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
+{
+       ID *part_id = &part->id;
+       if (part_id->tag & LIB_TAG_DOIT) {
+               return;
+       }
+       part_id->tag |= LIB_TAG_DOIT;
+
+       /* Animation data relations. */
+       build_animdata(&part->id);
+
+       OperationKey eval_key(part_id,
+                             DEG_NODE_TYPE_PARAMETERS,
+                             DEG_OPCODE_PARTICLE_SETTINGS_EVAL);
+       OperationKey recalc_clear_key(part_id,
+                                    DEG_NODE_TYPE_PARAMETERS,
+                                    DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR);
+       add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc");
 }
 
 void DepsgraphRelationBuilder::build_cloth(Object *object,
@@ -1473,12 +1567,22 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
        /* link components to each other */
        add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
 
+       OperationKey obdata_ubereval_key(&object->id,
+                                        DEG_NODE_TYPE_GEOMETRY,
+                                        DEG_OPCODE_GEOMETRY_UBEREVAL);
+
+       /* Special case: modifiers and DerivedMesh creation queries scene for various
+        * things like data mask to be used. We add relation here to ensure object is
+        * never evaluated prior to Scene's CoW is ready.
+        */
+       OperationKey scene_key(&scene_->id,
+                              DEG_NODE_TYPE_PARAMETERS,
+                              DEG_OPCODE_PLACEHOLDER,
+                              "Scene Eval");
+       add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+
        /* Modifiers */
        if (object->modifiers.first != NULL) {
-               OperationKey obdata_ubereval_key(&object->id,
-                                                DEG_NODE_TYPE_GEOMETRY,
-                                                DEG_OPCODE_GEOMETRY_UBEREVAL);
-
                LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
                        const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
                        if (mti->updateDepsgraph) {
@@ -1506,6 +1610,14 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
                        Material *ma = give_current_material(object, a);
                        if (ma != NULL) {
                                build_material(ma);
+
+                               if (object->type == OB_MESH) {
+                                       OperationKey material_key(&ma->id,
+                                                                 DEG_NODE_TYPE_SHADING,
+                                                                 DEG_OPCODE_MATERIAL_UPDATE);
+                                       OperationKey shading_key(&object->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_SHADING);
+                                       add_relation(material_key, shading_key, "Material Update");
+                               }
                        }
                }
        }
@@ -1584,18 +1696,18 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
                        // XXX: these needs geom data, but where is geom stored?
                        if (cu->bevobj) {
                                ComponentKey bevob_key(&cu->bevobj->id, DEG_NODE_TYPE_GEOMETRY);
-                               build_object(cu->bevobj);
+                               build_object(NULL, cu->bevobj);
                                add_relation(bevob_key, geom_key, "Curve Bevel");
                        }
                        if (cu->taperobj) {
                                ComponentKey taperob_key(&cu->taperobj->id, DEG_NODE_TYPE_GEOMETRY);
-                               build_object(cu->taperobj);
+                               build_object(NULL, cu->taperobj);
                                add_relation(taperob_key, geom_key, "Curve Taper");
                        }
                        if (object->type == OB_FONT) {
                                if (cu->textoncurve) {
                                        ComponentKey textoncurve_key(&cu->textoncurve->id, DEG_NODE_TYPE_GEOMETRY);
-                                       build_object(cu->textoncurve);
+                                       build_object(NULL, cu->textoncurve);
                                        add_relation(textoncurve_key, geom_key, "Text on Curve");
                                }
                        }
@@ -1630,11 +1742,17 @@ void DepsgraphRelationBuilder::build_camera(Object *object)
                return;
        }
        camera_id->tag |= LIB_TAG_DOIT;
+
+       ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+       ComponentKey camera_parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS);
+
+       add_relation(camera_parameters_key, object_parameters_key,
+                    "Camera -> Object");
+
        /* DOF */
-       if (cam->dof_ob) {
-               ComponentKey ob_param_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+       if (cam->dof_ob != NULL) {
                ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
-               add_relation(dof_ob_key, ob_param_key, "Camera DOF");
+               add_relation(dof_ob_key, object_parameters_key, "Camera DOF");
        }
 }
 
@@ -1647,30 +1765,44 @@ void DepsgraphRelationBuilder::build_lamp(Object *object)
                return;
        }
        lamp_id->tag |= LIB_TAG_DOIT;
+
+       ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS);
+       ComponentKey lamp_parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
+
+       add_relation(lamp_parameters_key, object_parameters_key,
+                    "Lamp -> Object");
+
        /* lamp's nodetree */
        if (la->nodetree != NULL) {
                build_nodetree(la->nodetree);
-               ComponentKey parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS);
-               ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_PARAMETERS);
-               add_relation(nodetree_key, parameters_key, "NTree->Lamp Parameters");
+               ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_SHADING);
+               add_relation(nodetree_key, lamp_parameters_key, "NTree->Lamp Parameters");
        }
        /* textures */
        build_texture_stack(la->mtex);
+
+       if (DEG_depsgraph_use_copy_on_write()) {
+               /* Make sure copy on write of lamp data is always properly updated for
+                * visible lamps.
+                */
+               OperationKey ob_copy_on_write_key(&object->id,
+                                                 DEG_NODE_TYPE_COPY_ON_WRITE,
+                                                 DEG_OPCODE_COPY_ON_WRITE);
+               OperationKey lamp_copy_on_write_key(lamp_id,
+                                                   DEG_NODE_TYPE_COPY_ON_WRITE,
+                                                   DEG_OPCODE_COPY_ON_WRITE);
+               add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order");
+       }
 }
 
 void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
 {
-       if (!ntree)
+       if (ntree == NULL) {
                return;
-
+       }
        ID *ntree_id = &ntree->id;
-
        build_animdata(ntree_id);
-
-       OperationKey parameters_key(ntree_id,
-                                   DEG_NODE_TYPE_PARAMETERS,
-                                   DEG_OPCODE_PARAMETERS_EVAL);
-
+       ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING);
        /* nodetree's nodes... */
        LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
                ID *id = bnode->id;
@@ -1688,7 +1820,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
                        /* nothing for now. */
                }
                else if (id_type == ID_OB) {
-                       build_object((Object *)id);
+                       build_object(NULL, (Object *)id);
                }
                else if (id_type == ID_SCE) {
                        /* Scenes are used by compositor trees, and handled by render
@@ -1704,15 +1836,22 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
                                build_nodetree(group_ntree);
                                group_ntree->id.tag |= LIB_TAG_DOIT;
                        }
-                       OperationKey group_parameters_key(&group_ntree->id,
-                                                         DEG_NODE_TYPE_PARAMETERS,
-                                                         DEG_OPCODE_PARAMETERS_EVAL);
-                       add_relation(group_parameters_key, parameters_key, "Group Node");
+                       ComponentKey group_shading_key(&group_ntree->id,
+                                                      DEG_NODE_TYPE_SHADING);
+                       add_relation(group_shading_key, shading_key, "Group Node");
                }
                else {
                        BLI_assert(!"Unknown ID type used for node");
                }
        }
+
+       OperationKey shading_update_key(ntree_id,
+                                       DEG_NODE_TYPE_SHADING,
+                                       DEG_OPCODE_MATERIAL_UPDATE);
+       OperationKey shading_parameters_key(ntree_id,
+                                           DEG_NODE_TYPE_SHADING_PARAMETERS,
+                                           DEG_OPCODE_MATERIAL_UPDATE);
+       add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
 }
 
 /* Recursively build graph for material */
@@ -1734,12 +1873,11 @@ void DepsgraphRelationBuilder::build_material(Material *ma)
        if (ma->nodetree != NULL) {
                build_nodetree(ma->nodetree);
                OperationKey ntree_key(&ma->nodetree->id,
-                                      DEG_NODE_TYPE_PARAMETERS,
-                                      DEG_OPCODE_PARAMETERS_EVAL);
+                                      DEG_NODE_TYPE_SHADING,
+                                      DEG_OPCODE_MATERIAL_UPDATE);
                OperationKey material_key(&ma->id,
                                          DEG_NODE_TYPE_SHADING,
-                                         DEG_OPCODE_PLACEHOLDER,
-                                         "Material Update");
+                                         DEG_OPCODE_MATERIAL_UPDATE);
                add_relation(ntree_key, material_key, "Material's NTree");
        }
 }
@@ -1787,7 +1925,8 @@ void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
        // TODO: parent object (when that feature is implemented)
 }
 
-void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) {
+void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
+{
        /* Animation. */
        build_animdata(&cache_file->id);
 }
@@ -1814,4 +1953,101 @@ void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
        build_animdata(&clip->id);
 }
 
+void DepsgraphRelationBuilder::build_lightprobe(Object *object)
+{
+       LightProbe *probe = (LightProbe *)object->data;
+       ID *probe_id = &probe->id;
+       if (probe_id->tag & LIB_TAG_DOIT) {
+               return;
+       }
+       probe_id->tag |= LIB_TAG_DOIT;
+       build_animdata(&probe->id);
+
+       OperationKey probe_key(probe_id,
+                              DEG_NODE_TYPE_PARAMETERS,
+                              DEG_OPCODE_PLACEHOLDER,
+                              "LightProbe Eval");
+       OperationKey object_key(&object->id,
+                               DEG_NODE_TYPE_PARAMETERS,
+                               DEG_OPCODE_PLACEHOLDER,
+                               "LightProbe Eval");
+       add_relation(probe_key, object_key, "LightProbe Update");
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations()
+{
+       foreach (IDDepsNode *id_node, graph_->id_nodes) {
+               build_copy_on_write_relations(id_node);
+       }
+}
+
+void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node)
+{
+       ID *id_orig = id_node->id_orig;
+
+       TimeSourceKey time_source_key;
+       OperationKey copy_on_write_key(id_orig,
+                                      DEG_NODE_TYPE_COPY_ON_WRITE,
+                                      DEG_OPCODE_COPY_ON_WRITE);
+       /* XXX: This is a quick hack to make Alt-A to work. */
+       // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
+       /* Resat of code is using rather low level trickery, so need to get some
+        * explicit pointers.
+        */
+       DepsNode *node_cow = find_node(copy_on_write_key);
+       OperationDepsNode *op_cow = node_cow->get_exit_operation();
+       /* Plug any other components to this one. */
+       GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp_node, id_node->components)
+       {
+               if (comp_node->type == DEG_NODE_TYPE_COPY_ON_WRITE) {
+                       /* Copy-on-write component never depends on itself. */
+                       continue;
+               }
+               if (!comp_node->depends_on_cow()) {
+                       /* Component explicitly requests to not add relation. */
+                       continue;
+               }
+               /* All entry operations of each component should wait for a proper
+                * copy of ID.
+                */
+               OperationDepsNode *op_entry = comp_node->get_entry_operation();
+               if (op_entry != NULL) {
+                       graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
+               }
+               /* All dangling operations should also be executed after copy-on-write. */
+               GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, comp_node->operations_map)
+               {
+                       if (op_node->inlinks.size() == 0) {
+                               graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+                       }
+               }
+               GHASH_FOREACH_END();
+               /* NOTE: We currently ignore implicit relations to an external
+                * datablocks for copy-on-write operations. This means, for example,
+                * copy-on-write component of Object will not wait for copy-on-write
+                * component of it's Mesh. This is because pointers are all known
+                * already so remapping will happen all correct. And then If some object
+                * evaluation step needs geometry, it will have transitive dependency
+                * to Mesh copy-on-write already.
+                */
+       }
+       GHASH_FOREACH_END();
+       /* TODO(sergey): This solves crash for now, but causes too many
+        * updates potentially.
+        */
+       if (GS(id_orig->name) == ID_OB) {
+               Object *object = (Object *)id_orig;
+               ID *object_data_id = (ID *)object->data;
+               if (object_data_id != NULL) {
+                       OperationKey data_copy_on_write_key(object_data_id,
+                                                           DEG_NODE_TYPE_COPY_ON_WRITE,
+                                                           DEG_OPCODE_COPY_ON_WRITE);
+                       add_relation(data_copy_on_write_key, copy_on_write_key, "Eval Order");
+               }
+               else {
+                       BLI_assert(object->type == OB_EMPTY);
+               }
+       }
+}
+
 }  // namespace DEG