Merge branch 'master' into blender2.8
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations.cc
index bd62833846172d4ebaa5745b93936687e01566df..dca1da0979b56216f3d7af225b72bc4cb5378e1c 100644 (file)
@@ -55,8 +55,10 @@ extern "C" {
 #include "DNA_key_types.h"
 #include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
+#include "DNA_mask_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
 #include "DNA_rigidbody_types.h"
@@ -320,88 +322,6 @@ void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key,
 
 /* **** Functions to build relations between entities  **** */
 
-void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene)
-{
-       /* LIB_TAG_DOIT is used to indicate whether node for given ID was already
-        * created or not.
-        */
-       BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
-       /* XXX nested node trees are not included in tag-clearing above,
-        * so we need to do this manually.
-        */
-       FOREACH_NODETREE(bmain, nodetree, id) {
-               if (id != (ID *)nodetree)
-                       nodetree->id.tag &= ~LIB_TAG_DOIT;
-       } FOREACH_NODETREE_END
-
-       if (scene->set) {
-               // TODO: link set to scene, especially our timesource...
-       }
-
-       /* scene objects */
-       for (Base *base = (Base *)scene->base.first; base; base = base->next) {
-               Object *ob = base->object;
-
-               /* object itself */
-               build_object(bmain, scene, ob);
-
-               /* object that this is a proxy for */
-               if (ob->proxy) {
-                       ob->proxy->proxy_from = ob;
-                       build_object(bmain, scene, ob->proxy);
-                       /* TODO(sergey): This is an inverted relation, matches old depsgraph
-                        * behavior and need to be investigated if it still need to be inverted.
-                        */
-                       ComponentKey ob_pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-                       ComponentKey proxy_pose_key(&ob->proxy->id, DEPSNODE_TYPE_EVAL_POSE);
-                       add_relation(ob_pose_key, proxy_pose_key, DEPSREL_TYPE_TRANSFORM, "Proxy");
-               }
-
-               /* Object dupligroup. */
-               if (ob->dup_group) {
-                       build_group(bmain, scene, ob, ob->dup_group);
-               }
-       }
-
-       /* rigidbody */
-       if (scene->rigidbody_world) {
-               build_rigidbody(scene);
-       }
-
-       /* scene's animation and drivers */
-       if (scene->adt) {
-               build_animdata(&scene->id);
-       }
-
-       /* world */
-       if (scene->world) {
-               build_world(scene->world);
-       }
-
-       /* compo nodes */
-       if (scene->nodetree) {
-               build_compositor(scene);
-       }
-
-       /* grease pencil */
-       if (scene->gpd) {
-               build_gpencil(&scene->id, scene->gpd);
-       }
-
-       for (Depsgraph::OperationNodes::const_iterator it_op = m_graph->operations.begin();
-            it_op != m_graph->operations.end();
-            ++it_op)
-       {
-               OperationDepsNode *node = *it_op;
-               IDDepsNode *id_node = node->owner->owner;
-               ID *id = id_node->id;
-               if (GS(id->name) == ID_OB) {
-                       Object *object = (Object *)id;
-                       object->customdata_mask |= node->customdata_mask;
-               }
-       }
-}
-
 void DepsgraphRelationBuilder::build_group(Main *bmain,
                                            Scene *scene,
                                            Object *object,
@@ -412,10 +332,7 @@ void DepsgraphRelationBuilder::build_group(Main *bmain,
        OperationKey object_local_transform_key(&object->id,
                                                DEPSNODE_TYPE_TRANSFORM,
                                                DEG_OPCODE_TRANSFORM_LOCAL);
-       for (GroupObject *go = (GroupObject *)group->gobject.first;
-            go != NULL;
-            go = go->next)
-       {
+       LINKLIST_FOREACH (GroupObject *, go, &group->gobject) {
                if (!group_done) {
                        build_object(bmain, scene, go->ob);
                }
@@ -687,9 +604,10 @@ void DepsgraphRelationBuilder::build_constraints(Scene *scene, ID *id, eDepsNode
                        ListBase targets = {NULL, NULL};
                        cti->get_constraint_targets(con, &targets);
 
-                       for (bConstraintTarget *ct = (bConstraintTarget *)targets.first; ct; ct = ct->next) {
-                               if (!ct->tar)
+                       LINKLIST_FOREACH (bConstraintTarget *, ct, &targets) {
+                               if (ct->tar == NULL) {
                                        continue;
+                               }
 
                                if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
                                        /* ignore IK constraints - these are handled separately (on pose level) */
@@ -816,7 +734,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
        }
 
        /* drivers */
-       for (FCurve *fcu = (FCurve *)adt->drivers.first; fcu; fcu = fcu->next) {
+       LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
                OperationKey driver_key(id,
                                        DEPSNODE_TYPE_PARAMETERS,
                                        DEG_OPCODE_DRIVER,
@@ -840,10 +758,7 @@ void DepsgraphRelationBuilder::build_animdata(ID *id)
                 */
                if (fcu->array_index > 0) {
                        FCurve *fcu_prev = NULL;
-                       for (FCurve *fcu_candidate = (FCurve *)adt->drivers.first;
-                            fcu_candidate != NULL;
-                            fcu_candidate = fcu_candidate->next)
-                       {
+                       LINKLIST_FOREACH (FCurve *, fcu_candidate, &adt->drivers) {
                                /* Writing to different RNA paths is  */
                                if (!STREQ(fcu_candidate->rna_path, fcu->rna_path)) {
                                        continue;
@@ -1007,7 +922,7 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
        // XXX: the data itself could also set this, if it were to be truly initialised later?
 
        /* loop over variables to get the target relationships */
-       for (DriverVar *dvar = (DriverVar *)driver->variables.first; dvar; dvar = dvar->next) {
+       LINKLIST_FOREACH (DriverVar *, dvar, &driver->variables) {
                /* only used targets */
                DRIVER_TARGETS_USED_LOOPER(dvar)
                {
@@ -1127,10 +1042,11 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* objects - simulation participants */
        if (rbw->group) {
-               for (GroupObject *go = (GroupObject *)rbw->group->gobject.first; go; go = go->next) {
+               LINKLIST_FOREACH (GroupObject *, go, &rbw->group->gobject) {
                        Object *ob = go->ob;
-                       if (!ob || ob->type != OB_MESH)
+                       if (ob == NULL || ob->type != OB_MESH) {
                                continue;
+                       }
 
                        /* hook up evaluation order...
                         * 1) flushing rigidbody results follows base transforms being applied
@@ -1178,10 +1094,11 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
 
        /* constraints */
        if (rbw->constraints) {
-               for (GroupObject *go = (GroupObject *)rbw->constraints->gobject.first; go; go = go->next) {
+               LINKLIST_FOREACH (GroupObject *, go, &rbw->constraints->gobject) {
                        Object *ob = go->ob;
-                       if (!ob || !ob->rigidbody_constraint)
+                       if (ob == NULL || !ob->rigidbody_constraint) {
                                continue;
+                       }
 
                        RigidBodyCon *rbc = ob->rigidbody_constraint;
 
@@ -1202,391 +1119,6 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
        }
 }
 
-/* IK Solver Eval Steps */
-void DepsgraphRelationBuilder::build_ik_pose(Object *ob,
-                                             bPoseChannel *pchan,
-                                             bConstraint *con,
-                                             RootPChanMap *root_map)
-{
-       bKinematicConstraint *data = (bKinematicConstraint *)con->data;
-
-       /* attach owner to IK Solver too
-        * - assume that owner is always part of chain
-        * - see notes on direction of rel below...
-        */
-       bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
-       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_IK_SOLVER);
-
-       /* IK target */
-       // XXX: this should get handled as part of the constraint code
-       if (data->tar != NULL) {
-               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
-                * we create dependency between target object and pose eval component.
-                *
-                * This way we ensuring the whole subtree is updated from scratch without
-                * need of intermediate matricies. This is an overkill, but good enough for
-                * testing IK solver.
-                */
-               // FIXME: geometry targets...
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
-                       /* TODO(sergey): This is only for until granular update stores intermediate result. */
-                       if (data->tar != ob) {
-                               /* different armature - can just read the results */
-                               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget);
-                               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
-                       }
-                       else {
-                               /* same armature - we'll use the ready state only, just in case this bone is in the chain we're solving */
-                               OperationKey target_key(&data->tar->id, DEPSNODE_TYPE_BONE, data->subtarget, DEG_OPCODE_BONE_DONE);
-                               add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-                       }
-               }
-               else if (ELEM(data->tar->type, OB_MESH, OB_LATTICE) && (data->subtarget[0])) {
-                       /* vertex group target */
-                       /* NOTE: for now, we don't need to represent vertex groups separately... */
-                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
-                       if (data->tar->type == OB_MESH) {
-                               OperationDepsNode *node2 = find_operation_node(target_key);
-                               if (node2 != NULL) {
-                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
-                               }
-                       }
-               }
-               else {
-                       /* Standard Object Target */
-                       ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_TRANSFORM);
-                       add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-
-               if ((data->tar == ob) && (data->subtarget[0])) {
-                       /* Prevent target's constraints from linking to anything from same
-                        * chain that it controls.
-                        */
-                       root_map->add_bone(data->subtarget, rootchan->name);
-               }
-       }
-
-       /* Pole Target */
-       // XXX: this should get handled as part of the constraint code
-       if (data->poletar != NULL) {
-               if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
-                       // XXX: same armature issues - ready vs done?
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_BONE, data->polesubtarget);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-               else if (ELEM(data->poletar->type, OB_MESH, OB_LATTICE) && (data->polesubtarget[0])) {
-                       /* vertex group target */
-                       /* NOTE: for now, we don't need to represent vertex groups separately... */
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_GEOMETRY);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_GEOMETRY_EVAL, con->name);
-
-                       if (data->poletar->type == OB_MESH) {
-                               OperationDepsNode *node2 = find_operation_node(target_key);
-                               if (node2 != NULL) {
-                                       node2->customdata_mask |= CD_MASK_MDEFORMVERT;
-                               }
-                       }
-               }
-               else {
-                       ComponentKey target_key(&data->poletar->id, DEPSNODE_TYPE_TRANSFORM);
-                       add_relation(target_key, solver_key, DEPSREL_TYPE_TRANSFORM, con->name);
-               }
-       }
-
-       DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n",
-                        pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
-
-       bPoseChannel *parchan = pchan;
-       /* exclude tip from chain? */
-       if (!(data->flag & CONSTRAINT_IK_TIP)) {
-               OperationKey tip_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
-                                               parchan->name, DEG_OPCODE_BONE_LOCAL);
-               add_relation(solver_key, tip_transforms_key,
-                            DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
-               parchan = pchan->parent;
-       }
-
-       root_map->add_bone(parchan->name, rootchan->name);
-
-       OperationKey parchan_transforms_key(&ob->id, DEPSNODE_TYPE_BONE,
-                                           parchan->name, DEG_OPCODE_BONE_READY);
-       add_relation(parchan_transforms_key, solver_key,
-                    DEPSREL_TYPE_TRANSFORM, "IK Solver Owner");
-
-       /* Walk to the chain's root */
-       //size_t segcount = 0;
-       int segcount = 0;
-
-       while (parchan) {
-               /* Make IK-solver dependent on this bone's result,
-                * since it can only run after the standard results
-                * of the bone are know. Validate links step on the
-                * bone will ensure that users of this bone only
-                * grab the result with IK solver results...
-                */
-               if (parchan != pchan) {
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
-                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Parent");
-
-                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
-               }
-               else {
-                       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "IK Solver Result");
-               }
-               parchan->flag |= POSE_DONE;
-
-
-               root_map->add_bone(parchan->name, rootchan->name);
-
-               /* continue up chain, until we reach target number of items... */
-               DEG_DEBUG_PRINTF("  %d = %s\n", segcount, parchan->name);
-               segcount++;
-               if ((segcount == data->rootbone) || (segcount > 255)) break;  /* 255 is weak */
-
-               parchan  = parchan->parent;
-       }
-
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-}
-
-/* Spline IK Eval Steps */
-void DepsgraphRelationBuilder::build_splineik_pose(Object *ob,
-                                                   bPoseChannel *pchan,
-                                                   bConstraint *con,
-                                                   RootPChanMap *root_map)
-{
-       bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
-       bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
-       OperationKey transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-       OperationKey solver_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, rootchan->name, DEG_OPCODE_POSE_SPLINE_IK_SOLVER);
-
-       /* attach owner to IK Solver too
-        * - assume that owner is always part of chain
-        * - see notes on direction of rel below...
-        */
-       add_relation(transforms_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Owner");
-
-       /* attach path dependency to solver */
-       if (data->tar) {
-               /* TODO(sergey): For until we'll store partial matricies in the depsgraph,
-                * we create dependency between target object and pose eval component.
-                * See IK pose for a bit more information.
-                */
-               // TODO: the bigggest point here is that we need the curve PATH and not just the general geometry...
-               ComponentKey target_key(&data->tar->id, DEPSNODE_TYPE_GEOMETRY);
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               add_relation(target_key, pose_key, DEPSREL_TYPE_TRANSFORM, "[Curve.Path -> Spline IK] DepsRel");
-       }
-
-       pchan->flag |= POSE_DONE;
-       OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-       add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Result");
-
-       root_map->add_bone(pchan->name, rootchan->name);
-
-       /* Walk to the chain's root */
-       //size_t segcount = 0;
-       int segcount = 0;
-
-       for (bPoseChannel *parchan = pchan->parent; parchan; parchan = parchan->parent) {
-               /* Make Spline IK solver dependent on this bone's result,
-                * since it can only run after the standard results
-                * of the bone are know. Validate links step on the
-                * bone will ensure that users of this bone only
-                * grab the result with IK solver results...
-                */
-               if (parchan != pchan) {
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_READY);
-                       add_relation(parent_key, solver_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Update");
-
-                       OperationKey done_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-                       add_relation(solver_key, done_key, DEPSREL_TYPE_TRANSFORM, "IK Chain Result");
-               }
-               parchan->flag |= POSE_DONE;
-
-               OperationKey final_transforms_key(&ob->id, DEPSNODE_TYPE_BONE, parchan->name, DEG_OPCODE_BONE_DONE);
-               add_relation(solver_key, final_transforms_key, DEPSREL_TYPE_TRANSFORM, "Spline IK Solver Result");
-
-               root_map->add_bone(parchan->name, rootchan->name);
-
-               /* continue up chain, until we reach target number of items... */
-               segcount++;
-               if ((segcount == data->chainlen) || (segcount > 255)) break;  /* 255 is weak */
-       }
-
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       add_relation(solver_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-}
-
-/* Pose/Armature Bones Graph */
-void DepsgraphRelationBuilder::build_rig(Scene *scene, Object *ob)
-{
-       /* Armature-Data */
-       bArmature *arm = (bArmature *)ob->data;
-
-       // TODO: selection status?
-
-       /* attach links between pose operations */
-       OperationKey init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
-       OperationKey flush_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-
-       add_relation(init_key, flush_key, DEPSREL_TYPE_COMPONENT_ORDER, "[Pose Init -> Pose Cleanup]");
-
-       /* Make sure pose is up-to-date with armature updates. */
-       OperationKey armature_key(&arm->id,
-                                 DEPSNODE_TYPE_PARAMETERS,
-                                 DEG_OPCODE_PLACEHOLDER,
-                                 "Armature Eval");
-       add_relation(armature_key, init_key, DEPSREL_TYPE_COMPONENT_ORDER, "Data dependency");
-
-       if (needs_animdata_node(&ob->id)) {
-               ComponentKey animation_key(&ob->id, DEPSNODE_TYPE_ANIMATION);
-               add_relation(animation_key, init_key, DEPSREL_TYPE_OPERATION, "Rig Animation");
-       }
-
-       /* IK Solvers...
-        * - These require separate processing steps are pose-level
-        *   to be executed between chains of bones (i.e. once the
-        *   base transforms of a bunch of bones is done)
-        *
-        * - We build relations for these before the dependencies
-        *   between ops in the same component as it is necessary
-        *   to check whether such bones are in the same IK chain
-        *   (or else we get weird issues with either in-chain
-        *   references, or with bones being parented to IK'd bones)
-        *
-        * Unsolved Issues:
-        * - Care is needed to ensure that multi-headed trees work out the same as in ik-tree building
-        * - Animated chain-lengths are a problem...
-        */
-       RootPChanMap root_map;
-       bool pose_depends_on_local_transform = false;
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-               for (bConstraint *con = (bConstraint *)pchan->constraints.first; con; con = con->next) {
-                       switch (con->type) {
-                               case CONSTRAINT_TYPE_KINEMATIC:
-                                       build_ik_pose(ob, pchan, con, &root_map);
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               case CONSTRAINT_TYPE_SPLINEIK:
-                                       build_splineik_pose(ob, pchan, con, &root_map);
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               /* Constraints which needs world's matrix for transform.
-                                * TODO(sergey): More constraints here?
-                                */
-                               case CONSTRAINT_TYPE_ROTLIKE:
-                               case CONSTRAINT_TYPE_SIZELIKE:
-                               case CONSTRAINT_TYPE_LOCLIKE:
-                               case CONSTRAINT_TYPE_TRANSLIKE:
-                                       /* TODO(sergey): Add used space check. */
-                                       pose_depends_on_local_transform = true;
-                                       break;
-
-                               default:
-                                       break;
-                       }
-               }
-       }
-       //root_map.print_debug();
-
-       if (pose_depends_on_local_transform) {
-               /* TODO(sergey): Once partial updates are possible use relation between
-                * object transform and solver itself in it's build function.
-                */
-               ComponentKey pose_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE);
-               ComponentKey local_transform_key(&ob->id, DEPSNODE_TYPE_TRANSFORM);
-               add_relation(local_transform_key, pose_key, DEPSREL_TYPE_TRANSFORM, "Local Transforms");
-       }
-
-
-       /* links between operations for each bone */
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
-               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
-               OperationKey bone_pose_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT);
-               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-
-               pchan->flag &= ~POSE_DONE;
-
-               /* pose init to bone local */
-               add_relation(init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "PoseEval Source-Bone Link");
-
-               /* local to pose parenting operation */
-               add_relation(bone_local_key, bone_pose_key, DEPSREL_TYPE_OPERATION, "Bone Local - PoseSpace Link");
-
-               /* parent relation */
-               if (pchan->parent != NULL) {
-                       eDepsOperation_Code parent_key_opcode;
-
-                       /* NOTE: this difference in handling allows us to prevent lockups while ensuring correct poses for separate chains */
-                       if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
-                               parent_key_opcode = DEG_OPCODE_BONE_READY;
-                       }
-                       else {
-                               parent_key_opcode = DEG_OPCODE_BONE_DONE;
-                       }
-
-                       OperationKey parent_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->parent->name, parent_key_opcode);
-                       add_relation(parent_key, bone_pose_key, DEPSREL_TYPE_TRANSFORM, "[Parent Bone -> Child Bone]");
-               }
-
-               /* constraints */
-               if (pchan->constraints.first != NULL) {
-                       /* constraints stack and constraint dependencies */
-                       build_constraints(scene, &ob->id, DEPSNODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map);
-
-                       /* pose -> constraints */
-                       OperationKey constraints_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_CONSTRAINTS);
-                       add_relation(bone_pose_key, constraints_key, DEPSREL_TYPE_OPERATION, "Constraints Stack");
-
-                       /* constraints -> ready */
-                       // TODO: when constraint stack is exploded, this step should occur before the first IK solver
-                       add_relation(constraints_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Constraints -> Ready");
-               }
-               else {
-                       /* pose -> ready */
-                       add_relation(bone_pose_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Pose -> Ready");
-               }
-
-               /* bone ready -> done
-                * NOTE: For bones without IK, this is all that's needed.
-                *       For IK chains however, an additional rel is created from IK to done,
-                *       with transitive reduction removing this one...
-                */
-               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
-
-               /* assume that all bones must be done for the pose to be ready (for deformers) */
-               add_relation(bone_done_key, flush_key, DEPSREL_TYPE_OPERATION, "PoseEval Result-Bone Link");
-       }
-}
-
-void DepsgraphRelationBuilder::build_proxy_rig(Object *ob)
-{
-       OperationKey pose_init_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT);
-       OperationKey pose_done_key(&ob->id, DEPSNODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE);
-       for (bPoseChannel *pchan = (bPoseChannel *)ob->pose->chanbase.first;
-            pchan != NULL;
-            pchan = pchan->next)
-       {
-               OperationKey bone_local_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL);
-               OperationKey bone_ready_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY);
-               OperationKey bone_done_key(&ob->id, DEPSNODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE);
-               add_relation(pose_init_key, bone_local_key, DEPSREL_TYPE_OPERATION, "Pose Init -> Bone Local");
-               add_relation(bone_local_key, bone_ready_key, DEPSREL_TYPE_OPERATION, "Local -> Ready");
-               add_relation(bone_ready_key, bone_done_key, DEPSREL_TYPE_OPERATION, "Ready -> Done");
-               add_relation(bone_done_key, pose_done_key, DEPSREL_TYPE_OPERATION, "Bone Done -> Pose Done");
-       }
-}
-
 /* Shapekeys */
 void DepsgraphRelationBuilder::build_shapekeys(ID *obdata, Key *key)
 {
@@ -1647,10 +1179,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Main *bmain, Scene *scene, Obje
 
        /* Modifiers */
        if (ob->modifiers.first) {
-               ModifierData *md;
                OperationKey prev_mod_key;
 
-               for (md = (ModifierData *)ob->modifiers.first; md; md = md->next) {
+               LINKLIST_FOREACH (ModifierData *, md, &ob->modifiers) {
                        const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
                        OperationKey mod_key(&ob->id, DEPSNODE_TYPE_GEOMETRY, DEG_OPCODE_GEOMETRY_MODIFIER, md->name);
 
@@ -1885,7 +1416,7 @@ void DepsgraphRelationBuilder::build_nodetree(ID *owner, bNodeTree *ntree)
                                    "Parameters Eval");
 
        /* nodetree's nodes... */
-       for (bNode *bnode = (bNode *)ntree->nodes.first; bnode; bnode = bnode->next) {
+       LINKLIST_FOREACH (bNode *, bnode, &ntree->nodes) {
                if (bnode->id) {
                        if (GS(bnode->id->name) == ID_MA) {
                                build_material(owner, (Material *)bnode->id);
@@ -1989,4 +1520,21 @@ bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
        return false;
 }
 
+void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) {
+       /* Animation. */
+       build_animdata(&cache_file->id);
+}
+
+void DepsgraphRelationBuilder::build_mask(Mask *mask)
+{
+       /* Animation. */
+       build_animdata(&mask->id);
+}
+
+void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
+{
+       /* Animation. */
+       build_animdata(&clip->id);
+}
+
 }  // namespace DEG