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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/depsgraph/intern/builder
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/depsgraph/intern/builder')
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.cc243
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder.h17
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc281
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.h1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.cc20
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h55
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.cc2509
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h357
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc570
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc206
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc137
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h42
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc4415
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h521
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h304
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc199
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc900
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc138
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc549
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.h72
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_transitive.cc96
21 files changed, 5423 insertions, 6209 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc
index b6e516ee9b4..ef36dec6f34 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder.cc
@@ -58,65 +58,63 @@ namespace DEG {
namespace {
struct VisibilityCheckData {
- eEvaluationMode eval_mode;
- bool is_visibility_animated;
+ eEvaluationMode eval_mode;
+ bool is_visibility_animated;
};
void visibility_animated_check_cb(ID * /*id*/, FCurve *fcu, void *user_data)
{
- VisibilityCheckData *data =
- reinterpret_cast<VisibilityCheckData *>(user_data);
- if (data->is_visibility_animated) {
- return;
- }
- if (data->eval_mode == DAG_EVAL_VIEWPORT) {
- if (STREQ(fcu->rna_path, "hide_viewport")) {
- data->is_visibility_animated = true;
- }
- }
- else if (data->eval_mode == DAG_EVAL_RENDER) {
- if (STREQ(fcu->rna_path, "hide_render")) {
- data->is_visibility_animated = true;
- }
- }
+ VisibilityCheckData *data = reinterpret_cast<VisibilityCheckData *>(user_data);
+ if (data->is_visibility_animated) {
+ return;
+ }
+ if (data->eval_mode == DAG_EVAL_VIEWPORT) {
+ if (STREQ(fcu->rna_path, "hide_viewport")) {
+ data->is_visibility_animated = true;
+ }
+ }
+ else if (data->eval_mode == DAG_EVAL_RENDER) {
+ if (STREQ(fcu->rna_path, "hide_render")) {
+ data->is_visibility_animated = true;
+ }
+ }
}
bool is_object_visibility_animated(const Depsgraph *graph, Object *object)
{
- AnimData *anim_data = BKE_animdata_from_id(&object->id);
- if (anim_data == NULL) {
- return false;
- }
- VisibilityCheckData data;
- data.eval_mode = graph->mode;
- data.is_visibility_animated = false;
- BKE_fcurves_id_cb(&object->id, visibility_animated_check_cb, &data);
- return data.is_visibility_animated;
+ AnimData *anim_data = BKE_animdata_from_id(&object->id);
+ if (anim_data == NULL) {
+ return false;
+ }
+ VisibilityCheckData data;
+ data.eval_mode = graph->mode;
+ data.is_visibility_animated = false;
+ BKE_fcurves_id_cb(&object->id, visibility_animated_check_cb, &data);
+ return data.is_visibility_animated;
}
} // namespace
bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base)
{
- const int base_flag = (graph->mode == DAG_EVAL_VIEWPORT) ?
- BASE_ENABLED_VIEWPORT : BASE_ENABLED_RENDER;
- if (base->flag & base_flag) {
- return true;
- }
- if (is_object_visibility_animated(graph, base->object)) {
- return true;
- }
- return false;
+ const int base_flag = (graph->mode == DAG_EVAL_VIEWPORT) ? BASE_ENABLED_VIEWPORT :
+ BASE_ENABLED_RENDER;
+ if (base->flag & base_flag) {
+ return true;
+ }
+ if (is_object_visibility_animated(graph, base->object)) {
+ return true;
+ }
+ return false;
}
-DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph)
- : bmain_(bmain),
- graph_(graph) {
+DepsgraphBuilder::DepsgraphBuilder(Main *bmain, Depsgraph *graph) : bmain_(bmain), graph_(graph)
+{
}
bool DepsgraphBuilder::need_pull_base_into_graph(Base *base)
{
- return deg_check_base_available_for_build(graph_, base);
+ return deg_check_base_available_for_build(graph_, base);
}
/*******************************************************************************
@@ -127,101 +125,90 @@ namespace {
void deg_graph_build_flush_visibility(Depsgraph *graph)
{
- enum {
- DEG_NODE_VISITED = (1 << 0),
- };
-
- BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *),
- "DEG flush layers stack");
- for (IDNode *id_node : graph->id_nodes) {
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- comp_node->affects_directly_visible |= id_node->is_directly_visible;
- }
- GHASH_FOREACH_END();
- }
- for (OperationNode *op_node : graph->operations) {
- op_node->custom_flags = 0;
- op_node->num_links_pending = 0;
- for (Relation *rel : op_node->outlinks) {
- if ((rel->from->type == NodeType::OPERATION) &&
- (rel->flag & RELATION_FLAG_CYCLIC) == 0)
- {
- ++op_node->num_links_pending;
- }
- }
- if (op_node->num_links_pending == 0) {
- BLI_stack_push(stack, &op_node);
- op_node->custom_flags |= DEG_NODE_VISITED;
- }
- }
- while (!BLI_stack_is_empty(stack)) {
- OperationNode *op_node;
- BLI_stack_pop(stack, &op_node);
- /* Flush layers to parents. */
- for (Relation *rel : op_node->inlinks) {
- if (rel->from->type == NodeType::OPERATION) {
- OperationNode *op_from = (OperationNode *)rel->from;
- op_from->owner->affects_directly_visible |=
- op_node->owner->affects_directly_visible;
- }
- }
- /* Schedule parent nodes. */
- for (Relation *rel : op_node->inlinks) {
- if (rel->from->type == NodeType::OPERATION) {
- OperationNode *op_from = (OperationNode *)rel->from;
- if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) {
- BLI_assert(op_from->num_links_pending > 0);
- --op_from->num_links_pending;
- }
- if ((op_from->num_links_pending == 0) &&
- (op_from->custom_flags & DEG_NODE_VISITED) == 0)
- {
- BLI_stack_push(stack, &op_from);
- op_from->custom_flags |= DEG_NODE_VISITED;
- }
- }
- }
- }
- BLI_stack_free(stack);
+ enum {
+ DEG_NODE_VISITED = (1 << 0),
+ };
+
+ BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack");
+ for (IDNode *id_node : graph->id_nodes) {
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ comp_node->affects_directly_visible |= id_node->is_directly_visible;
+ }
+ GHASH_FOREACH_END();
+ }
+ for (OperationNode *op_node : graph->operations) {
+ op_node->custom_flags = 0;
+ op_node->num_links_pending = 0;
+ for (Relation *rel : op_node->outlinks) {
+ if ((rel->from->type == NodeType::OPERATION) && (rel->flag & RELATION_FLAG_CYCLIC) == 0) {
+ ++op_node->num_links_pending;
+ }
+ }
+ if (op_node->num_links_pending == 0) {
+ BLI_stack_push(stack, &op_node);
+ op_node->custom_flags |= DEG_NODE_VISITED;
+ }
+ }
+ while (!BLI_stack_is_empty(stack)) {
+ OperationNode *op_node;
+ BLI_stack_pop(stack, &op_node);
+ /* Flush layers to parents. */
+ for (Relation *rel : op_node->inlinks) {
+ if (rel->from->type == NodeType::OPERATION) {
+ OperationNode *op_from = (OperationNode *)rel->from;
+ op_from->owner->affects_directly_visible |= op_node->owner->affects_directly_visible;
+ }
+ }
+ /* Schedule parent nodes. */
+ for (Relation *rel : op_node->inlinks) {
+ if (rel->from->type == NodeType::OPERATION) {
+ OperationNode *op_from = (OperationNode *)rel->from;
+ if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) {
+ BLI_assert(op_from->num_links_pending > 0);
+ --op_from->num_links_pending;
+ }
+ if ((op_from->num_links_pending == 0) && (op_from->custom_flags & DEG_NODE_VISITED) == 0) {
+ BLI_stack_push(stack, &op_from);
+ op_from->custom_flags |= DEG_NODE_VISITED;
+ }
+ }
+ }
+ }
+ BLI_stack_free(stack);
}
} // namespace
void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
{
- /* Make sure dependencies of visible ID datablocks are visible. */
- deg_graph_build_flush_visibility(graph);
- /* Re-tag IDs for update if it was tagged before the relations
- * update tag. */
- for (IDNode *id_node : graph->id_nodes) {
- ID *id = id_node->id_orig;
- id_node->finalize_build(graph);
- int flag = 0;
- /* Tag rebuild if special evaluation flags changed. */
- if (id_node->eval_flags != id_node->previous_eval_flags) {
- flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
- }
- /* Tag rebuild if the custom data mask changed. */
- if (id_node->customdata_masks != id_node->previous_customdata_masks) {
- flag |= ID_RECALC_GEOMETRY;
- }
- if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
- flag |= ID_RECALC_COPY_ON_WRITE;
- /* This means ID is being added to the dependency graph first
- * time, which is similar to "ob-visible-change" */
- if (GS(id->name) == ID_OB) {
- flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
- }
- }
- if (flag != 0) {
- graph_id_tag_update(bmain,
- graph,
- id_node->id_orig,
- flag,
- DEG_UPDATE_SOURCE_RELATIONS);
- }
- }
+ /* Make sure dependencies of visible ID datablocks are visible. */
+ deg_graph_build_flush_visibility(graph);
+ /* Re-tag IDs for update if it was tagged before the relations
+ * update tag. */
+ for (IDNode *id_node : graph->id_nodes) {
+ ID *id = id_node->id_orig;
+ id_node->finalize_build(graph);
+ int flag = 0;
+ /* Tag rebuild if special evaluation flags changed. */
+ if (id_node->eval_flags != id_node->previous_eval_flags) {
+ flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
+ }
+ /* Tag rebuild if the custom data mask changed. */
+ if (id_node->customdata_masks != id_node->previous_customdata_masks) {
+ flag |= ID_RECALC_GEOMETRY;
+ }
+ if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ flag |= ID_RECALC_COPY_ON_WRITE;
+ /* This means ID is being added to the dependency graph first
+ * time, which is similar to "ob-visible-change" */
+ if (GS(id->name) == ID_OB) {
+ flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
+ }
+ }
+ if (flag != 0) {
+ graph_id_tag_update(bmain, graph, id_node->id_orig, flag, DEG_UPDATE_SOURCE_RELATIONS);
+ }
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder.h b/source/blender/depsgraph/intern/builder/deg_builder.h
index 2461ca2211f..310944f2f28 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder.h
@@ -31,19 +31,18 @@ namespace DEG {
struct Depsgraph;
class DepsgraphBuilder {
-public:
- bool need_pull_base_into_graph(struct Base *base);
+ public:
+ bool need_pull_base_into_graph(struct Base *base);
-protected:
- DepsgraphBuilder(Main *bmain, Depsgraph *graph);
+ protected:
+ DepsgraphBuilder(Main *bmain, Depsgraph *graph);
- /* State which never changes, same for the whole builder time. */
- Main *bmain_;
- Depsgraph *graph_;
+ /* State which never changes, same for the whole builder time. */
+ Main *bmain_;
+ Depsgraph *graph_;
};
-bool deg_check_base_available_for_build(const Depsgraph *graph,
- Base *base);
+bool deg_check_base_available_for_build(const Depsgraph *graph, Base *base);
void deg_graph_build_finalize(struct Main *bmain, struct Depsgraph *graph);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index a6d86f5178f..af5c4e7130b 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -41,89 +41,88 @@ namespace DEG {
namespace {
enum eCyclicCheckVisitedState {
- /* Not is not visited at all during traversal. */
- NODE_NOT_VISITED = 0,
- /* Node has been visited during traversal and not in current stack. */
- NODE_VISITED = 1,
- /* Node has been visited during traversal and is in current stack. */
- NODE_IN_STACK = 2,
+ /* Not is not visited at all during traversal. */
+ NODE_NOT_VISITED = 0,
+ /* Node has been visited during traversal and not in current stack. */
+ NODE_VISITED = 1,
+ /* Node has been visited during traversal and is in current stack. */
+ NODE_IN_STACK = 2,
};
struct StackEntry {
- OperationNode *node;
- StackEntry *from;
- Relation *via_relation;
+ OperationNode *node;
+ StackEntry *from;
+ Relation *via_relation;
};
struct CyclesSolverState {
- CyclesSolverState(Depsgraph *graph)
- : graph(graph),
- traversal_stack(BLI_stack_new(sizeof(StackEntry),
- "DEG detect cycles stack")),
- num_cycles(0)
- {
- /* pass */
- }
- ~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;
+ CyclesSolverState(Depsgraph *graph)
+ : graph(graph),
+ traversal_stack(BLI_stack_new(sizeof(StackEntry), "DEG detect cycles stack")),
+ num_cycles(0)
+ {
+ /* pass */
+ }
+ ~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(Node *node,
- eCyclicCheckVisitedState state)
+BLI_INLINE void set_node_visited_state(Node *node, eCyclicCheckVisitedState state)
{
- node->custom_flags = (node->custom_flags & ~0x3) | (int)state;
+ node->custom_flags = (node->custom_flags & ~0x3) | (int)state;
}
BLI_INLINE eCyclicCheckVisitedState get_node_visited_state(Node *node)
{
- return (eCyclicCheckVisitedState)(node->custom_flags & 0x3);
+ return (eCyclicCheckVisitedState)(node->custom_flags & 0x3);
}
BLI_INLINE void set_node_num_visited_children(Node *node, int num_children)
{
- node->custom_flags = (node->custom_flags & 0x3) | (num_children << 2);
+ node->custom_flags = (node->custom_flags & 0x3) | (num_children << 2);
}
BLI_INLINE int get_node_num_visited_children(Node *node)
{
- return node->custom_flags >> 2;
+ return node->custom_flags >> 2;
}
void schedule_node_to_stack(CyclesSolverState *state, OperationNode *node)
{
- 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);
+ 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);
}
/* Schedule leaf nodes (node without input links) for traversal. */
void schedule_leaf_nodes(CyclesSolverState *state)
{
- for (OperationNode *node : state->graph->operations) {
- bool has_inlinks = false;
- for (Relation *rel : node->inlinks) {
- if (rel->from->type == NodeType::OPERATION) {
- has_inlinks = true;
- }
- }
- node->custom_flags = 0;
- if (has_inlinks == false) {
- schedule_node_to_stack(state, node);
- }
- else {
- set_node_visited_state(node, NODE_NOT_VISITED);
- }
- }
+ for (OperationNode *node : state->graph->operations) {
+ bool has_inlinks = false;
+ for (Relation *rel : node->inlinks) {
+ if (rel->from->type == NodeType::OPERATION) {
+ has_inlinks = true;
+ }
+ }
+ node->custom_flags = 0;
+ if (has_inlinks == false) {
+ 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
@@ -131,113 +130,111 @@ void schedule_leaf_nodes(CyclesSolverState *state)
*/
bool schedule_non_checked_node(CyclesSolverState *state)
{
- for (OperationNode *node : state->graph->operations) {
- if (get_node_visited_state(node) == NODE_NOT_VISITED) {
- schedule_node_to_stack(state, node);
- return true;
- }
- }
- return false;
+ for (OperationNode *node : state->graph->operations) {
+ if (get_node_visited_state(node) == NODE_NOT_VISITED) {
+ schedule_node_to_stack(state, node);
+ return true;
+ }
+ }
+ return false;
}
bool check_relation_can_murder(Relation *relation)
{
- if (relation->flag & RELATION_FLAG_GODMODE) {
- return false;
- }
- return true;
+ if (relation->flag & RELATION_FLAG_GODMODE) {
+ return false;
+ }
+ return true;
}
-Relation *select_relation_to_murder(Relation *relation,
- StackEntry *cycle_start_entry)
+Relation *select_relation_to_murder(Relation *relation, StackEntry *cycle_start_entry)
{
- /* More or less russian roulette solver, which will make sure only
- * specially marked relations are kept alive.
- *
- * TODO(sergey): There might be better strategies here. */
- if (check_relation_can_murder(relation)) {
- return relation;
- }
- StackEntry *current = cycle_start_entry;
- OperationNode *to_node = (OperationNode *)relation->to;
- while (current->node != to_node) {
- if (check_relation_can_murder(current->via_relation)) {
- return current->via_relation;
- }
- current = current->from;
- }
- return relation;
+ /* More or less russian roulette solver, which will make sure only
+ * specially marked relations are kept alive.
+ *
+ * TODO(sergey): There might be better strategies here. */
+ if (check_relation_can_murder(relation)) {
+ return relation;
+ }
+ StackEntry *current = cycle_start_entry;
+ OperationNode *to_node = (OperationNode *)relation->to;
+ while (current->node != to_node) {
+ if (check_relation_can_murder(current->via_relation)) {
+ return current->via_relation;
+ }
+ current = current->from;
+ }
+ return relation;
}
/* 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);
- OperationNode *node = entry->node;
- bool all_child_traversed = true;
- const int num_visited = get_node_num_visited_children(node);
- for (int i = num_visited; i < node->outlinks.size(); ++i) {
- Relation *rel = node->outlinks[i];
- if (rel->to->type == NodeType::OPERATION) {
- OperationNode *to = (OperationNode *)rel->to;
- eCyclicCheckVisitedState to_state = get_node_visited_state(to);
- if (to_state == NODE_IN_STACK) {
- printf("Dependency cycle detected:\n");
- printf(" '%s' depends on '%s' through '%s'\n",
- to->full_identifier().c_str(),
- node->full_identifier().c_str(),
- rel->name);
- StackEntry *current = entry;
- while (current->node != to) {
- BLI_assert(current != NULL);
- printf(" '%s' depends on '%s' through '%s'\n",
- current->node->full_identifier().c_str(),
- current->from->node->full_identifier().c_str(),
- current->via_relation->name);
- current = current->from;
- }
- Relation *sacrificial_relation =
- select_relation_to_murder(rel, entry);
- sacrificial_relation->flag |= RELATION_FLAG_CYCLIC;
- ++state->num_cycles;
- }
- else if (to_state == NODE_NOT_VISITED) {
- StackEntry new_entry;
- new_entry.node = to;
- new_entry.from = entry;
- new_entry.via_relation = rel;
- BLI_stack_push(traversal_stack, &new_entry);
- set_node_visited_state(node, NODE_IN_STACK);
- all_child_traversed = false;
- set_node_num_visited_children(node, i);
- break;
- }
- }
- }
- if (all_child_traversed) {
- set_node_visited_state(node, NODE_VISITED);
- BLI_stack_discard(traversal_stack);
- }
- }
+ BLI_Stack *traversal_stack = state->traversal_stack;
+ while (!BLI_stack_is_empty(traversal_stack)) {
+ StackEntry *entry = (StackEntry *)BLI_stack_peek(traversal_stack);
+ OperationNode *node = entry->node;
+ bool all_child_traversed = true;
+ const int num_visited = get_node_num_visited_children(node);
+ for (int i = num_visited; i < node->outlinks.size(); ++i) {
+ Relation *rel = node->outlinks[i];
+ if (rel->to->type == NodeType::OPERATION) {
+ OperationNode *to = (OperationNode *)rel->to;
+ eCyclicCheckVisitedState to_state = get_node_visited_state(to);
+ if (to_state == NODE_IN_STACK) {
+ printf("Dependency cycle detected:\n");
+ printf(" '%s' depends on '%s' through '%s'\n",
+ to->full_identifier().c_str(),
+ node->full_identifier().c_str(),
+ rel->name);
+ StackEntry *current = entry;
+ while (current->node != to) {
+ BLI_assert(current != NULL);
+ printf(" '%s' depends on '%s' through '%s'\n",
+ current->node->full_identifier().c_str(),
+ current->from->node->full_identifier().c_str(),
+ current->via_relation->name);
+ current = current->from;
+ }
+ Relation *sacrificial_relation = select_relation_to_murder(rel, entry);
+ sacrificial_relation->flag |= RELATION_FLAG_CYCLIC;
+ ++state->num_cycles;
+ }
+ else if (to_state == NODE_NOT_VISITED) {
+ StackEntry new_entry;
+ new_entry.node = to;
+ new_entry.from = entry;
+ new_entry.via_relation = rel;
+ BLI_stack_push(traversal_stack, &new_entry);
+ set_node_visited_state(node, NODE_IN_STACK);
+ all_child_traversed = false;
+ set_node_num_visited_children(node, i);
+ break;
+ }
+ }
+ }
+ if (all_child_traversed) {
+ set_node_visited_state(node, NODE_VISITED);
+ BLI_stack_discard(traversal_stack);
+ }
+ }
}
} // namespace
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);
- }
+ 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_cycle.h b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h
index 2fe24d1795a..aafdcdbea04 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.h
@@ -21,7 +21,6 @@
* \ingroup depsgraph
*/
-
#pragma once
namespace DEG {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.cc b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
index cc5ea98ca93..a519f3e60b5 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.cc
@@ -32,32 +32,32 @@ namespace DEG {
BuilderMap::BuilderMap()
{
- set = BLI_gset_ptr_new("deg builder gset");
+ set = BLI_gset_ptr_new("deg builder gset");
}
BuilderMap::~BuilderMap()
{
- BLI_gset_free(set, NULL);
+ BLI_gset_free(set, NULL);
}
bool BuilderMap::checkIsBuilt(ID *id)
{
- return BLI_gset_haskey(set, id);
+ return BLI_gset_haskey(set, id);
}
void BuilderMap::tagBuild(ID *id)
{
- BLI_gset_insert(set, 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;
+ 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
index 193a7837aa6..c1db1d9d2bb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h
@@ -29,32 +29,35 @@ 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;
+ 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 0cc1c2aa211..b37ecb45ac8 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc
@@ -114,16 +114,15 @@ namespace {
void free_copy_on_write_datablock(void *id_info_v)
{
- DepsgraphNodeBuilder::IDInfo *id_info =
- (DepsgraphNodeBuilder::IDInfo *)id_info_v;
- if (id_info->id_cow != NULL) {
- deg_free_copy_on_write_datablock(id_info->id_cow);
- MEM_freeN(id_info->id_cow);
- }
- MEM_freeN(id_info);
+ DepsgraphNodeBuilder::IDInfo *id_info = (DepsgraphNodeBuilder::IDInfo *)id_info_v;
+ if (id_info->id_cow != NULL) {
+ deg_free_copy_on_write_datablock(id_info->id_cow);
+ MEM_freeN(id_info->id_cow);
+ }
+ MEM_freeN(id_info);
}
-} /* namespace */
+} /* namespace */
/* ************ */
/* Node Builder */
@@ -143,131 +142,122 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
DepsgraphNodeBuilder::~DepsgraphNodeBuilder()
{
- if (id_info_hash_ != NULL) {
- BLI_ghash_free(id_info_hash_, NULL, free_copy_on_write_datablock);
- }
+ if (id_info_hash_ != NULL) {
+ BLI_ghash_free(id_info_hash_, NULL, free_copy_on_write_datablock);
+ }
}
IDNode *DepsgraphNodeBuilder::add_id_node(ID *id)
{
- IDNode *id_node = NULL;
- ID *id_cow = NULL;
- IDComponentsMask previously_visible_components_mask = 0;
- uint32_t previous_eval_flags = 0;
- DEGCustomDataMeshMasks previous_customdata_masks;
- IDInfo *id_info = (IDInfo *)BLI_ghash_lookup(id_info_hash_, id);
- if (id_info != NULL) {
- id_cow = id_info->id_cow;
- previously_visible_components_mask =
- id_info->previously_visible_components_mask;
- previous_eval_flags = id_info->previous_eval_flags;
- previous_customdata_masks = id_info->previous_customdata_masks;
- /* Tag ID info to not free the CoW ID pointer. */
- id_info->id_cow = NULL;
- }
- id_node = graph_->add_id_node(id, id_cow);
- id_node->previously_visible_components_mask =
- previously_visible_components_mask;
- id_node->previous_eval_flags = previous_eval_flags;
- id_node->previous_customdata_masks = previous_customdata_masks;
- /* 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_len(id_node->components) == 0) {
- ComponentNode *comp_cow =
- id_node->add_component(NodeType::COPY_ON_WRITE);
- OperationNode *op_cow = comp_cow->add_operation(
- function_bind(deg_evaluate_copy_on_write, _1, id_node),
- OperationCode::COPY_ON_WRITE,
- "", -1);
- graph_->operations.push_back(op_cow);
- }
- return id_node;
+ IDNode *id_node = NULL;
+ ID *id_cow = NULL;
+ IDComponentsMask previously_visible_components_mask = 0;
+ uint32_t previous_eval_flags = 0;
+ DEGCustomDataMeshMasks previous_customdata_masks;
+ IDInfo *id_info = (IDInfo *)BLI_ghash_lookup(id_info_hash_, id);
+ if (id_info != NULL) {
+ id_cow = id_info->id_cow;
+ previously_visible_components_mask = id_info->previously_visible_components_mask;
+ previous_eval_flags = id_info->previous_eval_flags;
+ previous_customdata_masks = id_info->previous_customdata_masks;
+ /* Tag ID info to not free the CoW ID pointer. */
+ id_info->id_cow = NULL;
+ }
+ id_node = graph_->add_id_node(id, id_cow);
+ id_node->previously_visible_components_mask = previously_visible_components_mask;
+ id_node->previous_eval_flags = previous_eval_flags;
+ id_node->previous_customdata_masks = previous_customdata_masks;
+ /* 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_len(id_node->components) == 0) {
+ ComponentNode *comp_cow = id_node->add_component(NodeType::COPY_ON_WRITE);
+ OperationNode *op_cow = comp_cow->add_operation(
+ function_bind(deg_evaluate_copy_on_write, _1, id_node),
+ OperationCode::COPY_ON_WRITE,
+ "",
+ -1);
+ graph_->operations.push_back(op_cow);
+ }
+ return id_node;
}
IDNode *DepsgraphNodeBuilder::find_id_node(ID *id)
{
- return graph_->find_id_node(id);
+ return graph_->find_id_node(id);
}
TimeSourceNode *DepsgraphNodeBuilder::add_time_source()
{
- return graph_->add_time_source();
+ return graph_->add_time_source();
}
-ComponentNode *DepsgraphNodeBuilder::add_component_node(
- ID *id,
- NodeType comp_type,
- const char *comp_name)
+ComponentNode *DepsgraphNodeBuilder::add_component_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name)
{
- IDNode *id_node = add_id_node(id);
- ComponentNode *comp_node = id_node->add_component(comp_type, comp_name);
- comp_node->owner = id_node;
- return comp_node;
+ IDNode *id_node = add_id_node(id);
+ ComponentNode *comp_node = id_node->add_component(comp_type, comp_name);
+ comp_node->owner = id_node;
+ return comp_node;
}
-OperationNode *DepsgraphNodeBuilder::add_operation_node(
- ComponentNode *comp_node,
- OperationCode opcode,
- const DepsEvalOperationCb& op,
- const char *name,
- int name_tag)
+OperationNode *DepsgraphNodeBuilder::add_operation_node(ComponentNode *comp_node,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op,
+ const char *name,
+ int name_tag)
{
- OperationNode *op_node = comp_node->find_operation(opcode, name, name_tag);
- if (op_node == NULL) {
- op_node = comp_node->add_operation(op, opcode, name, name_tag);
- graph_->operations.push_back(op_node);
- }
- else {
- fprintf(stderr,
- "add_operation: Operation already exists - %s has %s at %p\n",
- comp_node->identifier().c_str(),
- op_node->identifier().c_str(),
- op_node);
- BLI_assert(!"Should not happen!");
- }
- return op_node;
+ OperationNode *op_node = comp_node->find_operation(opcode, name, name_tag);
+ if (op_node == NULL) {
+ op_node = comp_node->add_operation(op, opcode, name, name_tag);
+ graph_->operations.push_back(op_node);
+ }
+ else {
+ fprintf(stderr,
+ "add_operation: Operation already exists - %s has %s at %p\n",
+ comp_node->identifier().c_str(),
+ op_node->identifier().c_str(),
+ op_node);
+ BLI_assert(!"Should not happen!");
+ }
+ return op_node;
}
-OperationNode *DepsgraphNodeBuilder::add_operation_node(
- ID *id,
- NodeType comp_type,
- const char *comp_name,
- OperationCode opcode,
- const DepsEvalOperationCb& op,
- const char *name,
- int name_tag)
+OperationNode *DepsgraphNodeBuilder::add_operation_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op,
+ const char *name,
+ int name_tag)
{
- ComponentNode *comp_node = add_component_node(id, comp_type, comp_name);
- return add_operation_node(comp_node, opcode, op, name, name_tag);
+ ComponentNode *comp_node = add_component_node(id, comp_type, comp_name);
+ return add_operation_node(comp_node, opcode, op, name, name_tag);
}
-OperationNode *DepsgraphNodeBuilder::add_operation_node(
- ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const DepsEvalOperationCb& op,
- const char *name,
- int name_tag)
+OperationNode *DepsgraphNodeBuilder::add_operation_node(ID *id,
+ NodeType comp_type,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op,
+ const char *name,
+ int name_tag)
{
- return add_operation_node(
- id, comp_type, "", opcode, op, name, name_tag);
+ return add_operation_node(id, comp_type, "", opcode, op, name, name_tag);
}
-OperationNode *DepsgraphNodeBuilder::ensure_operation_node(
- ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const DepsEvalOperationCb& op,
- const char *name,
- int name_tag)
+OperationNode *DepsgraphNodeBuilder::ensure_operation_node(ID *id,
+ NodeType comp_type,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op,
+ const char *name,
+ int name_tag)
{
- OperationNode *operation =
- find_operation_node(id, comp_type, opcode, name, name_tag);
- if (operation != NULL) {
- return operation;
- }
- return add_operation_node(id, comp_type, opcode, op, name, name_tag);
+ OperationNode *operation = find_operation_node(id, comp_type, opcode, name, name_tag);
+ if (operation != NULL) {
+ return operation;
+ }
+ return add_operation_node(id, comp_type, opcode, op, name, name_tag);
}
bool DepsgraphNodeBuilder::has_operation_node(ID *id,
@@ -277,266 +267,245 @@ bool DepsgraphNodeBuilder::has_operation_node(ID *id,
const char *name,
int name_tag)
{
- return find_operation_node(
- id, comp_type, comp_name, opcode, name, name_tag) != NULL;
+ return find_operation_node(id, comp_type, comp_name, opcode, name, name_tag) != NULL;
}
-OperationNode *DepsgraphNodeBuilder::find_operation_node(
- ID *id,
- NodeType comp_type,
- const char *comp_name,
- OperationCode opcode,
- const char *name,
- int name_tag)
+OperationNode *DepsgraphNodeBuilder::find_operation_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name,
+ OperationCode opcode,
+ const char *name,
+ int name_tag)
{
- ComponentNode *comp_node = add_component_node(id, comp_type, comp_name);
- return comp_node->find_operation(opcode, name, name_tag);
+ ComponentNode *comp_node = add_component_node(id, comp_type, comp_name);
+ return comp_node->find_operation(opcode, name, name_tag);
}
OperationNode *DepsgraphNodeBuilder::find_operation_node(
- ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const char *name,
- int name_tag)
+ ID *id, NodeType comp_type, OperationCode opcode, const char *name, int name_tag)
{
- return find_operation_node(id, comp_type, "", opcode, name, name_tag);
+ return find_operation_node(id, comp_type, "", opcode, name, name_tag);
}
ID *DepsgraphNodeBuilder::get_cow_id(const ID *id_orig) const
{
- return graph_->get_cow_id(id_orig);
+ return graph_->get_cow_id(id_orig);
}
ID *DepsgraphNodeBuilder::ensure_cow_id(ID *id_orig)
{
- if (id_orig->tag & LIB_TAG_COPIED_ON_WRITE) {
- /* ID is already remapped to copy-on-write. */
- return id_orig;
- }
- IDNode *id_node = add_id_node(id_orig);
- return id_node->id_cow;
+ if (id_orig->tag & LIB_TAG_COPIED_ON_WRITE) {
+ /* ID is already remapped to copy-on-write. */
+ return id_orig;
+ }
+ IDNode *id_node = add_id_node(id_orig);
+ return id_node->id_cow;
}
/* **** Build functions for entity nodes **** */
void DepsgraphNodeBuilder::begin_build()
{
- /* Store existing copy-on-write versions of datablock, so we can re-use
- * them for new ID nodes. */
- id_info_hash_ = BLI_ghash_ptr_new("Depsgraph id hash");
- for (IDNode *id_node : graph_->id_nodes) {
- IDInfo *id_info = (IDInfo *)MEM_mallocN(
- sizeof(IDInfo), "depsgraph id info");
- if (deg_copy_on_write_is_expanded(id_node->id_cow) &&
- id_node->id_orig != id_node->id_cow)
- {
- id_info->id_cow = id_node->id_cow;
- }
- else {
- id_info->id_cow = NULL;
- }
- id_info->previously_visible_components_mask =
- id_node->visible_components_mask;
- id_info->previous_eval_flags = id_node->eval_flags;
- id_info->previous_customdata_masks = id_node->customdata_masks;
- BLI_ghash_insert(id_info_hash_, id_node->id_orig, id_info);
- id_node->id_cow = NULL;
- }
-
- GSET_FOREACH_BEGIN(OperationNode *, op_node, graph_->entry_tags)
- {
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
-
- SavedEntryTag entry_tag;
- entry_tag.id_orig = id_node->id_orig;
- entry_tag.component_type = comp_node->type;
- entry_tag.opcode = op_node->opcode;
- entry_tag.name = op_node->name;
- entry_tag.name_tag = op_node->name_tag;
- saved_entry_tags_.push_back(entry_tag);
- };
- GSET_FOREACH_END();
-
- /* Make sure graph has no nodes left from previous state. */
- graph_->clear_all_nodes();
- graph_->operations.clear();
- BLI_gset_clear(graph_->entry_tags, NULL);
+ /* Store existing copy-on-write versions of datablock, so we can re-use
+ * them for new ID nodes. */
+ id_info_hash_ = BLI_ghash_ptr_new("Depsgraph id hash");
+ for (IDNode *id_node : graph_->id_nodes) {
+ IDInfo *id_info = (IDInfo *)MEM_mallocN(sizeof(IDInfo), "depsgraph id info");
+ if (deg_copy_on_write_is_expanded(id_node->id_cow) && id_node->id_orig != id_node->id_cow) {
+ id_info->id_cow = id_node->id_cow;
+ }
+ else {
+ id_info->id_cow = NULL;
+ }
+ id_info->previously_visible_components_mask = id_node->visible_components_mask;
+ id_info->previous_eval_flags = id_node->eval_flags;
+ id_info->previous_customdata_masks = id_node->customdata_masks;
+ BLI_ghash_insert(id_info_hash_, id_node->id_orig, id_info);
+ id_node->id_cow = NULL;
+ }
+
+ GSET_FOREACH_BEGIN (OperationNode *, op_node, graph_->entry_tags) {
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+
+ SavedEntryTag entry_tag;
+ entry_tag.id_orig = id_node->id_orig;
+ entry_tag.component_type = comp_node->type;
+ entry_tag.opcode = op_node->opcode;
+ entry_tag.name = op_node->name;
+ entry_tag.name_tag = op_node->name_tag;
+ saved_entry_tags_.push_back(entry_tag);
+ };
+ GSET_FOREACH_END();
+
+ /* Make sure graph has no nodes left from previous state. */
+ graph_->clear_all_nodes();
+ graph_->operations.clear();
+ BLI_gset_clear(graph_->entry_tags, NULL);
}
void DepsgraphNodeBuilder::end_build()
{
- for (const SavedEntryTag& entry_tag : saved_entry_tags_) {
- IDNode *id_node = find_id_node(entry_tag.id_orig);
- if (id_node == NULL) {
- continue;
- }
- ComponentNode *comp_node =
- id_node->find_component(entry_tag.component_type);
- if (comp_node == NULL) {
- continue;
- }
- OperationNode *op_node = comp_node->find_operation(
- entry_tag.opcode, entry_tag.name.c_str(), entry_tag.name_tag);
- if (op_node == NULL) {
- continue;
- }
- /* Since the tag is coming from a saved copy of entry tags, this means
- * that originally node was explicitly tagged for user update. */
- op_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT);
- }
+ for (const SavedEntryTag &entry_tag : saved_entry_tags_) {
+ IDNode *id_node = find_id_node(entry_tag.id_orig);
+ if (id_node == NULL) {
+ continue;
+ }
+ ComponentNode *comp_node = id_node->find_component(entry_tag.component_type);
+ if (comp_node == NULL) {
+ continue;
+ }
+ OperationNode *op_node = comp_node->find_operation(
+ entry_tag.opcode, entry_tag.name.c_str(), entry_tag.name_tag);
+ if (op_node == NULL) {
+ continue;
+ }
+ /* Since the tag is coming from a saved copy of entry tags, this means
+ * that originally node was explicitly tagged for user update. */
+ op_node->tag_update(graph_, DEG_UPDATE_SOURCE_USER_EDIT);
+ }
}
void DepsgraphNodeBuilder::build_id(ID *id)
{
- if (id == NULL) {
- return;
- }
- switch (GS(id->name)) {
- case ID_AC:
- build_action((bAction *)id);
- break;
- case ID_AR:
- build_armature((bArmature *)id);
- break;
- case ID_CA:
- build_camera((Camera *)id);
- break;
- case ID_GR:
- build_collection(NULL, (Collection *)id);
- break;
- case ID_OB:
- /* TODO(sergey): Get visibility from a "parent" somehow.
- *
- * NOTE: Using `false` visibility here should be fine, since if this
- * driver affects on something invisible we don't really care if the
- * driver gets evaluated (and even don't want this to force object
- * to become visible).
- *
- * If this happened to be affecting visible object, then it is up to
- * deg_graph_build_flush_visibility() to ensure visibility of the
- * object is true. */
- build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, false);
- break;
- case ID_KE:
- build_shapekeys((Key *)id);
- break;
- case ID_LA:
- build_light((Light *)id);
- break;
- case ID_LP:
- build_lightprobe((LightProbe *)id);
- break;
- case ID_NT:
- build_nodetree((bNodeTree *)id);
- break;
- case ID_MA:
- build_material((Material *)id);
- break;
- case ID_TE:
- build_texture((Tex *)id);
- break;
- case ID_IM:
- build_image((Image *)id);
- break;
- case ID_WO:
- build_world((World *)id);
- break;
- case ID_MSK:
- build_mask((Mask *)id);
- break;
- case ID_MC:
- build_movieclip((MovieClip *)id);
- break;
- case ID_ME:
- case ID_CU:
- case ID_MB:
- case ID_LT:
- /* TODO(sergey): Get visibility from a "parent" somehow.
- *
- * NOTE: Similarly to above, we don't want false-positives on
- * visibility. */
- build_object_data_geometry_datablock(id, false);
- break;
- case ID_SPK:
- build_speaker((Speaker *)id);
- break;
- case ID_TXT:
- /* Not a part of dependency graph. */
- break;
- case ID_CF:
- build_cachefile((CacheFile *)id);
- break;
- default:
- fprintf(stderr, "Unhandled ID %s\n", id->name);
- BLI_assert(!"Should never happen");
- break;
- }
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_AC:
+ build_action((bAction *)id);
+ break;
+ case ID_AR:
+ build_armature((bArmature *)id);
+ break;
+ case ID_CA:
+ build_camera((Camera *)id);
+ break;
+ case ID_GR:
+ build_collection(NULL, (Collection *)id);
+ break;
+ case ID_OB:
+ /* TODO(sergey): Get visibility from a "parent" somehow.
+ *
+ * NOTE: Using `false` visibility here should be fine, since if this
+ * driver affects on something invisible we don't really care if the
+ * driver gets evaluated (and even don't want this to force object
+ * to become visible).
+ *
+ * If this happened to be affecting visible object, then it is up to
+ * deg_graph_build_flush_visibility() to ensure visibility of the
+ * object is true. */
+ build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, false);
+ break;
+ case ID_KE:
+ build_shapekeys((Key *)id);
+ break;
+ case ID_LA:
+ build_light((Light *)id);
+ break;
+ case ID_LP:
+ build_lightprobe((LightProbe *)id);
+ break;
+ case ID_NT:
+ build_nodetree((bNodeTree *)id);
+ break;
+ case ID_MA:
+ build_material((Material *)id);
+ break;
+ case ID_TE:
+ build_texture((Tex *)id);
+ break;
+ case ID_IM:
+ build_image((Image *)id);
+ break;
+ case ID_WO:
+ build_world((World *)id);
+ break;
+ case ID_MSK:
+ build_mask((Mask *)id);
+ break;
+ case ID_MC:
+ build_movieclip((MovieClip *)id);
+ break;
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ case ID_LT:
+ /* TODO(sergey): Get visibility from a "parent" somehow.
+ *
+ * NOTE: Similarly to above, we don't want false-positives on
+ * visibility. */
+ build_object_data_geometry_datablock(id, false);
+ break;
+ case ID_SPK:
+ build_speaker((Speaker *)id);
+ break;
+ case ID_TXT:
+ /* Not a part of dependency graph. */
+ break;
+ case ID_CF:
+ build_cachefile((CacheFile *)id);
+ break;
+ default:
+ fprintf(stderr, "Unhandled ID %s\n", id->name);
+ BLI_assert(!"Should never happen");
+ break;
+ }
}
-void DepsgraphNodeBuilder::build_collection(
- LayerCollection *from_layer_collection,
- Collection *collection)
+void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collection,
+ Collection *collection)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT)
- ? COLLECTION_RESTRICT_VIEW
- : COLLECTION_RESTRICT_RENDER;
- const bool is_collection_restricted = (collection->flag & restrict_flag);
- const bool is_collection_visible =
- !is_collection_restricted && is_parent_collection_visible_;
- IDNode *id_node;
- if (built_map_.checkIsBuiltAndTag(collection)) {
- id_node = find_id_node(&collection->id);
- if (is_collection_visible &&
- id_node->is_directly_visible == false &&
- id_node->is_collection_fully_expanded == true)
- {
- /* Collection became visible, make sure nested collections and
- * objects are poked with the new visibility flag, since they
- * might become visible too. */
- }
- else if (from_layer_collection == NULL &&
- !id_node->is_collection_fully_expanded)
- {
- /* Initially collection was built from layer now, and was requested
- * to not recurs into object. But nw it's asked to recurs into all
- * objects. */
- }
- else {
- return;
- }
- }
- else {
- /* Collection itself. */
- id_node = add_id_node(&collection->id);
- id_node->is_directly_visible = is_collection_visible;
- }
- if (from_layer_collection != NULL) {
- /* If we came from layer collection we don't go deeper, view layer
- * builder takes care of going deeper. */
- return;
- }
- /* Backup state. */
- Collection *current_state_collection = collection_;
- const bool is_current_parent_collection_visible =
- is_parent_collection_visible_;
- /* Modify state as we've entered new collection/ */
- collection_ = collection;
- is_parent_collection_visible_ = is_collection_visible;
- /* Build collection objects. */
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- build_object(
- -1, cob->ob, DEG_ID_LINKED_INDIRECTLY, is_collection_visible);
- }
- /* Build child collections. */
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- build_collection(NULL, child->collection);
- }
- /* Restore state. */
- collection_ = current_state_collection;
- is_parent_collection_visible_ = is_current_parent_collection_visible;
- id_node->is_collection_fully_expanded = true;
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ COLLECTION_RESTRICT_RENDER;
+ const bool is_collection_restricted = (collection->flag & restrict_flag);
+ const bool is_collection_visible = !is_collection_restricted && is_parent_collection_visible_;
+ IDNode *id_node;
+ if (built_map_.checkIsBuiltAndTag(collection)) {
+ id_node = find_id_node(&collection->id);
+ if (is_collection_visible && id_node->is_directly_visible == false &&
+ id_node->is_collection_fully_expanded == true) {
+ /* Collection became visible, make sure nested collections and
+ * objects are poked with the new visibility flag, since they
+ * might become visible too. */
+ }
+ else if (from_layer_collection == NULL && !id_node->is_collection_fully_expanded) {
+ /* Initially collection was built from layer now, and was requested
+ * to not recurs into object. But nw it's asked to recurs into all
+ * objects. */
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ /* Collection itself. */
+ id_node = add_id_node(&collection->id);
+ id_node->is_directly_visible = is_collection_visible;
+ }
+ if (from_layer_collection != NULL) {
+ /* If we came from layer collection we don't go deeper, view layer
+ * builder takes care of going deeper. */
+ return;
+ }
+ /* Backup state. */
+ Collection *current_state_collection = collection_;
+ const bool is_current_parent_collection_visible = is_parent_collection_visible_;
+ /* Modify state as we've entered new collection/ */
+ collection_ = collection;
+ is_parent_collection_visible_ = is_collection_visible;
+ /* Build collection objects. */
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ build_object(-1, cob->ob, DEG_ID_LINKED_INDIRECTLY, is_collection_visible);
+ }
+ /* Build child collections. */
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ build_collection(NULL, child->collection);
+ }
+ /* Restore state. */
+ collection_ = current_state_collection;
+ is_parent_collection_visible_ = is_current_parent_collection_visible;
+ id_node->is_collection_fully_expanded = true;
}
void DepsgraphNodeBuilder::build_object(int base_index,
@@ -544,252 +513,236 @@ void DepsgraphNodeBuilder::build_object(int base_index,
eDepsNode_LinkedState_Type linked_state,
bool is_visible)
{
- const bool has_object = built_map_.checkIsBuiltAndTag(object);
- /* Skip rest of components if the ID node was already there. */
- if (has_object) {
- IDNode *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_index, object, linked_state);
- }
- id_node->linked_state = max(id_node->linked_state, linked_state);
- if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
- id_node->is_directly_visible |= is_visible;
- }
- return;
- }
- /* Create ID node for object and begin init. */
- IDNode *id_node = add_id_node(&object->id);
- Object *object_cow = get_cow_datablock(object);
- id_node->linked_state = linked_state;
- if (object == scene_->camera) {
- id_node->is_directly_visible = true;
- }
- else {
- id_node->is_directly_visible = is_visible;
- }
- /* Various flags, flushing from bases/collections. */
- build_object_flags(base_index, object, linked_state);
- /* Transform. */
- build_object_transform(object);
- /* Parent. */
- if (object->parent != NULL) {
- build_object(
- -1, object->parent, DEG_ID_LINKED_INDIRECTLY, is_visible);
- }
- /* Modifiers. */
- if (object->modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- data.is_parent_visible = is_visible;
- modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Grease Pencil Modifiers. */
- if (object->greasepencil_modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- data.is_parent_visible = is_visible;
- BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Shader FX. */
- if (object->shader_fx.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- data.is_parent_visible = is_visible;
- BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
- }
- /* Constraints. */
- if (object->constraints.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- data.is_parent_visible = is_visible;
- BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
- }
- /* Object data. */
- build_object_data(object, is_visible);
- /* Paramaters, used by both drivers/animation and also to inform dependency
- * from object's data. */
- build_parameters(&object->id);
- /* Build animation data,
- *
- * Do it now because it's possible object data will affect
- * on object's level animation, for example in case of rebuilding
- * pose for proxy. */
- build_animdata(&object->id);
- /* Particle systems. */
- if (object->particlesystem.first != NULL) {
- build_particle_systems(object, is_visible);
- }
- /* Proxy object to copy from. */
- if (object->proxy_from != NULL) {
- build_object(
- -1, object->proxy_from, DEG_ID_LINKED_INDIRECTLY, is_visible);
- }
- if (object->proxy_group != NULL) {
- build_object(
- -1, object->proxy_group, DEG_ID_LINKED_INDIRECTLY, is_visible);
- }
- /* Object dupligroup. */
- if (object->instance_collection != NULL) {
- const bool is_current_parent_collection_visible =
- is_parent_collection_visible_;
- is_parent_collection_visible_ = is_visible;
- build_collection(NULL, object->instance_collection);
- is_parent_collection_visible_ = is_current_parent_collection_visible;
- add_operation_node(
- &object->id, NodeType::DUPLI, OperationCode::DUPLI);
- }
- /* Syncronization back to original object. */
- add_operation_node(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL,
- function_bind(BKE_object_synchronize_to_original,
- _1,
- object_cow));
+ const bool has_object = built_map_.checkIsBuiltAndTag(object);
+ /* Skip rest of components if the ID node was already there. */
+ if (has_object) {
+ IDNode *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_index, object, linked_state);
+ }
+ id_node->linked_state = max(id_node->linked_state, linked_state);
+ if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
+ id_node->is_directly_visible |= is_visible;
+ }
+ return;
+ }
+ /* Create ID node for object and begin init. */
+ IDNode *id_node = add_id_node(&object->id);
+ Object *object_cow = get_cow_datablock(object);
+ id_node->linked_state = linked_state;
+ if (object == scene_->camera) {
+ id_node->is_directly_visible = true;
+ }
+ else {
+ id_node->is_directly_visible = is_visible;
+ }
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base_index, object, linked_state);
+ /* Transform. */
+ build_object_transform(object);
+ /* Parent. */
+ if (object->parent != NULL) {
+ build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY, is_visible);
+ }
+ /* Modifiers. */
+ if (object->modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.is_parent_visible = is_visible;
+ modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.is_parent_visible = is_visible;
+ BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.is_parent_visible = is_visible;
+ BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Constraints. */
+ if (object->constraints.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.is_parent_visible = is_visible;
+ BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
+ }
+ /* Object data. */
+ build_object_data(object, is_visible);
+ /* Paramaters, used by both drivers/animation and also to inform dependency
+ * from object's data. */
+ build_parameters(&object->id);
+ /* Build animation data,
+ *
+ * Do it now because it's possible object data will affect
+ * on object's level animation, for example in case of rebuilding
+ * pose for proxy. */
+ build_animdata(&object->id);
+ /* Particle systems. */
+ if (object->particlesystem.first != NULL) {
+ build_particle_systems(object, is_visible);
+ }
+ /* Proxy object to copy from. */
+ if (object->proxy_from != NULL) {
+ build_object(-1, object->proxy_from, DEG_ID_LINKED_INDIRECTLY, is_visible);
+ }
+ if (object->proxy_group != NULL) {
+ build_object(-1, object->proxy_group, DEG_ID_LINKED_INDIRECTLY, is_visible);
+ }
+ /* Object dupligroup. */
+ if (object->instance_collection != NULL) {
+ const bool is_current_parent_collection_visible = is_parent_collection_visible_;
+ is_parent_collection_visible_ = is_visible;
+ build_collection(NULL, object->instance_collection);
+ is_parent_collection_visible_ = is_current_parent_collection_visible;
+ add_operation_node(&object->id, NodeType::DUPLI, OperationCode::DUPLI);
+ }
+ /* Syncronization back to original object. */
+ add_operation_node(&object->id,
+ NodeType::SYNCHRONIZATION,
+ OperationCode::SYNCHRONIZE_TO_ORIGINAL,
+ function_bind(BKE_object_synchronize_to_original, _1, object_cow));
}
-void DepsgraphNodeBuilder::build_object_flags(
- int base_index,
- Object *object,
- eDepsNode_LinkedState_Type linked_state)
+void DepsgraphNodeBuilder::build_object_flags(int base_index,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state)
{
- if (base_index == -1) {
- return;
- }
- Scene *scene_cow = get_cow_datablock(scene_);
- Object *object_cow = get_cow_datablock(object);
- const bool is_from_set = (linked_state == DEG_ID_LINKED_VIA_SET);
- /* TODO(sergey): Is this really best component to be used? */
- add_operation_node(&object->id,
- NodeType::OBJECT_FROM_LAYER,
- OperationCode::OBJECT_BASE_FLAGS,
- function_bind(BKE_object_eval_eval_base_flags,
- _1,
- scene_cow,
- view_layer_index_,
- object_cow, base_index,
- is_from_set));
+ if (base_index == -1) {
+ return;
+ }
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
+ const bool is_from_set = (linked_state == DEG_ID_LINKED_VIA_SET);
+ /* TODO(sergey): Is this really best component to be used? */
+ add_operation_node(&object->id,
+ NodeType::OBJECT_FROM_LAYER,
+ OperationCode::OBJECT_BASE_FLAGS,
+ function_bind(BKE_object_eval_eval_base_flags,
+ _1,
+ scene_cow,
+ view_layer_index_,
+ object_cow,
+ base_index,
+ is_from_set));
}
-void DepsgraphNodeBuilder::build_object_data(
- Object *object, bool is_object_visible)
+void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visible)
{
- if (object->data == NULL) {
- return;
- }
- /* type-specific data. */
- switch (object->type) {
- case OB_MESH:
- case OB_CURVE:
- case OB_FONT:
- case OB_SURF:
- case OB_MBALL:
- case OB_LATTICE:
- case OB_GPENCIL:
- build_object_data_geometry(object, is_object_visible);
- break;
- case OB_ARMATURE:
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- build_proxy_rig(object);
- }
- else {
- build_rig(object, is_object_visible);
- }
- break;
- case OB_LAMP:
- build_object_data_light(object);
- break;
- case OB_CAMERA:
- build_object_data_camera(object);
- break;
- case OB_LIGHTPROBE:
- build_object_data_lightprobe(object);
- break;
- case OB_SPEAKER:
- build_object_data_speaker(object);
- break;
- default:
- {
- ID *obdata = (ID *)object->data;
- if (built_map_.checkIsBuilt(obdata) == 0) {
- build_animdata(obdata);
- }
- break;
- }
- }
+ if (object->data == NULL) {
+ return;
+ }
+ /* type-specific data. */
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ case OB_GPENCIL:
+ build_object_data_geometry(object, is_object_visible);
+ break;
+ case OB_ARMATURE:
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ build_proxy_rig(object);
+ }
+ else {
+ build_rig(object, is_object_visible);
+ }
+ break;
+ case OB_LAMP:
+ build_object_data_light(object);
+ break;
+ case OB_CAMERA:
+ build_object_data_camera(object);
+ break;
+ case OB_LIGHTPROBE:
+ build_object_data_lightprobe(object);
+ break;
+ case OB_SPEAKER:
+ build_object_data_speaker(object);
+ break;
+ default: {
+ ID *obdata = (ID *)object->data;
+ if (built_map_.checkIsBuilt(obdata) == 0) {
+ build_animdata(obdata);
+ }
+ break;
+ }
+ }
}
void DepsgraphNodeBuilder::build_object_data_camera(Object *object)
{
- Camera *camera = (Camera *)object->data;
- build_camera(camera);
+ Camera *camera = (Camera *)object->data;
+ build_camera(camera);
}
void DepsgraphNodeBuilder::build_object_data_light(Object *object)
{
- Light *lamp = (Light *)object->data;
- build_light(lamp);
+ Light *lamp = (Light *)object->data;
+ build_light(lamp);
}
void DepsgraphNodeBuilder::build_object_data_lightprobe(Object *object)
{
- LightProbe *probe = (LightProbe *)object->data;
- build_lightprobe(probe);
- add_operation_node(
- &object->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ LightProbe *probe = (LightProbe *)object->data;
+ build_lightprobe(probe);
+ add_operation_node(&object->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
}
void DepsgraphNodeBuilder::build_object_data_speaker(Object *object)
{
- Speaker *speaker = (Speaker *)object->data;
- build_speaker(speaker);
- add_operation_node(
- &object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ Speaker *speaker = (Speaker *)object->data;
+ build_speaker(speaker);
+ add_operation_node(&object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
}
void DepsgraphNodeBuilder::build_object_transform(Object *object)
{
- OperationNode *op_node;
- Object *ob_cow = get_cow_datablock(object);
- /* Transform entry operation. */
- op_node = add_operation_node(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
- op_node->set_as_entry();
- /* Local transforms (from transform channels - loc/rot/scale + deltas). */
- add_operation_node(&object->id, NodeType::TRANSFORM,
- OperationCode::TRANSFORM_LOCAL,
- function_bind(BKE_object_eval_local_transform,
- _1,
- ob_cow));
- /* Object parent. */
- if (object->parent != NULL) {
- add_operation_node(&object->id, NodeType::TRANSFORM,
- OperationCode::TRANSFORM_PARENT,
- function_bind(BKE_object_eval_parent, _1, ob_cow));
- }
- /* Object constraints. */
- if (object->constraints.first != NULL) {
- build_object_constraints(object);
- }
- /* Rest of transformation update. */
- add_operation_node(&object->id, NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL,
- function_bind(BKE_object_eval_uber_transform,
- _1,
- ob_cow));
- /* Operation to take of rigid body simulation. soft bodies and other firends
- * in the context of point cache invalidation. */
- add_operation_node(&object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- /* Object transform is done. */
- op_node = add_operation_node(&object->id, NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL,
- function_bind(BKE_object_eval_transform_final,
- _1,
- ob_cow));
- op_node->set_as_exit();
+ OperationNode *op_node;
+ Object *ob_cow = get_cow_datablock(object);
+ /* Transform entry operation. */
+ op_node = add_operation_node(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
+ op_node->set_as_entry();
+ /* Local transforms (from transform channels - loc/rot/scale + deltas). */
+ add_operation_node(&object->id,
+ NodeType::TRANSFORM,
+ OperationCode::TRANSFORM_LOCAL,
+ function_bind(BKE_object_eval_local_transform, _1, ob_cow));
+ /* Object parent. */
+ if (object->parent != NULL) {
+ add_operation_node(&object->id,
+ NodeType::TRANSFORM,
+ OperationCode::TRANSFORM_PARENT,
+ function_bind(BKE_object_eval_parent, _1, ob_cow));
+ }
+ /* Object constraints. */
+ if (object->constraints.first != NULL) {
+ build_object_constraints(object);
+ }
+ /* Rest of transformation update. */
+ add_operation_node(&object->id,
+ NodeType::TRANSFORM,
+ OperationCode::TRANSFORM_EVAL,
+ function_bind(BKE_object_eval_uber_transform, _1, ob_cow));
+ /* Operation to take of rigid body simulation. soft bodies and other firends
+ * in the context of point cache invalidation. */
+ add_operation_node(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ /* Object transform is done. */
+ op_node = add_operation_node(&object->id,
+ NodeType::TRANSFORM,
+ OperationCode::TRANSFORM_FINAL,
+ function_bind(BKE_object_eval_transform_final, _1, ob_cow));
+ op_node->set_as_exit();
}
/**
@@ -811,29 +764,26 @@ void DepsgraphNodeBuilder::build_object_transform(Object *object)
*/
void DepsgraphNodeBuilder::build_object_constraints(Object *object)
{
- /* create node for constraint stack */
- add_operation_node(&object->id, NodeType::TRANSFORM,
- OperationCode::TRANSFORM_CONSTRAINTS,
- function_bind(BKE_object_eval_constraints,
- _1,
- get_cow_datablock(scene_),
- get_cow_datablock(object)));
+ /* create node for constraint stack */
+ add_operation_node(
+ &object->id,
+ NodeType::TRANSFORM,
+ OperationCode::TRANSFORM_CONSTRAINTS,
+ function_bind(
+ BKE_object_eval_constraints, _1, get_cow_datablock(scene_), get_cow_datablock(object)));
}
void DepsgraphNodeBuilder::build_object_pointcache(Object *object)
{
- if (!BKE_ptcache_object_has(scene_, object, 0)) {
- return;
- }
- Scene *scene_cow = get_cow_datablock(scene_);
- Object *object_cow = get_cow_datablock(object);
- add_operation_node(&object->id,
- NodeType::POINT_CACHE,
- OperationCode::POINT_CACHE_RESET,
- function_bind(BKE_object_eval_ptcache_reset,
- _1,
- scene_cow,
- object_cow));
+ if (!BKE_ptcache_object_has(scene_, object, 0)) {
+ return;
+ }
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
+ add_operation_node(&object->id,
+ NodeType::POINT_CACHE,
+ OperationCode::POINT_CACHE_RESET,
+ function_bind(BKE_object_eval_ptcache_reset, _1, scene_cow, object_cow));
}
/**
@@ -842,58 +792,55 @@ void DepsgraphNodeBuilder::build_object_pointcache(Object *object)
*/
void DepsgraphNodeBuilder::build_animdata(ID *id)
{
- /* Special handling for animated images/sequences. */
- build_animation_images(id);
- /* Regular animation. */
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return;
- }
- if (adt->action != NULL) {
- build_action(adt->action);
- }
- /* Make sure ID node exists. */
- (void) add_id_node(id);
- ID *id_cow = get_cow_id(id);
- if (adt->action != NULL || !BLI_listbase_is_empty(&adt->nla_tracks)) {
- OperationNode *operation_node;
- /* Explicit entry operation. */
- operation_node = add_operation_node(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
- operation_node->set_as_entry();
- /* All the evaluation nodes. */
- add_operation_node(
- id,
- NodeType::ANIMATION,
- OperationCode::ANIMATION_EVAL,
- function_bind(BKE_animsys_eval_animdata, _1, id_cow));
- /* Explicit exit operation. */
- operation_node = add_operation_node(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
- operation_node->set_as_exit();
- }
- /* NLA strips contain actions. */
- LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
- build_animdata_nlastrip_targets(&nlt->strips);
- }
- /* Drivers. */
- int driver_index = 0;
- LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
- /* create driver */
- build_driver(id, fcu, driver_index++);
- }
+ /* Special handling for animated images/sequences. */
+ build_animation_images(id);
+ /* Regular animation. */
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ if (adt->action != NULL) {
+ build_action(adt->action);
+ }
+ /* Make sure ID node exists. */
+ (void)add_id_node(id);
+ ID *id_cow = get_cow_id(id);
+ if (adt->action != NULL || !BLI_listbase_is_empty(&adt->nla_tracks)) {
+ OperationNode *operation_node;
+ /* Explicit entry operation. */
+ operation_node = add_operation_node(id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
+ operation_node->set_as_entry();
+ /* All the evaluation nodes. */
+ add_operation_node(id,
+ NodeType::ANIMATION,
+ OperationCode::ANIMATION_EVAL,
+ function_bind(BKE_animsys_eval_animdata, _1, id_cow));
+ /* Explicit exit operation. */
+ operation_node = add_operation_node(id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
+ operation_node->set_as_exit();
+ }
+ /* NLA strips contain actions. */
+ LISTBASE_FOREACH (NlaTrack *, nlt, &adt->nla_tracks) {
+ build_animdata_nlastrip_targets(&nlt->strips);
+ }
+ /* Drivers. */
+ int driver_index = 0;
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ /* create driver */
+ build_driver(id, fcu, driver_index++);
+ }
}
void DepsgraphNodeBuilder::build_animdata_nlastrip_targets(ListBase *strips)
{
- LISTBASE_FOREACH (NlaStrip *, strip, strips) {
- if (strip->act != NULL) {
- build_action(strip->act);
- }
- else if (strip->strips.first != NULL) {
- build_animdata_nlastrip_targets(&strip->strips);
- }
- }
+ LISTBASE_FOREACH (NlaStrip *, strip, strips) {
+ if (strip->act != NULL) {
+ build_action(strip->act);
+ }
+ else if (strip->strips.first != NULL) {
+ build_animdata_nlastrip_targets(&strip->strips);
+ }
+ }
}
/**
@@ -901,22 +848,21 @@ void DepsgraphNodeBuilder::build_animdata_nlastrip_targets(ListBase *strips)
*/
void DepsgraphNodeBuilder::build_animation_images(ID *id)
{
- if (BKE_image_user_id_has_animation(id)) {
- ID *id_cow = get_cow_id(id);
- add_operation_node(id,
- NodeType::ANIMATION,
- OperationCode::IMAGE_ANIMATION,
- function_bind(BKE_image_user_id_eval_animation, _1, id_cow));
- }
+ if (BKE_image_user_id_has_animation(id)) {
+ ID *id_cow = get_cow_id(id);
+ add_operation_node(id,
+ NodeType::ANIMATION,
+ OperationCode::IMAGE_ANIMATION,
+ function_bind(BKE_image_user_id_eval_animation, _1, id_cow));
+ }
}
void DepsgraphNodeBuilder::build_action(bAction *action)
{
- if (built_map_.checkIsBuiltAndTag(action)) {
- return;
- }
- add_operation_node(
- &action->id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
+ if (built_map_.checkIsBuiltAndTag(action)) {
+ return;
+ }
+ add_operation_node(&action->id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
}
/**
@@ -927,754 +873,675 @@ void DepsgraphNodeBuilder::build_action(bAction *action)
*/
void DepsgraphNodeBuilder::build_driver(ID *id, FCurve *fcurve, int driver_index)
{
- /* Create data node for this driver */
- ID *id_cow = get_cow_id(id);
- ChannelDriver *driver_orig = fcurve->driver;
-
- /* TODO(sergey): ideally we could pass the COW of fcu, but since it
- * has not yet been allocated at this point we can't. As a workaround
- * the animation systems allocates an array so we can do a fast lookup
- * with the driver index. */
- ensure_operation_node(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- function_bind(BKE_animsys_eval_driver, _1, id_cow, driver_index, driver_orig),
- fcurve->rna_path ? fcurve->rna_path : "",
- fcurve->array_index);
- build_driver_variables(id, fcurve);
+ /* Create data node for this driver */
+ ID *id_cow = get_cow_id(id);
+ ChannelDriver *driver_orig = fcurve->driver;
+
+ /* TODO(sergey): ideally we could pass the COW of fcu, but since it
+ * has not yet been allocated at this point we can't. As a workaround
+ * the animation systems allocates an array so we can do a fast lookup
+ * with the driver index. */
+ ensure_operation_node(
+ id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ function_bind(BKE_animsys_eval_driver, _1, id_cow, driver_index, driver_orig),
+ fcurve->rna_path ? fcurve->rna_path : "",
+ fcurve->array_index);
+ build_driver_variables(id, fcurve);
}
-void DepsgraphNodeBuilder::build_driver_variables(ID * id, FCurve *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_BEGIN(dvar)
- {
- if (dtar->id == NULL) {
- continue;
- }
- build_id(dtar->id);
- build_driver_id_property(dtar->id, dtar->rna_path);
- /* Corresponds to dtar_id_ensure_proxy_from(). */
- if ((GS(dtar->id->name) == ID_OB) &&
- (((Object *)dtar->id)->proxy_from != NULL))
- {
- Object *proxy_from = ((Object *)dtar->id)->proxy_from;
- build_id(&proxy_from->id);
- build_driver_id_property(&proxy_from->id, dtar->rna_path);
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
+ build_driver_id_property(id, fcurve->rna_path);
+ LISTBASE_FOREACH (DriverVar *, dvar, &fcurve->driver->variables) {
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ if (dtar->id == NULL) {
+ continue;
+ }
+ build_id(dtar->id);
+ build_driver_id_property(dtar->id, dtar->rna_path);
+ /* Corresponds to dtar_id_ensure_proxy_from(). */
+ if ((GS(dtar->id->name) == ID_OB) && (((Object *)dtar->id)->proxy_from != NULL)) {
+ Object *proxy_from = ((Object *)dtar->id)->proxy_from;
+ build_id(&proxy_from->id);
+ build_driver_id_property(&proxy_from->id, dtar->rna_path);
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
}
-void DepsgraphNodeBuilder::build_driver_id_property(ID *id,
- const char *rna_path)
+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,
- NodeType::PARAMETERS,
- OperationCode::ID_PROPERTY,
- NULL,
- prop_identifier);
+ 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, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, NULL, prop_identifier);
}
void DepsgraphNodeBuilder::build_parameters(ID *id)
{
- (void) add_id_node(id);
- OperationNode *op_node;
- /* Explicit entry. */
- op_node = add_operation_node(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
- op_node->set_as_entry();
- /* Generic evaluation node. */
- add_operation_node(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
- /* Explicit exit operation. */
- op_node = add_operation_node(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
- op_node->set_as_exit();
+ (void)add_id_node(id);
+ OperationNode *op_node;
+ /* Explicit entry. */
+ op_node = add_operation_node(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
+ op_node->set_as_entry();
+ /* Generic evaluation node. */
+ add_operation_node(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ /* Explicit exit operation. */
+ op_node = add_operation_node(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ op_node->set_as_exit();
}
/* Recursively build graph for world */
void DepsgraphNodeBuilder::build_world(World *world)
{
- if (built_map_.checkIsBuiltAndTag(world)) {
- return;
- }
- /* World itself. */
- add_id_node(&world->id);
- World *world_cow = get_cow_datablock(world);
- /* Shading update. */
- add_operation_node(&world->id,
- NodeType::SHADING,
- OperationCode::WORLD_UPDATE,
- function_bind(BKE_world_eval, _1, world_cow));
- /* Animation. */
- build_animdata(&world->id);
- build_parameters(&world->id);
- /* World's nodetree. */
- build_nodetree(world->nodetree);
+ if (built_map_.checkIsBuiltAndTag(world)) {
+ return;
+ }
+ /* World itself. */
+ add_id_node(&world->id);
+ World *world_cow = get_cow_datablock(world);
+ /* Shading update. */
+ add_operation_node(&world->id,
+ NodeType::SHADING,
+ OperationCode::WORLD_UPDATE,
+ function_bind(BKE_world_eval, _1, world_cow));
+ /* Animation. */
+ build_animdata(&world->id);
+ build_parameters(&world->id);
+ /* World's nodetree. */
+ build_nodetree(world->nodetree);
}
/* Rigidbody Simulation - Scene Level */
void DepsgraphNodeBuilder::build_rigidbody(Scene *scene)
{
- RigidBodyWorld *rbw = scene->rigidbody_world;
- Scene *scene_cow = get_cow_datablock(scene);
-
- /**
- * Rigidbody Simulation Nodes
- * ==========================
- *
- * There are 3 nodes related to Rigidbody Simulation:
- * 1) "Initialize/Rebuild World" - this is called sparingly, only when the
- * simulation needs to be rebuilt (mainly after file reload, or moving
- * back to start frame)
- * 2) "Do Simulation" - perform a simulation step - interleaved between the
- * evaluation steps for clusters of objects (i.e. between those affected
- * and/or not affected by the sim for instance).
- *
- * 3) "Pull Results" - grab the specific transforms applied for a specific
- * object - performed as part of object's transform-stack building. */
-
- /* Create nodes --------------------------------------------------------- */
-
- /* XXX: is this the right component, or do we want to use another one
- * instead? */
-
- /* Init/rebuild operation. */
- add_operation_node(&scene->id, NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_REBUILD,
- function_bind(BKE_rigidbody_rebuild_sim, _1, scene_cow));
- /* Do-sim operation. */
- OperationNode *sim_node = add_operation_node(
- &scene->id, NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_SIM,
- function_bind(BKE_rigidbody_eval_simulation, _1, scene_cow));
- sim_node->set_as_entry();
- sim_node->set_as_exit();
- sim_node->owner->entry_operation = sim_node;
- /* Objects - simulation participants. */
- if (rbw->group != NULL) {
- build_collection(NULL, rbw->group);
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
- {
- if (object->type != OB_MESH) {
- continue;
- }
- /* Create operation for flushing results. */
- /* Object's transform component - where the rigidbody operation
- * lives. */
- add_operation_node(&object->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY,
- function_bind(
- BKE_rigidbody_object_sync_transforms,
- _1,
- scene_cow,
- get_cow_datablock(object)));
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- /* Constraints. */
- if (rbw->constraints != NULL) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
- {
- RigidBodyCon *rbc = object->rigidbody_constraint;
- if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
- /* When either ob1 or ob2 is NULL, the constraint doesn't work. */
- continue;
- }
- /* Make sure indirectly linked objects are fully built. */
- build_object(-1, object, DEG_ID_LINKED_INDIRECTLY, false);
- build_object(-1, rbc->ob1, DEG_ID_LINKED_INDIRECTLY, false);
- build_object(-1, rbc->ob2, DEG_ID_LINKED_INDIRECTLY, false);
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ Scene *scene_cow = get_cow_datablock(scene);
+
+ /**
+ * Rigidbody Simulation Nodes
+ * ==========================
+ *
+ * There are 3 nodes related to Rigidbody Simulation:
+ * 1) "Initialize/Rebuild World" - this is called sparingly, only when the
+ * simulation needs to be rebuilt (mainly after file reload, or moving
+ * back to start frame)
+ * 2) "Do Simulation" - perform a simulation step - interleaved between the
+ * evaluation steps for clusters of objects (i.e. between those affected
+ * and/or not affected by the sim for instance).
+ *
+ * 3) "Pull Results" - grab the specific transforms applied for a specific
+ * object - performed as part of object's transform-stack building. */
+
+ /* Create nodes --------------------------------------------------------- */
+
+ /* XXX: is this the right component, or do we want to use another one
+ * instead? */
+
+ /* Init/rebuild operation. */
+ add_operation_node(&scene->id,
+ NodeType::TRANSFORM,
+ OperationCode::RIGIDBODY_REBUILD,
+ function_bind(BKE_rigidbody_rebuild_sim, _1, scene_cow));
+ /* Do-sim operation. */
+ OperationNode *sim_node = add_operation_node(
+ &scene->id,
+ NodeType::TRANSFORM,
+ OperationCode::RIGIDBODY_SIM,
+ function_bind(BKE_rigidbody_eval_simulation, _1, scene_cow));
+ sim_node->set_as_entry();
+ sim_node->set_as_exit();
+ sim_node->owner->entry_operation = sim_node;
+ /* Objects - simulation participants. */
+ if (rbw->group != NULL) {
+ build_collection(NULL, rbw->group);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
+ if (object->type != OB_MESH) {
+ continue;
+ }
+ /* Create operation for flushing results. */
+ /* Object's transform component - where the rigidbody operation
+ * lives. */
+ add_operation_node(
+ &object->id,
+ NodeType::TRANSFORM,
+ OperationCode::RIGIDBODY_TRANSFORM_COPY,
+ function_bind(
+ BKE_rigidbody_object_sync_transforms, _1, scene_cow, get_cow_datablock(object)));
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ /* Constraints. */
+ if (rbw->constraints != NULL) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->constraints, object) {
+ RigidBodyCon *rbc = object->rigidbody_constraint;
+ if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
+ /* When either ob1 or ob2 is NULL, the constraint doesn't work. */
+ continue;
+ }
+ /* Make sure indirectly linked objects are fully built. */
+ build_object(-1, object, DEG_ID_LINKED_INDIRECTLY, false);
+ build_object(-1, rbc->ob1, DEG_ID_LINKED_INDIRECTLY, false);
+ build_object(-1, rbc->ob2, DEG_ID_LINKED_INDIRECTLY, false);
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
}
-void DepsgraphNodeBuilder::build_particle_systems(Object *object,
- bool is_object_visible)
+void DepsgraphNodeBuilder::build_particle_systems(Object *object, bool is_object_visible)
{
- /**
- * Particle Systems Nodes
- * ======================
- *
- * There are two types of nodes associated with representing
- * particle systems:
- * 1) Component (EVAL_PARTICLES) - This is the particle-system
- * evaluation context for an object. It acts as the container
- * for all the nodes associated with a particular set of particle
- * systems.
- * 2) Particle System Eval Operation - This operation node acts as a
- * blackbox evaluation step for one particle system referenced by
- * the particle systems stack. All dependencies link to this operation. */
- /* Component for all particle systems. */
- ComponentNode *psys_comp =
- add_component_node(&object->id, NodeType::PARTICLE_SYSTEM);
-
- Object *ob_cow = get_cow_datablock(object);
- OperationNode *op_node;
- op_node = add_operation_node(psys_comp,
- OperationCode::PARTICLE_SYSTEM_INIT,
- function_bind(BKE_particle_system_eval_init,
- _1,
- ob_cow));
- op_node->set_as_entry();
- /* 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);
- /* Particle system evaluation. */
- add_operation_node(psys_comp,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- NULL,
- psys->name);
- /* Keyed particle targets. */
- if (part->phystype == PART_PHYS_KEYED) {
- LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
- if (particle_target->ob == NULL ||
- particle_target->ob == object)
- {
- continue;
- }
- build_object(-1,
- particle_target->ob,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- }
- /* Visualization of particle system. */
- switch (part->ren_as) {
- case PART_DRAW_OB:
- if (part->instance_object != NULL) {
- build_object(-1,
- part->instance_object,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- break;
- case PART_DRAW_GR:
- if (part->instance_collection != NULL) {
- build_collection(NULL, part->instance_collection);
- }
- break;
- }
- }
- op_node = add_operation_node(
- psys_comp, OperationCode::PARTICLE_SYSTEM_DONE);
- op_node->set_as_exit();
+ /**
+ * Particle Systems Nodes
+ * ======================
+ *
+ * There are two types of nodes associated with representing
+ * particle systems:
+ * 1) Component (EVAL_PARTICLES) - This is the particle-system
+ * evaluation context for an object. It acts as the container
+ * for all the nodes associated with a particular set of particle
+ * systems.
+ * 2) Particle System Eval Operation - This operation node acts as a
+ * blackbox evaluation step for one particle system referenced by
+ * the particle systems stack. All dependencies link to this operation. */
+ /* Component for all particle systems. */
+ ComponentNode *psys_comp = add_component_node(&object->id, NodeType::PARTICLE_SYSTEM);
+
+ Object *ob_cow = get_cow_datablock(object);
+ OperationNode *op_node;
+ op_node = add_operation_node(psys_comp,
+ OperationCode::PARTICLE_SYSTEM_INIT,
+ function_bind(BKE_particle_system_eval_init, _1, ob_cow));
+ op_node->set_as_entry();
+ /* 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);
+ /* Particle system evaluation. */
+ add_operation_node(psys_comp, OperationCode::PARTICLE_SYSTEM_EVAL, NULL, psys->name);
+ /* Keyed particle targets. */
+ if (part->phystype == PART_PHYS_KEYED) {
+ LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
+ if (particle_target->ob == NULL || particle_target->ob == object) {
+ continue;
+ }
+ build_object(-1, particle_target->ob, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ }
+ /* Visualization of particle system. */
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->instance_object != NULL) {
+ build_object(-1, part->instance_object, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->instance_collection != NULL) {
+ build_collection(NULL, part->instance_collection);
+ }
+ break;
+ }
+ }
+ op_node = add_operation_node(psys_comp, OperationCode::PARTICLE_SYSTEM_DONE);
+ op_node->set_as_exit();
}
-void DepsgraphNodeBuilder::build_particle_settings(
- ParticleSettings *particle_settings) {
- if (built_map_.checkIsBuiltAndTag(particle_settings)) {
- return;
- }
- /* Make sure we've got proper copied ID pointer. */
- add_id_node(&particle_settings->id);
- ParticleSettings *particle_settings_cow =
- get_cow_datablock(particle_settings);
- /* Animation data. */
- build_animdata(&particle_settings->id);
- build_parameters(&particle_settings->id);
- /* Parameters change. */
- OperationNode *op_node;
- op_node = add_operation_node(&particle_settings->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_INIT);
- op_node->set_as_entry();
- add_operation_node(&particle_settings->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_RESET,
- function_bind(BKE_particle_settings_eval_reset,
- _1,
- particle_settings_cow));
- op_node = add_operation_node(&particle_settings->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_EVAL);
- op_node->set_as_exit();
- /* Texture slots. */
- for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
- MTex *mtex = particle_settings->mtex[mtex_index];
- if (mtex == NULL || mtex->tex == NULL) {
- continue;
- }
- build_texture(mtex->tex);
- }
+void DepsgraphNodeBuilder::build_particle_settings(ParticleSettings *particle_settings)
+{
+ if (built_map_.checkIsBuiltAndTag(particle_settings)) {
+ return;
+ }
+ /* Make sure we've got proper copied ID pointer. */
+ add_id_node(&particle_settings->id);
+ ParticleSettings *particle_settings_cow = get_cow_datablock(particle_settings);
+ /* Animation data. */
+ build_animdata(&particle_settings->id);
+ build_parameters(&particle_settings->id);
+ /* Parameters change. */
+ OperationNode *op_node;
+ op_node = add_operation_node(
+ &particle_settings->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_INIT);
+ op_node->set_as_entry();
+ add_operation_node(&particle_settings->id,
+ NodeType::PARTICLE_SETTINGS,
+ OperationCode::PARTICLE_SETTINGS_RESET,
+ function_bind(BKE_particle_settings_eval_reset, _1, particle_settings_cow));
+ op_node = add_operation_node(
+ &particle_settings->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL);
+ op_node->set_as_exit();
+ /* Texture slots. */
+ for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
+ MTex *mtex = particle_settings->mtex[mtex_index];
+ if (mtex == NULL || mtex->tex == NULL) {
+ continue;
+ }
+ build_texture(mtex->tex);
+ }
}
/* Shapekeys */
void DepsgraphNodeBuilder::build_shapekeys(Key *key)
{
- if (built_map_.checkIsBuiltAndTag(key)) {
- return;
- }
- build_animdata(&key->id);
- build_parameters(&key->id);
- /* This is an exit operation for the entire key datablock, is what is used
- * as dependency for modifiers evaluation. */
- add_operation_node(
- &key->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_SHAPEKEY);
- /* Create per-key block properties, allowing tricky inter-dependnecies for
- * drivers evaluation. */
- LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
- add_operation_node(&key->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- NULL,
- key_block->name);
- }
+ if (built_map_.checkIsBuiltAndTag(key)) {
+ return;
+ }
+ build_animdata(&key->id);
+ build_parameters(&key->id);
+ /* This is an exit operation for the entire key datablock, is what is used
+ * as dependency for modifiers evaluation. */
+ add_operation_node(&key->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_SHAPEKEY);
+ /* Create per-key block properties, allowing tricky inter-dependnecies for
+ * drivers evaluation. */
+ LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
+ add_operation_node(
+ &key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, NULL, key_block->name);
+ }
}
/* ObData Geometry Evaluation */
// XXX: what happens if the datablock is shared!
-void DepsgraphNodeBuilder::build_object_data_geometry(
- Object *object,
- bool is_object_visible)
+void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_object_visible)
{
- OperationNode *op_node;
- Scene *scene_cow = get_cow_datablock(scene_);
- Object *object_cow = get_cow_datablock(object);
- /* Entry operation, takes care of initialization, and some other
- * relations which needs to be run prior actual geometry evaluation. */
- op_node = add_operation_node(
- &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
- op_node->set_as_entry();
- /* Geometry evaluation. */
- op_node = add_operation_node(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- function_bind(BKE_object_eval_uber_data,
- _1,
- scene_cow,
- object_cow));
- op_node->set_as_exit();
- /* Materials. */
- if (object->totcol != 0) {
- if (object->type == OB_MESH) {
- add_operation_node(&object->id,
- NodeType::SHADING,
- OperationCode::SHADING,
- function_bind(BKE_object_eval_update_shading,
- _1,
- object_cow));
- }
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
- }
- }
- }
- /* Point caches. */
- build_object_pointcache(object);
- /* Geometry. */
- build_object_data_geometry_datablock((ID *)object->data, is_object_visible);
+ OperationNode *op_node;
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
+ /* Entry operation, takes care of initialization, and some other
+ * relations which needs to be run prior actual geometry evaluation. */
+ op_node = add_operation_node(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ op_node->set_as_entry();
+ /* Geometry evaluation. */
+ op_node = add_operation_node(
+ &object->id,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ function_bind(BKE_object_eval_uber_data, _1, scene_cow, object_cow));
+ op_node->set_as_exit();
+ /* Materials. */
+ if (object->totcol != 0) {
+ if (object->type == OB_MESH) {
+ add_operation_node(&object->id,
+ NodeType::SHADING,
+ OperationCode::SHADING,
+ function_bind(BKE_object_eval_update_shading, _1, object_cow));
+ }
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
+ if (ma != NULL) {
+ build_material(ma);
+ }
+ }
+ }
+ /* Point caches. */
+ build_object_pointcache(object);
+ /* Geometry. */
+ build_object_data_geometry_datablock((ID *)object->data, is_object_visible);
}
-void DepsgraphNodeBuilder::build_object_data_geometry_datablock(
- ID *obdata,
- bool is_object_visible)
+void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata, bool is_object_visible)
{
- if (built_map_.checkIsBuiltAndTag(obdata)) {
- return;
- }
- OperationNode *op_node;
- /* 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);
- /* Animation. */
- build_animdata(obdata);
- /* ShapeKeys */
- Key *key = BKE_key_from_id(obdata);
- if (key) {
- build_shapekeys(key);
- }
- /* Nodes for result of obdata's evaluation, and geometry
- * evaluation on object. */
- const ID_Type id_type = GS(obdata->name);
- switch (id_type) {
- case ID_ME:
- {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- function_bind(BKE_mesh_eval_geometry,
- _1,
- (Mesh *)obdata_cow));
- op_node->set_as_entry();
- break;
- }
- case ID_MB:
- {
- op_node = add_operation_node(
- obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- op_node->set_as_entry();
- break;
- }
- case ID_CU:
- {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- function_bind(BKE_curve_eval_geometry,
- _1,
- (Curve *)obdata_cow));
- op_node->set_as_entry();
- /* Make sure objects used for bevel.taper are in the graph.
- * NOTE: This objects might be not linked to the scene. */
- Curve *cu = (Curve *)obdata;
- if (cu->bevobj != NULL) {
- build_object(-1,
- cu->bevobj,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- if (cu->taperobj != NULL) {
- build_object(-1,
- cu->taperobj,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- if (cu->textoncurve != NULL) {
- build_object(-1,
- cu->textoncurve,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- break;
- }
- case ID_LT:
- {
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- function_bind(BKE_lattice_eval_geometry,
- _1,
- (Lattice *)obdata_cow));
- op_node->set_as_entry();
- break;
- }
-
- case ID_GD:
- {
- /* GPencil evaluation operations. */
- op_node = add_operation_node(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL,
- function_bind(BKE_gpencil_eval_geometry,
- _1,
- (bGPdata *)obdata_cow));
- op_node->set_as_entry();
- break;
- }
- default:
- BLI_assert(!"Should not happen");
- break;
- }
- op_node = add_operation_node(
- obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
- op_node->set_as_exit();
- /* Parameters for driver sources. */
- build_parameters(obdata);
- /* Batch cache. */
- add_operation_node(obdata,
- NodeType::BATCH_CACHE,
- OperationCode::GEOMETRY_SELECT_UPDATE,
- function_bind(BKE_object_data_select_update,
- _1,
- obdata_cow));
+ if (built_map_.checkIsBuiltAndTag(obdata)) {
+ return;
+ }
+ OperationNode *op_node;
+ /* 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);
+ /* Animation. */
+ build_animdata(obdata);
+ /* ShapeKeys */
+ Key *key = BKE_key_from_id(obdata);
+ if (key) {
+ build_shapekeys(key);
+ }
+ /* Nodes for result of obdata's evaluation, and geometry
+ * evaluation on object. */
+ const ID_Type id_type = GS(obdata->name);
+ switch (id_type) {
+ case ID_ME: {
+ op_node = add_operation_node(obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ function_bind(BKE_mesh_eval_geometry, _1, (Mesh *)obdata_cow));
+ op_node->set_as_entry();
+ break;
+ }
+ case ID_MB: {
+ op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ op_node->set_as_entry();
+ break;
+ }
+ case ID_CU: {
+ op_node = add_operation_node(
+ obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ function_bind(BKE_curve_eval_geometry, _1, (Curve *)obdata_cow));
+ op_node->set_as_entry();
+ /* Make sure objects used for bevel.taper are in the graph.
+ * NOTE: This objects might be not linked to the scene. */
+ Curve *cu = (Curve *)obdata;
+ if (cu->bevobj != NULL) {
+ build_object(-1, cu->bevobj, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ if (cu->taperobj != NULL) {
+ build_object(-1, cu->taperobj, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ if (cu->textoncurve != NULL) {
+ build_object(-1, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ break;
+ }
+ case ID_LT: {
+ op_node = add_operation_node(
+ obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ function_bind(BKE_lattice_eval_geometry, _1, (Lattice *)obdata_cow));
+ op_node->set_as_entry();
+ break;
+ }
+
+ case ID_GD: {
+ /* GPencil evaluation operations. */
+ op_node = add_operation_node(
+ obdata,
+ NodeType::GEOMETRY,
+ OperationCode::GEOMETRY_EVAL,
+ function_bind(BKE_gpencil_eval_geometry, _1, (bGPdata *)obdata_cow));
+ op_node->set_as_entry();
+ break;
+ }
+ default:
+ BLI_assert(!"Should not happen");
+ break;
+ }
+ op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
+ op_node->set_as_exit();
+ /* Parameters for driver sources. */
+ build_parameters(obdata);
+ /* Batch cache. */
+ add_operation_node(obdata,
+ NodeType::BATCH_CACHE,
+ OperationCode::GEOMETRY_SELECT_UPDATE,
+ function_bind(BKE_object_data_select_update, _1, obdata_cow));
}
void DepsgraphNodeBuilder::build_armature(bArmature *armature)
{
- if (built_map_.checkIsBuiltAndTag(armature)) {
- return;
- }
- build_animdata(&armature->id);
- build_parameters(&armature->id);
- /* Make sure pose is up-to-date with armature updates. */
- add_operation_node(
- &armature->id, NodeType::PARAMETERS, OperationCode::ARMATURE_EVAL);
+ if (built_map_.checkIsBuiltAndTag(armature)) {
+ return;
+ }
+ build_animdata(&armature->id);
+ build_parameters(&armature->id);
+ /* Make sure pose is up-to-date with armature updates. */
+ add_operation_node(&armature->id, NodeType::PARAMETERS, OperationCode::ARMATURE_EVAL);
}
void DepsgraphNodeBuilder::build_camera(Camera *camera)
{
- if (built_map_.checkIsBuiltAndTag(camera)) {
- return;
- }
- build_animdata(&camera->id);
- build_parameters(&camera->id);
+ if (built_map_.checkIsBuiltAndTag(camera)) {
+ return;
+ }
+ build_animdata(&camera->id);
+ build_parameters(&camera->id);
}
void DepsgraphNodeBuilder::build_light(Light *lamp)
{
- if (built_map_.checkIsBuiltAndTag(lamp)) {
- return;
- }
- build_animdata(&lamp->id);
- build_parameters(&lamp->id);
- /* light's nodetree */
- build_nodetree(lamp->nodetree);
+ if (built_map_.checkIsBuiltAndTag(lamp)) {
+ return;
+ }
+ build_animdata(&lamp->id);
+ build_parameters(&lamp->id);
+ /* light's nodetree */
+ build_nodetree(lamp->nodetree);
}
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
{
- if (ntree == NULL) {
- return;
- }
- if (built_map_.checkIsBuiltAndTag(ntree)) {
- return;
- }
- /* nodetree itself */
- add_id_node(&ntree->id);
- bNodeTree *ntree_cow = get_cow_datablock(ntree);
- /* General parameters. */
- build_parameters(&ntree->id);
- /* Animation, */
- build_animdata(&ntree->id);
- /* Shading update. */
- add_operation_node(
- &ntree->id, NodeType::SHADING, OperationCode::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,
- NodeType::SHADING_PARAMETERS,
- OperationCode::MATERIAL_UPDATE,
- function_bind(BKE_nodetree_shading_params_eval,
- _1,
- ntree_cow,
- ntree));
- /* nodetree's nodes... */
- LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
- ID *id = bnode->id;
- if (id == NULL) {
- continue;
- }
- ID_Type id_type = GS(id->name);
- if (id_type == ID_MA) {
- build_material((Material *)id);
- }
- else if (id_type == ID_TE) {
- build_texture((Tex *)id);
- }
- else if (id_type == ID_IM) {
- build_image((Image *)id);
- }
- else if (id_type == ID_OB) {
- /* TODO(sergey): Use visibility of owner of the node tree. */
- build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true);
- }
- else if (id_type == ID_SCE) {
- /* Scenes are used by compositor trees, and handled by render
- * pipeline. No need to build dependencies for them here. */
- }
- else if (id_type == ID_TXT) {
- /* Ignore script nodes. */
- }
- else if (id_type == ID_MSK) {
- build_mask((Mask *)id);
- }
- else if (id_type == ID_MC) {
- build_movieclip((MovieClip *)id);
- }
- else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- bNodeTree *group_ntree = (bNodeTree *)id;
- build_nodetree(group_ntree);
- }
- else {
- BLI_assert(!"Unknown ID type used for node");
- }
- }
-
- // TODO: link from nodetree to owner_component?
+ if (ntree == NULL) {
+ return;
+ }
+ if (built_map_.checkIsBuiltAndTag(ntree)) {
+ return;
+ }
+ /* nodetree itself */
+ add_id_node(&ntree->id);
+ bNodeTree *ntree_cow = get_cow_datablock(ntree);
+ /* General parameters. */
+ build_parameters(&ntree->id);
+ /* Animation, */
+ build_animdata(&ntree->id);
+ /* Shading update. */
+ add_operation_node(&ntree->id, NodeType::SHADING, OperationCode::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,
+ NodeType::SHADING_PARAMETERS,
+ OperationCode::MATERIAL_UPDATE,
+ function_bind(BKE_nodetree_shading_params_eval, _1, ntree_cow, ntree));
+ /* nodetree's nodes... */
+ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
+ ID *id = bnode->id;
+ if (id == NULL) {
+ continue;
+ }
+ ID_Type id_type = GS(id->name);
+ if (id_type == ID_MA) {
+ build_material((Material *)id);
+ }
+ else if (id_type == ID_TE) {
+ build_texture((Tex *)id);
+ }
+ else if (id_type == ID_IM) {
+ build_image((Image *)id);
+ }
+ else if (id_type == ID_OB) {
+ /* TODO(sergey): Use visibility of owner of the node tree. */
+ build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, true);
+ }
+ else if (id_type == ID_SCE) {
+ /* Scenes are used by compositor trees, and handled by render
+ * pipeline. No need to build dependencies for them here. */
+ }
+ else if (id_type == ID_TXT) {
+ /* Ignore script nodes. */
+ }
+ else if (id_type == ID_MSK) {
+ build_mask((Mask *)id);
+ }
+ else if (id_type == ID_MC) {
+ build_movieclip((MovieClip *)id);
+ }
+ else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ bNodeTree *group_ntree = (bNodeTree *)id;
+ build_nodetree(group_ntree);
+ }
+ else {
+ BLI_assert(!"Unknown ID type used for node");
+ }
+ }
+
+ // TODO: link from nodetree to owner_component?
}
/* Recursively build graph for material */
void DepsgraphNodeBuilder::build_material(Material *material)
{
- if (built_map_.checkIsBuiltAndTag(material)) {
- return;
- }
- /* Material itself. */
- add_id_node(&material->id);
- Material *material_cow = get_cow_datablock(material);
- /* Shading update. */
- add_operation_node(&material->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE,
- function_bind(BKE_material_eval,
- _1,
- material_cow));
- /* Material animation. */
- build_animdata(&material->id);
- build_parameters(&material->id);
- /* Material's nodetree. */
- build_nodetree(material->nodetree);
+ if (built_map_.checkIsBuiltAndTag(material)) {
+ return;
+ }
+ /* Material itself. */
+ add_id_node(&material->id);
+ Material *material_cow = get_cow_datablock(material);
+ /* Shading update. */
+ add_operation_node(&material->id,
+ NodeType::SHADING,
+ OperationCode::MATERIAL_UPDATE,
+ function_bind(BKE_material_eval, _1, material_cow));
+ /* Material animation. */
+ build_animdata(&material->id);
+ build_parameters(&material->id);
+ /* Material's nodetree. */
+ build_nodetree(material->nodetree);
}
/* Recursively build graph for texture */
void DepsgraphNodeBuilder::build_texture(Tex *texture)
{
- if (built_map_.checkIsBuiltAndTag(texture)) {
- return;
- }
- /* Texture itself. */
- build_animdata(&texture->id);
- build_parameters(&texture->id);
- /* Texture's nodetree. */
- build_nodetree(texture->nodetree);
- /* Special cases for different IDs which texture uses. */
- if (texture->type == TEX_IMAGE) {
- if (texture->ima != NULL) {
- build_image(texture->ima);
- }
- }
- add_operation_node(&texture->id,
- NodeType::GENERIC_DATABLOCK,
- OperationCode::GENERIC_DATABLOCK_UPDATE);
+ if (built_map_.checkIsBuiltAndTag(texture)) {
+ return;
+ }
+ /* Texture itself. */
+ build_animdata(&texture->id);
+ build_parameters(&texture->id);
+ /* Texture's nodetree. */
+ build_nodetree(texture->nodetree);
+ /* Special cases for different IDs which texture uses. */
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ build_image(texture->ima);
+ }
+ }
+ add_operation_node(
+ &texture->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
}
-void DepsgraphNodeBuilder::build_image(Image *image) {
- if (built_map_.checkIsBuiltAndTag(image)) {
- return;
- }
- build_parameters(&image->id);
- add_operation_node(&image->id,
- NodeType::GENERIC_DATABLOCK,
- OperationCode::GENERIC_DATABLOCK_UPDATE);
+void DepsgraphNodeBuilder::build_image(Image *image)
+{
+ if (built_map_.checkIsBuiltAndTag(image)) {
+ return;
+ }
+ build_parameters(&image->id);
+ add_operation_node(
+ &image->id, NodeType::GENERIC_DATABLOCK, OperationCode::GENERIC_DATABLOCK_UPDATE);
}
void DepsgraphNodeBuilder::build_compositor(Scene *scene)
{
- /* For now, just a plain wrapper? */
- // TODO: create compositing component?
- // XXX: component type undefined!
- //graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
-
- /* for now, nodetrees are just parameters; compositing occurs in internals
- * of renderer... */
- add_component_node(&scene->id, NodeType::PARAMETERS);
- build_nodetree(scene->nodetree);
+ /* For now, just a plain wrapper? */
+ // TODO: create compositing component?
+ // XXX: component type undefined!
+ //graph->get_node(&scene->id, NULL, NodeType::COMPOSITING, NULL);
+
+ /* for now, nodetrees are just parameters; compositing occurs in internals
+ * of renderer... */
+ add_component_node(&scene->id, NodeType::PARAMETERS);
+ build_nodetree(scene->nodetree);
}
void DepsgraphNodeBuilder::build_gpencil(bGPdata *gpd)
{
- if (built_map_.checkIsBuiltAndTag(gpd)) {
- return;
- }
- ID *gpd_id = &gpd->id;
-
- /* TODO(sergey): what about multiple users of same datablock? This should
- * only get added once. */
-
- /* The main reason Grease Pencil is included here is because the animation
- * (and drivers) need to be hosted somewhere. */
- build_animdata(gpd_id);
- build_parameters(gpd_id);
+ if (built_map_.checkIsBuiltAndTag(gpd)) {
+ return;
+ }
+ ID *gpd_id = &gpd->id;
+
+ /* TODO(sergey): what about multiple users of same datablock? This should
+ * only get added once. */
+
+ /* The main reason Grease Pencil is included here is because the animation
+ * (and drivers) need to be hosted somewhere. */
+ build_animdata(gpd_id);
+ build_parameters(gpd_id);
}
void DepsgraphNodeBuilder::build_cachefile(CacheFile *cache_file)
{
- if (built_map_.checkIsBuiltAndTag(cache_file)) {
- return;
- }
- ID *cache_file_id = &cache_file->id;
- /* Animation, */
- build_animdata(cache_file_id);
- build_parameters(cache_file_id);
- /* Cache evaluation itself. */
- add_operation_node(
- cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
+ if (built_map_.checkIsBuiltAndTag(cache_file)) {
+ return;
+ }
+ ID *cache_file_id = &cache_file->id;
+ /* Animation, */
+ build_animdata(cache_file_id);
+ build_parameters(cache_file_id);
+ /* Cache evaluation itself. */
+ add_operation_node(cache_file_id, NodeType::CACHE, OperationCode::FILE_CACHE_UPDATE);
}
void DepsgraphNodeBuilder::build_mask(Mask *mask)
{
- if (built_map_.checkIsBuiltAndTag(mask)) {
- return;
- }
- ID *mask_id = &mask->id;
- Mask *mask_cow = get_cow_datablock(mask);
- /* F-Curve based animation. */
- build_animdata(mask_id);
- build_parameters(mask_id);
- /* Animation based on mask's shapes. */
- add_operation_node(mask_id,
- NodeType::ANIMATION,
- OperationCode::MASK_ANIMATION,
- function_bind(BKE_mask_eval_animation, _1, mask_cow));
- /* Final mask evaluation. */
- add_operation_node(mask_id,
- NodeType::PARAMETERS,
- OperationCode::MASK_EVAL,
- function_bind(BKE_mask_eval_update, _1, mask_cow));
+ if (built_map_.checkIsBuiltAndTag(mask)) {
+ return;
+ }
+ ID *mask_id = &mask->id;
+ Mask *mask_cow = get_cow_datablock(mask);
+ /* F-Curve based animation. */
+ build_animdata(mask_id);
+ build_parameters(mask_id);
+ /* Animation based on mask's shapes. */
+ add_operation_node(mask_id,
+ NodeType::ANIMATION,
+ OperationCode::MASK_ANIMATION,
+ function_bind(BKE_mask_eval_animation, _1, mask_cow));
+ /* Final mask evaluation. */
+ add_operation_node(mask_id,
+ NodeType::PARAMETERS,
+ OperationCode::MASK_EVAL,
+ function_bind(BKE_mask_eval_update, _1, mask_cow));
}
void DepsgraphNodeBuilder::build_movieclip(MovieClip *clip)
{
- if (built_map_.checkIsBuiltAndTag(clip)) {
- return;
- }
- ID *clip_id = &clip->id;
- MovieClip *clip_cow = (MovieClip *)ensure_cow_id(clip_id);
- /* Animation. */
- build_animdata(clip_id);
- build_parameters(clip_id);
- /* Movie clip evaluation. */
- add_operation_node(clip_id,
- NodeType::PARAMETERS,
- OperationCode::MOVIECLIP_EVAL,
- function_bind(BKE_movieclip_eval_update, _1, clip_cow));
-
- add_operation_node(clip_id,
- NodeType::BATCH_CACHE,
- OperationCode::MOVIECLIP_SELECT_UPDATE,
- function_bind(BKE_movieclip_eval_selection_update, _1, clip_cow));
+ if (built_map_.checkIsBuiltAndTag(clip)) {
+ return;
+ }
+ ID *clip_id = &clip->id;
+ MovieClip *clip_cow = (MovieClip *)ensure_cow_id(clip_id);
+ /* Animation. */
+ build_animdata(clip_id);
+ build_parameters(clip_id);
+ /* Movie clip evaluation. */
+ add_operation_node(clip_id,
+ NodeType::PARAMETERS,
+ OperationCode::MOVIECLIP_EVAL,
+ function_bind(BKE_movieclip_eval_update, _1, clip_cow));
+
+ add_operation_node(clip_id,
+ NodeType::BATCH_CACHE,
+ OperationCode::MOVIECLIP_SELECT_UPDATE,
+ function_bind(BKE_movieclip_eval_selection_update, _1, clip_cow));
}
void DepsgraphNodeBuilder::build_lightprobe(LightProbe *probe)
{
- if (built_map_.checkIsBuiltAndTag(probe)) {
- return;
- }
- /* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(
- &probe->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
- build_animdata(&probe->id);
- build_parameters(&probe->id);
+ if (built_map_.checkIsBuiltAndTag(probe)) {
+ return;
+ }
+ /* Placeholder so we can add relations and tag ID node for update. */
+ add_operation_node(&probe->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ build_animdata(&probe->id);
+ build_parameters(&probe->id);
}
void DepsgraphNodeBuilder::build_speaker(Speaker *speaker)
{
- if (built_map_.checkIsBuiltAndTag(speaker)) {
- return;
- }
- /* Placeholder so we can add relations and tag ID node for update. */
- add_operation_node(
- &speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
- build_animdata(&speaker->id);
- build_parameters(&speaker->id);
+ if (built_map_.checkIsBuiltAndTag(speaker)) {
+ return;
+ }
+ /* Placeholder so we can add relations and tag ID node for update. */
+ add_operation_node(&speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ build_animdata(&speaker->id);
+ build_parameters(&speaker->id);
}
/* **** ID traversal callbacks functions **** */
@@ -1684,24 +1551,22 @@ void DepsgraphNodeBuilder::modifier_walk(void *user_data,
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:
- /* Special case for object, so we take owner visibility into
- * account. */
- data->builder->build_object(-1,
- (Object *)id,
- DEG_ID_LINKED_INDIRECTLY,
- data->is_parent_visible);
- break;
- default:
- data->builder->build_id(id);
- break;
- }
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_OB:
+ /* Special case for object, so we take owner visibility into
+ * account. */
+ data->builder->build_object(
+ -1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, data->is_parent_visible);
+ break;
+ default:
+ data->builder->build_id(id);
+ break;
+ }
}
void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/,
@@ -1709,24 +1574,22 @@ void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/,
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:
- /* Special case for object, so we take owner visibility into
- * account. */
- data->builder->build_object(-1,
- (Object *)id,
- DEG_ID_LINKED_INDIRECTLY,
- data->is_parent_visible);
- break;
- default:
- data->builder->build_id(id);
- break;
- }
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_OB:
+ /* Special case for object, so we take owner visibility into
+ * account. */
+ data->builder->build_object(
+ -1, (Object *)id, DEG_ID_LINKED_INDIRECTLY, data->is_parent_visible);
+ break;
+ default:
+ data->builder->build_id(id);
+ 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 d5d1ac2d33a..d88f5a792e0 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -75,209 +75,196 @@ struct OperationNode;
struct TimeSourceNode;
class DepsgraphNodeBuilder : public DepsgraphBuilder {
-public:
- DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
- ~DepsgraphNodeBuilder();
+ public:
+ DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph);
+ ~DepsgraphNodeBuilder();
- /* For given original ID get ID which is created by CoW system. */
- ID *get_cow_id(const ID *id_orig) const;
- /* Similar to above, but for the cases when there is no ID node we create
- * one. */
- ID *ensure_cow_id(ID *id_orig);
+ /* For given original ID get ID which is created by CoW system. */
+ ID *get_cow_id(const ID *id_orig) const;
+ /* Similar to above, but for the cases when there is no ID node we create
+ * one. */
+ ID *ensure_cow_id(ID *id_orig);
- /* Helper wrapper function which wraps get_cow_id with a needed type cast. */
- template<typename T>
- T *get_cow_datablock(const T *orig) const {
- return (T *)get_cow_id(&orig->id);
- }
+ /* Helper wrapper function which wraps get_cow_id with a needed type cast. */
+ template<typename T> T *get_cow_datablock(const T *orig) const
+ {
+ return (T *)get_cow_id(&orig->id);
+ }
- /* For a given COW datablock get corresponding original one. */
- template<typename T>
- T *get_orig_datablock(const T *cow) const {
- return (T *)cow->id.orig_id;
- }
+ /* For a given COW datablock get corresponding original one. */
+ template<typename T> T *get_orig_datablock(const T *cow) const
+ {
+ return (T *)cow->id.orig_id;
+ }
- void begin_build();
- void end_build();
+ void begin_build();
+ void end_build();
- IDNode *add_id_node(ID *id);
- IDNode *find_id_node(ID *id);
- TimeSourceNode *add_time_source();
+ IDNode *add_id_node(ID *id);
+ IDNode *find_id_node(ID *id);
+ TimeSourceNode *add_time_source();
- ComponentNode *add_component_node(ID *id,
- NodeType comp_type,
- const char *comp_name = "");
+ ComponentNode *add_component_node(ID *id, NodeType comp_type, const char *comp_name = "");
- OperationNode *add_operation_node(ComponentNode *comp_node,
- OperationCode opcode,
- const DepsEvalOperationCb& op = NULL,
- const char *name = "",
- int name_tag = -1);
- OperationNode *add_operation_node(ID *id,
- NodeType comp_type,
- const char *comp_name,
- OperationCode opcode,
- const DepsEvalOperationCb& op = NULL,
- const char *name = "",
- int name_tag = -1);
- OperationNode *add_operation_node(ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const DepsEvalOperationCb& op = NULL,
- const char *name = "",
- int name_tag = -1);
+ OperationNode *add_operation_node(ComponentNode *comp_node,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op = NULL,
+ const char *name = "",
+ int name_tag = -1);
+ OperationNode *add_operation_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op = NULL,
+ const char *name = "",
+ int name_tag = -1);
+ OperationNode *add_operation_node(ID *id,
+ NodeType comp_type,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op = NULL,
+ const char *name = "",
+ int name_tag = -1);
- OperationNode *ensure_operation_node(ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const DepsEvalOperationCb& op = NULL,
- const char *name = "",
- int name_tag = -1);
+ OperationNode *ensure_operation_node(ID *id,
+ NodeType comp_type,
+ OperationCode opcode,
+ const DepsEvalOperationCb &op = NULL,
+ const char *name = "",
+ int name_tag = -1);
- bool has_operation_node(ID *id,
- NodeType comp_type,
- const char *comp_name,
- OperationCode opcode,
- const char *name = "",
- int name_tag = -1);
+ bool has_operation_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name,
+ OperationCode opcode,
+ const char *name = "",
+ int name_tag = -1);
- OperationNode *find_operation_node(ID *id,
- NodeType comp_type,
- const char *comp_name,
- OperationCode opcode,
- const char *name = "",
- int name_tag = -1);
+ OperationNode *find_operation_node(ID *id,
+ NodeType comp_type,
+ const char *comp_name,
+ OperationCode opcode,
+ const char *name = "",
+ int name_tag = -1);
- OperationNode *find_operation_node(ID *id,
- NodeType comp_type,
- OperationCode opcode,
- const char *name = "",
- int name_tag = -1);
+ OperationNode *find_operation_node(
+ ID *id, NodeType comp_type, OperationCode opcode, const char *name = "", int name_tag = -1);
- void build_id(ID *id);
- void build_layer_collections(ListBase *lb);
- void build_view_layer(Scene *scene,
- ViewLayer *view_layer,
- eDepsNode_LinkedState_Type linked_state);
- void build_collection(LayerCollection *from_layer_collection,
- Collection *collection);
- void build_object(int base_index,
- Object *object,
- eDepsNode_LinkedState_Type linked_state,
- bool is_visible);
- void build_object_flags(int base_index,
- Object *object,
- eDepsNode_LinkedState_Type linked_state);
- void build_object_data(Object *object, bool is_object_visible);
- void build_object_data_camera(Object *object);
- void build_object_data_geometry(Object *object, bool is_object_visible);
- void build_object_data_geometry_datablock(ID *obdata,
- bool is_object_visible);
- void build_object_data_light(Object *object);
- void build_object_data_lightprobe(Object *object);
- void build_object_data_speaker(Object *object);
- void build_object_transform(Object *object);
- void build_object_constraints(Object *object);
- void build_object_pointcache(Object *object);
- void build_pose_constraints(Object *object,
- bPoseChannel *pchan,
- int pchan_index,
- bool is_object_visible);
- void build_rigidbody(Scene *scene);
- void build_particle_systems(Object *object, bool is_object_visible);
- void build_particle_settings(ParticleSettings *part);
- void build_animdata(ID *id);
- void build_animdata_nlastrip_targets(ListBase *strips);
- void build_animation_images(ID *id);
- void build_action(bAction *action);
- void build_driver(ID *id, FCurve *fcurve, int driver_index);
- void build_driver_variables(ID *id, FCurve *fcurve);
- void build_driver_id_property(ID *id, const char *rna_path);
- void build_parameters(ID *id);
- void build_ik_pose(Object *object,
- bPoseChannel *pchan,
- bConstraint *con);
- void build_splineik_pose(Object *object,
- bPoseChannel *pchan,
- bConstraint *con);
- void build_rig(Object *object, bool is_object_visible);
- void build_proxy_rig(Object *object);
- void build_armature(bArmature *armature);
- void build_shapekeys(Key *key);
- void build_camera(Camera *camera);
- void build_light(Light *lamp);
- void build_nodetree(bNodeTree *ntree);
- void build_material(Material *ma);
- void build_texture(Tex *tex);
- void build_image(Image *image);
- void build_world(World *world);
- void build_compositor(Scene *scene);
- void build_gpencil(bGPdata *gpd);
- void build_cachefile(CacheFile *cache_file);
- void build_mask(Mask *mask);
- void build_movieclip(MovieClip *clip);
- void build_lightprobe(LightProbe *probe);
- void build_speaker(Speaker *speaker);
+ void build_id(ID *id);
+ void build_layer_collections(ListBase *lb);
+ void build_view_layer(Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state);
+ void build_collection(LayerCollection *from_layer_collection, Collection *collection);
+ void build_object(int base_index,
+ Object *object,
+ eDepsNode_LinkedState_Type linked_state,
+ bool is_visible);
+ void build_object_flags(int base_index, Object *object, eDepsNode_LinkedState_Type linked_state);
+ void build_object_data(Object *object, bool is_object_visible);
+ void build_object_data_camera(Object *object);
+ void build_object_data_geometry(Object *object, bool is_object_visible);
+ void build_object_data_geometry_datablock(ID *obdata, bool is_object_visible);
+ void build_object_data_light(Object *object);
+ void build_object_data_lightprobe(Object *object);
+ void build_object_data_speaker(Object *object);
+ void build_object_transform(Object *object);
+ void build_object_constraints(Object *object);
+ void build_object_pointcache(Object *object);
+ void build_pose_constraints(Object *object,
+ bPoseChannel *pchan,
+ int pchan_index,
+ bool is_object_visible);
+ void build_rigidbody(Scene *scene);
+ void build_particle_systems(Object *object, bool is_object_visible);
+ void build_particle_settings(ParticleSettings *part);
+ void build_animdata(ID *id);
+ void build_animdata_nlastrip_targets(ListBase *strips);
+ void build_animation_images(ID *id);
+ void build_action(bAction *action);
+ void build_driver(ID *id, FCurve *fcurve, int driver_index);
+ void build_driver_variables(ID *id, FCurve *fcurve);
+ void build_driver_id_property(ID *id, const char *rna_path);
+ void build_parameters(ID *id);
+ void build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con);
+ void build_splineik_pose(Object *object, bPoseChannel *pchan, bConstraint *con);
+ void build_rig(Object *object, bool is_object_visible);
+ void build_proxy_rig(Object *object);
+ void build_armature(bArmature *armature);
+ void build_shapekeys(Key *key);
+ void build_camera(Camera *camera);
+ void build_light(Light *lamp);
+ void build_nodetree(bNodeTree *ntree);
+ void build_material(Material *ma);
+ void build_texture(Tex *tex);
+ void build_image(Image *image);
+ void build_world(World *world);
+ void build_compositor(Scene *scene);
+ void build_gpencil(bGPdata *gpd);
+ void build_cachefile(CacheFile *cache_file);
+ void build_mask(Mask *mask);
+ void build_movieclip(MovieClip *clip);
+ void build_lightprobe(LightProbe *probe);
+ void build_speaker(Speaker *speaker);
- /* Per-ID information about what was already in the dependency graph.
- * Allows to re-use certain values, to speed up following evaluation. */
- struct IDInfo {
- /* Copy-on-written pointer of the corresponding ID. */
- ID *id_cow;
- /* Mask of visible components from previous state of the
- * dependency graph. */
- IDComponentsMask previously_visible_components_mask;
- /* Special evaluation flag mask from the previous depsgraph. */
- uint32_t previous_eval_flags;
- /* Mesh CustomData mask from the previous depsgraph. */
- DEGCustomDataMeshMasks previous_customdata_masks;
- };
+ /* Per-ID information about what was already in the dependency graph.
+ * Allows to re-use certain values, to speed up following evaluation. */
+ struct IDInfo {
+ /* Copy-on-written pointer of the corresponding ID. */
+ ID *id_cow;
+ /* Mask of visible components from previous state of the
+ * dependency graph. */
+ IDComponentsMask previously_visible_components_mask;
+ /* Special evaluation flag mask from the previous depsgraph. */
+ uint32_t previous_eval_flags;
+ /* Mesh CustomData mask from the previous depsgraph. */
+ DEGCustomDataMeshMasks previous_customdata_masks;
+ };
-protected:
- /* Allows to identify an operation which was tagged for update at the time
- * relations are being updated. We can not reuse operation node pointer
- * since it will change during dependency graph construction. */
- struct SavedEntryTag {
- ID *id_orig;
- NodeType component_type;
- OperationCode opcode;
- string name;
- int name_tag;
- };
- vector<SavedEntryTag> saved_entry_tags_;
+ protected:
+ /* Allows to identify an operation which was tagged for update at the time
+ * relations are being updated. We can not reuse operation node pointer
+ * since it will change during dependency graph construction. */
+ struct SavedEntryTag {
+ ID *id_orig;
+ NodeType component_type;
+ OperationCode opcode;
+ string name;
+ int name_tag;
+ };
+ vector<SavedEntryTag> saved_entry_tags_;
- struct BuilderWalkUserData {
- DepsgraphNodeBuilder *builder;
- /* Denotes whether object the walk is invoked from is visible. */
- bool is_parent_visible;
- };
- 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);
+ struct BuilderWalkUserData {
+ DepsgraphNodeBuilder *builder;
+ /* Denotes whether object the walk is invoked from is visible. */
+ bool is_parent_visible;
+ };
+ 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 demotes currently built entities. */
- Scene *scene_;
- ViewLayer *view_layer_;
- int view_layer_index_;
- /* NOTE: Collection are possibly built recursively, so be careful when
- * setting the current state. */
- Collection *collection_;
- /* Accumulated flag over the hierarchy opf currently building collections.
- * Denotes whether all the hierarchy from parent of collection_ to the
- * very root is visible (aka not restricted.). */
- bool is_parent_collection_visible_;
+ /* State which demotes currently built entities. */
+ Scene *scene_;
+ ViewLayer *view_layer_;
+ int view_layer_index_;
+ /* NOTE: Collection are possibly built recursively, so be careful when
+ * setting the current state. */
+ Collection *collection_;
+ /* Accumulated flag over the hierarchy opf currently building collections.
+ * Denotes whether all the hierarchy from parent of collection_ to the
+ * very root is visible (aka not restricted.). */
+ bool is_parent_collection_visible_;
- /* Indexed by original ID, values are IDInfo. */
- GHash *id_info_hash_;
+ /* Indexed by original ID, values are IDInfo. */
+ GHash *id_info_hash_;
- /* Set of IDs which were already build. Makes it easier to keep track of
- * what was already built and what was not. */
- BuilderMap built_map_;
+ /* Set of IDs which were already build. Makes it easier to keep track of
+ * what was already built and what was not. */
+ BuilderMap built_map_;
};
} // 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 132600f2fdd..6f141bd7222 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc
@@ -58,60 +58,56 @@ extern "C" {
namespace DEG {
-void DepsgraphNodeBuilder::build_pose_constraints(
- Object *object,
- bPoseChannel *pchan,
- int pchan_index,
- bool is_object_visible)
+void DepsgraphNodeBuilder::build_pose_constraints(Object *object,
+ bPoseChannel *pchan,
+ int pchan_index,
+ bool is_object_visible)
{
- /* Pull indirect dependencies via constraints. */
- BuilderWalkUserData data;
- data.builder = this;
- data.is_parent_visible = is_object_visible;
- BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data);
- /* Create node for constraint stack. */
- add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_CONSTRAINTS,
- function_bind(BKE_pose_constraints_evaluate,
- _1,
- get_cow_datablock(scene_),
- get_cow_datablock(object),
- pchan_index));
+ /* Pull indirect dependencies via constraints. */
+ BuilderWalkUserData data;
+ data.builder = this;
+ data.is_parent_visible = is_object_visible;
+ BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data);
+ /* Create node for constraint stack. */
+ add_operation_node(&object->id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::BONE_CONSTRAINTS,
+ function_bind(BKE_pose_constraints_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ pchan_index));
}
/* IK Solver Eval Steps */
-void DepsgraphNodeBuilder::build_ik_pose(Object *object,
- bPoseChannel *pchan,
- bConstraint *con)
+void DepsgraphNodeBuilder::build_ik_pose(Object *object, bPoseChannel *pchan, bConstraint *con)
{
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
-
- /* Find the chain's root. */
- bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- if (rootchan == NULL) {
- return;
- }
-
- if (has_operation_node(&object->id, NodeType::EVAL_POSE, rootchan->name,
- OperationCode::POSE_IK_SOLVER))
- {
- 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,
- NodeType::EVAL_POSE,
- rootchan->name,
- OperationCode::POSE_IK_SOLVER,
- function_bind(BKE_pose_iktree_evaluate,
- _1,
- get_cow_datablock(scene_),
- get_cow_datablock(object),
- rootchan_index));
+ bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+
+ /* Find the chain's root. */
+ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+ if (rootchan == NULL) {
+ return;
+ }
+
+ if (has_operation_node(
+ &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_IK_SOLVER)) {
+ 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,
+ NodeType::EVAL_POSE,
+ rootchan->name,
+ OperationCode::POSE_IK_SOLVER,
+ function_bind(BKE_pose_iktree_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ rootchan_index));
}
/* Spline IK Eval Steps */
@@ -119,277 +115,229 @@ void DepsgraphNodeBuilder::build_splineik_pose(Object *object,
bPoseChannel *pchan,
bConstraint *con)
{
- bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
-
- /* Find the chain's root. */
- bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
-
- /* Operation node for evaluating/running Spline IK Solver.
- * 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,
- NodeType::EVAL_POSE,
- rootchan->name,
- OperationCode::POSE_SPLINE_IK_SOLVER,
- function_bind(BKE_pose_splineik_evaluate,
- _1,
- get_cow_datablock(scene_),
- get_cow_datablock(object),
- rootchan_index));
+ bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+
+ /* Find the chain's root. */
+ bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+
+ /* Operation node for evaluating/running Spline IK Solver.
+ * 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,
+ NodeType::EVAL_POSE,
+ rootchan->name,
+ OperationCode::POSE_SPLINE_IK_SOLVER,
+ function_bind(BKE_pose_splineik_evaluate,
+ _1,
+ get_cow_datablock(scene_),
+ get_cow_datablock(object),
+ rootchan_index));
}
/* Pose/Armature Bones Graph */
void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible)
{
- bArmature *armature = (bArmature *)object->data;
- Scene *scene_cow = get_cow_datablock(scene_);
- Object *object_cow = get_cow_datablock(object);
- OperationNode *op_node;
- /* Animation and/or drivers linking posebones to base-armature used to
- * define them.
- *
- * NOTE: AnimData here is really used to control animated deform properties,
- * which ideally should be able to be unique across different
- * instances. Eventually, we need some type of proxy/isolation
- * mechanism in-between here to ensure that we can use same rig
- * multiple times in same scene. */
- /* Armature. */
- build_armature(armature);
- /* Rebuild pose if not up to date. */
- if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
- /* By definition, no need to tag depsgraph as dirty from here, so we can pass NULL bmain. */
- BKE_pose_rebuild(NULL, object, armature, true);
- }
- /* Speed optimization for animation lookups. */
- 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);
- }
- }
- /**
- * Pose Rig Graph
- * ==============
- *
- * Pose Component:
- * - Mainly used for referencing Bone components.
- * - This is where the evaluation operations for init/exec/cleanup
- * (ik) solvers live, and are later hooked up (so that they can be
- * interleaved during runtime) with bone-operations they depend on/affect.
- * - init_pose_eval() and cleanup_pose_eval() are absolute first and last
- * steps of pose eval process. ALL bone operations must be performed
- * between these two...
- *
- * Bone Component:
- * - Used for representing each bone within the rig
- * - Acts to encapsulate the evaluation operations (base matrix + parenting,
- * and constraint stack) so that they can be easily found.
- * - Everything else which depends on bone-results hook up to the component
- * only so that we can redirect those to point at either the
- * post-IK/post-constraint/post-matrix steps, as needed. */
- /* Pose eval context. */
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT,
- function_bind(BKE_pose_eval_init,
- _1,
- scene_cow,
- object_cow));
- op_node->set_as_entry();
-
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT_IK,
- function_bind(BKE_pose_eval_init_ik,
- _1,
- scene_cow,
- object_cow));
-
- add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_CLEANUP,
- function_bind(BKE_pose_eval_cleanup,
- _1,
- scene_cow,
- object_cow));
-
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_DONE,
- function_bind(BKE_pose_eval_done,
- _1,
- object_cow));
- op_node->set_as_exit();
- /* Bones. */
- int pchan_index = 0;
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- /* Node for bone evaluation. */
- op_node = add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- op_node->set_as_entry();
-
- add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_POSE_PARENT,
- function_bind(BKE_pose_eval_bone, _1,
- scene_cow,
- object_cow,
- pchan_index));
-
- /* NOTE: Dedicated noop for easier relationship construction. */
- add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_READY);
-
- op_node = add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_DONE,
- function_bind(BKE_pose_bone_done,
- _1,
- object_cow,
- pchan_index));
-
- /* B-Bone shape computation - the real last step if present. */
- if (pchan->bone != NULL && pchan->bone->segments > 1) {
- op_node = add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_SEGMENTS,
- function_bind(BKE_pose_eval_bbone_segments, _1,
- object_cow,
- pchan_index));
- }
-
- op_node->set_as_exit();
-
- /* Custom properties. */
- if (pchan->prop != NULL) {
- add_operation_node(&object->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- NULL,
- pchan->name);
- }
- /* Build constraints. */
- if (pchan->constraints.first != NULL) {
- build_pose_constraints(
- object, pchan, pchan_index, is_object_visible);
- }
- /**
- * IK Solvers.
- *
- * - These require separate processing steps are pose-level
- * to be executed between chains of bones (i.e. once the
- * base transforms of a bunch of bones is done)
- *
- * Unsolved Issues:
- * - Care is needed to ensure that multi-headed trees work out the same
- * as in ik-tree building
- * - Animated chain-lengths are a problem. */
- LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
- switch (con->type) {
- case CONSTRAINT_TYPE_KINEMATIC:
- build_ik_pose(object, pchan, con);
- break;
-
- case CONSTRAINT_TYPE_SPLINEIK:
- build_splineik_pose(object, pchan, con);
- break;
-
- default:
- break;
- }
- }
- /* Custom shape. */
- if (pchan->custom != NULL) {
- /* TODO(sergey): Use own visibility. */
- build_object(
- -1,
- pchan->custom,
- DEG_ID_LINKED_INDIRECTLY,
- is_object_visible);
- }
- pchan_index++;
- }
+ bArmature *armature = (bArmature *)object->data;
+ Scene *scene_cow = get_cow_datablock(scene_);
+ Object *object_cow = get_cow_datablock(object);
+ OperationNode *op_node;
+ /* Animation and/or drivers linking posebones to base-armature used to
+ * define them.
+ *
+ * NOTE: AnimData here is really used to control animated deform properties,
+ * which ideally should be able to be unique across different
+ * instances. Eventually, we need some type of proxy/isolation
+ * mechanism in-between here to ensure that we can use same rig
+ * multiple times in same scene. */
+ /* Armature. */
+ build_armature(armature);
+ /* Rebuild pose if not up to date. */
+ if (object->pose == NULL || (object->pose->flag & POSE_RECALC)) {
+ /* By definition, no need to tag depsgraph as dirty from here, so we can pass NULL bmain. */
+ BKE_pose_rebuild(NULL, object, armature, true);
+ }
+ /* Speed optimization for animation lookups. */
+ 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);
+ }
+ }
+ /**
+ * Pose Rig Graph
+ * ==============
+ *
+ * Pose Component:
+ * - Mainly used for referencing Bone components.
+ * - This is where the evaluation operations for init/exec/cleanup
+ * (ik) solvers live, and are later hooked up (so that they can be
+ * interleaved during runtime) with bone-operations they depend on/affect.
+ * - init_pose_eval() and cleanup_pose_eval() are absolute first and last
+ * steps of pose eval process. ALL bone operations must be performed
+ * between these two...
+ *
+ * Bone Component:
+ * - Used for representing each bone within the rig
+ * - Acts to encapsulate the evaluation operations (base matrix + parenting,
+ * and constraint stack) so that they can be easily found.
+ * - Everything else which depends on bone-results hook up to the component
+ * only so that we can redirect those to point at either the
+ * post-IK/post-constraint/post-matrix steps, as needed. */
+ /* Pose eval context. */
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_INIT,
+ function_bind(BKE_pose_eval_init, _1, scene_cow, object_cow));
+ op_node->set_as_entry();
+
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_INIT_IK,
+ function_bind(BKE_pose_eval_init_ik, _1, scene_cow, object_cow));
+
+ add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_CLEANUP,
+ function_bind(BKE_pose_eval_cleanup, _1, scene_cow, object_cow));
+
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_DONE,
+ function_bind(BKE_pose_eval_done, _1, object_cow));
+ op_node->set_as_exit();
+ /* Bones. */
+ int pchan_index = 0;
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ /* Node for bone evaluation. */
+ op_node = add_operation_node(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ op_node->set_as_entry();
+
+ add_operation_node(&object->id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::BONE_POSE_PARENT,
+ function_bind(BKE_pose_eval_bone, _1, scene_cow, object_cow, pchan_index));
+
+ /* NOTE: Dedicated noop for easier relationship construction. */
+ add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
+
+ op_node = add_operation_node(&object->id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::BONE_DONE,
+ function_bind(BKE_pose_bone_done, _1, object_cow, pchan_index));
+
+ /* B-Bone shape computation - the real last step if present. */
+ if (pchan->bone != NULL && pchan->bone->segments > 1) {
+ op_node = add_operation_node(
+ &object->id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::BONE_SEGMENTS,
+ function_bind(BKE_pose_eval_bbone_segments, _1, object_cow, pchan_index));
+ }
+
+ op_node->set_as_exit();
+
+ /* Custom properties. */
+ if (pchan->prop != NULL) {
+ add_operation_node(
+ &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, NULL, pchan->name);
+ }
+ /* Build constraints. */
+ if (pchan->constraints.first != NULL) {
+ build_pose_constraints(object, pchan, pchan_index, is_object_visible);
+ }
+ /**
+ * IK Solvers.
+ *
+ * - These require separate processing steps are pose-level
+ * to be executed between chains of bones (i.e. once the
+ * base transforms of a bunch of bones is done)
+ *
+ * Unsolved Issues:
+ * - Care is needed to ensure that multi-headed trees work out the same
+ * as in ik-tree building
+ * - Animated chain-lengths are a problem. */
+ LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
+ switch (con->type) {
+ case CONSTRAINT_TYPE_KINEMATIC:
+ build_ik_pose(object, pchan, con);
+ break;
+
+ case CONSTRAINT_TYPE_SPLINEIK:
+ build_splineik_pose(object, pchan, con);
+ break;
+
+ default:
+ break;
+ }
+ }
+ /* Custom shape. */
+ if (pchan->custom != NULL) {
+ /* TODO(sergey): Use own visibility. */
+ build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY, is_object_visible);
+ }
+ pchan_index++;
+ }
}
void DepsgraphNodeBuilder::build_proxy_rig(Object *object)
{
- bArmature *armature = (bArmature *)object->data;
- OperationNode *op_node;
- Object *object_cow = get_cow_datablock(object);
- /* Sanity check. */
- BLI_assert(object->pose != NULL);
- /* Armature. */
- build_armature(armature);
- /* speed optimization for animation lookups */
- BKE_pose_channels_hash_make(object->pose);
- if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
- BKE_pose_update_constraint_flags(object->pose);
- }
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT,
- function_bind(BKE_pose_eval_proxy_init,
- _1,
- object_cow));
- op_node->set_as_entry();
-
- int pchan_index = 0;
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- op_node = add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- op_node->set_as_entry();
- /* Bone is ready for solvers. */
- add_operation_node(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_READY);
- /* Bone is fully evaluated. */
- op_node = add_operation_node(
- &object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_DONE,
- function_bind(BKE_pose_eval_proxy_copy_bone,
- _1,
- object_cow,
- pchan_index));
- op_node->set_as_exit();
-
- /* Custom properties. */
- if (pchan->prop != NULL) {
- add_operation_node(&object->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- NULL,
- pchan->name);
- }
-
- pchan_index++;
- }
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_CLEANUP,
- function_bind(BKE_pose_eval_proxy_cleanup,
- _1,
- object_cow));
- op_node = add_operation_node(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_DONE,
- function_bind(BKE_pose_eval_proxy_done,
- _1,
- object_cow));
- op_node->set_as_exit();
+ bArmature *armature = (bArmature *)object->data;
+ OperationNode *op_node;
+ Object *object_cow = get_cow_datablock(object);
+ /* Sanity check. */
+ BLI_assert(object->pose != NULL);
+ /* Armature. */
+ build_armature(armature);
+ /* speed optimization for animation lookups */
+ BKE_pose_channels_hash_make(object->pose);
+ if (object->pose->flag & POSE_CONSTRAINTS_NEED_UPDATE_FLAGS) {
+ BKE_pose_update_constraint_flags(object->pose);
+ }
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_INIT,
+ function_bind(BKE_pose_eval_proxy_init, _1, object_cow));
+ op_node->set_as_entry();
+
+ int pchan_index = 0;
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ op_node = add_operation_node(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ op_node->set_as_entry();
+ /* Bone is ready for solvers. */
+ add_operation_node(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
+ /* Bone is fully evaluated. */
+ op_node = add_operation_node(
+ &object->id,
+ NodeType::BONE,
+ pchan->name,
+ OperationCode::BONE_DONE,
+ function_bind(BKE_pose_eval_proxy_copy_bone, _1, object_cow, pchan_index));
+ op_node->set_as_exit();
+
+ /* Custom properties. */
+ if (pchan->prop != NULL) {
+ add_operation_node(
+ &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, NULL, pchan->name);
+ }
+
+ pchan_index++;
+ }
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_CLEANUP,
+ function_bind(BKE_pose_eval_proxy_cleanup, _1, object_cow));
+ op_node = add_operation_node(&object->id,
+ NodeType::EVAL_POSE,
+ OperationCode::POSE_DONE,
+ function_bind(BKE_pose_eval_proxy_done, _1, object_cow));
+ op_node->set_as_exit();
}
} // namespace DEG
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 36a9d53d670..60b711d76d3 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
@@ -60,115 +60,111 @@ namespace DEG {
void DepsgraphNodeBuilder::build_layer_collections(ListBase *lb)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ?
- COLLECTION_RESTRICT_VIEW : COLLECTION_RESTRICT_RENDER;
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ COLLECTION_RESTRICT_RENDER;
- for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
- if (lc->collection->flag & restrict_flag) {
- continue;
- }
- if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
- build_collection(lc, lc->collection);
- }
- build_layer_collections(&lc->layer_collections);
- }
+ for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
+ if (lc->collection->flag & restrict_flag) {
+ continue;
+ }
+ if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
+ build_collection(lc, lc->collection);
+ }
+ build_layer_collections(&lc->layer_collections);
+ }
}
-void DepsgraphNodeBuilder::build_view_layer(
- Scene *scene,
- ViewLayer *view_layer,
- eDepsNode_LinkedState_Type linked_state)
+void DepsgraphNodeBuilder::build_view_layer(Scene *scene,
+ ViewLayer *view_layer,
+ eDepsNode_LinkedState_Type linked_state)
{
- /* NOTE: Pass view layer index of 0 since after scene CoW there is
- * only one view layer in there. */
- view_layer_index_ = 0;
- /* Scene ID block. */
- IDNode *id_node = add_id_node(&scene->id);
- id_node->linked_state = linked_state;
- /* Time source. */
- add_time_source();
- /* Setup currently building context. */
- scene_ = scene;
- view_layer_ = view_layer;
- /* Get pointer to a CoW version of scene ID. */
- Scene *scene_cow = get_cow_datablock(scene);
- /* Scene objects. */
- int select_id = 1;
- /* NOTE: Base is used for function bindings as-is, so need to pass CoW base,
- * but object is expected to be an original one. Hence we go into some
- * tricks here iterating over the view layer. */
- int base_index = 0;
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- /* object itself */
- if (need_pull_base_into_graph(base)) {
- /* NOTE: We consider object visible even if it's currently
- * restricted by the base/restriction flags. Otherwise its drivers
- * will never be evaluated.
- *
- * TODO(sergey): Need to go more granular on visibility checks. */
- build_object(base_index, base->object, linked_state, true);
- ++base_index;
- }
- base->object->select_id = select_id++;
- }
- build_layer_collections(&view_layer->layer_collections);
- if (scene->camera != NULL) {
- build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY, true);
- }
- /* Rigidbody. */
- if (scene->rigidbody_world != NULL) {
- build_rigidbody(scene);
- }
- /* Scene's animation and drivers. */
- if (scene->adt != NULL) {
- build_animdata(&scene->id);
- }
- /* World. */
- if (scene->world != NULL) {
- build_world(scene->world);
- }
- /* Compositor nodes */
- if (scene->nodetree != NULL) {
- build_compositor(scene);
- }
- /* Cache file. */
- LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
- build_cachefile(cachefile);
- }
- /* Masks. */
- LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
- build_mask(mask);
- }
- /* Movie clips. */
- LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclips) {
- build_movieclip(clip);
- }
- /* Material override. */
- if (view_layer->mat_override != NULL) {
- build_material(view_layer->mat_override);
- }
- /* Freestyle collections. */
- LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
- if (fls->group != NULL) {
- build_collection(NULL, fls->group);
- }
- }
- /* Collections. */
- add_operation_node(&scene->id,
- NodeType::LAYER_COLLECTIONS,
- OperationCode::VIEW_LAYER_EVAL,
- function_bind(BKE_layer_eval_view_layer_indexed,
- _1,
- scene_cow,
- view_layer_index_));
- /* Parameters evaluation for scene relations mainly. */
- add_operation_node(
- &scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
- /* Build all set scenes. */
- if (scene->set != NULL) {
- ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
- build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET);
- }
+ /* NOTE: Pass view layer index of 0 since after scene CoW there is
+ * only one view layer in there. */
+ view_layer_index_ = 0;
+ /* Scene ID block. */
+ IDNode *id_node = add_id_node(&scene->id);
+ id_node->linked_state = linked_state;
+ /* Time source. */
+ add_time_source();
+ /* Setup currently building context. */
+ scene_ = scene;
+ view_layer_ = view_layer;
+ /* Get pointer to a CoW version of scene ID. */
+ Scene *scene_cow = get_cow_datablock(scene);
+ /* Scene objects. */
+ int select_id = 1;
+ /* NOTE: Base is used for function bindings as-is, so need to pass CoW base,
+ * but object is expected to be an original one. Hence we go into some
+ * tricks here iterating over the view layer. */
+ int base_index = 0;
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ /* object itself */
+ if (need_pull_base_into_graph(base)) {
+ /* NOTE: We consider object visible even if it's currently
+ * restricted by the base/restriction flags. Otherwise its drivers
+ * will never be evaluated.
+ *
+ * TODO(sergey): Need to go more granular on visibility checks. */
+ build_object(base_index, base->object, linked_state, true);
+ ++base_index;
+ }
+ base->object->select_id = select_id++;
+ }
+ build_layer_collections(&view_layer->layer_collections);
+ if (scene->camera != NULL) {
+ build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY, true);
+ }
+ /* Rigidbody. */
+ if (scene->rigidbody_world != NULL) {
+ build_rigidbody(scene);
+ }
+ /* Scene's animation and drivers. */
+ if (scene->adt != NULL) {
+ build_animdata(&scene->id);
+ }
+ /* World. */
+ if (scene->world != NULL) {
+ build_world(scene->world);
+ }
+ /* Compositor nodes */
+ if (scene->nodetree != NULL) {
+ build_compositor(scene);
+ }
+ /* Cache file. */
+ LISTBASE_FOREACH (CacheFile *, cachefile, &bmain_->cachefiles) {
+ build_cachefile(cachefile);
+ }
+ /* Masks. */
+ LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
+ build_mask(mask);
+ }
+ /* Movie clips. */
+ LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclips) {
+ build_movieclip(clip);
+ }
+ /* Material override. */
+ if (view_layer->mat_override != NULL) {
+ build_material(view_layer->mat_override);
+ }
+ /* Freestyle collections. */
+ LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
+ if (fls->group != NULL) {
+ build_collection(NULL, fls->group);
+ }
+ }
+ /* Collections. */
+ add_operation_node(
+ &scene->id,
+ NodeType::LAYER_COLLECTIONS,
+ OperationCode::VIEW_LAYER_EVAL,
+ function_bind(BKE_layer_eval_view_layer_indexed, _1, scene_cow, view_layer_index_));
+ /* Parameters evaluation for scene relations mainly. */
+ add_operation_node(&scene->id, NodeType::PARAMETERS, OperationCode::SCENE_EVAL);
+ /* Build all set scenes. */
+ if (scene->set != NULL) {
+ ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
+ build_view_layer(scene->set, set_view_layer, DEG_ID_LINKED_VIA_SET);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
index 9316a15c278..6d979724e7e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc
@@ -33,98 +33,97 @@ namespace DEG {
static void free_rootpchanmap_valueset(void *val)
{
- /* Just need to free the set itself - the names stored are all references. */
- GSet *values = (GSet *)val;
- BLI_gset_free(values, NULL);
+ /* Just need to free the set itself - the names stored are all references. */
+ GSet *values = (GSet *)val;
+ BLI_gset_free(values, NULL);
}
RootPChanMap::RootPChanMap()
{
- /* Just create empty map. */
- map_ = BLI_ghash_str_new("RootPChanMap");
+ /* Just create empty map. */
+ map_ = BLI_ghash_str_new("RootPChanMap");
}
RootPChanMap::~RootPChanMap()
{
- /* Free the map, and all the value sets. */
- BLI_ghash_free(map_, NULL, free_rootpchanmap_valueset);
+ /* Free the map, and all the value sets. */
+ BLI_ghash_free(map_, NULL, free_rootpchanmap_valueset);
}
/* Debug contents of map */
void RootPChanMap::print_debug()
{
- GHashIterator it1;
- GSetIterator it2;
-
- printf("Root PChan Map:\n");
- GHASH_ITER(it1, map_) {
- const char *item = (const char *)BLI_ghashIterator_getKey(&it1);
- GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1);
-
- printf(" %s : { ", item);
- GSET_ITER(it2, values) {
- const char *val = (const char *)BLI_gsetIterator_getKey(&it2);
- printf("%s, ", val);
- }
- printf("}\n");
- }
+ GHashIterator it1;
+ GSetIterator it2;
+
+ printf("Root PChan Map:\n");
+ GHASH_ITER (it1, map_) {
+ const char *item = (const char *)BLI_ghashIterator_getKey(&it1);
+ GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1);
+
+ printf(" %s : { ", item);
+ GSET_ITER (it2, values) {
+ const char *val = (const char *)BLI_gsetIterator_getKey(&it2);
+ printf("%s, ", val);
+ }
+ printf("}\n");
+ }
}
/* Add a mapping. */
void RootPChanMap::add_bone(const char *bone, const char *root)
{
- if (BLI_ghash_haskey(map_, bone)) {
- /* Add new entry, but only add the root if it doesn't already
- * exist in there. */
- GSet *values = (GSet *)BLI_ghash_lookup(map_, bone);
- BLI_gset_add(values, (void *)root);
- }
- else {
- /* Create new set and mapping. */
- GSet *values = BLI_gset_new(BLI_ghashutil_strhash_p,
- BLI_ghashutil_strcmp,
- "RootPChanMap Value Set");
- BLI_ghash_insert(map_, (void *)bone, (void *)values);
-
- /* Add new entry now. */
- BLI_gset_insert(values, (void *)root);
- }
+ if (BLI_ghash_haskey(map_, bone)) {
+ /* Add new entry, but only add the root if it doesn't already
+ * exist in there. */
+ GSet *values = (GSet *)BLI_ghash_lookup(map_, bone);
+ BLI_gset_add(values, (void *)root);
+ }
+ else {
+ /* Create new set and mapping. */
+ GSet *values = BLI_gset_new(
+ BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "RootPChanMap Value Set");
+ BLI_ghash_insert(map_, (void *)bone, (void *)values);
+
+ /* Add new entry now. */
+ BLI_gset_insert(values, (void *)root);
+ }
}
/* Check if there's a common root bone between two bones. */
bool RootPChanMap::has_common_root(const char *bone1, const char *bone2)
{
- /* Ensure that both are in the map... */
- if (BLI_ghash_haskey(map_, bone1) == false) {
- //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
- //print_debug();
- return false;
- }
-
- if (BLI_ghash_haskey(map_, bone2) == false) {
- //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
- //print_debug();
- return false;
- }
-
- GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1);
- GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2);
-
- GSetIterator it1, it2;
- GSET_ITER(it1, bone1_roots) {
- GSET_ITER(it2, bone2_roots) {
- const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1);
- const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2);
-
- if (strcmp(v1, v2) == 0) {
- //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
- return true;
- }
- }
- }
-
- //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
- return false;
+ /* Ensure that both are in the map... */
+ if (BLI_ghash_haskey(map_, bone1) == false) {
+ //fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2);
+ //print_debug();
+ return false;
+ }
+
+ if (BLI_ghash_haskey(map_, bone2) == false) {
+ //fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2);
+ //print_debug();
+ return false;
+ }
+
+ GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1);
+ GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2);
+
+ GSetIterator it1, it2;
+ GSET_ITER (it1, bone1_roots) {
+ GSET_ITER (it2, bone2_roots) {
+ const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1);
+ const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2);
+
+ if (strcmp(v1, v2) == 0) {
+ //fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2);
+ return true;
+ }
+ }
+ }
+
+ //fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2);
+ return false;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
index 1fb634a8707..0c1d22f9345 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h
@@ -28,27 +28,27 @@ struct GHash;
namespace DEG {
struct RootPChanMap {
- /* ctor and dtor - Create and free the internal map respectively. */
- RootPChanMap();
- ~RootPChanMap();
-
- /* Debug contents of map. */
- void print_debug();
-
- /* Add a mapping. */
- void add_bone(const char *bone, const char *root);
-
- /* Check if there's a common root bone between two bones. */
- bool has_common_root(const char *bone1, const char *bone2);
-
-protected:
- /* The actual map:
- * - Keys are "strings" (const char *) - not dynamically allocated.
- * - Values are "sets" (const char *) - not dynamically allocated.
- *
- * We don't use the C++ maps here, as it's more convenient to use
- * Blender's GHash and be able to compare by-value instead of by-ref. */
- struct GHash *map_;
+ /* ctor and dtor - Create and free the internal map respectively. */
+ RootPChanMap();
+ ~RootPChanMap();
+
+ /* Debug contents of map. */
+ void print_debug();
+
+ /* Add a mapping. */
+ void add_bone(const char *bone, const char *root);
+
+ /* Check if there's a common root bone between two bones. */
+ bool has_common_root(const char *bone1, const char *bone2);
+
+ protected:
+ /* The actual map:
+ * - Keys are "strings" (const char *) - not dynamically allocated.
+ * - Values are "sets" (const char *) - not dynamically allocated.
+ *
+ * We don't use the C++ maps here, as it's more convenient to use
+ * Blender's GHash and be able to compare by-value instead of by-ref. */
+ struct GHash *map_;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 489b688eaaa..87a8875f819 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h"
@@ -121,61 +121,60 @@ namespace DEG {
*/
static bool python_driver_depends_on_time(ChannelDriver *driver)
{
- if (driver->expression[0] == '\0') {
- /* Empty expression depends on nothing. */
- return false;
- }
- if (strchr(driver->expression, '(') != NULL) {
- /* Function calls are considered dependent on a time. */
- return true;
- }
- if (strstr(driver->expression, "frame") != NULL) {
- /* Variable `frame` depends on time. */
- /* TODO(sergey): This is a bit weak, but not sure about better way of
- * handling this. */
- return true;
- }
- /* Possible indirect time relation s should be handled via variable
- * targets. */
- return false;
+ if (driver->expression[0] == '\0') {
+ /* Empty expression depends on nothing. */
+ return false;
+ }
+ if (strchr(driver->expression, '(') != NULL) {
+ /* Function calls are considered dependent on a time. */
+ return true;
+ }
+ if (strstr(driver->expression, "frame") != NULL) {
+ /* Variable `frame` depends on time. */
+ /* TODO(sergey): This is a bit weak, but not sure about better way of
+ * handling this. */
+ return true;
+ }
+ /* Possible indirect time relation s should be handled via variable
+ * targets. */
+ return false;
}
static bool particle_system_depends_on_time(ParticleSystem *psys)
{
- ParticleSettings *part = psys->part;
- /* Non-hair particles we always consider dependent on time. */
- if (part->type != PART_HAIR) {
- return true;
- }
- /* Dynamics always depends on time. */
- if (psys->flag & PSYS_HAIR_DYNAMICS) {
- return true;
- }
- /* TODO(sergey): Check what else makes hair dependent on time. */
- return false;
+ ParticleSettings *part = psys->part;
+ /* Non-hair particles we always consider dependent on time. */
+ if (part->type != PART_HAIR) {
+ return true;
+ }
+ /* Dynamics always depends on time. */
+ if (psys->flag & PSYS_HAIR_DYNAMICS) {
+ return true;
+ }
+ /* TODO(sergey): Check what else makes hair dependent on time. */
+ return false;
}
static bool object_particles_depends_on_time(Object *object)
{
- if (object->type != OB_MESH) {
- return false;
- }
- LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
- if (particle_system_depends_on_time(psys)) {
- return true;
- }
- }
- return false;
+ if (object->type != OB_MESH) {
+ return false;
+ }
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ if (particle_system_depends_on_time(psys)) {
+ return true;
+ }
+ }
+ return false;
}
static bool check_id_has_anim_component(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return false;
- }
- return (adt->action != NULL) ||
- (!BLI_listbase_is_empty(&adt->nla_tracks));
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return false;
+ }
+ return (adt->action != NULL) || (!BLI_listbase_is_empty(&adt->nla_tracks));
}
static OperationCode bone_target_opcode(ID *target,
@@ -184,267 +183,251 @@ static OperationCode bone_target_opcode(ID *target,
const char *component_subdata,
RootPChanMap *root_map)
{
- /* Same armature. */
- if (target == id) {
- /* Using "done" here breaks in-chain deps, while using
- * "ready" here breaks most production rigs instead.
- * So, we do a compromise here, and only do this when an
- * IK chain conflict may occur. */
- if (root_map->has_common_root(component_subdata, subtarget)) {
- return OperationCode::BONE_READY;
- }
- }
- return OperationCode::BONE_DONE;
+ /* Same armature. */
+ if (target == id) {
+ /* Using "done" here breaks in-chain deps, while using
+ * "ready" here breaks most production rigs instead.
+ * So, we do a compromise here, and only do this when an
+ * IK chain conflict may occur. */
+ if (root_map->has_common_root(component_subdata, subtarget)) {
+ return OperationCode::BONE_READY;
+ }
+ }
+ return OperationCode::BONE_DONE;
}
static bool bone_has_segments(Object *object, const char *bone_name)
{
- /* Proxies don't have BONE_SEGMENTS */
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- return false;
- }
- /* Only B-Bones have segments. */
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
- return pchan && pchan->bone && pchan->bone->segments > 1;
+ /* Proxies don't have BONE_SEGMENTS */
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ return false;
+ }
+ /* Only B-Bones have segments. */
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ return pchan && pchan->bone && pchan->bone->segments > 1;
}
/* **** General purpose functions **** */
-DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
- Depsgraph *graph)
- : DepsgraphBuilder(bmain, graph),
- scene_(NULL),
- rna_node_query_(graph)
+DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph)
+ : DepsgraphBuilder(bmain, graph), scene_(NULL), rna_node_query_(graph)
{
}
-TimeSourceNode *DepsgraphRelationBuilder::get_node(
- const TimeSourceKey &key) const
+TimeSourceNode *DepsgraphRelationBuilder::get_node(const TimeSourceKey &key) const
{
- if (key.id) {
- /* XXX TODO */
- return NULL;
- }
- else {
- return graph_->time_source;
- }
+ if (key.id) {
+ /* XXX TODO */
+ return NULL;
+ }
+ else {
+ return graph_->time_source;
+ }
}
-ComponentNode *DepsgraphRelationBuilder::get_node(
- const ComponentKey &key) const
+ComponentNode *DepsgraphRelationBuilder::get_node(const ComponentKey &key) const
{
- IDNode *id_node = graph_->find_id_node(key.id);
- if (!id_node) {
- fprintf(stderr, "find_node component: Could not find ID %s\n",
- (key.id != NULL) ? key.id->name : "<null>");
- return NULL;
- }
+ IDNode *id_node = graph_->find_id_node(key.id);
+ if (!id_node) {
+ fprintf(stderr,
+ "find_node component: Could not find ID %s\n",
+ (key.id != NULL) ? key.id->name : "<null>");
+ return NULL;
+ }
- ComponentNode *node = id_node->find_component(key.type, key.name);
- return node;
+ ComponentNode *node = id_node->find_component(key.type, key.name);
+ return node;
}
-OperationNode *DepsgraphRelationBuilder::get_node(
- const OperationKey &key) const
+OperationNode *DepsgraphRelationBuilder::get_node(const OperationKey &key) const
{
- OperationNode *op_node = find_node(key);
- if (op_node == NULL) {
- fprintf(stderr, "find_node_operation: Failed for (%s, '%s')\n",
- operationCodeAsString(key.opcode), key.name);
- }
- return op_node;
+ OperationNode *op_node = find_node(key);
+ if (op_node == NULL) {
+ fprintf(stderr,
+ "find_node_operation: Failed for (%s, '%s')\n",
+ operationCodeAsString(key.opcode),
+ key.name);
+ }
+ return op_node;
}
Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key)
{
- return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
+ return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
}
-OperationNode *DepsgraphRelationBuilder::find_node(
- const OperationKey &key) const
+OperationNode *DepsgraphRelationBuilder::find_node(const OperationKey &key) const
{
- IDNode *id_node = graph_->find_id_node(key.id);
- if (!id_node) {
- return NULL;
- }
- ComponentNode *comp_node = id_node->find_component(key.component_type,
- key.component_name);
- if (!comp_node) {
- return NULL;
- }
- return comp_node->find_operation(key.opcode, key.name, key.name_tag);
+ IDNode *id_node = graph_->find_id_node(key.id);
+ if (!id_node) {
+ return NULL;
+ }
+ ComponentNode *comp_node = id_node->find_component(key.component_type, key.component_name);
+ if (!comp_node) {
+ return NULL;
+ }
+ return comp_node->find_operation(key.opcode, key.name, key.name_tag);
}
bool DepsgraphRelationBuilder::has_node(const OperationKey &key) const
{
- return find_node(key) != NULL;
+ return find_node(key) != NULL;
}
-void DepsgraphRelationBuilder::add_modifier_to_transform_relation(
- const DepsNodeHandle *handle,
- const char *description)
+void DepsgraphRelationBuilder::add_modifier_to_transform_relation(const DepsNodeHandle *handle,
+ const char *description)
{
- IDNode *id_node = handle->node->owner->owner;
- ID *id = id_node->id_orig;
- ComponentKey geometry_key(id, NodeType::GEOMETRY);
- /* Wire up the actual relation. */
- add_depends_on_transform_relation(id, geometry_key, description);
+ IDNode *id_node = handle->node->owner->owner;
+ ID *id = id_node->id_orig;
+ ComponentKey geometry_key(id, NodeType::GEOMETRY);
+ /* Wire up the actual relation. */
+ add_depends_on_transform_relation(id, geometry_key, description);
}
-void DepsgraphRelationBuilder::add_customdata_mask(
- Object *object,
- const DEGCustomDataMeshMasks &customdata_masks)
+void DepsgraphRelationBuilder::add_customdata_mask(Object *object,
+ const DEGCustomDataMeshMasks &customdata_masks)
{
- if (customdata_masks != DEGCustomDataMeshMasks() && object != NULL && object->type == OB_MESH) {
- DEG::IDNode *id_node = graph_->find_id_node(&object->id);
+ if (customdata_masks != DEGCustomDataMeshMasks() && object != NULL && object->type == OB_MESH) {
+ DEG::IDNode *id_node = graph_->find_id_node(&object->id);
- if (id_node == NULL) {
- BLI_assert(!"ID should always be valid");
- }
- else {
- id_node->customdata_masks |= customdata_masks;
- }
- }
+ if (id_node == NULL) {
+ BLI_assert(!"ID should always be valid");
+ }
+ else {
+ id_node->customdata_masks |= customdata_masks;
+ }
+ }
}
void DepsgraphRelationBuilder::add_special_eval_flag(ID *id, uint32_t flag)
{
- DEG::IDNode *id_node = graph_->find_id_node(id);
- if (id_node == NULL) {
- BLI_assert(!"ID should always be valid");
- }
- else {
- id_node->eval_flags |= flag;
- }
-}
-
-Relation *DepsgraphRelationBuilder::add_time_relation(
- TimeSourceNode *timesrc,
- Node *node_to,
- const char *description,
- int flags)
-{
- if (timesrc && node_to) {
- return graph_->add_new_relation(
- timesrc, node_to, description, flags);
- }
- else {
- DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
- 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);
- }
- return NULL;
-}
-
-Relation *DepsgraphRelationBuilder::add_operation_relation(
- OperationNode *node_from,
- OperationNode *node_to,
- const char *description,
- int flags)
-{
- if (node_from && node_to) {
- return graph_->add_new_relation(node_from,
- node_to,
- description,
- flags);
- }
- else {
- DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
- 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);
- }
- return NULL;
-}
-
-void DepsgraphRelationBuilder::add_particle_collision_relations(
- const OperationKey &key,
- Object *object,
- Collection *collection,
- const char *name)
-{
- ListBase *relations = build_collision_relations(graph_, collection, eModifierType_Collision);
-
- LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
- if (relation->ob != object) {
- ComponentKey trf_key(&relation->ob->id, NodeType::TRANSFORM);
- add_relation(trf_key, key, name);
-
- ComponentKey coll_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(coll_key, key, name);
- }
- }
-}
-
-void DepsgraphRelationBuilder::add_particle_forcefield_relations(
- const OperationKey &key,
- Object *object,
- ParticleSystem *psys,
- EffectorWeights *eff,
- bool add_absorption,
- const char *name)
-{
- ListBase *relations = build_effector_relations(graph_, eff->group);
-
- LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
- if (relation->ob != object) {
- /* Relation to forcefield object, optionally including geometry. */
- ComponentKey eff_key(&relation->ob->id, NodeType::TRANSFORM);
- add_relation(eff_key, key, name);
-
- if (ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
- relation->pd->forcefield == PFIELD_GUIDE)
- {
- ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(mod_key, key, name);
- }
-
- /* Smoke flow relations. */
- if (relation->pd->forcefield == PFIELD_SMOKEFLOW && relation->pd->f_source) {
- ComponentKey trf_key(&relation->pd->f_source->id,
- NodeType::TRANSFORM);
- add_relation(trf_key, key, "Smoke Force Domain");
- ComponentKey eff_key(&relation->pd->f_source->id,
- NodeType::GEOMETRY);
- add_relation(eff_key, key, "Smoke Force Domain");
- }
-
- /* Absorption forces need collision relation. */
- if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
- add_particle_collision_relations(key,
- object,
- NULL,
- "Force Absorption");
- }
- }
-
- if (relation->psys) {
- if (relation->ob != object) {
- ComponentKey eff_key(&relation->ob->id,
- NodeType::PARTICLE_SYSTEM);
- add_relation(eff_key, key, name);
- /* TODO: remove this when/if EVAL_PARTICLES is sufficient
- * for up to date particles. */
- ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
- add_relation(mod_key, key, name);
- }
- else if (relation->psys != psys) {
- OperationKey eff_key(&relation->ob->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- relation->psys->name);
- add_relation(eff_key, key, name);
- }
- }
- }
+ DEG::IDNode *id_node = graph_->find_id_node(id);
+ if (id_node == NULL) {
+ BLI_assert(!"ID should always be valid");
+ }
+ else {
+ id_node->eval_flags |= flag;
+ }
+}
+
+Relation *DepsgraphRelationBuilder::add_time_relation(TimeSourceNode *timesrc,
+ Node *node_to,
+ const char *description,
+ int flags)
+{
+ if (timesrc && node_to) {
+ return graph_->add_new_relation(timesrc, node_to, description, flags);
+ }
+ else {
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
+ 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);
+ }
+ return NULL;
+}
+
+Relation *DepsgraphRelationBuilder::add_operation_relation(OperationNode *node_from,
+ OperationNode *node_to,
+ const char *description,
+ int flags)
+{
+ if (node_from && node_to) {
+ return graph_->add_new_relation(node_from, node_to, description, flags);
+ }
+ else {
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
+ 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);
+ }
+ return NULL;
+}
+
+void DepsgraphRelationBuilder::add_particle_collision_relations(const OperationKey &key,
+ Object *object,
+ Collection *collection,
+ const char *name)
+{
+ ListBase *relations = build_collision_relations(graph_, collection, eModifierType_Collision);
+
+ LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
+ if (relation->ob != object) {
+ ComponentKey trf_key(&relation->ob->id, NodeType::TRANSFORM);
+ add_relation(trf_key, key, name);
+
+ ComponentKey coll_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(coll_key, key, name);
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::add_particle_forcefield_relations(const OperationKey &key,
+ Object *object,
+ ParticleSystem *psys,
+ EffectorWeights *eff,
+ bool add_absorption,
+ const char *name)
+{
+ ListBase *relations = build_effector_relations(graph_, eff->group);
+
+ LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
+ if (relation->ob != object) {
+ /* Relation to forcefield object, optionally including geometry. */
+ ComponentKey eff_key(&relation->ob->id, NodeType::TRANSFORM);
+ add_relation(eff_key, key, name);
+
+ if (ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
+ relation->pd->forcefield == PFIELD_GUIDE) {
+ ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(mod_key, key, name);
+ }
+
+ /* Smoke flow relations. */
+ if (relation->pd->forcefield == PFIELD_SMOKEFLOW && relation->pd->f_source) {
+ ComponentKey trf_key(&relation->pd->f_source->id, NodeType::TRANSFORM);
+ add_relation(trf_key, key, "Smoke Force Domain");
+ ComponentKey eff_key(&relation->pd->f_source->id, NodeType::GEOMETRY);
+ add_relation(eff_key, key, "Smoke Force Domain");
+ }
+
+ /* Absorption forces need collision relation. */
+ if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
+ add_particle_collision_relations(key, object, NULL, "Force Absorption");
+ }
+ }
+
+ if (relation->psys) {
+ if (relation->ob != object) {
+ ComponentKey eff_key(&relation->ob->id, NodeType::PARTICLE_SYSTEM);
+ add_relation(eff_key, key, name);
+ /* TODO: remove this when/if EVAL_PARTICLES is sufficient
+ * for up to date particles. */
+ ComponentKey mod_key(&relation->ob->id, NodeType::GEOMETRY);
+ add_relation(mod_key, key, name);
+ }
+ else if (relation->psys != psys) {
+ OperationKey eff_key(&relation->ob->id,
+ NodeType::PARTICLE_SYSTEM,
+ OperationCode::PARTICLE_SYSTEM_EVAL,
+ relation->psys->name);
+ add_relation(eff_key, key, name);
+ }
+ }
+ }
}
Depsgraph *DepsgraphRelationBuilder::getGraph()
{
- return graph_;
+ return graph_;
}
/* **** Functions to build relations between entities **** */
@@ -455,549 +438,491 @@ void DepsgraphRelationBuilder::begin_build()
void DepsgraphRelationBuilder::build_id(ID *id)
{
- if (id == NULL) {
- return;
- }
- switch (GS(id->name)) {
- case ID_AC:
- build_action((bAction *)id);
- break;
- case ID_AR:
- build_armature((bArmature *)id);
- break;
- case ID_CA:
- build_camera((Camera *)id);
- break;
- case ID_GR:
- build_collection(NULL, NULL, (Collection *)id);
- break;
- case ID_OB:
- build_object(NULL, (Object *)id);
- break;
- case ID_KE:
- build_shapekeys((Key *)id);
- break;
- case ID_LA:
- build_light((Light *)id);
- break;
- case ID_LP:
- build_lightprobe((LightProbe *)id);
- break;
- case ID_NT:
- build_nodetree((bNodeTree *)id);
- break;
- case ID_MA:
- build_material((Material *)id);
- break;
- case ID_TE:
- build_texture((Tex *)id);
- break;
- case ID_IM:
- build_image((Image *)id);
- break;
- case ID_WO:
- build_world((World *)id);
- break;
- case ID_MSK:
- build_mask((Mask *)id);
- break;
- case ID_MC:
- build_movieclip((MovieClip *)id);
- break;
- case ID_ME:
- case ID_CU:
- case ID_MB:
- case ID_LT:
- build_object_data_geometry_datablock(id);
- break;
- case ID_SPK:
- build_speaker((Speaker *)id);
- break;
- case ID_TXT:
- /* Not a part of dependency graph. */
- break;
- case ID_CF:
- build_cachefile((CacheFile *)id);
- break;
- default:
- fprintf(stderr, "Unhandled ID %s\n", id->name);
- BLI_assert(!"Should never happen");
- break;
- }
-}
-
-void DepsgraphRelationBuilder::build_collection(
- LayerCollection *from_layer_collection,
- Object *object,
- Collection *collection)
-{
- if (from_layer_collection != NULL) {
- /* If we came from layer collection we don't go deeper, view layer
- * builder takes care of going deeper.
- *
- * NOTE: Do early output before tagging build as done, so possbile
- * subsequent builds from outside of the layer collection properly
- * recurses into all the nested objects and collections. */
- return;
- }
- const bool group_done = built_map_.checkIsBuiltAndTag(collection);
- OperationKey object_transform_final_key(object != NULL ? &object->id : NULL,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- ComponentKey duplicator_key(object != NULL ? &object->id : NULL,
- NodeType::DUPLI);
- if (!group_done) {
- LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
- build_object(NULL, cob->ob);
- }
- LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
- build_collection(NULL, NULL, child->collection);
- }
- }
- if (object != NULL) {
- FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(collection, ob, graph_->mode)
- {
- ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
- add_relation(dupli_transform_key,
- object_transform_final_key,
- "Dupligroup");
- /* Hook to special component, to ensure proper visibility/evaluation
- * optimizations. */
- add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
- const NodeType dupli_geometry_component_type =
- geometry_tag_to_component(&ob->id);
- if (dupli_geometry_component_type != NodeType::UNDEFINED) {
- ComponentKey dupli_geometry_component_key(
- &ob->id, dupli_geometry_component_type);
- add_relation(dupli_geometry_component_key,
- duplicator_key,
- "Dupligroup");
- }
- }
- FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
- }
+ if (id == NULL) {
+ return;
+ }
+ switch (GS(id->name)) {
+ case ID_AC:
+ build_action((bAction *)id);
+ break;
+ case ID_AR:
+ build_armature((bArmature *)id);
+ break;
+ case ID_CA:
+ build_camera((Camera *)id);
+ break;
+ case ID_GR:
+ build_collection(NULL, NULL, (Collection *)id);
+ break;
+ case ID_OB:
+ build_object(NULL, (Object *)id);
+ break;
+ case ID_KE:
+ build_shapekeys((Key *)id);
+ break;
+ case ID_LA:
+ build_light((Light *)id);
+ break;
+ case ID_LP:
+ build_lightprobe((LightProbe *)id);
+ break;
+ case ID_NT:
+ build_nodetree((bNodeTree *)id);
+ break;
+ case ID_MA:
+ build_material((Material *)id);
+ break;
+ case ID_TE:
+ build_texture((Tex *)id);
+ break;
+ case ID_IM:
+ build_image((Image *)id);
+ break;
+ case ID_WO:
+ build_world((World *)id);
+ break;
+ case ID_MSK:
+ build_mask((Mask *)id);
+ break;
+ case ID_MC:
+ build_movieclip((MovieClip *)id);
+ break;
+ case ID_ME:
+ case ID_CU:
+ case ID_MB:
+ case ID_LT:
+ build_object_data_geometry_datablock(id);
+ break;
+ case ID_SPK:
+ build_speaker((Speaker *)id);
+ break;
+ case ID_TXT:
+ /* Not a part of dependency graph. */
+ break;
+ case ID_CF:
+ build_cachefile((CacheFile *)id);
+ break;
+ default:
+ fprintf(stderr, "Unhandled ID %s\n", id->name);
+ BLI_assert(!"Should never happen");
+ break;
+ }
+}
+
+void DepsgraphRelationBuilder::build_collection(LayerCollection *from_layer_collection,
+ Object *object,
+ Collection *collection)
+{
+ if (from_layer_collection != NULL) {
+ /* If we came from layer collection we don't go deeper, view layer
+ * builder takes care of going deeper.
+ *
+ * NOTE: Do early output before tagging build as done, so possbile
+ * subsequent builds from outside of the layer collection properly
+ * recurses into all the nested objects and collections. */
+ return;
+ }
+ const bool group_done = built_map_.checkIsBuiltAndTag(collection);
+ OperationKey object_transform_final_key(
+ object != NULL ? &object->id : NULL, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ ComponentKey duplicator_key(object != NULL ? &object->id : NULL, NodeType::DUPLI);
+ if (!group_done) {
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ build_object(NULL, cob->ob);
+ }
+ LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
+ build_collection(NULL, NULL, child->collection);
+ }
+ }
+ if (object != NULL) {
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, ob, graph_->mode) {
+ ComponentKey dupli_transform_key(&ob->id, NodeType::TRANSFORM);
+ add_relation(dupli_transform_key, object_transform_final_key, "Dupligroup");
+ /* Hook to special component, to ensure proper visibility/evaluation
+ * optimizations. */
+ add_relation(dupli_transform_key, duplicator_key, "Dupligroup");
+ const NodeType dupli_geometry_component_type = geometry_tag_to_component(&ob->id);
+ if (dupli_geometry_component_type != NodeType::UNDEFINED) {
+ ComponentKey dupli_geometry_component_key(&ob->id, dupli_geometry_component_type);
+ add_relation(dupli_geometry_component_key, duplicator_key, "Dupligroup");
+ }
+ }
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
+ }
}
void DepsgraphRelationBuilder::build_object(Base *base, Object *object)
{
- if (built_map_.checkIsBuiltAndTag(object)) {
- if (base != NULL) {
- build_object_flags(base, object);
- }
- return;
- }
- /* Object Transforms */
- OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT
- : OperationCode::TRANSFORM_LOCAL;
- OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
- OperationKey init_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
- OperationKey local_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
- OperationKey parent_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT);
- OperationKey final_transform_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
- OperationKey ob_eval_key(
- &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
- add_relation(init_transform_key, local_transform_key, "Transform Init");
- /* Various flags, flushing from bases/collections. */
- build_object_flags(base, object);
- /* Parenting. */
- if (object->parent != NULL) {
- /* Make sure parent object's relations are built. */
- build_object(NULL, object->parent);
- /* Parent relationship. */
- build_object_parent(object);
- /* Local -> parent. */
- add_relation(local_transform_key,
- parent_transform_key,
- "ObLocal -> ObParent");
- }
- /* Modifiers. */
- if (object->modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Grease Pencil Modifiers. */
- if (object->greasepencil_modifiers.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
- }
- /* Shader FX. */
- if (object->shader_fx.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
- }
- /* Constraints. */
- if (object->constraints.first != NULL) {
- BuilderWalkUserData data;
- data.builder = this;
- BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
- }
- /* Object constraints. */
- OperationKey object_transform_simulation_init_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- if (object->constraints.first != NULL) {
- OperationKey constraint_key(&object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_CONSTRAINTS);
- /* Constraint relations. */
- build_constraints(&object->id,
- NodeType::TRANSFORM,
- "",
- &object->constraints,
- NULL);
- /* operation order */
- add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
- add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
- add_relation(constraint_key, ob_eval_key, "Constraint -> Transform Eval");
- add_relation(ob_eval_key,
- object_transform_simulation_init_key,
- "Transform Eval -> Simulation Init");
- add_relation(object_transform_simulation_init_key,
- final_transform_key,
- "Simulation -> Final Transform");
- }
- else {
- add_relation(base_op_key, ob_eval_key, "Eval");
- add_relation(ob_eval_key,
- object_transform_simulation_init_key,
- "Transform Eval -> Simulation Init");
- add_relation(object_transform_simulation_init_key,
- final_transform_key,
- "Simulation -> Final Transform");
- }
- /* Animation data */
- build_animdata(&object->id);
- /* Object data. */
- build_object_data(object);
- /* Particle systems. */
- if (object->particlesystem.first != NULL) {
- build_particle_systems(object);
- }
- /* Proxy object to copy from. */
- if (object->proxy_from != NULL) {
- build_object(NULL, object->proxy_from);
- ComponentKey ob_transform_key(
- &object->proxy_from->id, NodeType::TRANSFORM);
- ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
- }
- if (object->proxy_group != NULL) {
- build_object(NULL, object->proxy_group);
- OperationKey proxy_group_eval_key(&object->proxy_group->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- add_relation(proxy_group_eval_key,
- final_transform_key,
- "Proxy Group Transform");
- }
- /* Object dupligroup. */
- if (object->instance_collection != NULL) {
- build_collection(NULL, object, object->instance_collection);
- }
- /* Point caches. */
- build_object_pointcache(object);
- /* Syncronization back to original object. */
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- final_transform_key, synchronize_key, "Synchronize to Original");
- /* Parameters. */
- build_parameters(&object->id);
+ if (built_map_.checkIsBuiltAndTag(object)) {
+ if (base != NULL) {
+ build_object_flags(base, object);
+ }
+ return;
+ }
+ /* Object Transforms */
+ OperationCode base_op = (object->parent) ? OperationCode::TRANSFORM_PARENT :
+ OperationCode::TRANSFORM_LOCAL;
+ OperationKey base_op_key(&object->id, NodeType::TRANSFORM, base_op);
+ OperationKey init_transform_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_INIT);
+ OperationKey local_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
+ OperationKey parent_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_PARENT);
+ OperationKey final_transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ OperationKey ob_eval_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(init_transform_key, local_transform_key, "Transform Init");
+ /* Various flags, flushing from bases/collections. */
+ build_object_flags(base, object);
+ /* Parenting. */
+ if (object->parent != NULL) {
+ /* Make sure parent object's relations are built. */
+ build_object(NULL, object->parent);
+ /* Parent relationship. */
+ build_object_parent(object);
+ /* Local -> parent. */
+ add_relation(local_transform_key, parent_transform_key, "ObLocal -> ObParent");
+ }
+ /* Modifiers. */
+ if (object->modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_shaderfx_foreachIDLink(object, modifier_walk, &data);
+ }
+ /* Constraints. */
+ if (object->constraints.first != NULL) {
+ BuilderWalkUserData data;
+ data.builder = this;
+ BKE_constraints_id_loop(&object->constraints, constraint_walk, &data);
+ }
+ /* Object constraints. */
+ OperationKey object_transform_simulation_init_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ if (object->constraints.first != NULL) {
+ OperationKey constraint_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_CONSTRAINTS);
+ /* Constraint relations. */
+ build_constraints(&object->id, NodeType::TRANSFORM, "", &object->constraints, NULL);
+ /* operation order */
+ add_relation(base_op_key, constraint_key, "ObBase-> Constraint Stack");
+ add_relation(constraint_key, final_transform_key, "ObConstraints -> Done");
+ add_relation(constraint_key, ob_eval_key, "Constraint -> Transform Eval");
+ add_relation(
+ ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
+ add_relation(object_transform_simulation_init_key,
+ final_transform_key,
+ "Simulation -> Final Transform");
+ }
+ else {
+ add_relation(base_op_key, ob_eval_key, "Eval");
+ add_relation(
+ ob_eval_key, object_transform_simulation_init_key, "Transform Eval -> Simulation Init");
+ add_relation(object_transform_simulation_init_key,
+ final_transform_key,
+ "Simulation -> Final Transform");
+ }
+ /* Animation data */
+ build_animdata(&object->id);
+ /* Object data. */
+ build_object_data(object);
+ /* Particle systems. */
+ if (object->particlesystem.first != NULL) {
+ build_particle_systems(object);
+ }
+ /* Proxy object to copy from. */
+ if (object->proxy_from != NULL) {
+ build_object(NULL, object->proxy_from);
+ ComponentKey ob_transform_key(&object->proxy_from->id, NodeType::TRANSFORM);
+ ComponentKey proxy_transform_key(&object->id, NodeType::TRANSFORM);
+ add_relation(ob_transform_key, proxy_transform_key, "Proxy Transform");
+ }
+ if (object->proxy_group != NULL) {
+ build_object(NULL, object->proxy_group);
+ OperationKey proxy_group_eval_key(
+ &object->proxy_group->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(proxy_group_eval_key, final_transform_key, "Proxy Group Transform");
+ }
+ /* Object dupligroup. */
+ if (object->instance_collection != NULL) {
+ build_collection(NULL, object, object->instance_collection);
+ }
+ /* Point caches. */
+ build_object_pointcache(object);
+ /* Syncronization back to original object. */
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(final_transform_key, synchronize_key, "Synchronize to Original");
+ /* Parameters. */
+ build_parameters(&object->id);
}
void DepsgraphRelationBuilder::build_object_flags(Base *base, Object *object)
{
- if (base == NULL) {
- return;
- }
- OperationKey view_layer_done_key(&scene_->id,
- NodeType::LAYER_COLLECTIONS,
- OperationCode::VIEW_LAYER_EVAL);
- OperationKey object_flags_key(&object->id,
- NodeType::OBJECT_FROM_LAYER,
- OperationCode::OBJECT_BASE_FLAGS);
- add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
- /* Syncronization back to original object. */
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- object_flags_key, synchronize_key, "Synchronize to Original");
+ if (base == NULL) {
+ return;
+ }
+ OperationKey view_layer_done_key(
+ &scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ OperationKey object_flags_key(
+ &object->id, NodeType::OBJECT_FROM_LAYER, OperationCode::OBJECT_BASE_FLAGS);
+ add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
+ /* Syncronization back to original object. */
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(object_flags_key, synchronize_key, "Synchronize to Original");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
- if (object->data == NULL) {
- return;
- }
- ID *obdata_id = (ID *)object->data;
- /* Object data animation. */
- if (!built_map_.checkIsBuilt(obdata_id)) {
- build_animdata(obdata_id);
- }
- /* type-specific data. */
- switch (object->type) {
- case OB_MESH:
- case OB_CURVE:
- case OB_FONT:
- case OB_SURF:
- case OB_MBALL:
- case OB_LATTICE:
- case OB_GPENCIL:
- {
- build_object_data_geometry(object);
- /* TODO(sergey): Only for until we support granular
- * update of curves. */
- if (object->type == OB_FONT) {
- Curve *curve = (Curve *)object->data;
- if (curve->textoncurve) {
- add_special_eval_flag(&curve->textoncurve->id, DAG_EVAL_NEED_CURVE_PATH);
- }
- }
- break;
- }
- case OB_ARMATURE:
- if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
- build_proxy_rig(object);
- }
- else {
- build_rig(object);
- }
- break;
- case OB_LAMP:
- build_object_data_light(object);
- break;
- case OB_CAMERA:
- build_object_data_camera(object);
- break;
- case OB_LIGHTPROBE:
- build_object_data_lightprobe(object);
- break;
- case OB_SPEAKER:
- build_object_data_speaker(object);
- break;
- }
- Key *key = BKE_key_from_object(object);
- if (key != NULL) {
- ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
- ComponentKey key_key(&key->id, NodeType::GEOMETRY);
- add_relation(key_key, geometry_key, "Shapekeys");
- build_nested_shapekey(&object->id, key);
- }
+ if (object->data == NULL) {
+ return;
+ }
+ ID *obdata_id = (ID *)object->data;
+ /* Object data animation. */
+ if (!built_map_.checkIsBuilt(obdata_id)) {
+ build_animdata(obdata_id);
+ }
+ /* type-specific data. */
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ case OB_MBALL:
+ case OB_LATTICE:
+ case OB_GPENCIL: {
+ build_object_data_geometry(object);
+ /* TODO(sergey): Only for until we support granular
+ * update of curves. */
+ if (object->type == OB_FONT) {
+ Curve *curve = (Curve *)object->data;
+ if (curve->textoncurve) {
+ add_special_eval_flag(&curve->textoncurve->id, DAG_EVAL_NEED_CURVE_PATH);
+ }
+ }
+ break;
+ }
+ case OB_ARMATURE:
+ if (ID_IS_LINKED(object) && object->proxy_from != NULL) {
+ build_proxy_rig(object);
+ }
+ else {
+ build_rig(object);
+ }
+ break;
+ case OB_LAMP:
+ build_object_data_light(object);
+ break;
+ case OB_CAMERA:
+ build_object_data_camera(object);
+ break;
+ case OB_LIGHTPROBE:
+ build_object_data_lightprobe(object);
+ break;
+ case OB_SPEAKER:
+ build_object_data_speaker(object);
+ break;
+ }
+ Key *key = BKE_key_from_object(object);
+ if (key != NULL) {
+ ComponentKey geometry_key((ID *)object->data, NodeType::GEOMETRY);
+ ComponentKey key_key(&key->id, NodeType::GEOMETRY);
+ add_relation(key_key, geometry_key, "Shapekeys");
+ build_nested_shapekey(&object->id, key);
+ }
}
void DepsgraphRelationBuilder::build_object_data_camera(Object *object)
{
- Camera *camera = (Camera *)object->data;
- build_camera(camera);
- ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
- ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
- add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
+ Camera *camera = (Camera *)object->data;
+ build_camera(camera);
+ ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
+ ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
+ add_relation(camera_parameters_key, object_parameters_key, "Camera -> Object");
}
void DepsgraphRelationBuilder::build_object_data_light(Object *object)
{
- Light *lamp = (Light *)object->data;
- build_light(lamp);
- ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
- ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
- add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
+ Light *lamp = (Light *)object->data;
+ build_light(lamp);
+ ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+ ComponentKey object_parameters_key(&object->id, NodeType::PARAMETERS);
+ add_relation(lamp_parameters_key, object_parameters_key, "Light -> Object");
}
void DepsgraphRelationBuilder::build_object_data_lightprobe(Object *object)
{
- LightProbe *probe = (LightProbe *)object->data;
- build_lightprobe(probe);
- OperationKey probe_key(&probe->id,
- NodeType::PARAMETERS,
- OperationCode::LIGHT_PROBE_EVAL);
- OperationKey object_key(&object->id,
- NodeType::PARAMETERS,
- OperationCode::LIGHT_PROBE_EVAL);
- add_relation(probe_key, object_key, "LightProbe Update");
+ LightProbe *probe = (LightProbe *)object->data;
+ build_lightprobe(probe);
+ OperationKey probe_key(&probe->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ OperationKey object_key(&object->id, NodeType::PARAMETERS, OperationCode::LIGHT_PROBE_EVAL);
+ add_relation(probe_key, object_key, "LightProbe Update");
}
void DepsgraphRelationBuilder::build_object_data_speaker(Object *object)
{
- Speaker *speaker = (Speaker *)object->data;
- build_speaker(speaker);
- OperationKey probe_key(&speaker->id,
- NodeType::PARAMETERS,
- OperationCode::SPEAKER_EVAL);
- OperationKey object_key(&object->id,
- NodeType::PARAMETERS,
- OperationCode::SPEAKER_EVAL);
- add_relation(probe_key, object_key, "Speaker Update");
+ Speaker *speaker = (Speaker *)object->data;
+ build_speaker(speaker);
+ OperationKey probe_key(&speaker->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ OperationKey object_key(&object->id, NodeType::PARAMETERS, OperationCode::SPEAKER_EVAL);
+ add_relation(probe_key, object_key, "Speaker Update");
}
void DepsgraphRelationBuilder::build_object_parent(Object *object)
{
- Object *parent = object->parent;
- ID *parent_id = &object->parent->id;
- ComponentKey ob_key(&object->id, NodeType::TRANSFORM);
- /* Type-specific links/ */
- switch (object->partype) {
- /* Armature Deform (Virtual Modifier) */
- case PARSKEL:
- {
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Armature Deform Parent");
- break;
- }
-
- /* Vertex Parent */
- case PARVERT1:
- case PARVERT3:
- {
- ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Vertex Parent");
- /* Original index is used for optimizations of lookups for subdiv
- * only meshes.
- * TODO(sergey): This optimization got lost at 2.8, so either verify
- * we can get rid of this mask here, or bring the optimization
- * back. */
- add_customdata_mask(object->parent,
- DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskEdge(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) |
- DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX));
- ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Vertex Parent TFM");
- break;
- }
-
- /* Bone Parent */
- case PARBONE:
- {
- ComponentKey parent_bone_key(
- parent_id, NodeType::BONE, object->parsubstr);
- OperationKey parent_transform_key(parent_id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(parent_bone_key, ob_key, "Bone Parent");
- add_relation(parent_transform_key, ob_key, "Armature Parent");
- break;
- }
-
- default:
- {
- if (object->parent->type == OB_LATTICE) {
- /* Lattice Deform Parent - Virtual Modifier. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Lattice Deform Parent");
- add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
- }
- else if (object->parent->type == OB_CURVE) {
- Curve *cu = (Curve *)object->parent->data;
-
- if (cu->flag & CU_PATH) {
- /* Follow Path. */
- ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Curve Follow Parent");
- ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Curve Follow TFM");
- }
- else {
- /* Standard Parent. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Curve Parent");
- }
- }
- else {
- /* Standard Parent. */
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Parent");
- }
- break;
- }
- }
- /* Metaballs are the odd balls here (no pun intended): they will request
- * instance-list (formerly known as dupli-list) during evaluation. This is
- * their way of interacting with all instanced surfaces, making a nice
- * effect when is used form particle system. */
- if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
- ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
- /* NOTE: Metaballs are evaluating geometry only after their transform,
- * so we onl;y hook up to transform channel here. */
- add_relation(parent_geometry_key, ob_key, "Parent");
- }
-
- /* Dupliverts uses original vertex index. */
- if (parent->transflag & OB_DUPLIVERTS) {
- add_customdata_mask(parent, DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX));
- }
+ Object *parent = object->parent;
+ ID *parent_id = &object->parent->id;
+ ComponentKey ob_key(&object->id, NodeType::TRANSFORM);
+ /* Type-specific links/ */
+ switch (object->partype) {
+ /* Armature Deform (Virtual Modifier) */
+ case PARSKEL: {
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Armature Deform Parent");
+ break;
+ }
+
+ /* Vertex Parent */
+ case PARVERT1:
+ case PARVERT3: {
+ ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Vertex Parent");
+ /* Original index is used for optimizations of lookups for subdiv
+ * only meshes.
+ * TODO(sergey): This optimization got lost at 2.8, so either verify
+ * we can get rid of this mask here, or bring the optimization
+ * back. */
+ add_customdata_mask(object->parent,
+ DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskEdge(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) |
+ DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX));
+ ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
+ add_relation(transform_key, ob_key, "Vertex Parent TFM");
+ break;
+ }
+
+ /* Bone Parent */
+ case PARBONE: {
+ ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr);
+ OperationKey parent_transform_key(
+ parent_id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(parent_bone_key, ob_key, "Bone Parent");
+ add_relation(parent_transform_key, ob_key, "Armature Parent");
+ break;
+ }
+
+ default: {
+ if (object->parent->type == OB_LATTICE) {
+ /* Lattice Deform Parent - Virtual Modifier. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Lattice Deform Parent");
+ add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
+ }
+ else if (object->parent->type == OB_CURVE) {
+ Curve *cu = (Curve *)object->parent->data;
+
+ if (cu->flag & CU_PATH) {
+ /* Follow Path. */
+ ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
+ add_relation(parent_key, ob_key, "Curve Follow Parent");
+ ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
+ add_relation(transform_key, ob_key, "Curve Follow TFM");
+ }
+ else {
+ /* Standard Parent. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Curve Parent");
+ }
+ }
+ else {
+ /* Standard Parent. */
+ ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_key, ob_key, "Parent");
+ }
+ break;
+ }
+ }
+ /* Metaballs are the odd balls here (no pun intended): they will request
+ * instance-list (formerly known as dupli-list) during evaluation. This is
+ * their way of interacting with all instanced surfaces, making a nice
+ * effect when is used form particle system. */
+ if (object->type == OB_MBALL && parent->transflag & OB_DUPLI) {
+ ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
+ /* NOTE: Metaballs are evaluating geometry only after their transform,
+ * so we onl;y hook up to transform channel here. */
+ add_relation(parent_geometry_key, ob_key, "Parent");
+ }
+
+ /* Dupliverts uses original vertex index. */
+ if (parent->transflag & OB_DUPLIVERTS) {
+ add_customdata_mask(parent, DEGCustomDataMeshMasks::MaskVert(CD_MASK_ORIGINDEX));
+ }
}
void DepsgraphRelationBuilder::build_object_pointcache(Object *object)
{
- ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
- /* Different point caches are affecting different aspects of life of the
- * object. We keep track of those aspects and avoid duplicate relations. */
- enum {
- FLAG_TRANSFORM = (1 << 0),
- FLAG_GEOMETRY = (1 << 1),
- FLAG_ALL = (FLAG_TRANSFORM | FLAG_GEOMETRY),
- };
- ListBase ptcache_id_list;
- BKE_ptcache_ids_from_object(&ptcache_id_list, object, scene_, 0);
- int handled_components = 0;
- LISTBASE_FOREACH (PTCacheID *, ptcache_id, &ptcache_id_list) {
- /* Check which components needs the point cache. */
- int flag = -1;
- if (ptcache_id->type == PTCACHE_TYPE_RIGIDBODY) {
- flag = FLAG_TRANSFORM;
- OperationKey transform_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- add_relation(point_cache_key,
- transform_key,
- "Point Cache -> Rigid Body");
- }
- else {
- flag = FLAG_GEOMETRY;
- OperationKey geometry_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(
- point_cache_key, geometry_key, "Point Cache -> Geometry");
- }
- BLI_assert(flag != -1);
- /* Tag that we did handle that component. */
- handled_components |= flag;
- if (handled_components == FLAG_ALL) {
- break;
- }
- }
- /* Manual edits to any dependency (or self) should reset the point cache. */
- if (!BLI_listbase_is_empty(&ptcache_id_list)) {
- OperationKey transform_eval_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- OperationKey geometry_init_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_INIT);
- add_relation(transform_eval_key,
- point_cache_key,
- "Transform Simulation -> Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- add_relation(geometry_init_key,
- point_cache_key,
- "Geometry Init -> Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- }
- BLI_freelistN(&ptcache_id_list);
+ ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
+ /* Different point caches are affecting different aspects of life of the
+ * object. We keep track of those aspects and avoid duplicate relations. */
+ enum {
+ FLAG_TRANSFORM = (1 << 0),
+ FLAG_GEOMETRY = (1 << 1),
+ FLAG_ALL = (FLAG_TRANSFORM | FLAG_GEOMETRY),
+ };
+ ListBase ptcache_id_list;
+ BKE_ptcache_ids_from_object(&ptcache_id_list, object, scene_, 0);
+ int handled_components = 0;
+ LISTBASE_FOREACH (PTCacheID *, ptcache_id, &ptcache_id_list) {
+ /* Check which components needs the point cache. */
+ int flag = -1;
+ if (ptcache_id->type == PTCACHE_TYPE_RIGIDBODY) {
+ flag = FLAG_TRANSFORM;
+ OperationKey transform_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ add_relation(point_cache_key, transform_key, "Point Cache -> Rigid Body");
+ }
+ else {
+ flag = FLAG_GEOMETRY;
+ OperationKey geometry_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(point_cache_key, geometry_key, "Point Cache -> Geometry");
+ }
+ BLI_assert(flag != -1);
+ /* Tag that we did handle that component. */
+ handled_components |= flag;
+ if (handled_components == FLAG_ALL) {
+ break;
+ }
+ }
+ /* Manual edits to any dependency (or self) should reset the point cache. */
+ if (!BLI_listbase_is_empty(&ptcache_id_list)) {
+ OperationKey transform_eval_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ OperationKey geometry_init_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ add_relation(transform_eval_key,
+ point_cache_key,
+ "Transform Simulation -> Point Cache",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ add_relation(geometry_init_key,
+ point_cache_key,
+ "Geometry Init -> Point Cache",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ }
+ BLI_freelistN(&ptcache_id_list);
}
void DepsgraphRelationBuilder::build_constraints(ID *id,
@@ -1006,1069 +931,879 @@ void DepsgraphRelationBuilder::build_constraints(ID *id,
ListBase *constraints,
RootPChanMap *root_map)
{
- OperationKey constraint_op_key(
- id,
- component_type,
- component_subdata,
- (component_type == NodeType::BONE)
- ? OperationCode::BONE_CONSTRAINTS
- : OperationCode::TRANSFORM_CONSTRAINTS);
- /* Add dependencies for each constraint in turn. */
- for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- /* Invalid constraint type. */
- if (cti == NULL) {
- continue;
- }
- /* Special case for camera tracking -- it doesn't use targets to
- * define relations. */
- /* TODO: we can now represent dependencies in a much richer manner,
- * so review how this is done. */
- if (ELEM(cti->type,
- CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- bool depends_on_camera = false;
- if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
- if (((data->clip) ||
- (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0])
- {
- depends_on_camera = true;
- }
- if (data->depth_ob) {
- ComponentKey depth_transform_key(&data->depth_ob->id,
- NodeType::TRANSFORM);
- ComponentKey depth_geometry_key(&data->depth_ob->id,
- NodeType::GEOMETRY);
- add_relation(depth_transform_key, constraint_op_key, cti->name);
- add_relation(depth_geometry_key, constraint_op_key, cti->name);
- }
- }
- else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- depends_on_camera = true;
- }
- if (depends_on_camera && scene_->camera != NULL) {
- ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
- add_relation(camera_key, constraint_op_key, cti->name);
- }
- /* TODO(sergey): This is more a TimeSource -> MovieClip ->
- * Constraint dependency chain. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
- }
- else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
- * dependency chain. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
- bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
- if (data->cache_file) {
- ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
- add_relation(cache_key, constraint_op_key, cti->name);
- }
- }
- else if (cti->get_constraint_targets) {
- ListBase targets = {NULL, NULL};
- cti->get_constraint_targets(con, &targets);
- LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
- if (ct->tar == NULL) {
- continue;
- }
- if (ELEM(con->type,
- CONSTRAINT_TYPE_KINEMATIC,
- CONSTRAINT_TYPE_SPLINEIK))
- {
- /* Ignore IK constraints - these are handled separately
- * (on pose level). */
- }
- else if (ELEM(con->type,
- CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO))
- {
- /* These constraints require path geometry data. */
- ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, constraint_op_key, cti->name);
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
- OperationCode opcode;
- /* relation to bone */
- opcode = bone_target_opcode(&ct->tar->id, ct->subtarget,
- id, component_subdata, root_map);
- /* Armature constraint always wants the final position and chan_mat. */
- if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
- opcode = OperationCode::BONE_DONE;
- }
- /* if needs bbone shape, reference the segment computation */
- if (BKE_constraint_target_uses_bbone(con, ct) &&
- bone_has_segments(ct->tar, ct->subtarget))
- {
- opcode = OperationCode::BONE_SEGMENTS;
- }
- OperationKey target_key(&ct->tar->id,
- NodeType::BONE,
- ct->subtarget,
- opcode);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) &&
- (ct->subtarget[0]))
- {
- /* Vertex group. */
- /* NOTE: Vertex group is likely to be used to get vertices
- * in a world space. This requires to know both geometry
- * and transformation of the target object. */
- ComponentKey target_transform_key(
- &ct->tar->id, NodeType::TRANSFORM);
- ComponentKey target_geometry_key(
- &ct->tar->id, NodeType::GEOMETRY);
- add_relation(
- target_transform_key, constraint_op_key, cti->name);
- add_relation(
- target_geometry_key, constraint_op_key, cti->name);
- add_customdata_mask(ct->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
- }
- else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
- bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
-
- /* Constraints which requires the target object surface. */
- ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, constraint_op_key, cti->name);
-
- /* Add dependency on normal layers if necessary. */
- if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
- bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
- if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
- add_customdata_mask(ct->tar,
- DEGCustomDataMeshMasks::MaskVert(CD_MASK_NORMAL) |
- DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL));
- }
- if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
- add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
- }
- }
-
- /* NOTE: obdata eval now doesn't necessarily depend on the
- * object's transform. */
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- else {
- /* Standard object relation. */
- // TODO: loc vs rot vs scale?
- if (&ct->tar->id == id) {
- /* Constraint targeting own object:
- * - This case is fine IFF we're dealing with a bone
- * constraint pointing to its own armature. In that
- * case, it's just transform -> bone.
- * - If however it is a real self targeting case, just
- * make it depend on the previous constraint (or the
- * pre-constraint state). */
- if ((ct->tar->type == OB_ARMATURE) &&
- (component_type == NodeType::BONE))
- {
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- else {
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_LOCAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- }
- else {
- /* Normal object dependency. */
- OperationKey target_key(&ct->tar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, constraint_op_key, cti->name);
- }
- }
- /* Constraints which needs world's matrix for transform.
- * TODO(sergey): More constraints here? */
- if (ELEM(con->type,
- CONSTRAINT_TYPE_ROTLIKE,
- CONSTRAINT_TYPE_SIZELIKE,
- CONSTRAINT_TYPE_LOCLIKE,
- CONSTRAINT_TYPE_TRANSLIKE))
- {
- /* TODO(sergey): Add used space check. */
- ComponentKey target_transform_key(&ct->tar->id,
- NodeType::TRANSFORM);
- add_relation(target_transform_key, constraint_op_key, cti->name);
- }
- }
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- }
+ OperationKey constraint_op_key(id,
+ component_type,
+ component_subdata,
+ (component_type == NodeType::BONE) ?
+ OperationCode::BONE_CONSTRAINTS :
+ OperationCode::TRANSFORM_CONSTRAINTS);
+ /* Add dependencies for each constraint in turn. */
+ for (bConstraint *con = (bConstraint *)constraints->first; con; con = con->next) {
+ const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
+ /* Invalid constraint type. */
+ if (cti == NULL) {
+ continue;
+ }
+ /* Special case for camera tracking -- it doesn't use targets to
+ * define relations. */
+ /* TODO: we can now represent dependencies in a much richer manner,
+ * so review how this is done. */
+ if (ELEM(cti->type,
+ CONSTRAINT_TYPE_FOLLOWTRACK,
+ CONSTRAINT_TYPE_CAMERASOLVER,
+ CONSTRAINT_TYPE_OBJECTSOLVER)) {
+ bool depends_on_camera = false;
+ if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
+ bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
+ if (((data->clip) || (data->flag & FOLLOWTRACK_ACTIVECLIP)) && data->track[0]) {
+ depends_on_camera = true;
+ }
+ if (data->depth_ob) {
+ ComponentKey depth_transform_key(&data->depth_ob->id, NodeType::TRANSFORM);
+ ComponentKey depth_geometry_key(&data->depth_ob->id, NodeType::GEOMETRY);
+ add_relation(depth_transform_key, constraint_op_key, cti->name);
+ add_relation(depth_geometry_key, constraint_op_key, cti->name);
+ }
+ }
+ else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
+ depends_on_camera = true;
+ }
+ if (depends_on_camera && scene_->camera != NULL) {
+ ComponentKey camera_key(&scene_->camera->id, NodeType::TRANSFORM);
+ add_relation(camera_key, constraint_op_key, cti->name);
+ }
+ /* TODO(sergey): This is more a TimeSource -> MovieClip ->
+ * Constraint dependency chain. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
+ }
+ else if (cti->type == CONSTRAINT_TYPE_TRANSFORM_CACHE) {
+ /* TODO(kevin): This is more a TimeSource -> CacheFile -> Constraint
+ * dependency chain. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, constraint_op_key, "TimeSrc -> Animation");
+ bTransformCacheConstraint *data = (bTransformCacheConstraint *)con->data;
+ if (data->cache_file) {
+ ComponentKey cache_key(&data->cache_file->id, NodeType::CACHE);
+ add_relation(cache_key, constraint_op_key, cti->name);
+ }
+ }
+ else if (cti->get_constraint_targets) {
+ ListBase targets = {NULL, NULL};
+ cti->get_constraint_targets(con, &targets);
+ LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
+ if (ct->tar == NULL) {
+ continue;
+ }
+ if (ELEM(con->type, CONSTRAINT_TYPE_KINEMATIC, CONSTRAINT_TYPE_SPLINEIK)) {
+ /* Ignore IK constraints - these are handled separately
+ * (on pose level). */
+ }
+ else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
+ /* These constraints require path geometry data. */
+ ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ else if ((ct->tar->type == OB_ARMATURE) && (ct->subtarget[0])) {
+ OperationCode opcode;
+ /* relation to bone */
+ opcode = bone_target_opcode(
+ &ct->tar->id, ct->subtarget, id, component_subdata, root_map);
+ /* Armature constraint always wants the final position and chan_mat. */
+ if (ELEM(con->type, CONSTRAINT_TYPE_ARMATURE)) {
+ opcode = OperationCode::BONE_DONE;
+ }
+ /* if needs bbone shape, reference the segment computation */
+ if (BKE_constraint_target_uses_bbone(con, ct) &&
+ bone_has_segments(ct->tar, ct->subtarget)) {
+ opcode = OperationCode::BONE_SEGMENTS;
+ }
+ OperationKey target_key(&ct->tar->id, NodeType::BONE, ct->subtarget, opcode);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
+ /* Vertex group. */
+ /* NOTE: Vertex group is likely to be used to get vertices
+ * in a world space. This requires to know both geometry
+ * and transformation of the target object. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ ComponentKey target_geometry_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ add_relation(target_geometry_key, constraint_op_key, cti->name);
+ add_customdata_mask(ct->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
+ }
+ else if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) {
+ bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *)con->data;
+
+ /* Constraints which requires the target object surface. */
+ ComponentKey target_key(&ct->tar->id, NodeType::GEOMETRY);
+ add_relation(target_key, constraint_op_key, cti->name);
+
+ /* Add dependency on normal layers if necessary. */
+ if (ct->tar->type == OB_MESH && scon->shrinkType != MOD_SHRINKWRAP_NEAREST_VERTEX) {
+ bool track = (scon->flag & CON_SHRINKWRAP_TRACK_NORMAL) != 0;
+ if (track || BKE_shrinkwrap_needs_normals(scon->shrinkType, scon->shrinkMode)) {
+ add_customdata_mask(ct->tar,
+ DEGCustomDataMeshMasks::MaskVert(CD_MASK_NORMAL) |
+ DEGCustomDataMeshMasks::MaskLoop(CD_MASK_CUSTOMLOOPNORMAL));
+ }
+ if (scon->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
+ add_special_eval_flag(&ct->tar->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
+ }
+ }
+
+ /* NOTE: obdata eval now doesn't necessarily depend on the
+ * object's transform. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ else {
+ /* Standard object relation. */
+ // TODO: loc vs rot vs scale?
+ if (&ct->tar->id == id) {
+ /* Constraint targeting own object:
+ * - This case is fine IFF we're dealing with a bone
+ * constraint pointing to its own armature. In that
+ * case, it's just transform -> bone.
+ * - If however it is a real self targeting case, just
+ * make it depend on the previous constraint (or the
+ * pre-constraint state). */
+ if ((ct->tar->type == OB_ARMATURE) && (component_type == NodeType::BONE)) {
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ else {
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_LOCAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ }
+ else {
+ /* Normal object dependency. */
+ OperationKey target_key(
+ &ct->tar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, constraint_op_key, cti->name);
+ }
+ }
+ /* Constraints which needs world's matrix for transform.
+ * TODO(sergey): More constraints here? */
+ if (ELEM(con->type,
+ CONSTRAINT_TYPE_ROTLIKE,
+ CONSTRAINT_TYPE_SIZELIKE,
+ CONSTRAINT_TYPE_LOCLIKE,
+ CONSTRAINT_TYPE_TRANSLIKE)) {
+ /* TODO(sergey): Add used space check. */
+ ComponentKey target_transform_key(&ct->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, constraint_op_key, cti->name);
+ }
+ }
+ if (cti->flush_constraint_targets) {
+ cti->flush_constraint_targets(con, &targets, 1);
+ }
+ }
+ }
}
void DepsgraphRelationBuilder::build_animdata(ID *id)
{
- /* Images. */
- build_animation_images(id);
- /* Animation curves and NLA. */
- build_animdata_curves(id);
- /* Drivers. */
- build_animdata_drivers(id);
+ /* Images. */
+ build_animation_images(id);
+ /* Animation curves and NLA. */
+ build_animdata_curves(id);
+ /* Drivers. */
+ build_animdata_drivers(id);
}
void DepsgraphRelationBuilder::build_animdata_curves(ID *id)
{
- AnimData *adt = BKE_animdata_from_id(id);
- if (adt == NULL) {
- return;
- }
- if (adt->action != NULL) {
- build_action(adt->action);
- }
- if (adt->action == NULL && BLI_listbase_is_empty(&adt->nla_tracks)) {
- return;
- }
- /* Ensure evaluation order from entry to exit. */
- OperationKey animation_entry_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
- OperationKey animation_eval_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
- OperationKey animation_exit_key(
- id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
- add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
- add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
- /* Wire up dependency from action. */
- ComponentKey adt_key(id, NodeType::ANIMATION);
- /* Relation from action itself. */
- if (adt->action != NULL) {
- ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
- add_relation(action_key, adt_key, "Action -> Animation");
- }
- /* Get source operations. */
- Node *node_from = get_node(adt_key);
- BLI_assert(node_from != NULL);
- if (node_from == NULL) {
- return;
- }
- OperationNode *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,
- OperationNode *operation_from,
- ListBase *curves)
-{
- /* Iterate over all curves and build relations. */
- PointerRNA id_ptr;
- RNA_id_pointer_create(id, &id_ptr);
- LISTBASE_FOREACH (FCurve *, fcu, curves) {
- PointerRNA ptr;
- PropertyRNA *prop;
- int index;
- if (!RNA_path_resolve_full(
- &id_ptr, fcu->rna_path, &ptr, &prop, &index))
- {
- continue;
- }
- Node *node_to = rna_node_query_.find_node(
- &ptr, prop, RNAPointerSource::ENTRY);
- if (node_to == NULL) {
- continue;
- }
- OperationNode *operation_to = node_to->get_entry_operation();
- /* NOTE: Special case for bones, avoid relation from animation to
- * each of the bones. Bone evaluation could only start from pose
- * init anyway. */
- if (operation_to->opcode == OperationCode::BONE_LOCAL) {
- OperationKey pose_init_key(
- id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
- add_relation(adt_key,
- pose_init_key,
- "Animation -> Prop",
- RELATION_CHECK_BEFORE_ADD);
- continue;
- }
- graph_->add_new_relation(operation_from, operation_to,
- "Animation -> Prop",
- RELATION_CHECK_BEFORE_ADD);
- /* It is possible that animation is writing to a nested ID datablock,
- * need to make sure animation is evaluated after target ID is copied. */
- const IDNode *id_node_from = operation_from->owner->owner;
- const IDNode *id_node_to = operation_to->owner->owner;
- if (id_node_from != id_node_to) {
- ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_WRITE);
- add_relation(cow_key,
- adt_key,
- "Animated CoW -> Animation",
- RELATION_CHECK_BEFORE_ADD);
- }
- }
-}
-
-void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(
- ID *id, ComponentKey &adt_key,
- OperationNode *operation_from,
- ListBase *strips)
-{
- LISTBASE_FOREACH (NlaStrip *, strip, strips) {
- if (strip->act != NULL) {
- build_action(strip->act);
-
- ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
- add_relation(action_key, adt_key, "Action -> Animation");
-
- 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);
- }
- }
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ if (adt->action != NULL) {
+ build_action(adt->action);
+ }
+ if (adt->action == NULL && BLI_listbase_is_empty(&adt->nla_tracks)) {
+ return;
+ }
+ /* Ensure evaluation order from entry to exit. */
+ OperationKey animation_entry_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_ENTRY);
+ OperationKey animation_eval_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_EVAL);
+ OperationKey animation_exit_key(id, NodeType::ANIMATION, OperationCode::ANIMATION_EXIT);
+ add_relation(animation_entry_key, animation_eval_key, "Init -> Eval");
+ add_relation(animation_eval_key, animation_exit_key, "Eval -> Exit");
+ /* Wire up dependency from action. */
+ ComponentKey adt_key(id, NodeType::ANIMATION);
+ /* Relation from action itself. */
+ if (adt->action != NULL) {
+ ComponentKey action_key(&adt->action->id, NodeType::ANIMATION);
+ add_relation(action_key, adt_key, "Action -> Animation");
+ }
+ /* Get source operations. */
+ Node *node_from = get_node(adt_key);
+ BLI_assert(node_from != NULL);
+ if (node_from == NULL) {
+ return;
+ }
+ OperationNode *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,
+ OperationNode *operation_from,
+ ListBase *curves)
+{
+ /* Iterate over all curves and build relations. */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ LISTBASE_FOREACH (FCurve *, fcu, curves) {
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, &prop, &index)) {
+ continue;
+ }
+ Node *node_to = rna_node_query_.find_node(&ptr, prop, RNAPointerSource::ENTRY);
+ if (node_to == NULL) {
+ continue;
+ }
+ OperationNode *operation_to = node_to->get_entry_operation();
+ /* NOTE: Special case for bones, avoid relation from animation to
+ * each of the bones. Bone evaluation could only start from pose
+ * init anyway. */
+ if (operation_to->opcode == OperationCode::BONE_LOCAL) {
+ OperationKey pose_init_key(id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
+ add_relation(adt_key, pose_init_key, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
+ continue;
+ }
+ graph_->add_new_relation(
+ operation_from, operation_to, "Animation -> Prop", RELATION_CHECK_BEFORE_ADD);
+ /* It is possible that animation is writing to a nested ID datablock,
+ * need to make sure animation is evaluated after target ID is copied. */
+ const IDNode *id_node_from = operation_from->owner->owner;
+ const IDNode *id_node_to = operation_to->owner->owner;
+ if (id_node_from != id_node_to) {
+ ComponentKey cow_key(id_node_to->id_orig, NodeType::COPY_ON_WRITE);
+ add_relation(cow_key, adt_key, "Animated CoW -> Animation", RELATION_CHECK_BEFORE_ADD);
+ }
+ }
+}
+
+void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationNode *operation_from,
+ ListBase *strips)
+{
+ LISTBASE_FOREACH (NlaStrip *, strip, strips) {
+ if (strip->act != NULL) {
+ build_action(strip->act);
+
+ ComponentKey action_key(&strip->act->id, NodeType::ANIMATION);
+ add_relation(action_key, adt_key, "Action -> Animation");
+
+ 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);
- if (adt == NULL) {
- return;
- }
- ComponentKey adt_key(id, NodeType::ANIMATION);
- LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
-
- /* create the driver's relations to targets */
- build_driver(id, fcu);
- /* Special case for array drivers: we can not multithread them because
- * of the way how they work internally: animation system will write the
- * whole array back to RNA even when changing individual array value.
- *
- * Some tricky things here:
- * - array_index is -1 for single channel drivers, meaning we only have
- * to do some magic when array_index is not -1.
- * - We do relation from next array index to a previous one, so we don't
- * have to deal with array index 0.
- *
- * TODO(sergey): Avoid liner lookup somehow. */
- if (fcu->array_index > 0) {
- FCurve *fcu_prev = NULL;
- 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)) {
- continue;
- }
- /* We only do relation from previous fcurve to previous one. */
- if (fcu_candidate->array_index >= fcu->array_index) {
- continue;
- }
- /* Choose fcurve with highest possible array index. */
- if (fcu_prev == NULL ||
- fcu_candidate->array_index > fcu_prev->array_index)
- {
- fcu_prev = fcu_candidate;
- }
- }
- if (fcu_prev != NULL) {
- OperationKey prev_driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu_prev->rna_path ? fcu_prev->rna_path : "",
- fcu_prev->array_index);
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- add_relation(prev_driver_key, driver_key, "Driver Order");
- }
- }
-
- /* prevent driver from occurring before own animation... */
- if (adt->action || adt->nla_tracks.first) {
- add_relation(adt_key, driver_key, "AnimData Before Drivers");
- }
- }
+ AnimData *adt = BKE_animdata_from_id(id);
+ if (adt == NULL) {
+ return;
+ }
+ ComponentKey adt_key(id, NodeType::ANIMATION);
+ LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+
+ /* create the driver's relations to targets */
+ build_driver(id, fcu);
+ /* Special case for array drivers: we can not multithread them because
+ * of the way how they work internally: animation system will write the
+ * whole array back to RNA even when changing individual array value.
+ *
+ * Some tricky things here:
+ * - array_index is -1 for single channel drivers, meaning we only have
+ * to do some magic when array_index is not -1.
+ * - We do relation from next array index to a previous one, so we don't
+ * have to deal with array index 0.
+ *
+ * TODO(sergey): Avoid liner lookup somehow. */
+ if (fcu->array_index > 0) {
+ FCurve *fcu_prev = NULL;
+ 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)) {
+ continue;
+ }
+ /* We only do relation from previous fcurve to previous one. */
+ if (fcu_candidate->array_index >= fcu->array_index) {
+ continue;
+ }
+ /* Choose fcurve with highest possible array index. */
+ if (fcu_prev == NULL || fcu_candidate->array_index > fcu_prev->array_index) {
+ fcu_prev = fcu_candidate;
+ }
+ }
+ if (fcu_prev != NULL) {
+ OperationKey prev_driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu_prev->rna_path ? fcu_prev->rna_path : "",
+ fcu_prev->array_index);
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ add_relation(prev_driver_key, driver_key, "Driver Order");
+ }
+ }
+
+ /* prevent driver from occurring before own animation... */
+ if (adt->action || adt->nla_tracks.first) {
+ add_relation(adt_key, driver_key, "AnimData Before Drivers");
+ }
+ }
}
void DepsgraphRelationBuilder::build_animation_images(ID *id)
{
- /* TODO: can we check for existance of node for performance? */
- if (BKE_image_user_id_has_animation(id)) {
- OperationKey image_animation_key(id,
- NodeType::ANIMATION,
- OperationCode::IMAGE_ANIMATION);
- TimeSourceKey time_src_key;
- add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
- }
+ /* TODO: can we check for existance of node for performance? */
+ if (BKE_image_user_id_has_animation(id)) {
+ OperationKey image_animation_key(id, NodeType::ANIMATION, OperationCode::IMAGE_ANIMATION);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, image_animation_key, "TimeSrc -> Image Animation");
+ }
}
void DepsgraphRelationBuilder::build_action(bAction *action)
{
- if (built_map_.checkIsBuiltAndTag(action)) {
- return;
- }
- TimeSourceKey time_src_key;
- ComponentKey animation_key(&action->id, NodeType::ANIMATION);
- add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
+ if (built_map_.checkIsBuiltAndTag(action)) {
+ return;
+ }
+ TimeSourceKey time_src_key;
+ ComponentKey animation_key(&action->id, NodeType::ANIMATION);
+ add_relation(time_src_key, animation_key, "TimeSrc -> Animation");
}
void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu)
{
- ChannelDriver *driver = fcu->driver;
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- /* Driver -> data components (for interleaved evaluation
- * bones/constraints/modifiers). */
- build_driver_data(id, fcu);
- /* Loop over variables to get the target relationships. */
- build_driver_variables(id, fcu);
- /* It's quite tricky to detect if the driver actually depends on time or
- * not, so for now we'll be quite conservative here about optimization and
- * consider all python drivers to be depending on time. */
- if ((driver->type == DRIVER_TYPE_PYTHON) &&
- python_driver_depends_on_time(driver))
- {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
- }
+ ChannelDriver *driver = fcu->driver;
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ /* Driver -> data components (for interleaved evaluation
+ * bones/constraints/modifiers). */
+ build_driver_data(id, fcu);
+ /* Loop over variables to get the target relationships. */
+ build_driver_variables(id, fcu);
+ /* It's quite tricky to detect if the driver actually depends on time or
+ * not, so for now we'll be quite conservative here about optimization and
+ * consider all python drivers to be depending on time. */
+ if ((driver->type == DRIVER_TYPE_PYTHON) && python_driver_depends_on_time(driver)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, driver_key, "TimeSrc -> Driver");
+ }
}
void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
{
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
- /* Drivers on armature-level bone settings (i.e. bbone stuff),
- * which will affect the evaluation of corresponding pose bones. */
- IDNode *arm_node = graph_->find_id_node(id);
- char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
- if (arm_node != NULL && bone_name != NULL) {
- /* Find objects which use this, and make their eval callbacks
- * depend on this. */
- for (Relation *rel : arm_node->outlinks) {
- IDNode *to_node = (IDNode *)rel->to;
- /* We only care about objects with pose data which use this. */
- if (GS(to_node->id_orig->name) == ID_OB) {
- Object *object = (Object *)to_node->id_orig;
- // NOTE: object->pose may be NULL
- bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose,
- bone_name);
- if (pchan != NULL) {
- OperationKey bone_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- add_relation(driver_key,
- bone_key,
- "Arm Bone -> Driver -> Bone");
- }
- }
- }
- /* Free temp data. */
- MEM_freeN(bone_name);
- bone_name = NULL;
- }
- else {
- fprintf(stderr,
- "Couldn't find armature bone name for driver path - '%s'\n",
- rna_path);
- }
- }
- else if (rna_path != NULL && rna_path[0] != '\0') {
- RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
- if (RNA_pointer_is_null(&property_entry_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. */
- return;
- }
- add_relation(
- driver_key, property_entry_key, "Driver -> Driven Property");
- /* Similar to the case with f-curves, driver might drive a nested
- * datablock, which means driver execution should wait for that
- * datablock to be copied. */
- {
- PointerRNA id_ptr;
- PointerRNA ptr;
- RNA_id_pointer_create(id, &id_ptr);
- if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
- if (id_ptr.id.data != ptr.id.data) {
- ComponentKey cow_key((ID *)ptr.id.data,
- NodeType::COPY_ON_WRITE);
- add_relation(cow_key,
- driver_key,
- "Driven CoW -> Driver",
- RELATION_CHECK_BEFORE_ADD);
- }
- }
- }
- if (property_entry_key.prop != NULL &&
- RNA_property_is_idprop(property_entry_key.prop))
- {
- RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
- OperationKey parameters_key(id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL);
- add_relation(property_exit_key,
- parameters_key,
- "Driven Property -> Properties");
- }
- }
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ if (GS(id->name) == ID_AR && strstr(rna_path, "bones[")) {
+ /* Drivers on armature-level bone settings (i.e. bbone stuff),
+ * which will affect the evaluation of corresponding pose bones. */
+ IDNode *arm_node = graph_->find_id_node(id);
+ char *bone_name = BLI_str_quoted_substrN(rna_path, "bones[");
+ if (arm_node != NULL && bone_name != NULL) {
+ /* Find objects which use this, and make their eval callbacks
+ * depend on this. */
+ for (Relation *rel : arm_node->outlinks) {
+ IDNode *to_node = (IDNode *)rel->to;
+ /* We only care about objects with pose data which use this. */
+ if (GS(to_node->id_orig->name) == ID_OB) {
+ Object *object = (Object *)to_node->id_orig;
+ // NOTE: object->pose may be NULL
+ bPoseChannel *pchan = BKE_pose_channel_find_name(object->pose, bone_name);
+ if (pchan != NULL) {
+ OperationKey bone_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ add_relation(driver_key, bone_key, "Arm Bone -> Driver -> Bone");
+ }
+ }
+ }
+ /* Free temp data. */
+ MEM_freeN(bone_name);
+ bone_name = NULL;
+ }
+ else {
+ fprintf(stderr, "Couldn't find armature bone name for driver path - '%s'\n", rna_path);
+ }
+ }
+ else if (rna_path != NULL && rna_path[0] != '\0') {
+ RNAPathKey property_entry_key(id, rna_path, RNAPointerSource::ENTRY);
+ if (RNA_pointer_is_null(&property_entry_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. */
+ return;
+ }
+ add_relation(driver_key, property_entry_key, "Driver -> Driven Property");
+ /* Similar to the case with f-curves, driver might drive a nested
+ * datablock, which means driver execution should wait for that
+ * datablock to be copied. */
+ {
+ PointerRNA id_ptr;
+ PointerRNA ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
+ if (id_ptr.id.data != ptr.id.data) {
+ ComponentKey cow_key((ID *)ptr.id.data, NodeType::COPY_ON_WRITE);
+ add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD);
+ }
+ }
+ }
+ if (property_entry_key.prop != NULL && RNA_property_is_idprop(property_entry_key.prop)) {
+ RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
+ OperationKey parameters_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
+ }
+ }
}
void DepsgraphRelationBuilder::build_driver_variables(ID *id, FCurve *fcu)
{
- ChannelDriver *driver = fcu->driver;
- OperationKey driver_key(id,
- NodeType::PARAMETERS,
- OperationCode::DRIVER,
- fcu->rna_path ? fcu->rna_path : "",
- fcu->array_index);
- const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
- const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
- LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* Only used targets. */
- DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar)
- {
- if (dtar->id == NULL) {
- continue;
- }
- build_id(dtar->id);
- build_driver_id_property(dtar->id, dtar->rna_path);
- /* Initialize relations coming to proxy_from. */
- Object *proxy_from = NULL;
- if ((GS(dtar->id->name) == ID_OB) &&
- (((Object *)dtar->id)->proxy_from != NULL))
- {
- proxy_from = ((Object *)dtar->id)->proxy_from;
- build_id(&proxy_from->id);
- }
- /* Special handling for directly-named bones. */
- if ((dtar->flag & DTAR_FLAG_STRUCT_REF) &&
- (((Object *)dtar->id)->type == OB_ARMATURE) &&
- (dtar->pchan_name[0]))
- {
- Object *object = (Object *)dtar->id;
- bPoseChannel *target_pchan =
- BKE_pose_channel_find_name(object->pose,
- dtar->pchan_name);
- if (target_pchan == NULL) {
- continue;
- }
- OperationKey variable_key(dtar->id,
- NodeType::BONE,
- target_pchan->name,
- OperationCode::BONE_DONE);
- if (is_same_bone_dependency(variable_key, self_key)) {
- continue;
- }
- add_relation(variable_key, driver_key, "Bone Target -> Driver");
- }
- else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
- /* Get node associated with the object's transforms. */
- if (dtar->id == id) {
- /* Ignore input dependency if we're driving properties of
- * the same ID, otherwise we'll be ending up in a cyclic
- * dependency here. */
- continue;
- }
- OperationKey target_key(dtar->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(target_key, driver_key, "Target -> Driver");
- }
- else if (dtar->rna_path != NULL && dtar->rna_path[0] != '\0') {
- RNAPathKey variable_exit_key(
- dtar->id, dtar->rna_path, RNAPointerSource::EXIT);
- if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
- continue;
- }
- if (is_same_bone_dependency(variable_exit_key, self_key) ||
- is_same_nodetree_node_dependency(variable_exit_key, self_key))
- {
- continue;
- }
- add_relation(variable_exit_key,
- driver_key,
- "RNA Target -> Driver");
- if (proxy_from != NULL) {
- RNAPathKey proxy_from_variable_key(&proxy_from->id,
- dtar->rna_path,
- RNAPointerSource::EXIT);
- RNAPathKey variable_entry_key(
- dtar->id, dtar->rna_path, RNAPointerSource::ENTRY);
- add_relation(proxy_from_variable_key,
- variable_entry_key,
- "Proxy From -> Variable");
- }
- }
- else {
- /* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
- * is an incomplete target reference, so nothing to do here. */
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
-}
-
-void DepsgraphRelationBuilder::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);
- OperationKey id_property_key(id,
- NodeType::PARAMETERS,
- OperationCode::ID_PROPERTY,
- prop_identifier);
- OperationKey parameters_exit_key(id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EXIT);
- add_relation(id_property_key,
- parameters_exit_key,
- "ID Property -> Done",
- RELATION_CHECK_BEFORE_ADD);
+ ChannelDriver *driver = fcu->driver;
+ OperationKey driver_key(id,
+ NodeType::PARAMETERS,
+ OperationCode::DRIVER,
+ fcu->rna_path ? fcu->rna_path : "",
+ fcu->array_index);
+ const char *rna_path = fcu->rna_path ? fcu->rna_path : "";
+ const RNAPathKey self_key(id, rna_path, RNAPointerSource::ENTRY);
+ LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
+ /* Only used targets. */
+ DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
+ if (dtar->id == NULL) {
+ continue;
+ }
+ build_id(dtar->id);
+ build_driver_id_property(dtar->id, dtar->rna_path);
+ /* Initialize relations coming to proxy_from. */
+ Object *proxy_from = NULL;
+ if ((GS(dtar->id->name) == ID_OB) && (((Object *)dtar->id)->proxy_from != NULL)) {
+ proxy_from = ((Object *)dtar->id)->proxy_from;
+ build_id(&proxy_from->id);
+ }
+ /* Special handling for directly-named bones. */
+ if ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (((Object *)dtar->id)->type == OB_ARMATURE) &&
+ (dtar->pchan_name[0])) {
+ Object *object = (Object *)dtar->id;
+ bPoseChannel *target_pchan = BKE_pose_channel_find_name(object->pose, dtar->pchan_name);
+ if (target_pchan == NULL) {
+ continue;
+ }
+ OperationKey variable_key(
+ dtar->id, NodeType::BONE, target_pchan->name, OperationCode::BONE_DONE);
+ if (is_same_bone_dependency(variable_key, self_key)) {
+ continue;
+ }
+ add_relation(variable_key, driver_key, "Bone Target -> Driver");
+ }
+ else if (dtar->flag & DTAR_FLAG_STRUCT_REF) {
+ /* Get node associated with the object's transforms. */
+ if (dtar->id == id) {
+ /* Ignore input dependency if we're driving properties of
+ * the same ID, otherwise we'll be ending up in a cyclic
+ * dependency here. */
+ continue;
+ }
+ OperationKey target_key(dtar->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(target_key, driver_key, "Target -> Driver");
+ }
+ else if (dtar->rna_path != NULL && dtar->rna_path[0] != '\0') {
+ RNAPathKey variable_exit_key(dtar->id, dtar->rna_path, RNAPointerSource::EXIT);
+ if (RNA_pointer_is_null(&variable_exit_key.ptr)) {
+ continue;
+ }
+ if (is_same_bone_dependency(variable_exit_key, self_key) ||
+ is_same_nodetree_node_dependency(variable_exit_key, self_key)) {
+ continue;
+ }
+ add_relation(variable_exit_key, driver_key, "RNA Target -> Driver");
+ if (proxy_from != NULL) {
+ RNAPathKey proxy_from_variable_key(
+ &proxy_from->id, dtar->rna_path, RNAPointerSource::EXIT);
+ RNAPathKey variable_entry_key(dtar->id, dtar->rna_path, RNAPointerSource::ENTRY);
+ add_relation(proxy_from_variable_key, variable_entry_key, "Proxy From -> Variable");
+ }
+ }
+ else {
+ /* If rna_path is NULL, and DTAR_FLAG_STRUCT_REF isn't set, this
+ * is an incomplete target reference, so nothing to do here. */
+ }
+ }
+ DRIVER_TARGETS_LOOPER_END;
+ }
+}
+
+void DepsgraphRelationBuilder::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);
+ OperationKey id_property_key(
+ id, NodeType::PARAMETERS, OperationCode::ID_PROPERTY, prop_identifier);
+ OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ add_relation(
+ id_property_key, parameters_exit_key, "ID Property -> Done", RELATION_CHECK_BEFORE_ADD);
}
void DepsgraphRelationBuilder::build_parameters(ID *id)
{
- OperationKey parameters_entry_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
- OperationKey parameters_eval_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
- OperationKey parameters_exit_key(
- id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
- add_relation(
- parameters_entry_key, parameters_eval_key, "Entry -> Eval");
- add_relation(
- parameters_eval_key, parameters_exit_key, "Entry -> Exit");
+ OperationKey parameters_entry_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_ENTRY);
+ OperationKey parameters_eval_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ OperationKey parameters_exit_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
+ add_relation(parameters_entry_key, parameters_eval_key, "Entry -> Eval");
+ add_relation(parameters_eval_key, parameters_exit_key, "Entry -> Exit");
}
void DepsgraphRelationBuilder::build_world(World *world)
{
- if (built_map_.checkIsBuiltAndTag(world)) {
- return;
- }
- /* animation */
- build_animdata(&world->id);
- build_parameters(&world->id);
- /* world's nodetree */
- if (world->nodetree != NULL) {
- build_nodetree(world->nodetree);
- OperationKey ntree_key(&world->nodetree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey world_key(&world->id,
- NodeType::SHADING,
- OperationCode::WORLD_UPDATE);
- add_relation(ntree_key, world_key, "World's NTree");
- build_nested_nodetree(&world->id, world->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(world)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&world->id);
+ build_parameters(&world->id);
+ /* world's nodetree */
+ if (world->nodetree != NULL) {
+ build_nodetree(world->nodetree);
+ OperationKey ntree_key(
+ &world->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey world_key(&world->id, NodeType::SHADING, OperationCode::WORLD_UPDATE);
+ add_relation(ntree_key, world_key, "World's NTree");
+ build_nested_nodetree(&world->id, world->nodetree);
+ }
}
void DepsgraphRelationBuilder::build_rigidbody(Scene *scene)
{
- RigidBodyWorld *rbw = scene->rigidbody_world;
- OperationKey rb_init_key(&scene->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_REBUILD);
- OperationKey rb_simulate_key(&scene->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_SIM);
- /* Simulation depends on time. */
- TimeSourceKey time_src_key;
- add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
- /* Simulation should always be run after initialization. */
- /* NOTE: It is possible in theory to have dependency cycle which involves
- * this relation. We never want it to be killed. */
- add_relation(rb_init_key,
- rb_simulate_key,
- "Rigidbody [Init -> SimStep]",
- RELATION_FLAG_GODMODE);
- /* Effectors should be evaluated at the time simulation is being
- * initialized.
- * TODO(sergey): Verify that it indeed goes to initialization and not to a
- * simulation. */
- ListBase *effector_relations =
- build_effector_relations(graph_, rbw->effector_weights->group);
- LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
- ComponentKey effector_transform_key(
- &effector_relation->ob->id, NodeType::TRANSFORM);
- add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
- if (effector_relation->pd != NULL) {
- const short shape = effector_relation->pd->shape;
- if (ELEM(shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS)) {
- ComponentKey effector_geometry_key(
- &effector_relation->ob->id, NodeType::GEOMETRY);
- add_relation(
- effector_geometry_key, rb_init_key, "RigidBody Field");
- }
- }
- }
- /* Objects. */
- if (rbw->group != NULL) {
- build_collection(NULL, NULL, rbw->group);
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
- {
- if (object->type != OB_MESH) {
- continue;
- }
- OperationKey rb_transform_copy_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- /* Rigid body synchronization depends on the actual simulation. */
- add_relation(rb_simulate_key,
- rb_transform_copy_key,
- "Rigidbody Sim Eval -> RBO Sync");
- /* Simulation uses object transformation after parenting and solving
- * contraints. */
- OperationKey object_transform_simulation_init_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_SIMULATION_INIT);
- OperationKey object_transform_eval_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- add_relation(object_transform_simulation_init_key,
- rb_simulate_key,
- "Object Transform -> Rigidbody Sim Eval");
- /* Geometry must be known to create the rigid body. RBO_MESH_BASE
- * uses the non-evaluated mesh, so then the evaluation is
- * unnecessary. */
- if (object->rigidbody_object != NULL &&
- object->rigidbody_object->mesh_source != RBO_MESH_BASE)
- {
- /* NOTE: We prefer this relation to be never killed, to avoid
- * access partially evaluated mesh from solver. */
- ComponentKey object_geometry_key(
- &object->id, NodeType::GEOMETRY);
- add_relation(object_geometry_key,
- rb_simulate_key,
- "Object Geom Eval -> Rigidbody Rebuild",
- RELATION_FLAG_GODMODE);
- }
- /* Final transform is whetever solver gave to us. */
- OperationKey object_transform_final_key(
- &object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_FINAL);
- add_relation(rb_transform_copy_key,
- object_transform_final_key,
- "Rigidbody Sync -> Transform Final");
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
- /* Constraints. */
- if (rbw->constraints != NULL) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
- {
- RigidBodyCon *rbc = object->rigidbody_constraint;
- if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
- /* When either ob1 or ob2 is NULL, the constraint doesn't
- * work. */
- continue;
- }
- /* Make sure indirectly linked objects are fully built. */
- build_object(NULL, object);
- build_object(NULL, rbc->ob1);
- build_object(NULL, rbc->ob2);
- /* final result of the constraint object's transform controls how
- * the constraint affects the physics sim for these objects. */
- ComponentKey trans_key(&object->id, NodeType::TRANSFORM);
- OperationKey ob1_key(&rbc->ob1->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- OperationKey ob2_key(&rbc->ob2->id,
- NodeType::TRANSFORM,
- OperationCode::RIGIDBODY_TRANSFORM_COPY);
- /* Constrained-objects sync depends on the constraint-holder. */
- add_relation(
- trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
- add_relation(
- trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
- /* Ensure that sim depends on this constraint's transform. */
- add_relation(trans_key,
- rb_simulate_key,
- "RigidBodyConstraint Transform -> RB Simulation");
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
+ RigidBodyWorld *rbw = scene->rigidbody_world;
+ OperationKey rb_init_key(&scene->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_REBUILD);
+ OperationKey rb_simulate_key(&scene->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_SIM);
+ /* Simulation depends on time. */
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, rb_init_key, "TimeSrc -> Rigidbody Init");
+ /* Simulation should always be run after initialization. */
+ /* NOTE: It is possible in theory to have dependency cycle which involves
+ * this relation. We never want it to be killed. */
+ add_relation(rb_init_key, rb_simulate_key, "Rigidbody [Init -> SimStep]", RELATION_FLAG_GODMODE);
+ /* Effectors should be evaluated at the time simulation is being
+ * initialized.
+ * TODO(sergey): Verify that it indeed goes to initialization and not to a
+ * simulation. */
+ ListBase *effector_relations = build_effector_relations(graph_, rbw->effector_weights->group);
+ LISTBASE_FOREACH (EffectorRelation *, effector_relation, effector_relations) {
+ ComponentKey effector_transform_key(&effector_relation->ob->id, NodeType::TRANSFORM);
+ add_relation(effector_transform_key, rb_init_key, "RigidBody Field");
+ if (effector_relation->pd != NULL) {
+ const short shape = effector_relation->pd->shape;
+ if (ELEM(shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS)) {
+ ComponentKey effector_geometry_key(&effector_relation->ob->id, NodeType::GEOMETRY);
+ add_relation(effector_geometry_key, rb_init_key, "RigidBody Field");
+ }
+ }
+ }
+ /* Objects. */
+ if (rbw->group != NULL) {
+ build_collection(NULL, NULL, rbw->group);
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->group, object) {
+ if (object->type != OB_MESH) {
+ continue;
+ }
+ OperationKey rb_transform_copy_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ /* Rigid body synchronization depends on the actual simulation. */
+ add_relation(rb_simulate_key, rb_transform_copy_key, "Rigidbody Sim Eval -> RBO Sync");
+ /* Simulation uses object transformation after parenting and solving
+ * contraints. */
+ OperationKey object_transform_simulation_init_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_SIMULATION_INIT);
+ OperationKey object_transform_eval_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ add_relation(object_transform_simulation_init_key,
+ rb_simulate_key,
+ "Object Transform -> Rigidbody Sim Eval");
+ /* Geometry must be known to create the rigid body. RBO_MESH_BASE
+ * uses the non-evaluated mesh, so then the evaluation is
+ * unnecessary. */
+ if (object->rigidbody_object != NULL &&
+ object->rigidbody_object->mesh_source != RBO_MESH_BASE) {
+ /* NOTE: We prefer this relation to be never killed, to avoid
+ * access partially evaluated mesh from solver. */
+ ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
+ add_relation(object_geometry_key,
+ rb_simulate_key,
+ "Object Geom Eval -> Rigidbody Rebuild",
+ RELATION_FLAG_GODMODE);
+ }
+ /* Final transform is whetever solver gave to us. */
+ OperationKey object_transform_final_key(
+ &object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
+ add_relation(
+ rb_transform_copy_key, object_transform_final_key, "Rigidbody Sync -> Transform Final");
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
+ /* Constraints. */
+ if (rbw->constraints != NULL) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->constraints, object) {
+ RigidBodyCon *rbc = object->rigidbody_constraint;
+ if (rbc == NULL || rbc->ob1 == NULL || rbc->ob2 == NULL) {
+ /* When either ob1 or ob2 is NULL, the constraint doesn't
+ * work. */
+ continue;
+ }
+ /* Make sure indirectly linked objects are fully built. */
+ build_object(NULL, object);
+ build_object(NULL, rbc->ob1);
+ build_object(NULL, rbc->ob2);
+ /* final result of the constraint object's transform controls how
+ * the constraint affects the physics sim for these objects. */
+ ComponentKey trans_key(&object->id, NodeType::TRANSFORM);
+ OperationKey ob1_key(
+ &rbc->ob1->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ OperationKey ob2_key(
+ &rbc->ob2->id, NodeType::TRANSFORM, OperationCode::RIGIDBODY_TRANSFORM_COPY);
+ /* Constrained-objects sync depends on the constraint-holder. */
+ add_relation(trans_key, ob1_key, "RigidBodyConstraint -> RBC.Object_1");
+ add_relation(trans_key, ob2_key, "RigidBodyConstraint -> RBC.Object_2");
+ /* Ensure that sim depends on this constraint's transform. */
+ add_relation(trans_key, rb_simulate_key, "RigidBodyConstraint Transform -> RB Simulation");
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
}
void DepsgraphRelationBuilder::build_particle_systems(Object *object)
{
- TimeSourceKey time_src_key;
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- OperationKey eval_init_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_INIT);
- OperationKey eval_done_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_DONE);
- ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
- if (BKE_ptcache_object_has(scene_, object, 0)) {
- ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
- add_relation(eval_key,
- point_cache_key,
- "Particle Point Cache",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- }
- /* Particle systems. */
- LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
- ParticleSettings *part = psys->part;
- /* Build particle settings relations.
- * NOTE: The call itself ensures settings are only build once. */
- build_particle_settings(part);
- /* This particle system. */
- OperationKey psys_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- psys->name);
- /* Update particle system when settings changes. */
- OperationKey particle_settings_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_EVAL);
- add_relation(particle_settings_key,
- eval_init_key,
- "Particle Settings Change");
- add_relation(eval_init_key, psys_key, "Init -> PSys");
- add_relation(psys_key, eval_done_key, "PSys -> Done");
- /* 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. */
- if (part->type != PART_HAIR) {
- add_particle_collision_relations(psys_key,
- object,
- part->collision_group,
- "Particle Collision");
- }
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) &&
- psys->clmd != NULL &&
- psys->clmd->coll_parms != NULL)
- {
- add_particle_collision_relations(psys_key,
- object,
- psys->clmd->coll_parms->group,
- "Hair Collision");
- }
- /* Effectors. */
- add_particle_forcefield_relations(psys_key,
- object,
- psys,
- part->effector_weights,
- part->type == PART_HAIR,
- "Particle Field");
- /* Boids .*/
- if (part->boids != NULL) {
- LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
- LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid) {
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- }
- else if (rule->type == eBoidRuleType_FollowLeader) {
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
- }
- if (ruleob != NULL) {
- ComponentKey ruleob_key(&ruleob->id,
- NodeType::TRANSFORM);
- add_relation(ruleob_key, psys_key, "Boid Rule");
- }
- }
- }
- }
- /* Keyed particle targets. */
- if (part->phystype == PART_PHYS_KEYED) {
- LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
- if (particle_target->ob == NULL ||
- particle_target->ob == object)
- {
- continue;
- }
- /* Make sure target object is pulled into the graph. */
- build_object(NULL, particle_target->ob);
- /* Use geometry component, since that's where particles are
- * actually evaluated. */
- ComponentKey target_key(&particle_target->ob->id,
- NodeType::GEOMETRY);
- add_relation(target_key, psys_key, "Keyed Target");
- }
- }
- /* Visualization. */
- switch (part->ren_as) {
- case PART_DRAW_OB:
- if (part->instance_object != NULL) {
- /* Make sure object's relations are all built. */
- build_object(NULL, part->instance_object);
- /* Build relation for the particle visualization. */
- build_particle_system_visualization_object(
- object, psys, part->instance_object);
- }
- break;
- case PART_DRAW_GR:
- if (part->instance_collection != NULL) {
- build_collection(NULL, NULL, part->instance_collection);
- LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
- build_particle_system_visualization_object(
- object, psys, go->ob);
- }
- }
- break;
- }
- }
- /* Particle depends on the object transform, so that channel is to be ready
- * first. */
- add_depends_on_transform_relation(
- &object->id, obdata_ubereval_key, "Particle Eval");
+ TimeSourceKey time_src_key;
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey eval_init_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_INIT);
+ OperationKey eval_done_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_DONE);
+ ComponentKey eval_key(&object->id, NodeType::PARTICLE_SYSTEM);
+ if (BKE_ptcache_object_has(scene_, object, 0)) {
+ ComponentKey point_cache_key(&object->id, NodeType::POINT_CACHE);
+ add_relation(
+ eval_key, point_cache_key, "Particle Point Cache", RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ }
+ /* Particle systems. */
+ LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
+ ParticleSettings *part = psys->part;
+ /* Build particle settings relations.
+ * NOTE: The call itself ensures settings are only build once. */
+ build_particle_settings(part);
+ /* This particle system. */
+ OperationKey psys_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name);
+ /* Update particle system when settings changes. */
+ OperationKey particle_settings_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL);
+ add_relation(particle_settings_key, eval_init_key, "Particle Settings Change");
+ add_relation(eval_init_key, psys_key, "Init -> PSys");
+ add_relation(psys_key, eval_done_key, "PSys -> Done");
+ /* 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. */
+ if (part->type != PART_HAIR) {
+ add_particle_collision_relations(
+ psys_key, object, part->collision_group, "Particle Collision");
+ }
+ else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd != NULL &&
+ psys->clmd->coll_parms != NULL) {
+ add_particle_collision_relations(
+ psys_key, object, psys->clmd->coll_parms->group, "Hair Collision");
+ }
+ /* Effectors. */
+ add_particle_forcefield_relations(
+ psys_key, object, psys, part->effector_weights, part->type == PART_HAIR, "Particle Field");
+ /* Boids .*/
+ if (part->boids != NULL) {
+ LISTBASE_FOREACH (BoidState *, state, &part->boids->states) {
+ LISTBASE_FOREACH (BoidRule *, rule, &state->rules) {
+ Object *ruleob = NULL;
+ if (rule->type == eBoidRuleType_Avoid) {
+ ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
+ }
+ else if (rule->type == eBoidRuleType_FollowLeader) {
+ ruleob = ((BoidRuleFollowLeader *)rule)->ob;
+ }
+ if (ruleob != NULL) {
+ ComponentKey ruleob_key(&ruleob->id, NodeType::TRANSFORM);
+ add_relation(ruleob_key, psys_key, "Boid Rule");
+ }
+ }
+ }
+ }
+ /* Keyed particle targets. */
+ if (part->phystype == PART_PHYS_KEYED) {
+ LISTBASE_FOREACH (ParticleTarget *, particle_target, &psys->targets) {
+ if (particle_target->ob == NULL || particle_target->ob == object) {
+ continue;
+ }
+ /* Make sure target object is pulled into the graph. */
+ build_object(NULL, particle_target->ob);
+ /* Use geometry component, since that's where particles are
+ * actually evaluated. */
+ ComponentKey target_key(&particle_target->ob->id, NodeType::GEOMETRY);
+ add_relation(target_key, psys_key, "Keyed Target");
+ }
+ }
+ /* Visualization. */
+ switch (part->ren_as) {
+ case PART_DRAW_OB:
+ if (part->instance_object != NULL) {
+ /* Make sure object's relations are all built. */
+ build_object(NULL, part->instance_object);
+ /* Build relation for the particle visualization. */
+ build_particle_system_visualization_object(object, psys, part->instance_object);
+ }
+ break;
+ case PART_DRAW_GR:
+ if (part->instance_collection != NULL) {
+ build_collection(NULL, NULL, part->instance_collection);
+ LISTBASE_FOREACH (CollectionObject *, go, &part->instance_collection->gobject) {
+ build_particle_system_visualization_object(object, psys, go->ob);
+ }
+ }
+ break;
+ }
+ }
+ /* Particle depends on the object transform, so that channel is to be ready
+ * first. */
+ add_depends_on_transform_relation(&object->id, obdata_ubereval_key, "Particle Eval");
}
void DepsgraphRelationBuilder::build_particle_settings(ParticleSettings *part)
{
- if (built_map_.checkIsBuiltAndTag(part)) {
- return;
- }
- /* Animation data relations. */
- build_animdata(&part->id);
- build_parameters(&part->id);
- OperationKey particle_settings_init_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_INIT);
- OperationKey particle_settings_eval_key(&part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_EVAL);
- OperationKey particle_settings_reset_key(
- &part->id,
- NodeType::PARTICLE_SETTINGS,
- OperationCode::PARTICLE_SETTINGS_RESET);
- add_relation(particle_settings_init_key,
- particle_settings_eval_key,
- "Particle Settings Init Order");
- add_relation(particle_settings_reset_key,
- particle_settings_eval_key,
- "Particle Settings Reset");
- /* Texture slots. */
- for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
- MTex *mtex = part->mtex[mtex_index];
- if (mtex == NULL || mtex->tex == NULL) {
- continue;
- }
- build_texture(mtex->tex);
- ComponentKey texture_key(&mtex->tex->id,
- NodeType::GENERIC_DATABLOCK);
- add_relation(texture_key,
- particle_settings_reset_key,
- "Particle Texture",
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
- /* TODO(sergey): Consider moving texture space handling to an own
- * function. */
- if (mtex->texco == TEXCO_OBJECT && mtex->object != NULL) {
- ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
- add_relation(object_key,
- particle_settings_eval_key,
- "Particle Texture Space");
- }
- }
- if (check_id_has_anim_component(&part->id)) {
- ComponentKey animation_key(&part->id, NodeType::ANIMATION);
- add_relation(animation_key,
- particle_settings_eval_key,
- "Particle Settings Animation");
- }
-}
-
-void DepsgraphRelationBuilder::build_particle_system_visualization_object(
- Object *object,
- ParticleSystem *psys,
- Object *draw_object)
-{
- OperationKey psys_key(&object->id,
- NodeType::PARTICLE_SYSTEM,
- OperationCode::PARTICLE_SYSTEM_EVAL,
- psys->name);
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
- add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
- if (draw_object->type == OB_MBALL) {
- ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
- add_relation(obdata_ubereval_key,
- dup_geometry_key,
- "Particle MBall Visualization");
- }
+ if (built_map_.checkIsBuiltAndTag(part)) {
+ return;
+ }
+ /* Animation data relations. */
+ build_animdata(&part->id);
+ build_parameters(&part->id);
+ OperationKey particle_settings_init_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_INIT);
+ OperationKey particle_settings_eval_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_EVAL);
+ OperationKey particle_settings_reset_key(
+ &part->id, NodeType::PARTICLE_SETTINGS, OperationCode::PARTICLE_SETTINGS_RESET);
+ add_relation(
+ particle_settings_init_key, particle_settings_eval_key, "Particle Settings Init Order");
+ add_relation(particle_settings_reset_key, particle_settings_eval_key, "Particle Settings Reset");
+ /* Texture slots. */
+ for (int mtex_index = 0; mtex_index < MAX_MTEX; ++mtex_index) {
+ MTex *mtex = part->mtex[mtex_index];
+ if (mtex == NULL || mtex->tex == NULL) {
+ continue;
+ }
+ build_texture(mtex->tex);
+ ComponentKey texture_key(&mtex->tex->id, NodeType::GENERIC_DATABLOCK);
+ add_relation(texture_key,
+ particle_settings_reset_key,
+ "Particle Texture",
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY);
+ /* TODO(sergey): Consider moving texture space handling to an own
+ * function. */
+ if (mtex->texco == TEXCO_OBJECT && mtex->object != NULL) {
+ ComponentKey object_key(&mtex->object->id, NodeType::TRANSFORM);
+ add_relation(object_key, particle_settings_eval_key, "Particle Texture Space");
+ }
+ }
+ if (check_id_has_anim_component(&part->id)) {
+ ComponentKey animation_key(&part->id, NodeType::ANIMATION);
+ add_relation(animation_key, particle_settings_eval_key, "Particle Settings Animation");
+ }
+}
+
+void DepsgraphRelationBuilder::build_particle_system_visualization_object(Object *object,
+ ParticleSystem *psys,
+ Object *draw_object)
+{
+ OperationKey psys_key(
+ &object->id, NodeType::PARTICLE_SYSTEM, OperationCode::PARTICLE_SYSTEM_EVAL, psys->name);
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ ComponentKey dup_ob_key(&draw_object->id, NodeType::TRANSFORM);
+ add_relation(dup_ob_key, psys_key, "Particle Object Visualization");
+ if (draw_object->type == OB_MBALL) {
+ ComponentKey dup_geometry_key(&draw_object->id, NodeType::GEOMETRY);
+ add_relation(obdata_ubereval_key, dup_geometry_key, "Particle MBall Visualization");
+ }
}
/* Shapekeys */
void DepsgraphRelationBuilder::build_shapekeys(Key *key)
{
- if (built_map_.checkIsBuiltAndTag(key)) {
- return;
- }
- /* Attach animdata to geometry. */
- build_animdata(&key->id);
- build_parameters(&key->id);
- /* Connect all blocks properties to the final result evaluation. */
- ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
- OperationKey parameters_eval_key(&key->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL);
- LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
- OperationKey key_block_key(&key->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- key_block->name);
- add_relation(key_block_key, geometry_key, "Key Block Properties");
- add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
- }
+ if (built_map_.checkIsBuiltAndTag(key)) {
+ return;
+ }
+ /* Attach animdata to geometry. */
+ build_animdata(&key->id);
+ build_parameters(&key->id);
+ /* Connect all blocks properties to the final result evaluation. */
+ ComponentKey geometry_key(&key->id, NodeType::GEOMETRY);
+ OperationKey parameters_eval_key(&key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
+ LISTBASE_FOREACH (KeyBlock *, key_block, &key->block) {
+ OperationKey key_block_key(
+ &key->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, key_block->name);
+ add_relation(key_block_key, geometry_key, "Key Block Properties");
+ add_relation(key_block_key, parameters_eval_key, "Key Block Properties");
+ }
}
/**
@@ -2092,535 +1827,475 @@ void DepsgraphRelationBuilder::build_shapekeys(Key *key)
* downstream re-evaluation of the individual instances of this geometry. */
void DepsgraphRelationBuilder::build_object_data_geometry(Object *object)
{
- ID *obdata = (ID *)object->data;
- /* Init operation of object-level geometry evaluation. */
- OperationKey geom_init_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_INIT);
- /* Get nodes for result of obdata's evaluation, and geometry evaluation
- * on object. */
- ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
- ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
- /* Link components to each other. */
- add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- /* Special case: modifiers evaluation queries scene for various things like
- * data mask to be used. We add relation here to ensure object is never
- * evaluated prior to Scene's CoW is ready. */
- OperationKey scene_key(&scene_->id,
- NodeType::LAYER_COLLECTIONS,
- OperationCode::VIEW_LAYER_EVAL);
- Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
- rel->flag |= RELATION_FLAG_NO_FLUSH;
- /* Modifiers */
- if (object->modifiers.first != NULL) {
- 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);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- mti->updateDepsgraph(md, &ctx);
- }
- if (BKE_object_modifier_use_time(object, md)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Grease Pencil Modifiers. */
- if (object->greasepencil_modifiers.first != NULL) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) {
- const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo((GpencilModifierType)md->type);
- if (mti->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- mti->updateDepsgraph(md, &ctx);
- }
- if (BKE_object_modifier_gpencil_use_time(object, md)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Shader FX. */
- if (object->shader_fx.first != NULL) {
- ModifierUpdateDepsgraphContext ctx = {};
- ctx.scene = scene_;
- ctx.object = object;
- LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
- const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type);
- if (fxi->updateDepsgraph) {
- DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
- ctx.node = reinterpret_cast< ::DepsNodeHandle* >(&handle);
- fxi->updateDepsgraph(fx, &ctx);
- }
- if (BKE_object_shaderfx_use_time(object, fx)) {
- TimeSourceKey time_src_key;
- add_relation(time_src_key, obdata_ubereval_key, "Time Source");
- }
- }
- }
- /* Materials. */
- if (object->totcol) {
- for (int a = 1; a <= object->totcol; a++) {
- Material *ma = give_current_material(object, a);
- if (ma != NULL) {
- build_material(ma);
-
- if (object->type == OB_MESH) {
- OperationKey material_key(&ma->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey shading_key(&object->id,
- NodeType::SHADING,
- OperationCode::SHADING);
- add_relation(material_key, shading_key, "Material Update");
- }
- }
- }
- }
- /* Geometry collision. */
- if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
- // add geometry collider relations
- }
- /* Make sure uber update is the last in the dependencies. */
- if (object->type != OB_ARMATURE) {
- /* Armatures does no longer require uber node. */
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(geom_init_key,
- obdata_ubereval_key,
- "Object Geometry UberEval");
- if (object->totcol != 0 && object->type == OB_MESH) {
- ComponentKey object_shading_key(&object->id, NodeType::SHADING);
- Relation *rel = add_relation(obdata_ubereval_key,
- object_shading_key,
- "Object Geometry batch Update");
- rel->flag |= RELATION_FLAG_NO_FLUSH;
- }
- }
- if (object->type == OB_MBALL) {
- Object *mom = BKE_mball_basis_find(scene_, object);
- ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
- /* motherball - mom depends on children! */
- if (mom == object) {
- ComponentKey mom_transform_key(&mom->id,
- NodeType::TRANSFORM);
- add_relation(mom_transform_key,
- mom_geom_key,
- "Metaball Motherball Transform -> Geometry");
- }
- else {
- ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(geom_key, mom_geom_key, "Metaball Motherball");
- add_relation(transform_key, mom_geom_key, "Metaball Motherball");
- }
- }
- /* NOTE: This is compatibility code to support particle systems
- *
- * for viewport being properly rendered in final render mode.
- * This relation is similar to what dag_object_time_update_flags()
- * was doing for mesh objects with particle system.
- *
- * Ideally we need to get rid of this relation. */
- if (object_particles_depends_on_time(object)) {
- TimeSourceKey time_key;
- OperationKey obdata_ubereval_key(&object->id,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL);
- add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
- }
- /* Object data datablock. */
- build_object_data_geometry_datablock((ID *)object->data);
- Key *key = BKE_key_from_object(object);
- if (key != NULL) {
- if (key->adt != NULL) {
- if (key->adt->action || key->adt->nla_tracks.first) {
- ComponentKey obdata_key((ID *)object->data,
- NodeType::GEOMETRY);
- ComponentKey adt_key(&key->id, NodeType::ANIMATION);
- add_relation(adt_key, obdata_key, "Animation");
- }
- }
- }
- /* Syncronization back to original object. */
- ComponentKey final_geometry_jey(&object->id, NodeType::GEOMETRY);
- OperationKey synchronize_key(&object->id,
- NodeType::SYNCHRONIZATION,
- OperationCode::SYNCHRONIZE_TO_ORIGINAL);
- add_relation(
- final_geometry_jey, synchronize_key, "Synchronize to Original");
+ ID *obdata = (ID *)object->data;
+ /* Init operation of object-level geometry evaluation. */
+ OperationKey geom_init_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_INIT);
+ /* Get nodes for result of obdata's evaluation, and geometry evaluation
+ * on object. */
+ ComponentKey obdata_geom_key(obdata, NodeType::GEOMETRY);
+ ComponentKey geom_key(&object->id, NodeType::GEOMETRY);
+ /* Link components to each other. */
+ add_relation(obdata_geom_key, geom_key, "Object Geometry Base Data");
+ OperationKey obdata_ubereval_key(&object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ /* Special case: modifiers evaluation queries scene for various things like
+ * data mask to be used. We add relation here to ensure object is never
+ * evaluated prior to Scene's CoW is ready. */
+ OperationKey scene_key(&scene_->id, NodeType::LAYER_COLLECTIONS, OperationCode::VIEW_LAYER_EVAL);
+ Relation *rel = add_relation(scene_key, obdata_ubereval_key, "CoW Relation");
+ rel->flag |= RELATION_FLAG_NO_FLUSH;
+ /* Modifiers */
+ if (object->modifiers.first != NULL) {
+ 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);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ mti->updateDepsgraph(md, &ctx);
+ }
+ if (BKE_object_modifier_use_time(object, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Grease Pencil Modifiers. */
+ if (object->greasepencil_modifiers.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) {
+ const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(
+ (GpencilModifierType)md->type);
+ if (mti->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ mti->updateDepsgraph(md, &ctx);
+ }
+ if (BKE_object_modifier_gpencil_use_time(object, md)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Shader FX. */
+ if (object->shader_fx.first != NULL) {
+ ModifierUpdateDepsgraphContext ctx = {};
+ ctx.scene = scene_;
+ ctx.object = object;
+ LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) {
+ const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type);
+ if (fxi->updateDepsgraph) {
+ DepsNodeHandle handle = create_node_handle(obdata_ubereval_key);
+ ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle);
+ fxi->updateDepsgraph(fx, &ctx);
+ }
+ if (BKE_object_shaderfx_use_time(object, fx)) {
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, obdata_ubereval_key, "Time Source");
+ }
+ }
+ }
+ /* Materials. */
+ if (object->totcol) {
+ for (int a = 1; a <= object->totcol; a++) {
+ Material *ma = give_current_material(object, a);
+ if (ma != NULL) {
+ build_material(ma);
+
+ if (object->type == OB_MESH) {
+ OperationKey material_key(&ma->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey shading_key(&object->id, NodeType::SHADING, OperationCode::SHADING);
+ add_relation(material_key, shading_key, "Material Update");
+ }
+ }
+ }
+ }
+ /* Geometry collision. */
+ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) {
+ // add geometry collider relations
+ }
+ /* Make sure uber update is the last in the dependencies. */
+ if (object->type != OB_ARMATURE) {
+ /* Armatures does no longer require uber node. */
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(geom_init_key, obdata_ubereval_key, "Object Geometry UberEval");
+ if (object->totcol != 0 && object->type == OB_MESH) {
+ ComponentKey object_shading_key(&object->id, NodeType::SHADING);
+ Relation *rel = add_relation(
+ obdata_ubereval_key, object_shading_key, "Object Geometry batch Update");
+ rel->flag |= RELATION_FLAG_NO_FLUSH;
+ }
+ }
+ if (object->type == OB_MBALL) {
+ Object *mom = BKE_mball_basis_find(scene_, object);
+ ComponentKey mom_geom_key(&mom->id, NodeType::GEOMETRY);
+ /* motherball - mom depends on children! */
+ if (mom == object) {
+ ComponentKey mom_transform_key(&mom->id, NodeType::TRANSFORM);
+ add_relation(mom_transform_key, mom_geom_key, "Metaball Motherball Transform -> Geometry");
+ }
+ else {
+ ComponentKey transform_key(&object->id, NodeType::TRANSFORM);
+ add_relation(geom_key, mom_geom_key, "Metaball Motherball");
+ add_relation(transform_key, mom_geom_key, "Metaball Motherball");
+ }
+ }
+ /* NOTE: This is compatibility code to support particle systems
+ *
+ * for viewport being properly rendered in final render mode.
+ * This relation is similar to what dag_object_time_update_flags()
+ * was doing for mesh objects with particle system.
+ *
+ * Ideally we need to get rid of this relation. */
+ if (object_particles_depends_on_time(object)) {
+ TimeSourceKey time_key;
+ OperationKey obdata_ubereval_key(
+ &object->id, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ add_relation(time_key, obdata_ubereval_key, "Legacy particle time");
+ }
+ /* Object data datablock. */
+ build_object_data_geometry_datablock((ID *)object->data);
+ Key *key = BKE_key_from_object(object);
+ if (key != NULL) {
+ if (key->adt != NULL) {
+ if (key->adt->action || key->adt->nla_tracks.first) {
+ ComponentKey obdata_key((ID *)object->data, NodeType::GEOMETRY);
+ ComponentKey adt_key(&key->id, NodeType::ANIMATION);
+ add_relation(adt_key, obdata_key, "Animation");
+ }
+ }
+ }
+ /* Syncronization back to original object. */
+ ComponentKey final_geometry_jey(&object->id, NodeType::GEOMETRY);
+ OperationKey synchronize_key(
+ &object->id, NodeType::SYNCHRONIZATION, OperationCode::SYNCHRONIZE_TO_ORIGINAL);
+ add_relation(final_geometry_jey, synchronize_key, "Synchronize to Original");
}
void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
{
- if (built_map_.checkIsBuiltAndTag(obdata)) {
- return;
- }
- /* Animation. */
- build_animdata(obdata);
- build_parameters(obdata);
- /* ShapeKeys. */
- Key *key = BKE_key_from_id(obdata);
- if (key != NULL) {
- build_shapekeys(key);
- }
- /* Link object data evaluation node to exit operation. */
- OperationKey obdata_geom_eval_key(
- obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
- OperationKey obdata_geom_done_key(obdata,
- NodeType::GEOMETRY,
- OperationCode::GEOMETRY_EVAL_DONE);
- add_relation(obdata_geom_eval_key,
- obdata_geom_done_key,
- "ObData Geom Eval Done");
- /* Type-specific links. */
- const ID_Type id_type = GS(obdata->name);
- switch (id_type) {
- case ID_ME:
- break;
- case ID_MB:
- break;
- case ID_CU:
- {
- Curve *cu = (Curve *)obdata;
- if (cu->bevobj != NULL) {
- ComponentKey bevob_geom_key(
- &cu->bevobj->id,
- NodeType::GEOMETRY);
- add_relation(
- bevob_geom_key,
- obdata_geom_eval_key,
- "Curve Bevel Geometry");
- ComponentKey bevob_key(
- &cu->bevobj->id,
- NodeType::TRANSFORM);
- add_relation(
- bevob_key,
- obdata_geom_eval_key,
- "Curve Bevel Transform");
- build_object(NULL, cu->bevobj);
- }
- if (cu->taperobj != NULL) {
- ComponentKey taperob_key(
- &cu->taperobj->id,
- NodeType::GEOMETRY);
- add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
- build_object(NULL, cu->taperobj);
- }
- if (cu->textoncurve != NULL) {
- ComponentKey textoncurve_key(
- &cu->textoncurve->id,
- NodeType::GEOMETRY);
- add_relation(
- textoncurve_key,
- obdata_geom_eval_key,
- "Text on Curve");
- build_object(NULL, cu->textoncurve);
- }
- break;
- }
- case ID_LT:
- break;
- case ID_GD: /* Grease Pencil */
- {
- bGPdata *gpd = (bGPdata *)obdata;
-
- /* Geometry cache needs to be recalculated on frame change
- * (e.g. to fix crashes after scrubbing the timeline when
- * onion skinning is enabled, since the ghosts need to be
- * re-added to the cache once scrubbing ends). */
- TimeSourceKey time_key;
- ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
- add_relation(time_key,
- geometry_key,
- "GP Frame Change");
-
- /* Geometry cache also needs to be recalculated when Material
- * settings change (e.g. when fill.opacity changes on/off,
- * we need to rebuild the bGPDstroke->triangles caches). */
- for (int i = 0; i < gpd->totcol; i++) {
- Material *ma = gpd->mat[i];
- if ((ma != NULL) && (ma->gp_style != NULL)) {
- OperationKey material_key(&ma->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- add_relation(material_key,
- geometry_key,
- "Material -> GP Data");
- }
- }
- break;
- }
- default:
- BLI_assert(!"Should not happen");
- break;
- }
+ if (built_map_.checkIsBuiltAndTag(obdata)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(obdata);
+ build_parameters(obdata);
+ /* ShapeKeys. */
+ Key *key = BKE_key_from_id(obdata);
+ if (key != NULL) {
+ build_shapekeys(key);
+ }
+ /* Link object data evaluation node to exit operation. */
+ OperationKey obdata_geom_eval_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
+ OperationKey obdata_geom_done_key(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL_DONE);
+ add_relation(obdata_geom_eval_key, obdata_geom_done_key, "ObData Geom Eval Done");
+ /* Type-specific links. */
+ const ID_Type id_type = GS(obdata->name);
+ switch (id_type) {
+ case ID_ME:
+ break;
+ case ID_MB:
+ break;
+ case ID_CU: {
+ Curve *cu = (Curve *)obdata;
+ if (cu->bevobj != NULL) {
+ ComponentKey bevob_geom_key(&cu->bevobj->id, NodeType::GEOMETRY);
+ add_relation(bevob_geom_key, obdata_geom_eval_key, "Curve Bevel Geometry");
+ ComponentKey bevob_key(&cu->bevobj->id, NodeType::TRANSFORM);
+ add_relation(bevob_key, obdata_geom_eval_key, "Curve Bevel Transform");
+ build_object(NULL, cu->bevobj);
+ }
+ if (cu->taperobj != NULL) {
+ ComponentKey taperob_key(&cu->taperobj->id, NodeType::GEOMETRY);
+ add_relation(taperob_key, obdata_geom_eval_key, "Curve Taper");
+ build_object(NULL, cu->taperobj);
+ }
+ if (cu->textoncurve != NULL) {
+ ComponentKey textoncurve_key(&cu->textoncurve->id, NodeType::GEOMETRY);
+ add_relation(textoncurve_key, obdata_geom_eval_key, "Text on Curve");
+ build_object(NULL, cu->textoncurve);
+ }
+ break;
+ }
+ case ID_LT:
+ break;
+ case ID_GD: /* Grease Pencil */
+ {
+ bGPdata *gpd = (bGPdata *)obdata;
+
+ /* Geometry cache needs to be recalculated on frame change
+ * (e.g. to fix crashes after scrubbing the timeline when
+ * onion skinning is enabled, since the ghosts need to be
+ * re-added to the cache once scrubbing ends). */
+ TimeSourceKey time_key;
+ ComponentKey geometry_key(obdata, NodeType::GEOMETRY);
+ add_relation(time_key, geometry_key, "GP Frame Change");
+
+ /* Geometry cache also needs to be recalculated when Material
+ * settings change (e.g. when fill.opacity changes on/off,
+ * we need to rebuild the bGPDstroke->triangles caches). */
+ for (int i = 0; i < gpd->totcol; i++) {
+ Material *ma = gpd->mat[i];
+ if ((ma != NULL) && (ma->gp_style != NULL)) {
+ OperationKey material_key(&ma->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ add_relation(material_key, geometry_key, "Material -> GP Data");
+ }
+ }
+ break;
+ }
+ default:
+ BLI_assert(!"Should not happen");
+ break;
+ }
}
void DepsgraphRelationBuilder::build_armature(bArmature *armature)
{
- if (built_map_.checkIsBuiltAndTag(armature)) {
- return;
- }
- build_animdata(&armature->id);
- build_parameters(&armature->id);
+ if (built_map_.checkIsBuiltAndTag(armature)) {
+ return;
+ }
+ build_animdata(&armature->id);
+ build_parameters(&armature->id);
}
void DepsgraphRelationBuilder::build_camera(Camera *camera)
{
- if (built_map_.checkIsBuiltAndTag(camera)) {
- return;
- }
- build_parameters(&camera->id);
- if (camera->dof_ob != NULL) {
- ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
- ComponentKey dof_ob_key(&camera->dof_ob->id, NodeType::TRANSFORM);
- add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
- }
+ if (built_map_.checkIsBuiltAndTag(camera)) {
+ return;
+ }
+ build_parameters(&camera->id);
+ if (camera->dof_ob != NULL) {
+ ComponentKey camera_parameters_key(&camera->id, NodeType::PARAMETERS);
+ ComponentKey dof_ob_key(&camera->dof_ob->id, NodeType::TRANSFORM);
+ add_relation(dof_ob_key, camera_parameters_key, "Camera DOF");
+ }
}
/* Lights */
void DepsgraphRelationBuilder::build_light(Light *lamp)
{
- if (built_map_.checkIsBuiltAndTag(lamp)) {
- return;
- }
- build_parameters(&lamp->id);
- /* light's nodetree */
- if (lamp->nodetree != NULL) {
- build_nodetree(lamp->nodetree);
- ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
- ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
- add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
- build_nested_nodetree(&lamp->id, lamp->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(lamp)) {
+ return;
+ }
+ build_parameters(&lamp->id);
+ /* light's nodetree */
+ if (lamp->nodetree != NULL) {
+ build_nodetree(lamp->nodetree);
+ ComponentKey lamp_parameters_key(&lamp->id, NodeType::PARAMETERS);
+ ComponentKey nodetree_key(&lamp->nodetree->id, NodeType::SHADING);
+ add_relation(nodetree_key, lamp_parameters_key, "NTree->Light Parameters");
+ build_nested_nodetree(&lamp->id, lamp->nodetree);
+ }
}
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
{
- if (ntree == NULL) {
- return;
- }
- if (built_map_.checkIsBuiltAndTag(ntree)) {
- return;
- }
- build_animdata(&ntree->id);
- build_parameters(&ntree->id);
- ComponentKey shading_key(&ntree->id, NodeType::SHADING);
- /* nodetree's nodes... */
- LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
- ID *id = bnode->id;
- if (id == NULL) {
- continue;
- }
- ID_Type id_type = GS(id->name);
- if (id_type == ID_MA) {
- build_material((Material *)bnode->id);
- }
- else if (id_type == ID_TE) {
- build_texture((Tex *)bnode->id);
- }
- else if (id_type == ID_IM) {
- build_image((Image *)bnode->id);
- }
- else if (id_type == ID_OB) {
- build_object(NULL, (Object *)id);
- }
- else if (id_type == ID_SCE) {
- /* Scenes are used by compositor trees, and handled by render
- * pipeline. No need to build dependencies for them here. */
- }
- else if (id_type == ID_TXT) {
- /* Ignore script nodes. */
- }
- else if (id_type == ID_MSK) {
- build_mask((Mask *)id);
- }
- else if (id_type == ID_MC) {
- build_movieclip((MovieClip *)id);
- }
- else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
- bNodeTree *group_ntree = (bNodeTree *)id;
- build_nodetree(group_ntree);
- ComponentKey group_shading_key(&group_ntree->id,
- NodeType::SHADING);
- add_relation(group_shading_key, shading_key, "Group Node");
- }
- else {
- BLI_assert(!"Unknown ID type used for node");
- }
- }
-
- OperationKey shading_update_key(&ntree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey shading_parameters_key(&ntree->id,
- NodeType::SHADING_PARAMETERS,
- OperationCode::MATERIAL_UPDATE);
- add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
-
- if (check_id_has_anim_component(&ntree->id)) {
- ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
- add_relation(animation_key, shading_parameters_key, "NTree Shading Parameters");
- }
- ComponentKey parameters_key(&ntree->id, NodeType::PARAMETERS);
- add_relation(parameters_key, shading_parameters_key, "NTree Shading Parameters");
+ if (ntree == NULL) {
+ return;
+ }
+ if (built_map_.checkIsBuiltAndTag(ntree)) {
+ return;
+ }
+ build_animdata(&ntree->id);
+ build_parameters(&ntree->id);
+ ComponentKey shading_key(&ntree->id, NodeType::SHADING);
+ /* nodetree's nodes... */
+ LISTBASE_FOREACH (bNode *, bnode, &ntree->nodes) {
+ ID *id = bnode->id;
+ if (id == NULL) {
+ continue;
+ }
+ ID_Type id_type = GS(id->name);
+ if (id_type == ID_MA) {
+ build_material((Material *)bnode->id);
+ }
+ else if (id_type == ID_TE) {
+ build_texture((Tex *)bnode->id);
+ }
+ else if (id_type == ID_IM) {
+ build_image((Image *)bnode->id);
+ }
+ else if (id_type == ID_OB) {
+ build_object(NULL, (Object *)id);
+ }
+ else if (id_type == ID_SCE) {
+ /* Scenes are used by compositor trees, and handled by render
+ * pipeline. No need to build dependencies for them here. */
+ }
+ else if (id_type == ID_TXT) {
+ /* Ignore script nodes. */
+ }
+ else if (id_type == ID_MSK) {
+ build_mask((Mask *)id);
+ }
+ else if (id_type == ID_MC) {
+ build_movieclip((MovieClip *)id);
+ }
+ else if (ELEM(bnode->type, NODE_GROUP, NODE_CUSTOM_GROUP)) {
+ bNodeTree *group_ntree = (bNodeTree *)id;
+ build_nodetree(group_ntree);
+ ComponentKey group_shading_key(&group_ntree->id, NodeType::SHADING);
+ add_relation(group_shading_key, shading_key, "Group Node");
+ }
+ else {
+ BLI_assert(!"Unknown ID type used for node");
+ }
+ }
+
+ OperationKey shading_update_key(&ntree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey shading_parameters_key(
+ &ntree->id, NodeType::SHADING_PARAMETERS, OperationCode::MATERIAL_UPDATE);
+ add_relation(shading_parameters_key, shading_update_key, "NTree Shading Parameters");
+
+ if (check_id_has_anim_component(&ntree->id)) {
+ ComponentKey animation_key(&ntree->id, NodeType::ANIMATION);
+ add_relation(animation_key, shading_parameters_key, "NTree Shading Parameters");
+ }
+ ComponentKey parameters_key(&ntree->id, NodeType::PARAMETERS);
+ add_relation(parameters_key, shading_parameters_key, "NTree Shading Parameters");
}
/* Recursively build graph for material */
void DepsgraphRelationBuilder::build_material(Material *material)
{
- if (built_map_.checkIsBuiltAndTag(material)) {
- return;
- }
- /* animation */
- build_animdata(&material->id);
- build_parameters(&material->id);
- /* material's nodetree */
- if (material->nodetree != NULL) {
- build_nodetree(material->nodetree);
- OperationKey ntree_key(&material->nodetree->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- OperationKey material_key(&material->id,
- NodeType::SHADING,
- OperationCode::MATERIAL_UPDATE);
- add_relation(ntree_key, material_key, "Material's NTree");
- build_nested_nodetree(&material->id, material->nodetree);
- }
+ if (built_map_.checkIsBuiltAndTag(material)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&material->id);
+ build_parameters(&material->id);
+ /* material's nodetree */
+ if (material->nodetree != NULL) {
+ build_nodetree(material->nodetree);
+ OperationKey ntree_key(
+ &material->nodetree->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ OperationKey material_key(&material->id, NodeType::SHADING, OperationCode::MATERIAL_UPDATE);
+ add_relation(ntree_key, material_key, "Material's NTree");
+ build_nested_nodetree(&material->id, material->nodetree);
+ }
}
/* Recursively build graph for texture */
void DepsgraphRelationBuilder::build_texture(Tex *texture)
{
- if (built_map_.checkIsBuiltAndTag(texture)) {
- return;
- }
- /* texture itself */
- build_animdata(&texture->id);
- build_parameters(&texture->id);
- /* texture's nodetree */
- build_nodetree(texture->nodetree);
- /* Special cases for different IDs which texture uses. */
- if (texture->type == TEX_IMAGE) {
- if (texture->ima != NULL) {
- build_image(texture->ima);
- }
- }
- build_nested_nodetree(&texture->id, texture->nodetree);
- if (check_id_has_anim_component(&texture->id)) {
- ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
- ComponentKey datablock_key(&texture->id,
- NodeType::GENERIC_DATABLOCK);
- add_relation(animation_key, datablock_key, "Datablock Animation");
- }
+ if (built_map_.checkIsBuiltAndTag(texture)) {
+ return;
+ }
+ /* texture itself */
+ build_animdata(&texture->id);
+ build_parameters(&texture->id);
+ /* texture's nodetree */
+ build_nodetree(texture->nodetree);
+ /* Special cases for different IDs which texture uses. */
+ if (texture->type == TEX_IMAGE) {
+ if (texture->ima != NULL) {
+ build_image(texture->ima);
+ }
+ }
+ build_nested_nodetree(&texture->id, texture->nodetree);
+ if (check_id_has_anim_component(&texture->id)) {
+ ComponentKey animation_key(&texture->id, NodeType::ANIMATION);
+ ComponentKey datablock_key(&texture->id, NodeType::GENERIC_DATABLOCK);
+ add_relation(animation_key, datablock_key, "Datablock Animation");
+ }
}
void DepsgraphRelationBuilder::build_image(Image *image)
{
- if (built_map_.checkIsBuiltAndTag(image)) {
- return;
- }
- build_parameters(&image->id);
+ if (built_map_.checkIsBuiltAndTag(image)) {
+ return;
+ }
+ build_parameters(&image->id);
}
void DepsgraphRelationBuilder::build_compositor(Scene *scene)
{
- /* For now, just a plain wrapper? */
- build_nodetree(scene->nodetree);
+ /* For now, just a plain wrapper? */
+ build_nodetree(scene->nodetree);
}
void DepsgraphRelationBuilder::build_gpencil(bGPdata *gpd)
{
- if (built_map_.checkIsBuiltAndTag(gpd)) {
- return;
- }
- /* animation */
- build_animdata(&gpd->id);
- build_parameters(&gpd->id);
+ if (built_map_.checkIsBuiltAndTag(gpd)) {
+ return;
+ }
+ /* animation */
+ build_animdata(&gpd->id);
+ build_parameters(&gpd->id);
- // TODO: parent object (when that feature is implemented)
+ // TODO: parent object (when that feature is implemented)
}
void DepsgraphRelationBuilder::build_cachefile(CacheFile *cache_file)
{
- if (built_map_.checkIsBuiltAndTag(cache_file)) {
- return;
- }
- /* Animation. */
- build_animdata(&cache_file->id);
- build_parameters(&cache_file->id);
- if (check_id_has_anim_component(&cache_file->id)) {
- ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
- ComponentKey datablock_key(&cache_file->id,
- NodeType::CACHE);
- add_relation(animation_key, datablock_key, "Datablock Animation");
- }
+ if (built_map_.checkIsBuiltAndTag(cache_file)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(&cache_file->id);
+ build_parameters(&cache_file->id);
+ if (check_id_has_anim_component(&cache_file->id)) {
+ ComponentKey animation_key(&cache_file->id, NodeType::ANIMATION);
+ ComponentKey datablock_key(&cache_file->id, NodeType::CACHE);
+ add_relation(animation_key, datablock_key, "Datablock Animation");
+ }
}
void DepsgraphRelationBuilder::build_mask(Mask *mask)
{
- if (built_map_.checkIsBuiltAndTag(mask)) {
- return;
- }
- ID *mask_id = &mask->id;
- /* F-Curve animation. */
- build_animdata(mask_id);
- build_parameters(mask_id);
- /* Own mask animation. */
- OperationKey mask_animation_key(mask_id,
- NodeType::ANIMATION,
- OperationCode::MASK_ANIMATION);
- TimeSourceKey time_src_key;
- add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
- /* Final mask evaluation. */
- ComponentKey parameters_key(mask_id, NodeType::PARAMETERS);
- add_relation(mask_animation_key, parameters_key, "Mask Animation -> Mask Eval");
+ if (built_map_.checkIsBuiltAndTag(mask)) {
+ return;
+ }
+ ID *mask_id = &mask->id;
+ /* F-Curve animation. */
+ build_animdata(mask_id);
+ build_parameters(mask_id);
+ /* Own mask animation. */
+ OperationKey mask_animation_key(mask_id, NodeType::ANIMATION, OperationCode::MASK_ANIMATION);
+ TimeSourceKey time_src_key;
+ add_relation(time_src_key, mask_animation_key, "TimeSrc -> Mask Animation");
+ /* Final mask evaluation. */
+ ComponentKey parameters_key(mask_id, NodeType::PARAMETERS);
+ add_relation(mask_animation_key, parameters_key, "Mask Animation -> Mask Eval");
}
void DepsgraphRelationBuilder::build_movieclip(MovieClip *clip)
{
- if (built_map_.checkIsBuiltAndTag(clip)) {
- return;
- }
- /* Animation. */
- build_animdata(&clip->id);
- build_parameters(&clip->id);
+ if (built_map_.checkIsBuiltAndTag(clip)) {
+ return;
+ }
+ /* Animation. */
+ build_animdata(&clip->id);
+ build_parameters(&clip->id);
}
void DepsgraphRelationBuilder::build_lightprobe(LightProbe *probe)
{
- if (built_map_.checkIsBuiltAndTag(probe)) {
- return;
- }
- build_animdata(&probe->id);
- build_parameters(&probe->id);
+ if (built_map_.checkIsBuiltAndTag(probe)) {
+ return;
+ }
+ build_animdata(&probe->id);
+ build_parameters(&probe->id);
}
void DepsgraphRelationBuilder::build_speaker(Speaker *speaker)
{
- if (built_map_.checkIsBuiltAndTag(speaker)) {
- return;
- }
- build_animdata(&speaker->id);
- build_parameters(&speaker->id);
+ if (built_map_.checkIsBuiltAndTag(speaker)) {
+ return;
+ }
+ build_animdata(&speaker->id);
+ build_parameters(&speaker->id);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations()
{
- for (IDNode *id_node : graph_->id_nodes) {
- build_copy_on_write_relations(id_node);
- }
+ for (IDNode *id_node : graph_->id_nodes) {
+ build_copy_on_write_relations(id_node);
+ }
}
/* Nested datablocks (node trees, shape keys) requires special relation to
@@ -2630,150 +2305,132 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations()
*/
void DepsgraphRelationBuilder::build_nested_datablock(ID *owner, ID *id)
{
- OperationKey owner_copy_on_write_key(owner,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- OperationKey id_copy_on_write_key(id,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- add_relation(id_copy_on_write_key,
- owner_copy_on_write_key,
- "Eval Order");
+ OperationKey owner_copy_on_write_key(
+ owner, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ OperationKey id_copy_on_write_key(id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ add_relation(id_copy_on_write_key, owner_copy_on_write_key, "Eval Order");
}
-void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner,
- bNodeTree *ntree)
+void DepsgraphRelationBuilder::build_nested_nodetree(ID *owner, bNodeTree *ntree)
{
- if (ntree == NULL) {
- return;
- }
- build_nested_datablock(owner, &ntree->id);
+ if (ntree == NULL) {
+ return;
+ }
+ build_nested_datablock(owner, &ntree->id);
}
void DepsgraphRelationBuilder::build_nested_shapekey(ID *owner, Key *key)
{
- if (key == NULL) {
- return;
- }
- build_nested_datablock(owner, &key->id);
+ if (key == NULL) {
+ return;
+ }
+ build_nested_datablock(owner, &key->id);
}
void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
{
- ID *id_orig = id_node->id_orig;
- const ID_Type id_type = GS(id_orig->name);
- TimeSourceKey time_source_key;
- OperationKey copy_on_write_key(id_orig,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- /* XXX: This is a quick hack to make Alt-A to work. */
- // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
- /* Resat of code is using rather low level trickery, so need to get some
- * explicit pointers. */
- Node *node_cow = find_node(copy_on_write_key);
- OperationNode *op_cow = node_cow->get_exit_operation();
- /* Plug any other components to this one. */
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- if (comp_node->type == NodeType::COPY_ON_WRITE) {
- /* Copy-on-write component never depends on itself. */
- continue;
- }
- if (!comp_node->depends_on_cow()) {
- /* Component explicitly requests to not add relation. */
- continue;
- }
- int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
- if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
- rel_flag &= ~RELATION_FLAG_NO_FLUSH;
- }
- /* Notes on exceptions:
- * - Parameters component is where drivers are living. Changing any
- * of the (custom) properties in the original datablock (even the
- * ones which do not imply other component update) need to make
- * sure drivers are properly updated.
- * This way, for example, changing ID property will properly poke
- * all drivers to be updated.
- *
- * - View layers have cached array of bases in them, which is not
- * copied by copy-on-write, and not preserved. PROBABLY it is better
- * to preserve that cache in copy-on-write, but for the time being
- * we allow flush to layer collections component which will ensure
- * that cached array fo bases exists and is up-to-date. */
- if (comp_node->type == NodeType::PARAMETERS ||
- comp_node->type == NodeType::LAYER_COLLECTIONS)
- {
- rel_flag &= ~RELATION_FLAG_NO_FLUSH;
- }
- /* All entry operations of each component should wait for a proper
- * copy of ID. */
- OperationNode *op_entry = comp_node->get_entry_operation();
- if (op_entry != NULL) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_entry, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- /* All dangling operations should also be executed after copy-on-write. */
- GHASH_FOREACH_BEGIN(OperationNode *, op_node, comp_node->operations_map)
- {
- if (op_node == op_entry) {
- continue;
- }
- if (op_node->inlinks.size() == 0) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_node, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- else {
- bool has_same_comp_dependency = false;
- for (Relation *rel_current : op_node->inlinks) {
- if (rel_current->from->type != NodeType::OPERATION) {
- continue;
- }
- OperationNode *op_node_from =
- (OperationNode *)rel_current->from;
- if (op_node_from->owner == op_node->owner) {
- has_same_comp_dependency = true;
- break;
- }
- }
- if (!has_same_comp_dependency) {
- Relation *rel = graph_->add_new_relation(
- op_cow, op_node, "CoW Dependency");
- rel->flag |= rel_flag;
- }
- }
- }
- GHASH_FOREACH_END();
- /* NOTE: We currently ignore implicit relations to an external
- * datablocks for copy-on-write operations. This means, for example,
- * copy-on-write component of Object will not wait for copy-on-write
- * component of it's Mesh. This is because pointers are all known
- * already so remapping will happen all correct. And then If some object
- * evaluation step needs geometry, it will have transitive dependency
- * to Mesh copy-on-write already. */
- }
- GHASH_FOREACH_END();
- /* TODO(sergey): This solves crash for now, but causes too many
- * updates potentially. */
- if (GS(id_orig->name) == ID_OB) {
- Object *object = (Object *)id_orig;
- ID *object_data_id = (ID *)object->data;
- if (object_data_id != NULL) {
- if (deg_copy_on_write_is_needed(object_data_id)) {
- OperationKey data_copy_on_write_key(object_data_id,
- NodeType::COPY_ON_WRITE,
- OperationCode::COPY_ON_WRITE);
- add_relation(data_copy_on_write_key,
- copy_on_write_key,
- "Eval Order",
- RELATION_FLAG_GODMODE);
- }
- }
- else {
- BLI_assert(object->type == OB_EMPTY);
- }
- }
+ ID *id_orig = id_node->id_orig;
+ const ID_Type id_type = GS(id_orig->name);
+ TimeSourceKey time_source_key;
+ OperationKey copy_on_write_key(id_orig, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ /* XXX: This is a quick hack to make Alt-A to work. */
+ // add_relation(time_source_key, copy_on_write_key, "Fluxgate capacitor hack");
+ /* Resat of code is using rather low level trickery, so need to get some
+ * explicit pointers. */
+ Node *node_cow = find_node(copy_on_write_key);
+ OperationNode *op_cow = node_cow->get_exit_operation();
+ /* Plug any other components to this one. */
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ if (comp_node->type == NodeType::COPY_ON_WRITE) {
+ /* Copy-on-write component never depends on itself. */
+ continue;
+ }
+ if (!comp_node->depends_on_cow()) {
+ /* Component explicitly requests to not add relation. */
+ continue;
+ }
+ int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
+ if (id_type == ID_ME && comp_node->type == NodeType::GEOMETRY) {
+ rel_flag &= ~RELATION_FLAG_NO_FLUSH;
+ }
+ /* Notes on exceptions:
+ * - Parameters component is where drivers are living. Changing any
+ * of the (custom) properties in the original datablock (even the
+ * ones which do not imply other component update) need to make
+ * sure drivers are properly updated.
+ * This way, for example, changing ID property will properly poke
+ * all drivers to be updated.
+ *
+ * - View layers have cached array of bases in them, which is not
+ * copied by copy-on-write, and not preserved. PROBABLY it is better
+ * to preserve that cache in copy-on-write, but for the time being
+ * we allow flush to layer collections component which will ensure
+ * that cached array fo bases exists and is up-to-date. */
+ if (comp_node->type == NodeType::PARAMETERS ||
+ comp_node->type == NodeType::LAYER_COLLECTIONS) {
+ rel_flag &= ~RELATION_FLAG_NO_FLUSH;
+ }
+ /* All entry operations of each component should wait for a proper
+ * copy of ID. */
+ OperationNode *op_entry = comp_node->get_entry_operation();
+ if (op_entry != NULL) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_entry, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ /* All dangling operations should also be executed after copy-on-write. */
+ GHASH_FOREACH_BEGIN (OperationNode *, op_node, comp_node->operations_map) {
+ if (op_node == op_entry) {
+ continue;
+ }
+ if (op_node->inlinks.size() == 0) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ else {
+ bool has_same_comp_dependency = false;
+ for (Relation *rel_current : op_node->inlinks) {
+ if (rel_current->from->type != NodeType::OPERATION) {
+ continue;
+ }
+ OperationNode *op_node_from = (OperationNode *)rel_current->from;
+ if (op_node_from->owner == op_node->owner) {
+ has_same_comp_dependency = true;
+ break;
+ }
+ }
+ if (!has_same_comp_dependency) {
+ Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency");
+ rel->flag |= rel_flag;
+ }
+ }
+ }
+ GHASH_FOREACH_END();
+ /* NOTE: We currently ignore implicit relations to an external
+ * datablocks for copy-on-write operations. This means, for example,
+ * copy-on-write component of Object will not wait for copy-on-write
+ * component of it's Mesh. This is because pointers are all known
+ * already so remapping will happen all correct. And then If some object
+ * evaluation step needs geometry, it will have transitive dependency
+ * to Mesh copy-on-write already. */
+ }
+ GHASH_FOREACH_END();
+ /* TODO(sergey): This solves crash for now, but causes too many
+ * updates potentially. */
+ if (GS(id_orig->name) == ID_OB) {
+ Object *object = (Object *)id_orig;
+ ID *object_data_id = (ID *)object->data;
+ if (object_data_id != NULL) {
+ if (deg_copy_on_write_is_needed(object_data_id)) {
+ OperationKey data_copy_on_write_key(
+ object_data_id, NodeType::COPY_ON_WRITE, OperationCode::COPY_ON_WRITE);
+ add_relation(
+ data_copy_on_write_key, copy_on_write_key, "Eval Order", RELATION_FLAG_GODMODE);
+ }
+ }
+ else {
+ BLI_assert(object->type == OB_EMPTY);
+ }
+ }
}
/* **** ID traversal callbacks functions **** */
@@ -2783,12 +2440,12 @@ void DepsgraphRelationBuilder::modifier_walk(void *user_data,
struct ID **idpoin,
int /*cb_flag*/)
{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- ID *id = *idpoin;
- if (id == NULL) {
- return;
- }
- data->builder->build_id(id);
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ data->builder->build_id(id);
}
void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
@@ -2796,12 +2453,12 @@ void DepsgraphRelationBuilder::constraint_walk(bConstraint * /*con*/,
bool /*is_reference*/,
void *user_data)
{
- BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
- ID *id = *idpoin;
- if (id == NULL) {
- return;
- }
- data->builder->build_id(id);
+ BuilderWalkUserData *data = (BuilderWalkUserData *)user_data;
+ ID *id = *idpoin;
+ if (id == NULL) {
+ return;
+ }
+ data->builder->build_id(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 0a0f0e99865..5b2d34a270c 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -93,301 +93,268 @@ struct Relation;
struct RootPChanMap;
struct TimeSourceNode;
-struct TimeSourceKey
-{
- TimeSourceKey();
- TimeSourceKey(ID *id);
+struct TimeSourceKey {
+ TimeSourceKey();
+ TimeSourceKey(ID *id);
- string identifier() const;
+ string identifier() const;
- ID *id;
+ ID *id;
};
-struct ComponentKey
-{
- ComponentKey();
- ComponentKey(ID *id, NodeType type, const char *name = "");
+struct ComponentKey {
+ ComponentKey();
+ ComponentKey(ID *id, NodeType type, const char *name = "");
- string identifier() const;
+ string identifier() const;
- ID *id;
- NodeType type;
- const char *name;
+ ID *id;
+ NodeType type;
+ const char *name;
};
-struct OperationKey
-{
- OperationKey();
- OperationKey(ID *id,
- NodeType component_type,
- const char *name,
- int name_tag = -1);
- OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- const char *name,
- int name_tag);
-
- OperationKey(ID *id,
- NodeType component_type,
- OperationCode opcode);
- OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- OperationCode opcode);
-
- OperationKey(ID *id,
- NodeType component_type,
- OperationCode opcode,
- const char *name,
- int name_tag = -1);
- OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- OperationCode opcode,
- const char *name,
- int name_tag = -1);
-
- string identifier() const;
-
- ID *id;
- NodeType component_type;
- const char *component_name;
- OperationCode opcode;
- const char *name;
- int name_tag;
+struct OperationKey {
+ OperationKey();
+ OperationKey(ID *id, NodeType component_type, const char *name, int name_tag = -1);
+ OperationKey(
+ ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag);
+
+ OperationKey(ID *id, NodeType component_type, OperationCode opcode);
+ OperationKey(ID *id, NodeType component_type, const char *component_name, OperationCode opcode);
+
+ OperationKey(
+ ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag = -1);
+ OperationKey(ID *id,
+ NodeType component_type,
+ const char *component_name,
+ OperationCode opcode,
+ const char *name,
+ int name_tag = -1);
+
+ string identifier() const;
+
+ ID *id;
+ NodeType component_type;
+ const char *component_name;
+ OperationCode opcode;
+ const char *name;
+ int name_tag;
};
-struct RNAPathKey
-{
- RNAPathKey(ID *id, const char *path, RNAPointerSource source);
- RNAPathKey(ID *id,
- const PointerRNA &ptr,
- PropertyRNA *prop,
- RNAPointerSource source);
+struct RNAPathKey {
+ RNAPathKey(ID *id, const char *path, RNAPointerSource source);
+ RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source);
- string identifier() const;
+ string identifier() const;
- ID *id;
- PointerRNA ptr;
- PropertyRNA *prop;
- RNAPointerSource source;
+ ID *id;
+ PointerRNA ptr;
+ PropertyRNA *prop;
+ RNAPointerSource source;
};
-class DepsgraphRelationBuilder : public DepsgraphBuilder
-{
-public:
- DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph);
-
- void begin_build();
-
- template <typename KeyFrom, typename KeyTo>
- Relation *add_relation(const KeyFrom& key_from,
- const KeyTo& key_to,
- const char *description,
- int flags = 0);
-
- template <typename KeyTo>
- Relation *add_relation(const TimeSourceKey& key_from,
- const KeyTo& key_to,
- const char *description,
- int flags = 0);
-
- template <typename KeyType>
- Relation *add_node_handle_relation(const KeyType& key_from,
- const DepsNodeHandle *handle,
- const char *description,
- int flags = 0);
-
- template <typename KeyTo>
- Relation *add_depends_on_transform_relation(ID *id,
- const KeyTo& key_to,
- const char *description,
- int flags = 0);
-
- /* Adds relation from proper transformation opertation to the modifier.
- * Takes care of checking for possible physics solvers modifying position
- * of this object. */
- void add_modifier_to_transform_relation(const DepsNodeHandle *handle,
- const char *description);
-
- void add_customdata_mask(Object *object,
- const DEGCustomDataMeshMasks &customdata_masks);
- void add_special_eval_flag(ID *object, uint32_t flag);
-
- void build_id(ID *id);
- void build_layer_collections(ListBase *lb);
- void build_view_layer(Scene *scene, ViewLayer *view_layer);
- void build_collection(LayerCollection *from_layer_collection,
- Object *object,
- Collection *collection);
- void build_object(Base *base, Object *object);
- void build_object_flags(Base *base, Object *object);
- void build_object_data(Object *object);
- void build_object_data_camera(Object *object);
- void build_object_data_geometry(Object *object);
- void build_object_data_geometry_datablock(ID *obdata);
- void build_object_data_light(Object *object);
- void build_object_data_lightprobe(Object *object);
- void build_object_data_speaker(Object *object);
- void build_object_parent(Object *object);
- void build_object_pointcache(Object *object);
- void build_constraints(ID *id,
- NodeType component_type,
- const char *component_subdata,
- ListBase *constraints,
- RootPChanMap *root_map);
- void build_animdata(ID *id);
- void build_animdata_curves(ID *id);
- void build_animdata_curves_targets(ID *id,
- ComponentKey &adt_key,
- OperationNode *operation_from,
- ListBase *curves);
- void build_animdata_nlastrip_targets(ID *id,
- ComponentKey &adt_key,
- OperationNode *operation_from,
- ListBase *strips);
- void build_animdata_drivers(ID *id);
- void build_animation_images(ID *id);
- void build_action(bAction *action);
- void build_driver(ID *id, FCurve *fcurve);
- void build_driver_data(ID *id, FCurve *fcurve);
- void build_driver_variables(ID *id, FCurve *fcurve);
- void build_driver_id_property(ID *id, const char *rna_path);
- void build_parameters(ID *id);
- void build_world(World *world);
- void build_rigidbody(Scene *scene);
- void build_particle_systems(Object *object);
- void build_particle_settings(ParticleSettings *part);
- void build_particle_system_visualization_object(Object *object,
- ParticleSystem *psys,
- Object *draw_object);
- void build_ik_pose(Object *object,
- bPoseChannel *pchan,
- bConstraint *con,
- RootPChanMap *root_map);
- void build_splineik_pose(Object *object,
- bPoseChannel *pchan,
- bConstraint *con,
- RootPChanMap *root_map);
- void build_rig(Object *object);
- void build_proxy_rig(Object *object);
- void build_shapekeys(Key *key);
- void build_armature(bArmature *armature);
- void build_camera(Camera *camera);
- void build_light(Light *lamp);
- void build_nodetree(bNodeTree *ntree);
- void build_material(Material *ma);
- void build_texture(Tex *tex);
- void build_image(Image *image);
- void build_compositor(Scene *scene);
- void build_gpencil(bGPdata *gpd);
- void build_cachefile(CacheFile *cache_file);
- void build_mask(Mask *mask);
- void build_movieclip(MovieClip *clip);
- void build_lightprobe(LightProbe *probe);
- void build_speaker(Speaker *speaker);
-
- void build_nested_datablock(ID *owner, ID *id);
- void build_nested_nodetree(ID *owner, bNodeTree *ntree);
- void build_nested_shapekey(ID *owner, Key *key);
-
- void add_particle_collision_relations(const OperationKey &key,
- Object *object,
- Collection *collection,
- const char *name);
- void add_particle_forcefield_relations(const OperationKey &key,
- Object *object,
- ParticleSystem *psys,
- EffectorWeights *eff,
- bool add_absorption, const char *name);
-
- void build_copy_on_write_relations();
- void build_copy_on_write_relations(IDNode *id_node);
-
- template <typename KeyType>
- OperationNode *find_operation_node(const KeyType &key);
-
- Depsgraph *getGraph();
-
-protected:
- TimeSourceNode *get_node(const TimeSourceKey &key) const;
- ComponentNode *get_node(const ComponentKey &key) const;
- OperationNode *get_node(const OperationKey &key) const;
- Node *get_node(const RNAPathKey &key);
-
- OperationNode *find_node(const OperationKey &key) const;
- bool has_node(const OperationKey &key) const;
-
- Relation *add_time_relation(TimeSourceNode *timesrc,
- Node *node_to,
- const char *description,
- int flags = 0);
- Relation *add_operation_relation(OperationNode *node_from,
- OperationNode *node_to,
- const char *description,
- int flags = 0);
-
- template <typename KeyType>
- DepsNodeHandle create_node_handle(const KeyType& key,
- const char *default_name = "");
-
- /* TODO(sergey): All those is_same* functions are to be generalized. */
-
- /* Check whether two keys corresponds to the same bone from same armature.
- *
- * This is used by drivers relations builder to avoid possible fake
- * dependency cycle when one bone property drives another property of the
- * same bone. */
- template <typename KeyFrom, typename KeyTo>
- bool is_same_bone_dependency(const KeyFrom& key_from, const KeyTo& key_to);
-
- /* Similar to above, but used to check whether driver is using node from
- * the same node tree as a driver variable. */
- template <typename KeyFrom, typename KeyTo>
- bool is_same_nodetree_node_dependency(const KeyFrom& key_from,
- 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 demotes currently built entities. */
- Scene *scene_;
-
- BuilderMap built_map_;
- RNANodeQuery rna_node_query_;
+class DepsgraphRelationBuilder : public DepsgraphBuilder {
+ public:
+ DepsgraphRelationBuilder(Main *bmain, Depsgraph *graph);
+
+ void begin_build();
+
+ template<typename KeyFrom, typename KeyTo>
+ Relation *add_relation(const KeyFrom &key_from,
+ const KeyTo &key_to,
+ const char *description,
+ int flags = 0);
+
+ template<typename KeyTo>
+ Relation *add_relation(const TimeSourceKey &key_from,
+ const KeyTo &key_to,
+ const char *description,
+ int flags = 0);
+
+ template<typename KeyType>
+ Relation *add_node_handle_relation(const KeyType &key_from,
+ const DepsNodeHandle *handle,
+ const char *description,
+ int flags = 0);
+
+ template<typename KeyTo>
+ Relation *add_depends_on_transform_relation(ID *id,
+ const KeyTo &key_to,
+ const char *description,
+ int flags = 0);
+
+ /* Adds relation from proper transformation opertation to the modifier.
+ * Takes care of checking for possible physics solvers modifying position
+ * of this object. */
+ void add_modifier_to_transform_relation(const DepsNodeHandle *handle, const char *description);
+
+ void add_customdata_mask(Object *object, const DEGCustomDataMeshMasks &customdata_masks);
+ void add_special_eval_flag(ID *object, uint32_t flag);
+
+ void build_id(ID *id);
+ void build_layer_collections(ListBase *lb);
+ void build_view_layer(Scene *scene, ViewLayer *view_layer);
+ void build_collection(LayerCollection *from_layer_collection,
+ Object *object,
+ Collection *collection);
+ void build_object(Base *base, Object *object);
+ void build_object_flags(Base *base, Object *object);
+ void build_object_data(Object *object);
+ void build_object_data_camera(Object *object);
+ void build_object_data_geometry(Object *object);
+ void build_object_data_geometry_datablock(ID *obdata);
+ void build_object_data_light(Object *object);
+ void build_object_data_lightprobe(Object *object);
+ void build_object_data_speaker(Object *object);
+ void build_object_parent(Object *object);
+ void build_object_pointcache(Object *object);
+ void build_constraints(ID *id,
+ NodeType component_type,
+ const char *component_subdata,
+ ListBase *constraints,
+ RootPChanMap *root_map);
+ void build_animdata(ID *id);
+ void build_animdata_curves(ID *id);
+ void build_animdata_curves_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationNode *operation_from,
+ ListBase *curves);
+ void build_animdata_nlastrip_targets(ID *id,
+ ComponentKey &adt_key,
+ OperationNode *operation_from,
+ ListBase *strips);
+ void build_animdata_drivers(ID *id);
+ void build_animation_images(ID *id);
+ void build_action(bAction *action);
+ void build_driver(ID *id, FCurve *fcurve);
+ void build_driver_data(ID *id, FCurve *fcurve);
+ void build_driver_variables(ID *id, FCurve *fcurve);
+ void build_driver_id_property(ID *id, const char *rna_path);
+ void build_parameters(ID *id);
+ void build_world(World *world);
+ void build_rigidbody(Scene *scene);
+ void build_particle_systems(Object *object);
+ void build_particle_settings(ParticleSettings *part);
+ void build_particle_system_visualization_object(Object *object,
+ ParticleSystem *psys,
+ Object *draw_object);
+ void build_ik_pose(Object *object,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map);
+ void build_splineik_pose(Object *object,
+ bPoseChannel *pchan,
+ bConstraint *con,
+ RootPChanMap *root_map);
+ void build_rig(Object *object);
+ void build_proxy_rig(Object *object);
+ void build_shapekeys(Key *key);
+ void build_armature(bArmature *armature);
+ void build_camera(Camera *camera);
+ void build_light(Light *lamp);
+ void build_nodetree(bNodeTree *ntree);
+ void build_material(Material *ma);
+ void build_texture(Tex *tex);
+ void build_image(Image *image);
+ void build_compositor(Scene *scene);
+ void build_gpencil(bGPdata *gpd);
+ void build_cachefile(CacheFile *cache_file);
+ void build_mask(Mask *mask);
+ void build_movieclip(MovieClip *clip);
+ void build_lightprobe(LightProbe *probe);
+ void build_speaker(Speaker *speaker);
+
+ void build_nested_datablock(ID *owner, ID *id);
+ void build_nested_nodetree(ID *owner, bNodeTree *ntree);
+ void build_nested_shapekey(ID *owner, Key *key);
+
+ void add_particle_collision_relations(const OperationKey &key,
+ Object *object,
+ Collection *collection,
+ const char *name);
+ void add_particle_forcefield_relations(const OperationKey &key,
+ Object *object,
+ ParticleSystem *psys,
+ EffectorWeights *eff,
+ bool add_absorption,
+ const char *name);
+
+ void build_copy_on_write_relations();
+ void build_copy_on_write_relations(IDNode *id_node);
+
+ template<typename KeyType> OperationNode *find_operation_node(const KeyType &key);
+
+ Depsgraph *getGraph();
+
+ protected:
+ TimeSourceNode *get_node(const TimeSourceKey &key) const;
+ ComponentNode *get_node(const ComponentKey &key) const;
+ OperationNode *get_node(const OperationKey &key) const;
+ Node *get_node(const RNAPathKey &key);
+
+ OperationNode *find_node(const OperationKey &key) const;
+ bool has_node(const OperationKey &key) const;
+
+ Relation *add_time_relation(TimeSourceNode *timesrc,
+ Node *node_to,
+ const char *description,
+ int flags = 0);
+ Relation *add_operation_relation(OperationNode *node_from,
+ OperationNode *node_to,
+ const char *description,
+ int flags = 0);
+
+ template<typename KeyType>
+ DepsNodeHandle create_node_handle(const KeyType &key, const char *default_name = "");
+
+ /* TODO(sergey): All those is_same* functions are to be generalized. */
+
+ /* Check whether two keys corresponds to the same bone from same armature.
+ *
+ * This is used by drivers relations builder to avoid possible fake
+ * dependency cycle when one bone property drives another property of the
+ * same bone. */
+ template<typename KeyFrom, typename KeyTo>
+ bool is_same_bone_dependency(const KeyFrom &key_from, const KeyTo &key_to);
+
+ /* Similar to above, but used to check whether driver is using node from
+ * the same node tree as a driver variable. */
+ template<typename KeyFrom, typename KeyTo>
+ bool is_same_nodetree_node_dependency(const KeyFrom &key_from, 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 demotes currently built entities. */
+ Scene *scene_;
+
+ BuilderMap built_map_;
+ RNANodeQuery rna_node_query_;
};
-struct DepsNodeHandle
-{
- DepsNodeHandle(DepsgraphRelationBuilder *builder,
- OperationNode *node,
- const char *default_name = "")
- : builder(builder),
- node(node),
- default_name(default_name)
- {
- BLI_assert(node != NULL);
- }
-
- DepsgraphRelationBuilder *builder;
- OperationNode *node;
- const char *default_name;
+struct DepsNodeHandle {
+ DepsNodeHandle(DepsgraphRelationBuilder *builder,
+ OperationNode *node,
+ const char *default_name = "")
+ : builder(builder), node(node), default_name(default_name)
+ {
+ BLI_assert(node != NULL);
+ }
+
+ DepsgraphRelationBuilder *builder;
+ OperationNode *node;
+ const char *default_name;
};
} // namespace DEG
-
#include "intern/builder/deg_builder_relations_impl.h"
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
index 86a17ae4a47..4412fa3fca3 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h
@@ -32,187 +32,189 @@ extern "C" {
namespace DEG {
-template <typename KeyType>
-OperationNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key)
+template<typename KeyType>
+OperationNode *DepsgraphRelationBuilder::find_operation_node(const KeyType &key)
{
- Node *node = get_node(key);
- return node != NULL ? node->get_exit_operation() : NULL;
+ Node *node = get_node(key);
+ return node != NULL ? node->get_exit_operation() : NULL;
}
-template <typename KeyFrom, typename KeyTo>
+template<typename KeyFrom, typename KeyTo>
Relation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
const KeyTo &key_to,
const char *description,
int flags)
{
- Node *node_from = get_node(key_from);
- Node *node_to = get_node(key_to);
- OperationNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
- OperationNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
- if (op_from && op_to) {
- return add_operation_relation(op_from, op_to, description, flags);
- }
- else {
- if (!op_from) {
- /* XXX TODO handle as error or report if needed */
- fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
- description, key_from.identifier().c_str());
- }
- else {
- fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
- description, key_from.identifier().c_str());
- }
- if (!op_to) {
- /* XXX TODO handle as error or report if needed */
- fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
- description, key_to.identifier().c_str());
- }
- else {
- fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
- description, key_to.identifier().c_str());
- }
- }
- return NULL;
+ Node *node_from = get_node(key_from);
+ Node *node_to = get_node(key_to);
+ OperationNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+ OperationNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+ if (op_from && op_to) {
+ return add_operation_relation(op_from, op_to, description, flags);
+ }
+ else {
+ if (!op_from) {
+ /* XXX TODO handle as error or report if needed */
+ fprintf(stderr,
+ "add_relation(%s) - Could not find op_from (%s)\n",
+ description,
+ key_from.identifier().c_str());
+ }
+ else {
+ fprintf(stderr,
+ "add_relation(%s) - Failed, but op_from (%s) was ok\n",
+ description,
+ key_from.identifier().c_str());
+ }
+ if (!op_to) {
+ /* XXX TODO handle as error or report if needed */
+ fprintf(stderr,
+ "add_relation(%s) - Could not find op_to (%s)\n",
+ description,
+ key_to.identifier().c_str());
+ }
+ else {
+ fprintf(stderr,
+ "add_relation(%s) - Failed, but op_to (%s) was ok\n",
+ description,
+ key_to.identifier().c_str());
+ }
+ }
+ return NULL;
}
-template <typename KeyTo>
-Relation *DepsgraphRelationBuilder::add_relation(
- const TimeSourceKey &key_from,
- const KeyTo &key_to,
- const char *description,
- int flags)
+template<typename KeyTo>
+Relation *DepsgraphRelationBuilder::add_relation(const TimeSourceKey &key_from,
+ const KeyTo &key_to,
+ const char *description,
+ int flags)
{
- TimeSourceNode *time_from = get_node(key_from);
- Node *node_to = get_node(key_to);
- OperationNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
- if (time_from != NULL && op_to != NULL) {
- return add_time_relation(
- time_from, op_to, description, flags);
- }
- return NULL;
+ TimeSourceNode *time_from = get_node(key_from);
+ Node *node_to = get_node(key_to);
+ OperationNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
+ if (time_from != NULL && op_to != NULL) {
+ return add_time_relation(time_from, op_to, description, flags);
+ }
+ return NULL;
}
-template <typename KeyType>
-Relation *DepsgraphRelationBuilder::add_node_handle_relation(
- const KeyType &key_from,
- const DepsNodeHandle *handle,
- const char *description,
- int flags)
+template<typename KeyType>
+Relation *DepsgraphRelationBuilder::add_node_handle_relation(const KeyType &key_from,
+ const DepsNodeHandle *handle,
+ const char *description,
+ int flags)
{
- Node *node_from = get_node(key_from);
- OperationNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
- OperationNode *op_to = handle->node->get_entry_operation();
- if (op_from != NULL && op_to != NULL) {
- return add_operation_relation(op_from, op_to, description, flags);
- }
- else {
- if (!op_from) {
- fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
- description, key_from.identifier().c_str());
- }
- if (!op_to) {
- fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
- description, key_from.identifier().c_str());
- }
- }
- return NULL;
+ Node *node_from = get_node(key_from);
+ OperationNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
+ OperationNode *op_to = handle->node->get_entry_operation();
+ if (op_from != NULL && op_to != NULL) {
+ return add_operation_relation(op_from, op_to, description, flags);
+ }
+ else {
+ if (!op_from) {
+ fprintf(stderr,
+ "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
+ description,
+ key_from.identifier().c_str());
+ }
+ if (!op_to) {
+ fprintf(stderr,
+ "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
+ description,
+ key_from.identifier().c_str());
+ }
+ }
+ return NULL;
}
-template <typename KeyTo>
-Relation *DepsgraphRelationBuilder::add_depends_on_transform_relation(
- ID *id,
- const KeyTo& key_to,
- const char *description,
- int flags)
+template<typename KeyTo>
+Relation *DepsgraphRelationBuilder::add_depends_on_transform_relation(ID *id,
+ const KeyTo &key_to,
+ const char *description,
+ int flags)
{
- if (GS(id->name) == ID_OB) {
- Object *object = reinterpret_cast<Object *>(id);
- if (object->rigidbody_object != NULL) {
- OperationKey transform_key(&object->id,
- NodeType::TRANSFORM,
- OperationCode::TRANSFORM_EVAL);
- return add_relation(transform_key, key_to, description, flags);
- }
- }
- ComponentKey transform_key(id, NodeType::TRANSFORM);
- return add_relation(transform_key, key_to, description, flags);
+ if (GS(id->name) == ID_OB) {
+ Object *object = reinterpret_cast<Object *>(id);
+ if (object->rigidbody_object != NULL) {
+ OperationKey transform_key(&object->id, NodeType::TRANSFORM, OperationCode::TRANSFORM_EVAL);
+ return add_relation(transform_key, key_to, description, flags);
+ }
+ }
+ ComponentKey transform_key(id, NodeType::TRANSFORM);
+ return add_relation(transform_key, key_to, description, flags);
}
-template <typename KeyType>
-DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
- const KeyType &key,
- const char *default_name)
+template<typename KeyType>
+DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(const KeyType &key,
+ const char *default_name)
{
- return DepsNodeHandle(this, get_node(key), default_name);
+ return DepsNodeHandle(this, get_node(key), default_name);
}
/* Rig compatibility: we check if bone is using local transform as a variable
* for driver on itself and ignore those relations to avoid "false-positive"
* dependency cycles.
*/
-template <typename KeyFrom, typename KeyTo>
-bool DepsgraphRelationBuilder::is_same_bone_dependency(const KeyFrom& key_from,
- const KeyTo& key_to)
+template<typename KeyFrom, typename KeyTo>
+bool DepsgraphRelationBuilder::is_same_bone_dependency(const KeyFrom &key_from,
+ const KeyTo &key_to)
{
- /* Get operations for requested keys. */
- Node *node_from = get_node(key_from);
- Node *node_to = get_node(key_to);
- if (node_from == NULL || node_to == NULL) {
- return false;
- }
- OperationNode *op_from = node_from->get_exit_operation();
- OperationNode *op_to = node_to->get_entry_operation();
- if (op_from == NULL || op_to == NULL) {
- return false;
- }
- /* Different armatures, bone can't be the same. */
- if (op_from->owner->owner != op_to->owner->owner) {
- return false;
- }
- /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
- if (!(op_from->opcode == OperationCode::BONE_DONE &&
- op_to->opcode == OperationCode::BONE_LOCAL))
- {
- return false;
- }
- /* ... BUT, we also need to check if it's same bone. */
- if (op_from->owner->name != op_to->owner->name) {
- return false;
- }
- return true;
+ /* Get operations for requested keys. */
+ Node *node_from = get_node(key_from);
+ Node *node_to = get_node(key_to);
+ if (node_from == NULL || node_to == NULL) {
+ return false;
+ }
+ OperationNode *op_from = node_from->get_exit_operation();
+ OperationNode *op_to = node_to->get_entry_operation();
+ if (op_from == NULL || op_to == NULL) {
+ return false;
+ }
+ /* Different armatures, bone can't be the same. */
+ if (op_from->owner->owner != op_to->owner->owner) {
+ return false;
+ }
+ /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
+ if (!(op_from->opcode == OperationCode::BONE_DONE &&
+ op_to->opcode == OperationCode::BONE_LOCAL)) {
+ return false;
+ }
+ /* ... BUT, we also need to check if it's same bone. */
+ if (op_from->owner->name != op_to->owner->name) {
+ return false;
+ }
+ return true;
}
-template <typename KeyFrom, typename KeyTo>
-bool DepsgraphRelationBuilder::is_same_nodetree_node_dependency(
- const KeyFrom& key_from,
- const KeyTo& key_to)
+template<typename KeyFrom, typename KeyTo>
+bool DepsgraphRelationBuilder::is_same_nodetree_node_dependency(const KeyFrom &key_from,
+ const KeyTo &key_to)
{
- /* Get operations for requested keys. */
- Node *node_from = get_node(key_from);
- Node *node_to = get_node(key_to);
- if (node_from == NULL || node_to == NULL) {
- return false;
- }
- OperationNode *op_from = node_from->get_exit_operation();
- OperationNode *op_to = node_to->get_entry_operation();
- if (op_from == NULL || op_to == NULL) {
- return false;
- }
- /* Check if this is actually a node tree. */
- if (GS(op_from->owner->owner->id_orig->name) != ID_NT) {
- return false;
- }
- /* Different node trees. */
- if (op_from->owner->owner != op_to->owner->owner) {
- return false;
- }
- /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
- if (!(op_from->opcode == OperationCode::PARAMETERS_EVAL &&
- op_to->opcode == OperationCode::PARAMETERS_EVAL))
- {
- return false;
- }
- return true;
+ /* Get operations for requested keys. */
+ Node *node_from = get_node(key_from);
+ Node *node_to = get_node(key_to);
+ if (node_from == NULL || node_to == NULL) {
+ return false;
+ }
+ OperationNode *op_from = node_from->get_exit_operation();
+ OperationNode *op_to = node_to->get_entry_operation();
+ if (op_from == NULL || op_to == NULL) {
+ return false;
+ }
+ /* Check if this is actually a node tree. */
+ if (GS(op_from->owner->owner->id_orig->name) != ID_NT) {
+ return false;
+ }
+ /* Different node trees. */
+ if (op_from->owner->owner != op_to->owner->owner) {
+ return false;
+ }
+ /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
+ if (!(op_from->opcode == OperationCode::PARAMETERS_EVAL &&
+ op_to->opcode == OperationCode::PARAMETERS_EVAL)) {
+ return false;
+ }
+ return true;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
index 22ff10d3b70..35af968d46e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_keys.cc
@@ -30,100 +30,85 @@ namespace DEG {
////////////////////////////////////////////////////////////////////////////////
// Time source.
-TimeSourceKey::TimeSourceKey()
- : id(NULL)
+TimeSourceKey::TimeSourceKey() : id(NULL)
{
}
-TimeSourceKey::TimeSourceKey(ID *id)
- : id(id)
+TimeSourceKey::TimeSourceKey(ID *id) : id(id)
{
}
string TimeSourceKey::identifier() const
{
- return string("TimeSourceKey");
+ return string("TimeSourceKey");
}
////////////////////////////////////////////////////////////////////////////////
// Component.
-ComponentKey::ComponentKey()
- : id(NULL),
- type(NodeType::UNDEFINED),
- name("")
+ComponentKey::ComponentKey() : id(NULL), type(NodeType::UNDEFINED), name("")
{
}
ComponentKey::ComponentKey(ID *id, NodeType type, const char *name)
- : id(id),
- type(type),
- name(name)
+ : id(id), type(type), name(name)
{
}
string ComponentKey::identifier() const
{
- const char *idname = (id) ? id->name : "<None>";
- string result = string("ComponentKey(");
- result += idname;
- result += ", " + string(nodeTypeAsString(type));
- if (name[0] != '\0') {
- result += ", '" + string(name) + "'";
- }
- result += ')';
- return result;
+ const char *idname = (id) ? id->name : "<None>";
+ string result = string("ComponentKey(");
+ result += idname;
+ result += ", " + string(nodeTypeAsString(type));
+ if (name[0] != '\0') {
+ result += ", '" + string(name) + "'";
+ }
+ result += ')';
+ return result;
}
////////////////////////////////////////////////////////////////////////////////
// Operation.
OperationKey::OperationKey()
- : id(NULL),
- component_type(NodeType::UNDEFINED),
- component_name(""),
- opcode(OperationCode::OPERATION),
- name(""),
- name_tag(-1)
+ : id(NULL),
+ component_type(NodeType::UNDEFINED),
+ component_name(""),
+ opcode(OperationCode::OPERATION),
+ name(""),
+ name_tag(-1)
{
}
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- const char *name,
- int name_tag)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(OperationCode::OPERATION),
- name(name),
- name_tag(name_tag)
+OperationKey::OperationKey(ID *id, NodeType component_type, const char *name, int name_tag)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(OperationCode::OPERATION),
+ name(name),
+ name_tag(name_tag)
{
}
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- const char *component_name,
- const char *name,
- int name_tag)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(OperationCode::OPERATION),
- name(name),
- name_tag(name_tag)
+OperationKey::OperationKey(
+ ID *id, NodeType component_type, const char *component_name, const char *name, int name_tag)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(OperationCode::OPERATION),
+ name(name),
+ name_tag(name_tag)
{
}
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- OperationCode opcode)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(opcode),
- name(""),
- name_tag(-1)
+OperationKey::OperationKey(ID *id, NodeType component_type, OperationCode opcode)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(opcode),
+ name(""),
+ name_tag(-1)
{
}
@@ -131,26 +116,23 @@ OperationKey::OperationKey(ID *id,
NodeType component_type,
const char *component_name,
OperationCode opcode)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(opcode),
- name(""),
- name_tag(-1)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(opcode),
+ name(""),
+ name_tag(-1)
{
}
-OperationKey::OperationKey(ID *id,
- NodeType component_type,
- OperationCode opcode,
- const char *name,
- int name_tag)
- : id(id),
- component_type(component_type),
- component_name(""),
- opcode(opcode),
- name(name),
- name_tag(name_tag)
+OperationKey::OperationKey(
+ ID *id, NodeType component_type, OperationCode opcode, const char *name, int name_tag)
+ : id(id),
+ component_type(component_type),
+ component_name(""),
+ opcode(opcode),
+ name(name),
+ name_tag(name_tag)
{
}
@@ -160,63 +142,54 @@ OperationKey::OperationKey(ID *id,
OperationCode opcode,
const char *name,
int name_tag)
- : id(id),
- component_type(component_type),
- component_name(component_name),
- opcode(opcode),
- name(name),
- name_tag(name_tag)
+ : id(id),
+ component_type(component_type),
+ component_name(component_name),
+ opcode(opcode),
+ name(name),
+ name_tag(name_tag)
{
}
string OperationKey::identifier() const
{
- string result = string("OperationKey(");
- result += "type: " + string(nodeTypeAsString(component_type));
- result += ", component name: '" + string(component_name) + "'";
- result += ", operation code: " + string(operationCodeAsString(opcode));
- if (name[0] != '\0') {
- result += ", '" + string(name) + "'";
- }
- result += ")";
- return result;
+ string result = string("OperationKey(");
+ result += "type: " + string(nodeTypeAsString(component_type));
+ result += ", component name: '" + string(component_name) + "'";
+ result += ", operation code: " + string(operationCodeAsString(opcode));
+ if (name[0] != '\0') {
+ result += ", '" + string(name) + "'";
+ }
+ result += ")";
+ return result;
}
////////////////////////////////////////////////////////////////////////////////
// RNA path.
-RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source)
- : id(id),
- source(source)
+RNAPathKey::RNAPathKey(ID *id, const char *path, RNAPointerSource source) : id(id), source(source)
{
- /* Create ID pointer for root of path lookup. */
- PointerRNA id_ptr;
- RNA_id_pointer_create(id, &id_ptr);
- /* Try to resolve path. */
- int index;
- if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) {
- ptr = PointerRNA_NULL;
- prop = NULL;
- }
+ /* Create ID pointer for root of path lookup. */
+ PointerRNA id_ptr;
+ RNA_id_pointer_create(id, &id_ptr);
+ /* Try to resolve path. */
+ int index;
+ if (!RNA_path_resolve_full(&id_ptr, path, &ptr, &prop, &index)) {
+ ptr = PointerRNA_NULL;
+ prop = NULL;
+ }
}
-RNAPathKey::RNAPathKey(ID *id,
- const PointerRNA &ptr,
- PropertyRNA *prop,
- RNAPointerSource source)
- : id(id),
- ptr(ptr),
- prop(prop),
- source(source)
+RNAPathKey::RNAPathKey(ID *id, const PointerRNA &ptr, PropertyRNA *prop, RNAPointerSource source)
+ : id(id), ptr(ptr), prop(prop), source(source)
{
}
string RNAPathKey::identifier() const
{
- const char *id_name = (id) ? id->name : "<No ID>";
- const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
- return string("RnaPathKey(") + "id: " + id_name +
- ", prop: '" + prop_name + "')";
+ const char *id_name = (id) ? id->name : "<No ID>";
+ const char *prop_name = (prop) ? RNA_property_identifier(prop) : "<No Prop>";
+ return string("RnaPathKey(") + "id: " + id_name + ", prop: '" + prop_name + "')";
}
} // 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 9d36e9495e3..1d222258449 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h"
@@ -67,166 +67,139 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object,
bConstraint *con,
RootPChanMap *root_map)
{
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
- /* Attach owner to IK Solver to. */
- bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
- if (rootchan == NULL) {
- return;
- }
- OperationKey pchan_local_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- OperationKey init_ik_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
- OperationKey solver_key(&object->id,
- NodeType::EVAL_POSE,
- rootchan->name,
- OperationCode::POSE_IK_SOLVER);
- OperationKey pose_cleanup_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
- add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
- add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
- /* Never cleanup before solver is run. */
- add_relation(solver_key,
- pose_cleanup_key,
- "IK Solver -> Cleanup",
- RELATION_FLAG_GODMODE);
- /* IK target */
- /* TODO(sergey): This should get handled as part of the constraint code. */
- if (data->tar != NULL) {
- /* TODO(sergey): For until we'll store partial matrices in the
- * depsgraph, we create dependency between target object and pose eval
- * component.
- *
- * This way we ensuring the whole subtree is updated from scratch
- * without need of intermediate matrices. This is an overkill, but good
- * enough for testing IK solver. */
- ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
- if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
- /* TODO(sergey): This is only for until granular update stores
- * intermediate result. */
- if (data->tar != object) {
- /* Different armature - can just read the results. */
- ComponentKey target_key(
- &data->tar->id, NodeType::BONE, data->subtarget);
- add_relation(target_key, pose_key, con->name);
- }
- else {
- /* Same armature - we'll use the ready state only, just in case
- * this bone is in the chain we're solving. */
- OperationKey target_key(&data->tar->id,
- NodeType::BONE,
- data->subtarget,
- OperationCode::BONE_DONE);
- add_relation(target_key, solver_key, con->name);
- }
- }
- else if (data->subtarget[0] &&
- ELEM(data->tar->type, OB_MESH, OB_LATTICE))
- {
- /* Vertex group target. */
- /* NOTE: for now, we don't need to represent vertex groups
- * separately. */
- ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
- add_relation(target_key, solver_key, con->name);
- add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
- }
- else {
- /* Standard Object Target. */
- ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
- add_relation(target_key, pose_key, con->name);
- }
- if (data->tar == object && data->subtarget[0]) {
- /* Prevent target's constraints from linking to anything from same
- * chain that it controls. */
- root_map->add_bone(data->subtarget, rootchan->name);
- }
- }
- /* Pole Target. */
- /* TODO(sergey): This should get handled as part of the constraint code. */
- if (data->poletar != NULL) {
- if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
- ComponentKey target_key(&data->poletar->id,
- NodeType::BONE,
- data->polesubtarget);
- add_relation(target_key, solver_key, con->name);
- }
- else if (data->polesubtarget[0] &&
- ELEM(data->poletar->type, OB_MESH, OB_LATTICE))
- {
- /* Vertex group target. */
- /* NOTE: for now, we don't need to represent vertex groups
- * separately. */
- ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
- add_relation(target_key, solver_key, con->name);
- add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
- }
- else {
- ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
- add_relation(target_key, solver_key, con->name);
- }
- }
- DEG_DEBUG_PRINTF(
- (::Depsgraph *)graph_,
- BUILD,
- "\nStarting IK Build: pchan = %s, target = (%s, %s), "
- "segcount = %d\n",
- pchan->name, data->tar ? data->tar->id.name : "NULL",
- data->subtarget, data->rootbone);
- bPoseChannel *parchan = pchan;
- /* Exclude tip from chain if needed. */
- if (!(data->flag & CONSTRAINT_IK_TIP)) {
- parchan = pchan->parent;
- }
- root_map->add_bone(parchan->name, rootchan->name);
- OperationKey parchan_transforms_key(&object->id, NodeType::BONE,
- parchan->name, OperationCode::BONE_READY);
- add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
- /* Walk to the chain's root. */
- int segcount = 0;
- while (parchan != NULL) {
- /* Make IK-solver dependent on this bone's result, since it can only run
- * after the standard results of the bone are know. Validate links step
- * on the bone will ensure that users of this bone only grab the result
- * with IK solver results. */
- if (parchan != pchan) {
- OperationKey parent_key(&object->id,
- NodeType::BONE,
- parchan->name,
- OperationCode::BONE_READY);
- add_relation(parent_key, solver_key, "IK Chain Parent");
- OperationKey bone_done_key(&object->id,
- NodeType::BONE,
- parchan->name,
- OperationCode::BONE_DONE);
- add_relation(solver_key, bone_done_key, "IK Chain Result");
- }
- else {
- OperationKey final_transforms_key(&object->id,
- NodeType::BONE,
- parchan->name,
- OperationCode::BONE_DONE);
- add_relation(solver_key, final_transforms_key, "IK Solver Result");
- }
- parchan->flag |= POSE_DONE;
- root_map->add_bone(parchan->name, rootchan->name);
- /* continue up chain, until we reach target number of items. */
- DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
- BUILD,
- " %d = %s\n",
- segcount, parchan->name);
- /* TODO(sergey): This is an arbitrary value, which was just following
- * old code convention. */
- segcount++;
- if ((segcount == data->rootbone) || (segcount > 255)) {
- break;
- }
- parchan = parchan->parent;
- }
- OperationKey pose_done_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
- add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
+ bKinematicConstraint *data = (bKinematicConstraint *)con->data;
+ /* Attach owner to IK Solver to. */
+ bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
+ if (rootchan == NULL) {
+ return;
+ }
+ OperationKey pchan_local_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ OperationKey init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
+ OperationKey solver_key(
+ &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_IK_SOLVER);
+ OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
+ add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
+ add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
+ /* Never cleanup before solver is run. */
+ add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup", RELATION_FLAG_GODMODE);
+ /* IK target */
+ /* TODO(sergey): This should get handled as part of the constraint code. */
+ if (data->tar != NULL) {
+ /* TODO(sergey): For until we'll store partial matrices in the
+ * depsgraph, we create dependency between target object and pose eval
+ * component.
+ *
+ * This way we ensuring the whole subtree is updated from scratch
+ * without need of intermediate matrices. This is an overkill, but good
+ * enough for testing IK solver. */
+ ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
+ if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
+ /* TODO(sergey): This is only for until granular update stores
+ * intermediate result. */
+ if (data->tar != object) {
+ /* Different armature - can just read the results. */
+ ComponentKey target_key(&data->tar->id, NodeType::BONE, data->subtarget);
+ add_relation(target_key, pose_key, con->name);
+ }
+ else {
+ /* Same armature - we'll use the ready state only, just in case
+ * this bone is in the chain we're solving. */
+ OperationKey target_key(
+ &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE);
+ add_relation(target_key, solver_key, con->name);
+ }
+ }
+ else if (data->subtarget[0] && ELEM(data->tar->type, OB_MESH, OB_LATTICE)) {
+ /* Vertex group target. */
+ /* NOTE: for now, we don't need to represent vertex groups
+ * separately. */
+ ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
+ add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
+ }
+ else {
+ /* Standard Object Target. */
+ ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
+ add_relation(target_key, pose_key, con->name);
+ }
+ if (data->tar == object && data->subtarget[0]) {
+ /* Prevent target's constraints from linking to anything from same
+ * chain that it controls. */
+ root_map->add_bone(data->subtarget, rootchan->name);
+ }
+ }
+ /* Pole Target. */
+ /* TODO(sergey): This should get handled as part of the constraint code. */
+ if (data->poletar != NULL) {
+ if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
+ ComponentKey target_key(&data->poletar->id, NodeType::BONE, data->polesubtarget);
+ add_relation(target_key, solver_key, con->name);
+ }
+ else if (data->polesubtarget[0] && ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) {
+ /* Vertex group target. */
+ /* NOTE: for now, we don't need to represent vertex groups
+ * separately. */
+ ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
+ add_relation(target_key, solver_key, con->name);
+ add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT));
+ }
+ else {
+ ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
+ add_relation(target_key, solver_key, con->name);
+ }
+ }
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
+ BUILD,
+ "\nStarting IK Build: pchan = %s, target = (%s, %s), "
+ "segcount = %d\n",
+ pchan->name,
+ data->tar ? data->tar->id.name : "NULL",
+ data->subtarget,
+ data->rootbone);
+ bPoseChannel *parchan = pchan;
+ /* Exclude tip from chain if needed. */
+ if (!(data->flag & CONSTRAINT_IK_TIP)) {
+ parchan = pchan->parent;
+ }
+ root_map->add_bone(parchan->name, rootchan->name);
+ OperationKey parchan_transforms_key(
+ &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
+ add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
+ /* Walk to the chain's root. */
+ int segcount = 0;
+ while (parchan != NULL) {
+ /* Make IK-solver dependent on this bone's result, since it can only run
+ * after the standard results of the bone are know. Validate links step
+ * on the bone will ensure that users of this bone only grab the result
+ * with IK solver results. */
+ if (parchan != pchan) {
+ OperationKey parent_key(
+ &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
+ add_relation(parent_key, solver_key, "IK Chain Parent");
+ OperationKey bone_done_key(
+ &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
+ add_relation(solver_key, bone_done_key, "IK Chain Result");
+ }
+ else {
+ OperationKey final_transforms_key(
+ &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "IK Solver Result");
+ }
+ parchan->flag |= POSE_DONE;
+ root_map->add_bone(parchan->name, rootchan->name);
+ /* continue up chain, until we reach target number of items. */
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph_, BUILD, " %d = %s\n", segcount, parchan->name);
+ /* TODO(sergey): This is an arbitrary value, which was just following
+ * old code convention. */
+ segcount++;
+ if ((segcount == data->rootbone) || (segcount > 255)) {
+ break;
+ }
+ parchan = parchan->parent;
+ }
+ OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
+ add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
}
/* Spline IK Eval Steps */
@@ -235,375 +208,270 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *object,
bConstraint *con,
RootPChanMap *root_map)
{
- bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
- bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
- OperationKey transforms_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_READY);
- OperationKey init_ik_key(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT_IK);
- OperationKey solver_key(&object->id,
- NodeType::EVAL_POSE,
- rootchan->name,
- OperationCode::POSE_SPLINE_IK_SOLVER);
- OperationKey pose_cleanup_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
- /* Solver depends on initialization. */
- add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
- /* Never cleanup before solver is run. */
- add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
- /* Attach owner to IK Solver. */
- add_relation(transforms_key,
- solver_key,
- "Spline IK Solver Owner",
- RELATION_FLAG_GODMODE);
- /* Attach path dependency to solver. */
- if (data->tar != NULL) {
- ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY);
- add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK");
- ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM);
- add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK");
- add_special_eval_flag(&data->tar->id, DAG_EVAL_NEED_CURVE_PATH);
- }
- pchan->flag |= POSE_DONE;
- OperationKey final_transforms_key(
- &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
- add_relation(solver_key, final_transforms_key, "Spline IK Result");
- root_map->add_bone(pchan->name, rootchan->name);
- /* Walk to the chain's root/ */
- int segcount = 1;
- for (bPoseChannel *parchan = pchan->parent;
- parchan != NULL && segcount < data->chainlen;
- parchan = parchan->parent, segcount++)
- {
- /* Make Spline IK solver dependent on this bone's result, since it can
- * only run after the standard results of the bone are know. Validate
- * links step on the bone will ensure that users of this bone only grab
- * the result with IK solver results. */
- OperationKey parent_key(&object->id,
- NodeType::BONE,
- parchan->name,
- OperationCode::BONE_READY);
- add_relation(parent_key, solver_key, "Spline IK Solver Update");
- OperationKey bone_done_key(&object->id,
- NodeType::BONE,
- parchan->name,
- OperationCode::BONE_DONE);
- add_relation(solver_key, bone_done_key, "Spline IK Solver Result");
- parchan->flag |= POSE_DONE;
- root_map->add_bone(parchan->name, rootchan->name);
- }
- OperationKey pose_done_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
- add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
+ bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
+ bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
+ OperationKey transforms_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
+ OperationKey init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
+ OperationKey solver_key(
+ &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_SPLINE_IK_SOLVER);
+ OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
+ /* Solver depends on initialization. */
+ add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
+ /* Never cleanup before solver is run. */
+ add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
+ /* Attach owner to IK Solver. */
+ add_relation(transforms_key, solver_key, "Spline IK Solver Owner", RELATION_FLAG_GODMODE);
+ /* Attach path dependency to solver. */
+ if (data->tar != NULL) {
+ ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY);
+ add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK");
+ ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM);
+ add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK");
+ add_special_eval_flag(&data->tar->id, DAG_EVAL_NEED_CURVE_PATH);
+ }
+ pchan->flag |= POSE_DONE;
+ OperationKey final_transforms_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
+ add_relation(solver_key, final_transforms_key, "Spline IK Result");
+ root_map->add_bone(pchan->name, rootchan->name);
+ /* Walk to the chain's root/ */
+ int segcount = 1;
+ for (bPoseChannel *parchan = pchan->parent; parchan != NULL && segcount < data->chainlen;
+ parchan = parchan->parent, segcount++) {
+ /* Make Spline IK solver dependent on this bone's result, since it can
+ * only run after the standard results of the bone are know. Validate
+ * links step on the bone will ensure that users of this bone only grab
+ * the result with IK solver results. */
+ OperationKey parent_key(&object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY);
+ add_relation(parent_key, solver_key, "Spline IK Solver Update");
+ OperationKey bone_done_key(
+ &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE);
+ add_relation(solver_key, bone_done_key, "Spline IK Solver Result");
+ parchan->flag |= POSE_DONE;
+ root_map->add_bone(parchan->name, rootchan->name);
+ }
+ OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
+ add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
}
/* Pose/Armature Bones Graph */
void DepsgraphRelationBuilder::build_rig(Object *object)
{
- /* Armature-Data */
- bArmature *armature = (bArmature *)object->data;
- // TODO: selection status?
- /* Attach links between pose operations. */
- ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
- OperationKey pose_init_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
- OperationKey pose_init_ik_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
- OperationKey pose_cleanup_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
- OperationKey pose_done_key(
- &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
- add_relation(
- local_transform, pose_init_key, "Local Transform -> Pose Init");
- add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
- add_relation(
- pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
- /* Make sure pose is up-to-date with armature updates. */
- build_armature(armature);
- OperationKey armature_key(&armature->id,
- NodeType::PARAMETERS,
- OperationCode::ARMATURE_EVAL);
- add_relation(armature_key, pose_init_key, "Data dependency");
- /* Run cleanup even when there are no bones. */
- add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup");
- /* IK Solvers.
- *
- * - These require separate processing steps are pose-level to be executed
- * between chains of bones (i.e. once the base transforms of a bunch of
- * bones is done).
- *
- * - We build relations for these before the dependencies between operations
- * in the same component as it is necessary to check whether such bones
- * are in the same IK chain (or else we get weird issues with either
- * in-chain references, or with bones being parented to IK'd bones).
- *
- * Unsolved Issues:
- * - Care is needed to ensure that multi-headed trees work out the same as
- * in ik-tree building
- * - Animated chain-lengths are a problem. */
- RootPChanMap root_map;
- bool pose_depends_on_local_transform = false;
- 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);
- pose_depends_on_local_transform = true;
- break;
- case CONSTRAINT_TYPE_SPLINEIK:
- build_splineik_pose(object, pchan, con, &root_map);
- pose_depends_on_local_transform = true;
- break;
- /* Constraints which needs world's matrix for transform.
- * TODO(sergey): More constraints here? */
- case CONSTRAINT_TYPE_ROTLIKE:
- case CONSTRAINT_TYPE_SIZELIKE:
- case CONSTRAINT_TYPE_LOCLIKE:
- case CONSTRAINT_TYPE_TRANSLIKE:
- /* TODO(sergey): Add used space check. */
- pose_depends_on_local_transform = true;
- break;
- default:
- break;
- }
- }
- }
- // root_map.print_debug();
- if (pose_depends_on_local_transform) {
- /* TODO(sergey): Once partial updates are possible use relation between
- * object transform and solver itself in it's build function. */
- ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
- ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
- add_relation(local_transform_key, pose_key, "Local Transforms");
- }
- /* Links between operations for each bone. */
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- OperationKey bone_local_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_LOCAL);
- OperationKey bone_pose_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_POSE_PARENT);
- OperationKey bone_ready_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_READY);
- OperationKey bone_done_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_DONE);
- pchan->flag &= ~POSE_DONE;
- /* Pose init to bone local. */
- add_relation(pose_init_key,
- bone_local_key,
- "Pose Init - Bone Local",
- RELATION_FLAG_GODMODE);
- /* Local to pose parenting operation. */
- add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
- /* Parent relation. */
- if (pchan->parent != NULL) {
- OperationCode parent_key_opcode;
- /* NOTE: this difference in handling allows us to prevent lockups
- * while ensuring correct poses for separate chains. */
- if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
- parent_key_opcode = OperationCode::BONE_READY;
- }
- else {
- parent_key_opcode = OperationCode::BONE_DONE;
- }
+ /* Armature-Data */
+ bArmature *armature = (bArmature *)object->data;
+ // TODO: selection status?
+ /* Attach links between pose operations. */
+ ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
+ OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
+ OperationKey pose_init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
+ OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
+ OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
+ add_relation(local_transform, pose_init_key, "Local Transform -> Pose Init");
+ add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
+ add_relation(pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
+ /* Make sure pose is up-to-date with armature updates. */
+ build_armature(armature);
+ OperationKey armature_key(&armature->id, NodeType::PARAMETERS, OperationCode::ARMATURE_EVAL);
+ add_relation(armature_key, pose_init_key, "Data dependency");
+ /* Run cleanup even when there are no bones. */
+ add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup");
+ /* IK Solvers.
+ *
+ * - These require separate processing steps are pose-level to be executed
+ * between chains of bones (i.e. once the base transforms of a bunch of
+ * bones is done).
+ *
+ * - We build relations for these before the dependencies between operations
+ * in the same component as it is necessary to check whether such bones
+ * are in the same IK chain (or else we get weird issues with either
+ * in-chain references, or with bones being parented to IK'd bones).
+ *
+ * Unsolved Issues:
+ * - Care is needed to ensure that multi-headed trees work out the same as
+ * in ik-tree building
+ * - Animated chain-lengths are a problem. */
+ RootPChanMap root_map;
+ bool pose_depends_on_local_transform = false;
+ 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);
+ pose_depends_on_local_transform = true;
+ break;
+ case CONSTRAINT_TYPE_SPLINEIK:
+ build_splineik_pose(object, pchan, con, &root_map);
+ pose_depends_on_local_transform = true;
+ break;
+ /* Constraints which needs world's matrix for transform.
+ * TODO(sergey): More constraints here? */
+ case CONSTRAINT_TYPE_ROTLIKE:
+ case CONSTRAINT_TYPE_SIZELIKE:
+ case CONSTRAINT_TYPE_LOCLIKE:
+ case CONSTRAINT_TYPE_TRANSLIKE:
+ /* TODO(sergey): Add used space check. */
+ pose_depends_on_local_transform = true;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ // root_map.print_debug();
+ if (pose_depends_on_local_transform) {
+ /* TODO(sergey): Once partial updates are possible use relation between
+ * object transform and solver itself in it's build function. */
+ ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
+ ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
+ add_relation(local_transform_key, pose_key, "Local Transforms");
+ }
+ /* Links between operations for each bone. */
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ OperationKey bone_local_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ OperationKey bone_pose_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_POSE_PARENT);
+ OperationKey bone_ready_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
+ OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
+ pchan->flag &= ~POSE_DONE;
+ /* Pose init to bone local. */
+ add_relation(pose_init_key, bone_local_key, "Pose Init - Bone Local", RELATION_FLAG_GODMODE);
+ /* Local to pose parenting operation. */
+ add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
+ /* Parent relation. */
+ if (pchan->parent != NULL) {
+ OperationCode parent_key_opcode;
+ /* NOTE: this difference in handling allows us to prevent lockups
+ * while ensuring correct poses for separate chains. */
+ if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
+ parent_key_opcode = OperationCode::BONE_READY;
+ }
+ else {
+ parent_key_opcode = OperationCode::BONE_DONE;
+ }
- OperationKey parent_key(&object->id,
- NodeType::BONE,
- pchan->parent->name,
- parent_key_opcode);
- add_relation(
- parent_key, bone_pose_key, "Parent Bone -> Child Bone");
- }
- /* Build 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,
- NodeType::BONE,
- pchan->name,
- &pchan->constraints,
- &root_map);
- /* Pose -> constraints. */
- OperationKey constraints_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_CONSTRAINTS);
- add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack");
- add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack");
- /* Constraints -> ready/ */
- /* TODO(sergey): When constraint stack is exploded, this step should
- * occur before the first IK solver. */
- add_relation(
- constraints_key, bone_ready_key, "Constraints -> Ready");
- }
- else {
- /* Pose -> Ready */
- add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
- }
- /* Bone ready -> Bone done.
- * NOTE: For bones without IK, this is all that's needed.
- * For IK chains however, an additional rel is created from IK
- * to done, with transitive reduction removing this one. */
- add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
- /* B-Bone shape is the real final step after Done if present. */
- if (pchan->bone != NULL && pchan->bone->segments > 1) {
- OperationKey bone_segments_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_SEGMENTS);
- /* B-Bone shape depends on the final position of the bone. */
- add_relation(bone_done_key,
- bone_segments_key,
- "Done -> B-Bone Segments");
- /* B-Bone shape depends on final position of handle bones. */
- bPoseChannel *prev, *next;
- BKE_pchan_bbone_handles_get(pchan, &prev, &next);
- if (prev) {
- OperationKey prev_key(&object->id,
- NodeType::BONE,
- prev->name,
- OperationCode::BONE_DONE);
- add_relation(prev_key,
- bone_segments_key,
- "Prev Handle -> B-Bone Segments");
- }
- if (next) {
- OperationKey next_key(&object->id,
- NodeType::BONE,
- next->name,
- OperationCode::BONE_DONE);
- add_relation(next_key,
- bone_segments_key,
- "Next Handle -> B-Bone Segments");
- }
- /* Pose requires the B-Bone shape. */
- add_relation(bone_segments_key,
- pose_done_key,
- "PoseEval Result-Bone Link",
- RELATION_FLAG_GODMODE);
- add_relation(bone_segments_key,
- pose_cleanup_key,
- "Cleanup dependency");
- }
- else {
- /* Assume that all bones must be done for the pose to be ready
- * (for deformers). */
- add_relation(bone_done_key,
- pose_done_key,
- "PoseEval Result-Bone Link");
+ OperationKey parent_key(&object->id, NodeType::BONE, pchan->parent->name, parent_key_opcode);
+ add_relation(parent_key, bone_pose_key, "Parent Bone -> Child Bone");
+ }
+ /* Build 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, NodeType::BONE, pchan->name, &pchan->constraints, &root_map);
+ /* Pose -> constraints. */
+ OperationKey constraints_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_CONSTRAINTS);
+ add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack");
+ add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack");
+ /* Constraints -> ready/ */
+ /* TODO(sergey): When constraint stack is exploded, this step should
+ * occur before the first IK solver. */
+ add_relation(constraints_key, bone_ready_key, "Constraints -> Ready");
+ }
+ else {
+ /* Pose -> Ready */
+ add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
+ }
+ /* Bone ready -> Bone done.
+ * NOTE: For bones without IK, this is all that's needed.
+ * For IK chains however, an additional rel is created from IK
+ * to done, with transitive reduction removing this one. */
+ add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
+ /* B-Bone shape is the real final step after Done if present. */
+ if (pchan->bone != NULL && pchan->bone->segments > 1) {
+ OperationKey bone_segments_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
+ /* B-Bone shape depends on the final position of the bone. */
+ add_relation(bone_done_key, bone_segments_key, "Done -> B-Bone Segments");
+ /* B-Bone shape depends on final position of handle bones. */
+ bPoseChannel *prev, *next;
+ BKE_pchan_bbone_handles_get(pchan, &prev, &next);
+ if (prev) {
+ OperationKey prev_key(&object->id, NodeType::BONE, prev->name, OperationCode::BONE_DONE);
+ add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments");
+ }
+ if (next) {
+ OperationKey next_key(&object->id, NodeType::BONE, next->name, OperationCode::BONE_DONE);
+ add_relation(next_key, bone_segments_key, "Next Handle -> B-Bone Segments");
+ }
+ /* Pose requires the B-Bone shape. */
+ add_relation(
+ bone_segments_key, pose_done_key, "PoseEval Result-Bone Link", RELATION_FLAG_GODMODE);
+ add_relation(bone_segments_key, pose_cleanup_key, "Cleanup dependency");
+ }
+ else {
+ /* Assume that all bones must be done for the pose to be ready
+ * (for deformers). */
+ add_relation(bone_done_key, pose_done_key, "PoseEval Result-Bone Link");
- /* Bones must be traversed before cleanup. */
- add_relation(bone_done_key,
- pose_cleanup_key,
- "Done -> Cleanup");
+ /* Bones must be traversed before cleanup. */
+ add_relation(bone_done_key, pose_cleanup_key, "Done -> Cleanup");
- add_relation(bone_ready_key,
- pose_cleanup_key,
- "Ready -> Cleanup");
- }
- /* Custom shape. */
- if (pchan->custom != NULL) {
- build_object(NULL, pchan->custom);
- }
- }
+ add_relation(bone_ready_key, pose_cleanup_key, "Ready -> Cleanup");
+ }
+ /* Custom shape. */
+ if (pchan->custom != NULL) {
+ build_object(NULL, pchan->custom);
+ }
+ }
}
void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
{
- bArmature *armature = (bArmature *)object->data;
- Object *proxy_from = object->proxy_from;
- build_armature(armature);
- OperationKey pose_init_key(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_INIT);
- OperationKey pose_done_key(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_DONE);
- OperationKey pose_cleanup_key(&object->id,
- NodeType::EVAL_POSE,
- OperationCode::POSE_CLEANUP);
- LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
- OperationKey bone_local_key(&object->id,
- NodeType::BONE, pchan->name,
- OperationCode::BONE_LOCAL);
- OperationKey bone_ready_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_READY);
- OperationKey bone_done_key(&object->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_DONE);
- OperationKey from_bone_done_key(&proxy_from->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::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_cleanup_key, "Bone Done -> Pose Cleanup");
- add_relation(bone_done_key,
- pose_done_key,
- "Bone Done -> Pose Done",
- RELATION_FLAG_GODMODE);
- /* Make sure bone in the proxy is not done before it's FROM is done. */
- if (pchan->bone && pchan->bone->segments > 1) {
- OperationKey from_bone_segments_key(&proxy_from->id,
- NodeType::BONE,
- pchan->name,
- OperationCode::BONE_SEGMENTS);
- add_relation(from_bone_segments_key,
- bone_done_key,
- "Bone Segments -> Bone Done",
- RELATION_FLAG_GODMODE);
- }
- else {
- add_relation(from_bone_done_key,
- bone_done_key,
- "Bone Done -> Bone Done");
- }
+ bArmature *armature = (bArmature *)object->data;
+ Object *proxy_from = object->proxy_from;
+ build_armature(armature);
+ OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
+ OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
+ OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
+ OperationKey bone_local_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL);
+ OperationKey bone_ready_key(
+ &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY);
+ OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
+ OperationKey from_bone_done_key(
+ &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::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_cleanup_key, "Bone Done -> Pose Cleanup");
+ add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done", RELATION_FLAG_GODMODE);
+ /* Make sure bone in the proxy is not done before it's FROM is done. */
+ if (pchan->bone && pchan->bone->segments > 1) {
+ OperationKey from_bone_segments_key(
+ &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS);
+ add_relation(from_bone_segments_key,
+ bone_done_key,
+ "Bone Segments -> Bone Done",
+ RELATION_FLAG_GODMODE);
+ }
+ else {
+ add_relation(from_bone_done_key, bone_done_key, "Bone Done -> Bone Done");
+ }
- /* Parent relation: even though the proxy bone itself doesn't need
- * the parent bone, some users expect the parent to be ready if the
- * bone itself is (e.g. for computing the local space matrix).
- */
- if (pchan->parent != NULL) {
- OperationKey parent_key(&object->id,
- NodeType::BONE,
- pchan->parent->name,
- OperationCode::BONE_DONE);
- add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone");
- }
+ /* Parent relation: even though the proxy bone itself doesn't need
+ * the parent bone, some users expect the parent to be ready if the
+ * bone itself is (e.g. for computing the local space matrix).
+ */
+ if (pchan->parent != NULL) {
+ OperationKey parent_key(
+ &object->id, NodeType::BONE, pchan->parent->name, OperationCode::BONE_DONE);
+ add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone");
+ }
- if (pchan->prop != NULL) {
- OperationKey bone_parameters(&object->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- pchan->name);
- OperationKey from_bone_parameters(&proxy_from->id,
- NodeType::PARAMETERS,
- OperationCode::PARAMETERS_EVAL,
- pchan->name);
- add_relation(from_bone_parameters,
- bone_parameters,
- "Proxy Bone Parameters");
- }
- }
+ if (pchan->prop != NULL) {
+ OperationKey bone_parameters(
+ &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
+ OperationKey from_bone_parameters(
+ &proxy_from->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name);
+ add_relation(from_bone_parameters, bone_parameters, "Proxy Bone Parameters");
+ }
+ }
}
} // namespace DEG
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 622bb4a8a02..a325544e046 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
@@ -27,7 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "MEM_guardedalloc.h"
@@ -61,78 +61,78 @@ namespace DEG {
void DepsgraphRelationBuilder::build_layer_collections(ListBase *lb)
{
- const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ?
- COLLECTION_RESTRICT_VIEW : COLLECTION_RESTRICT_RENDER;
-
- for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
- if ((lc->collection->flag & restrict_flag)) {
- continue;
- }
- if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
- build_collection(lc, NULL, lc->collection);
- }
- build_layer_collections(&lc->layer_collections);
- }
+ const int restrict_flag = (graph_->mode == DAG_EVAL_VIEWPORT) ? COLLECTION_RESTRICT_VIEW :
+ COLLECTION_RESTRICT_RENDER;
+
+ for (LayerCollection *lc = (LayerCollection *)lb->first; lc; lc = lc->next) {
+ if ((lc->collection->flag & restrict_flag)) {
+ continue;
+ }
+ if ((lc->flag & LAYER_COLLECTION_EXCLUDE) == 0) {
+ build_collection(lc, NULL, lc->collection);
+ }
+ build_layer_collections(&lc->layer_collections);
+ }
}
void DepsgraphRelationBuilder::build_view_layer(Scene *scene, ViewLayer *view_layer)
{
- /* Setup currently building context. */
- scene_ = scene;
- /* Scene objects. */
- /* NOTE: Nodes builder requires us to pass CoW base because it's being
- * 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. */
- LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- if (need_pull_base_into_graph(base)) {
- build_object(base, base->object);
- }
- }
-
- build_layer_collections(&view_layer->layer_collections);
-
- if (scene->camera != NULL) {
- build_object(NULL, scene->camera);
- }
- /* Rigidbody. */
- if (scene->rigidbody_world != NULL) {
- build_rigidbody(scene);
- }
- /* Scene's animation and drivers. */
- if (scene->adt != NULL) {
- build_animdata(&scene->id);
- }
- /* World. */
- if (scene->world != NULL) {
- build_world(scene->world);
- }
- /* Compositor nodes. */
- if (scene->nodetree != NULL) {
- build_compositor(scene);
- }
- /* Masks. */
- LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
- build_mask(mask);
- }
- /* Movie clips. */
- LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclips) {
- build_movieclip(clip);
- }
- /* Material override. */
- if (view_layer->mat_override != NULL) {
- build_material(view_layer->mat_override);
- }
- /* Freestyle collections. */
- LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
- if (fls->group != NULL) {
- build_collection(NULL, NULL, fls->group);
- }
- }
- /* Build all set scenes. */
- if (scene->set != NULL) {
- ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
- build_view_layer(scene->set, set_view_layer);
- }
+ /* Setup currently building context. */
+ scene_ = scene;
+ /* Scene objects. */
+ /* NOTE: Nodes builder requires us to pass CoW base because it's being
+ * 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. */
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ if (need_pull_base_into_graph(base)) {
+ build_object(base, base->object);
+ }
+ }
+
+ build_layer_collections(&view_layer->layer_collections);
+
+ if (scene->camera != NULL) {
+ build_object(NULL, scene->camera);
+ }
+ /* Rigidbody. */
+ if (scene->rigidbody_world != NULL) {
+ build_rigidbody(scene);
+ }
+ /* Scene's animation and drivers. */
+ if (scene->adt != NULL) {
+ build_animdata(&scene->id);
+ }
+ /* World. */
+ if (scene->world != NULL) {
+ build_world(scene->world);
+ }
+ /* Compositor nodes. */
+ if (scene->nodetree != NULL) {
+ build_compositor(scene);
+ }
+ /* Masks. */
+ LISTBASE_FOREACH (Mask *, mask, &bmain_->masks) {
+ build_mask(mask);
+ }
+ /* Movie clips. */
+ LISTBASE_FOREACH (MovieClip *, clip, &bmain_->movieclips) {
+ build_movieclip(clip);
+ }
+ /* Material override. */
+ if (view_layer->mat_override != NULL) {
+ build_material(view_layer->mat_override);
+ }
+ /* Freestyle collections. */
+ LISTBASE_FOREACH (FreestyleLineSet *, fls, &view_layer->freestyle_config.linesets) {
+ if (fls->group != NULL) {
+ build_collection(NULL, NULL, fls->group);
+ }
+ }
+ /* Build all set scenes. */
+ if (scene->set != NULL) {
+ ViewLayer *set_view_layer = BKE_view_layer_default_render(scene->set);
+ build_view_layer(scene->set, set_view_layer);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index c8c6cc75418..810d3ee3f66 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -55,74 +55,67 @@ namespace DEG {
/* ********************************* ID Data ******************************** */
class RNANodeQueryIDData {
-public:
- explicit RNANodeQueryIDData(const ID *id)
- : id_(id),
- contraint_to_pchan_map_(NULL) {
- }
+ public:
+ explicit RNANodeQueryIDData(const ID *id) : id_(id), contraint_to_pchan_map_(NULL)
+ {
+ }
- ~RNANodeQueryIDData() {
- if (contraint_to_pchan_map_ != NULL) {
- BLI_ghash_free(contraint_to_pchan_map_, NULL, NULL);
- }
- }
+ ~RNANodeQueryIDData()
+ {
+ if (contraint_to_pchan_map_ != NULL) {
+ BLI_ghash_free(contraint_to_pchan_map_, NULL, NULL);
+ }
+ }
- const bPoseChannel *get_pchan_for_constraint(const bConstraint *constraint)
- {
- ensure_constraint_to_pchan_map();
- return static_cast<bPoseChannel *>(
- BLI_ghash_lookup(contraint_to_pchan_map_, constraint));
- }
+ const bPoseChannel *get_pchan_for_constraint(const bConstraint *constraint)
+ {
+ ensure_constraint_to_pchan_map();
+ return static_cast<bPoseChannel *>(BLI_ghash_lookup(contraint_to_pchan_map_, constraint));
+ }
- void ensure_constraint_to_pchan_map()
- {
- if (contraint_to_pchan_map_ != NULL) {
- return;
- }
- BLI_assert(GS(id_->name) == ID_OB);
- const Object *object = reinterpret_cast<const Object *>(id_);
- contraint_to_pchan_map_ =
- BLI_ghash_ptr_new("id data pchan constraint map");
- if (object->pose != NULL) {
- LISTBASE_FOREACH (
- const bPoseChannel *, pchan, &object->pose->chanbase)
- {
- LISTBASE_FOREACH (
- const bConstraint *, constraint, &pchan->constraints)
- {
- BLI_ghash_insert(contraint_to_pchan_map_,
- const_cast<bConstraint *>(constraint),
- const_cast<bPoseChannel *>(pchan));
- }
- }
- }
- }
+ void ensure_constraint_to_pchan_map()
+ {
+ if (contraint_to_pchan_map_ != NULL) {
+ return;
+ }
+ BLI_assert(GS(id_->name) == ID_OB);
+ const Object *object = reinterpret_cast<const Object *>(id_);
+ contraint_to_pchan_map_ = BLI_ghash_ptr_new("id data pchan constraint map");
+ if (object->pose != NULL) {
+ LISTBASE_FOREACH (const bPoseChannel *, pchan, &object->pose->chanbase) {
+ LISTBASE_FOREACH (const bConstraint *, constraint, &pchan->constraints) {
+ BLI_ghash_insert(contraint_to_pchan_map_,
+ const_cast<bConstraint *>(constraint),
+ const_cast<bPoseChannel *>(pchan));
+ }
+ }
+ }
+ }
-protected:
- /* ID this data corresponds to. */
- const ID *id_;
+ protected:
+ /* ID this data corresponds to. */
+ const ID *id_;
- /* indexed by bConstraint*, returns pose channel which contains that
- * constraint. */
- GHash *contraint_to_pchan_map_;
+ /* indexed by bConstraint*, returns pose channel which contains that
+ * constraint. */
+ GHash *contraint_to_pchan_map_;
};
/* ***************************** Node Identifier **************************** */
RNANodeIdentifier::RNANodeIdentifier()
- : id(NULL),
- type(NodeType::UNDEFINED),
- component_name(""),
- operation_code(OperationCode::OPERATION),
- operation_name(),
- operation_name_tag(-1)
+ : id(NULL),
+ type(NodeType::UNDEFINED),
+ component_name(""),
+ operation_code(OperationCode::OPERATION),
+ operation_name(),
+ operation_name_tag(-1)
{
}
bool RNANodeIdentifier::is_valid() const
{
- return id != NULL &&
- type != NodeType::UNDEFINED;
+ return id != NULL && type != NodeType::UNDEFINED;
}
/* ********************************** Query ********************************* */
@@ -131,264 +124,244 @@ namespace {
void ghash_id_data_free_func(void *value)
{
- RNANodeQueryIDData *id_data = static_cast<RNANodeQueryIDData *>(value);
- OBJECT_GUARDED_DELETE(id_data, RNANodeQueryIDData);
+ RNANodeQueryIDData *id_data = static_cast<RNANodeQueryIDData *>(value);
+ OBJECT_GUARDED_DELETE(id_data, RNANodeQueryIDData);
}
} // namespace
RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph)
- : depsgraph_(depsgraph),
- id_data_map_(BLI_ghash_ptr_new("rna node query id data hash"))
+ : depsgraph_(depsgraph), id_data_map_(BLI_ghash_ptr_new("rna node query id data hash"))
{
}
RNANodeQuery::~RNANodeQuery()
{
- BLI_ghash_free(id_data_map_, NULL, ghash_id_data_free_func);
+ BLI_ghash_free(id_data_map_, NULL, ghash_id_data_free_func);
}
Node *RNANodeQuery::find_node(const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource source)
{
- const RNANodeIdentifier node_identifier = construct_node_identifier(
- ptr, prop, source);
- if (!node_identifier.is_valid()) {
- return NULL;
- }
- IDNode *id_node = depsgraph_->find_id_node(node_identifier.id);
- if (id_node == NULL) {
- return NULL;
- }
- ComponentNode *comp_node = id_node->find_component(
- node_identifier.type, node_identifier.component_name);
- if (comp_node == NULL) {
- return NULL;
- }
- if (node_identifier.operation_code == OperationCode::OPERATION) {
- return comp_node;
- }
- return comp_node->find_operation(node_identifier.operation_code,
- node_identifier.operation_name,
- node_identifier.operation_name_tag);
+ const RNANodeIdentifier node_identifier = construct_node_identifier(ptr, prop, source);
+ if (!node_identifier.is_valid()) {
+ return NULL;
+ }
+ IDNode *id_node = depsgraph_->find_id_node(node_identifier.id);
+ if (id_node == NULL) {
+ return NULL;
+ }
+ ComponentNode *comp_node = id_node->find_component(node_identifier.type,
+ node_identifier.component_name);
+ if (comp_node == NULL) {
+ return NULL;
+ }
+ if (node_identifier.operation_code == OperationCode::OPERATION) {
+ return comp_node;
+ }
+ return comp_node->find_operation(node_identifier.operation_code,
+ node_identifier.operation_name,
+ node_identifier.operation_name_tag);
}
-RNANodeIdentifier RNANodeQuery::construct_node_identifier(
- const PointerRNA *ptr,
- const PropertyRNA *prop,
- RNAPointerSource source)
+RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ RNAPointerSource source)
{
- RNANodeIdentifier node_identifier;
- if (ptr->type == NULL) {
- return node_identifier;
- }
- /* Set default values for returns. */
- node_identifier.id = static_cast<ID *>(ptr->id.data);
- node_identifier.component_name = "";
- node_identifier.operation_code = OperationCode::OPERATION;
- node_identifier.operation_name = "";
- node_identifier.operation_name_tag = -1;
- /* Handling of commonly known scenarios. */
- if (ptr->type == &RNA_PoseBone) {
- const bPoseChannel *pchan =
- static_cast<const bPoseChannel *>(ptr->data);
- if (prop != NULL && RNA_property_is_idprop(prop)) {
- node_identifier.type = NodeType::PARAMETERS;
- node_identifier.operation_code = OperationCode::ID_PROPERTY;
- node_identifier.operation_name =
- RNA_property_identifier(
- reinterpret_cast<const PropertyRNA *>(prop));
- node_identifier.operation_name_tag = -1;
- }
- else {
- /* Bone - generally, we just want the bone component. */
- node_identifier.type = NodeType::BONE;
- node_identifier.component_name = pchan->name;
- /* But B-Bone properties should connect to the actual operation. */
- if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 &&
- STRPREFIX(RNA_property_identifier(prop), "bbone_"))
- {
- node_identifier.operation_code = OperationCode::BONE_SEGMENTS;
- }
- }
- return node_identifier;
- }
- else if (ptr->type == &RNA_Bone) {
- const Bone *bone = static_cast<const Bone *>(ptr->data);
- /* Armature-level bone, but it ends up going to bone component
- * anyway. */
- // NOTE: the ID in this case will end up being bArmature.
- node_identifier.type = NodeType::BONE;
- node_identifier.component_name = bone->name;
- return node_identifier;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
- const Object *object = static_cast<const Object *>(ptr->id.data);
- const bConstraint *constraint =
- static_cast<const bConstraint *>(ptr->data);
- RNANodeQueryIDData *id_data = ensure_id_data(&object->id);
- /* Check whether is object or bone constraint. */
- /* NOTE: Currently none of the area can address transform of an object
- * at a given constraint, but for rigging one might use constraint
- * influence to be used to drive some corrective shape keys or so. */
- const bPoseChannel *pchan =
- id_data->get_pchan_for_constraint(constraint);
- if (pchan == NULL) {
- node_identifier.type = NodeType::TRANSFORM;
- node_identifier.operation_code = OperationCode::TRANSFORM_LOCAL;
- }
- else {
- node_identifier.type = NodeType::BONE;
- node_identifier.operation_code = OperationCode::BONE_LOCAL;
- node_identifier.component_name = pchan->name;
- }
- return node_identifier;
- }
- else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) {
- Object *object = (Object *)ptr->id.data;
- bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
- /* Check whether is object or bone constraint. */
- bPoseChannel *pchan = NULL;
- bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan);
- if (con != NULL) {
- if (pchan != NULL) {
- node_identifier.type = NodeType::BONE;
- node_identifier.operation_code = OperationCode::BONE_LOCAL;
- node_identifier.component_name = pchan->name;
- }
- else {
- node_identifier.type = NodeType::TRANSFORM;
- node_identifier.operation_code = OperationCode::TRANSFORM_LOCAL;
- }
- return node_identifier;
- }
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
- /* When modifier is used as FROM operation this is likely referencing to
- * the property (for example, modifier's influence).
- * But when it's used as TO operation, this is geometry component. */
- switch (source) {
- case RNAPointerSource::ENTRY:
- node_identifier.type = NodeType::GEOMETRY;
- break;
- case RNAPointerSource::EXIT:
- node_identifier.type = NodeType::PARAMETERS;
- node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
- break;
- }
- return node_identifier;
- }
- else if (ptr->type == &RNA_Object) {
- /* Transforms props? */
- if (prop != NULL) {
- const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
- /* TODO(sergey): How to optimize this? */
- if (strstr(prop_identifier, "location") ||
- strstr(prop_identifier, "rotation") ||
- strstr(prop_identifier, "scale") ||
- strstr(prop_identifier, "matrix_"))
- {
- node_identifier.type = NodeType::TRANSFORM;
- return node_identifier;
- }
- else if (strstr(prop_identifier, "data")) {
- /* We access object.data, most likely a geometry.
- * Might be a bone tho. */
- node_identifier.type = NodeType::GEOMETRY;
- return node_identifier;
- }
- else if (STREQ(prop_identifier, "hide_viewport") ||
- STREQ(prop_identifier, "hide_render"))
- {
- node_identifier.type = NodeType::OBJECT_FROM_LAYER;
- return node_identifier;
- }
- }
- }
- else if (ptr->type == &RNA_ShapeKey) {
- KeyBlock *key_block = static_cast<KeyBlock *>(ptr->data);
- node_identifier.id = static_cast<ID *>(ptr->id.data);
- node_identifier.type = NodeType::PARAMETERS;
- node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
- node_identifier.operation_name = key_block->name;
- return node_identifier;
- }
- else if (ptr->type == &RNA_Key) {
- node_identifier.id = static_cast<ID *>(ptr->id.data);
- node_identifier.type = NodeType::GEOMETRY;
- return node_identifier;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
- const Sequence *seq = static_cast<Sequence *>(ptr->data);
- /* Sequencer strip */
- node_identifier.type = NodeType::SEQUENCER;
- node_identifier.component_name = seq->name;
- return node_identifier;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
- node_identifier.type = NodeType::SHADING;
- return node_identifier;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
- node_identifier.type = NodeType::SHADING;
- return node_identifier;
- }
- else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) {
- node_identifier.id = (ID *)ptr->id.data;
- node_identifier.type = NodeType::GEOMETRY;
- return node_identifier;
- }
- else if (ELEM(ptr->type, &RNA_BezierSplinePoint, &RNA_SplinePoint)) {
- node_identifier.id = (ID *)ptr->id.data;
- node_identifier.type = NodeType::GEOMETRY;
- return node_identifier;
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_ImageUser)) {
- if (GS(node_identifier.id->name) == ID_NT) {
- node_identifier.type = NodeType::ANIMATION;
- node_identifier.operation_code = OperationCode::IMAGE_ANIMATION;
- return node_identifier;
- }
- }
- else if (ELEM(ptr->type, &RNA_MeshVertex,
- &RNA_MeshEdge,
- &RNA_MeshLoop,
- &RNA_MeshPolygon))
- {
- node_identifier.type = NodeType::GEOMETRY;
- return node_identifier;
- }
- if (prop != NULL) {
- /* All unknown data effectively falls under "parameter evaluation". */
- if (RNA_property_is_idprop(prop)) {
- node_identifier.type = NodeType::PARAMETERS;
- node_identifier.operation_code = OperationCode::ID_PROPERTY;
- node_identifier.operation_name =
- RNA_property_identifier((PropertyRNA *)prop);
- node_identifier.operation_name_tag = -1;
- }
- else {
- node_identifier.type = NodeType::PARAMETERS;
- node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
- node_identifier.operation_name = "";
- node_identifier.operation_name_tag = -1;
- }
- return node_identifier;
- }
- return node_identifier;
+ RNANodeIdentifier node_identifier;
+ if (ptr->type == NULL) {
+ return node_identifier;
+ }
+ /* Set default values for returns. */
+ node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.component_name = "";
+ node_identifier.operation_code = OperationCode::OPERATION;
+ node_identifier.operation_name = "";
+ node_identifier.operation_name_tag = -1;
+ /* Handling of commonly known scenarios. */
+ if (ptr->type == &RNA_PoseBone) {
+ const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr->data);
+ if (prop != NULL && RNA_property_is_idprop(prop)) {
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::ID_PROPERTY;
+ node_identifier.operation_name = RNA_property_identifier(
+ reinterpret_cast<const PropertyRNA *>(prop));
+ node_identifier.operation_name_tag = -1;
+ }
+ else {
+ /* Bone - generally, we just want the bone component. */
+ node_identifier.type = NodeType::BONE;
+ node_identifier.component_name = pchan->name;
+ /* But B-Bone properties should connect to the actual operation. */
+ if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 &&
+ STRPREFIX(RNA_property_identifier(prop), "bbone_")) {
+ node_identifier.operation_code = OperationCode::BONE_SEGMENTS;
+ }
+ }
+ return node_identifier;
+ }
+ else if (ptr->type == &RNA_Bone) {
+ const Bone *bone = static_cast<const Bone *>(ptr->data);
+ /* Armature-level bone, but it ends up going to bone component
+ * anyway. */
+ // NOTE: the ID in this case will end up being bArmature.
+ node_identifier.type = NodeType::BONE;
+ node_identifier.component_name = bone->name;
+ return node_identifier;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
+ const Object *object = static_cast<const Object *>(ptr->id.data);
+ const bConstraint *constraint = static_cast<const bConstraint *>(ptr->data);
+ RNANodeQueryIDData *id_data = ensure_id_data(&object->id);
+ /* Check whether is object or bone constraint. */
+ /* NOTE: Currently none of the area can address transform of an object
+ * at a given constraint, but for rigging one might use constraint
+ * influence to be used to drive some corrective shape keys or so. */
+ const bPoseChannel *pchan = id_data->get_pchan_for_constraint(constraint);
+ if (pchan == NULL) {
+ node_identifier.type = NodeType::TRANSFORM;
+ node_identifier.operation_code = OperationCode::TRANSFORM_LOCAL;
+ }
+ else {
+ node_identifier.type = NodeType::BONE;
+ node_identifier.operation_code = OperationCode::BONE_LOCAL;
+ node_identifier.component_name = pchan->name;
+ }
+ return node_identifier;
+ }
+ else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) {
+ Object *object = (Object *)ptr->id.data;
+ bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
+ /* Check whether is object or bone constraint. */
+ bPoseChannel *pchan = NULL;
+ bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan);
+ if (con != NULL) {
+ if (pchan != NULL) {
+ node_identifier.type = NodeType::BONE;
+ node_identifier.operation_code = OperationCode::BONE_LOCAL;
+ node_identifier.component_name = pchan->name;
+ }
+ else {
+ node_identifier.type = NodeType::TRANSFORM;
+ node_identifier.operation_code = OperationCode::TRANSFORM_LOCAL;
+ }
+ return node_identifier;
+ }
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+ /* When modifier is used as FROM operation this is likely referencing to
+ * the property (for example, modifier's influence).
+ * But when it's used as TO operation, this is geometry component. */
+ switch (source) {
+ case RNAPointerSource::ENTRY:
+ node_identifier.type = NodeType::GEOMETRY;
+ break;
+ case RNAPointerSource::EXIT:
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
+ break;
+ }
+ return node_identifier;
+ }
+ else if (ptr->type == &RNA_Object) {
+ /* Transforms props? */
+ if (prop != NULL) {
+ const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
+ /* TODO(sergey): How to optimize this? */
+ if (strstr(prop_identifier, "location") || strstr(prop_identifier, "rotation") ||
+ strstr(prop_identifier, "scale") || strstr(prop_identifier, "matrix_")) {
+ node_identifier.type = NodeType::TRANSFORM;
+ return node_identifier;
+ }
+ else if (strstr(prop_identifier, "data")) {
+ /* We access object.data, most likely a geometry.
+ * Might be a bone tho. */
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
+ else if (STREQ(prop_identifier, "hide_viewport") || STREQ(prop_identifier, "hide_render")) {
+ node_identifier.type = NodeType::OBJECT_FROM_LAYER;
+ return node_identifier;
+ }
+ }
+ }
+ else if (ptr->type == &RNA_ShapeKey) {
+ KeyBlock *key_block = static_cast<KeyBlock *>(ptr->data);
+ node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
+ node_identifier.operation_name = key_block->name;
+ return node_identifier;
+ }
+ else if (ptr->type == &RNA_Key) {
+ node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
+ const Sequence *seq = static_cast<Sequence *>(ptr->data);
+ /* Sequencer strip */
+ node_identifier.type = NodeType::SEQUENCER;
+ node_identifier.component_name = seq->name;
+ return node_identifier;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
+ node_identifier.type = NodeType::SHADING;
+ return node_identifier;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
+ node_identifier.type = NodeType::SHADING;
+ return node_identifier;
+ }
+ else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) {
+ node_identifier.id = (ID *)ptr->id.data;
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
+ else if (ELEM(ptr->type, &RNA_BezierSplinePoint, &RNA_SplinePoint)) {
+ node_identifier.id = (ID *)ptr->id.data;
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_ImageUser)) {
+ if (GS(node_identifier.id->name) == ID_NT) {
+ node_identifier.type = NodeType::ANIMATION;
+ node_identifier.operation_code = OperationCode::IMAGE_ANIMATION;
+ return node_identifier;
+ }
+ }
+ else if (ELEM(ptr->type, &RNA_MeshVertex, &RNA_MeshEdge, &RNA_MeshLoop, &RNA_MeshPolygon)) {
+ node_identifier.type = NodeType::GEOMETRY;
+ return node_identifier;
+ }
+ if (prop != NULL) {
+ /* All unknown data effectively falls under "parameter evaluation". */
+ if (RNA_property_is_idprop(prop)) {
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::ID_PROPERTY;
+ node_identifier.operation_name = RNA_property_identifier((PropertyRNA *)prop);
+ node_identifier.operation_name_tag = -1;
+ }
+ else {
+ node_identifier.type = NodeType::PARAMETERS;
+ node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
+ node_identifier.operation_name = "";
+ node_identifier.operation_name_tag = -1;
+ }
+ return node_identifier;
+ }
+ return node_identifier;
}
RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id)
{
- RNANodeQueryIDData **id_data_ptr;
- if (!BLI_ghash_ensure_p(id_data_map_,
- const_cast<ID *>(id),
- reinterpret_cast<void***>(&id_data_ptr)))
- {
- *id_data_ptr = OBJECT_GUARDED_NEW(RNANodeQueryIDData, id);
- }
- return *id_data_ptr;
+ RNANodeQueryIDData **id_data_ptr;
+ if (!BLI_ghash_ensure_p(
+ id_data_map_, const_cast<ID *>(id), reinterpret_cast<void ***>(&id_data_ptr))) {
+ *id_data_ptr = OBJECT_GUARDED_NEW(RNANodeQueryIDData, id);
+ }
+ return *id_data_ptr;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
index 5e121476087..e8dbd7fb523 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h
@@ -41,58 +41,56 @@ class RNANodeQueryIDData;
* interested in a result of the given property or whether we are linking some
* dependency to that property. */
enum class RNAPointerSource {
- /* Query will return pointer to an entry operation of component which is
- * responsible for evaluation of the given property. */
- ENTRY,
- /* Query will return pointer to an exit operation of component which is
- * responsible for evaluation of the given property.
- * More precisely, it will return operation at which the property is known
- * to be evaluated. */
- EXIT,
+ /* Query will return pointer to an entry operation of component which is
+ * responsible for evaluation of the given property. */
+ ENTRY,
+ /* Query will return pointer to an exit operation of component which is
+ * responsible for evaluation of the given property.
+ * More precisely, it will return operation at which the property is known
+ * to be evaluated. */
+ EXIT,
};
/* A helper structure which wraps all fields needed to find a node inside of
* the dependency graph. */
class RNANodeIdentifier {
-public:
- RNANodeIdentifier();
-
- /* Check whether this identifier is valid and usable. */
- bool is_valid() const;
-
- ID *id;
- NodeType type;
- const char *component_name;
- OperationCode operation_code;
- const char *operation_name;
- int operation_name_tag;
+ public:
+ RNANodeIdentifier();
+
+ /* Check whether this identifier is valid and usable. */
+ bool is_valid() const;
+
+ ID *id;
+ NodeType type;
+ const char *component_name;
+ OperationCode operation_code;
+ const char *operation_name;
+ int operation_name_tag;
};
/* Helper class which performs optimized lookups of a node within a given
* dependency graph which satisfies given RNA pointer or RAN path. */
class RNANodeQuery {
-public:
- RNANodeQuery(Depsgraph *depsgraph);
- ~RNANodeQuery();
+ public:
+ RNANodeQuery(Depsgraph *depsgraph);
+ ~RNANodeQuery();
- Node *find_node(const PointerRNA *ptr,
- const PropertyRNA *prop,
- RNAPointerSource source);
+ Node *find_node(const PointerRNA *ptr, const PropertyRNA *prop, RNAPointerSource source);
-protected:
- Depsgraph *depsgraph_;
+ protected:
+ Depsgraph *depsgraph_;
- /* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */
- GHash *id_data_map_;
+ /* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */
+ GHash *id_data_map_;
- /* Construct identifier of the node which correspods given configuration
- * of RNA property. */
- RNANodeIdentifier construct_node_identifier(const PointerRNA *ptr,
- const PropertyRNA *prop,
- RNAPointerSource source);
+ /* Construct identifier of the node which correspods given configuration
+ * of RNA property. */
+ RNANodeIdentifier construct_node_identifier(const PointerRNA *ptr,
+ const PropertyRNA *prop,
+ RNAPointerSource source);
- /* Make sure ID data exists for the given ID, and returns it. */
- RNANodeQueryIDData *ensure_id_data(const ID *id);
+ /* Make sure ID data exists for the given ID, and returns it. */
+ RNANodeQueryIDData *ensure_id_data(const ID *id);
};
} // 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 2aa716fc87c..3e5e96d30ff 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc
@@ -50,63 +50,61 @@ namespace DEG {
*/
enum {
- OP_VISITED = 1,
- OP_REACHABLE = 2,
+ OP_VISITED = 1,
+ OP_REACHABLE = 2,
};
static void deg_graph_tag_paths_recursive(Node *node)
{
- if (node->custom_flags & OP_VISITED) {
- return;
- }
- node->custom_flags |= OP_VISITED;
- for (Relation *rel : node->inlinks) {
- deg_graph_tag_paths_recursive(rel->from);
- /* Do this only in inlinks loop, so the target node does not get
- * flagged. */
- rel->from->custom_flags |= OP_REACHABLE;
- }
+ if (node->custom_flags & OP_VISITED) {
+ return;
+ }
+ node->custom_flags |= OP_VISITED;
+ for (Relation *rel : node->inlinks) {
+ deg_graph_tag_paths_recursive(rel->from);
+ /* Do this only in inlinks loop, so the target node does not get
+ * flagged. */
+ rel->from->custom_flags |= OP_REACHABLE;
+ }
}
void deg_graph_transitive_reduction(Depsgraph *graph)
{
- int num_removed_relations = 0;
- for (OperationNode *target : graph->operations) {
- /* Clear tags. */
- for (OperationNode *node : graph->operations) {
- node->custom_flags = 0;
- }
- /* Mark nodes from which we can reach the target
- * start with children, so the target node and direct children are not
- * flagged. */
- target->custom_flags |= OP_VISITED;
- for (Relation *rel : target->inlinks) {
- deg_graph_tag_paths_recursive(rel->from);
- }
- /* Remove redundant paths to the target. */
- for (Node::Relations::const_iterator it_rel = target->inlinks.begin();
- it_rel != target->inlinks.end();
- )
- {
- Relation *rel = *it_rel;
- if (rel->from->type == NodeType::TIMESOURCE) {
- /* HACK: time source nodes don't get "custom_flags" flag
- * set/cleared. */
- /* TODO: there will be other types in future, so iterators above
- * need modifying. */
- ++it_rel;
- }
- else if (rel->from->custom_flags & OP_REACHABLE) {
- rel->unlink();
- OBJECT_GUARDED_DELETE(rel, Relation);
- ++num_removed_relations;
- }
- else {
- ++it_rel;
- }
- }
- }
- DEG_DEBUG_PRINTF((::Depsgraph *)graph, BUILD, "Removed %d relations\n", num_removed_relations);
+ int num_removed_relations = 0;
+ for (OperationNode *target : graph->operations) {
+ /* Clear tags. */
+ for (OperationNode *node : graph->operations) {
+ node->custom_flags = 0;
+ }
+ /* Mark nodes from which we can reach the target
+ * start with children, so the target node and direct children are not
+ * flagged. */
+ target->custom_flags |= OP_VISITED;
+ for (Relation *rel : target->inlinks) {
+ deg_graph_tag_paths_recursive(rel->from);
+ }
+ /* Remove redundant paths to the target. */
+ for (Node::Relations::const_iterator it_rel = target->inlinks.begin();
+ it_rel != target->inlinks.end();) {
+ Relation *rel = *it_rel;
+ if (rel->from->type == NodeType::TIMESOURCE) {
+ /* HACK: time source nodes don't get "custom_flags" flag
+ * set/cleared. */
+ /* TODO: there will be other types in future, so iterators above
+ * need modifying. */
+ ++it_rel;
+ }
+ else if (rel->from->custom_flags & OP_REACHABLE) {
+ rel->unlink();
+ OBJECT_GUARDED_DELETE(rel, Relation);
+ ++num_removed_relations;
+ }
+ else {
+ ++it_rel;
+ }
+ }
+ }
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph, BUILD, "Removed %d relations\n", num_removed_relations);
}
} // namespace DEG