Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2018-04-15 13:16:55 +0300
commit7e1832c8d546ec13e752b7bd42ce13e3fc10ae86 (patch)
tree0fff9d878db69b288f909ff9a0f8aefe31ab8d80 /source/blender/depsgraph/intern/builder
parentc0c8df3f2cf3ab03cec1f660619b0fe2290caf2a (diff)
parent94959dba1b53640e2a36cf9b5ca46aaf49c5c74a (diff)
Merge branch 'blender2.8' into hair_guides
Diffstat (limited to 'source/blender/depsgraph/intern/builder')
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc93
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.cc64
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h69
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc455
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h57
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_layer_collection.cc126
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc92
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc57
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc460
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h47
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_layer_collection.cc124
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc59
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc12
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc2
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