Merge branch 'master' into blender2.8

This commit is contained in:
Sergey Sharybin
2017-12-06 10:38:34 +01:00
10 changed files with 496 additions and 401 deletions

View 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

View 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,

View 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. */
@@ -899,26 +920,86 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
}
void DepsgraphRelationBuilder::build_animdata(ID *id)
{
/* Animation curves and NLA. */
build_animdata_curves(id);
/* Drivers. */
build_animdata_drievrs(id);
}
void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
if (adt == NULL)
if (adt == NULL) {
return;
ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION);
/* 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
}
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);
}
/* drivers */
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);
}
}
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);

View 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());
}
}
}
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"

View File

@@ -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

View 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

View 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;
eDepsNode_Type node_type;
const char *component_name, *operation_name;
eDepsOperation_Code operation_code;
int operation_name_tag;
/* 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)) {
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

View 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);

View 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,

View 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) {