Merge branch 'master' into blender2.8
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 6 Dec 2017 09:38:34 +0000 (10:38 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 6 Dec 2017 09:38:34 +0000 (10:38 +0100)
source/blender/depsgraph/CMakeLists.txt
source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.cc
source/blender/depsgraph/intern/builder/deg_builder_relations.h
source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h [new file with mode: 0644]
source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
source/blender/depsgraph/intern/depsgraph.cc
source/blender/depsgraph/intern/depsgraph.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c

index 89ba6e27aed6be5cbc0c5c68cd0e93346cedaf58..9495321a0ff77641703836f6a6313d4519323ff5 100644 (file)
@@ -80,6 +80,7 @@ set(SRC
        intern/builder/deg_builder_nodes.h
        intern/builder/deg_builder_pchanmap.h
        intern/builder/deg_builder_relations.h
+       intern/builder/deg_builder_relations_impl.h
        intern/builder/deg_builder_transitive.h
        intern/eval/deg_eval.h
        intern/eval/deg_eval_copy_on_write.h
index dfe97d02ec606e6dca1002da6ea1092c9fbee0de..f6f2dcce4672c27a0df0f62fcc794268cc23643d 100644 (file)
@@ -359,6 +359,15 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
                                             NULL,
                                             DEG_OPCODE_BONE_DONE);
                op_node->set_as_exit();
+
+               /* Custom properties. */
+               if (pchan->prop != NULL) {
+                       add_operation_node(&object->id,
+                                          DEG_NODE_TYPE_PARAMETERS,
+                                          NULL,
+                                          DEG_OPCODE_PARAMETERS_EVAL,
+                                          pchan->name);
+               }
        }
        op_node = add_operation_node(&object->id,
                                     DEG_NODE_TYPE_EVAL_POSE,
index aeb9f9ab93772f5faa6f42efeae57e0449c6710b..5c984535cb8035878a7791cd566303e758206054 100644 (file)
@@ -120,10 +120,10 @@ struct BuilderWalkUserData {
        DepsgraphRelationBuilder *builder;
 };
 
-static void modifier_walk(void *user_data,
-                          struct Object * /*object*/,
-                          struct Object **obpoin,
-                          int /*cb_flag*/)
+void modifier_walk(void *user_data,
+                   struct Object * /*object*/,
+                   struct Object **obpoin,
+                   int /*cb_flag*/)
 {
        BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
        if (*obpoin) {
@@ -275,10 +275,11 @@ bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
 
 void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
                                                  DepsNode *node_to,
-                                                 const char *description)
+                                                 const char *description,
+                                                 bool check_unique)
 {
        if (timesrc && node_to) {
-               graph_->add_new_relation(timesrc, node_to, description);
+               graph_->add_new_relation(timesrc, node_to, description, check_unique);
        }
        else {
                DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n",
@@ -291,10 +292,11 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc,
 void DepsgraphRelationBuilder::add_operation_relation(
         OperationDepsNode *node_from,
         OperationDepsNode *node_to,
-        const char *description)
+        const char *description,
+        bool check_unique)
 {
        if (node_from && node_to) {
-               graph_->add_new_relation(node_from, node_to, description);
+               graph_->add_new_relation(node_from, node_to, description, check_unique);
        }
        else {
                DEG_DEBUG_PRINTF("add_operation_relation(%p = %s, %p = %s, %s) Failed\n",
@@ -304,13 +306,22 @@ void DepsgraphRelationBuilder::add_operation_relation(
        }
 }
 
-void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key, Scene *scene, Object *object, Group *group, bool dupli, const char *name)
+void DepsgraphRelationBuilder::add_collision_relations(
+        const OperationKey &key,
+        Scene *scene,
+        Object *object,
+        Group *group,
+        bool dupli,
+        const char *name)
 {
        unsigned int numcollobj;
-       Object **collobjs = get_collisionobjects_ext(scene, object, group, &numcollobj, eModifierType_Collision, dupli);
-
-       for (unsigned int i = 0; i < numcollobj; i++)
-       {
+       Object **collobjs = get_collisionobjects_ext(scene,
+                                                    object,
+                                                    group,
+                                                    &numcollobj,
+                                                    eModifierType_Collision,
+                                                    dupli);
+       for (unsigned int i = 0; i < numcollobj; i++) {
                Object *ob1 = collobjs[i];
 
                ComponentKey trf_key(&ob1->id, DEG_NODE_TYPE_TRANSFORM);
@@ -319,47 +330,62 @@ void DepsgraphRelationBuilder::add_collision_relations(const OperationKey &key,
                ComponentKey coll_key(&ob1->id, DEG_NODE_TYPE_GEOMETRY);
                add_relation(coll_key, key, name);
        }
-
-       if (collobjs)
+       if (collobjs != NULL) {
                MEM_freeN(collobjs);
+       }
 }
 
-void DepsgraphRelationBuilder::add_forcefield_relations(const OperationKey &key, Scene *scene, Object *object, ParticleSystem *psys, EffectorWeights *eff, bool add_absorption, const char *name)
+void DepsgraphRelationBuilder::add_forcefield_relations(
+        const OperationKey &key,
+        Scene *scene,
+        Object *object,
+        ParticleSystem *psys,
+        EffectorWeights *eff,
+        bool add_absorption,
+        const char *name)
 {
        ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false);
-
-       if (effectors) {
-               for (EffectorCache *eff = (EffectorCache *)effectors->first; eff; eff = eff->next) {
+       if (effectors != NULL) {
+               LINKLIST_FOREACH(EffectorCache *, eff, effectors) {
                        if (eff->ob != object) {
                                ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM);
                                add_relation(eff_key, key, name);
                        }
-
-                       if (eff->psys) {
+                       if (eff->psys != NULL) {
                                if (eff->ob != object) {
                                        ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES);
                                        add_relation(eff_key, key, name);
 
-                                       /* TODO: remove this when/if EVAL_PARTICLES is sufficient for up to date particles */
+                                       /* TODO: remove this when/if EVAL_PARTICLES is sufficient
+                                        * for up to date particles.
+                                        */
                                        ComponentKey mod_key(&eff->ob->id, DEG_NODE_TYPE_GEOMETRY);
                                        add_relation(mod_key, key, name);
                                }
                                else if (eff->psys != psys) {
-                                       OperationKey eff_key(&eff->ob->id, DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, eff->psys->name);
+                                       OperationKey eff_key(&eff->ob->id,
+                                                            DEG_NODE_TYPE_EVAL_PARTICLES,
+                                                            DEG_OPCODE_PARTICLE_SYSTEM_EVAL,
+                                                            eff->psys->name);
                                        add_relation(eff_key, key, name);
                                }
                        }
-
                        if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
-                               ComponentKey trf_key(&eff->pd->f_source->id, DEG_NODE_TYPE_TRANSFORM);
+                               ComponentKey trf_key(&eff->pd->f_source->id,
+                                                    DEG_NODE_TYPE_TRANSFORM);
                                add_relation(trf_key, key, "Smoke Force Domain");
 
-                               ComponentKey eff_key(&eff->pd->f_source->id, DEG_NODE_TYPE_GEOMETRY);
+                               ComponentKey eff_key(&eff->pd->f_source->id,
+                                                    DEG_NODE_TYPE_GEOMETRY);
                                add_relation(eff_key, key, "Smoke Force Domain");
                        }
-
                        if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
-                               add_collision_relations(key, scene, object, NULL, true, "Force Absorption");
+                               add_collision_relations(key,
+                                                       scene,
+                                                       object,
+                                                       NULL,
+                                                       true,
+                                                       "Force Absorption");
                        }
                }
        }
@@ -496,11 +522,6 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
        }
        /* Animation data */
        build_animdata(&object->id);
-       // XXX: This should be hooked up by the build_animdata code
-       if (needs_animdata_node(&object->id)) {
-               ComponentKey adt_key(&object->id, DEG_NODE_TYPE_ANIMATION);
-               add_relation(adt_key, local_transform_key, "Object Animation");
-       }
        /* Object data. */
        build_object_data(object);
        /* Particle systems. */
@@ -900,25 +921,85 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
 
 void DepsgraphRelationBuilder::build_animdata(ID *id)
 {
-       AnimData *adt = BKE_animdata_from_id(id);
+       /* Animation curves and NLA. */
+       build_animdata_curves(id);
+       /* Drivers. */
+       build_animdata_drievrs(id);
+}
 
-       if (adt == NULL)
+void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
+{
+       AnimData *adt = BKE_animdata_from_id(id);
+       if (adt == NULL) {
                return;
-
+       }
+       if (adt->action == NULL && adt->nla_tracks.first == NULL) {
+               return;
+       }
+       /* Wire up dependency to time source. */
        ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
+       TimeSourceKey time_src_key;
+       add_relation(time_src_key, adt_key, "TimeSrc -> Animation");
+       /* Build relations from animation operation to properties it changes. */
+       build_animdata_curves_targets(id);
+}
 
-       /* animation */
-       if (adt->action || adt->nla_tracks.first) {
-               /* wire up dependency to time source */
-               TimeSourceKey time_src_key;
-               add_relation(time_src_key, adt_key, "TimeSrc -> Animation");
-
-               // XXX: Hook up specific update callbacks for special properties which may need it...
-
-               // XXX: animdata "hierarchy" - top-level overrides need to go after lower-down
+void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id)
+{
+       AnimData *adt = BKE_animdata_from_id(id);
+       if (adt == NULL || adt->action == NULL) {
+               return;
+       }
+       /* Get source operation. */
+       ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
+       DepsNode *node_from = get_node(adt_key);
+       BLI_assert(node_from != NULL);
+       if (node_from == NULL) {
+               return;
+       }
+       OperationDepsNode *operation_from = node_from->get_exit_operation();
+       BLI_assert(operation_from != NULL);
+       /* Iterate over all curves and build relations. */
+       PointerRNA id_ptr;
+       RNA_id_pointer_create(id, &id_ptr);
+       LINKLIST_FOREACH(FCurve *, fcu, &adt->action->curves) {
+               PointerRNA ptr;
+               PropertyRNA *prop;
+               int index;
+               if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path,
+                                          &ptr, &prop, &index))
+               {
+                       continue;
+               }
+               DepsNode *node_to = graph_->find_node_from_pointer(&ptr, prop);
+               if (node_to == NULL) {
+                       continue;
+               }
+               OperationDepsNode *operation_to = node_to->get_entry_operation();
+               /* NOTE: Special case for bones, avoid relation from animation to
+                * each of the bones. Bone evaluation could only start from pose
+                * init anyway.
+                */
+               if (operation_to->opcode == DEG_OPCODE_BONE_LOCAL) {
+                       OperationKey pose_init_key(id,
+                                                  DEG_NODE_TYPE_EVAL_POSE,
+                                                  DEG_OPCODE_POSE_INIT);
+                       add_relation(adt_key, pose_init_key, "Animation -> Prop", true);
+                       continue;
+               }
+               graph_->add_new_relation(operation_from, operation_to,
+                                        "Animation -> Prop",
+                                        true);
        }
+}
 
-       /* drivers */
+void DepsgraphRelationBuilder::build_animdata_drievrs(ID *id)
+{
+       AnimData *adt = BKE_animdata_from_id(id);
+       if (adt == NULL) {
+               return;
+       }
+       ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
        LINKLIST_FOREACH (FCurve *, fcu, &adt->drivers) {
                OperationKey driver_key(id,
                                        DEG_NODE_TYPE_PARAMETERS,
@@ -990,45 +1071,34 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
                                DEG_OPCODE_DRIVER,
                                fcu->rna_path ? fcu->rna_path : "",
                                fcu->array_index);
-       bPoseChannel *pchan = NULL;
-       const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
-       const ID_Type id_type = GS(id->name);
-
-       /* Create dependency between driver and data affected by it. */
-       /* - direct property relationship... */
-       //RNAPathKey affected_key(id, fcu->rna_path);
-       //add_relation(driver_key, affected_key, "Driver -> Data");
-
        /* Driver -> data components (for interleaved evaluation
         * bones/constraints/modifiers).
         */
-       // XXX: this probably should probably be moved out into a separate function.
-       if (strstr(rna_path, "pose.bones[") != NULL) {
-               /* interleaved drivers during bone eval */
-               /* TODO: ideally, if this is for a constraint, it goes to said
-                * constraint.
-                */
-               Object *object = (Object *)id;
-               char *bone_name = BLI_str_quoted_substrN(rna_path, "pose.bones[");
-               pchan = BKE_pose_channel_find_name(object->pose, bone_name);
-               if (bone_name != NULL) {
-                       MEM_freeN(bone_name);
-                       bone_name = NULL;
-               }
-               if (pchan != NULL) {
-                       OperationKey bone_key(id,
-                                             DEG_NODE_TYPE_BONE,
-                                             pchan->name,
-                                             DEG_OPCODE_BONE_LOCAL);
-                       add_relation(driver_key, bone_key, "Driver -> Bone");
-               }
-               else {
-                       fprintf(stderr,
-                               "Couldn't find bone name for driver path - '%s'\n",
-                               rna_path);
-               }
+       build_driver_data(id, fcu);
+       /* Loop over variables to get the target relationships. */
+       build_driver_variables(id, fcu);
+       /* It's quite tricky to detect if the driver actually depends on time or
+        * not, so for now we'll be quite conservative here about optimization and
+        * consider all python drivers to be depending on time.
+        */
+       if ((driver->type == DRIVER_TYPE_PYTHON) &&
+           python_driver_depends_on_time(driver))
+       {
+               TimeSourceKey time_src_key;
+               add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
        }
-       else if (id_type == ID_AR && strstr(rna_path, "bones[")) {
+}
+
+void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
+{
+       OperationKey driver_key(id,
+                               DEG_NODE_TYPE_PARAMETERS,
+                               DEG_OPCODE_DRIVER,
+                               fcu->rna_path ? fcu->rna_path : "",
+                               fcu->array_index);
+       const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+       const RNAPathKey self_key(id, rna_path);
+       if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
                /* Drivers on armature-level bone settings (i.e. bbone stuff),
                 * which will affect the evaluation of corresponding pose bones.
                 */
@@ -1067,55 +1137,23 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
                                rna_path);
                }
        }
-       else if (id_type == ID_OB && strstr(rna_path, "modifiers[")) {
-               OperationKey modifier_key(id,
-                                         DEG_NODE_TYPE_GEOMETRY,
-                                         DEG_OPCODE_GEOMETRY_UBEREVAL);
-               if (has_node(modifier_key)) {
-                       add_relation(driver_key, modifier_key, "Driver -> Modifier");
-               }
-               else {
-                       printf("Unexisting driver RNA path: %s\n", rna_path);
-               }
-       }
-       else if (id_type == ID_KE && strstr(rna_path, "key_blocks[")) {
-               /* Shape key driver - hook into the base geometry operation. */
-               // XXX: double check where this points
-               Key *shape_key = (Key *)id;
-               ComponentKey geometry_key(shape_key->from, DEG_NODE_TYPE_GEOMETRY);
-               add_relation(driver_key, geometry_key, "Driver -> ShapeKey Geom");
-       }
-       else if (strstr(rna_path, "key_blocks[")) {
-               ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
-               add_relation(driver_key, geometry_key, "Driver -> ShapeKey Geom");
-       }
        else {
-               if (GS(id->name) == ID_OB) {
-                       /* assume that driver affects a transform... */
-                       OperationKey local_transform_key(id,
-                                                        DEG_NODE_TYPE_TRANSFORM,
-                                                        DEG_OPCODE_TRANSFORM_LOCAL);
-                       add_relation(driver_key,
-                                    local_transform_key,
-                                    "Driver -> Transform");
-               }
-               else if (GS(id->name) == ID_KE) {
-                       ComponentKey geometry_key(id, DEG_NODE_TYPE_GEOMETRY);
-                       add_relation(driver_key,
-                                    geometry_key,
-                                    "Driver -> Shapekey Geometry");
-               }
+               RNAPathKey target_key(id, rna_path);
+               add_relation(driver_key, target_key, "Driver -> Target");
        }
-       /* Ensure that affected prop's update callbacks will be triggered once
-        * done.
-        */
-       /* TODO: Implement this once the functionality to add these links exists
-        * RNA.
-        */
-       /* XXX: the data itself could also set this, if it were to be truly
-        * initialised later?
-        */
-       /* Loop over variables to get the target relationships. */
+}
+
+void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
+{
+       ChannelDriver *driver = fcu->driver;
+       OperationKey driver_key(id,
+                               DEG_NODE_TYPE_PARAMETERS,
+                               DEG_OPCODE_DRIVER,
+                               fcu->rna_path ? fcu->rna_path : "",
+                               fcu->array_index);
+       const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+       const RNAPathKey self_key(id, rna_path);
+
        LINKLIST_FOREACH (DriverVar *, dvar, &driver->variables) {
                /* Only used targets. */
                DRIVER_TARGETS_USED_LOOPER(dvar)
@@ -1124,31 +1162,25 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
                                continue;
                        }
                        /* Special handling for directly-named bones. */
-                       if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) {
+                       if ((dtar->flag & DTAR_FLAG_STRUCT_REF) &&
+                           (((Object *)dtar->id)->type == OB_ARMATURE) &&
+                           (dtar->pchan_name[0]))
+                       {
                                Object *object = (Object *)dtar->id;
                                bPoseChannel *target_pchan =
-                                       BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
-                               if (target_pchan != NULL) {
-                                       /* Get node associated with bone. */
-                                       // XXX: watch the space!
-                                       /* Some cases can't use final bone transform, for example:
-                                        * - Driving the bone with itself (addressed here)
-                                        * - Relations inside an IK chain (TODO?)
-                                        */
-                                       if (dtar->id == id &&
-                                           pchan != NULL &&
-                                           STREQ(pchan->name, target_pchan->name))
-                                       {
-                                               continue;
-                                       }
-                                       OperationKey target_key(dtar->id,
-                                                               DEG_NODE_TYPE_BONE,
-                                                               target_pchan->name,
-                                                               DEG_OPCODE_BONE_DONE);
-                                       add_relation(target_key,
-                                                    driver_key,
-                                                    "Bone Target -> Driver");
+                                       BKE_pose_channel_find_name(object->pose,
+                                                                  dtar->pchan_name);
+                               if (target_pchan == NULL) {
+                                       continue;
                                }
+                               OperationKey variable_key(dtar->id,
+                                                       DEG_NODE_TYPE_BONE,
+                                                       target_pchan->name,
+                                                       DEG_OPCODE_BONE_DONE);
+                               if (is_same_bone_dependency(variable_key, self_key)) {
+                                       continue;
+                               }
+                               add_relation(variable_key, driver_key, "Bone Target -> Driver");
                        }
                        else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
                                /* Get node associated with the object's transforms. */
@@ -1164,32 +1196,15 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
                                                        DEG_OPCODE_TRANSFORM_FINAL);
                                add_relation(target_key, driver_key, "Target -> Driver");
                        }
-                       else if (dtar->rna_path && strstr(dtar->rna_path, "pose.bones[")) {
-                               /* Workaround for ensuring that local bone transforms don't end
-                                * up having to wait for pose eval to finish (to prevent cycles).
-                                */
-                               Object *object = (Object *)dtar->id;
-                               char *bone_name = BLI_str_quoted_substrN(dtar->rna_path,
-                                                                        "pose.bones[");
-                               bPoseChannel *target_pchan =
-                                       BKE_pose_channel_find_name(object->pose, bone_name);
-                               if (bone_name != NULL) {
-                                       MEM_freeN(bone_name);
-                                       bone_name = NULL;
+                       else if (dtar->rna_path) {
+                               RNAPathKey variable_key(dtar->id, dtar->rna_path);
+                               if (RNA_pointer_is_null(&variable_key.ptr)) {
+                                       continue;
                                }
-                               if (target_pchan != NULL) {
-                                       if (dtar->id == id &&
-                                           pchan != NULL &&
-                                           STREQ(pchan->name, target_pchan->name))
-                                       {
-                                               continue;
-                                       }
-                                       OperationKey bone_key(dtar->id,
-                                                             DEG_NODE_TYPE_BONE,
-                                                             target_pchan->name,
-                                                             DEG_OPCODE_BONE_LOCAL);
-                                       add_relation(bone_key, driver_key, "RNA Bone -> Driver");
+                               if (is_same_bone_dependency(variable_key, self_key)) {
+                                       continue;
                                }
+                               add_relation(variable_key, driver_key, "RNA Bone -> Driver");
                        }
                        else {
                                if (dtar->id == id) {
@@ -1207,16 +1222,6 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
                }
                DRIVER_TARGETS_LOOPER_END
        }
-       /* It's quite tricky to detect if the driver actually depends on time or
-        * not, so for now we'll be quite conservative here about optimization and
-        * consider all python drivers to be depending on time.
-        */
-       if ((driver->type == DRIVER_TYPE_PYTHON) &&
-           python_driver_depends_on_time(driver))
-       {
-               TimeSourceKey time_src_key;
-               add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
-       }
 }
 
 void DepsgraphRelationBuilder::build_world(World *world)
@@ -1574,7 +1579,6 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
        if (object->modifiers.first != NULL) {
                LINKLIST_FOREACH (ModifierData *, md, &object->modifiers) {
                        const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type);
-
                        if (mti->updateDepsgraph) {
                                DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
                                mti->updateDepsgraph(
@@ -1584,23 +1588,10 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
                                        object,
                                        reinterpret_cast< ::DepsNodeHandle* >(&handle));
                        }
-
                        if (BKE_object_modifier_use_time(object, md)) {
                                TimeSourceKey time_src_key;
                                add_relation(time_src_key, obdata_ubereval_key, "Time Source");
-
-                               /* Hacky fix for T45633 (Animated modifiers aren't updated)
-                                *
-                                * This check works because BKE_object_modifier_use_time() tests
-                                * for either the modifier needing time, or that it is animated.
-                                */
-                               /* XXX: Remove this hack when these links are added as part of build_animdata() instead */
-                               if (modifier_dependsOnTime(md) == false && needs_animdata_node(&object->id)) {
-                                       ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION);
-                                       add_relation(animation_key, obdata_ubereval_key, "Modifier Animation");
-                               }
                        }
-
                        if (md->type == eModifierType_Cloth) {
                                build_cloth(object, md);
                        }
@@ -1733,16 +1724,6 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object)
        if (key) {
                build_shapekeys(obdata, key);
        }
-
-       if (needs_animdata_node(obdata)) {
-               ComponentKey animation_key(obdata, DEG_NODE_TYPE_ANIMATION);
-               ComponentKey parameters_key(obdata, DEG_NODE_TYPE_PARAMETERS);
-               add_relation(animation_key, parameters_key, "Geom Parameters");
-               /* Evaluation usually depends on animation.
-                * TODO(sergey): Need to re-hook it after granular update is implemented..
-                */
-               add_relation(animation_key, obdata_geom_eval_key, "Animation");
-       }
 }
 
 /* Cameras */
@@ -1762,11 +1743,6 @@ void DepsgraphRelationBuilder::build_camera(Object *object)
        add_relation(camera_parameters_key, object_parameters_key,
                     "Camera -> Object");
 
-       if (needs_animdata_node(camera_id)) {
-               ComponentKey animation_key(camera_id, DEG_NODE_TYPE_ANIMATION);
-               add_relation(animation_key, camera_parameters_key, "Camera Parameters");
-       }
-
        /* DOF */
        if (cam->dof_ob != NULL) {
                ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM);
@@ -1790,18 +1766,12 @@ void DepsgraphRelationBuilder::build_lamp(Object *object)
        add_relation(lamp_parameters_key, object_parameters_key,
                     "Lamp -> Object");
 
-       if (needs_animdata_node(lamp_id)) {
-               ComponentKey animation_key(lamp_id, DEG_NODE_TYPE_ANIMATION);
-               add_relation(animation_key, lamp_parameters_key, "Lamp Parameters");
-       }
-
        /* lamp's nodetree */
-       if (la->nodetree) {
+       if (la->nodetree != NULL) {
                build_nodetree(la->nodetree);
                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);
 
@@ -1866,11 +1836,6 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
                }
        }
 
