diff options
author | Lukas Tönne <lukas.toenne@gmail.com> | 2018-04-15 13:16:55 +0300 |
---|---|---|
committer | Lukas Tönne <lukas.toenne@gmail.com> | 2018-04-15 13:16:55 +0300 |
commit | 7e1832c8d546ec13e752b7bd42ce13e3fc10ae86 (patch) | |
tree | 0fff9d878db69b288f909ff9a0f8aefe31ab8d80 /source/blender/depsgraph/intern/builder | |
parent | c0c8df3f2cf3ab03cec1f660619b0fe2290caf2a (diff) | |
parent | 94959dba1b53640e2a36cf9b5ca46aaf49c5c74a (diff) |
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/depsgraph/intern/builder')
14 files changed, 860 insertions, 857 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc index e30b9b44490..026aa309b02 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc @@ -46,6 +46,8 @@ namespace DEG { +namespace { + typedef enum eCyclicCheckVisitedState { /* Not is not visited at all during traversal. */ NODE_NOT_VISITED = 0, @@ -55,6 +57,30 @@ typedef enum eCyclicCheckVisitedState { NODE_IN_STACK = 2, } eCyclicCheckVisitedState; +struct StackEntry { + OperationDepsNode *node; + StackEntry *from; + DepsRelation *via_relation; +}; + +struct CyclesSolverState { + CyclesSolverState(Depsgraph *graph) + : graph(graph), + traversal_stack(BLI_stack_new(sizeof(StackEntry), + "DEG detect cycles stack")), + num_cycles(0) { + } + ~CyclesSolverState() { + BLI_stack_free(traversal_stack); + if (num_cycles != 0) { + printf("Detected %d dependency cycles\n", num_cycles); + } + } + Depsgraph *graph; + BLI_Stack *traversal_stack; + int num_cycles; +}; + BLI_INLINE void set_node_visited_state(DepsNode *node, eCyclicCheckVisitedState state) { @@ -76,18 +102,20 @@ BLI_INLINE int get_node_num_visited_children(DepsNode *node) return node->done >> 2; } -void deg_graph_detect_cycles(Depsgraph *graph) +void schedule_node_to_stack(CyclesSolverState *state, OperationDepsNode *node) { - struct StackEntry { - OperationDepsNode *node; - StackEntry *from; - DepsRelation *via_relation; - }; - - BLI_Stack *traversal_stack = BLI_stack_new(sizeof(StackEntry), - "DEG detect cycles stack"); + StackEntry entry; + entry.node = node; + entry.from = NULL; + entry.via_relation = NULL; + BLI_stack_push(state->traversal_stack, &entry); + set_node_visited_state(node, NODE_IN_STACK); +} - foreach (OperationDepsNode *node, graph->operations) { +/* Schedule leaf nodes (node without input links) for traversal. */ +void schedule_leaf_nodes(CyclesSolverState *state) +{ + foreach (OperationDepsNode *node, state->graph->operations) { bool has_inlinks = false; foreach (DepsRelation *rel, node->inlinks) { if (rel->from->type == DEG_NODE_TYPE_OPERATION) { @@ -96,18 +124,32 @@ void deg_graph_detect_cycles(Depsgraph *graph) } node->done = 0; if (has_inlinks == false) { - StackEntry entry; - entry.node = node; - entry.from = NULL; - entry.via_relation = NULL; - BLI_stack_push(traversal_stack, &entry); - set_node_visited_state(node, NODE_IN_STACK); + schedule_node_to_stack(state, node); } else { set_node_visited_state(node, NODE_NOT_VISITED); } } +} + +/* Schedule node which was not checked yet for being belong to + * any of dependency cycle. + */ +bool schedule_non_checked_node(CyclesSolverState *state) +{ + foreach (OperationDepsNode *node, state->graph->operations) { + if (get_node_visited_state(node) == NODE_NOT_VISITED) { + schedule_node_to_stack(state, node); + return true; + } + } + return false; +} +/* Solve cycles with all nodes which are scheduled for traversal. */ +void solve_cycles(CyclesSolverState *state) +{ + BLI_Stack *traversal_stack = state->traversal_stack; while (!BLI_stack_is_empty(traversal_stack)) { StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack); OperationDepsNode *node = entry->node; @@ -136,6 +178,7 @@ void deg_graph_detect_cycles(Depsgraph *graph) } /* TODO(sergey): So called russian roulette cycle solver. */ rel->flag |= DEPSREL_FLAG_CYCLIC; + ++state->num_cycles; } else if (to_state == NODE_NOT_VISITED) { StackEntry new_entry; @@ -155,8 +198,24 @@ void deg_graph_detect_cycles(Depsgraph *graph) BLI_stack_discard(traversal_stack); } } +} + +} // namespace - BLI_stack_free(traversal_stack); +void deg_graph_detect_cycles(Depsgraph *graph) +{ + CyclesSolverState state(graph); + /* First we solve cycles which are reachable from leaf nodes. */ + schedule_leaf_nodes(&state); + solve_cycles(&state); + /* We are not done yet. It is possible to have closed loop cycle, + * for example A -> B -> C -> A. These nodes were not scheduled + * yet (since they all have inlinks), and were not traversed since + * nobody else points to them. + */ + while (schedule_non_checked_node(&state)) { + solve_cycles(&state); + } } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc new file mode 100644 index 00000000000..67cb04d1b98 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc @@ -0,0 +1,64 @@ +/* + * ***** 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) 2018 Blender Foundation. + * All rights reserved. + * + * Original Author: Sergey Sharybin + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/depsgraph/intern/builder/deg_builder_map.cc + * \ingroup depsgraph + */ + +#include "intern/builder/deg_builder_map.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +namespace DEG { + +BuilderMap::BuilderMap() { + set = BLI_gset_ptr_new("deg builder gset"); +} + + +BuilderMap::~BuilderMap() { + BLI_gset_free(set, NULL); +} + +bool BuilderMap::checkIsBuilt(ID *id) { + return BLI_gset_haskey(set, id); +} + +void BuilderMap::tagBuild(ID *id) { + BLI_gset_insert(set, id); +} + +bool BuilderMap::checkIsBuiltAndTag(ID *id) { + void **key_p; + if (!BLI_gset_ensure_p_ex(set, id, &key_p)) { + *key_p = id; + return false; + } + return true; +} + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h new file mode 100644 index 00000000000..5ad22a9aa77 --- /dev/null +++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h @@ -0,0 +1,69 @@ +/* + * ***** 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) 2018 Blender Foundation. + * All rights reserved. + * + * Original Author: Sergey Sharybin + * Contributor(s): None Yet + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/depsgraph/intern/builder/deg_builder_map.h + * \ingroup depsgraph + */ + +#pragma once + +struct GSet; +struct ID; + +namespace DEG { + +class BuilderMap { +public: + BuilderMap(); + ~BuilderMap(); + + /* Check whether given ID is already handled by builder (or if it's being + * handled). + */ + bool checkIsBuilt(ID *id); + + /* Tag given ID as handled/built. */ + void tagBuild(ID *id); + + /* Combination of previous two functions, returns truth if ID was already + * handled, or tags is handled otherwise and return false. + */ + bool checkIsBuiltAndTag(ID *id); + + template<typename T> bool checkIsBuilt(T *datablock) { + return checkIsBuilt(&datablock->id); + } + template<typename T> void tagBuild(T *datablock) { + tagBuild(&datablock->id); + } + template<typename T> bool checkIsBuiltAndTag(T *datablock) { + return checkIsBuiltAndTag(&datablock->id); + } + + GSet *set; +}; + +} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 0ddb9fd3f28..994674f95fe 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -92,6 +92,7 @@ extern "C" { #include "BKE_node.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_rigidbody.h" #include "BKE_sound.h" #include "BKE_tracking.h" @@ -119,43 +120,11 @@ namespace DEG { namespace { -struct BuilderWalkUserData { - DepsgraphNodeBuilder *builder; -}; - -static void modifier_walk(void *user_data, - struct Object * /*object*/, - struct Object **obpoin, - int /*cb_flag*/) -{ - BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; - if (*obpoin) { - data->builder->build_object(NULL, - *obpoin, - DEG_ID_LINKED_INDIRECTLY); - } -} - -void constraint_walk(bConstraint * /*con*/, - ID **idpoin, - bool /*is_reference*/, - void *user_data) -{ - BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; - if (*idpoin) { - ID *id = *idpoin; - if (GS(id->name) == ID_OB) { - data->builder->build_object(NULL, - (Object *)id, - DEG_ID_LINKED_INDIRECTLY); - } - } -} - void free_copy_on_write_datablock(void *id_v) { ID *id = (ID *)id_v; deg_free_copy_on_write_datablock(id); + MEM_freeN(id); } } /* namespace */ @@ -169,6 +138,7 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph), scene_(NULL), + view_layer_(NULL), cow_id_hash_(NULL) { } @@ -180,10 +150,10 @@ DepsgraphNodeBuilder::~DepsgraphNodeBuilder() } } -IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag) +IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id) { if (!DEG_depsgraph_use_copy_on_write()) { - return graph_->add_id_node(id, do_tag); + return graph_->add_id_node(id); } IDDepsNode *id_node = NULL; ID *id_cow = (ID *)BLI_ghash_lookup(cow_id_hash_, id); @@ -193,12 +163,12 @@ IDDepsNode *DepsgraphNodeBuilder::add_id_node(ID *id, bool do_tag) */ BLI_ghash_remove(cow_id_hash_, id, NULL, NULL); } - id_node = graph_->add_id_node(id, do_tag, id_cow); + id_node = graph_->add_id_node(id, id_cow); /* Currently all ID nodes are supposed to have copy-on-write logic. * * NOTE: Zero number of components indicates that ID node was just created. */ - if (BLI_ghash_size(id_node->components) == 0) { + if (BLI_ghash_len(id_node->components) == 0) { ComponentDepsNode *comp_cow = id_node->add_component(DEG_NODE_TYPE_COPY_ON_WRITE); OperationDepsNode *op_cow = comp_cow->add_operation( @@ -286,6 +256,22 @@ OperationDepsNode *DepsgraphNodeBuilder::add_operation_node( name_tag); } +OperationDepsNode *DepsgraphNodeBuilder::ensure_operation_node( + ID *id, + eDepsNode_Type comp_type, + const DepsEvalOperationCb& op, + eDepsOperation_Code opcode, + const char *name, + int name_tag) +{ + OperationDepsNode *operation = + find_operation_node(id, comp_type, opcode, name, name_tag); + if (operation != NULL) { + return operation; + } + return add_operation_node(id, comp_type, op, opcode, name, name_tag); +} + bool DepsgraphNodeBuilder::has_operation_node(ID *id, eDepsNode_Type comp_type, const char *comp_name, @@ -334,41 +320,13 @@ ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig) /* ID is already remapped to copy-on-write. */ return id_orig; } - IDDepsNode *id_node = add_id_node(id_orig, false); - return id_node->id_cow; -} - -ID *DepsgraphNodeBuilder::expand_cow_id(IDDepsNode *id_node) -{ - return deg_expand_copy_on_write_datablock(graph_, id_node, this, true); -} - -ID *DepsgraphNodeBuilder::expand_cow_id(ID *id_orig) -{ IDDepsNode *id_node = add_id_node(id_orig); - return expand_cow_id(id_node); + return id_node->id_cow; } /* **** Build functions for entity nodes **** */ void DepsgraphNodeBuilder::begin_build() { - /* LIB_TAG_DOIT is used to indicate whether node for given ID was already - * created or not. This flag is being set in add_id_node(), so functions - * shouldn't bother with setting it, they only might query this flag when - * needed. - */ - BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false); - /* XXX nested node trees are not included in tag-clearing above, - * so we need to do this manually. - */ - FOREACH_NODETREE(bmain_, nodetree, id) - { - if (id != (ID *)nodetree) { - nodetree->id.tag &= ~LIB_TAG_DOIT; - } - } - FOREACH_NODETREE_END; - if (DEG_depsgraph_use_copy_on_write()) { /* Store existing copy-on-write versions of datablock, so we can re-use * them for new ID nodes. @@ -376,6 +334,9 @@ void DepsgraphNodeBuilder::begin_build() { cow_id_hash_ = BLI_ghash_ptr_new("Depsgraph id hash"); foreach (IDDepsNode *id_node, graph_->id_nodes) { if (deg_copy_on_write_is_expanded(id_node->id_cow)) { + if (id_node->id_orig == id_node->id_cow) { + continue; + } BLI_ghash_insert(cow_id_hash_, id_node->id_orig, id_node->id_cow); @@ -425,14 +386,12 @@ void DepsgraphNodeBuilder::end_build() void DepsgraphNodeBuilder::build_group(Group *group) { - ID *group_id = &group->id; - if (group_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(group)) { return; } - group_id->tag |= LIB_TAG_DOIT; /* Build group objects. */ - BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { - build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY); + LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { + build_object(-1, base->object, DEG_ID_LINKED_INDIRECTLY); } /* Operation to evaluate the whole view layer. * @@ -440,50 +399,50 @@ void DepsgraphNodeBuilder::build_group(Group *group) * This way we wouldn't need to worry about possible relations from DONE, * regardless whether it's a group or scene or something else. */ - add_id_node(group_id); + add_id_node(&group->id); Group *group_cow = get_cow_datablock(group); - add_operation_node(group_id, + add_operation_node(&group->id, DEG_NODE_TYPE_LAYER_COLLECTIONS, function_bind(BKE_group_eval_view_layers, _1, group_cow), - DEG_OPCODE_VIEW_LAYER_DONE); + DEG_OPCODE_VIEW_LAYER_EVAL); } -void DepsgraphNodeBuilder::build_object(Base *base, +void DepsgraphNodeBuilder::build_object(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state) { + const bool has_object = built_map_.checkIsBuiltAndTag(object); /* Skip rest of components if the ID node was already there. */ - if (object->id.tag & LIB_TAG_DOIT) { + if (has_object) { IDDepsNode *id_node = find_id_node(&object->id); /* We need to build some extra stuff if object becomes linked * directly. */ if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) { - build_object_flags(base, object, linked_state); + build_object_flags(base_index, object, linked_state); } id_node->linked_state = max(id_node->linked_state, linked_state); return; } - object->id.tag |= LIB_TAG_DOIT; /* Create ID node for object and begin init. */ IDDepsNode *id_node = add_id_node(&object->id); id_node->linked_state = linked_state; object->customdata_mask = 0; /* Various flags, flushing from bases/collections. */ - build_object_flags(base, object, linked_state); + build_object_flags(base_index, object, linked_state); /* Transform. */ build_object_transform(object); /* Parent. */ if (object->parent != NULL) { - build_object(NULL, object->parent, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY); } /* Modifiers. */ if (object->modifiers.first != NULL) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachObjectLink(object, modifier_walk, &data); + modifiers_foreachIDLink(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != NULL) { @@ -499,6 +458,11 @@ void DepsgraphNodeBuilder::build_object(Base *base, * on object's level animation, for example in case of rebuilding * pose for proxy. */ + OperationDepsNode *op_node = add_operation_node(&object->id, + DEG_NODE_TYPE_PARAMETERS, + NULL, + DEG_OPCODE_PARAMETERS_EVAL); + op_node->set_as_exit(); build_animdata(&object->id); /* Particle systems. */ if (object->particlesystem.first != NULL) { @@ -511,7 +475,7 @@ void DepsgraphNodeBuilder::build_object(Base *base, /* Object that this is a proxy for. */ if (object->proxy) { object->proxy->proxy_from = object; - build_object(NULL, object->proxy, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, object->proxy, DEG_ID_LINKED_INDIRECTLY); } /* Object dupligroup. */ if (object->dup_group != NULL) { @@ -520,11 +484,11 @@ void DepsgraphNodeBuilder::build_object(Base *base, } void DepsgraphNodeBuilder::build_object_flags( - Base *base, + int base_index, Object *object, eDepsNode_LinkedState_Type linked_state) { - if (base == NULL) { + if (base_index == -1) { return; } /* TODO(sergey): Is this really best component to be used? */ @@ -533,7 +497,9 @@ void DepsgraphNodeBuilder::build_object_flags( add_operation_node(&object->id, DEG_NODE_TYPE_LAYER_COLLECTIONS, function_bind(BKE_object_eval_flush_base_flags, - _1, object_cow, base, is_from_set), + _1, + object_cow, base_index, + is_from_set), DEG_OPCODE_OBJECT_BASE_FLAGS); } @@ -583,7 +549,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object) default: { ID *obdata = (ID *)object->data; - if ((obdata->tag & LIB_TAG_DOIT) == 0) { + if (built_map_.checkIsBuilt(obdata) == 0) { build_animdata(obdata); } break; @@ -702,7 +668,7 @@ void DepsgraphNodeBuilder::build_animdata(ID *id) } /* drivers */ - BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { + LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { /* create driver */ build_driver(id, fcu); } @@ -714,50 +680,69 @@ void DepsgraphNodeBuilder::build_animdata(ID *id) * \param id: ID-Block that driver is attached to * \param fcu: Driver-FCurve */ -OperationDepsNode *DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcu) +void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve) { ID *id_cow = get_cow_id(id); /* Create data node for this driver */ - /* TODO(sergey): Avoid creating same operation multiple times, - * in the future we need to avoid lookup of the operation as well - * and use some tagging magic instead. - */ - OperationDepsNode *driver_op = find_operation_node( - id, - DEG_NODE_TYPE_PARAMETERS, - DEG_OPCODE_DRIVER, - fcu->rna_path ? fcu->rna_path : "", - fcu->array_index); - - if (driver_op == NULL) { - /* TODO(sergey): Shall we use COW of fcu itself here? */ - driver_op = add_operation_node(id, - DEG_NODE_TYPE_PARAMETERS, - function_bind(BKE_animsys_eval_driver, - _1, - id_cow, - fcu), - DEG_OPCODE_DRIVER, - fcu->rna_path ? fcu->rna_path : "", - fcu->array_index); + /* TODO(sergey): Shall we use COW of fcu itself here? */ + ensure_operation_node(id, + DEG_NODE_TYPE_PARAMETERS, + function_bind(BKE_animsys_eval_driver, _1, id_cow, fcurve), + DEG_OPCODE_DRIVER, + fcurve->rna_path ? fcurve->rna_path : "", + fcurve->array_index); + build_driver_variables(id, fcurve); +} + +void DepsgraphNodeBuilder::build_driver_variables(ID * id, FCurve *fcurve) +{ + build_driver_id_property(id, fcurve->rna_path); + LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) { + DRIVER_TARGETS_USED_LOOPER(dvar) + { + build_driver_id_property(dtar->id, dtar->rna_path); + } + DRIVER_TARGETS_LOOPER_END } +} - /* return driver node created */ - return driver_op; +void DepsgraphNodeBuilder::build_driver_id_property(ID *id, + const char *rna_path) +{ + if (id == NULL || rna_path == NULL) { + return; + } + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + RNA_id_pointer_create(id, &id_ptr); + if (!RNA_path_resolve_full(&id_ptr, rna_path, &ptr, &prop, NULL)) { + return; + } + if (prop == NULL) { + return; + } + if (!RNA_property_is_idprop(prop)) { + return; + } + const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop); + ensure_operation_node(id, + DEG_NODE_TYPE_PARAMETERS, + NULL, + DEG_OPCODE_ID_PROPERTY, + prop_identifier); } /* Recursively build graph for world */ void DepsgraphNodeBuilder::build_world(World *world) { - ID *world_id = &world->id; - if (world_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(world)) { return; } /* Animation. */ - build_animdata(world_id); + build_animdata(&world->id); /* world itself */ - add_operation_node(world_id, + add_operation_node(&world->id, DEG_NODE_TYPE_SHADING, function_bind(BKE_world_eval, _1, @@ -820,7 +805,7 @@ void DepsgraphNodeBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - BLI_LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { Object *object = base->object; if (!object || (object->type != OB_MESH)) @@ -856,8 +841,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object) * blackbox evaluation step for one particle system referenced by * the particle systems stack. All dependencies link to this operation. */ - - /* component for all particle systems */ + /* Component for all particle systems. */ ComponentDepsNode *psys_comp = add_component_node(&object->id, DEG_NODE_TYPE_EVAL_PARTICLES); @@ -871,54 +855,57 @@ void DepsgraphNodeBuilder::build_particles(Object *object) scene_cow, ob_cow), DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT); - - /* particle systems */ - BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + /* Build all particle systems. */ + LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { ParticleSettings *part = psys->part; - /* Build particle settings operations. * * NOTE: The call itself ensures settings are only build once. */ build_particle_settings(part); - - /* Update on particle settings change. */ - add_operation_node(psys_comp, - function_bind(BKE_particle_system_settings_eval, - _1, - psys), - DEG_OPCODE_PARTICLE_SETTINGS_EVAL, - psys->name); - /* Particle system evaluation. */ add_operation_node(psys_comp, NULL, DEG_OPCODE_PARTICLE_SYSTEM_EVAL, psys->name); + /* Visualization of particle system. */ + switch (part->ren_as) { + case PART_DRAW_OB: + if (part->dup_ob != NULL) { + build_object(-1, + part->dup_ob, + DEG_ID_LINKED_INDIRECTLY); + } + break; + case PART_DRAW_GR: + if (part->dup_group != NULL) { + build_group(part->dup_group); + } + break; + } } /* TODO(sergey): Do we need a point cache operations here? */ + add_operation_node(&object->id, + DEG_NODE_TYPE_CACHE, + function_bind(BKE_ptcache_object_reset, + scene_cow, + ob_cow, + PTCACHE_RESET_DEPSGRAPH), + DEG_OPCODE_POINT_CACHE_RESET); } void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *part) { - ID *part_id = &part->id; - if (part_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(part)) { return; } - part_id->tag |= LIB_TAG_DOIT; /* Animation data. */ - build_animdata(part_id); + build_animdata(&part->id); /* Parameters change. */ - add_operation_node(part_id, + add_operation_node(&part->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PARTICLE_SETTINGS_EVAL); - add_operation_node(part_id, - DEG_NODE_TYPE_PARAMETERS, - function_bind(BKE_particle_system_settings_recalc_clear, - _1, - part), - DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR); } void DepsgraphNodeBuilder::build_cloth(Object *object) @@ -952,17 +939,6 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) Scene *scene_cow = get_cow_datablock(scene_); Object *object_cow = get_cow_datablock(object); - /* TODO(sergey): This way using this object's properties as driver target - * works fine. - * - * Does this depend on other nodes? - */ - op_node = add_operation_node(&object->id, - DEG_NODE_TYPE_PARAMETERS, - NULL, - DEG_OPCODE_PARAMETERS_EVAL); - op_node->set_as_exit(); - /* Temporary uber-update node, which does everything. * It is for the being we're porting old dependencies into the new system. * We'll get rid of this node as soon as all the granular update functions @@ -989,7 +965,7 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) // TODO: "Done" operation /* Cloth modifier. */ - BLI_LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { if (md->type == eModifierType_Cloth) { build_cloth(object); } @@ -1020,10 +996,9 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) } ID *obdata = (ID *)object->data; - if (obdata->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(obdata)) { return; } - obdata->tag |= LIB_TAG_DOIT; /* Make sure we've got an ID node before requesting CoW pointer. */ (void) add_id_node((ID *)obdata); ID *obdata_cow = get_cow_id(obdata); @@ -1103,13 +1078,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) */ Curve *cu = (Curve *)obdata; if (cu->bevobj != NULL) { - build_object(NULL, cu->bevobj, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->bevobj, DEG_ID_LINKED_INDIRECTLY); } if (cu->taperobj != NULL) { - build_object(NULL, cu->taperobj, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->taperobj, DEG_ID_LINKED_INDIRECTLY); } if (object->type == OB_FONT && cu->textoncurve != NULL) { - build_object(NULL, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY); } break; } @@ -1164,24 +1139,14 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object) /* Cameras */ void DepsgraphNodeBuilder::build_camera(Object *object) { - /* Object itself. */ - add_operation_node(&object->id, - DEG_NODE_TYPE_PARAMETERS, - NULL, - DEG_OPCODE_PARAMETERS_EVAL, - "Camera Parameters"); - /* Object data. */ - /* TODO: Link scene-camera links in somehow. */ - Camera *cam = (Camera *)object->data; - ID *camera_id = &cam->id; - if (camera_id->tag & LIB_TAG_DOIT) { + /* TODO: Link scene-camera links in somehow... */ + Camera *camera = (Camera *)object->data; + if (built_map_.checkIsBuiltAndTag(camera)) { return; } - - build_animdata(&cam->id); - - add_operation_node(camera_id, + build_animdata(&camera->id); + add_operation_node(&camera->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PARAMETERS_EVAL); @@ -1190,34 +1155,20 @@ void DepsgraphNodeBuilder::build_camera(Object *object) /* Lamps */ void DepsgraphNodeBuilder::build_lamp(Object *object) { - /* Object itself. */ - add_operation_node(&object->id, - DEG_NODE_TYPE_PARAMETERS, - NULL, - DEG_OPCODE_PARAMETERS_EVAL, - "Lamp Parameters"); - /* Object data. */ - Lamp *la = (Lamp *)object->data; - ID *lamp_id = &la->id; - if (lamp_id->tag & LIB_TAG_DOIT) { + Lamp *lamp = (Lamp *)object->data; + if (built_map_.checkIsBuiltAndTag(lamp)) { return; } - - build_animdata(&la->id); - - add_operation_node(lamp_id, + build_animdata(&lamp->id); + add_operation_node(&lamp->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PARAMETERS_EVAL); - /* lamp's nodetree */ - if (la->nodetree) { - build_nodetree(la->nodetree); - } - + build_nodetree(lamp->nodetree); /* textures */ - build_texture_stack(la->mtex); + build_texture_stack(lamp->mtex); } void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) @@ -1225,21 +1176,23 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) if (ntree == NULL) { return; } + if (built_map_.checkIsBuiltAndTag(ntree)) { + return; + } /* nodetree itself */ - ID *ntree_id = &ntree->id; - add_id_node(ntree_id); + add_id_node(&ntree->id); bNodeTree *ntree_cow = get_cow_datablock(ntree); /* Animation, */ - build_animdata(ntree_id); + build_animdata(&ntree->id); /* Shading update. */ - add_operation_node(ntree_id, + add_operation_node(&ntree->id, DEG_NODE_TYPE_SHADING, NULL, DEG_OPCODE_MATERIAL_UPDATE); /* NOTE: We really pass original and CoW node trees here, this is how the * callback works. Ideally we need to find a better way for that. */ - add_operation_node(ntree_id, + add_operation_node(&ntree->id, DEG_NODE_TYPE_SHADING_PARAMETERS, function_bind(BKE_nodetree_shading_params_eval, _1, @@ -1247,7 +1200,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) ntree), DEG_OPCODE_MATERIAL_UPDATE); /* nodetree's nodes... */ - BLI_LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { + LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { ID *id = bnode->id; if (id == NULL) { continue; @@ -1263,7 +1216,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) build_image((Image *)id); } else if (id_type == ID_OB) { - build_object(NULL, (Object *)id, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY); } else if (id_type == ID_SCE) { /* Scenes are used by compositor trees, and handled by render @@ -1275,9 +1228,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) } else if (bnode->type == NODE_GROUP) { bNodeTree *group_ntree = (bNodeTree *)id; - if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) { - build_nodetree(group_ntree); - } + build_nodetree(group_ntree); } else { BLI_assert(!"Unknown ID type used for node"); @@ -1290,23 +1241,21 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree) /* Recursively build graph for material */ void DepsgraphNodeBuilder::build_material(Material *material) { - ID *material_id = &material->id; - if (material_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(material)) { return; } - material_id->tag |= LIB_TAG_DOIT; /* Material itself. */ - add_id_node(material_id); + add_id_node(&material->id); Material *material_cow = get_cow_datablock(material); /* Shading update. */ - add_operation_node(material_id, + add_operation_node(&material->id, DEG_NODE_TYPE_SHADING, function_bind(BKE_material_eval, _1, material_cow), DEG_OPCODE_MATERIAL_UPDATE); /* Material animation. */ - build_animdata(material_id); + build_animdata(&material->id); /* Textures. */ build_texture_stack(material->mtex); /* Material's nodetree. */ @@ -1326,33 +1275,34 @@ void DepsgraphNodeBuilder::build_texture_stack(MTex **texture_stack) } /* Recursively build graph for texture */ -void DepsgraphNodeBuilder::build_texture(Tex *tex) +void DepsgraphNodeBuilder::build_texture(Tex *texture) { - ID *tex_id = &tex->id; - if (tex_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(texture)) { return; } - tex_id->tag |= LIB_TAG_DOIT; /* Texture itself. */ - build_animdata(tex_id); + build_animdata(&texture->id); /* Texture's nodetree. */ - build_nodetree(tex->nodetree); + build_nodetree(texture->nodetree); /* Special cases for different IDs which texture uses. */ - if (tex->type == TEX_IMAGE) { - if (tex->ima != NULL) { - build_image(tex->ima); + if (texture->type == TEX_IMAGE) { + if (texture->ima != NULL) { + build_image(texture->ima); } } + /* Placeholder so we can add relations and tag ID node for update. */ + add_operation_node(&texture->id, + DEG_NODE_TYPE_PARAMETERS, + NULL, + DEG_OPCODE_PLACEHOLDER); } void DepsgraphNodeBuilder::build_image(Image *image) { - ID *image_id = &image->id; - if (image_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(image)) { return; } - image_id->tag |= LIB_TAG_DOIT; /* Placeholder so we can add relations and tag ID node for update. */ - add_operation_node(image_id, + add_operation_node(&image->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, @@ -1431,13 +1381,11 @@ void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip) void DepsgraphNodeBuilder::build_lightprobe(Object *object) { LightProbe *probe = (LightProbe *)object->data; - ID *probe_id = &probe->id; - if (probe_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(probe)) { return; } - probe_id->tag |= LIB_TAG_DOIT; /* Placeholder so we can add relations and tag ID node for update. */ - add_operation_node(probe_id, + add_operation_node(&probe->id, DEG_NODE_TYPE_PARAMETERS, NULL, DEG_OPCODE_PLACEHOLDER, @@ -1448,7 +1396,56 @@ void DepsgraphNodeBuilder::build_lightprobe(Object *object) DEG_OPCODE_PLACEHOLDER, "LightProbe Eval"); - build_animdata(probe_id); + build_animdata(&probe->id); +} + +/* **** ID traversal callbacks functions **** */ + +void DepsgraphNodeBuilder::modifier_walk(void *user_data, + struct Object * /*object*/, + struct ID **idpoin, + int /*cb_flag*/) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + ID *id = *idpoin; + if (id == NULL) { + return; + } + switch (GS(id->name)) { + case ID_OB: + data->builder->build_object(-1, + (Object *)id, + DEG_ID_LINKED_INDIRECTLY); + break; + case ID_TE: + data->builder->build_texture((Tex *)id); + break; + default: + /* pass */ + break; + } +} + +void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/, + ID **idpoin, + bool /*is_reference*/, + void *user_data) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + ID *id = *idpoin; + if (id == NULL) { + return; + } + switch (GS(id->name)) { + case ID_OB: + data->builder->build_object(-1, + (Object *)id, + DEG_ID_LINKED_INDIRECTLY); + break; + default: + /* pass */ + break; + } } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 1482f7d947d..c933e139758 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -30,6 +30,7 @@ #pragma once +#include "intern/builder/deg_builder_map.h" #include "intern/depsgraph_types.h" #include "DEG_depsgraph.h" /* used for DEG_depsgraph_use_copy_on_write() */ @@ -89,16 +90,6 @@ struct DepsgraphNodeBuilder { return (T *)get_cow_id(&orig->id); } - /* Get fully expanded (ready for use) copy-on-write datablock for the given - * original datablock. - */ - ID *expand_cow_id(IDDepsNode *id_node); - ID *expand_cow_id(ID *id_orig); - template<typename T> - T *expand_cow_datablock(T *orig) { - return (T *)expand_cow_id(&orig->id); - } - /* For a given COW datablock get corresponding original one. */ template<typename T> T *get_orig_datablock(const T *cow) const { @@ -113,7 +104,7 @@ struct DepsgraphNodeBuilder { void begin_build(); void end_build(); - IDDepsNode *add_id_node(ID *id, bool do_tag = true); + IDDepsNode *add_id_node(ID *id); IDDepsNode *find_id_node(ID *id); TimeSourceDepsNode *add_time_source(); @@ -140,6 +131,13 @@ struct DepsgraphNodeBuilder { const char *name = "", int name_tag = -1); + OperationDepsNode *ensure_operation_node(ID *id, + eDepsNode_Type comp_type, + const DepsEvalOperationCb& op, + eDepsOperation_Code opcode, + const char *name = "", + int name_tag = -1); + bool has_operation_node(ID *id, eDepsNode_Type comp_type, const char *comp_name, @@ -164,22 +162,24 @@ struct DepsgraphNodeBuilder { ViewLayer *view_layer, eDepsNode_LinkedState_Type linked_state); void build_group(Group *group); - void build_object(Base *base, + void build_object(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); - void build_object_flags(Base *base, + void build_object_flags(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state); void build_object_data(Object *object); void build_object_transform(Object *object); void build_object_constraints(Object *object); - void build_pose_constraints(Object *object, bPoseChannel *pchan); + void build_pose_constraints(Object *object, bPoseChannel *pchan, int pchan_index); void build_rigidbody(Scene *scene); void build_particles(Object *object); void build_particle_settings(ParticleSettings *part); void build_cloth(Object *object); void build_animdata(ID *id); - OperationDepsNode *build_driver(ID *id, FCurve *fcurve); + void build_driver(ID *id, FCurve *fcurve); + void build_driver_variables(ID *id, FCurve *fcurve); + void build_driver_id_property(ID *id, const char *rna_path); void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con); @@ -205,17 +205,6 @@ struct DepsgraphNodeBuilder { void build_movieclip(MovieClip *clip); void build_lightprobe(Object *object); - struct LayerCollectionState { - int index; - LayerCollection *parent; - }; - void build_layer_collection(ID *owner_id, - LayerCollection *layer_collection, - LayerCollectionState *state); - void build_layer_collections(ID *owner_id, - ListBase *layer_collections, - LayerCollectionState *state); - void build_view_layer_collections(ID *owner_id, ViewLayer *view_layer); protected: struct SavedEntryTag { ID *id; @@ -224,14 +213,30 @@ protected: }; vector<SavedEntryTag> saved_entry_tags_; + struct BuilderWalkUserData { + DepsgraphNodeBuilder *builder; + }; + + static void modifier_walk(void *user_data, + struct Object *object, + struct ID **idpoin, + int cb_flag); + + static void constraint_walk(bConstraint *constraint, + ID **idpoin, + bool is_reference, + void *user_data); + /* State which never changes, same for the whole builder time. */ Main *bmain_; Depsgraph *graph_; /* State which demotes currently built entities. */ Scene *scene_; + ViewLayer *view_layer_; GHash *cow_id_hash_; + BuilderMap built_map_; }; } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc deleted file mode 100644 index 137a79e7276..00000000000 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc +++ /dev/null @@ -1,126 +0,0 @@ -/* - * ***** 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: Joshua Leung - * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc - * \ingroup depsgraph - * - * Methods for constructing depsgraph's nodes - */ - -#include "intern/builder/deg_builder_nodes.h" - -#include <stdio.h> -#include <stdlib.h> - -#include "MEM_guardedalloc.h" - -extern "C" { -#include "BLI_utildefines.h" -#include "BLI_listbase.h" -#include "BLI_string.h" - -#include "BKE_layer.h" - -#include "DNA_scene_types.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -} /* extern "C" */ - -#include "intern/builder/deg_builder.h" -#include "intern/eval/deg_eval_copy_on_write.h" -#include "intern/nodes/deg_node.h" -#include "intern/nodes/deg_node_component.h" -#include "intern/nodes/deg_node_operation.h" -#include "intern/depsgraph_types.h" -#include "intern/depsgraph_intern.h" -#include "util/deg_util_foreach.h" - -namespace DEG { - -void DepsgraphNodeBuilder::build_layer_collection( - ID *owner_id, - LayerCollection *layer_collection, - LayerCollectionState *state) -{ - /* TODO(sergey): This will attempt to create component for each collection. - * Harmless but could be optimized. - */ - ComponentDepsNode *comp = add_component_node( - owner_id, - DEG_NODE_TYPE_LAYER_COLLECTIONS); - - add_operation_node(comp, - function_bind(BKE_layer_eval_layer_collection, - _1, - layer_collection, - state->parent), - DEG_OPCODE_VIEW_LAYER_EVAL, - layer_collection->scene_collection->name, - state->index); - ++state->index; - - /* Recurs into nested layer collections. */ - LayerCollection *parent = state->parent; - state->parent = layer_collection; - build_layer_collections(owner_id, &layer_collection->layer_collections, state); - state->parent = parent; -} - -void DepsgraphNodeBuilder::build_layer_collections(ID *owner_id, - ListBase *layer_collections, - LayerCollectionState *state) -{ - BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) { - build_layer_collection(owner_id, layer_collection, state); - } -} - -void DepsgraphNodeBuilder::build_view_layer_collections( - ID *owner_id, - ViewLayer *view_layer) -{ - LayerCollectionState state; - state.index = 0; - ComponentDepsNode *comp = add_component_node( - owner_id, - DEG_NODE_TYPE_LAYER_COLLECTIONS); - add_operation_node(comp, - function_bind(BKE_layer_eval_layer_collection_pre, - _1, - owner_id, - view_layer), - DEG_OPCODE_VIEW_LAYER_INIT); - add_operation_node(comp, - function_bind(BKE_layer_eval_layer_collection_post, - _1, - view_layer), - DEG_OPCODE_VIEW_LAYER_DONE); - state.parent = NULL; - build_layer_collections(owner_id, &view_layer->layer_collections, &state); -} - -} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 2fc42efa440..208462713a5 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -50,6 +50,7 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_constraint.h" } /* extern "C" */ #include "DEG_depsgraph.h" @@ -67,15 +68,20 @@ extern "C" { namespace DEG { void DepsgraphNodeBuilder::build_pose_constraints(Object *object, - bPoseChannel *pchan) + bPoseChannel *pchan, + int pchan_index) { - /* create node for constraint stack */ + /* Pull indirect dependencies via constraints. */ + BuilderWalkUserData data; + data.builder = this; + BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data); + /* Create node for constraint stack. */ add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, function_bind(BKE_pose_constraints_evaluate, _1, get_cow_datablock(scene_), get_cow_datablock(object), - pchan), + pchan_index), DEG_OPCODE_BONE_CONSTRAINTS); } @@ -98,13 +104,15 @@ void DepsgraphNodeBuilder::build_ik_pose(Object *object, return; } + int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan); + BLI_assert(rootchan_index != -1); /* Operation node for evaluating/running IK Solver. */ add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, function_bind(BKE_pose_iktree_evaluate, _1, get_cow_datablock(scene_), get_cow_datablock(object), - rootchan), + rootchan_index), DEG_OPCODE_POSE_IK_SOLVER); } @@ -122,12 +130,14 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object, * Store the "root bone" of this chain in the solver, so it knows where to * start. */ + int rootchan_index = BLI_findindex(&object->pose->chanbase, rootchan); + BLI_assert(rootchan_index != -1); add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, rootchan->name, function_bind(BKE_pose_splineik_evaluate, _1, get_cow_datablock(scene_), get_cow_datablock(object), - rootchan), + rootchan_index), DEG_OPCODE_POSE_SPLINE_IK_SOLVER); } @@ -135,22 +145,15 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object, void DepsgraphNodeBuilder::build_rig(Object *object) { bArmature *armature = (bArmature *)object->data; - const short armature_tag = armature->id.tag; Scene *scene_cow; Object *object_cow; - bArmature *armature_cow; if (DEG_depsgraph_use_copy_on_write()) { - /* NOTE: We need to expand both object and armature, so this way we can - * safely create object level pose. - */ scene_cow = get_cow_datablock(scene_); - object_cow = expand_cow_datablock(object); - armature_cow = expand_cow_datablock(armature); + object_cow = get_cow_datablock(object); } else { scene_cow = scene_; object_cow = object; - armature_cow = armature; } OperationDepsNode *op_node; @@ -163,9 +166,8 @@ void DepsgraphNodeBuilder::build_rig(Object *object) * mechanism in-between here to ensure that we can use same rig * multiple times in same scene. */ - if ((armature_tag & LIB_TAG_DOIT) == 0) { + if (!built_map_.checkIsBuilt(armature)) { build_animdata(&armature->id); - /* Make sure pose is up-to-date with armature updates. */ add_operation_node(&armature->id, DEG_NODE_TYPE_PARAMETERS, @@ -175,22 +177,22 @@ void DepsgraphNodeBuilder::build_rig(Object *object) } /* Rebuild pose if not up to date. */ - if (object_cow->pose == NULL || (object->pose->flag & POSE_RECALC)) { - BKE_pose_rebuild(object_cow, armature_cow); + if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild(object, armature); /* XXX: Without this animation gets lost in certain circumstances * after loading file. Need to investigate further since it does * not happen with simple scenes.. */ - if (object_cow->adt) { - object_cow->adt->recalc |= ADT_RECALC_ANIM; + if (object->adt) { + object->adt->recalc |= ADT_RECALC_ANIM; } } /* speed optimization for animation lookups */ - if (object_cow->pose != NULL) { - BKE_pose_channels_hash_make(object_cow->pose); - if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { - BKE_pose_update_constraint_flags(object_cow->pose); + if (object->pose != NULL) { + BKE_pose_channels_hash_make(object->pose); + if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { + BKE_pose_update_constraint_flags(object->pose); } } @@ -222,8 +224,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) function_bind(BKE_pose_eval_init, _1, scene_cow, - object_cow, - object_cow->pose), + object_cow), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); @@ -232,8 +233,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) function_bind(BKE_pose_eval_init_ik, _1, scene_cow, - object_cow, - object_cow->pose), + object_cow), DEG_OPCODE_POSE_INIT_IK); op_node = add_operation_node(&object->id, @@ -241,13 +241,13 @@ void DepsgraphNodeBuilder::build_rig(Object *object) function_bind(BKE_pose_eval_flush, _1, scene_cow, - object_cow, - object_cow->pose), + object_cow), DEG_OPCODE_POSE_DONE); op_node->set_as_exit(); /* bones */ - BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) { + int pchan_index = 0; + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { /* Node for bone evaluation. */ op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, NULL, DEG_OPCODE_BONE_LOCAL); @@ -257,7 +257,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) function_bind(BKE_pose_eval_bone, _1, scene_cow, object_cow, - pchan), + pchan_index), DEG_OPCODE_BONE_POSE_PARENT); /* NOTE: Dedicated noop for easier relationship construction. */ @@ -266,7 +266,10 @@ void DepsgraphNodeBuilder::build_rig(Object *object) DEG_OPCODE_BONE_READY); op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, - function_bind(BKE_pose_bone_done, _1, pchan), + function_bind(BKE_pose_bone_done, + _1, + object_cow, + pchan_index), DEG_OPCODE_BONE_DONE); op_node->set_as_exit(); /* Custom properties. */ @@ -279,7 +282,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) } /* Build constraints. */ if (pchan->constraints.first != NULL) { - build_pose_constraints(object, pchan); + build_pose_constraints(object, pchan, pchan_index); } /** * IK Solvers. @@ -293,7 +296,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object) * as in ik-tree building * - Animated chain-lengths are a problem. */ - BLI_LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { + LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { switch (con->type) { case CONSTRAINT_TYPE_KINEMATIC: build_ik_pose(object, pchan, con); @@ -307,13 +310,13 @@ void DepsgraphNodeBuilder::build_rig(Object *object) break; } } + /* Custom shape. */ - /* NOTE: Custom shape datablock is already remapped to CoW version. */ if (pchan->custom != NULL) { - build_object(NULL, - get_orig_datablock(pchan->custom), - DEG_ID_LINKED_INDIRECTLY); + build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY); } + + pchan_index++; } } @@ -323,10 +326,7 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) OperationDepsNode *op_node; Object *object_cow; if (DEG_depsgraph_use_copy_on_write()) { - /* NOTE: We need to expand both object and armature, so this way we can - * safely create object level pose. - */ - object_cow = expand_cow_datablock(object); + object_cow = get_cow_datablock(object); } else { object_cow = object; @@ -337,8 +337,8 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) build_animdata(&arm->id); /* speed optimization for animation lookups */ BKE_pose_channels_hash_make(object->pose); - if (object_cow->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { - BKE_pose_update_constraint_flags(object_cow->pose); + if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) { + BKE_pose_update_constraint_flags(object->pose); } op_node = add_operation_node(&object->id, DEG_NODE_TYPE_EVAL_POSE, @@ -347,8 +347,8 @@ void DepsgraphNodeBuilder::build_proxy_rig(Object *object) object_cow), DEG_OPCODE_POSE_INIT); op_node->set_as_entry(); - BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object_cow->pose->chanbase) { - /* Local bone transform. */ + + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { op_node = add_operation_node(&object->id, DEG_NODE_TYPE_BONE, pchan->name, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 4ca19f4e14f..390619aeeaa 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -76,35 +76,14 @@ void DepsgraphNodeBuilder::build_view_layer( add_time_source(); /* Setup currently building context. */ scene_ = scene; - /* Expand Scene Cow datablock to get proper pointers to bases. */ + view_layer_ = view_layer; + /* Get pointer to a CoW version of scene ID. */ Scene *scene_cow; - ViewLayer *view_layer_cow; if (DEG_depsgraph_use_copy_on_write()) { - /* NOTE: We need to create ID nodes for all objects coming from bases, - * otherwise remapping will not replace objects with their CoW versions - * for CoW bases. - */ - BLI_LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { - Object *object = base->object; - add_id_node(&object->id, false); - } - /* Create ID node for nested ID of nodetree as well, otherwise remapping - * will not work correct either. - */ - if (scene->nodetree != NULL) { - add_id_node(&scene->nodetree->id, false); - } - /* Make sure we've got ID node, so we can get pointer to CoW datablock. - */ - scene_cow = expand_cow_datablock(scene); - view_layer_cow = (ViewLayer *)BLI_findstring( - &scene_cow->view_layers, - view_layer->name, - offsetof(ViewLayer, name)); + scene_cow = get_cow_datablock(scene); } else { scene_cow = scene; - view_layer_cow = view_layer; } /* Scene objects. */ int select_color = 1; @@ -112,17 +91,15 @@ void DepsgraphNodeBuilder::build_view_layer( * but object is expected to be an original one. Hence we go into some * tricks here iterating over the view layer. */ - for (Base *base_orig = (Base *)view_layer->object_bases.first, - *base_cow = (Base *)view_layer_cow->object_bases.first; - base_orig != NULL; - base_orig = base_orig->next, base_cow = base_cow->next) - { + int base_index = 0; + LISTBASE_FOREACH(Base *, base, &view_layer->object_bases) { /* object itself */ - build_object(base_cow, base_orig->object, linked_state); - base_orig->object->select_color = select_color++; + build_object(base_index, base->object, linked_state); + base->object->select_color = select_color++; + ++base_index; } if (scene->camera != NULL) { - build_object(NULL, scene->camera, DEG_ID_LINKED_INDIRECTLY); + build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY); } /* Rigidbody. */ if (scene->rigidbody_world != NULL) { @@ -145,19 +122,27 @@ void DepsgraphNodeBuilder::build_view_layer( build_gpencil(scene->gpd); } /* Cache file. */ - BLI_LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) { + LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) { build_cachefile(cachefile); } /* Masks. */ - BLI_LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) { + LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) { build_mask(mask); } /* Movie clips. */ - BLI_LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) { + LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) { build_movieclip(clip); } /* Collections. */ - build_view_layer_collections(&scene->id, view_layer_cow); + int view_layer_index = BLI_findindex(&scene->view_layers, view_layer); + BLI_assert(view_layer_index != -1); + add_operation_node(&scene->id, + DEG_NODE_TYPE_LAYER_COLLECTIONS, + function_bind(BKE_layer_eval_view_layer_indexed, + _1, + &scene_cow->id, + view_layer_index), + DEG_OPCODE_VIEW_LAYER_EVAL); /* Parameters evaluation for scene relations mainly. */ add_operation_node(&scene->id, DEG_NODE_TYPE_PARAMETERS, diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 04a72f85a78..7da2c4f54a1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -68,7 +68,7 @@ extern "C" { #include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" -#include "DNA_object_force.h" +#include "DNA_object_force_types.h" #include "BKE_action.h" #include "BKE_armature.h" @@ -117,39 +117,6 @@ extern "C" { namespace DEG { -namespace { - -struct BuilderWalkUserData { - DepsgraphRelationBuilder *builder; -}; - -void modifier_walk(void *user_data, - struct Object * /*object*/, - struct Object **obpoin, - int /*cb_flag*/) -{ - BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; - if (*obpoin) { - data->builder->build_object(NULL, *obpoin); - } -} - -void constraint_walk(bConstraint * /*con*/, - ID **idpoin, - bool /*is_reference*/, - void *user_data) -{ - BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; - if (*idpoin) { - ID *id = *idpoin; - if (GS(id->name) == ID_OB) { - data->builder->build_object(NULL, (Object *)id); - } - } -} - -} /* namespace */ - /* ***************** */ /* Relations Builder */ @@ -196,7 +163,7 @@ static bool particle_system_depends_on_time(ParticleSystem *psys) static bool object_particles_depends_on_time(Object *object) { - BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { if (particle_system_depends_on_time(psys)) { return true; } @@ -285,7 +252,7 @@ void DepsgraphRelationBuilder::add_time_relation(TimeSourceDepsNode *timesrc, graph_->add_new_relation(timesrc, node_to, description, check_unique); } else { - DEG_DEBUG_PRINTF("add_time_relation(%p = %s, %p = %s, %s) Failed\n", + DEG_DEBUG_PRINTF(BUILD, "add_time_relation(%p = %s, %p = %s, %s) Failed\n", timesrc, (timesrc) ? timesrc->identifier().c_str() : "<None>", node_to, (node_to) ? node_to->identifier().c_str() : "<None>", description); @@ -302,7 +269,7 @@ void DepsgraphRelationBuilder::add_operation_relation( 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", + DEG_DEBUG_PRINTF(BUILD, "add_operation_relation(%p = %s, %p = %s, %s) Failed\n", node_from, (node_from) ? node_from->identifier().c_str() : "<None>", node_to, (node_to) ? node_to->identifier().c_str() : "<None>", description); @@ -349,7 +316,7 @@ void DepsgraphRelationBuilder::add_forcefield_relations( { ListBase *effectors = pdInitEffectors(NULL, scene, object, psys, eff, false); if (effectors != NULL) { - BLI_LISTBASE_FOREACH (EffectorCache *, eff, effectors) { + LISTBASE_FOREACH (EffectorCache *, eff, effectors) { if (eff->ob != object) { ComponentKey eff_key(&eff->ob->id, DEG_NODE_TYPE_TRANSFORM); add_relation(eff_key, key, name); @@ -405,52 +372,35 @@ Depsgraph *DepsgraphRelationBuilder::getGraph() void DepsgraphRelationBuilder::begin_build() { - /* LIB_TAG_DOIT is used to indicate whether node for given ID was already - * created or not. - */ - BKE_main_id_tag_all(bmain_, LIB_TAG_DOIT, false); - /* XXX nested node trees are notr included in tag-clearing above, - * so we need to do this manually. - */ - FOREACH_NODETREE(bmain_, nodetree, id) - { - if (id != (ID *)nodetree) { - nodetree->id.tag &= ~LIB_TAG_DOIT; - } - } - FOREACH_NODETREE_END } void DepsgraphRelationBuilder::build_group(Object *object, Group *group) { - ID *group_id = &group->id; - bool group_done = (group_id->tag & LIB_TAG_DOIT) != 0; - OperationKey object_local_transform_key(&object->id, + const bool group_done = built_map_.checkIsBuiltAndTag(group); + OperationKey object_local_transform_key(object != NULL ? &object->id : NULL, DEG_NODE_TYPE_TRANSFORM, DEG_OPCODE_TRANSFORM_LOCAL); - if (!group_done) { - BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { build_object(NULL, base->object); } - group_id->tag |= LIB_TAG_DOIT; } - - BLI_LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { - ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM); - add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup"); + if (object != NULL) { + LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) { + ComponentKey dupli_transform_key(&base->object->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(dupli_transform_key, object_local_transform_key, "Dupligroup"); + } } } void DepsgraphRelationBuilder::build_object(Base *base, Object *object) { - if (object->id.tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(object)) { if (base != NULL) { build_object_flags(base, object); } return; } - object->id.tag |= LIB_TAG_DOIT; /* Object Transforms */ eDepsOperation_Code base_op = (object->parent) ? DEG_OPCODE_TRANSFORM_PARENT : DEG_OPCODE_TRANSFORM_LOCAL; @@ -482,7 +432,7 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) if (object->modifiers.first != NULL) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachObjectLink(object, modifier_walk, &data); + modifiers_foreachIDLink(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != NULL) { @@ -557,7 +507,7 @@ void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object) } OperationKey view_layer_done_key(&scene_->id, DEG_NODE_TYPE_LAYER_COLLECTIONS, - DEG_OPCODE_VIEW_LAYER_DONE); + DEG_OPCODE_VIEW_LAYER_EVAL); OperationKey object_flags_key(&object->id, DEG_NODE_TYPE_LAYER_COLLECTIONS, DEG_OPCODE_OBJECT_BASE_FLAGS); @@ -779,7 +729,7 @@ void DepsgraphRelationBuilder::build_constraints(ID *id, else if (cti->get_constraint_targets) { ListBase targets = {NULL, NULL}; cti->get_constraint_targets(con, &targets); - BLI_LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) { + LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) { if (ct->tar == NULL) { continue; } @@ -942,18 +892,7 @@ void DepsgraphRelationBuilder::build_animdata_curves(ID *id) 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); -} - -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); + /* Get source operations. */ DepsNode *node_from = get_node(adt_key); BLI_assert(node_from != NULL); if (node_from == NULL) { @@ -961,10 +900,28 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id) } OperationDepsNode *operation_from = node_from->get_exit_operation(); BLI_assert(operation_from != NULL); + /* Build relations from animation operation to properties it changes. */ + if (adt->action != NULL) { + build_animdata_curves_targets(id, adt_key, + operation_from, + &adt->action->curves); + } + LISTBASE_FOREACH(NlaTrack *, nlt, &adt->nla_tracks) { + build_animdata_nlastrip_targets(id, adt_key, + operation_from, + &nlt->strips); + } +} + +void DepsgraphRelationBuilder::build_animdata_curves_targets( + ID *id, ComponentKey &adt_key, + OperationDepsNode *operation_from, + ListBase *curves) +{ /* Iterate over all curves and build relations. */ PointerRNA id_ptr; RNA_id_pointer_create(id, &id_ptr); - BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) { + LISTBASE_FOREACH(FCurve *, fcu, curves) { PointerRNA ptr; PropertyRNA *prop; int index; @@ -1007,6 +964,25 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id) } } +void DepsgraphRelationBuilder::build_animdata_nlastrip_targets( + ID *id, ComponentKey &adt_key, + OperationDepsNode *operation_from, + ListBase *strips) +{ + LISTBASE_FOREACH(NlaStrip *, strip, strips) { + if (strip->act != NULL) { + build_animdata_curves_targets(id, adt_key, + operation_from, + &strip->act->curves); + } + else if (strip->strips.first != NULL) { + build_animdata_nlastrip_targets(id, adt_key, + operation_from, + &strip->strips); + } + } +} + void DepsgraphRelationBuilder::build_animdata_drivers(ID *id) { AnimData *adt = BKE_animdata_from_id(id); @@ -1014,7 +990,7 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id) return; } ComponentKey adt_key(id, DEG_NODE_TYPE_ANIMATION); - BLI_LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { + LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) { OperationKey driver_key(id, DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_DRIVER, @@ -1037,7 +1013,7 @@ void DepsgraphRelationBuilder::build_animdata_drivers(ID *id) */ if (fcu->array_index > 0) { FCurve *fcu_prev = NULL; - BLI_LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) { + LISTBASE_FOREACH (FCurve *, fcu_candidate, &adt->drivers) { /* Writing to different RNA paths is */ const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; if (!STREQ(fcu_candidate->rna_path, rna_path)) { @@ -1172,6 +1148,26 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu) } } } + if (RNA_pointer_is_null(&target_key.ptr)) { + /* TODO(sergey): This would only mean that driver is broken. + * so we can't create relation anyway. However, we need to avoid + * adding drivers which are known to be buggy to a dependency + * graph, in order to save computational power. + */ + } + else { + if (target_key.prop != NULL && + RNA_property_is_idprop(target_key.prop)) + { + OperationKey parameters_key(id, + DEG_NODE_TYPE_PARAMETERS, + DEG_OPCODE_PARAMETERS_EVAL); + add_relation(target_key, + parameters_key, + "Driver Target -> Properties"); + } + add_relation(driver_key, target_key, "Driver -> Target"); + } } } @@ -1186,7 +1182,7 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu) const char *rna_path = fcu->rna_path ? fcu->rna_path : ""; const RNAPathKey self_key(id, rna_path); - BLI_LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { + LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { /* Only used targets. */ DRIVER_TARGETS_USED_LOOPER(dvar) { @@ -1261,24 +1257,18 @@ void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu) void DepsgraphRelationBuilder::build_world(World *world) { - ID *world_id = &world->id; - if (world_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(world)) { return; } - world_id->tag |= LIB_TAG_DOIT; - - build_animdata(world_id); - + build_animdata(&world->id); /* TODO: other settings? */ - /* textures */ build_texture_stack(world->mtex); - /* world's nodetree */ if (world->nodetree != NULL) { build_nodetree(world->nodetree); ComponentKey ntree_key(&world->nodetree->id, DEG_NODE_TYPE_SHADING); - ComponentKey world_key(world_id, DEG_NODE_TYPE_SHADING); + ComponentKey world_key(&world->id, DEG_NODE_TYPE_SHADING); add_relation(ntree_key, world_key, "NTree->World Shading Update"); } } @@ -1301,7 +1291,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* objects - simulation participants */ if (rbw->group) { - BLI_LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, &rbw->group->view_layer->object_bases) { Object *object = base->object; if (object == NULL || object->type != OB_MESH) { continue; @@ -1355,7 +1345,7 @@ void DepsgraphRelationBuilder::build_rigidbody(Scene *scene) /* constraints */ if (rbw->constraints) { - BLI_LISTBASE_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, &rbw->constraints->view_layer->object_bases) { Object *object = base->object; if (object == NULL || !object->rigidbody_constraint) { continue; @@ -1390,8 +1380,8 @@ void DepsgraphRelationBuilder::build_particles(Object *object) DEG_NODE_TYPE_EVAL_PARTICLES, DEG_OPCODE_PARTICLE_SYSTEM_EVAL_INIT); - /* particle systems */ - BLI_LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { + /* Particle systems. */ + LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { ParticleSettings *part = psys->part; /* Build particle settings relations. @@ -1410,33 +1400,14 @@ void DepsgraphRelationBuilder::build_particles(Object *object) OperationKey particle_settings_key(&part->id, DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PARTICLE_SETTINGS_EVAL); - OperationKey particle_settings_recalc_clear_key( - &part->id, - DEG_NODE_TYPE_PARAMETERS, - DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR); - OperationKey psys_settings_key(&object->id, - DEG_NODE_TYPE_EVAL_PARTICLES, - DEG_OPCODE_PARTICLE_SETTINGS_EVAL, - psys->name); - add_relation(particle_settings_key, psys_settings_key, "Particle Settings Change"); - add_relation(psys_settings_key, psys_key, "Particle Settings Update"); - add_relation(psys_key, - particle_settings_recalc_clear_key, - "Particle Settings Recalc Clear"); - - /* XXX: if particle system is later re-enabled, we must do full rebuild? */ - if (!psys_check_enabled(object, psys, G.is_rendering)) - continue; - + add_relation(particle_settings_key, eval_init_key, "Particle Settings Change"); add_relation(eval_init_key, psys_key, "Init -> PSys"); - /* TODO(sergey): Currently particle update is just a placeholder, * hook it to the ubereval node so particle system is getting updated * on playback. */ add_relation(psys_key, obdata_ubereval_key, "PSys -> UberEval"); - - /* collisions */ + /* Collisions */ if (part->type != PART_HAIR) { add_collision_relations(psys_key, scene_, @@ -1456,8 +1427,7 @@ void DepsgraphRelationBuilder::build_particles(Object *object) true, "Hair Collision"); } - - /* effectors */ + /* Effectors. */ add_forcefield_relations(psys_key, scene_, object, @@ -1465,35 +1435,46 @@ void DepsgraphRelationBuilder::build_particles(Object *object) part->effector_weights, part->type == PART_HAIR, "Particle Field"); - - /* boids */ + /* Boids .*/ if (part->boids) { - BLI_LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { - BLI_LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { Object *ruleob = NULL; - if (rule->type == eBoidRuleType_Avoid) + if (rule->type == eBoidRuleType_Avoid) { ruleob = ((BoidRuleGoalAvoid *)rule)->ob; - else if (rule->type == eBoidRuleType_FollowLeader) + } + else if (rule->type == eBoidRuleType_FollowLeader) { ruleob = ((BoidRuleFollowLeader *)rule)->ob; - + } if (ruleob) { - ComponentKey ruleob_key(&ruleob->id, DEG_NODE_TYPE_TRANSFORM); + ComponentKey ruleob_key(&ruleob->id, + DEG_NODE_TYPE_TRANSFORM); add_relation(ruleob_key, psys_key, "Boid Rule"); } } } } - - if (part->ren_as == PART_DRAW_OB && part->dup_ob) { - ComponentKey dup_ob_key(&part->dup_ob->id, DEG_NODE_TYPE_TRANSFORM); - add_relation(dup_ob_key, psys_key, "Particle Object Visualization"); - if (part->dup_ob->type == OB_MBALL) { - ComponentKey dup_geometry_key(&part->dup_ob->id, - DEG_NODE_TYPE_GEOMETRY); - add_relation(obdata_ubereval_key, - dup_geometry_key, - "Particle MBall Visualization"); - } + switch (part->ren_as) { + case PART_DRAW_OB: + if (part->dup_ob != NULL) { + /* Make sure object's relations are all built. */ + build_object(NULL, part->dup_ob); + /* Build relation for the particle visualization. */ + build_particles_visualization_object(object, + psys, + part->dup_ob); + } + break; + case PART_DRAW_GR: + if (part->dup_group != NULL) { + build_group(NULL, part->dup_group); + LISTBASE_FOREACH (GroupObject *, go, &part->dup_group->gobject) { + build_particles_visualization_object(object, + psys, + go->ob); + } + } + break; } } @@ -1506,27 +1487,42 @@ void DepsgraphRelationBuilder::build_particles(Object *object) ComponentKey transform_key(&object->id, DEG_NODE_TYPE_TRANSFORM); add_relation(transform_key, obdata_ubereval_key, "Partcile Eval"); - /* TODO(sergey): Do we need a point cache operations here? */ + OperationKey point_cache_reset_key(&object->id, + DEG_NODE_TYPE_CACHE, + DEG_OPCODE_POINT_CACHE_RESET); + add_relation(transform_key, point_cache_reset_key, "Object Transform -> Point Cache Reset"); + add_relation(point_cache_reset_key, obdata_ubereval_key, "Point Cache Reset -> UberEval"); } void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part) { - ID *part_id = &part->id; - if (part_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(part)) { return; } - part_id->tag |= LIB_TAG_DOIT; - /* Animation data relations. */ build_animdata(&part->id); +} - OperationKey eval_key(part_id, - DEG_NODE_TYPE_PARAMETERS, - DEG_OPCODE_PARTICLE_SETTINGS_EVAL); - OperationKey recalc_clear_key(part_id, - DEG_NODE_TYPE_PARAMETERS, - DEG_OPCODE_PARTICLE_SETTINGS_RECALC_CLEAR); - add_relation(eval_key, recalc_clear_key, "Particle Settings Clear Recalc"); +void DepsgraphRelationBuilder::build_particles_visualization_object( + Object *object, + ParticleSystem *psys, + Object *draw_object) +{ + OperationKey psys_key(&object->id, + DEG_NODE_TYPE_EVAL_PARTICLES, + DEG_OPCODE_PARTICLE_SYSTEM_EVAL, + psys->name); + OperationKey obdata_ubereval_key(&object->id, + DEG_NODE_TYPE_GEOMETRY, + DEG_OPCODE_GEOMETRY_UBEREVAL); + ComponentKey dup_ob_key(&draw_object->id, DEG_NODE_TYPE_TRANSFORM); + add_relation(dup_ob_key, psys_key, "Particle Object Visualization"); + if (draw_object->type == OB_MBALL) { + ComponentKey dup_geometry_key(&draw_object->id, DEG_NODE_TYPE_GEOMETRY); + add_relation(obdata_ubereval_key, + dup_geometry_key, + "Particle MBall Visualization"); + } } void DepsgraphRelationBuilder::build_cloth(Object *object, @@ -1616,16 +1612,16 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) /* Modifiers */ if (object->modifiers.first != NULL) { - BLI_LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + ModifierUpdateDepsgraphContext ctx = {}; + ctx.scene = scene_; + ctx.object = object; + + LISTBASE_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( - md, - bmain_, - scene_, - object, - reinterpret_cast< ::DepsNodeHandle* >(&handle)); + ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle); + mti->updateDepsgraph(md, &ctx); } if (BKE_object_modifier_use_time(object, md)) { TimeSourceKey time_src_key; @@ -1670,10 +1666,9 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval"); } - if (obdata->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(obdata)) { return; } - obdata->tag |= LIB_TAG_DOIT; /* Link object data evaluation node to exit operation. */ OperationKey obdata_geom_eval_key(obdata, DEG_NODE_TYPE_GEOMETRY, DEG_OPCODE_PLACEHOLDER, "Geometry Eval"); @@ -1782,22 +1777,20 @@ void DepsgraphRelationBuilder::build_obdata_geom(Object *object) // TODO: Link scene-camera links in somehow... void DepsgraphRelationBuilder::build_camera(Object *object) { - Camera *cam = (Camera *)object->data; - ID *camera_id = &cam->id; - if (camera_id->tag & LIB_TAG_DOIT) { + Camera *camera = (Camera *)object->data; + if (built_map_.checkIsBuiltAndTag(camera)) { return; } - camera_id->tag |= LIB_TAG_DOIT; ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS); - ComponentKey camera_parameters_key(camera_id, DEG_NODE_TYPE_PARAMETERS); + ComponentKey camera_parameters_key(&camera->id, DEG_NODE_TYPE_PARAMETERS); add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object"); /* DOF */ - if (cam->dof_ob != NULL) { - ComponentKey dof_ob_key(&cam->dof_ob->id, DEG_NODE_TYPE_TRANSFORM); + if (camera->dof_ob != NULL) { + ComponentKey dof_ob_key(&camera->dof_ob->id, DEG_NODE_TYPE_TRANSFORM); add_relation(dof_ob_key, object_parameters_key, "Camera DOF"); } } @@ -1805,27 +1798,25 @@ void DepsgraphRelationBuilder::build_camera(Object *object) /* Lamps */ void DepsgraphRelationBuilder::build_lamp(Object *object) { - Lamp *la = (Lamp *)object->data; - ID *lamp_id = &la->id; - if (lamp_id->tag & LIB_TAG_DOIT) { + Lamp *lamp = (Lamp *)object->data; + if (built_map_.checkIsBuiltAndTag(lamp)) { return; } - lamp_id->tag |= LIB_TAG_DOIT; ComponentKey object_parameters_key(&object->id, DEG_NODE_TYPE_PARAMETERS); - ComponentKey lamp_parameters_key(lamp_id, DEG_NODE_TYPE_PARAMETERS); + ComponentKey lamp_parameters_key(&lamp->id, DEG_NODE_TYPE_PARAMETERS); add_relation(lamp_parameters_key, object_parameters_key, "Lamp -> Object"); /* lamp's nodetree */ - if (la->nodetree != NULL) { - build_nodetree(la->nodetree); - ComponentKey nodetree_key(&la->nodetree->id, DEG_NODE_TYPE_SHADING); + if (lamp->nodetree != NULL) { + build_nodetree(lamp->nodetree); + ComponentKey nodetree_key(&lamp->nodetree->id, DEG_NODE_TYPE_SHADING); add_relation(nodetree_key, lamp_parameters_key, "NTree->Lamp Parameters"); } /* textures */ - build_texture_stack(la->mtex); + build_texture_stack(lamp->mtex); if (DEG_depsgraph_use_copy_on_write()) { /* Make sure copy on write of lamp data is always properly updated for @@ -1834,7 +1825,7 @@ void DepsgraphRelationBuilder::build_lamp(Object *object) OperationKey ob_copy_on_write_key(&object->id, DEG_NODE_TYPE_COPY_ON_WRITE, DEG_OPCODE_COPY_ON_WRITE); - OperationKey lamp_copy_on_write_key(lamp_id, + OperationKey lamp_copy_on_write_key(&lamp->id, DEG_NODE_TYPE_COPY_ON_WRITE, DEG_OPCODE_COPY_ON_WRITE); add_relation(lamp_copy_on_write_key, ob_copy_on_write_key, "Eval Order"); @@ -1846,11 +1837,13 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) if (ntree == NULL) { return; } - ID *ntree_id = &ntree->id; - build_animdata(ntree_id); - ComponentKey shading_key(ntree_id, DEG_NODE_TYPE_SHADING); + if (built_map_.checkIsBuiltAndTag(ntree)) { + return; + } + build_animdata(&ntree->id); + ComponentKey shading_key(&ntree->id, DEG_NODE_TYPE_SHADING); /* nodetree's nodes... */ - BLI_LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { + LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) { ID *id = bnode->id; if (id == NULL) { continue; @@ -1878,10 +1871,7 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) } else if (bnode->type == NODE_GROUP) { bNodeTree *group_ntree = (bNodeTree *)id; - if ((group_ntree->id.tag & LIB_TAG_DOIT) == 0) { - build_nodetree(group_ntree); - group_ntree->id.tag |= LIB_TAG_DOIT; - } + build_nodetree(group_ntree); ComponentKey group_shading_key(&group_ntree->id, DEG_NODE_TYPE_SHADING); add_relation(group_shading_key, shading_key, "Group Node"); @@ -1891,37 +1881,32 @@ void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree) } } - OperationKey shading_update_key(ntree_id, + OperationKey shading_update_key(&ntree->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_MATERIAL_UPDATE); - OperationKey shading_parameters_key(ntree_id, + OperationKey shading_parameters_key(&ntree->id, DEG_NODE_TYPE_SHADING_PARAMETERS, DEG_OPCODE_MATERIAL_UPDATE); add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters"); } /* Recursively build graph for material */ -void DepsgraphRelationBuilder::build_material(Material *ma) +void DepsgraphRelationBuilder::build_material(Material *material) { - ID *ma_id = &ma->id; - if (ma_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(material)) { return; } - ma_id->tag |= LIB_TAG_DOIT; - /* animation */ - build_animdata(ma_id); - + build_animdata(&material->id); /* textures */ - build_texture_stack(ma->mtex); - + build_texture_stack(material->mtex); /* material's nodetree */ - if (ma->nodetree != NULL) { - build_nodetree(ma->nodetree); - OperationKey ntree_key(&ma->nodetree->id, + if (material->nodetree != NULL) { + build_nodetree(material->nodetree); + OperationKey ntree_key(&material->nodetree->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_MATERIAL_UPDATE); - OperationKey material_key(&ma->id, + OperationKey material_key(&material->id, DEG_NODE_TYPE_SHADING, DEG_OPCODE_MATERIAL_UPDATE); add_relation(ntree_key, material_key, "Material's NTree"); @@ -1929,28 +1914,22 @@ void DepsgraphRelationBuilder::build_material(Material *ma) } /* Recursively build graph for texture */ -void DepsgraphRelationBuilder::build_texture(Tex *tex) +void DepsgraphRelationBuilder::build_texture(Tex *texture) { - ID *tex_id = &tex->id; - if (tex_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(texture)) { return; } - tex_id->tag |= LIB_TAG_DOIT; - /* texture itself */ - build_animdata(tex_id); - + build_animdata(&texture->id); /* texture's nodetree */ - build_nodetree(tex->nodetree); + build_nodetree(texture->nodetree); } /* Texture-stack attached to some shading datablock */ void DepsgraphRelationBuilder::build_texture_stack(MTex **texture_stack) { - int i; - /* for now assume that all texture-stacks have same number of max items */ - for (i = 0; i < MAX_MTEX; i++) { + for (int i = 0; i < MAX_MTEX; i++) { MTex *mtex = texture_stack[i]; if (mtex && mtex->tex) build_texture(mtex->tex); @@ -2002,14 +1981,12 @@ void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip) void DepsgraphRelationBuilder::build_lightprobe(Object *object) { LightProbe *probe = (LightProbe *)object->data; - ID *probe_id = &probe->id; - if (probe_id->tag & LIB_TAG_DOIT) { + if (built_map_.checkIsBuiltAndTag(probe)) { return; } - probe_id->tag |= LIB_TAG_DOIT; build_animdata(&probe->id); - OperationKey probe_key(probe_id, + OperationKey probe_key(&probe->id, DEG_NODE_TYPE_PARAMETERS, DEG_OPCODE_PLACEHOLDER, "LightProbe Eval"); @@ -2066,6 +2043,22 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node if (op_node->inlinks.size() == 0) { graph_->add_new_relation(op_cow, op_node, "CoW Dependency"); } + else { + bool has_same_comp_dependency = false; + foreach (DepsRelation *rel, op_node->inlinks) { + if (rel->from->type != DEG_NODE_TYPE_OPERATION) { + continue; + } + OperationDepsNode *op_node_from = (OperationDepsNode *)rel->from; + if (op_node_from->owner == op_node->owner) { + has_same_comp_dependency = true; + break; + } + } + if (!has_same_comp_dependency) { + graph_->add_new_relation(op_cow, op_node, "CoW Dependency"); + } + } } GHASH_FOREACH_END(); /* NOTE: We currently ignore implicit relations to an external @@ -2096,4 +2089,43 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDDepsNode *id_node } } +/* **** ID traversal callbacks functions **** */ + +void DepsgraphRelationBuilder::modifier_walk(void *user_data, + struct Object * /*object*/, + struct ID **idpoin, + int /*cb_flag*/) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + ID *id = *idpoin; + if (id == NULL) { + return; + } + switch (GS(id->name)) { + case ID_OB: + data->builder->build_object(NULL, (Object *)id); + break; + case ID_TE: + data->builder->build_texture((Tex *)id); + break; + default: + /* pass */ + break; + } +} + +void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/, + ID **idpoin, + bool /*is_reference*/, + void *user_data) +{ + BuilderWalkUserData *data = (BuilderWalkUserData *)user_data; + if (*idpoin) { + ID *id = *idpoin; + if (GS(id->name) == ID_OB) { + data->builder->build_object(NULL, (Object *)id); + } + } +} + } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 1d556f6b2ce..4ddad462a5a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -43,6 +43,7 @@ #include "BLI_utildefines.h" #include "BLI_string.h" +#include "intern/builder/deg_builder_map.h" #include "intern/nodes/deg_node.h" #include "intern/nodes/deg_node_component.h" #include "intern/nodes/deg_node_operation.h" @@ -67,13 +68,13 @@ struct bNodeTree; struct Object; struct bPoseChannel; struct bConstraint; +struct ParticleSystem; +struct ParticleSettings; struct Scene; struct ViewLayer; struct Tex; struct World; struct EffectorWeights; -struct ParticleSystem; -struct ParticleSettings; struct Groom; struct PropertyRNA; @@ -206,7 +207,14 @@ struct DepsgraphRelationBuilder RootPChanMap *root_map); void build_animdata(ID *id); void build_animdata_curves(ID *id); - void build_animdata_curves_targets(ID *id); + void build_animdata_curves_targets(ID *id, + ComponentKey &adt_key, + OperationDepsNode *operation_from, + ListBase *curves); + void build_animdata_nlastrip_targets(ID *id, + ComponentKey &adt_key, + OperationDepsNode *operation_from, + ListBase *strips); void build_animdata_drivers(ID *id); void build_driver(ID *id, FCurve *fcurve); void build_driver_data(ID *id, FCurve *fcurve); @@ -215,6 +223,9 @@ struct DepsgraphRelationBuilder void build_rigidbody(Scene *scene); void build_particles(Object *object); void build_particle_settings(ParticleSettings *part); + void build_particles_visualization_object(Object *object, + ParticleSystem *psys, + Object *draw_object); void build_cloth(Object *object, ModifierData *md); void build_ik_pose(Object *object, bPoseChannel *pchan, @@ -254,20 +265,6 @@ struct DepsgraphRelationBuilder EffectorWeights *eff, bool add_absorption, const char *name); - struct LayerCollectionState { - int index; - OperationKey init_key; - OperationKey done_key; - OperationKey prev_key; - }; - void build_layer_collection(ID *owner_id, - LayerCollection *layer_collection, - LayerCollectionState *state); - void build_layer_collections(ID *owner_id, - ListBase *layer_collections, - LayerCollectionState *state); - void build_view_layer_collections(struct ID *owner_id, ViewLayer *view_layer); - void build_copy_on_write_relations(); void build_copy_on_write_relations(IDDepsNode *id_node); @@ -324,12 +321,28 @@ protected: const KeyTo& key_to); private: + struct BuilderWalkUserData { + DepsgraphRelationBuilder *builder; + }; + + static void modifier_walk(void *user_data, + struct Object *object, + struct ID **idpoin, + int cb_flag); + + static void constraint_walk(bConstraint *con, + ID **idpoin, + bool is_reference, + void *user_data); + /* State which never changes, same for the whole builder time. */ Main *bmain_; Depsgraph *graph_; /* State which demotes currently built entities. */ Scene *scene_; + + BuilderMap built_map_; }; struct DepsNodeHandle diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc deleted file mode 100644 index 9cf82b5fb47..00000000000 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc +++ /dev/null @@ -1,124 +0,0 @@ -/* - * ***** 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: Joshua Leung - * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013) - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc - * \ingroup depsgraph - * - * Methods for constructing depsgraph - */ - -#include "intern/builder/deg_builder_relations.h" - -#include <stdio.h> -#include <stdlib.h> -#include <cstring> /* required for STREQ later on. */ - -#include "MEM_guardedalloc.h" - -extern "C" { -#include "BLI_blenlib.h" -#include "BLI_utildefines.h" - -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" - -#include "BKE_layer.h" -#include "BKE_main.h" -#include "BKE_node.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -} /* extern "C" */ - -#include "intern/builder/deg_builder.h" -#include "intern/builder/deg_builder_pchanmap.h" - -#include "intern/nodes/deg_node.h" -#include "intern/nodes/deg_node_component.h" -#include "intern/nodes/deg_node_operation.h" - -#include "intern/depsgraph_intern.h" -#include "intern/depsgraph_types.h" - -#include "util/deg_util_foreach.h" - -namespace DEG { - -void DepsgraphRelationBuilder::build_layer_collection( - ID *owner_id, - LayerCollection *layer_collection, - LayerCollectionState *state) -{ - OperationKey layer_key(owner_id, - DEG_NODE_TYPE_LAYER_COLLECTIONS, - DEG_OPCODE_VIEW_LAYER_EVAL, - layer_collection->scene_collection->name, - state->index); - add_relation(state->prev_key, layer_key, "Layer collection order"); - - ++state->index; - state->prev_key = layer_key; - - /* Recurs into nested layer collections. */ - build_layer_collections(owner_id, &layer_collection->layer_collections, state); -} - -void DepsgraphRelationBuilder::build_layer_collections( - ID *owner_id, - ListBase *layer_collections, - LayerCollectionState *state) -{ - BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) { - /* Recurs into the layer. */ - build_layer_collection(owner_id, layer_collection, state); - } -} - -void DepsgraphRelationBuilder::build_view_layer_collections( - ID *owner_id, - ViewLayer *view_layer) -{ - LayerCollectionState state; - state.index = 0; - - OperationKey init_key(owner_id, - DEG_NODE_TYPE_LAYER_COLLECTIONS, - DEG_OPCODE_VIEW_LAYER_INIT); - OperationKey done_key(owner_id, - DEG_NODE_TYPE_LAYER_COLLECTIONS, - DEG_OPCODE_VIEW_LAYER_DONE); - - state.init_key = init_key; - state.done_key = done_key; - state.prev_key = init_key; - - build_layer_collections(owner_id, &view_layer->layer_collections, &state); - - add_relation(state.prev_key, done_key, "Layer collection order"); -} - -} // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index ad812a4b505..c80e0d568f3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -51,6 +51,7 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" +#include "BKE_constraint.h" } /* extern "C" */ #include "DEG_depsgraph.h" @@ -175,15 +176,12 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, } } - DEG_DEBUG_PRINTF("\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n", + DEG_DEBUG_PRINTF(BUILD, "\nStarting IK Build: pchan = %s, target = (%s, %s), segcount = %d\n", pchan->name, data->tar->id.name, data->subtarget, data->rootbone); bPoseChannel *parchan = pchan; /* exclude tip from chain? */ if (!(data->flag & CONSTRAINT_IK_TIP)) { - OperationKey tip_transforms_key(&object->id, DEG_NODE_TYPE_BONE, - parchan->name, DEG_OPCODE_BONE_LOCAL); - add_relation(solver_key, tip_transforms_key, "IK Solver Result"); parchan = pchan->parent; } @@ -221,7 +219,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, root_map->add_bone(parchan->name, rootchan->name); /* continue up chain, until we reach target number of items... */ - DEG_DEBUG_PRINTF(" %d = %s\n", segcount, parchan->name); + DEG_DEBUG_PRINTF(BUILD, " %d = %s\n", segcount, parchan->name); segcount++; if ((segcount == data->rootbone) || (segcount > 255)) break; /* 255 is weak */ @@ -341,8 +339,8 @@ void DepsgraphRelationBuilder::build_rig(Object *object) */ RootPChanMap root_map; bool pose_depends_on_local_transform = false; - BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - BLI_LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { switch (con->type) { case CONSTRAINT_TYPE_KINEMATIC: build_ik_pose(object, pchan, con, &root_map); @@ -382,7 +380,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object) } /* links between operations for each bone */ - BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); OperationKey bone_pose_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_POSE_PARENT); OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); @@ -409,6 +407,11 @@ void DepsgraphRelationBuilder::build_rig(Object *object) } /* Buil constraints. */ if (pchan->constraints.first != NULL) { + /* Build relations for indirectly linked objects. */ + BuilderWalkUserData data; + data.builder = this; + BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data); + /* constraints stack and constraint dependencies */ build_constraints(&object->id, DEG_NODE_TYPE_BONE, pchan->name, &pchan->constraints, &root_map); @@ -434,6 +437,7 @@ void DepsgraphRelationBuilder::build_rig(Object *object) /* assume that all bones must be done for the pose to be ready (for deformers) */ add_relation(bone_done_key, flush_key, "PoseEval Result-Bone Link"); + /* Custom shape. */ if (pchan->custom != NULL) { build_object(NULL, pchan->custom); @@ -443,16 +447,43 @@ void DepsgraphRelationBuilder::build_rig(Object *object) void DepsgraphRelationBuilder::build_proxy_rig(Object *object) { - OperationKey pose_init_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_INIT); - OperationKey pose_done_key(&object->id, DEG_NODE_TYPE_EVAL_POSE, DEG_OPCODE_POSE_DONE); - BLI_LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - OperationKey bone_local_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_LOCAL); - OperationKey bone_ready_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_READY); - OperationKey bone_done_key(&object->id, DEG_NODE_TYPE_BONE, pchan->name, DEG_OPCODE_BONE_DONE); + Object *proxy_from = object->proxy_from; + OperationKey pose_init_key(&object->id, + DEG_NODE_TYPE_EVAL_POSE, + DEG_OPCODE_POSE_INIT); + OperationKey pose_done_key(&object->id, + DEG_NODE_TYPE_EVAL_POSE, + DEG_OPCODE_POSE_DONE); + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + OperationKey bone_local_key(&object->id, + DEG_NODE_TYPE_BONE, pchan->name, + DEG_OPCODE_BONE_LOCAL); + OperationKey bone_ready_key(&object->id, + DEG_NODE_TYPE_BONE, + pchan->name, + DEG_OPCODE_BONE_READY); + OperationKey bone_done_key(&object->id, + DEG_NODE_TYPE_BONE, + pchan->name, + DEG_OPCODE_BONE_DONE); add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done"); + + if (pchan->prop != NULL) { + OperationKey bone_parameters(&object->id, + DEG_NODE_TYPE_PARAMETERS, + DEG_OPCODE_PARAMETERS_EVAL, + pchan->name); + OperationKey from_bone_parameters(&proxy_from->id, + DEG_NODE_TYPE_PARAMETERS, + DEG_OPCODE_PARAMETERS_EVAL, + pchan->name); + add_relation(from_bone_parameters, + bone_parameters, + "Proxy Bone Parameters"); + } } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index cfb98fe2f79..85f465efb82 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -78,7 +78,7 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la * passed to the evaluation functions. During relations builder we only * do NULL-pointer check of the base, so it's fine to pass original one. */ - BLI_LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { + LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) { build_object(base, base->object); } if (scene->camera != NULL) { @@ -105,15 +105,13 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la build_gpencil(scene->gpd); } /* Masks. */ - BLI_LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) { + LISTBASE_FOREACH (Mask *, mask, &bmain_->mask) { build_mask(mask); } /* Movie clips. */ - BLI_LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) { + LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclip) { build_movieclip(clip); } - /* Collections. */ - build_view_layer_collections(&scene_->id, view_layer); /* TODO(sergey): Do this flush on CoW object? */ foreach (OperationDepsNode *node, graph_->operations) { IDDepsNode *id_node = node->owner->owner; @@ -129,8 +127,8 @@ void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_la build_view_layer(scene->set, set_view_layer); } - graph_->scene = scene; - graph_->view_layer = view_layer; + BLI_assert(graph_->scene == scene); + BLI_assert(graph_->view_layer == view_layer); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc index 7731b76c6b9..12760cad73c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc @@ -117,7 +117,7 @@ void deg_graph_transitive_reduction(Depsgraph *graph) } } } - DEG_DEBUG_PRINTF("Removed %d relations\n", num_removed_relations); + DEG_DEBUG_PRINTF(BUILD, "Removed %d relations\n", num_removed_relations); } } // namespace DEG |