-       if (needs_animdata_node(ntree_id)) {
-               ComponentKey animation_key(ntree_id, DEG_NODE_TYPE_ANIMATION);
-               add_relation(animation_key, shading_key, "NTree Parameters");
-       }
-
        OperationKey shading_update_key(ntree_id,
                                        DEG_NODE_TYPE_SHADING,
                                        DEG_OPCODE_MATERIAL_UPDATE);
@@ -1951,15 +1916,6 @@ void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
        // TODO: parent object (when that feature is implemented)
 }
 
-bool DepsgraphRelationBuilder::needs_animdata_node(ID *id)
-{
-       AnimData *adt = BKE_animdata_from_id(id);
-       if (adt != NULL) {
-               return (adt->action != NULL) || (adt->nla_tracks.first != NULL);
-       }
-       return false;
-}
-
 void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file) {
        /* Animation. */
        build_animdata(&cache_file->id);
index 569383fe479ba5060a2383dd65347d55eedc6c6d..9f661b8e8254c5b8f41b1a8d6e1ef4acdf3f5106 100644 (file)
@@ -31,6 +31,7 @@
 #pragma once
 
 #include <cstdio>
+#include <cstring>
 
 #include "intern/depsgraph_types.h"
 
@@ -43,6 +44,7 @@
 #include "BLI_string.h"
 
 #include "intern/nodes/deg_node.h"
+#include "intern/nodes/deg_node_component.h"
 #include "intern/nodes/deg_node_operation.h"
 
 struct Base;
@@ -175,17 +177,20 @@ struct DepsgraphRelationBuilder
        template <typename KeyFrom, typename KeyTo>
        void add_relation(const KeyFrom& key_from,
                          const KeyTo& key_to,
-                         const char *description);
+                         const char *description,
+                         bool check_unique = false);
 
        template <typename KeyTo>
        void add_relation(const TimeSourceKey& key_from,
                          const KeyTo& key_to,
-                         const char *description);
+                         const char *description,
+                         bool check_unique = false);
 
        template <typename KeyType>
        void add_node_handle_relation(const KeyType& key_from,
                                      const DepsNodeHandle *handle,
-                                     const char *description);
+                                     const char *description,
+                                     bool check_unique = false);
 
        void build_view_layer(Scene *scene, ViewLayer *view_layer);
        void build_group(Object *object, Group *group);
@@ -199,7 +204,12 @@ struct DepsgraphRelationBuilder
                               ListBase *constraints,
                               RootPChanMap *root_map);
        void build_animdata(ID *id);
+       void build_animdata_curves(ID *id);
+       void build_animdata_curves_targets(ID *id);
+       void build_animdata_drievrs(ID *id);
        void build_driver(ID *id, FCurve *fcurve);
+       void build_driver_data(ID *id, FCurve *fcurve);
+       void build_driver_variables(ID *id, FCurve *fcurve);
        void build_world(World *world);
        void build_rigidbody(Scene *scene);
        void build_particles(Object *object);
@@ -276,16 +286,19 @@ protected:
 
        void add_time_relation(TimeSourceDepsNode *timesrc,
                               DepsNode *node_to,
-                              const char *description);
+                              const char *description,
+                              bool check_unique = false);
        void add_operation_relation(OperationDepsNode *node_from,
                                    OperationDepsNode *node_to,
-                                   const char *description);
+                                   const char *description,
+                                   bool check_unique = false);
 
        template <typename KeyType>
        DepsNodeHandle create_node_handle(const KeyType& key,
                                          const char *default_name = "");
 
-       bool needs_animdata_node(ID *id);
+       template <typename KeyFrom, typename KeyTo>
+       bool is_same_bone_dependency(const KeyFrom& key_from, const KeyTo& key_to);
 
 private:
        /* State which never changes, same for the whole builder time. */
@@ -298,10 +311,12 @@ private:
 
 struct DepsNodeHandle
 {
-       DepsNodeHandle(DepsgraphRelationBuilder *builder, OperationDepsNode *node, const char *default_name = "") :
-           builder(builder),
-           node(node),
-           default_name(default_name)
+       DepsNodeHandle(DepsgraphRelationBuilder *builder,
+                      OperationDepsNode *node,
+                      const char *default_name = "")
+               : builder(builder),
+                 node(node),
+                 default_name(default_name)
        {
                BLI_assert(node != NULL);
        }
@@ -311,92 +326,7 @@ struct DepsNodeHandle
        const char *default_name;
 };
 
-/* Utilities for Builders ----------------------------------------------------- */
-
-template <typename KeyType>
-OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key)
-{
-       DepsNode *node = get_node(key);
-       return node != NULL ? node->get_exit_operation() : NULL;
-}
-
-template <typename KeyFrom, typename KeyTo>
-void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
-                                            const KeyTo &key_to,
-                                            const char *description)
-{
-       DepsNode *node_from = get_node(key_from);
-       DepsNode *node_to = get_node(key_to);
-       OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
-       OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
-       if (op_from && op_to) {
-               add_operation_relation(op_from, op_to, description);
-       }
-       else {
-               if (!op_from) {
-                       /* XXX TODO handle as error or report if needed */
-                       fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
-                               description, key_from.identifier().c_str());
-               }
-               else {
-                       fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
-                               description, key_from.identifier().c_str());
-               }
-               if (!op_to) {
-                       /* XXX TODO handle as error or report if needed */
-                       fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
-                               description, key_to.identifier().c_str());
-               }
-               else {
-                       fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
-                               description, key_to.identifier().c_str());
-               }
-       }
-}
-
-template <typename KeyTo>
-void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
-                                            const KeyTo &key_to,
-                                            const char *description)
-{
-       TimeSourceDepsNode *time_from = get_node(key_from);
-       DepsNode *node_to = get_node(key_to);
-       OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
-       if (time_from != NULL && op_to != NULL) {
-               add_time_relation(time_from, op_to, description);
-       }
-}
-
-template <typename KeyType>
-void DepsgraphRelationBuilder::add_node_handle_relation(
-        const KeyType &key_from,
-        const DepsNodeHandle *handle,
-        const char *description)
-{
-       DepsNode *node_from = get_node(key_from);
-       OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
-       OperationDepsNode *op_to = handle->node->get_entry_operation();
-       if (op_from != NULL && op_to != NULL) {
-               add_operation_relation(op_from, op_to, description);
-       }
-       else {
-               if (!op_from) {
-                       fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
-                               description, key_from.identifier().c_str());
-               }
-               if (!op_to) {
-                       fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
-                               description, key_from.identifier().c_str());
-               }
-       }
-}
+}  // namespace DEG
 
-template <typename KeyType>
-DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
-        const KeyType &key,
-        const char *default_name)
-{
-       return DepsNodeHandle(this, get_node(key), default_name);
-}
 
-}  // namespace DEG
+#include "intern/builder/deg_builder_relations_impl.h"
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
new file mode 100644 (file)
index 0000000..ba55a83
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Lukas Toenne
+ * Contributor(s): Sergey SHarybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/builder/deg_builder_relations_impl.h
+ *  \ingroup depsgraph
+ */
+
+#pragma once
+
+namespace DEG {
+
+template <typename KeyType>
+OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key)
+{
+       DepsNode *node = get_node(key);
+       return node != NULL ? node->get_exit_operation() : NULL;
+}
+
+template <typename KeyFrom, typename KeyTo>
+void DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
+                                            const KeyTo &key_to,
+                                            const char *description,
+                                            bool check_unique)
+{
+       DepsNode *node_from = get_node(key_from);
+       DepsNode *node_to = get_node(key_to);
+       OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+       OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+       if (op_from && op_to) {
+               add_operation_relation(op_from, op_to, description, check_unique);
+       }
+       else {
+               if (!op_from) {
+                       /* XXX TODO handle as error or report if needed */
+                       fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
+                               description, key_from.identifier().c_str());
+               }
+               else {
+                       fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
+                               description, key_from.identifier().c_str());
+               }
+               if (!op_to) {
+                       /* XXX TODO handle as error or report if needed */
+                       fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
+                               description, key_to.identifier().c_str());
+               }
+               else {
+                       fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
+                               description, key_to.identifier().c_str());
+               }
+       }
+}
+
+template <typename KeyTo>
+void DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
+                                            const KeyTo &key_to,
+                                            const char *description,
+                                            bool check_unique)
+{
+       TimeSourceDepsNode *time_from = get_node(key_from);
+       DepsNode *node_to = get_node(key_to);
+       OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+       if (time_from != NULL && op_to != NULL) {
+               add_time_relation(time_from, op_to, description, check_unique);
+       }
+}
+
+template <typename KeyType>
+void DepsgraphRelationBuilder::add_node_handle_relation(
+        const KeyType &key_from,
+        const DepsNodeHandle *handle,
+        const char *description,
+        bool check_unique)
+{
+       DepsNode *node_from = get_node(key_from);
+       OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+       OperationDepsNode *op_to = handle->node->get_entry_operation();
+       if (op_from != NULL && op_to != NULL) {
+               add_operation_relation(op_from, op_to, description, check_unique);
+       }
+       else {
+               if (!op_from) {
+                       fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
+                               description, key_from.identifier().c_str());
+               }
+               if (!op_to) {
+                       fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
+                               description, key_from.identifier().c_str());
+               }
+       }
+}
+
+template <typename KeyType>
+DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
+        const KeyType &key,
+        const char *default_name)
+{
+       return DepsNodeHandle(this, get_node(key), default_name);
+}
+
+/* Rig compatibility: we check if bone is using local transform as a variable
+ * for driver on itself and ignore those relations to avoid "false-positive"
+ * dependency cycles.
+ */
+template <typename KeyFrom, typename KeyTo>
+bool DepsgraphRelationBuilder::is_same_bone_dependency(const KeyFrom& key_from,
+                                                       const KeyTo& key_to)
+{
+       /* Get operations for requested keys. */
+       DepsNode *node_from = get_node(key_from);
+       DepsNode *node_to = get_node(key_to);
+       if (node_from == NULL || node_to == NULL) {
+               return false;
+       }
+       OperationDepsNode *op_from = node_from->get_exit_operation();
+       OperationDepsNode *op_to = node_to->get_entry_operation();
+       if (op_from == NULL || op_to == NULL) {
+               return false;
+       }
+       /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
+       if (!(op_from->opcode == DEG_OPCODE_BONE_DONE &&
+             op_to->opcode == DEG_OPCODE_BONE_LOCAL)) {
+               return false;
+       }
+       /* ... BUT, we also need to check if it's same bone.  */
+       if (!STREQ(op_from->owner->name, op_to->owner->name)) {
+               return false;
+       }
+       return true;
+}
+
+}  // namespace DEG
index 2a2108e84803bec99d84d3e04b7be58317a7bcb5..2aff1ca33c7c6e873c1a247267c0cd7d0c0fde06 100644 (file)
@@ -324,11 +324,6 @@ void DepsgraphRelationBuilder::build_rig(Object *object)
                                  "Armature Eval");
        add_relation(armature_key, init_key, "Data dependency");
 
-       if (needs_animdata_node(&object->id)) {
-               ComponentKey animation_key(&object->id, DEG_NODE_TYPE_ANIMATION);
-               add_relation(animation_key, init_key, "Rig Animation");
-       }
-
        /* IK Solvers...
         * - These require separate processing steps are pose-level
         *   to be executed between chains of bones (i.e. once the
index e30e00e61b588b4cb1f5b8ee1f8fa34013cec645..4fea8b49706eb872a4b8884e0924b071ccbf54b9 100644 (file)
@@ -103,41 +103,39 @@ Depsgraph::~Depsgraph()
 
 /* Query Conditions from RNA ----------------------- */
 
-static bool pointer_to_id_node_criteria(const PointerRNA *ptr,
-                                        const PropertyRNA *prop,
-                                        ID **id)
-{
-       if (ptr->type == NULL) {
-               return false;
-       }
-       if (prop != NULL) {
-               if (RNA_struct_is_ID(ptr->type)) {
-                       *id = (ID *)ptr->data;
-                       return true;
-               }
-       }
-       return false;
-}
-
-static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
-                                               const PropertyRNA *prop,
-                                               ID **id,
-                                               eDepsNode_Type *type,
-                                               const char **subdata)
+static bool pointer_to_component_node_criteria(
+        const PointerRNA *ptr,
+        const PropertyRNA *prop,
+        ID **id,
+        eDepsNode_Type *type,
+        const char **subdata,
+        eDepsOperation_Code *operation_code,
+        const char **operation_name,
+        int *operation_name_tag)
 {
        if (ptr->type == NULL) {
                return false;
        }
        /* Set default values for returns. */
-       *id      = (ID *)ptr->id.data;  /* For obvious reasons... */
-       *subdata = "";                 /* Default to no subdata (e.g. bone) name
-                                       * lookup in most cases. */
+       *id = (ID *)ptr->id.data;
+       *subdata = "";
+       *operation_code = DEG_OPCODE_OPERATION;
+       *operation_name = "";
+       *operation_name_tag = -1;
        /* Handling of commonly known scenarios. */
        if (ptr->type == &RNA_PoseBone) {
                bPoseChannel *pchan = (bPoseChannel *)ptr->data;
-               /* Bone - generally, we just want the bone component. */
-               *type = DEG_NODE_TYPE_BONE;
-               *subdata = pchan->name;
+               if (prop != NULL && RNA_property_is_idprop(prop)) {
+                       *type = DEG_NODE_TYPE_PARAMETERS;
+                       *subdata = "";
+                       *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
+                       *operation_name = pchan->name;;
+               }
+               else {
+                       /* Bone - generally, we just want the bone component. */
+                       *type = DEG_NODE_TYPE_BONE;
+                       *subdata = pchan->name;
+               }
                return true;
        }
        else if (ptr->type == &RNA_Bone) {
@@ -200,7 +198,12 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
                 * owns it.
                 */
                *id = key->from;
-               *type = DEG_NODE_TYPE_PARAMETERS;
+               *type = DEG_NODE_TYPE_GEOMETRY;
+               return true;
+       }
+       else if (ptr->type == &RNA_Key) {
+               *id = (ID *)ptr->id.data;
+               *type = DEG_NODE_TYPE_GEOMETRY;
                return true;
        }
        else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
@@ -213,6 +216,9 @@ static bool pointer_to_component_node_criteria(const PointerRNA *ptr,
        if (prop != NULL) {
                /* All unknown data effectively falls under "parameter evaluation". */
                *type = DEG_NODE_TYPE_PARAMETERS;
+               *operation_code = DEG_OPCODE_PARAMETERS_EVAL;
+               *operation_name = "";
+               *operation_name_tag = -1;
                return true;
        }
        return false;
@@ -223,20 +229,32 @@ DepsNode *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
                                             const PropertyRNA *prop) const
 {
        ID *id;
-       eDepsNode_Type type;
-       const char *name;
-
-       /* Get querying conditions. */
-       if (pointer_to_id_node_criteria(ptr, prop, &id)) {
-               return find_id_node(id);
-       }
-       else if (pointer_to_component_node_criteria(ptr, prop, &id, &type, &name)) {
+       eDepsNode_Type node_type;
+       const char *component_name, *operation_name;
+       eDepsOperation_Code operation_code;
+       int operation_name_tag;
+
+       if (pointer_to_component_node_criteria(
+                        ptr, prop,
+                        &id, &node_type, &component_name,
+                        &operation_code, &operation_name, &operation_name_tag))
+       {
                IDDepsNode *id_node = find_id_node(id);
-               if (id_node != NULL) {
-                       return id_node->find_component(type, name);
+               if (id_node == NULL) {
+                       return NULL;
+               }
+               ComponentDepsNode *comp_node =
+                       id_node->find_component(node_type, component_name);
+               if (comp_node == NULL) {
+                       return NULL;
+               }
+               if (operation_code == DEG_OPCODE_OPERATION) {
+                       return comp_node;
                }
+               return comp_node->find_operation(operation_code,
+                                                operation_name,
+                                                operation_name_tag);
        }
-
        return NULL;
 }
 
@@ -318,10 +336,18 @@ void Depsgraph::clear_id_nodes()
 /* Add new relationship between two nodes. */
 DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
                                           OperationDepsNode *to,
-                                          const char *description)
+                                          const char *description,
+                                          bool check_unique)
 {
+       DepsRelation *rel = NULL;
+       if (check_unique) {
+               rel = check_nodes_connected(from, to, description);
+       }
+       if (rel != NULL) {
+               return rel;
+       }
        /* Create new relation, and add it to the graph. */
-       DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
+       rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
        /* TODO(sergey): Find a better place for this. */
 #ifdef WITH_OPENSUBDIV
        ComponentDepsNode *comp_node = from->owner;
@@ -341,13 +367,38 @@ DepsRelation *Depsgraph::add_new_relation(OperationDepsNode *from,
 
 /* Add new relation between two nodes */
 DepsRelation *Depsgraph::add_new_relation(DepsNode *from, DepsNode *to,
-                                          const char *description)
+                                          const char *description,
+                                          bool check_unique)
 {
+       DepsRelation *rel = NULL;
+       if (check_unique) {
+               rel = check_nodes_connected(from, to, description);
+       }
+       if (rel != NULL) {
+               return rel;
+       }
        /* Create new relation, and add it to the graph. */
-       DepsRelation *rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
+       rel = OBJECT_GUARDED_NEW(DepsRelation, from, to, description);
        return rel;
 }
 
+DepsRelation *Depsgraph::check_nodes_connected(const DepsNode *from,
+                                               const DepsNode *to,
+                                               const char *description)
+{
+       foreach (DepsRelation *rel, from->outlinks) {
+               BLI_assert(rel->from == from);
+               if (rel->to != to) {
+                       continue;
+               }
+               if (description != NULL && !STREQ(rel->name, description)) {
+                       continue;
+               }
+               return rel;
+       }
+       return NULL;
+}
+
 /* ************************ */
 /* Relationships Management */
 
@@ -359,24 +410,6 @@ DepsRelation::DepsRelation(DepsNode *from,
     name(description),
     flag(0)
 {
-#ifndef NDEBUG
-/*
-       for (OperationDepsNode::Relations::const_iterator it = from->outlinks.begin();
-            it != from->outlinks.end();
-            ++it)
-       {
-               DepsRelation *rel = *it;
-               if (rel->from == from &&
-                   rel->to == to &&
-                   rel->type == type &&
-                   rel->name == description)
-               {
-                       BLI_assert(!"Duplicated relation, should not happen!");
-               }
-       }
-*/
-#endif
-
        /* Hook it up to the nodes which use it.
         *
         * NOTE: We register relation in the nodes which this link connects to here
index d841ae045f2cb05ec0e167651bda549e2a54a609..8a34be0c7a24ebe96001cdbbd76c7c257c76f29d 100644 (file)
@@ -123,11 +123,21 @@ struct Depsgraph {
        /* Add new relationship between two nodes. */
        DepsRelation *add_new_relation(OperationDepsNode *from,
                                       OperationDepsNode *to,
-                                      const char *description);
+                                      const char *description,
+                                      bool check_unique = false);
 
        DepsRelation *add_new_relation(DepsNode *from,
                                       DepsNode *to,
-                                      const char *description);
+                                      const char *description,
+                                      bool check_unique = false);
+
+       /* Check whether two nodes are connected by relation with given
+        * description. Description might be NULL to check ANY relation between
+        * given nodes.
+        */
+       DepsRelation *check_nodes_connected(const DepsNode *from,
+                                           const DepsNode *to,
+                                           const char *description);
 
        /* Tag a specific node as needing updates. */
        void add_entry_tag(OperationDepsNode *node);
index b7f038dd3f6c0df832fa6ba637c3c56d20e53a20..a99541385d0139ec2bd714abfebc61febe5e12e2 100644 (file)
@@ -741,6 +741,7 @@ extern StructRNA RNA_XorController;
 void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr);
 void RNA_id_pointer_create(struct ID *id, PointerRNA *r_ptr);
 void RNA_pointer_create(struct ID *id, StructRNA *type, void *data, PointerRNA *r_ptr);
+bool RNA_pointer_is_null(const PointerRNA *ptr);
 
 bool RNA_path_resolved_create(
         PointerRNA *ptr, struct PropertyRNA *prop,
index 6e90cd5a013a475f1978e32773c9afdf250d76c6..345c3d23dbe1cd6465cc584bfe311bc15dd9c22c 100644 (file)
@@ -175,6 +175,11 @@ void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
        }
 }
 
+bool RNA_pointer_is_null(const PointerRNA *ptr)
+{
+       return !((ptr->data != NULL) && (ptr->id.data != NULL) && (ptr->type != NULL));
+}
+
 static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
 {
        if (type && type->flag & STRUCT_ID) {