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
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')
-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
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug.cc26
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug.h34
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc865
-rw-r--r--source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc176
-rw-r--r--source/blender/depsgraph/intern/depsgraph.cc383
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h195
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc341
-rw-r--r--source/blender/depsgraph/intern/depsgraph_debug.cc492
-rw-r--r--source/blender/depsgraph/intern/depsgraph_eval.cc54
-rw-r--r--source/blender/depsgraph/intern/depsgraph_physics.cc292
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc300
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_filter.cc292
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_foreach.cc286
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc510
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc1110
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.h7
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type.cc21
-rw-r--r--source/blender/depsgraph/intern/depsgraph_type.h187
-rw-r--r--source/blender/depsgraph/intern/depsgraph_update.cc22
-rw-r--r--source/blender/depsgraph/intern/depsgraph_update.h6
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval.cc415
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc1612
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h9
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_flush.cc534
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_stats.cc35
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.cc177
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h275
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.cc477
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_component.h244
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory.cc15
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory.h23
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_factory_impl.h48
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.cc244
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h88
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.cc315
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h383
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_time.cc8
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_time.h14
59 files changed, 10563 insertions, 11584 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
diff --git a/source/blender/depsgraph/intern/debug/deg_debug.cc b/source/blender/depsgraph/intern/debug/deg_debug.cc
index a6c4b59e7df..b811f11f721 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug.cc
@@ -34,27 +34,27 @@ namespace DEG {
bool terminal_do_color(void)
{
- return (G.debug & G_DEBUG_DEPSGRAPH_PRETTY) != 0;
+ return (G.debug & G_DEBUG_DEPSGRAPH_PRETTY) != 0;
}
string color_for_pointer(const void *pointer)
{
- if (!terminal_do_color()) {
- return "";
- }
- int r, g, b;
- BLI_hash_pointer_to_color(pointer, &r, &g, &b);
- char buffer[64];
- BLI_snprintf(buffer, sizeof(buffer), TRUECOLOR_ANSI_COLOR_FORMAT, r, g, b);
- return string(buffer);
+ if (!terminal_do_color()) {
+ return "";
+ }
+ int r, g, b;
+ BLI_hash_pointer_to_color(pointer, &r, &g, &b);
+ char buffer[64];
+ BLI_snprintf(buffer, sizeof(buffer), TRUECOLOR_ANSI_COLOR_FORMAT, r, g, b);
+ return string(buffer);
}
string color_end(void)
{
- if (!terminal_do_color()) {
- return "";
- }
- return string(TRUECOLOR_ANSI_COLOR_FINISH);
+ if (!terminal_do_color()) {
+ return "";
+ }
+ return string(TRUECOLOR_ANSI_COLOR_FINISH);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/debug/deg_debug.h b/source/blender/depsgraph/intern/debug/deg_debug.h
index 1cdcba9b8fd..3e4da644641 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug.h
+++ b/source/blender/depsgraph/intern/debug/deg_debug.h
@@ -32,25 +32,25 @@
namespace DEG {
#define DEG_DEBUG_PRINTF(depsgraph, type, ...) \
- do { \
- if (DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_ ## type) { \
- DEG_debug_print_begin(depsgraph); \
- fprintf(stdout, __VA_ARGS__); \
- } \
- } while (0)
+ do { \
+ if (DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_##type) { \
+ DEG_debug_print_begin(depsgraph); \
+ fprintf(stdout, __VA_ARGS__); \
+ } \
+ } while (0)
#define DEG_GLOBAL_DEBUG_PRINTF(type, ...) \
- do { \
- if (G.debug & G_DEBUG_DEPSGRAPH_ ## type) { \
- fprintf(stdout, __VA_ARGS__); \
- } \
- } while (0)
-
-#define DEG_ERROR_PRINTF(...) \
- do { \
- fprintf(stderr, __VA_ARGS__); \
- fflush(stderr); \
- } while (0)
+ do { \
+ if (G.debug & G_DEBUG_DEPSGRAPH_##type) { \
+ fprintf(stdout, __VA_ARGS__); \
+ } \
+ } while (0)
+
+#define DEG_ERROR_PRINTF(...) \
+ do { \
+ fprintf(stderr, __VA_ARGS__); \
+ fflush(stderr); \
+ } while (0)
bool terminal_do_color(void);
string color_for_pointer(const void *pointer);
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
index 34f68528059..abd3b398cb7 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc
@@ -30,7 +30,7 @@
extern "C" {
#include "DNA_listBase.h"
-} /* extern "C" */
+} /* extern "C" */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
@@ -60,547 +60,546 @@ static float deg_debug_graphviz_node_label_size = 14.0f;
static const int deg_debug_max_colors = 12;
#ifdef COLOR_SCHEME_NODE_TYPE
static const char *deg_debug_colors[] = {
- "#a6cee3", "#1f78b4", "#b2df8a",
- "#33a02c", "#fb9a99", "#e31a1c",
- "#fdbf6f", "#ff7f00", "#cab2d6",
- "#6a3d9a", "#ffff99", "#b15928",
+ "#a6cee3",
+ "#1f78b4",
+ "#b2df8a",
+ "#33a02c",
+ "#fb9a99",
+ "#e31a1c",
+ "#fdbf6f",
+ "#ff7f00",
+ "#cab2d6",
+ "#6a3d9a",
+ "#ffff99",
+ "#b15928",
"#ff00ff",
};
#endif
static const char *deg_debug_colors_light[] = {
- "#8dd3c7", "#ffffb3", "#bebada",
- "#fb8072", "#80b1d3", "#fdb462",
- "#b3de69", "#fccde5", "#d9d9d9",
- "#bc80bd", "#ccebc5", "#ffed6f",
+ "#8dd3c7",
+ "#ffffb3",
+ "#bebada",
+ "#fb8072",
+ "#80b1d3",
+ "#fdb462",
+ "#b3de69",
+ "#fccde5",
+ "#d9d9d9",
+ "#bc80bd",
+ "#ccebc5",
+ "#ffed6f",
"#ff00ff",
};
#ifdef COLOR_SCHEME_NODE_TYPE
static const int deg_debug_node_type_color_map[][2] = {
- {NodeType::TIMESOURCE, 0},
- {NodeType::ID_REF, 1},
+ {NodeType::TIMESOURCE, 0},
+ {NodeType::ID_REF, 1},
/* Outer Types */
- {NodeType::PARAMETERS, 2},
- {NodeType::PROXY, 3},
- {NodeType::ANIMATION, 4},
- {NodeType::TRANSFORM, 5},
- {NodeType::GEOMETRY, 6},
- {NodeType::SEQUENCER, 7},
- {NodeType::SHADING, 8},
+ {NodeType::PARAMETERS, 2},
+ {NodeType::PROXY, 3},
+ {NodeType::ANIMATION, 4},
+ {NodeType::TRANSFORM, 5},
+ {NodeType::GEOMETRY, 6},
+ {NodeType::SEQUENCER, 7},
+ {NodeType::SHADING, 8},
{NodeType::SHADING_PARAMETERS, 9},
- {NodeType::CACHE, 10},
- {NodeType::POINT_CACHE, 11},
- {NodeType::LAYER_COLLECTIONS, 12},
- {NodeType::COPY_ON_WRITE, 13},
- {-1, 0},
+ {NodeType::CACHE, 10},
+ {NodeType::POINT_CACHE, 11},
+ {NodeType::LAYER_COLLECTIONS, 12},
+ {NodeType::COPY_ON_WRITE, 13},
+ {-1, 0},
};
#endif
static int deg_debug_node_color_index(const Node *node)
{
#ifdef COLOR_SCHEME_NODE_CLASS
- /* Some special types. */
- switch (node->type) {
- case NodeType::ID_REF:
- return 5;
- case NodeType::OPERATION:
- {
- OperationNode *op_node = (OperationNode *)node;
- if (op_node->is_noop())
- return 8;
- break;
- }
-
- default:
- break;
- }
- /* Do others based on class. */
- switch (node->get_class()) {
- case NodeClass::OPERATION:
- return 4;
- case NodeClass::COMPONENT:
- return 1;
- default:
- return 9;
- }
+ /* Some special types. */
+ switch (node->type) {
+ case NodeType::ID_REF:
+ return 5;
+ case NodeType::OPERATION: {
+ OperationNode *op_node = (OperationNode *)node;
+ if (op_node->is_noop())
+ return 8;
+ break;
+ }
+
+ default:
+ break;
+ }
+ /* Do others based on class. */
+ switch (node->get_class()) {
+ case NodeClass::OPERATION:
+ return 4;
+ case NodeClass::COMPONENT:
+ return 1;
+ default:
+ return 9;
+ }
#endif
#ifdef COLOR_SCHEME_NODE_TYPE
- const int (*pair)[2];
- for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
- if ((*pair)[0] == node->type) {
- return (*pair)[1];
- }
- }
- return -1;
+ const int(*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ if ((*pair)[0] == node->type) {
+ return (*pair)[1];
+ }
+ }
+ return -1;
#endif
}
struct DebugContext {
- FILE *file;
- bool show_tags;
+ FILE *file;
+ bool show_tags;
};
-static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+ ATTR_PRINTF_FORMAT(2, 3);
static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- vfprintf(ctx.file, fmt, args);
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(ctx.file, fmt, args);
+ va_end(args);
}
static void deg_debug_graphviz_legend_color(const DebugContext &ctx,
const char *name,
const char *color)
{
- deg_debug_fprintf(ctx, "<TR>");
- deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
- deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color);
- deg_debug_fprintf(ctx, "</TR>" NL);
+ deg_debug_fprintf(ctx, "<TR>");
+ deg_debug_fprintf(ctx, "<TD>%s</TD>", name);
+ deg_debug_fprintf(ctx, "<TD BGCOLOR=\"%s\"></TD>", color);
+ deg_debug_fprintf(ctx, "</TR>" NL);
}
static void deg_debug_graphviz_legend(const DebugContext &ctx)
{
- deg_debug_fprintf(ctx, "{" NL);
- deg_debug_fprintf(ctx, "rank = sink;" NL);
- deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL);
- deg_debug_fprintf(ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL);
- deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL);
+ deg_debug_fprintf(ctx, "{" NL);
+ deg_debug_fprintf(ctx, "rank = sink;" NL);
+ deg_debug_fprintf(ctx, "Legend [shape=none, margin=0, label=<" NL);
+ deg_debug_fprintf(
+ ctx, " <TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"4\">" NL);
+ deg_debug_fprintf(ctx, "<TR><TD COLSPAN=\"2\"><B>Legend</B></TD></TR>" NL);
#ifdef COLOR_SCHEME_NODE_CLASS
- const char **colors = deg_debug_colors_light;
- deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]);
- deg_debug_graphviz_legend_color(ctx, "Component", colors[1]);
- deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]);
- deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]);
+ const char **colors = deg_debug_colors_light;
+ deg_debug_graphviz_legend_color(ctx, "Operation", colors[4]);
+ deg_debug_graphviz_legend_color(ctx, "Component", colors[1]);
+ deg_debug_graphviz_legend_color(ctx, "ID Node", colors[5]);
+ deg_debug_graphviz_legend_color(ctx, "NOOP", colors[8]);
#endif
#ifdef COLOR_SCHEME_NODE_TYPE
- const int (*pair)[2];
- for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
- DepsNodeFactory *nti = type_get_factory((NodeType)(*pair)[0]);
- deg_debug_graphviz_legend_color(ctx,
- nti->tname().c_str(),
- deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
- }
+ const int(*pair)[2];
+ for (pair = deg_debug_node_type_color_map; (*pair)[0] >= 0; ++pair) {
+ DepsNodeFactory *nti = type_get_factory((NodeType)(*pair)[0]);
+ deg_debug_graphviz_legend_color(
+ ctx, nti->tname().c_str(), deg_debug_colors_light[(*pair)[1] % deg_debug_max_colors]);
+ }
#endif
- deg_debug_fprintf(ctx, "</TABLE>" NL);
- deg_debug_fprintf(ctx, ">" NL);
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, "}" NL);
+ deg_debug_fprintf(ctx, "</TABLE>" NL);
+ deg_debug_fprintf(ctx, ">" NL);
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, "}" NL);
}
-static void deg_debug_graphviz_node_color(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_color(const DebugContext &ctx, const Node *node)
{
- const char *color_default = "black";
- const char *color_modified = "orangered4";
- const char *color_update = "dodgerblue3";
- const char *color = color_default;
- if (ctx.show_tags) {
- if (node->get_class() == NodeClass::OPERATION) {
- OperationNode *op_node = (OperationNode *)node;
- if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
- color = color_modified;
- }
- else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- color = color_update;
- }
- }
- }
- deg_debug_fprintf(ctx, "\"%s\"", color);
+ const char *color_default = "black";
+ const char *color_modified = "orangered4";
+ const char *color_update = "dodgerblue3";
+ const char *color = color_default;
+ if (ctx.show_tags) {
+ if (node->get_class() == NodeClass::OPERATION) {
+ OperationNode *op_node = (OperationNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ color = color_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ color = color_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%s\"", color);
}
-static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_penwidth(const DebugContext &ctx, const Node *node)
{
- float penwidth_default = 1.0f;
- float penwidth_modified = 4.0f;
- float penwidth_update = 4.0f;
- float penwidth = penwidth_default;
- if (ctx.show_tags) {
- if (node->get_class() == NodeClass::OPERATION) {
- OperationNode *op_node = (OperationNode *)node;
- if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
- penwidth = penwidth_modified;
- }
- else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- penwidth = penwidth_update;
- }
- }
- }
- deg_debug_fprintf(ctx, "\"%f\"", penwidth);
+ float penwidth_default = 1.0f;
+ float penwidth_modified = 4.0f;
+ float penwidth_update = 4.0f;
+ float penwidth = penwidth_default;
+ if (ctx.show_tags) {
+ if (node->get_class() == NodeClass::OPERATION) {
+ OperationNode *op_node = (OperationNode *)node;
+ if (op_node->flag & DEPSOP_FLAG_DIRECTLY_MODIFIED) {
+ penwidth = penwidth_modified;
+ }
+ else if (op_node->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ penwidth = penwidth_update;
+ }
+ }
+ }
+ deg_debug_fprintf(ctx, "\"%f\"", penwidth);
}
-static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_fillcolor(const DebugContext &ctx, const Node *node)
{
- const char *defaultcolor = "gainsboro";
- int color_index = deg_debug_node_color_index(node);
- const char *fillcolor = color_index < 0 ? defaultcolor : deg_debug_colors_light[color_index % deg_debug_max_colors];
- deg_debug_fprintf(ctx, "\"%s\"", fillcolor);
+ const char *defaultcolor = "gainsboro";
+ int color_index = deg_debug_node_color_index(node);
+ const char *fillcolor = color_index < 0 ?
+ defaultcolor :
+ deg_debug_colors_light[color_index % deg_debug_max_colors];
+ deg_debug_fprintf(ctx, "\"%s\"", fillcolor);
}
-static void deg_debug_graphviz_relation_color(const DebugContext &ctx,
- const Relation *rel)
+static void deg_debug_graphviz_relation_color(const DebugContext &ctx, const Relation *rel)
{
- const char *color_default = "black";
- const char *color_cyclic = "red4"; /* The color of crime scene. */
- const char *color_godmode = "blue4"; /* The color of beautiful sky. */
- const char *color = color_default;
- if (rel->flag & RELATION_FLAG_CYCLIC) {
- color = color_cyclic;
- }
- else if (rel->flag & RELATION_FLAG_GODMODE) {
- color = color_godmode;
- }
- deg_debug_fprintf(ctx, "%s", color);
+ const char *color_default = "black";
+ const char *color_cyclic = "red4"; /* The color of crime scene. */
+ const char *color_godmode = "blue4"; /* The color of beautiful sky. */
+ const char *color = color_default;
+ if (rel->flag & RELATION_FLAG_CYCLIC) {
+ color = color_cyclic;
+ }
+ else if (rel->flag & RELATION_FLAG_GODMODE) {
+ color = color_godmode;
+ }
+ deg_debug_fprintf(ctx, "%s", color);
}
-static void deg_debug_graphviz_relation_style(const DebugContext &ctx,
- const Relation *rel)
+static void deg_debug_graphviz_relation_style(const DebugContext &ctx, const Relation *rel)
{
- const char *style_default = "solid";
- const char *style_no_flush = "dashed";
- const char *style_flush_user_only = "dotted";
- const char *style = style_default;
- if (rel->flag & RELATION_FLAG_NO_FLUSH) {
- style = style_no_flush;
- }
- if (rel->flag & RELATION_FLAG_FLUSH_USER_EDIT_ONLY) {
- style = style_flush_user_only;
- }
- deg_debug_fprintf(ctx, "%s", style);
+ const char *style_default = "solid";
+ const char *style_no_flush = "dashed";
+ const char *style_flush_user_only = "dotted";
+ const char *style = style_default;
+ if (rel->flag & RELATION_FLAG_NO_FLUSH) {
+ style = style_no_flush;
+ }
+ if (rel->flag & RELATION_FLAG_FLUSH_USER_EDIT_ONLY) {
+ style = style_flush_user_only;
+ }
+ deg_debug_fprintf(ctx, "%s", style);
}
-static void deg_debug_graphviz_relation_arrowhead(const DebugContext &ctx,
- const Relation *rel)
+static void deg_debug_graphviz_relation_arrowhead(const DebugContext &ctx, const Relation *rel)
{
- const char *shape_default = "normal";
- const char *shape_no_cow = "box";
- const char *shape = shape_default;
- if (rel->from->get_class() == NodeClass::OPERATION &&
- rel->to->get_class() == NodeClass::OPERATION)
- {
- OperationNode *op_from = (OperationNode *)rel->from;
- OperationNode *op_to = (OperationNode *)rel->to;
- if (op_from->owner->type == NodeType::COPY_ON_WRITE &&
- !op_to->owner->need_tag_cow_before_update())
- {
- shape = shape_no_cow;
- }
- }
- deg_debug_fprintf(ctx, "%s", shape);
+ const char *shape_default = "normal";
+ const char *shape_no_cow = "box";
+ const char *shape = shape_default;
+ if (rel->from->get_class() == NodeClass::OPERATION &&
+ rel->to->get_class() == NodeClass::OPERATION) {
+ OperationNode *op_from = (OperationNode *)rel->from;
+ OperationNode *op_to = (OperationNode *)rel->to;
+ if (op_from->owner->type == NodeType::COPY_ON_WRITE &&
+ !op_to->owner->need_tag_cow_before_update()) {
+ shape = shape_no_cow;
+ }
+ }
+ deg_debug_fprintf(ctx, "%s", shape);
}
static void deg_debug_graphviz_node_style(const DebugContext &ctx, const Node *node)
{
- const char *base_style = "filled"; /* default style */
- if (ctx.show_tags) {
- if (node->get_class() == NodeClass::OPERATION) {
- OperationNode *op_node = (OperationNode *)node;
- if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
- base_style = "striped";
- }
- }
- }
- switch (node->get_class()) {
- case NodeClass::GENERIC:
- deg_debug_fprintf(ctx, "\"%s\"", base_style);
- break;
- case NodeClass::COMPONENT:
- deg_debug_fprintf(ctx, "\"%s\"", base_style);
- break;
- case NodeClass::OPERATION:
- deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
- break;
- }
+ const char *base_style = "filled"; /* default style */
+ if (ctx.show_tags) {
+ if (node->get_class() == NodeClass::OPERATION) {
+ OperationNode *op_node = (OperationNode *)node;
+ if (op_node->flag & (DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE)) {
+ base_style = "striped";
+ }
+ }
+ }
+ switch (node->get_class()) {
+ case NodeClass::GENERIC:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case NodeClass::COMPONENT:
+ deg_debug_fprintf(ctx, "\"%s\"", base_style);
+ break;
+ case NodeClass::OPERATION:
+ deg_debug_fprintf(ctx, "\"%s,rounded\"", base_style);
+ break;
+ }
}
-static void deg_debug_graphviz_node_single(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_single(const DebugContext &ctx, const Node *node)
{
- const char *shape = "box";
- string name = node->identifier();
- deg_debug_fprintf(ctx, "// %s\n", name.c_str());
- deg_debug_fprintf(ctx, "\"node_%p\"", node);
- deg_debug_fprintf(ctx, "[");
-// deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
- deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
- deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
- deg_debug_fprintf(ctx, ",shape=%s", shape);
- deg_debug_fprintf(ctx, ",style="); deg_debug_graphviz_node_style(ctx, node);
- deg_debug_fprintf(ctx, ",color="); deg_debug_graphviz_node_color(ctx, node);
- deg_debug_fprintf(ctx, ",fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node);
- deg_debug_fprintf(ctx, ",penwidth="); deg_debug_graphviz_node_penwidth(ctx, node);
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
+ const char *shape = "box";
+ string name = node->identifier();
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+ // deg_debug_fprintf(ctx, "label=<<B>%s</B>>", name);
+ deg_debug_fprintf(ctx, "label=<%s>", name.c_str());
+ deg_debug_fprintf(ctx, ",fontname=\"%s\"", deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, ",fontsize=%f", deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, ",shape=%s", shape);
+ deg_debug_fprintf(ctx, ",style=");
+ deg_debug_graphviz_node_style(ctx, node);
+ deg_debug_fprintf(ctx, ",color=");
+ deg_debug_graphviz_node_color(ctx, node);
+ deg_debug_fprintf(ctx, ",fillcolor=");
+ deg_debug_graphviz_node_fillcolor(ctx, node);
+ deg_debug_fprintf(ctx, ",penwidth=");
+ deg_debug_graphviz_node_penwidth(ctx, node);
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
}
-static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_cluster_begin(const DebugContext &ctx, const Node *node)
{
- string name = node->identifier();
- deg_debug_fprintf(ctx, "// %s\n", name.c_str());
- deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
-// deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
- deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
- deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
- deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
- deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
- deg_debug_fprintf(ctx, "style="); deg_debug_graphviz_node_style(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "color="); deg_debug_graphviz_node_color(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "fillcolor="); deg_debug_graphviz_node_fillcolor(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- deg_debug_fprintf(ctx, "penwidth="); deg_debug_graphviz_node_penwidth(ctx, node); deg_debug_fprintf(ctx, ";" NL);
- /* dummy node, so we can add edges between clusters */
- deg_debug_fprintf(ctx, "\"node_%p\"", node);
- deg_debug_fprintf(ctx, "[");
- deg_debug_fprintf(ctx, "shape=%s", "point");
- deg_debug_fprintf(ctx, ",style=%s", "invis");
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
+ string name = node->identifier();
+ deg_debug_fprintf(ctx, "// %s\n", name.c_str());
+ deg_debug_fprintf(ctx, "subgraph \"cluster_%p\" {" NL, node);
+ // deg_debug_fprintf(ctx, "label=<<B>%s</B>>;" NL, name);
+ deg_debug_fprintf(ctx, "label=<%s>;" NL, name.c_str());
+ deg_debug_fprintf(ctx, "fontname=\"%s\";" NL, deg_debug_graphviz_fontname);
+ deg_debug_fprintf(ctx, "fontsize=%f;" NL, deg_debug_graphviz_node_label_size);
+ deg_debug_fprintf(ctx, "margin=\"%d\";" NL, 16);
+ deg_debug_fprintf(ctx, "style=");
+ deg_debug_graphviz_node_style(ctx, node);
+ deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "color=");
+ deg_debug_graphviz_node_color(ctx, node);
+ deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "fillcolor=");
+ deg_debug_graphviz_node_fillcolor(ctx, node);
+ deg_debug_fprintf(ctx, ";" NL);
+ deg_debug_fprintf(ctx, "penwidth=");
+ deg_debug_graphviz_node_penwidth(ctx, node);
+ deg_debug_fprintf(ctx, ";" NL);
+ /* dummy node, so we can add edges between clusters */
+ deg_debug_fprintf(ctx, "\"node_%p\"", node);
+ deg_debug_fprintf(ctx, "[");
+ deg_debug_fprintf(ctx, "shape=%s", "point");
+ deg_debug_fprintf(ctx, ",style=%s", "invis");
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
}
static void deg_debug_graphviz_node_cluster_end(const DebugContext &ctx)
{
- deg_debug_fprintf(ctx, "}" NL);
- deg_debug_fprintf(ctx, NL);
+ deg_debug_fprintf(ctx, "}" NL);
+ deg_debug_fprintf(ctx, NL);
}
-static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
- const Depsgraph *graph);
-static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
- const Depsgraph *graph);
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgraph *graph);
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph);
-static void deg_debug_graphviz_node(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node)
{
- switch (node->type) {
- case NodeType::ID_REF:
- {
- const IDNode *id_node = (const IDNode *)node;
- if (BLI_ghash_len(id_node->components) == 0) {
- deg_debug_graphviz_node_single(ctx, node);
- }
- else {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- GHASH_FOREACH_BEGIN(const ComponentNode *, comp, id_node->components)
- {
- deg_debug_graphviz_node(ctx, comp);
- }
- GHASH_FOREACH_END();
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- break;
- }
- case NodeType::PARAMETERS:
- case NodeType::ANIMATION:
- case NodeType::TRANSFORM:
- case NodeType::PROXY:
- case NodeType::GEOMETRY:
- case NodeType::SEQUENCER:
- case NodeType::EVAL_POSE:
- case NodeType::BONE:
- case NodeType::SHADING:
- case NodeType::SHADING_PARAMETERS:
- case NodeType::CACHE:
- case NodeType::POINT_CACHE:
- case NodeType::LAYER_COLLECTIONS:
- case NodeType::PARTICLE_SYSTEM:
- case NodeType::PARTICLE_SETTINGS:
- case NodeType::COPY_ON_WRITE:
- case NodeType::OBJECT_FROM_LAYER:
- case NodeType::BATCH_CACHE:
- case NodeType::DUPLI:
- case NodeType::SYNCHRONIZATION:
- case NodeType::GENERIC_DATABLOCK:
- {
- ComponentNode *comp_node = (ComponentNode *)node;
- if (!comp_node->operations.empty()) {
- deg_debug_graphviz_node_cluster_begin(ctx, node);
- for (Node *op_node : comp_node->operations) {
- deg_debug_graphviz_node(ctx, op_node);
- }
- deg_debug_graphviz_node_cluster_end(ctx);
- }
- else {
- deg_debug_graphviz_node_single(ctx, node);
- }
- break;
- }
- case NodeType::UNDEFINED:
- case NodeType::TIMESOURCE:
- case NodeType::OPERATION:
- deg_debug_graphviz_node_single(ctx, node);
- break;
- case NodeType::NUM_TYPES:
- break;
- }
+ switch (node->type) {
+ case NodeType::ID_REF: {
+ const IDNode *id_node = (const IDNode *)node;
+ if (BLI_ghash_len(id_node->components) == 0) {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ else {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ GHASH_FOREACH_BEGIN (const ComponentNode *, comp, id_node->components) {
+ deg_debug_graphviz_node(ctx, comp);
+ }
+ GHASH_FOREACH_END();
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ break;
+ }
+ case NodeType::PARAMETERS:
+ case NodeType::ANIMATION:
+ case NodeType::TRANSFORM:
+ case NodeType::PROXY:
+ case NodeType::GEOMETRY:
+ case NodeType::SEQUENCER:
+ case NodeType::EVAL_POSE:
+ case NodeType::BONE:
+ case NodeType::SHADING:
+ case NodeType::SHADING_PARAMETERS:
+ case NodeType::CACHE:
+ case NodeType::POINT_CACHE:
+ case NodeType::LAYER_COLLECTIONS:
+ case NodeType::PARTICLE_SYSTEM:
+ case NodeType::PARTICLE_SETTINGS:
+ case NodeType::COPY_ON_WRITE:
+ case NodeType::OBJECT_FROM_LAYER:
+ case NodeType::BATCH_CACHE:
+ case NodeType::DUPLI:
+ case NodeType::SYNCHRONIZATION:
+ case NodeType::GENERIC_DATABLOCK: {
+ ComponentNode *comp_node = (ComponentNode *)node;
+ if (!comp_node->operations.empty()) {
+ deg_debug_graphviz_node_cluster_begin(ctx, node);
+ for (Node *op_node : comp_node->operations) {
+ deg_debug_graphviz_node(ctx, op_node);
+ }
+ deg_debug_graphviz_node_cluster_end(ctx);
+ }
+ else {
+ deg_debug_graphviz_node_single(ctx, node);
+ }
+ break;
+ }
+ case NodeType::UNDEFINED:
+ case NodeType::TIMESOURCE:
+ case NodeType::OPERATION:
+ deg_debug_graphviz_node_single(ctx, node);
+ break;
+ case NodeType::NUM_TYPES:
+ break;
+ }
}
static bool deg_debug_graphviz_is_cluster(const Node *node)
{
- switch (node->type) {
- case NodeType::ID_REF:
- {
- const IDNode *id_node = (const IDNode *)node;
- return BLI_ghash_len(id_node->components) > 0;
- }
- case NodeType::PARAMETERS:
- case NodeType::ANIMATION:
- case NodeType::TRANSFORM:
- case NodeType::PROXY:
- case NodeType::GEOMETRY:
- case NodeType::SEQUENCER:
- case NodeType::EVAL_POSE:
- case NodeType::BONE:
- {
- ComponentNode *comp_node = (ComponentNode *)node;
- return !comp_node->operations.empty();
- }
- default:
- return false;
- }
+ switch (node->type) {
+ case NodeType::ID_REF: {
+ const IDNode *id_node = (const IDNode *)node;
+ return BLI_ghash_len(id_node->components) > 0;
+ }
+ case NodeType::PARAMETERS:
+ case NodeType::ANIMATION:
+ case NodeType::TRANSFORM:
+ case NodeType::PROXY:
+ case NodeType::GEOMETRY:
+ case NodeType::SEQUENCER:
+ case NodeType::EVAL_POSE:
+ case NodeType::BONE: {
+ ComponentNode *comp_node = (ComponentNode *)node;
+ return !comp_node->operations.empty();
+ }
+ default:
+ return false;
+ }
}
-static bool deg_debug_graphviz_is_owner(const Node *node,
- const Node *other)
+static bool deg_debug_graphviz_is_owner(const Node *node, const Node *other)
{
- switch (node->get_class()) {
- case NodeClass::COMPONENT:
- {
- ComponentNode *comp_node = (ComponentNode *)node;
- if (comp_node->owner == other)
- return true;
- break;
- }
- case NodeClass::OPERATION:
- {
- OperationNode *op_node = (OperationNode *)node;
- if (op_node->owner == other)
- return true;
- else if (op_node->owner->owner == other)
- return true;
- break;
- }
- default: break;
- }
- return false;
+ switch (node->get_class()) {
+ case NodeClass::COMPONENT: {
+ ComponentNode *comp_node = (ComponentNode *)node;
+ if (comp_node->owner == other)
+ return true;
+ break;
+ }
+ case NodeClass::OPERATION: {
+ OperationNode *op_node = (OperationNode *)node;
+ if (op_node->owner == other)
+ return true;
+ else if (op_node->owner->owner == other)
+ return true;
+ break;
+ }
+ default:
+ break;
+ }
+ return false;
}
-static void deg_debug_graphviz_node_relations(const DebugContext &ctx,
- const Node *node)
+static void deg_debug_graphviz_node_relations(const DebugContext &ctx, const Node *node)
{
- for (Relation *rel : node->inlinks) {
- float penwidth = 2.0f;
-
- const Node *tail = rel->to; /* same as node */
- const Node *head = rel->from;
- deg_debug_fprintf(ctx, "// %s -> %s\n",
- head->identifier().c_str(),
- tail->identifier().c_str());
- deg_debug_fprintf(ctx, "\"node_%p\"", head);
- deg_debug_fprintf(ctx, " -> ");
- deg_debug_fprintf(ctx, "\"node_%p\"", tail);
-
- deg_debug_fprintf(ctx, "[");
- /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
- deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
- // deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
- deg_debug_fprintf(ctx, ",color=");
- deg_debug_graphviz_relation_color(ctx, rel);
- deg_debug_fprintf(ctx, ",style=");
- deg_debug_graphviz_relation_style(ctx, rel);
- deg_debug_fprintf(ctx, ",arrowhead=");
- deg_debug_graphviz_relation_arrowhead(ctx, rel);
- deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
- /* NOTE: edge from node to own cluster is not possible and gives graphviz
- * warning, avoid this here by just linking directly to the invisible
- * placeholder node. */
- if (deg_debug_graphviz_is_cluster(tail) &&
- !deg_debug_graphviz_is_owner(head, tail))
- {
- deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
- }
- if (deg_debug_graphviz_is_cluster(head) &&
- !deg_debug_graphviz_is_owner(tail, head))
- {
- deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
- }
- deg_debug_fprintf(ctx, "];" NL);
- deg_debug_fprintf(ctx, NL);
- }
+ for (Relation *rel : node->inlinks) {
+ float penwidth = 2.0f;
+
+ const Node *tail = rel->to; /* same as node */
+ const Node *head = rel->from;
+ deg_debug_fprintf(
+ ctx, "// %s -> %s\n", head->identifier().c_str(), tail->identifier().c_str());
+ deg_debug_fprintf(ctx, "\"node_%p\"", head);
+ deg_debug_fprintf(ctx, " -> ");
+ deg_debug_fprintf(ctx, "\"node_%p\"", tail);
+
+ deg_debug_fprintf(ctx, "[");
+ /* Note: without label an id seem necessary to avoid bugs in graphviz/dot */
+ deg_debug_fprintf(ctx, "id=\"%s\"", rel->name);
+ // deg_debug_fprintf(ctx, "label=\"%s\"", rel->name);
+ deg_debug_fprintf(ctx, ",color=");
+ deg_debug_graphviz_relation_color(ctx, rel);
+ deg_debug_fprintf(ctx, ",style=");
+ deg_debug_graphviz_relation_style(ctx, rel);
+ deg_debug_fprintf(ctx, ",arrowhead=");
+ deg_debug_graphviz_relation_arrowhead(ctx, rel);
+ deg_debug_fprintf(ctx, ",penwidth=\"%f\"", penwidth);
+ /* NOTE: edge from node to own cluster is not possible and gives graphviz
+ * warning, avoid this here by just linking directly to the invisible
+ * placeholder node. */
+ if (deg_debug_graphviz_is_cluster(tail) && !deg_debug_graphviz_is_owner(head, tail)) {
+ deg_debug_fprintf(ctx, ",ltail=\"cluster_%p\"", tail);
+ }
+ if (deg_debug_graphviz_is_cluster(head) && !deg_debug_graphviz_is_owner(tail, head)) {
+ deg_debug_fprintf(ctx, ",lhead=\"cluster_%p\"", head);
+ }
+ deg_debug_fprintf(ctx, "];" NL);
+ deg_debug_fprintf(ctx, NL);
+ }
}
-static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx,
- const Depsgraph *graph)
+static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgraph *graph)
{
- for (Node *node : graph->id_nodes) {
- deg_debug_graphviz_node(ctx, node);
- }
- TimeSourceNode *time_source = graph->find_time_source();
- if (time_source != NULL) {
- deg_debug_graphviz_node(ctx, time_source);
- }
+ for (Node *node : graph->id_nodes) {
+ deg_debug_graphviz_node(ctx, node);
+ }
+ TimeSourceNode *time_source = graph->find_time_source();
+ if (time_source != NULL) {
+ deg_debug_graphviz_node(ctx, time_source);
+ }
}
-static void deg_debug_graphviz_graph_relations(const DebugContext &ctx,
- const Depsgraph *graph)
+static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph)
{
- for (IDNode *id_node : graph->id_nodes) {
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- for (OperationNode *op_node : comp_node->operations) {
- deg_debug_graphviz_node_relations(ctx, op_node);
- }
- }
- GHASH_FOREACH_END();
- }
-
- TimeSourceNode *time_source = graph->find_time_source();
- if (time_source != NULL) {
- deg_debug_graphviz_node_relations(ctx, time_source);
- }
+ for (IDNode *id_node : graph->id_nodes) {
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ for (OperationNode *op_node : comp_node->operations) {
+ deg_debug_graphviz_node_relations(ctx, op_node);
+ }
+ }
+ GHASH_FOREACH_END();
+ }
+
+ TimeSourceNode *time_source = graph->find_time_source();
+ if (time_source != NULL) {
+ deg_debug_graphviz_node_relations(ctx, time_source);
+ }
}
} // namespace DEG
-void DEG_debug_relations_graphviz(const Depsgraph *graph,
- FILE *f,
- const char *label)
+void DEG_debug_relations_graphviz(const Depsgraph *graph, FILE *f, const char *label)
{
- if (!graph) {
- return;
- }
+ if (!graph) {
+ return;
+ }
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- DEG::DebugContext ctx;
- ctx.file = f;
+ DEG::DebugContext ctx;
+ ctx.file = f;
- DEG::deg_debug_fprintf(ctx, "digraph depgraph {" NL);
- DEG::deg_debug_fprintf(ctx, "rankdir=LR;" NL);
- DEG::deg_debug_fprintf(ctx, "graph [");
- DEG::deg_debug_fprintf(ctx, "compound=true");
- DEG::deg_debug_fprintf(ctx, ",labelloc=\"t\"");
- DEG::deg_debug_fprintf(ctx, ",fontsize=%f", DEG::deg_debug_graphviz_graph_label_size);
- DEG::deg_debug_fprintf(ctx, ",fontname=\"%s\"", DEG::deg_debug_graphviz_fontname);
- DEG::deg_debug_fprintf(ctx, ",label=\"%s\"", label);
- DEG::deg_debug_fprintf(ctx, ",splines=ortho");
- DEG::deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato
- DEG::deg_debug_fprintf(ctx, "];" NL);
+ DEG::deg_debug_fprintf(ctx, "digraph depgraph {" NL);
+ DEG::deg_debug_fprintf(ctx, "rankdir=LR;" NL);
+ DEG::deg_debug_fprintf(ctx, "graph [");
+ DEG::deg_debug_fprintf(ctx, "compound=true");
+ DEG::deg_debug_fprintf(ctx, ",labelloc=\"t\"");
+ DEG::deg_debug_fprintf(ctx, ",fontsize=%f", DEG::deg_debug_graphviz_graph_label_size);
+ DEG::deg_debug_fprintf(ctx, ",fontname=\"%s\"", DEG::deg_debug_graphviz_fontname);
+ DEG::deg_debug_fprintf(ctx, ",label=\"%s\"", label);
+ DEG::deg_debug_fprintf(ctx, ",splines=ortho");
+ DEG::deg_debug_fprintf(ctx, ",overlap=scalexy"); // XXX: only when using neato
+ DEG::deg_debug_fprintf(ctx, "];" NL);
- DEG::deg_debug_graphviz_graph_nodes(ctx, deg_graph);
- DEG::deg_debug_graphviz_graph_relations(ctx, deg_graph);
+ DEG::deg_debug_graphviz_graph_nodes(ctx, deg_graph);
+ DEG::deg_debug_graphviz_graph_relations(ctx, deg_graph);
- DEG::deg_debug_graphviz_legend(ctx);
+ DEG::deg_debug_graphviz_legend(ctx);
- DEG::deg_debug_fprintf(ctx, "}" NL);
+ DEG::deg_debug_fprintf(ctx, "}" NL);
}
#undef NL
diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
index 41b22c0c23a..b4cf30685a2 100644
--- a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
+++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc
@@ -42,112 +42,110 @@ namespace DEG {
namespace {
struct DebugContext {
- FILE *file;
- const Depsgraph *graph;
- const char *label;
- const char *output_filename;
+ FILE *file;
+ const Depsgraph *graph;
+ const char *label;
+ const char *output_filename;
};
struct StatsEntry {
- const IDNode *id_node;
- double time;
+ const IDNode *id_node;
+ double time;
};
/* TODO(sergey): De-duplicate with graphviz relation debugger. */
-static void deg_debug_fprintf(const DebugContext &ctx,
- const char *fmt,
- ...) ATTR_PRINTF_FORMAT(2, 3);
+static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
+ ATTR_PRINTF_FORMAT(2, 3);
static void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
{
- va_list args;
- va_start(args, fmt);
- vfprintf(ctx.file, fmt, args);
- va_end(args);
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(ctx.file, fmt, args);
+ va_end(args);
}
-BLI_INLINE double get_node_time(const DebugContext& /*ctx*/,
- const Node *node)
+BLI_INLINE double get_node_time(const DebugContext & /*ctx*/, const Node *node)
{
- // TODO(sergey): Figure out a nice way to define which exact time
- // we want to show.
- return node->stats.current_time;
+ // TODO(sergey): Figure out a nice way to define which exact time
+ // we want to show.
+ return node->stats.current_time;
}
-bool stat_entry_comparator(const StatsEntry& a, const StatsEntry& b)
+bool stat_entry_comparator(const StatsEntry &a, const StatsEntry &b)
{
- return a.time > b.time;
+ return a.time > b.time;
}
-string gnuplotify_id_code(const string& name)
+string gnuplotify_id_code(const string &name)
{
- return string("") + name[0] + name[1];
+ return string("") + name[0] + name[1];
}
-string gnuplotify_name(const string& name)
+string gnuplotify_name(const string &name)
{
- string result = "";
- const int length = name.length();
- for (int i = 0; i < length; ++i) {
- const char ch = name[i];
- if (ch == '_') {
- result += "\\\\\\";
- }
- result += ch;
- }
- return result;
+ string result = "";
+ const int length = name.length();
+ for (int i = 0; i < length; ++i) {
+ const char ch = name[i];
+ if (ch == '_') {
+ result += "\\\\\\";
+ }
+ result += ch;
+ }
+ return result;
}
-void write_stats_data(const DebugContext& ctx)
+void write_stats_data(const DebugContext &ctx)
{
- // Fill in array of all stats which are to be displayed.
- vector<StatsEntry> stats;
- stats.reserve(ctx.graph->id_nodes.size());
- for (const IDNode *id_node : ctx.graph->id_nodes) {
- const double time = get_node_time(ctx, id_node);
- if (time == 0.0) {
- continue;
- }
- StatsEntry entry;
- entry.id_node = id_node;
- entry.time = time;
- stats.push_back(entry);
- }
- // Sort the data.
- std::sort(stats.begin(), stats.end(), stat_entry_comparator);
- // We limit number of entries, otherwise things become unreadable.
- stats.resize(min_ii(stats.size(), 32));
- std::reverse(stats.begin(), stats.end());
- // Print data to the file stream.
- deg_debug_fprintf(ctx, "$data << EOD" NL);
- for (const StatsEntry& entry : stats) {
- deg_debug_fprintf(
- ctx, "\"[%s] %s\",%f" NL,
- gnuplotify_id_code(entry.id_node->id_orig->name).c_str(),
- gnuplotify_name(entry.id_node->id_orig->name + 2).c_str(),
- entry.time);
- }
- deg_debug_fprintf(ctx, "EOD" NL);
+ // Fill in array of all stats which are to be displayed.
+ vector<StatsEntry> stats;
+ stats.reserve(ctx.graph->id_nodes.size());
+ for (const IDNode *id_node : ctx.graph->id_nodes) {
+ const double time = get_node_time(ctx, id_node);
+ if (time == 0.0) {
+ continue;
+ }
+ StatsEntry entry;
+ entry.id_node = id_node;
+ entry.time = time;
+ stats.push_back(entry);
+ }
+ // Sort the data.
+ std::sort(stats.begin(), stats.end(), stat_entry_comparator);
+ // We limit number of entries, otherwise things become unreadable.
+ stats.resize(min_ii(stats.size(), 32));
+ std::reverse(stats.begin(), stats.end());
+ // Print data to the file stream.
+ deg_debug_fprintf(ctx, "$data << EOD" NL);
+ for (const StatsEntry &entry : stats) {
+ deg_debug_fprintf(ctx,
+ "\"[%s] %s\",%f" NL,
+ gnuplotify_id_code(entry.id_node->id_orig->name).c_str(),
+ gnuplotify_name(entry.id_node->id_orig->name + 2).c_str(),
+ entry.time);
+ }
+ deg_debug_fprintf(ctx, "EOD" NL);
}
-void deg_debug_stats_gnuplot(const DebugContext& ctx)
+void deg_debug_stats_gnuplot(const DebugContext &ctx)
{
- // Data itself.
- write_stats_data(ctx);
- // Optional label.
- if (ctx.label && ctx.label[0]) {
- deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
- }
- // Rest of the commands.
- // TODO(sergey): Need to decide on the resolution somehow.
- deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
- deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
- deg_debug_fprintf(ctx, "set grid" NL);
- deg_debug_fprintf(ctx, "set datafile separator ','" NL);
- deg_debug_fprintf(ctx, "set style fill solid" NL);
- deg_debug_fprintf(ctx, "plot \"$data\" using " \
- "($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
- "with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
-
+ // Data itself.
+ write_stats_data(ctx);
+ // Optional label.
+ if (ctx.label && ctx.label[0]) {
+ deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
+ }
+ // Rest of the commands.
+ // TODO(sergey): Need to decide on the resolution somehow.
+ deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
+ deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
+ deg_debug_fprintf(ctx, "set grid" NL);
+ deg_debug_fprintf(ctx, "set datafile separator ','" NL);
+ deg_debug_fprintf(ctx, "set style fill solid" NL);
+ deg_debug_fprintf(ctx,
+ "plot \"$data\" using "
+ "($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
+ "with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
}
} // namespace
@@ -158,13 +156,13 @@ void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph,
const char *label,
const char *output_filename)
{
- if (depsgraph == NULL) {
- return;
- }
- DEG::DebugContext ctx;
- ctx.file = f;
- ctx.graph = (DEG::Depsgraph *)depsgraph;
- ctx.label = label;
- ctx.output_filename = output_filename;
- DEG::deg_debug_stats_gnuplot(ctx);
+ if (depsgraph == NULL) {
+ return;
+ }
+ DEG::DebugContext ctx;
+ ctx.file = f;
+ ctx.graph = (DEG::Depsgraph *)depsgraph;
+ ctx.label = label;
+ ctx.output_filename = output_filename;
+ DEG::deg_debug_stats_gnuplot(ctx);
}
diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc
index 43bdba55360..e2a9dde1eea 100644
--- a/source/blender/depsgraph/intern/depsgraph.cc
+++ b/source/blender/depsgraph/intern/depsgraph.cc
@@ -59,206 +59,195 @@ extern "C" {
namespace DEG {
/* TODO(sergey): Find a better place for this. */
-template <typename T>
-static void remove_from_vector(vector<T> *vector, const T& value)
+template<typename T> static void remove_from_vector(vector<T> *vector, const T &value)
{
- vector->erase(std::remove(vector->begin(), vector->end(), value),
- vector->end());
+ vector->erase(std::remove(vector->begin(), vector->end(), value), vector->end());
}
-Depsgraph::Depsgraph(Scene *scene,
- ViewLayer *view_layer,
- eEvaluationMode mode)
- : time_source(NULL),
- need_update(true),
- scene(scene),
- view_layer(view_layer),
- mode(mode),
- ctime(BKE_scene_frame_get(scene)),
- scene_cow(NULL),
- is_active(false),
- debug_is_evaluating(false)
+Depsgraph::Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
+ : time_source(NULL),
+ need_update(true),
+ scene(scene),
+ view_layer(view_layer),
+ mode(mode),
+ ctime(BKE_scene_frame_get(scene)),
+ scene_cow(NULL),
+ is_active(false),
+ debug_is_evaluating(false)
{
- BLI_spin_init(&lock);
- id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
- entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
- debug_flags = G.debug;
- memset(id_type_updated, 0, sizeof(id_type_updated));
- memset(physics_relations, 0, sizeof(physics_relations));
+ BLI_spin_init(&lock);
+ id_hash = BLI_ghash_ptr_new("Depsgraph id hash");
+ entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags");
+ debug_flags = G.debug;
+ memset(id_type_updated, 0, sizeof(id_type_updated));
+ memset(physics_relations, 0, sizeof(physics_relations));
}
Depsgraph::~Depsgraph()
{
- clear_id_nodes();
- BLI_ghash_free(id_hash, NULL, NULL);
- BLI_gset_free(entry_tags, NULL);
- if (time_source != NULL) {
- OBJECT_GUARDED_DELETE(time_source, TimeSourceNode);
- }
- BLI_spin_end(&lock);
+ clear_id_nodes();
+ BLI_ghash_free(id_hash, NULL, NULL);
+ BLI_gset_free(entry_tags, NULL);
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceNode);
+ }
+ BLI_spin_end(&lock);
}
/* Node Management ---------------------------- */
TimeSourceNode *Depsgraph::add_time_source()
{
- if (time_source == NULL) {
- DepsNodeFactory *factory = type_get_factory(NodeType::TIMESOURCE);
- time_source = (TimeSourceNode *)factory->create_node(NULL, "", "Time Source");
- }
- return time_source;
+ if (time_source == NULL) {
+ DepsNodeFactory *factory = type_get_factory(NodeType::TIMESOURCE);
+ time_source = (TimeSourceNode *)factory->create_node(NULL, "", "Time Source");
+ }
+ return time_source;
}
TimeSourceNode *Depsgraph::find_time_source() const
{
- return time_source;
+ return time_source;
}
IDNode *Depsgraph::find_id_node(const ID *id) const
{
- return reinterpret_cast<IDNode *>(BLI_ghash_lookup(id_hash, id));
+ return reinterpret_cast<IDNode *>(BLI_ghash_lookup(id_hash, id));
}
IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint)
{
- BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
- IDNode *id_node = find_id_node(id);
- if (!id_node) {
- DepsNodeFactory *factory = type_get_factory(NodeType::ID_REF);
- id_node = (IDNode *)factory->create_node(id, "", id->name);
- id_node->init_copy_on_write(id_cow_hint);
- /* Register node in ID hash.
- *
- * NOTE: We address ID nodes by the original ID pointer they are
- * referencing to. */
- BLI_ghash_insert(id_hash, id, id_node);
- id_nodes.push_back(id_node);
- }
- return id_node;
+ BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
+ IDNode *id_node = find_id_node(id);
+ if (!id_node) {
+ DepsNodeFactory *factory = type_get_factory(NodeType::ID_REF);
+ id_node = (IDNode *)factory->create_node(id, "", id->name);
+ id_node->init_copy_on_write(id_cow_hint);
+ /* Register node in ID hash.
+ *
+ * NOTE: We address ID nodes by the original ID pointer they are
+ * referencing to. */
+ BLI_ghash_insert(id_hash, id, id_node);
+ id_nodes.push_back(id_node);
+ }
+ return id_node;
}
-void Depsgraph::clear_id_nodes_conditional(const std::function <bool (ID_Type id_type)>& filter)
+void Depsgraph::clear_id_nodes_conditional(const std::function<bool(ID_Type id_type)> &filter)
{
- for (IDNode *id_node : id_nodes) {
- if (id_node->id_cow == NULL) {
- /* This means builder "stole" ownership of the copy-on-written
- * datablock for her own dirty needs. */
- continue;
- }
- if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
- continue;
- }
- const ID_Type id_type = GS(id_node->id_cow->name);
- if (filter(id_type)) {
- id_node->destroy();
- }
- }
+ for (IDNode *id_node : id_nodes) {
+ if (id_node->id_cow == NULL) {
+ /* This means builder "stole" ownership of the copy-on-written
+ * datablock for her own dirty needs. */
+ continue;
+ }
+ if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ continue;
+ }
+ const ID_Type id_type = GS(id_node->id_cow->name);
+ if (filter(id_type)) {
+ id_node->destroy();
+ }
+ }
}
void Depsgraph::clear_id_nodes()
{
- /* Free memory used by ID nodes. */
-
- /* Stupid workaround to ensure we free IDs in a proper order. */
- clear_id_nodes_conditional([](ID_Type id_type) { return id_type == ID_SCE; });
- clear_id_nodes_conditional([](ID_Type id_type) { return id_type != ID_PA; });
-
- for (IDNode *id_node : id_nodes) {
- OBJECT_GUARDED_DELETE(id_node, IDNode);
- }
- /* Clear containers. */
- BLI_ghash_clear(id_hash, NULL, NULL);
- id_nodes.clear();
- /* Clear physics relation caches. */
- clear_physics_relations(this);
+ /* Free memory used by ID nodes. */
+
+ /* Stupid workaround to ensure we free IDs in a proper order. */
+ clear_id_nodes_conditional([](ID_Type id_type) { return id_type == ID_SCE; });
+ clear_id_nodes_conditional([](ID_Type id_type) { return id_type != ID_PA; });
+
+ for (IDNode *id_node : id_nodes) {
+ OBJECT_GUARDED_DELETE(id_node, IDNode);
+ }
+ /* Clear containers. */
+ BLI_ghash_clear(id_hash, NULL, NULL);
+ id_nodes.clear();
+ /* Clear physics relation caches. */
+ clear_physics_relations(this);
}
/* Add new relation between two nodes */
-Relation *Depsgraph::add_new_relation(Node *from, Node *to,
- const char *description,
- int flags)
+Relation *Depsgraph::add_new_relation(Node *from, Node *to, const char *description, int flags)
{
- Relation *rel = NULL;
- if (flags & RELATION_CHECK_BEFORE_ADD) {
- rel = check_nodes_connected(from, to, description);
- }
- if (rel != NULL) {
- rel->flag |= flags;
- return rel;
- }
+ Relation *rel = NULL;
+ if (flags & RELATION_CHECK_BEFORE_ADD) {
+ rel = check_nodes_connected(from, to, description);
+ }
+ if (rel != NULL) {
+ rel->flag |= flags;
+ return rel;
+ }
#ifndef NDEBUG
- if (from->type == NodeType::OPERATION &&
- to->type == NodeType::OPERATION)
- {
- OperationNode *operation_from = static_cast<OperationNode *>(from);
- OperationNode *operation_to = static_cast<OperationNode *>(to);
- BLI_assert(operation_to->owner->type != NodeType::COPY_ON_WRITE ||
- operation_from->owner->type == NodeType::COPY_ON_WRITE);
- }
+ if (from->type == NodeType::OPERATION && to->type == NodeType::OPERATION) {
+ OperationNode *operation_from = static_cast<OperationNode *>(from);
+ OperationNode *operation_to = static_cast<OperationNode *>(to);
+ BLI_assert(operation_to->owner->type != NodeType::COPY_ON_WRITE ||
+ operation_from->owner->type == NodeType::COPY_ON_WRITE);
+ }
#endif
- /* Create new relation, and add it to the graph. */
- rel = OBJECT_GUARDED_NEW(Relation, from, to, description);
- rel->flag |= flags;
- return rel;
+ /* Create new relation, and add it to the graph. */
+ rel = OBJECT_GUARDED_NEW(Relation, from, to, description);
+ rel->flag |= flags;
+ return rel;
}
Relation *Depsgraph::check_nodes_connected(const Node *from,
const Node *to,
const char *description)
{
- for (Relation *rel : from->outlinks) {
- BLI_assert(rel->from == from);
- if (rel->to != to) {
- continue;
- }
- if (description != NULL && !STREQ(rel->name, description)) {
- continue;
- }
- return rel;
- }
- return NULL;
+ for (Relation *rel : from->outlinks) {
+ BLI_assert(rel->from == from);
+ if (rel->to != to) {
+ continue;
+ }
+ if (description != NULL && !STREQ(rel->name, description)) {
+ continue;
+ }
+ return rel;
+ }
+ return NULL;
}
/* ************************ */
/* Relationships Management */
Relation::Relation(Node *from, Node *to, const char *description)
- : from(from),
- to(to),
- name(description),
- flag(0)
+ : from(from), to(to), name(description), flag(0)
{
- /* Hook it up to the nodes which use it.
- *
- * NOTE: We register relation in the nodes which this link connects to here
- * in constructor but we don't unregister it in the destructor.
- *
- * Reasoning:
- *
- * - Destructor is currently used on global graph destruction, so there's no
- * real need in avoiding dangling pointers, all the memory is to be freed
- * anyway.
- *
- * - Unregistering relation is not a cheap operation, so better to have it
- * as an explicit call if we need this. */
- from->outlinks.push_back(this);
- to->inlinks.push_back(this);
+ /* Hook it up to the nodes which use it.
+ *
+ * NOTE: We register relation in the nodes which this link connects to here
+ * in constructor but we don't unregister it in the destructor.
+ *
+ * Reasoning:
+ *
+ * - Destructor is currently used on global graph destruction, so there's no
+ * real need in avoiding dangling pointers, all the memory is to be freed
+ * anyway.
+ *
+ * - Unregistering relation is not a cheap operation, so better to have it
+ * as an explicit call if we need this. */
+ from->outlinks.push_back(this);
+ to->inlinks.push_back(this);
}
Relation::~Relation()
{
- /* Sanity check. */
- BLI_assert(from != NULL && to != NULL);
+ /* Sanity check. */
+ BLI_assert(from != NULL && to != NULL);
}
void Relation::unlink()
{
- /* Sanity check. */
- BLI_assert(from != NULL && to != NULL);
- remove_from_vector(&from->outlinks, this);
- remove_from_vector(&to->inlinks, this);
+ /* Sanity check. */
+ BLI_assert(from != NULL && to != NULL);
+ remove_from_vector(&from->outlinks, this);
+ remove_from_vector(&to->inlinks, this);
}
/* Low level tagging -------------------------------------- */
@@ -266,50 +255,50 @@ void Relation::unlink()
/* Tag a specific node as needing updates. */
void Depsgraph::add_entry_tag(OperationNode *node)
{
- /* Sanity check. */
- if (node == NULL) {
- return;
- }
- /* Add to graph-level set of directly modified nodes to start searching
- * from.
- * NOTE: this is necessary since we have several thousand nodes to play
- * with. */
- BLI_gset_insert(entry_tags, node);
+ /* Sanity check. */
+ if (node == NULL) {
+ return;
+ }
+ /* Add to graph-level set of directly modified nodes to start searching
+ * from.
+ * NOTE: this is necessary since we have several thousand nodes to play
+ * with. */
+ BLI_gset_insert(entry_tags, node);
}
void Depsgraph::clear_all_nodes()
{
- clear_id_nodes();
- if (time_source != NULL) {
- OBJECT_GUARDED_DELETE(time_source, TimeSourceNode);
- time_source = NULL;
- }
+ clear_id_nodes();
+ if (time_source != NULL) {
+ OBJECT_GUARDED_DELETE(time_source, TimeSourceNode);
+ time_source = NULL;
+ }
}
ID *Depsgraph::get_cow_id(const ID *id_orig) const
{
- IDNode *id_node = find_id_node(id_orig);
- if (id_node == NULL) {
- /* This function is used from places where we expect ID to be either
- * already a copy-on-write version or have a corresponding copy-on-write
- * version.
- *
- * We try to enforce that in debug builds, for for release we play a bit
- * safer game here. */
- if ((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
- /* TODO(sergey): This is nice sanity check to have, but it fails
- * in following situations:
- *
- * - Material has link to texture, which is not needed by new
- * shading system and hence can be ignored at construction.
- * - Object or mesh has material at a slot which is not used (for
- * example, object has material slot by materials are set to
- * object data). */
- // BLI_assert(!"Request for non-existing copy-on-write ID");
- }
- return (ID *)id_orig;
- }
- return id_node->id_cow;
+ IDNode *id_node = find_id_node(id_orig);
+ if (id_node == NULL) {
+ /* This function is used from places where we expect ID to be either
+ * already a copy-on-write version or have a corresponding copy-on-write
+ * version.
+ *
+ * We try to enforce that in debug builds, for for release we play a bit
+ * safer game here. */
+ if ((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
+ /* TODO(sergey): This is nice sanity check to have, but it fails
+ * in following situations:
+ *
+ * - Material has link to texture, which is not needed by new
+ * shading system and hence can be ignored at construction.
+ * - Object or mesh has material at a slot which is not used (for
+ * example, object has material slot by materials are set to
+ * object data). */
+ // BLI_assert(!"Request for non-existing copy-on-write ID");
+ }
+ return (ID *)id_orig;
+ }
+ return id_node->id_cow;
}
} // namespace DEG
@@ -318,48 +307,42 @@ ID *Depsgraph::get_cow_id(const ID *id_orig) const
/* Public Graph API */
/* Initialize a new Depsgraph */
-Depsgraph *DEG_graph_new(Scene *scene,
- ViewLayer *view_layer,
- eEvaluationMode mode)
+Depsgraph *DEG_graph_new(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
{
- DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph,
- scene,
- view_layer,
- mode);
- return reinterpret_cast<Depsgraph *>(deg_depsgraph);
+ DEG::Depsgraph *deg_depsgraph = OBJECT_GUARDED_NEW(DEG::Depsgraph, scene, view_layer, mode);
+ return reinterpret_cast<Depsgraph *>(deg_depsgraph);
}
/* Free graph's contents and graph itself */
void DEG_graph_free(Depsgraph *graph)
{
- using DEG::Depsgraph;
- DEG::Depsgraph *deg_depsgraph = reinterpret_cast<DEG::Depsgraph *>(graph);
- OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph);
+ using DEG::Depsgraph;
+ DEG::Depsgraph *deg_depsgraph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph);
}
bool DEG_is_active(const struct Depsgraph *depsgraph)
{
- if (depsgraph == NULL) {
- /* Happens for such cases as work object in what_does_obaction(),
- * and sine render pipeline parts. Shouldn't really be accepting
- * NULL depsgraph, but is quite hard to get proper one in those
- * cases. */
- return false;
- }
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
- return deg_graph->is_active;
+ if (depsgraph == NULL) {
+ /* Happens for such cases as work object in what_does_obaction(),
+ * and sine render pipeline parts. Shouldn't really be accepting
+ * NULL depsgraph, but is quite hard to get proper one in those
+ * cases. */
+ return false;
+ }
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
+ return deg_graph->is_active;
}
void DEG_make_active(struct Depsgraph *depsgraph)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- deg_graph->is_active = true;
- /* TODO(sergey): Copy data from evaluated state to original. */
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ deg_graph->is_active = true;
+ /* TODO(sergey): Copy data from evaluated state to original. */
}
void DEG_make_inactive(struct Depsgraph *depsgraph)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- deg_graph->is_active = false;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ deg_graph->is_active = false;
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index de01969e963..2dcbb6b5574 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -35,7 +35,7 @@
#include "BKE_main.h" /* for MAX_LIBARRAY */
-#include "BLI_threads.h" /* for SpinLock */
+#include "BLI_threads.h" /* for SpinLock */
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_physics.h"
@@ -63,34 +63,34 @@ struct TimeSourceNode;
/* Settings/Tags on Relationship.
* NOTE: Is a bitmask, allowing accumulation. */
enum RelationFlag {
- /* "cyclic" link - when detecting cycles, this relationship was the one
- * which triggers a cyclic relationship to exist in the graph. */
- RELATION_FLAG_CYCLIC = (1 << 0),
- /* Update flush will not go through this relation. */
- RELATION_FLAG_NO_FLUSH = (1 << 1),
- /* Only flush along the relation is update comes from a node which was
- * affected by user input. */
- RELATION_FLAG_FLUSH_USER_EDIT_ONLY = (1 << 2),
- /* The relation can not be killed by the cyclic dependencies solver. */
- RELATION_FLAG_GODMODE = (1 << 4),
- /* Relation will check existance before being added. */
- RELATION_CHECK_BEFORE_ADD = (1 << 5),
+ /* "cyclic" link - when detecting cycles, this relationship was the one
+ * which triggers a cyclic relationship to exist in the graph. */
+ RELATION_FLAG_CYCLIC = (1 << 0),
+ /* Update flush will not go through this relation. */
+ RELATION_FLAG_NO_FLUSH = (1 << 1),
+ /* Only flush along the relation is update comes from a node which was
+ * affected by user input. */
+ RELATION_FLAG_FLUSH_USER_EDIT_ONLY = (1 << 2),
+ /* The relation can not be killed by the cyclic dependencies solver. */
+ RELATION_FLAG_GODMODE = (1 << 4),
+ /* Relation will check existance before being added. */
+ RELATION_CHECK_BEFORE_ADD = (1 << 5),
};
/* B depends on A (A -> B) */
struct Relation {
- Relation(Node *from, Node *to, const char *description);
- ~Relation();
+ Relation(Node *from, Node *to, const char *description);
+ ~Relation();
- void unlink();
+ void unlink();
- /* the nodes in the relationship (since this is shared between the nodes) */
- Node *from; /* A */
- Node *to; /* B */
+ /* the nodes in the relationship (since this is shared between the nodes) */
+ Node *from; /* A */
+ Node *to; /* B */
- /* relationship attributes */
- const char *name; /* label for debugging */
- int flag; /* Bitmask of RelationFlag) */
+ /* relationship attributes */
+ const char *name; /* label for debugging */
+ int flag; /* Bitmask of RelationFlag) */
};
/* ********* */
@@ -98,112 +98,105 @@ struct Relation {
/* Dependency Graph object */
struct Depsgraph {
- // TODO(sergey): Go away from C++ container and use some native BLI.
- typedef vector<OperationNode *> OperationNodes;
- typedef vector<IDNode *> IDDepsNodes;
+ // TODO(sergey): Go away from C++ container and use some native BLI.
+ typedef vector<OperationNode *> OperationNodes;
+ typedef vector<IDNode *> IDDepsNodes;
- Depsgraph(Scene *scene,
- ViewLayer *view_layer,
- eEvaluationMode mode);
- ~Depsgraph();
+ Depsgraph(Scene *scene, ViewLayer *view_layer, eEvaluationMode mode);
+ ~Depsgraph();
- TimeSourceNode *add_time_source();
- TimeSourceNode *find_time_source() const;
+ TimeSourceNode *add_time_source();
+ TimeSourceNode *find_time_source() const;
- IDNode *find_id_node(const ID *id) const;
- IDNode *add_id_node(ID *id, ID *id_cow_hint = NULL);
- void clear_id_nodes();
- void clear_id_nodes_conditional(const std::function <bool (ID_Type id_type)>& filter);
+ IDNode *find_id_node(const ID *id) const;
+ IDNode *add_id_node(ID *id, ID *id_cow_hint = NULL);
+ void clear_id_nodes();
+ void clear_id_nodes_conditional(const std::function<bool(ID_Type id_type)> &filter);
- /* Add new relationship between two nodes. */
- Relation *add_new_relation(Node *from,
- Node *to,
- const char *description,
- int flags = 0);
+ /* Add new relationship between two nodes. */
+ Relation *add_new_relation(Node *from, Node *to, const char *description, int flags = 0);
- /* Check whether two nodes are connected by relation with given
- * description. Description might be NULL to check ANY relation between
- * given nodes. */
- Relation *check_nodes_connected(const Node *from,
- const Node *to,
- const char *description);
+ /* Check whether two nodes are connected by relation with given
+ * description. Description might be NULL to check ANY relation between
+ * given nodes. */
+ Relation *check_nodes_connected(const Node *from, const Node *to, const char *description);
- /* Tag a specific node as needing updates. */
- void add_entry_tag(OperationNode *node);
+ /* Tag a specific node as needing updates. */
+ void add_entry_tag(OperationNode *node);
- /* Clear storage used by all nodes. */
- void clear_all_nodes();
+ /* Clear storage used by all nodes. */
+ void clear_all_nodes();
- /* Copy-on-Write Functionality ........ */
+ /* Copy-on-Write Functionality ........ */
- /* For given original ID get ID which is created by CoW system. */
- ID *get_cow_id(const ID *id_orig) const;
+ /* For given original ID get ID which is created by CoW system. */
+ ID *get_cow_id(const ID *id_orig) const;
- /* Core Graph Functionality ........... */
+ /* Core Graph Functionality ........... */
- /* <ID : IDNode> mapping from ID blocks to nodes representing these
- * blocks, used for quick lookups. */
- GHash *id_hash;
+ /* <ID : IDNode> mapping from ID blocks to nodes representing these
+ * blocks, used for quick lookups. */
+ GHash *id_hash;
- /* Ordered list of ID nodes, order matches ID allocation order.
- * Used for faster iteration, especially for areas which are critical to
- * keep exact order of iteration. */
- IDDepsNodes id_nodes;
+ /* Ordered list of ID nodes, order matches ID allocation order.
+ * Used for faster iteration, especially for areas which are critical to
+ * keep exact order of iteration. */
+ IDDepsNodes id_nodes;
- /* Top-level time source node. */
- TimeSourceNode *time_source;
+ /* Top-level time source node. */
+ TimeSourceNode *time_source;
- /* Indicates whether relations needs to be updated. */
- bool need_update;
+ /* Indicates whether relations needs to be updated. */
+ bool need_update;
- /* Indicates which ID types were updated. */
- char id_type_updated[MAX_LIBARRAY];
+ /* Indicates which ID types were updated. */
+ char id_type_updated[MAX_LIBARRAY];
- /* Quick-Access Temp Data ............. */
+ /* Quick-Access Temp Data ............. */
- /* Nodes which have been tagged as "directly modified". */
- GSet *entry_tags;
+ /* Nodes which have been tagged as "directly modified". */
+ GSet *entry_tags;
- /* Convenience Data ................... */
+ /* Convenience Data ................... */
- /* XXX: should be collected after building (if actually needed?) */
- /* All operation nodes, sorted in order of single-thread traversal order. */
- OperationNodes operations;
+ /* XXX: should be collected after building (if actually needed?) */
+ /* All operation nodes, sorted in order of single-thread traversal order. */
+ OperationNodes operations;
- /* Spin lock for threading-critical operations.
- * Mainly used by graph evaluation. */
- SpinLock lock;
+ /* Spin lock for threading-critical operations.
+ * Mainly used by graph evaluation. */
+ SpinLock lock;
- /* Scene, layer, mode this dependency graph is built for. */
- Scene *scene;
- ViewLayer *view_layer;
- eEvaluationMode mode;
+ /* Scene, layer, mode this dependency graph is built for. */
+ Scene *scene;
+ ViewLayer *view_layer;
+ eEvaluationMode mode;
- /* Time at which dependency graph is being or was last evaluated. */
- float ctime;
+ /* Time at which dependency graph is being or was last evaluated. */
+ float ctime;
- /* Evaluated version of datablocks we access a lot.
- * Stored here to save us form doing hash lookup. */
- Scene *scene_cow;
+ /* Evaluated version of datablocks we access a lot.
+ * Stored here to save us form doing hash lookup. */
+ Scene *scene_cow;
- /* Active dependency graph is a dependency graph which is used by the
- * currently active window. When dependency graph is active, it is allowed
- * for evaluation functions to write animation f-curve result, drivers
- * result and other selective things (object matrix?) to original object.
- *
- * This way we simplify operators, which don't need to worry about where
- * to read stuff from. */
- bool is_active;
+ /* Active dependency graph is a dependency graph which is used by the
+ * currently active window. When dependency graph is active, it is allowed
+ * for evaluation functions to write animation f-curve result, drivers
+ * result and other selective things (object matrix?) to original object.
+ *
+ * This way we simplify operators, which don't need to worry about where
+ * to read stuff from. */
+ bool is_active;
- /* NOTE: Corresponds to G_DEBUG_DEPSGRAPH_* flags. */
- int debug_flags;
- string debug_name;
+ /* NOTE: Corresponds to G_DEBUG_DEPSGRAPH_* flags. */
+ int debug_flags;
+ string debug_name;
- bool debug_is_evaluating;
+ bool debug_is_evaluating;
- /* Cached list of colliders/effectors for collections and the scene
- * created along with relations, for fast lookup during evaluation. */
- GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
+ /* Cached list of colliders/effectors for collections and the scene
+ * created along with relations, for fast lookup during evaluation. */
+ GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM];
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 3cec2b45ea4..e4c84264960 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -63,37 +63,47 @@ extern "C" {
/* ****************** */
/* External Build API */
-static DEG::NodeType deg_build_scene_component_type(
- eDepsSceneComponentType component)
+static DEG::NodeType deg_build_scene_component_type(eDepsSceneComponentType component)
{
- switch (component) {
- case DEG_SCENE_COMP_PARAMETERS: return DEG::NodeType::PARAMETERS;
- case DEG_SCENE_COMP_ANIMATION: return DEG::NodeType::ANIMATION;
- case DEG_SCENE_COMP_SEQUENCER: return DEG::NodeType::SEQUENCER;
- }
- return DEG::NodeType::UNDEFINED;
+ switch (component) {
+ case DEG_SCENE_COMP_PARAMETERS:
+ return DEG::NodeType::PARAMETERS;
+ case DEG_SCENE_COMP_ANIMATION:
+ return DEG::NodeType::ANIMATION;
+ case DEG_SCENE_COMP_SEQUENCER:
+ return DEG::NodeType::SEQUENCER;
+ }
+ return DEG::NodeType::UNDEFINED;
}
-static DEG::NodeType deg_build_object_component_type(
- eDepsObjectComponentType component)
+static DEG::NodeType deg_build_object_component_type(eDepsObjectComponentType component)
{
- switch (component) {
- case DEG_OB_COMP_PARAMETERS: return DEG::NodeType::PARAMETERS;
- case DEG_OB_COMP_PROXY: return DEG::NodeType::PROXY;
- case DEG_OB_COMP_ANIMATION: return DEG::NodeType::ANIMATION;
- case DEG_OB_COMP_TRANSFORM: return DEG::NodeType::TRANSFORM;
- case DEG_OB_COMP_GEOMETRY: return DEG::NodeType::GEOMETRY;
- case DEG_OB_COMP_EVAL_POSE: return DEG::NodeType::EVAL_POSE;
- case DEG_OB_COMP_BONE: return DEG::NodeType::BONE;
- case DEG_OB_COMP_SHADING: return DEG::NodeType::SHADING;
- case DEG_OB_COMP_CACHE: return DEG::NodeType::CACHE;
- }
- return DEG::NodeType::UNDEFINED;
+ switch (component) {
+ case DEG_OB_COMP_PARAMETERS:
+ return DEG::NodeType::PARAMETERS;
+ case DEG_OB_COMP_PROXY:
+ return DEG::NodeType::PROXY;
+ case DEG_OB_COMP_ANIMATION:
+ return DEG::NodeType::ANIMATION;
+ case DEG_OB_COMP_TRANSFORM:
+ return DEG::NodeType::TRANSFORM;
+ case DEG_OB_COMP_GEOMETRY:
+ return DEG::NodeType::GEOMETRY;
+ case DEG_OB_COMP_EVAL_POSE:
+ return DEG::NodeType::EVAL_POSE;
+ case DEG_OB_COMP_BONE:
+ return DEG::NodeType::BONE;
+ case DEG_OB_COMP_SHADING:
+ return DEG::NodeType::SHADING;
+ case DEG_OB_COMP_CACHE:
+ return DEG::NodeType::CACHE;
+ }
+ return DEG::NodeType::UNDEFINED;
}
static DEG::DepsNodeHandle *get_node_handle(DepsNodeHandle *node_handle)
{
- return reinterpret_cast<DEG::DepsNodeHandle *>(node_handle);
+ return reinterpret_cast<DEG::DepsNodeHandle *>(node_handle);
}
void DEG_add_scene_relation(DepsNodeHandle *node_handle,
@@ -101,12 +111,10 @@ void DEG_add_scene_relation(DepsNodeHandle *node_handle,
eDepsSceneComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_scene_component_type(component);
- DEG::ComponentKey comp_key(&scene->id, type);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_node_handle_relation(comp_key,
- deg_node_handle,
- description);
+ DEG::NodeType type = deg_build_scene_component_type(component);
+ DEG::ComponentKey comp_key(&scene->id, type);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_object_relation(DepsNodeHandle *node_handle,
@@ -114,12 +122,10 @@ void DEG_add_object_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&object->id, type);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_node_handle_relation(comp_key,
- deg_node_handle,
- description);
+ DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&object->id, type);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
@@ -127,12 +133,10 @@ void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&cache_file->id, type);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_node_handle_relation(comp_key,
- deg_node_handle,
- description);
+ DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&cache_file->id, type);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_bone_relation(DepsNodeHandle *node_handle,
@@ -141,12 +145,10 @@ void DEG_add_bone_relation(DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&object->id, type, bone_name);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_node_handle_relation(comp_key,
- deg_node_handle,
- description);
+ DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&object->id, type, bone_name);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
@@ -154,82 +156,66 @@ void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
eDepsObjectComponentType component,
const char *description)
{
- DEG::NodeType type = deg_build_object_component_type(component);
- DEG::ComponentKey comp_key(&object->id, type);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
- /* Add relation from source to the node handle. */
- relation_builder->add_node_handle_relation(
- comp_key, deg_node_handle, description);
- /* Node deduct point cache component and connect source to it. */
- ID *id = DEG_get_id_from_handle(node_handle);
- DEG::ComponentKey point_cache_key(id, DEG::NodeType::POINT_CACHE);
- DEG::Relation *rel = relation_builder->add_relation(
- comp_key, point_cache_key, "Point Cache");
- if (rel != NULL) {
- rel->flag |= DEG::RELATION_FLAG_FLUSH_USER_EDIT_ONLY;
- }
- else {
- fprintf(stderr,
- "Error in point cache relation from %s to ^%s.\n",
- object->id.name,
- id->name);
- }
+ DEG::NodeType type = deg_build_object_component_type(component);
+ DEG::ComponentKey comp_key(&object->id, type);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
+ /* Add relation from source to the node handle. */
+ relation_builder->add_node_handle_relation(comp_key, deg_node_handle, description);
+ /* Node deduct point cache component and connect source to it. */
+ ID *id = DEG_get_id_from_handle(node_handle);
+ DEG::ComponentKey point_cache_key(id, DEG::NodeType::POINT_CACHE);
+ DEG::Relation *rel = relation_builder->add_relation(comp_key, point_cache_key, "Point Cache");
+ if (rel != NULL) {
+ rel->flag |= DEG::RELATION_FLAG_FLUSH_USER_EDIT_ONLY;
+ }
+ else {
+ fprintf(stderr, "Error in point cache relation from %s to ^%s.\n", object->id.name, id->name);
+ }
}
void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle,
struct ID *id,
const char *description)
{
- DEG::OperationKey operation_key(
- id,
- DEG::NodeType::GENERIC_DATABLOCK,
- DEG::OperationCode::GENERIC_DATABLOCK_UPDATE);
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_node_handle_relation(operation_key,
- deg_node_handle,
- description);
+ DEG::OperationKey operation_key(
+ id, DEG::NodeType::GENERIC_DATABLOCK, DEG::OperationCode::GENERIC_DATABLOCK_UPDATE);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description);
}
-void DEG_add_modifier_to_transform_relation(
- struct DepsNodeHandle *node_handle,
- const char *description)
+void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle,
+ const char *description)
{
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_modifier_to_transform_relation(
- deg_node_handle,
- description);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_modifier_to_transform_relation(deg_node_handle, description);
}
-void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle,
- ID *id,
- uint32_t flag)
+void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle, ID *id, uint32_t flag)
{
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_special_eval_flag(id, flag);
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_special_eval_flag(id, flag);
}
void DEG_add_customdata_mask(struct DepsNodeHandle *node_handle,
struct Object *object,
const CustomData_MeshMasks *masks)
{
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- deg_node_handle->builder->add_customdata_mask(
- object,
- DEG::DEGCustomDataMeshMasks(masks));
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ deg_node_handle->builder->add_customdata_mask(object, DEG::DEGCustomDataMeshMasks(masks));
}
struct ID *DEG_get_id_from_handle(struct DepsNodeHandle *node_handle)
{
- DEG::DepsNodeHandle *deg_handle = get_node_handle(node_handle);
- return deg_handle->node->owner->owner->id_orig;
+ DEG::DepsNodeHandle *deg_handle = get_node_handle(node_handle);
+ return deg_handle->node->owner->owner->id_orig;
}
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
{
- DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
- DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
- return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
+ DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
+ DEG::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
+ return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
}
/* ******************** */
@@ -239,106 +225,97 @@ struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
* graph container.
*/
void DEG_graph_build_from_view_layer(Depsgraph *graph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
{
- double start_time = 0.0;
- if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
- start_time = PIL_check_seconds_timer();
- }
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- /* Perform sanity checks. */
- BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1);
- BLI_assert(deg_graph->scene == scene);
- BLI_assert(deg_graph->view_layer == view_layer);
- /* Generate all the nodes in the graph first */
- DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
- node_builder.begin_build();
- node_builder.build_view_layer(scene,
- view_layer,
- DEG::DEG_ID_LINKED_DIRECTLY);
- node_builder.end_build();
- /* Hook up relationships between operations - to determine evaluation
- * order. */
- DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph);
- relation_builder.begin_build();
- relation_builder.build_view_layer(scene, view_layer);
- relation_builder.build_copy_on_write_relations();
- /* Detect and solve cycles. */
- DEG::deg_graph_detect_cycles(deg_graph);
- /* Simplify the graph by removing redundant relations (to optimize
- * traversal later). */
- /* TODO: it would be useful to have an option to disable this in cases where
- * it is causing trouble. */
- if (G.debug_value == 799) {
- DEG::deg_graph_transitive_reduction(deg_graph);
- }
- /* Store pointers to commonly used valuated datablocks. */
- deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
- /* Flush visibility layer and re-schedule nodes for update. */
- DEG::deg_graph_build_finalize(bmain, deg_graph);
- DEG_graph_on_visible_update(bmain, graph);
+ double start_time = 0.0;
+ if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+ start_time = PIL_check_seconds_timer();
+ }
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ /* Perform sanity checks. */
+ BLI_assert(BLI_findindex(&scene->view_layers, view_layer) != -1);
+ BLI_assert(deg_graph->scene == scene);
+ BLI_assert(deg_graph->view_layer == view_layer);
+ /* Generate all the nodes in the graph first */
+ DEG::DepsgraphNodeBuilder node_builder(bmain, deg_graph);
+ node_builder.begin_build();
+ node_builder.build_view_layer(scene, view_layer, DEG::DEG_ID_LINKED_DIRECTLY);
+ node_builder.end_build();
+ /* Hook up relationships between operations - to determine evaluation
+ * order. */
+ DEG::DepsgraphRelationBuilder relation_builder(bmain, deg_graph);
+ relation_builder.begin_build();
+ relation_builder.build_view_layer(scene, view_layer);
+ relation_builder.build_copy_on_write_relations();
+ /* Detect and solve cycles. */
+ DEG::deg_graph_detect_cycles(deg_graph);
+ /* Simplify the graph by removing redundant relations (to optimize
+ * traversal later). */
+ /* TODO: it would be useful to have an option to disable this in cases where
+ * it is causing trouble. */
+ if (G.debug_value == 799) {
+ DEG::deg_graph_transitive_reduction(deg_graph);
+ }
+ /* Store pointers to commonly used valuated datablocks. */
+ deg_graph->scene_cow = (Scene *)deg_graph->get_cow_id(&deg_graph->scene->id);
+ /* Flush visibility layer and re-schedule nodes for update. */
+ DEG::deg_graph_build_finalize(bmain, deg_graph);
+ DEG_graph_on_visible_update(bmain, graph);
#if 0
- if (!DEG_debug_consistency_check(deg_graph)) {
- printf("Consistency validation failed, ABORTING!\n");
- abort();
- }
+ if (!DEG_debug_consistency_check(deg_graph)) {
+ printf("Consistency validation failed, ABORTING!\n");
+ abort();
+ }
#endif
- /* Relations are up to date. */
- deg_graph->need_update = false;
- /* Finish statistics. */
- if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
- printf("Depsgraph built in %f seconds.\n",
- PIL_check_seconds_timer() - start_time);
- }
+ /* Relations are up to date. */
+ deg_graph->need_update = false;
+ /* Finish statistics. */
+ if (G.debug & (G_DEBUG_DEPSGRAPH_BUILD | G_DEBUG_DEPSGRAPH_TIME)) {
+ printf("Depsgraph built in %f seconds.\n", PIL_check_seconds_timer() - start_time);
+ }
}
/* Tag graph relations for update. */
void DEG_graph_tag_relations_update(Depsgraph *graph)
{
- DEG_DEBUG_PRINTF(graph, TAG, "%s: Tagging relations for update.\n", __func__);
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- deg_graph->need_update = true;
- /* NOTE: When relations are updated, it's quite possible that
- * we've got new bases in the scene. This means, we need to
- * re-create flat array of bases in view layer.
- *
- * TODO(sergey): Try to make it so we don't flush updates
- * to the whole depsgraph. */
- DEG::IDNode *id_node = deg_graph->find_id_node(&deg_graph->scene->id);
- if (id_node != NULL) {
- id_node->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_RELATIONS);
- }
+ DEG_DEBUG_PRINTF(graph, TAG, "%s: Tagging relations for update.\n", __func__);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->need_update = true;
+ /* NOTE: When relations are updated, it's quite possible that
+ * we've got new bases in the scene. This means, we need to
+ * re-create flat array of bases in view layer.
+ *
+ * TODO(sergey): Try to make it so we don't flush updates
+ * to the whole depsgraph. */
+ DEG::IDNode *id_node = deg_graph->find_id_node(&deg_graph->scene->id);
+ if (id_node != NULL) {
+ id_node->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_RELATIONS);
+ }
}
/* Create or update relations in the specified graph. */
-void DEG_graph_relations_update(Depsgraph *graph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+void DEG_graph_relations_update(Depsgraph *graph, Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)graph;
- if (!deg_graph->need_update) {
- /* Graph is up to date, nothing to do. */
- return;
- }
- DEG_graph_build_from_view_layer(graph, bmain, scene, view_layer);
+ DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)graph;
+ if (!deg_graph->need_update) {
+ /* Graph is up to date, nothing to do. */
+ return;
+ }
+ DEG_graph_build_from_view_layer(graph, bmain, scene, view_layer);
}
/* Tag all relations for update. */
void DEG_relations_tag_update(Main *bmain)
{
- DEG_GLOBAL_DEBUG_PRINTF(TAG, "%s: Tagging relations for update.\n", __func__);
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- Depsgraph *depsgraph =
- (Depsgraph *)BKE_scene_get_depsgraph(scene,
- view_layer,
- false);
- if (depsgraph != NULL) {
- DEG_graph_tag_relations_update(depsgraph);
- }
- }
- }
+ DEG_GLOBAL_DEBUG_PRINTF(TAG, "%s: Tagging relations for update.\n", __func__);
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph = (Depsgraph *)BKE_scene_get_depsgraph(scene, view_layer, false);
+ if (depsgraph != NULL) {
+ DEG_graph_tag_relations_update(depsgraph);
+ }
+ }
+ }
}
diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc
index 67450d1350f..e795bed144d 100644
--- a/source/blender/depsgraph/intern/depsgraph_debug.cc
+++ b/source/blender/depsgraph/intern/depsgraph_debug.cc
@@ -28,7 +28,7 @@
extern "C" {
#include "DNA_scene_types.h"
-} /* extern "C" */
+} /* extern "C" */
#include "DNA_object_types.h"
@@ -46,49 +46,44 @@ extern "C" {
void DEG_debug_flags_set(Depsgraph *depsgraph, int flags)
{
- DEG::Depsgraph *deg_graph =
- reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- deg_graph->debug_flags = flags;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ deg_graph->debug_flags = flags;
}
int DEG_debug_flags_get(const Depsgraph *depsgraph)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
- return deg_graph->debug_flags;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
+ return deg_graph->debug_flags;
}
void DEG_debug_name_set(struct Depsgraph *depsgraph, const char *name)
{
- DEG::Depsgraph *deg_graph =
- reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- deg_graph->debug_name = name;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ deg_graph->debug_name = name;
}
const char *DEG_debug_name_get(struct Depsgraph *depsgraph)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
- return deg_graph->debug_name.c_str();
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph);
+ return deg_graph->debug_name.c_str();
}
-bool DEG_debug_compare(const struct Depsgraph *graph1,
- const struct Depsgraph *graph2)
+bool DEG_debug_compare(const struct Depsgraph *graph1, const struct Depsgraph *graph2)
{
- BLI_assert(graph1 != NULL);
- BLI_assert(graph2 != NULL);
- const DEG::Depsgraph *deg_graph1 = reinterpret_cast<const DEG::Depsgraph *>(graph1);
- const DEG::Depsgraph *deg_graph2 = reinterpret_cast<const DEG::Depsgraph *>(graph2);
- if (deg_graph1->operations.size() != deg_graph2->operations.size()) {
- return false;
- }
- /* TODO(sergey): Currently we only do real stupid check,
- * which is fast but which isn't 100% reliable.
- *
- * Would be cool to make it more robust, but it's good enough
- * for now. Also, proper graph check is actually NP-complex
- * problem. */
- return true;
+ BLI_assert(graph1 != NULL);
+ BLI_assert(graph2 != NULL);
+ const DEG::Depsgraph *deg_graph1 = reinterpret_cast<const DEG::Depsgraph *>(graph1);
+ const DEG::Depsgraph *deg_graph2 = reinterpret_cast<const DEG::Depsgraph *>(graph2);
+ if (deg_graph1->operations.size() != deg_graph2->operations.size()) {
+ return false;
+ }
+ /* TODO(sergey): Currently we only do real stupid check,
+ * which is fast but which isn't 100% reliable.
+ *
+ * Would be cool to make it more robust, but it's good enough
+ * for now. Also, proper graph check is actually NP-complex
+ * problem. */
+ return true;
}
bool DEG_debug_graph_relations_validate(Depsgraph *graph,
@@ -96,105 +91,107 @@ bool DEG_debug_graph_relations_validate(Depsgraph *graph,
Scene *scene,
ViewLayer *view_layer)
{
- Depsgraph *temp_depsgraph = DEG_graph_new(scene, view_layer, DEG_get_mode(graph));
- bool valid = true;
- DEG_graph_build_from_view_layer(temp_depsgraph, bmain, scene, view_layer);
- if (!DEG_debug_compare(temp_depsgraph, graph)) {
- fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
- BLI_assert(!"This should not happen!");
- valid = false;
- }
- DEG_graph_free(temp_depsgraph);
- return valid;
+ Depsgraph *temp_depsgraph = DEG_graph_new(scene, view_layer, DEG_get_mode(graph));
+ bool valid = true;
+ DEG_graph_build_from_view_layer(temp_depsgraph, bmain, scene, view_layer);
+ if (!DEG_debug_compare(temp_depsgraph, graph)) {
+ fprintf(stderr, "ERROR! Depsgraph wasn't tagged for update when it should have!\n");
+ BLI_assert(!"This should not happen!");
+ valid = false;
+ }
+ DEG_graph_free(temp_depsgraph);
+ return valid;
}
bool DEG_debug_consistency_check(Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(graph);
- /* Validate links exists in both directions. */
- for (DEG::OperationNode *node : deg_graph->operations) {
- for (DEG::Relation *rel : node->outlinks) {
- int counter1 = 0;
- for (DEG::Relation *tmp_rel : node->outlinks) {
- if (tmp_rel == rel) {
- ++counter1;
- }
- }
- int counter2 = 0;
- for (DEG::Relation *tmp_rel : rel->to->inlinks) {
- if (tmp_rel == rel) {
- ++counter2;
- }
- }
- if (counter1 != counter2) {
- printf("Relation exists in outgoing direction but not in "
- "incoming (%d vs. %d).\n",
- counter1, counter2);
- return false;
- }
- }
- }
-
- for (DEG::OperationNode *node : deg_graph->operations) {
- for (DEG::Relation *rel : node->inlinks) {
- int counter1 = 0;
- for (DEG::Relation *tmp_rel : node->inlinks) {
- if (tmp_rel == rel) {
- ++counter1;
- }
- }
- int counter2 = 0;
- for (DEG::Relation *tmp_rel : rel->from->outlinks) {
- if (tmp_rel == rel) {
- ++counter2;
- }
- }
- if (counter1 != counter2) {
- printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n",
- counter1, counter2);
- }
- }
- }
-
- /* Validate node valency calculated in both directions. */
- for (DEG::OperationNode *node : deg_graph->operations) {
- node->num_links_pending = 0;
- node->custom_flags = 0;
- }
-
- for (DEG::OperationNode *node : deg_graph->operations) {
- if (node->custom_flags) {
- printf("Node %s is twice in the operations!\n",
- node->identifier().c_str());
- return false;
- }
- for (DEG::Relation *rel : node->outlinks) {
- if (rel->to->type == DEG::NodeType::OPERATION) {
- DEG::OperationNode *to = (DEG::OperationNode *)rel->to;
- BLI_assert(to->num_links_pending < to->inlinks.size());
- ++to->num_links_pending;
- }
- }
- node->custom_flags = 1;
- }
-
- for (DEG::OperationNode *node : deg_graph->operations) {
- int num_links_pending = 0;
- for (DEG::Relation *rel : node->inlinks) {
- if (rel->from->type == DEG::NodeType::OPERATION) {
- ++num_links_pending;
- }
- }
- if (node->num_links_pending != num_links_pending) {
- printf("Valency mismatch: %s, %u != %d\n",
- node->identifier().c_str(),
- node->num_links_pending, num_links_pending);
- printf("Number of inlinks: %d\n", (int)node->inlinks.size());
- return false;
- }
- }
- return true;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ /* Validate links exists in both directions. */
+ for (DEG::OperationNode *node : deg_graph->operations) {
+ for (DEG::Relation *rel : node->outlinks) {
+ int counter1 = 0;
+ for (DEG::Relation *tmp_rel : node->outlinks) {
+ if (tmp_rel == rel) {
+ ++counter1;
+ }
+ }
+ int counter2 = 0;
+ for (DEG::Relation *tmp_rel : rel->to->inlinks) {
+ if (tmp_rel == rel) {
+ ++counter2;
+ }
+ }
+ if (counter1 != counter2) {
+ printf(
+ "Relation exists in outgoing direction but not in "
+ "incoming (%d vs. %d).\n",
+ counter1,
+ counter2);
+ return false;
+ }
+ }
+ }
+
+ for (DEG::OperationNode *node : deg_graph->operations) {
+ for (DEG::Relation *rel : node->inlinks) {
+ int counter1 = 0;
+ for (DEG::Relation *tmp_rel : node->inlinks) {
+ if (tmp_rel == rel) {
+ ++counter1;
+ }
+ }
+ int counter2 = 0;
+ for (DEG::Relation *tmp_rel : rel->from->outlinks) {
+ if (tmp_rel == rel) {
+ ++counter2;
+ }
+ }
+ if (counter1 != counter2) {
+ printf("Relation exists in incoming direction but not in outcoming (%d vs. %d).\n",
+ counter1,
+ counter2);
+ }
+ }
+ }
+
+ /* Validate node valency calculated in both directions. */
+ for (DEG::OperationNode *node : deg_graph->operations) {
+ node->num_links_pending = 0;
+ node->custom_flags = 0;
+ }
+
+ for (DEG::OperationNode *node : deg_graph->operations) {
+ if (node->custom_flags) {
+ printf("Node %s is twice in the operations!\n", node->identifier().c_str());
+ return false;
+ }
+ for (DEG::Relation *rel : node->outlinks) {
+ if (rel->to->type == DEG::NodeType::OPERATION) {
+ DEG::OperationNode *to = (DEG::OperationNode *)rel->to;
+ BLI_assert(to->num_links_pending < to->inlinks.size());
+ ++to->num_links_pending;
+ }
+ }
+ node->custom_flags = 1;
+ }
+
+ for (DEG::OperationNode *node : deg_graph->operations) {
+ int num_links_pending = 0;
+ for (DEG::Relation *rel : node->inlinks) {
+ if (rel->from->type == DEG::NodeType::OPERATION) {
+ ++num_links_pending;
+ }
+ }
+ if (node->num_links_pending != num_links_pending) {
+ printf("Valency mismatch: %s, %u != %d\n",
+ node->identifier().c_str(),
+ node->num_links_pending,
+ num_links_pending);
+ printf("Number of inlinks: %d\n", (int)node->inlinks.size());
+ return false;
+ }
+ }
+ return true;
}
/* ------------------------------------------------ */
@@ -205,65 +202,66 @@ bool DEG_debug_consistency_check(Depsgraph *graph)
* \param[out] r_operations The number of operation nodes in the graph
* \param[out] r_relations The number of relations between (executable) nodes in the graph
*/
-void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer,
- size_t *r_operations, size_t *r_relations)
+void DEG_stats_simple(const Depsgraph *graph,
+ size_t *r_outer,
+ size_t *r_operations,
+ size_t *r_relations)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
-
- /* number of operations */
- if (r_operations) {
- /* All operations should be in this list, allowing us to count the total
- * number of nodes. */
- *r_operations = deg_graph->operations.size();
- }
-
- /* Count number of outer nodes and/or relations between these. */
- if (r_outer || r_relations) {
- size_t tot_outer = 0;
- size_t tot_rels = 0;
-
- for (DEG::IDNode *id_node : deg_graph->id_nodes) {
- tot_outer++;
- GHASH_FOREACH_BEGIN(DEG::ComponentNode *, comp_node, id_node->components)
- {
- tot_outer++;
- for (DEG::OperationNode *op_node : comp_node->operations) {
- tot_rels += op_node->inlinks.size();
- }
- }
- GHASH_FOREACH_END();
- }
-
- DEG::TimeSourceNode *time_source = deg_graph->find_time_source();
- if (time_source != NULL) {
- tot_rels += time_source->inlinks.size();
- }
-
- if (r_relations) *r_relations = tot_rels;
- if (r_outer) *r_outer = tot_outer;
- }
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+
+ /* number of operations */
+ if (r_operations) {
+ /* All operations should be in this list, allowing us to count the total
+ * number of nodes. */
+ *r_operations = deg_graph->operations.size();
+ }
+
+ /* Count number of outer nodes and/or relations between these. */
+ if (r_outer || r_relations) {
+ size_t tot_outer = 0;
+ size_t tot_rels = 0;
+
+ for (DEG::IDNode *id_node : deg_graph->id_nodes) {
+ tot_outer++;
+ GHASH_FOREACH_BEGIN (DEG::ComponentNode *, comp_node, id_node->components) {
+ tot_outer++;
+ for (DEG::OperationNode *op_node : comp_node->operations) {
+ tot_rels += op_node->inlinks.size();
+ }
+ }
+ GHASH_FOREACH_END();
+ }
+
+ DEG::TimeSourceNode *time_source = deg_graph->find_time_source();
+ if (time_source != NULL) {
+ tot_rels += time_source->inlinks.size();
+ }
+
+ if (r_relations)
+ *r_relations = tot_rels;
+ if (r_outer)
+ *r_outer = tot_outer;
+ }
}
bool DEG_debug_is_evaluating(struct Depsgraph *depsgraph)
{
- DEG::Depsgraph *deg_graph =
- reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- return deg_graph->debug_is_evaluating;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ return deg_graph->debug_is_evaluating;
}
static DEG::string depsgraph_name_for_logging(struct Depsgraph *depsgraph)
{
- const char *name = DEG_debug_name_get(depsgraph);
- if (name[0] == '\0') {
- return "";
- }
- return "[" + DEG::string(name) + "]: ";
+ const char *name = DEG_debug_name_get(depsgraph);
+ if (name[0] == '\0') {
+ return "";
+ }
+ return "[" + DEG::string(name) + "]: ";
}
void DEG_debug_print_begin(struct Depsgraph *depsgraph)
{
- fprintf(stdout, "%s",
- depsgraph_name_for_logging(depsgraph).c_str());
+ fprintf(stdout, "%s", depsgraph_name_for_logging(depsgraph).c_str());
}
void DEG_debug_print_eval(struct Depsgraph *depsgraph,
@@ -271,18 +269,18 @@ void DEG_debug_print_eval(struct Depsgraph *depsgraph,
const char *object_name,
const void *object_address)
{
- if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
- return;
- }
- fprintf(stdout,
- "%s%s on %s %s(%p)%s\n",
- depsgraph_name_for_logging(depsgraph).c_str(),
- function_name,
- object_name,
- DEG::color_for_pointer(object_address).c_str(),
- object_address,
- DEG::color_end().c_str());
- fflush(stdout);
+ if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s%s on %s %s(%p)%s\n",
+ depsgraph_name_for_logging(depsgraph).c_str(),
+ function_name,
+ object_name,
+ DEG::color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::color_end().c_str());
+ fflush(stdout);
}
void DEG_debug_print_eval_subdata(struct Depsgraph *depsgraph,
@@ -293,23 +291,23 @@ void DEG_debug_print_eval_subdata(struct Depsgraph *depsgraph,
const char *subdata_name,
const void *subdata_address)
{
- if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
- return;
- }
- fprintf(stdout,
- "%s%s on %s %s(%p)%s %s %s %s(%p)%s\n",
- depsgraph_name_for_logging(depsgraph).c_str(),
- function_name,
- object_name,
- DEG::color_for_pointer(object_address).c_str(),
- object_address,
- DEG::color_end().c_str(),
- subdata_comment,
- subdata_name,
- DEG::color_for_pointer(subdata_address).c_str(),
- subdata_address,
- DEG::color_end().c_str());
- fflush(stdout);
+ if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s%s on %s %s(%p)%s %s %s %s(%p)%s\n",
+ depsgraph_name_for_logging(depsgraph).c_str(),
+ function_name,
+ object_name,
+ DEG::color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::color_end().c_str(),
+ subdata_comment,
+ subdata_name,
+ DEG::color_for_pointer(subdata_address).c_str(),
+ subdata_address,
+ DEG::color_end().c_str());
+ fflush(stdout);
}
void DEG_debug_print_eval_subdata_index(struct Depsgraph *depsgraph,
@@ -321,24 +319,24 @@ void DEG_debug_print_eval_subdata_index(struct Depsgraph *depsgraph,
const void *subdata_address,
const int subdata_index)
{
- if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
- return;
- }
- fprintf(stdout,
- "%s%s on %s %s(%p)%s %s %s[%d] %s(%p)%s\n",
- depsgraph_name_for_logging(depsgraph).c_str(),
- function_name,
- object_name,
- DEG::color_for_pointer(object_address).c_str(),
- object_address,
- DEG::color_end().c_str(),
- subdata_comment,
- subdata_name,
- subdata_index,
- DEG::color_for_pointer(subdata_address).c_str(),
- subdata_address,
- DEG::color_end().c_str());
- fflush(stdout);
+ if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s%s on %s %s(%p)%s %s %s[%d] %s(%p)%s\n",
+ depsgraph_name_for_logging(depsgraph).c_str(),
+ function_name,
+ object_name,
+ DEG::color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::color_end().c_str(),
+ subdata_comment,
+ subdata_name,
+ subdata_index,
+ DEG::color_for_pointer(subdata_address).c_str(),
+ subdata_address,
+ DEG::color_end().c_str());
+ fflush(stdout);
}
void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph,
@@ -349,23 +347,23 @@ void DEG_debug_print_eval_parent_typed(struct Depsgraph *depsgraph,
const char *parent_name,
const void *parent_address)
{
- if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
- return;
- }
- fprintf(stdout,
- "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n",
- depsgraph_name_for_logging(depsgraph).c_str(),
- function_name,
- object_name,
- DEG::color_for_pointer(object_address).c_str(),
- object_address,
- DEG::color_end().c_str(),
- parent_comment,
- parent_name,
- DEG::color_for_pointer(parent_address).c_str(),
- parent_address,
- DEG::color_end().c_str());
- fflush(stdout);
+ if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s%s on %s %s(%p) [%s] %s %s %s(%p)%s\n",
+ depsgraph_name_for_logging(depsgraph).c_str(),
+ function_name,
+ object_name,
+ DEG::color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::color_end().c_str(),
+ parent_comment,
+ parent_name,
+ DEG::color_for_pointer(parent_address).c_str(),
+ parent_address,
+ DEG::color_end().c_str());
+ fflush(stdout);
}
void DEG_debug_print_eval_time(struct Depsgraph *depsgraph,
@@ -374,17 +372,17 @@ void DEG_debug_print_eval_time(struct Depsgraph *depsgraph,
const void *object_address,
float time)
{
- if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
- return;
- }
- fprintf(stdout,
- "%s%s on %s %s(%p)%s at time %f\n",
- depsgraph_name_for_logging(depsgraph).c_str(),
- function_name,
- object_name,
- DEG::color_for_pointer(object_address).c_str(),
- object_address,
- DEG::color_end().c_str(),
- time);
- fflush(stdout);
+ if ((DEG_debug_flags_get(depsgraph) & G_DEBUG_DEPSGRAPH_EVAL) == 0) {
+ return;
+ }
+ fprintf(stdout,
+ "%s%s on %s %s(%p)%s at time %f\n",
+ depsgraph_name_for_logging(depsgraph).c_str(),
+ function_name,
+ object_name,
+ DEG::color_for_pointer(object_address).c_str(),
+ object_address,
+ DEG::color_end().c_str(),
+ time);
+ fflush(stdout);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc
index 30370c5ac15..6f3262174b4 100644
--- a/source/blender/depsgraph/intern/depsgraph_eval.cc
+++ b/source/blender/depsgraph/intern/depsgraph_eval.cc
@@ -51,40 +51,38 @@ extern "C" {
/* Evaluate all nodes tagged for updating. */
void DEG_evaluate_on_refresh(Depsgraph *graph)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- deg_graph->ctime = BKE_scene_frame_get(deg_graph->scene);
- /* Update time on primary timesource. */
- DEG::TimeSourceNode *tsrc = deg_graph->find_time_source();
- tsrc->cfra = deg_graph->ctime;
- /* Update time in scene. */
- if (deg_graph->scene_cow) {
- BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime);
- }
- DEG::deg_evaluate_on_refresh(deg_graph);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->ctime = BKE_scene_frame_get(deg_graph->scene);
+ /* Update time on primary timesource. */
+ DEG::TimeSourceNode *tsrc = deg_graph->find_time_source();
+ tsrc->cfra = deg_graph->ctime;
+ /* Update time in scene. */
+ if (deg_graph->scene_cow) {
+ BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime);
+ }
+ DEG::deg_evaluate_on_refresh(deg_graph);
}
/* Frame-change happened for root scene that graph belongs to. */
-void DEG_evaluate_on_framechange(Main *bmain,
- Depsgraph *graph,
- float ctime)
+void DEG_evaluate_on_framechange(Main *bmain, Depsgraph *graph, float ctime)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- deg_graph->ctime = ctime;
- /* Update time on primary timesource. */
- DEG::TimeSourceNode *tsrc = deg_graph->find_time_source();
- tsrc->cfra = ctime;
- tsrc->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_TIME);
- DEG::deg_graph_flush_updates(bmain, deg_graph);
- /* Update time in scene. */
- if (deg_graph->scene_cow) {
- BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime);
- }
- /* Perform recalculation updates. */
- DEG::deg_evaluate_on_refresh(deg_graph);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ deg_graph->ctime = ctime;
+ /* Update time on primary timesource. */
+ DEG::TimeSourceNode *tsrc = deg_graph->find_time_source();
+ tsrc->cfra = ctime;
+ tsrc->tag_update(deg_graph, DEG::DEG_UPDATE_SOURCE_TIME);
+ DEG::deg_graph_flush_updates(bmain, deg_graph);
+ /* Update time in scene. */
+ if (deg_graph->scene_cow) {
+ BKE_scene_frame_set(deg_graph->scene_cow, deg_graph->ctime);
+ }
+ /* Perform recalculation updates. */
+ DEG::deg_evaluate_on_refresh(deg_graph);
}
bool DEG_needs_eval(Depsgraph *graph)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
- return BLI_gset_len(deg_graph->entry_tags) != 0;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph);
+ return BLI_gset_len(deg_graph->entry_tags) != 0;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc
index 02265ba0e7a..3f81e49b170 100644
--- a/source/blender/depsgraph/intern/depsgraph_physics.cc
+++ b/source/blender/depsgraph/intern/depsgraph_physics.cc
@@ -49,51 +49,44 @@ extern "C" {
/*************************** Evaluation Query API *****************************/
-static ePhysicsRelationType modifier_to_relation_type(
- unsigned int modifier_type)
+static ePhysicsRelationType modifier_to_relation_type(unsigned int modifier_type)
{
- switch (modifier_type) {
- case eModifierType_Collision:
- return DEG_PHYSICS_COLLISION;
- case eModifierType_Smoke:
- return DEG_PHYSICS_SMOKE_COLLISION;
- case eModifierType_DynamicPaint:
- return DEG_PHYSICS_DYNAMIC_BRUSH;
- }
-
- BLI_assert(!"Unknown collision modifier type");
- return DEG_PHYSICS_RELATIONS_NUM;
+ switch (modifier_type) {
+ case eModifierType_Collision:
+ return DEG_PHYSICS_COLLISION;
+ case eModifierType_Smoke:
+ return DEG_PHYSICS_SMOKE_COLLISION;
+ case eModifierType_DynamicPaint:
+ return DEG_PHYSICS_DYNAMIC_BRUSH;
+ }
+
+ BLI_assert(!"Unknown collision modifier type");
+ return DEG_PHYSICS_RELATIONS_NUM;
}
-ListBase *DEG_get_effector_relations(const Depsgraph *graph,
- Collection *collection)
+ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collection)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(graph);
- if (deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR] == NULL) {
- return NULL;
- }
-
- ID *collection_orig = DEG_get_original_id(&collection->id);
- return (ListBase *)BLI_ghash_lookup(
- deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR],
- collection_orig);
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ if (deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR] == NULL) {
+ return NULL;
+ }
+
+ ID *collection_orig = DEG_get_original_id(&collection->id);
+ return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR],
+ collection_orig);
}
ListBase *DEG_get_collision_relations(const Depsgraph *graph,
Collection *collection,
unsigned int modifier_type)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(graph);
- const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
- if (deg_graph->physics_relations[type] == NULL) {
- return NULL;
- }
- ID *collection_orig = DEG_get_original_id(&collection->id);
- return (ListBase *)BLI_ghash_lookup(
- deg_graph->physics_relations[type],
- collection_orig);
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
+ if (deg_graph->physics_relations[type] == NULL) {
+ return NULL;
+ }
+ ID *collection_orig = DEG_get_original_id(&collection->id);
+ return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[type], collection_orig);
}
/********************** Depsgraph Building API ************************/
@@ -105,26 +98,20 @@ void DEG_add_collision_relations(DepsNodeHandle *handle,
DEG_CollobjFilterFunction filter_function,
const char *name)
{
- Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
- DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
- ListBase *relations = build_collision_relations(
- deg_graph, collection, modifier_type);
- LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
- Object *ob1 = relation->ob;
- if (ob1 == object) {
- continue;
- }
- if (filter_function == NULL ||
- filter_function(
- ob1,
- modifiers_findByType(ob1, (ModifierType)modifier_type)))
- {
- DEG_add_object_pointcache_relation(
- handle, ob1, DEG_OB_COMP_TRANSFORM, name);
- DEG_add_object_pointcache_relation(
- handle, ob1, DEG_OB_COMP_GEOMETRY, name);
- }
- }
+ Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
+ DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
+ ListBase *relations = build_collision_relations(deg_graph, collection, modifier_type);
+ LISTBASE_FOREACH (CollisionRelation *, relation, relations) {
+ Object *ob1 = relation->ob;
+ if (ob1 == object) {
+ continue;
+ }
+ if (filter_function == NULL ||
+ filter_function(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) {
+ DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name);
+ DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name);
+ }
+ }
}
void DEG_add_forcefield_relations(DepsNodeHandle *handle,
@@ -134,144 +121,119 @@ void DEG_add_forcefield_relations(DepsNodeHandle *handle,
int skip_forcefield,
const char *name)
{
- Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
- DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
- ListBase *relations =
- build_effector_relations(deg_graph, effector_weights->group);
- LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
- if (relation->ob == object) {
- continue;
- }
- if (relation->pd->forcefield == skip_forcefield) {
- continue;
- }
-
- /* Relation to forcefield object, optionally including geometry.
- * Use special point cache relations for automatic cache clearing. */
- DEG_add_object_pointcache_relation(
- handle, relation->ob, DEG_OB_COMP_TRANSFORM, name);
-
- if (relation->psys ||
- ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
- relation->pd->forcefield == PFIELD_GUIDE)
- {
- /* TODO(sergey): Consider going more granular with more dedicated
- * particle system operation. */
- DEG_add_object_pointcache_relation(
- handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
- }
-
- /* Smoke flow relations. */
- if (relation->pd->forcefield == PFIELD_SMOKEFLOW &&
- relation->pd->f_source != NULL)
- {
- DEG_add_object_pointcache_relation(handle,
- relation->pd->f_source,
- DEG_OB_COMP_TRANSFORM,
- "Smoke Force Domain");
- DEG_add_object_pointcache_relation(handle,
- relation->pd->f_source,
- DEG_OB_COMP_GEOMETRY,
- "Smoke Force Domain");
- }
-
- /* Absorption forces need collision relation. */
- if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
- DEG_add_collision_relations(handle,
- object,
- NULL,
- eModifierType_Collision,
- NULL,
- "Force Absorption");
- }
- }
+ Depsgraph *depsgraph = DEG_get_graph_from_handle(handle);
+ DEG::Depsgraph *deg_graph = (DEG::Depsgraph *)depsgraph;
+ ListBase *relations = build_effector_relations(deg_graph, effector_weights->group);
+ LISTBASE_FOREACH (EffectorRelation *, relation, relations) {
+ if (relation->ob == object) {
+ continue;
+ }
+ if (relation->pd->forcefield == skip_forcefield) {
+ continue;
+ }
+
+ /* Relation to forcefield object, optionally including geometry.
+ * Use special point cache relations for automatic cache clearing. */
+ DEG_add_object_pointcache_relation(handle, relation->ob, DEG_OB_COMP_TRANSFORM, name);
+
+ if (relation->psys || ELEM(relation->pd->shape, PFIELD_SHAPE_SURFACE, PFIELD_SHAPE_POINTS) ||
+ relation->pd->forcefield == PFIELD_GUIDE) {
+ /* TODO(sergey): Consider going more granular with more dedicated
+ * particle system operation. */
+ DEG_add_object_pointcache_relation(handle, relation->ob, DEG_OB_COMP_GEOMETRY, name);
+ }
+
+ /* Smoke flow relations. */
+ if (relation->pd->forcefield == PFIELD_SMOKEFLOW && relation->pd->f_source != NULL) {
+ DEG_add_object_pointcache_relation(
+ handle, relation->pd->f_source, DEG_OB_COMP_TRANSFORM, "Smoke Force Domain");
+ DEG_add_object_pointcache_relation(
+ handle, relation->pd->f_source, DEG_OB_COMP_GEOMETRY, "Smoke Force Domain");
+ }
+
+ /* Absorption forces need collision relation. */
+ if (add_absorption && (relation->pd->flag & PFIELD_VISIBILITY)) {
+ DEG_add_collision_relations(
+ handle, object, NULL, eModifierType_Collision, NULL, "Force Absorption");
+ }
+ }
}
/******************************** Internal API ********************************/
-namespace DEG
-{
+namespace DEG {
ListBase *build_effector_relations(Depsgraph *graph, Collection *collection)
{
- GHash *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
- if (hash == NULL) {
- graph->physics_relations[DEG_PHYSICS_EFFECTOR] =
- BLI_ghash_ptr_new("Depsgraph physics relations hash");
- hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
- }
- ListBase *relations =
- reinterpret_cast<ListBase*>(BLI_ghash_lookup(hash, collection));
- if (relations == NULL) {
- ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
- relations = BKE_effector_relations_create(
- depsgraph, graph->view_layer, collection);
- BLI_ghash_insert(hash, &collection->id, relations);
- }
- return relations;
+ GHash *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
+ if (hash == NULL) {
+ graph->physics_relations[DEG_PHYSICS_EFFECTOR] = BLI_ghash_ptr_new(
+ "Depsgraph physics relations hash");
+ hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR];
+ }
+ ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection));
+ if (relations == NULL) {
+ ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
+ relations = BKE_effector_relations_create(depsgraph, graph->view_layer, collection);
+ BLI_ghash_insert(hash, &collection->id, relations);
+ }
+ return relations;
}
ListBase *build_collision_relations(Depsgraph *graph,
Collection *collection,
unsigned int modifier_type)
{
- const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
- GHash *hash = graph->physics_relations[type];
- if (hash == NULL) {
- graph->physics_relations[type] =
- BLI_ghash_ptr_new("Depsgraph physics relations hash");
- hash = graph->physics_relations[type];
- }
- ListBase *relations =
- reinterpret_cast<ListBase*>(BLI_ghash_lookup(hash, collection));
- if (relations == NULL) {
- ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph*>(graph);
- relations = BKE_collision_relations_create(
- depsgraph, collection, modifier_type);
- BLI_ghash_insert(hash, &collection->id, relations);
- }
- return relations;
+ const ePhysicsRelationType type = modifier_to_relation_type(modifier_type);
+ GHash *hash = graph->physics_relations[type];
+ if (hash == NULL) {
+ graph->physics_relations[type] = BLI_ghash_ptr_new("Depsgraph physics relations hash");
+ hash = graph->physics_relations[type];
+ }
+ ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection));
+ if (relations == NULL) {
+ ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph);
+ relations = BKE_collision_relations_create(depsgraph, collection, modifier_type);
+ BLI_ghash_insert(hash, &collection->id, relations);
+ }
+ return relations;
}
namespace {
void free_effector_relations(void *value)
{
- BKE_effector_relations_free(reinterpret_cast<ListBase*>(value));
+ BKE_effector_relations_free(reinterpret_cast<ListBase *>(value));
}
void free_collision_relations(void *value)
{
- BKE_collision_relations_free(reinterpret_cast<ListBase*>(value));
+ BKE_collision_relations_free(reinterpret_cast<ListBase *>(value));
}
} // namespace
void clear_physics_relations(Depsgraph *graph)
{
- for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) {
- if (graph->physics_relations[i]) {
- const ePhysicsRelationType type = (ePhysicsRelationType)i;
-
- switch (type) {
- case DEG_PHYSICS_EFFECTOR:
- BLI_ghash_free(graph->physics_relations[i],
- NULL,
- free_effector_relations);
- break;
- case DEG_PHYSICS_COLLISION:
- case DEG_PHYSICS_SMOKE_COLLISION:
- case DEG_PHYSICS_DYNAMIC_BRUSH:
- BLI_ghash_free(graph->physics_relations[i],
- NULL,
- free_collision_relations);
- break;
- case DEG_PHYSICS_RELATIONS_NUM:
- break;
- }
- graph->physics_relations[i] = NULL;
- }
- }
+ for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) {
+ if (graph->physics_relations[i]) {
+ const ePhysicsRelationType type = (ePhysicsRelationType)i;
+
+ switch (type) {
+ case DEG_PHYSICS_EFFECTOR:
+ BLI_ghash_free(graph->physics_relations[i], NULL, free_effector_relations);
+ break;
+ case DEG_PHYSICS_COLLISION:
+ case DEG_PHYSICS_SMOKE_COLLISION:
+ case DEG_PHYSICS_DYNAMIC_BRUSH:
+ BLI_ghash_free(graph->physics_relations[i], NULL, free_collision_relations);
+ break;
+ case DEG_PHYSICS_RELATIONS_NUM:
+ break;
+ }
+ graph->physics_relations[i] = NULL;
+ }
+ }
}
-}
+} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 3b7f19e9916..a653366a588 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -26,7 +26,7 @@
#include "MEM_guardedalloc.h"
extern "C" {
-#include <string.h> // XXX: memcpy
+#include <string.h> // XXX: memcpy
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
@@ -34,7 +34,7 @@ extern "C" {
#include "BKE_main.h"
#include "BLI_listbase.h"
-#include "BKE_action.h" // XXX: BKE_pose_channel_from_name
+#include "BKE_action.h" // XXX: BKE_pose_channel_from_name
} /* extern "C" */
#include "DNA_object_types.h"
@@ -51,211 +51,215 @@ extern "C" {
struct Scene *DEG_get_input_scene(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- return deg_graph->scene;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->scene;
}
struct ViewLayer *DEG_get_input_view_layer(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- return deg_graph->view_layer;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->view_layer;
}
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- return deg_graph->mode;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->mode;
}
float DEG_get_ctime(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- return deg_graph->ctime;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->ctime;
}
-
bool DEG_id_type_updated(const Depsgraph *graph, short id_type)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- return deg_graph->id_type_updated[BKE_idcode_to_index(id_type)] != 0;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ return deg_graph->id_type_updated[BKE_idcode_to_index(id_type)] != 0;
}
bool DEG_id_type_any_updated(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- /* Loop over all ID types. */
- for (int id_type_index = 0; id_type_index < MAX_LIBARRAY; id_type_index++) {
- if (deg_graph->id_type_updated[id_type_index]) {
- return true;
- }
- }
+ /* Loop over all ID types. */
+ for (int id_type_index = 0; id_type_index < MAX_LIBARRAY; id_type_index++) {
+ if (deg_graph->id_type_updated[id_type_index]) {
+ return true;
+ }
+ }
- return false;
+ return false;
}
uint32_t DEG_get_eval_flags_for_id(const Depsgraph *graph, ID *id)
{
- if (graph == NULL) {
- /* Happens when converting objects to mesh from a python script
- * after modifying scene graph.
- *
- * Currently harmless because it's only called for temporary
- * objects which are out of the DAG anyway. */
- return 0;
- }
+ if (graph == NULL) {
+ /* Happens when converting objects to mesh from a python script
+ * after modifying scene graph.
+ *
+ * Currently harmless because it's only called for temporary
+ * objects which are out of the DAG anyway. */
+ return 0;
+ }
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- const DEG::IDNode *id_node = deg_graph->find_id_node(DEG_get_original_id(id));
- if (id_node == NULL) {
- /* TODO(sergey): Does it mean we need to check set scene? */
- return 0;
- }
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::IDNode *id_node = deg_graph->find_id_node(DEG_get_original_id(id));
+ if (id_node == NULL) {
+ /* TODO(sergey): Does it mean we need to check set scene? */
+ return 0;
+ }
- return id_node->eval_flags;
+ return id_node->eval_flags;
}
-void DEG_get_customdata_mask_for_object(const Depsgraph *graph, Object *ob, CustomData_MeshMasks *r_mask)
+void DEG_get_customdata_mask_for_object(const Depsgraph *graph,
+ Object *ob,
+ CustomData_MeshMasks *r_mask)
{
- if (graph == NULL) {
- /* Happens when converting objects to mesh from a python script
- * after modifying scene graph.
- *
- * Currently harmless because it's only called for temporary
- * objects which are out of the DAG anyway. */
- return;
- }
+ if (graph == NULL) {
+ /* Happens when converting objects to mesh from a python script
+ * after modifying scene graph.
+ *
+ * Currently harmless because it's only called for temporary
+ * objects which are out of the DAG anyway. */
+ return;
+ }
- const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- const DEG::IDNode *id_node = deg_graph->find_id_node(DEG_get_original_id(&ob->id));
- if (id_node == NULL) {
- /* TODO(sergey): Does it mean we need to check set scene? */
- return;
- }
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ const DEG::IDNode *id_node = deg_graph->find_id_node(DEG_get_original_id(&ob->id));
+ if (id_node == NULL) {
+ /* TODO(sergey): Does it mean we need to check set scene? */
+ return;
+ }
- r_mask->vmask |= id_node->customdata_masks.vert_mask;
- r_mask->emask |= id_node->customdata_masks.edge_mask;
- r_mask->fmask |= id_node->customdata_masks.face_mask;
- r_mask->lmask |= id_node->customdata_masks.loop_mask;
- r_mask->pmask |= id_node->customdata_masks.poly_mask;
+ r_mask->vmask |= id_node->customdata_masks.vert_mask;
+ r_mask->emask |= id_node->customdata_masks.edge_mask;
+ r_mask->fmask |= id_node->customdata_masks.face_mask;
+ r_mask->lmask |= id_node->customdata_masks.loop_mask;
+ r_mask->pmask |= id_node->customdata_masks.poly_mask;
}
Scene *DEG_get_evaluated_scene(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(graph);
- Scene *scene_cow = deg_graph->scene_cow;
- /* TODO(sergey): Shall we expand datablock here? Or is it OK to assume
- * that calleer is OK with just a pointer in case scene is not updated
- * yet? */
- BLI_assert(scene_cow != NULL && DEG::deg_copy_on_write_is_expanded(&scene_cow->id));
- return scene_cow;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ Scene *scene_cow = deg_graph->scene_cow;
+ /* TODO(sergey): Shall we expand datablock here? Or is it OK to assume
+ * that calleer is OK with just a pointer in case scene is not updated
+ * yet? */
+ BLI_assert(scene_cow != NULL && DEG::deg_copy_on_write_is_expanded(&scene_cow->id));
+ return scene_cow;
}
ViewLayer *DEG_get_evaluated_view_layer(const Depsgraph *graph)
{
- const DEG::Depsgraph *deg_graph =
- reinterpret_cast<const DEG::Depsgraph *>(graph);
- Scene *scene_cow = DEG_get_evaluated_scene(graph);
- if (scene_cow == NULL) {
- return NULL; /* Happens with new, not-yet-built/evaluated graphes. */
- }
- /* Do name-based lookup. */
- /* TODO(sergey): Can this be optimized? */
- ViewLayer *view_layer_orig = deg_graph->view_layer;
- ViewLayer *view_layer_cow =
- (ViewLayer *)BLI_findstring(&scene_cow->view_layers,
- view_layer_orig->name,
- offsetof(ViewLayer, name));
- BLI_assert(view_layer_cow != NULL);
- return view_layer_cow;
+ const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ Scene *scene_cow = DEG_get_evaluated_scene(graph);
+ if (scene_cow == NULL) {
+ return NULL; /* Happens with new, not-yet-built/evaluated graphes. */
+ }
+ /* Do name-based lookup. */
+ /* TODO(sergey): Can this be optimized? */
+ ViewLayer *view_layer_orig = deg_graph->view_layer;
+ ViewLayer *view_layer_cow = (ViewLayer *)BLI_findstring(
+ &scene_cow->view_layers, view_layer_orig->name, offsetof(ViewLayer, name));
+ BLI_assert(view_layer_cow != NULL);
+ return view_layer_cow;
}
Object *DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
{
- return (Object *)DEG_get_evaluated_id(depsgraph, &object->id);
+ return (Object *)DEG_get_evaluated_id(depsgraph, &object->id);
}
ID *DEG_get_evaluated_id(const Depsgraph *depsgraph, ID *id)
{
- if (id == NULL) {
- return NULL;
- }
- /* TODO(sergey): This is a duplicate of Depsgraph::get_cow_id(),
- * but here we never do assert, since we don't know nature of the
- * incoming ID datablock. */
- const DEG::Depsgraph *deg_graph = (const DEG::Depsgraph *)depsgraph;
- const DEG::IDNode *id_node = deg_graph->find_id_node(id);
- if (id_node == NULL) {
- return id;
- }
- return id_node->id_cow;
+ if (id == NULL) {
+ return NULL;
+ }
+ /* TODO(sergey): This is a duplicate of Depsgraph::get_cow_id(),
+ * but here we never do assert, since we don't know nature of the
+ * incoming ID datablock. */
+ const DEG::Depsgraph *deg_graph = (const DEG::Depsgraph *)depsgraph;
+ const DEG::IDNode *id_node = deg_graph->find_id_node(id);
+ if (id_node == NULL) {
+ return id;
+ }
+ return id_node->id_cow;
}
/* Get evaluated version of data pointed to by RNA pointer */
-void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph, PointerRNA *ptr, PointerRNA *r_ptr_eval)
+void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph,
+ PointerRNA *ptr,
+ PointerRNA *r_ptr_eval)
{
- if ((ptr == NULL) || (r_ptr_eval == NULL)) {
- return;
- }
- ID *orig_id = (ID *)ptr->id.data;
- ID *cow_id = DEG_get_evaluated_id(depsgraph, orig_id);
- if (ptr->id.data == ptr->data) {
- /* For ID pointers, it's easy... */
- r_ptr_eval->id.data = (void *)cow_id;
- r_ptr_eval->data = (void *)cow_id;
- r_ptr_eval->type = ptr->type;
- }
- else if (ptr->type == &RNA_PoseBone) {
- /* HACK: Since bone keyframing is quite commonly used,
- * speed things up for this case by doing a special lookup
- * for bones */
- const Object *ob_eval = (Object *)cow_id;
- bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- r_ptr_eval->id.data = (void *)cow_id;
- r_ptr_eval->data = (void *)pchan_eval;
- r_ptr_eval->type = ptr->type;
- }
- else {
- /* For everything else, try to get RNA Path of the BMain-pointer,
- * then use that to look up what the COW-domain one should be
- * given the COW ID pointer as the new lookup point */
- /* TODO: Find a faster alternative, or implement support for other
- * common types too above (e.g. modifiers) */
- char *path = RNA_path_from_ID_to_struct(ptr);
- if (path) {
- PointerRNA cow_id_ptr;
- RNA_id_pointer_create(cow_id, &cow_id_ptr);
- if (!RNA_path_resolve(&cow_id_ptr, path, r_ptr_eval, NULL)) {
- /* Couldn't find COW copy of data */
- fprintf(stderr,
- "%s: Couldn't resolve RNA path ('%s') relative to COW ID (%p) for '%s'\n",
- __func__, path, (void *)cow_id, orig_id->name);
- }
- }
- else {
- /* Path resolution failed - XXX: Hide this behind a debug flag */
- fprintf(stderr,
- "%s: Couldn't get RNA path for %s relative to %s\n",
- __func__, RNA_struct_identifier(ptr->type), orig_id->name);
- }
- }
+ if ((ptr == NULL) || (r_ptr_eval == NULL)) {
+ return;
+ }
+ ID *orig_id = (ID *)ptr->id.data;
+ ID *cow_id = DEG_get_evaluated_id(depsgraph, orig_id);
+ if (ptr->id.data == ptr->data) {
+ /* For ID pointers, it's easy... */
+ r_ptr_eval->id.data = (void *)cow_id;
+ r_ptr_eval->data = (void *)cow_id;
+ r_ptr_eval->type = ptr->type;
+ }
+ else if (ptr->type == &RNA_PoseBone) {
+ /* HACK: Since bone keyframing is quite commonly used,
+ * speed things up for this case by doing a special lookup
+ * for bones */
+ const Object *ob_eval = (Object *)cow_id;
+ bPoseChannel *pchan = (bPoseChannel *)ptr->data;
+ const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
+ r_ptr_eval->id.data = (void *)cow_id;
+ r_ptr_eval->data = (void *)pchan_eval;
+ r_ptr_eval->type = ptr->type;
+ }
+ else {
+ /* For everything else, try to get RNA Path of the BMain-pointer,
+ * then use that to look up what the COW-domain one should be
+ * given the COW ID pointer as the new lookup point */
+ /* TODO: Find a faster alternative, or implement support for other
+ * common types too above (e.g. modifiers) */
+ char *path = RNA_path_from_ID_to_struct(ptr);
+ if (path) {
+ PointerRNA cow_id_ptr;
+ RNA_id_pointer_create(cow_id, &cow_id_ptr);
+ if (!RNA_path_resolve(&cow_id_ptr, path, r_ptr_eval, NULL)) {
+ /* Couldn't find COW copy of data */
+ fprintf(stderr,
+ "%s: Couldn't resolve RNA path ('%s') relative to COW ID (%p) for '%s'\n",
+ __func__,
+ path,
+ (void *)cow_id,
+ orig_id->name);
+ }
+ }
+ else {
+ /* Path resolution failed - XXX: Hide this behind a debug flag */
+ fprintf(stderr,
+ "%s: Couldn't get RNA path for %s relative to %s\n",
+ __func__,
+ RNA_struct_identifier(ptr->type),
+ orig_id->name);
+ }
+ }
}
Object *DEG_get_original_object(Object *object)
{
- return (Object *)DEG_get_original_id(&object->id);
+ return (Object *)DEG_get_original_id(&object->id);
}
ID *DEG_get_original_id(ID *id)
{
- if (id == NULL) {
- return NULL;
- }
- if (id->orig_id == NULL) {
- return id;
- }
- BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) != 0);
- return (ID *)id->orig_id;
+ if (id == NULL) {
+ return NULL;
+ }
+ if (id->orig_id == NULL) {
+ return id;
+ }
+ BLI_assert((id->tag & LIB_TAG_COPIED_ON_WRITE) != 0);
+ return (ID *)id->orig_id;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_filter.cc b/source/blender/depsgraph/intern/depsgraph_query_filter.cc
index dbfc488d44e..987e9330d35 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_filter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_filter.cc
@@ -26,7 +26,7 @@
#include "MEM_guardedalloc.h"
extern "C" {
-#include <string.h> // XXX: memcpy
+#include <string.h> // XXX: memcpy
#include "BLI_utildefines.h"
#include "BKE_idcode.h"
@@ -34,7 +34,7 @@ extern "C" {
#include "BLI_listbase.h"
#include "BLI_ghash.h"
-#include "BKE_action.h" // XXX: BKE_pose_channel_from_name
+#include "BKE_action.h" // XXX: BKE_pose_channel_from_name
} /* extern "C" */
#include "DNA_object_types.h"
@@ -56,7 +56,6 @@ extern "C" {
#include "intern/node/deg_node_id.h"
#include "intern/node/deg_node_operation.h"
-
/* *************************************************** */
/* Graph Filtering Internals */
@@ -64,8 +63,8 @@ namespace DEG {
/* UserData for deg_add_retained_id_cb */
struct RetainedIdUserData {
- DEG_FilterQuery *query;
- GSet *set;
+ DEG_FilterQuery *query;
+ GSet *set;
};
/* Helper for DEG_foreach_ancestor_id()
@@ -73,8 +72,8 @@ struct RetainedIdUserData {
*/
static void deg_add_retained_id_cb(ID *id, void *user_data)
{
- RetainedIdUserData *data = (RetainedIdUserData *)user_data;
- BLI_gset_add(data->set, (void *)id);
+ RetainedIdUserData *data = (RetainedIdUserData *)user_data;
+ BLI_gset_add(data->set, (void *)id);
}
/* ------------------------------------------- */
@@ -83,92 +82,87 @@ static void deg_add_retained_id_cb(ID *id, void *user_data)
/* TODO: Make this part of OperationNode? */
static void deg_unlink_opnode(Depsgraph *graph, OperationNode *op_node)
{
- vector<Relation *> all_links;
-
- /* Collect all inlinks to this operation */
- for (Relation *rel : op_node->inlinks) {
- all_links.push_back(rel);
- }
- /* Collect all outlinks from this operation */
- for (Relation *rel : op_node->outlinks) {
- all_links.push_back(rel);
- }
-
- /* Delete all collected relations */
- for (Relation *rel : all_links) {
- rel->unlink();
- OBJECT_GUARDED_DELETE(rel, Relation);
- }
-
- /* Remove from entry tags */
- if (BLI_gset_haskey(graph->entry_tags, op_node)) {
- BLI_gset_remove(graph->entry_tags, op_node, NULL);
- }
+ vector<Relation *> all_links;
+
+ /* Collect all inlinks to this operation */
+ for (Relation *rel : op_node->inlinks) {
+ all_links.push_back(rel);
+ }
+ /* Collect all outlinks from this operation */
+ for (Relation *rel : op_node->outlinks) {
+ all_links.push_back(rel);
+ }
+
+ /* Delete all collected relations */
+ for (Relation *rel : all_links) {
+ rel->unlink();
+ OBJECT_GUARDED_DELETE(rel, Relation);
+ }
+
+ /* Remove from entry tags */
+ if (BLI_gset_haskey(graph->entry_tags, op_node)) {
+ BLI_gset_remove(graph->entry_tags, op_node, NULL);
+ }
}
/* Remove every ID Node (and its associated subnodes, COW data) */
static void deg_filter_remove_unwanted_ids(Depsgraph *graph, GSet *retained_ids)
{
- /* 1) First pass over ID nodes + their operations
- * - Identify and tag ID's (via "custom_flags = 1") to be removed
- * - Remove all links to/from operations that will be removed. */
- for (IDNode *id_node : graph->id_nodes) {
- id_node->custom_flags = !BLI_gset_haskey(retained_ids, (void *)id_node->id_orig);
- if (id_node->custom_flags) {
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- for (OperationNode *op_node : comp_node->operations) {
- deg_unlink_opnode(graph, op_node);
- }
- }
- GHASH_FOREACH_END();
- }
- }
-
- /* 2) Remove unwanted operations from graph->operations */
- for (Depsgraph::OperationNodes::iterator it_opnode = graph->operations.begin();
- it_opnode != graph->operations.end();
- )
- {
- OperationNode *op_node = *it_opnode;
- IDNode *id_node = op_node->owner->owner;
- if (id_node->custom_flags) {
- it_opnode = graph->operations.erase(it_opnode);
- }
- else {
- ++it_opnode;
- }
- }
-
- /* Free ID nodes that are no longer wanted
- *
- * This is loosely based on Depsgraph::clear_id_nodes().
- * However, we don't worry about the conditional freeing for physics
- * stuff, since it's rarely needed currently. */
- for (Depsgraph::IDDepsNodes::iterator it_id = graph->id_nodes.begin();
- it_id != graph->id_nodes.end();
- )
- {
- IDNode *id_node = *it_id;
- ID *id = id_node->id_orig;
-
- if (id_node->custom_flags) {
- /* Destroy node data, then remove from collections, and free */
- id_node->destroy();
-
- BLI_ghash_remove(graph->id_hash, id, NULL, NULL);
- it_id = graph->id_nodes.erase(it_id);
-
- OBJECT_GUARDED_DELETE(id_node, IDNode);
- }
- else {
- /* This node has not been marked for deletion. Increment iterator */
- ++it_id;
- }
- }
+ /* 1) First pass over ID nodes + their operations
+ * - Identify and tag ID's (via "custom_flags = 1") to be removed
+ * - Remove all links to/from operations that will be removed. */
+ for (IDNode *id_node : graph->id_nodes) {
+ id_node->custom_flags = !BLI_gset_haskey(retained_ids, (void *)id_node->id_orig);
+ if (id_node->custom_flags) {
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ for (OperationNode *op_node : comp_node->operations) {
+ deg_unlink_opnode(graph, op_node);
+ }
+ }
+ GHASH_FOREACH_END();
+ }
+ }
+
+ /* 2) Remove unwanted operations from graph->operations */
+ for (Depsgraph::OperationNodes::iterator it_opnode = graph->operations.begin();
+ it_opnode != graph->operations.end();) {
+ OperationNode *op_node = *it_opnode;
+ IDNode *id_node = op_node->owner->owner;
+ if (id_node->custom_flags) {
+ it_opnode = graph->operations.erase(it_opnode);
+ }
+ else {
+ ++it_opnode;
+ }
+ }
+
+ /* Free ID nodes that are no longer wanted
+ *
+ * This is loosely based on Depsgraph::clear_id_nodes().
+ * However, we don't worry about the conditional freeing for physics
+ * stuff, since it's rarely needed currently. */
+ for (Depsgraph::IDDepsNodes::iterator it_id = graph->id_nodes.begin();
+ it_id != graph->id_nodes.end();) {
+ IDNode *id_node = *it_id;
+ ID *id = id_node->id_orig;
+
+ if (id_node->custom_flags) {
+ /* Destroy node data, then remove from collections, and free */
+ id_node->destroy();
+
+ BLI_ghash_remove(graph->id_hash, id, NULL, NULL);
+ it_id = graph->id_nodes.erase(it_id);
+
+ OBJECT_GUARDED_DELETE(id_node, IDNode);
+ }
+ else {
+ /* This node has not been marked for deletion. Increment iterator */
+ ++it_id;
+ }
+ }
}
-} //namespace DEG
+} //namespace DEG
/* *************************************************** */
/* Graph Filtering API */
@@ -179,67 +173,71 @@ static void deg_filter_remove_unwanted_ids(Depsgraph *graph, GSet *retained_ids)
*/
Depsgraph *DEG_graph_filter(const Depsgraph *graph_src, Main *bmain, DEG_FilterQuery *query)
{
- const DEG::Depsgraph *deg_graph_src = reinterpret_cast<const DEG::Depsgraph *>(graph_src);
- if (deg_graph_src == NULL) {
- return NULL;
- }
-
- /* Construct a full new depsgraph based on the one we got */
- /* TODO: Improve the builders to not add any ID nodes we don't need later (e.g. ProxyBuilder?) */
- Depsgraph *graph_new = DEG_graph_new(deg_graph_src->scene,
- deg_graph_src->view_layer,
- deg_graph_src->mode);
- DEG_graph_build_from_view_layer(graph_new,
- bmain,
- deg_graph_src->scene,
- deg_graph_src->view_layer);
-
- /* Build a set of all the id's we want to keep */
- GSet *retained_ids = BLI_gset_ptr_new(__func__);
- DEG::RetainedIdUserData retained_id_data = {query, retained_ids};
-
- LISTBASE_FOREACH (DEG_FilterTarget *, target, &query->targets) {
- /* Target Itself */
- BLI_gset_add(retained_ids, (void *)target->id);
-
- /* Target's Ancestors (i.e. things it depends on) */
- DEG_foreach_ancestor_ID(graph_new,
- target->id,
- DEG::deg_add_retained_id_cb,
- &retained_id_data);
- }
-
- /* Remove everything we don't want to keep around anymore */
- DEG::Depsgraph *deg_graph_new = reinterpret_cast<DEG::Depsgraph *>(graph_new);
- if (BLI_gset_len(retained_ids) > 0) {
- DEG::deg_filter_remove_unwanted_ids(deg_graph_new, retained_ids);
- }
- // TODO: query->LOD filters
-
- /* Free temp data */
- BLI_gset_free(retained_ids, NULL);
- retained_ids = NULL;
-
- /* Print Stats */
- // XXX: Hide behind debug flags
- size_t s_outer, s_operations, s_relations;
- size_t s_ids = deg_graph_src->id_nodes.size();
- unsigned int s_idh = BLI_ghash_len(deg_graph_src->id_hash);
-
- size_t n_outer, n_operations, n_relations;
- size_t n_ids = deg_graph_new->id_nodes.size();
- unsigned int n_idh = BLI_ghash_len(deg_graph_new->id_hash);
-
- DEG_stats_simple(graph_src, &s_outer, &s_operations, &s_relations);
- DEG_stats_simple(graph_new, &n_outer, &n_operations, &n_relations);
-
- printf("%s: src = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
- __func__, s_ids, s_idh, s_outer, s_operations, s_relations);
- printf("%s: new = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
- __func__, n_ids, n_idh, n_outer, n_operations, n_relations);
-
- /* Return this new graph instance */
- return graph_new;
+ const DEG::Depsgraph *deg_graph_src = reinterpret_cast<const DEG::Depsgraph *>(graph_src);
+ if (deg_graph_src == NULL) {
+ return NULL;
+ }
+
+ /* Construct a full new depsgraph based on the one we got */
+ /* TODO: Improve the builders to not add any ID nodes we don't need later (e.g. ProxyBuilder?) */
+ Depsgraph *graph_new = DEG_graph_new(
+ deg_graph_src->scene, deg_graph_src->view_layer, deg_graph_src->mode);
+ DEG_graph_build_from_view_layer(
+ graph_new, bmain, deg_graph_src->scene, deg_graph_src->view_layer);
+
+ /* Build a set of all the id's we want to keep */
+ GSet *retained_ids = BLI_gset_ptr_new(__func__);
+ DEG::RetainedIdUserData retained_id_data = {query, retained_ids};
+
+ LISTBASE_FOREACH (DEG_FilterTarget *, target, &query->targets) {
+ /* Target Itself */
+ BLI_gset_add(retained_ids, (void *)target->id);
+
+ /* Target's Ancestors (i.e. things it depends on) */
+ DEG_foreach_ancestor_ID(graph_new, target->id, DEG::deg_add_retained_id_cb, &retained_id_data);
+ }
+
+ /* Remove everything we don't want to keep around anymore */
+ DEG::Depsgraph *deg_graph_new = reinterpret_cast<DEG::Depsgraph *>(graph_new);
+ if (BLI_gset_len(retained_ids) > 0) {
+ DEG::deg_filter_remove_unwanted_ids(deg_graph_new, retained_ids);
+ }
+ // TODO: query->LOD filters
+
+ /* Free temp data */
+ BLI_gset_free(retained_ids, NULL);
+ retained_ids = NULL;
+
+ /* Print Stats */
+ // XXX: Hide behind debug flags
+ size_t s_outer, s_operations, s_relations;
+ size_t s_ids = deg_graph_src->id_nodes.size();
+ unsigned int s_idh = BLI_ghash_len(deg_graph_src->id_hash);
+
+ size_t n_outer, n_operations, n_relations;
+ size_t n_ids = deg_graph_new->id_nodes.size();
+ unsigned int n_idh = BLI_ghash_len(deg_graph_new->id_hash);
+
+ DEG_stats_simple(graph_src, &s_outer, &s_operations, &s_relations);
+ DEG_stats_simple(graph_new, &n_outer, &n_operations, &n_relations);
+
+ printf("%s: src = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
+ __func__,
+ s_ids,
+ s_idh,
+ s_outer,
+ s_operations,
+ s_relations);
+ printf("%s: new = (ID's: %zu (%u), Out: %zu, Op: %zu, Rel: %zu)\n",
+ __func__,
+ n_ids,
+ n_idh,
+ n_outer,
+ n_operations,
+ n_relations);
+
+ /* Return this new graph instance */
+ return graph_new;
}
/* *************************************************** */
diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
index a2ca4be5e33..717793d60f1 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc
@@ -51,17 +51,17 @@ namespace DEG {
typedef std::deque<OperationNode *> TraversalQueue;
enum {
- DEG_NODE_VISITED = (1 << 0),
+ DEG_NODE_VISITED = (1 << 0),
};
static void deg_foreach_clear_flags(const Depsgraph *graph)
{
- for (OperationNode *op_node : graph->operations) {
- op_node->scheduled = false;
- }
- for (IDNode *id_node : graph->id_nodes) {
- id_node->custom_flags = 0;
- }
+ for (OperationNode *op_node : graph->operations) {
+ op_node->scheduled = false;
+ }
+ for (IDNode *id_node : graph->id_nodes) {
+ id_node->custom_flags = 0;
+ }
}
static void deg_foreach_dependent_ID(const Depsgraph *graph,
@@ -69,165 +69,161 @@ static void deg_foreach_dependent_ID(const Depsgraph *graph,
DEGForeachIDCallback callback,
void *user_data)
{
- /* Start with getting ID node from the graph. */
- IDNode *target_id_node = graph->find_id_node(id);
- if (target_id_node == NULL) {
- /* TODO(sergey): Shall we inform or assert here about attempt to start
- * iterating over non-existing ID? */
- return;
- }
- /* Make sure all runtime flags are ready and clear. */
- deg_foreach_clear_flags(graph);
- /* Start with scheduling all operations from ID node. */
- TraversalQueue queue;
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, target_id_node->components)
- {
- for (OperationNode *op_node : comp_node->operations) {
- queue.push_back(op_node);
- op_node->scheduled = true;
- }
- }
- GHASH_FOREACH_END();
- target_id_node->custom_flags |= DEG_NODE_VISITED;
- /* Process the queue. */
- while (!queue.empty()) {
- /* get next operation node to process. */
- OperationNode *op_node = queue.front();
- queue.pop_front();
- for (;;) {
- /* Check whether we need to inform callee about corresponding ID node. */
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
- if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
- /* TODO(sergey): Is it orig or CoW? */
- callback(id_node->id_orig, user_data);
- id_node->custom_flags |= DEG_NODE_VISITED;
- }
- /* Schedule outgoing operation nodes. */
- if (op_node->outlinks.size() == 1) {
- OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to;
- if (to_node->scheduled == false) {
- to_node->scheduled = true;
- op_node = to_node;
- }
- else {
- break;
- }
- }
- else {
- for (Relation *rel : op_node->outlinks) {
- OperationNode *to_node = (OperationNode *)rel->to;
- if (to_node->scheduled == false) {
- queue.push_front(to_node);
- to_node->scheduled = true;
- }
- }
- break;
- }
- }
- }
+ /* Start with getting ID node from the graph. */
+ IDNode *target_id_node = graph->find_id_node(id);
+ if (target_id_node == NULL) {
+ /* TODO(sergey): Shall we inform or assert here about attempt to start
+ * iterating over non-existing ID? */
+ return;
+ }
+ /* Make sure all runtime flags are ready and clear. */
+ deg_foreach_clear_flags(graph);
+ /* Start with scheduling all operations from ID node. */
+ TraversalQueue queue;
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) {
+ for (OperationNode *op_node : comp_node->operations) {
+ queue.push_back(op_node);
+ op_node->scheduled = true;
+ }
+ }
+ GHASH_FOREACH_END();
+ target_id_node->custom_flags |= DEG_NODE_VISITED;
+ /* Process the queue. */
+ while (!queue.empty()) {
+ /* get next operation node to process. */
+ OperationNode *op_node = queue.front();
+ queue.pop_front();
+ for (;;) {
+ /* Check whether we need to inform callee about corresponding ID node. */
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+ if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
+ /* TODO(sergey): Is it orig or CoW? */
+ callback(id_node->id_orig, user_data);
+ id_node->custom_flags |= DEG_NODE_VISITED;
+ }
+ /* Schedule outgoing operation nodes. */
+ if (op_node->outlinks.size() == 1) {
+ OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to;
+ if (to_node->scheduled == false) {
+ to_node->scheduled = true;
+ op_node = to_node;
+ }
+ else {
+ break;
+ }
+ }
+ else {
+ for (Relation *rel : op_node->outlinks) {
+ OperationNode *to_node = (OperationNode *)rel->to;
+ if (to_node->scheduled == false) {
+ queue.push_front(to_node);
+ to_node->scheduled = true;
+ }
+ }
+ break;
+ }
+ }
+ }
}
static void deg_foreach_ancestor_ID(const Depsgraph *graph,
- const ID *id,
- DEGForeachIDCallback callback,
- void *user_data)
+ const ID *id,
+ DEGForeachIDCallback callback,
+ void *user_data)
{
- /* Start with getting ID node from the graph. */
- IDNode *target_id_node = graph->find_id_node(id);
- if (target_id_node == NULL) {
- /* TODO(sergey): Shall we inform or assert here about attempt to start
- * iterating over non-existing ID? */
- return;
- }
- /* Make sure all runtime flags are ready and clear. */
- deg_foreach_clear_flags(graph);
- /* Start with scheduling all operations from ID node. */
- TraversalQueue queue;
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, target_id_node->components)
- {
- for (OperationNode *op_node : comp_node->operations) {
- queue.push_back(op_node);
- op_node->scheduled = true;
- }
- }
- GHASH_FOREACH_END();
- target_id_node->custom_flags |= DEG_NODE_VISITED;
- /* Process the queue. */
- while (!queue.empty()) {
- /* get next operation node to process. */
- OperationNode *op_node = queue.front();
- queue.pop_front();
- for (;;) {
- /* Check whether we need to inform callee about corresponding ID node. */
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
- if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
- /* TODO(sergey): Is it orig or CoW? */
- callback(id_node->id_orig, user_data);
- id_node->custom_flags |= DEG_NODE_VISITED;
- }
- /* Schedule incoming operation nodes. */
- if (op_node->inlinks.size() == 1) {
- Node *from = op_node->inlinks[0]->from;
- if (from->get_class() == NodeClass::OPERATION) {
- OperationNode *from_node = (OperationNode *)from;
- if (from_node->scheduled == false) {
- from_node->scheduled = true;
- op_node = from_node;
- }
- else {
- break;
- }
- }
- }
- else {
- for (Relation *rel : op_node->inlinks) {
- Node *from = rel->from;
- if (from->get_class() == NodeClass::OPERATION) {
- OperationNode *from_node = (OperationNode *)from;
- if (from_node->scheduled == false) {
- queue.push_front(from_node);
- from_node->scheduled = true;
- }
- }
- }
- break;
- }
- }
- }
+ /* Start with getting ID node from the graph. */
+ IDNode *target_id_node = graph->find_id_node(id);
+ if (target_id_node == NULL) {
+ /* TODO(sergey): Shall we inform or assert here about attempt to start
+ * iterating over non-existing ID? */
+ return;
+ }
+ /* Make sure all runtime flags are ready and clear. */
+ deg_foreach_clear_flags(graph);
+ /* Start with scheduling all operations from ID node. */
+ TraversalQueue queue;
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) {
+ for (OperationNode *op_node : comp_node->operations) {
+ queue.push_back(op_node);
+ op_node->scheduled = true;
+ }
+ }
+ GHASH_FOREACH_END();
+ target_id_node->custom_flags |= DEG_NODE_VISITED;
+ /* Process the queue. */
+ while (!queue.empty()) {
+ /* get next operation node to process. */
+ OperationNode *op_node = queue.front();
+ queue.pop_front();
+ for (;;) {
+ /* Check whether we need to inform callee about corresponding ID node. */
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+ if ((id_node->custom_flags & DEG_NODE_VISITED) == 0) {
+ /* TODO(sergey): Is it orig or CoW? */
+ callback(id_node->id_orig, user_data);
+ id_node->custom_flags |= DEG_NODE_VISITED;
+ }
+ /* Schedule incoming operation nodes. */
+ if (op_node->inlinks.size() == 1) {
+ Node *from = op_node->inlinks[0]->from;
+ if (from->get_class() == NodeClass::OPERATION) {
+ OperationNode *from_node = (OperationNode *)from;
+ if (from_node->scheduled == false) {
+ from_node->scheduled = true;
+ op_node = from_node;
+ }
+ else {
+ break;
+ }
+ }
+ }
+ else {
+ for (Relation *rel : op_node->inlinks) {
+ Node *from = rel->from;
+ if (from->get_class() == NodeClass::OPERATION) {
+ OperationNode *from_node = (OperationNode *)from;
+ if (from_node->scheduled == false) {
+ queue.push_front(from_node);
+ from_node->scheduled = true;
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
}
static void deg_foreach_id(const Depsgraph *depsgraph,
- DEGForeachIDCallback callback, void *user_data)
+ DEGForeachIDCallback callback,
+ void *user_data)
{
- for (const IDNode *id_node : depsgraph->id_nodes) {
- callback(id_node->id_orig, user_data);
- }
+ for (const IDNode *id_node : depsgraph->id_nodes) {
+ callback(id_node->id_orig, user_data);
+ }
}
} // namespace DEG
void DEG_foreach_dependent_ID(const Depsgraph *depsgraph,
const ID *id,
- DEGForeachIDCallback callback, void *user_data)
+ DEGForeachIDCallback callback,
+ void *user_data)
{
- DEG::deg_foreach_dependent_ID((const DEG::Depsgraph *)depsgraph,
- id,
- callback, user_data);
+ DEG::deg_foreach_dependent_ID((const DEG::Depsgraph *)depsgraph, id, callback, user_data);
}
void DEG_foreach_ancestor_ID(const Depsgraph *depsgraph,
const ID *id,
- DEGForeachIDCallback callback, void *user_data)
+ DEGForeachIDCallback callback,
+ void *user_data)
{
- DEG::deg_foreach_ancestor_ID((const DEG::Depsgraph *)depsgraph,
- id,
- callback, user_data);
+ DEG::deg_foreach_ancestor_ID((const DEG::Depsgraph *)depsgraph, id, callback, user_data);
}
-void DEG_foreach_ID(const Depsgraph *depsgraph,
- DEGForeachIDCallback callback, void *user_data)
+void DEG_foreach_ID(const Depsgraph *depsgraph, DEGForeachIDCallback callback, void *user_data)
{
- DEG::deg_foreach_id((const DEG::Depsgraph *)depsgraph, callback, user_data);
+ DEG::deg_foreach_id((const DEG::Depsgraph *)depsgraph, callback, user_data);
}
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
index 2dfffe92368..d3bf27747c0 100644
--- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -67,315 +67,309 @@ namespace {
void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
{
#ifdef INVALIDATE_WORK_DATA
- BLI_assert(data != NULL);
- memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
+ BLI_assert(data != NULL);
+ memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
#else
- (void) data;
+ (void)data;
#endif
}
void verify_id_properties_freed(DEGObjectIterData *data)
{
- if (data->dupli_object_current == NULL) {
- // We didn't enter duplication yet, so we can't have any dangling
- // pointers.
- return;
- }
- const Object *dupli_object = data->dupli_object_current->ob;
- Object *temp_dupli_object = &data->temp_dupli_object;
- if (temp_dupli_object->id.properties == NULL) {
- // No ID properties in temp datablock -- no leak is possible.
- return;
- }
- if (temp_dupli_object->id.properties == dupli_object->id.properties) {
- // Temp copy of object did not modify ID properties.
- return;
- }
- // Free memory which is owned by temporary storage which is about to
- // get overwritten.
- IDP_FreeProperty(temp_dupli_object->id.properties);
- MEM_freeN(temp_dupli_object->id.properties);
- temp_dupli_object->id.properties = NULL;
+ if (data->dupli_object_current == NULL) {
+ // We didn't enter duplication yet, so we can't have any dangling
+ // pointers.
+ return;
+ }
+ const Object *dupli_object = data->dupli_object_current->ob;
+ Object *temp_dupli_object = &data->temp_dupli_object;
+ if (temp_dupli_object->id.properties == NULL) {
+ // No ID properties in temp datablock -- no leak is possible.
+ return;
+ }
+ if (temp_dupli_object->id.properties == dupli_object->id.properties) {
+ // Temp copy of object did not modify ID properties.
+ return;
+ }
+ // Free memory which is owned by temporary storage which is about to
+ // get overwritten.
+ IDP_FreeProperty(temp_dupli_object->id.properties);
+ MEM_freeN(temp_dupli_object->id.properties);
+ temp_dupli_object->id.properties = NULL;
}
static bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject *dob)
{
- /* Automatic hiding if this object is being instanced on verts/faces/frames
- * by its parent. Ideally this should not be needed, but due to the wrong
- * dependency direction in the data design there is no way to keep the object
- * visible otherwise. The better solution eventually would be for objects
- * to specify which object they instance, instead of through parenting. */
- if (eval_mode == DAG_EVAL_RENDER || dob) {
- const int hide_original_types = OB_DUPLIVERTS | OB_DUPLIFACES;
-
- if (!dob || !(dob->type & hide_original_types)) {
- if (ob->parent && (ob->parent->transflag & hide_original_types)) {
- return true;
- }
- }
- }
-
- return false;
+ /* Automatic hiding if this object is being instanced on verts/faces/frames
+ * by its parent. Ideally this should not be needed, but due to the wrong
+ * dependency direction in the data design there is no way to keep the object
+ * visible otherwise. The better solution eventually would be for objects
+ * to specify which object they instance, instead of through parenting. */
+ if (eval_mode == DAG_EVAL_RENDER || dob) {
+ const int hide_original_types = OB_DUPLIVERTS | OB_DUPLIFACES;
+
+ if (!dob || !(dob->type & hide_original_types)) {
+ if (ob->parent && (ob->parent->transflag & hide_original_types)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
{
- DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
- while (data->dupli_object_next != NULL) {
- DupliObject *dob = data->dupli_object_next;
- Object *obd = dob->ob;
-
- data->dupli_object_next = data->dupli_object_next->next;
-
- if (dob->no_draw) {
- continue;
- }
- if (obd->type == OB_MBALL) {
- continue;
- }
- if (deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
- continue;
- }
-
- verify_id_properties_freed(data);
-
- data->dupli_object_current = dob;
-
- /* Temporary object to evaluate. */
- Object *dupli_parent = data->dupli_parent;
- Object *temp_dupli_object = &data->temp_dupli_object;
- *temp_dupli_object = *dob->ob;
- temp_dupli_object->select_id = dupli_parent->select_id;
- temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
- temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits;
- temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt);
- copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
-
- /* Duplicated elements shouldn't care whether their original collection is visible or not. */
- temp_dupli_object->base_flag |= BASE_VISIBLE;
-
- int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
- if (ob_visibility == 0) {
- continue;
- }
-
- copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
- iter->current = &data->temp_dupli_object;
- BLI_assert(
- DEG::deg_validate_copy_on_write_datablock(
- &data->temp_dupli_object.id));
- return true;
- }
-
- return false;
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ while (data->dupli_object_next != NULL) {
+ DupliObject *dob = data->dupli_object_next;
+ Object *obd = dob->ob;
+
+ data->dupli_object_next = data->dupli_object_next->next;
+
+ if (dob->no_draw) {
+ continue;
+ }
+ if (obd->type == OB_MBALL) {
+ continue;
+ }
+ if (deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
+ continue;
+ }
+
+ verify_id_properties_freed(data);
+
+ data->dupli_object_current = dob;
+
+ /* Temporary object to evaluate. */
+ Object *dupli_parent = data->dupli_parent;
+ Object *temp_dupli_object = &data->temp_dupli_object;
+ *temp_dupli_object = *dob->ob;
+ temp_dupli_object->select_id = dupli_parent->select_id;
+ temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
+ temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits;
+ temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt);
+ copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
+
+ /* Duplicated elements shouldn't care whether their original collection is visible or not. */
+ temp_dupli_object->base_flag |= BASE_VISIBLE;
+
+ int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
+ if (ob_visibility == 0) {
+ continue;
+ }
+
+ copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
+ iter->current = &data->temp_dupli_object;
+ BLI_assert(DEG::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id));
+ return true;
+ }
+
+ return false;
}
void deg_iterator_objects_step(BLI_Iterator *iter, DEG::IDNode *id_node)
{
- /* Set it early in case we need to exit and we are running from within a loop. */
- iter->skip = true;
-
- if (!id_node->is_directly_visible) {
- return;
- }
-
- DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
- const ID_Type id_type = GS(id_node->id_orig->name);
-
- if (id_type != ID_OB) {
- return;
- }
-
- switch (id_node->linked_state) {
- case DEG::DEG_ID_LINKED_DIRECTLY:
- if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) {
- return;
- }
- break;
- case DEG::DEG_ID_LINKED_VIA_SET:
- if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) {
- return;
- }
- break;
- case DEG::DEG_ID_LINKED_INDIRECTLY:
- if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) {
- return;
- }
- break;
- }
-
- Object *object = (Object *)id_node->id_cow;
- BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
-
- int ob_visibility = OB_VISIBLE_ALL;
- if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) {
- ob_visibility = BKE_object_visibility(object, data->eval_mode);
-
- if (deg_object_hide_original(data->eval_mode, object, NULL)) {
- return;
- }
- }
-
- if (ob_visibility & OB_VISIBLE_INSTANCES) {
- if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
- (object->transflag & OB_DUPLI))
- {
- data->dupli_parent = object;
- data->dupli_list = object_duplilist(data->graph, data->scene, object);
- data->dupli_object_next = (DupliObject *)data->dupli_list->first;
- }
- }
-
- if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) {
- iter->current = object;
- iter->skip = false;
- }
+ /* Set it early in case we need to exit and we are running from within a loop. */
+ iter->skip = true;
+
+ if (!id_node->is_directly_visible) {
+ return;
+ }
+
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ const ID_Type id_type = GS(id_node->id_orig->name);
+
+ if (id_type != ID_OB) {
+ return;
+ }
+
+ switch (id_node->linked_state) {
+ case DEG::DEG_ID_LINKED_DIRECTLY:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) {
+ return;
+ }
+ break;
+ case DEG::DEG_ID_LINKED_VIA_SET:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) {
+ return;
+ }
+ break;
+ case DEG::DEG_ID_LINKED_INDIRECTLY:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) {
+ return;
+ }
+ break;
+ }
+
+ Object *object = (Object *)id_node->id_cow;
+ BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
+
+ int ob_visibility = OB_VISIBLE_ALL;
+ if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) {
+ ob_visibility = BKE_object_visibility(object, data->eval_mode);
+
+ if (deg_object_hide_original(data->eval_mode, object, NULL)) {
+ return;
+ }
+ }
+
+ if (ob_visibility & OB_VISIBLE_INSTANCES) {
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && (object->transflag & OB_DUPLI)) {
+ data->dupli_parent = object;
+ data->dupli_list = object_duplilist(data->graph, data->scene, object);
+ data->dupli_object_next = (DupliObject *)data->dupli_list->first;
+ }
+ }
+
+ if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) {
+ iter->current = object;
+ iter->skip = false;
+ }
}
} // namespace
void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
{
- Depsgraph *depsgraph = data->graph;
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- const size_t num_id_nodes = deg_graph->id_nodes.size();
-
- iter->data = data;
-
- if (num_id_nodes == 0) {
- iter->valid = false;
- return;
- }
-
- data->dupli_parent = NULL;
- data->dupli_list = NULL;
- data->dupli_object_next = NULL;
- data->dupli_object_current = NULL;
- data->scene = DEG_get_evaluated_scene(depsgraph);
- data->id_node_index = 0;
- data->num_id_nodes = num_id_nodes;
- data->eval_mode = DEG_get_mode(depsgraph);
- deg_invalidate_iterator_work_data(data);
-
- DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
- deg_iterator_objects_step(iter, id_node);
-
- if (iter->skip) {
- DEG_iterator_objects_next(iter);
- }
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ const size_t num_id_nodes = deg_graph->id_nodes.size();
+
+ iter->data = data;
+
+ if (num_id_nodes == 0) {
+ iter->valid = false;
+ return;
+ }
+
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ data->scene = DEG_get_evaluated_scene(depsgraph);
+ data->id_node_index = 0;
+ data->num_id_nodes = num_id_nodes;
+ data->eval_mode = DEG_get_mode(depsgraph);
+ deg_invalidate_iterator_work_data(data);
+
+ DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ deg_iterator_objects_step(iter, id_node);
+
+ if (iter->skip) {
+ DEG_iterator_objects_next(iter);
+ }
}
void DEG_iterator_objects_next(BLI_Iterator *iter)
{
- DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
- Depsgraph *depsgraph = data->graph;
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- do {
- iter->skip = false;
- if (data->dupli_list) {
- if (deg_objects_dupli_iterator_next(iter)) {
- return;
- }
- else {
- verify_id_properties_freed(data);
- free_object_duplilist(data->dupli_list);
- data->dupli_parent = NULL;
- data->dupli_list = NULL;
- data->dupli_object_next = NULL;
- data->dupli_object_current = NULL;
- deg_invalidate_iterator_work_data(data);
- }
- }
-
- ++data->id_node_index;
- if (data->id_node_index == data->num_id_nodes) {
- iter->valid = false;
- return;
- }
-
- DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
- deg_iterator_objects_step(iter, id_node);
- } while (iter->skip);
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ do {
+ iter->skip = false;
+ if (data->dupli_list) {
+ if (deg_objects_dupli_iterator_next(iter)) {
+ return;
+ }
+ else {
+ verify_id_properties_freed(data);
+ free_object_duplilist(data->dupli_list);
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ deg_invalidate_iterator_work_data(data);
+ }
+ }
+
+ ++data->id_node_index;
+ if (data->id_node_index == data->num_id_nodes) {
+ iter->valid = false;
+ return;
+ }
+
+ DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ deg_iterator_objects_step(iter, id_node);
+ } while (iter->skip);
}
void DEG_iterator_objects_end(BLI_Iterator *iter)
{
- DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
- if (data != NULL) {
- /* Force crash in case the iterator data is referenced and accessed down
- * the line. (T51718) */
- deg_invalidate_iterator_work_data(data);
- }
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ if (data != NULL) {
+ /* Force crash in case the iterator data is referenced and accessed down
+ * the line. (T51718) */
+ deg_invalidate_iterator_work_data(data);
+ }
}
/* ************************ DEG ID ITERATOR ********************* */
static void DEG_iterator_ids_step(BLI_Iterator *iter, DEG::IDNode *id_node, bool only_updated)
{
- ID *id_cow = id_node->id_cow;
-
- if (!id_node->is_directly_visible) {
- iter->skip = true;
- return;
- }
- else if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) {
- bNodeTree *ntree = ntreeFromID(id_cow);
-
- /* Nodetree is considered part of the datablock. */
- if (!(ntree && (ntree->id.recalc & ID_RECALC_ALL))) {
- iter->skip = true;
- return;
- }
- }
-
- iter->current = id_cow;
- iter->skip = false;
+ ID *id_cow = id_node->id_cow;
+
+ if (!id_node->is_directly_visible) {
+ iter->skip = true;
+ return;
+ }
+ else if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) {
+ bNodeTree *ntree = ntreeFromID(id_cow);
+
+ /* Nodetree is considered part of the datablock. */
+ if (!(ntree && (ntree->id.recalc & ID_RECALC_ALL))) {
+ iter->skip = true;
+ return;
+ }
+ }
+
+ iter->current = id_cow;
+ iter->skip = false;
}
void DEG_iterator_ids_begin(BLI_Iterator *iter, DEGIDIterData *data)
{
- Depsgraph *depsgraph = data->graph;
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- const size_t num_id_nodes = deg_graph->id_nodes.size();
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ const size_t num_id_nodes = deg_graph->id_nodes.size();
- iter->data = data;
+ iter->data = data;
- if ((num_id_nodes == 0) ||
- (data->only_updated && !DEG_id_type_any_updated(depsgraph)))
- {
- iter->valid = false;
- return;
- }
+ if ((num_id_nodes == 0) || (data->only_updated && !DEG_id_type_any_updated(depsgraph))) {
+ iter->valid = false;
+ return;
+ }
- data->id_node_index = 0;
- data->num_id_nodes = num_id_nodes;
+ data->id_node_index = 0;
+ data->num_id_nodes = num_id_nodes;
- DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
- DEG_iterator_ids_step(iter, id_node, data->only_updated);
+ DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_ids_step(iter, id_node, data->only_updated);
- if (iter->skip) {
- DEG_iterator_ids_next(iter);
- }
+ if (iter->skip) {
+ DEG_iterator_ids_next(iter);
+ }
}
void DEG_iterator_ids_next(BLI_Iterator *iter)
{
- DEGIDIterData *data = (DEGIDIterData *)iter->data;
- Depsgraph *depsgraph = data->graph;
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
-
- do {
- iter->skip = false;
-
- ++data->id_node_index;
- if (data->id_node_index == data->num_id_nodes) {
- iter->valid = false;
- return;
- }
-
- DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
- DEG_iterator_ids_step(iter, id_node, data->only_updated);
- } while (iter->skip);
+ DEGIDIterData *data = (DEGIDIterData *)iter->data;
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+
+ do {
+ iter->skip = false;
+
+ ++data->id_node_index;
+ if (data->id_node_index == data->num_id_nodes) {
+ iter->valid = false;
+ return;
+ }
+
+ DEG::IDNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_ids_step(iter, id_node, data->only_updated);
+ } while (iter->skip);
}
void DEG_iterator_ids_end(BLI_Iterator *UNUSED(iter))
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index daa599b6972..f682dadee8e 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -26,7 +26,7 @@
#include "intern/depsgraph_tag.h"
#include <stdio.h>
-#include <cstring> /* required for memset */
+#include <cstring> /* required for memset */
#include <queue>
#include "BLI_utildefines.h"
@@ -79,78 +79,75 @@ namespace DEG {
namespace {
-void depsgraph_geometry_tag_to_component(const ID *id,
- NodeType *component_type)
+void depsgraph_geometry_tag_to_component(const ID *id, NodeType *component_type)
{
- const NodeType result = geometry_tag_to_component(id);
- if (result != NodeType::UNDEFINED) {
- *component_type = result;
- }
+ const NodeType result = geometry_tag_to_component(id);
+ if (result != NodeType::UNDEFINED) {
+ *component_type = result;
+ }
}
bool is_selectable_data_id_type(const ID_Type id_type)
{
- return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD);
+ return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD);
}
-void depsgraph_select_tag_to_component_opcode(
- const ID *id,
- NodeType *component_type,
- OperationCode *operation_code)
+void depsgraph_select_tag_to_component_opcode(const ID *id,
+ NodeType *component_type,
+ OperationCode *operation_code)
{
- const ID_Type id_type = GS(id->name);
- if (id_type == ID_SCE) {
- /* We need to flush base flags to all objects in a scene since we
- * don't know which ones changed. However, we don't want to update
- * the whole scene, so pick up some operation which will do as less
- * as possible.
- *
- * TODO(sergey): We can introduce explicit exit operation which
- * does nothing and which is only used to cascade flush down the
- * road. */
- *component_type = NodeType::LAYER_COLLECTIONS;
- *operation_code = OperationCode::VIEW_LAYER_EVAL;
- }
- else if (id_type == ID_OB) {
- *component_type = NodeType::OBJECT_FROM_LAYER;
- *operation_code = OperationCode::OBJECT_BASE_FLAGS;
- }
- else if (id_type == ID_MC) {
- *component_type = NodeType::BATCH_CACHE;
- *operation_code = OperationCode::MOVIECLIP_SELECT_UPDATE;
- }
- else if (is_selectable_data_id_type(id_type)) {
- *component_type = NodeType::BATCH_CACHE;
- *operation_code = OperationCode::GEOMETRY_SELECT_UPDATE;
- }
- else {
- *component_type = NodeType::COPY_ON_WRITE;
- *operation_code = OperationCode::COPY_ON_WRITE;
- }
+ const ID_Type id_type = GS(id->name);
+ if (id_type == ID_SCE) {
+ /* We need to flush base flags to all objects in a scene since we
+ * don't know which ones changed. However, we don't want to update
+ * the whole scene, so pick up some operation which will do as less
+ * as possible.
+ *
+ * TODO(sergey): We can introduce explicit exit operation which
+ * does nothing and which is only used to cascade flush down the
+ * road. */
+ *component_type = NodeType::LAYER_COLLECTIONS;
+ *operation_code = OperationCode::VIEW_LAYER_EVAL;
+ }
+ else if (id_type == ID_OB) {
+ *component_type = NodeType::OBJECT_FROM_LAYER;
+ *operation_code = OperationCode::OBJECT_BASE_FLAGS;
+ }
+ else if (id_type == ID_MC) {
+ *component_type = NodeType::BATCH_CACHE;
+ *operation_code = OperationCode::MOVIECLIP_SELECT_UPDATE;
+ }
+ else if (is_selectable_data_id_type(id_type)) {
+ *component_type = NodeType::BATCH_CACHE;
+ *operation_code = OperationCode::GEOMETRY_SELECT_UPDATE;
+ }
+ else {
+ *component_type = NodeType::COPY_ON_WRITE;
+ *operation_code = OperationCode::COPY_ON_WRITE;
+ }
}
-void depsgraph_base_flags_tag_to_component_opcode(
- const ID *id,
- NodeType *component_type,
- OperationCode *operation_code)
+void depsgraph_base_flags_tag_to_component_opcode(const ID *id,
+ NodeType *component_type,
+ OperationCode *operation_code)
{
- const ID_Type id_type = GS(id->name);
- if (id_type == ID_SCE) {
- *component_type = NodeType::LAYER_COLLECTIONS;
- *operation_code = OperationCode::VIEW_LAYER_EVAL;
- }
- else if (id_type == ID_OB) {
- *component_type = NodeType::OBJECT_FROM_LAYER;
- *operation_code = OperationCode::OBJECT_BASE_FLAGS;
- }
+ const ID_Type id_type = GS(id->name);
+ if (id_type == ID_SCE) {
+ *component_type = NodeType::LAYER_COLLECTIONS;
+ *operation_code = OperationCode::VIEW_LAYER_EVAL;
+ }
+ else if (id_type == ID_OB) {
+ *component_type = NodeType::OBJECT_FROM_LAYER;
+ *operation_code = OperationCode::OBJECT_BASE_FLAGS;
+ }
}
OperationCode psysTagToOperationCode(IDRecalcFlag tag)
{
- if (tag == ID_RECALC_PSYS_RESET) {
- return OperationCode::PARTICLE_SETTINGS_RESET;
- }
- return OperationCode::OPERATION;
+ if (tag == ID_RECALC_PSYS_RESET) {
+ return OperationCode::PARTICLE_SETTINGS_RESET;
+ }
+ return OperationCode::OPERATION;
}
void depsgraph_tag_to_component_opcode(const ID *id,
@@ -158,101 +155,94 @@ void depsgraph_tag_to_component_opcode(const ID *id,
NodeType *component_type,
OperationCode *operation_code)
{
- const ID_Type id_type = GS(id->name);
- *component_type = NodeType::UNDEFINED;
- *operation_code = OperationCode::OPERATION;
- /* Special case for now, in the future we should get rid of this. */
- if (tag == 0) {
- *component_type = NodeType::ID_REF;
- *operation_code = OperationCode::OPERATION;
- return;
- }
- switch (tag) {
- case ID_RECALC_TRANSFORM:
- *component_type = NodeType::TRANSFORM;
- break;
- case ID_RECALC_GEOMETRY:
- depsgraph_geometry_tag_to_component(id, component_type);
- break;
- case ID_RECALC_ANIMATION:
- *component_type = NodeType::ANIMATION;
- break;
- case ID_RECALC_PSYS_REDO:
- case ID_RECALC_PSYS_RESET:
- case ID_RECALC_PSYS_CHILD:
- case ID_RECALC_PSYS_PHYS:
- if (id_type == ID_PA) {
- /* NOTES:
- * - For particle settings node we need to use different
- * component. Will be nice to get this unified with object,
- * but we can survive for now with single exception here.
- * Particles needs reconsideration anyway, */
- *component_type = NodeType::PARTICLE_SETTINGS;
- *operation_code = psysTagToOperationCode(tag);
- }
- else {
- *component_type = NodeType::PARTICLE_SYSTEM;
- }
- break;
- case ID_RECALC_COPY_ON_WRITE:
- *component_type = NodeType::COPY_ON_WRITE;
- break;
- case ID_RECALC_SHADING:
- if (id_type == ID_NT) {
- *component_type = NodeType::SHADING_PARAMETERS;
- }
- else {
- *component_type = NodeType::SHADING;
- }
- break;
- case ID_RECALC_SELECT:
- depsgraph_select_tag_to_component_opcode(id,
- component_type,
- operation_code);
- break;
- case ID_RECALC_BASE_FLAGS:
- depsgraph_base_flags_tag_to_component_opcode(id,
- component_type,
- operation_code);
- break;
- case ID_RECALC_POINT_CACHE:
- *component_type = NodeType::POINT_CACHE;
- break;
- case ID_RECALC_EDITORS:
- /* There is no such node in depsgraph, this tag is to be handled
- * separately. */
- break;
- case ID_RECALC_ALL:
- case ID_RECALC_PSYS_ALL:
- BLI_assert(!"Should not happen");
- break;
- }
+ const ID_Type id_type = GS(id->name);
+ *component_type = NodeType::UNDEFINED;
+ *operation_code = OperationCode::OPERATION;
+ /* Special case for now, in the future we should get rid of this. */
+ if (tag == 0) {
+ *component_type = NodeType::ID_REF;
+ *operation_code = OperationCode::OPERATION;
+ return;
+ }
+ switch (tag) {
+ case ID_RECALC_TRANSFORM:
+ *component_type = NodeType::TRANSFORM;
+ break;
+ case ID_RECALC_GEOMETRY:
+ depsgraph_geometry_tag_to_component(id, component_type);
+ break;
+ case ID_RECALC_ANIMATION:
+ *component_type = NodeType::ANIMATION;
+ break;
+ case ID_RECALC_PSYS_REDO:
+ case ID_RECALC_PSYS_RESET:
+ case ID_RECALC_PSYS_CHILD:
+ case ID_RECALC_PSYS_PHYS:
+ if (id_type == ID_PA) {
+ /* NOTES:
+ * - For particle settings node we need to use different
+ * component. Will be nice to get this unified with object,
+ * but we can survive for now with single exception here.
+ * Particles needs reconsideration anyway, */
+ *component_type = NodeType::PARTICLE_SETTINGS;
+ *operation_code = psysTagToOperationCode(tag);
+ }
+ else {
+ *component_type = NodeType::PARTICLE_SYSTEM;
+ }
+ break;
+ case ID_RECALC_COPY_ON_WRITE:
+ *component_type = NodeType::COPY_ON_WRITE;
+ break;
+ case ID_RECALC_SHADING:
+ if (id_type == ID_NT) {
+ *component_type = NodeType::SHADING_PARAMETERS;
+ }
+ else {
+ *component_type = NodeType::SHADING;
+ }
+ break;
+ case ID_RECALC_SELECT:
+ depsgraph_select_tag_to_component_opcode(id, component_type, operation_code);
+ break;
+ case ID_RECALC_BASE_FLAGS:
+ depsgraph_base_flags_tag_to_component_opcode(id, component_type, operation_code);
+ break;
+ case ID_RECALC_POINT_CACHE:
+ *component_type = NodeType::POINT_CACHE;
+ break;
+ case ID_RECALC_EDITORS:
+ /* There is no such node in depsgraph, this tag is to be handled
+ * separately. */
+ break;
+ case ID_RECALC_ALL:
+ case ID_RECALC_PSYS_ALL:
+ BLI_assert(!"Should not happen");
+ break;
+ }
}
-void id_tag_update_ntree_special(Main *bmain,
- Depsgraph *graph,
- ID *id,
- int flag,
- eUpdateSource update_source)
+void id_tag_update_ntree_special(
+ Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source)
{
- bNodeTree *ntree = ntreeFromID(id);
- if (ntree == NULL) {
- return;
- }
- graph_id_tag_update(bmain, graph, &ntree->id, flag, update_source);
+ bNodeTree *ntree = ntreeFromID(id);
+ if (ntree == NULL) {
+ return;
+ }
+ graph_id_tag_update(bmain, graph, &ntree->id, flag, update_source);
}
void depsgraph_update_editors_tag(Main *bmain, Depsgraph *graph, ID *id)
{
- /* NOTE: We handle this immediately, without delaying anything, to be
- * sure we don't cause threading issues with OpenGL. */
- /* TODO(sergey): Make sure this works for CoW-ed datablocks as well. */
- DEGEditorUpdateContext update_ctx = {NULL};
- update_ctx.bmain = bmain;
- update_ctx.depsgraph = (::Depsgraph *)graph;
- update_ctx.scene = graph->scene;
- update_ctx.view_layer = graph->view_layer;
- deg_editors_id_update(&update_ctx, id);
+ /* NOTE: We handle this immediately, without delaying anything, to be
+ * sure we don't cause threading issues with OpenGL. */
+ /* TODO(sergey): Make sure this works for CoW-ed datablocks as well. */
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ update_ctx.depsgraph = (::Depsgraph *)graph;
+ update_ctx.scene = graph->scene;
+ update_ctx.view_layer = graph->view_layer;
+ deg_editors_id_update(&update_ctx, id);
}
void depsgraph_tag_component(Depsgraph *graph,
@@ -261,28 +251,25 @@ void depsgraph_tag_component(Depsgraph *graph,
OperationCode operation_code,
eUpdateSource update_source)
{
- ComponentNode *component_node =
- id_node->find_component(component_type);
- if (component_node == NULL) {
- return;
- }
- if (operation_code == OperationCode::OPERATION) {
- component_node->tag_update(graph, update_source);
- }
- else {
- OperationNode *operation_node =
- component_node->find_operation(operation_code);
- if (operation_node != NULL) {
- operation_node->tag_update(graph, update_source);
- }
- }
- /* If component depends on copy-on-write, tag it as well. */
- if (component_node->need_tag_cow_before_update()) {
- ComponentNode *cow_comp =
- id_node->find_component(NodeType::COPY_ON_WRITE);
- cow_comp->tag_update(graph, update_source);
- id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE;
- }
+ ComponentNode *component_node = id_node->find_component(component_type);
+ if (component_node == NULL) {
+ return;
+ }
+ if (operation_code == OperationCode::OPERATION) {
+ component_node->tag_update(graph, update_source);
+ }
+ else {
+ OperationNode *operation_node = component_node->find_operation(operation_code);
+ if (operation_node != NULL) {
+ operation_node->tag_update(graph, update_source);
+ }
+ }
+ /* If component depends on copy-on-write, tag it as well. */
+ if (component_node->need_tag_cow_before_update()) {
+ ComponentNode *cow_comp = id_node->find_component(NodeType::COPY_ON_WRITE);
+ cow_comp->tag_update(graph, update_source);
+ id_node->id_orig->recalc |= ID_RECALC_COPY_ON_WRITE;
+ }
}
/* This is a tag compatibility with legacy code.
@@ -290,61 +277,50 @@ void depsgraph_tag_component(Depsgraph *graph,
* Mainly, old code was tagging object with ID_RECALC_GEOMETRY tag to inform
* that object's data datablock changed. Now API expects that ID is given
* explicitly, but not all areas are aware of this yet. */
-void deg_graph_id_tag_legacy_compat(Main *bmain,
- Depsgraph *depsgraph,
- ID *id,
- IDRecalcFlag tag,
- eUpdateSource update_source)
+void deg_graph_id_tag_legacy_compat(
+ Main *bmain, Depsgraph *depsgraph, ID *id, IDRecalcFlag tag, eUpdateSource update_source)
{
- if (tag == ID_RECALC_GEOMETRY || tag == 0) {
- switch (GS(id->name)) {
- case ID_OB:
- {
- Object *object = (Object *)id;
- ID *data_id = (ID *)object->data;
- if (data_id != NULL) {
- graph_id_tag_update(
- bmain, depsgraph, data_id, 0, update_source);
- }
- break;
- }
- /* TODO(sergey): Shape keys are annoying, maybe we should find a
- * way to chain geometry evaluation to them, so we don't need extra
- * tagging here. */
- case ID_ME:
- {
- Mesh *mesh = (Mesh *)id;
- ID *key_id = &mesh->key->id;
- if (key_id != NULL) {
- graph_id_tag_update(
- bmain, depsgraph, key_id, 0, update_source);
- }
- break;
- }
- case ID_LT:
- {
- Lattice *lattice = (Lattice *)id;
- ID *key_id = &lattice->key->id;
- if (key_id != NULL) {
- graph_id_tag_update(
- bmain, depsgraph, key_id, 0, update_source);
- }
- break;
- }
- case ID_CU:
- {
- Curve *curve = (Curve *)id;
- ID *key_id = &curve->key->id;
- if (key_id != NULL) {
- graph_id_tag_update(
- bmain, depsgraph, key_id, 0, update_source);
- }
- break;
- }
- default:
- break;
- }
- }
+ if (tag == ID_RECALC_GEOMETRY || tag == 0) {
+ switch (GS(id->name)) {
+ case ID_OB: {
+ Object *object = (Object *)id;
+ ID *data_id = (ID *)object->data;
+ if (data_id != NULL) {
+ graph_id_tag_update(bmain, depsgraph, data_id, 0, update_source);
+ }
+ break;
+ }
+ /* TODO(sergey): Shape keys are annoying, maybe we should find a
+ * way to chain geometry evaluation to them, so we don't need extra
+ * tagging here. */
+ case ID_ME: {
+ Mesh *mesh = (Mesh *)id;
+ ID *key_id = &mesh->key->id;
+ if (key_id != NULL) {
+ graph_id_tag_update(bmain, depsgraph, key_id, 0, update_source);
+ }
+ break;
+ }
+ case ID_LT: {
+ Lattice *lattice = (Lattice *)id;
+ ID *key_id = &lattice->key->id;
+ if (key_id != NULL) {
+ graph_id_tag_update(bmain, depsgraph, key_id, 0, update_source);
+ }
+ break;
+ }
+ case ID_CU: {
+ Curve *curve = (Curve *)id;
+ ID *key_id = &curve->key->id;
+ if (key_id != NULL) {
+ graph_id_tag_update(bmain, depsgraph, key_id, 0, update_source);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
static void graph_id_tag_update_single_flag(Main *bmain,
@@ -354,90 +330,88 @@ static void graph_id_tag_update_single_flag(Main *bmain,
IDRecalcFlag tag,
eUpdateSource update_source)
{
- if (tag == ID_RECALC_EDITORS) {
- if (graph != NULL) {
- depsgraph_update_editors_tag(bmain, graph, id);
- }
- return;
- }
- /* Get description of what is to be tagged. */
- NodeType component_type;
- OperationCode operation_code;
- depsgraph_tag_to_component_opcode(id,
- tag,
- &component_type,
- &operation_code);
- /* Check whether we've got something to tag. */
- if (component_type == NodeType::UNDEFINED) {
- /* Given ID does not support tag. */
- /* TODO(sergey): Shall we raise some panic here? */
- return;
- }
- /* Tag ID recalc flag. */
- DepsNodeFactory *factory = type_get_factory(component_type);
- BLI_assert(factory != NULL);
- id->recalc |= factory->id_recalc_tag();
- /* Some sanity checks before moving forward. */
- if (id_node == NULL) {
- /* Happens when object is tagged for update and not yet in the
- * dependency graph (but will be after relations update). */
- return;
- }
- /* Tag corresponding dependency graph operation for update. */
- if (component_type == NodeType::ID_REF) {
- id_node->tag_update(graph, update_source);
- }
- else {
- depsgraph_tag_component(
- graph, id_node, component_type, operation_code, update_source);
- }
- /* TODO(sergey): Get rid of this once all areas are using proper data ID
- * for tagging. */
- deg_graph_id_tag_legacy_compat(bmain, graph, id, tag, update_source);
-
+ if (tag == ID_RECALC_EDITORS) {
+ if (graph != NULL) {
+ depsgraph_update_editors_tag(bmain, graph, id);
+ }
+ return;
+ }
+ /* Get description of what is to be tagged. */
+ NodeType component_type;
+ OperationCode operation_code;
+ depsgraph_tag_to_component_opcode(id, tag, &component_type, &operation_code);
+ /* Check whether we've got something to tag. */
+ if (component_type == NodeType::UNDEFINED) {
+ /* Given ID does not support tag. */
+ /* TODO(sergey): Shall we raise some panic here? */
+ return;
+ }
+ /* Tag ID recalc flag. */
+ DepsNodeFactory *factory = type_get_factory(component_type);
+ BLI_assert(factory != NULL);
+ id->recalc |= factory->id_recalc_tag();
+ /* Some sanity checks before moving forward. */
+ if (id_node == NULL) {
+ /* Happens when object is tagged for update and not yet in the
+ * dependency graph (but will be after relations update). */
+ return;
+ }
+ /* Tag corresponding dependency graph operation for update. */
+ if (component_type == NodeType::ID_REF) {
+ id_node->tag_update(graph, update_source);
+ }
+ else {
+ depsgraph_tag_component(graph, id_node, component_type, operation_code, update_source);
+ }
+ /* TODO(sergey): Get rid of this once all areas are using proper data ID
+ * for tagging. */
+ deg_graph_id_tag_legacy_compat(bmain, graph, id, tag, update_source);
}
-string stringify_append_bit(const string& str, IDRecalcFlag tag)
+string stringify_append_bit(const string &str, IDRecalcFlag tag)
{
- string result = str;
- if (!result.empty()) {
- result += ", ";
- }
- result += DEG_update_tag_as_string(tag);
- return result;
+ string result = str;
+ if (!result.empty()) {
+ result += ", ";
+ }
+ result += DEG_update_tag_as_string(tag);
+ return result;
}
string stringify_update_bitfield(int flag)
{
- if (flag == 0) {
- return "LEGACY_0";
- }
- string result = "";
- int current_flag = flag;
- /* Special cases to avoid ALL flags form being split into
- * individual bits. */
- if ((current_flag & ID_RECALC_PSYS_ALL) == ID_RECALC_PSYS_ALL) {
- result = stringify_append_bit(result, ID_RECALC_PSYS_ALL);
- }
- /* Handle all the rest of the flags. */
- while (current_flag != 0) {
- IDRecalcFlag tag =
- (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
- result = stringify_append_bit(result, tag);
- }
- return result;
+ if (flag == 0) {
+ return "LEGACY_0";
+ }
+ string result = "";
+ int current_flag = flag;
+ /* Special cases to avoid ALL flags form being split into
+ * individual bits. */
+ if ((current_flag & ID_RECALC_PSYS_ALL) == ID_RECALC_PSYS_ALL) {
+ result = stringify_append_bit(result, ID_RECALC_PSYS_ALL);
+ }
+ /* Handle all the rest of the flags. */
+ while (current_flag != 0) {
+ IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
+ result = stringify_append_bit(result, tag);
+ }
+ return result;
}
const char *update_source_as_string(eUpdateSource source)
{
- switch (source) {
- case DEG_UPDATE_SOURCE_TIME: return "TIME";
- case DEG_UPDATE_SOURCE_USER_EDIT: return "USER_EDIT";
- case DEG_UPDATE_SOURCE_RELATIONS: return "RELATIONS";
- case DEG_UPDATE_SOURCE_VISIBILITY: return "VISIBILITY";
- }
- BLI_assert(!"Should never happen.");
- return "UNKNOWN";
+ switch (source) {
+ case DEG_UPDATE_SOURCE_TIME:
+ return "TIME";
+ case DEG_UPDATE_SOURCE_USER_EDIT:
+ return "USER_EDIT";
+ case DEG_UPDATE_SOURCE_RELATIONS:
+ return "RELATIONS";
+ case DEG_UPDATE_SOURCE_VISIBILITY:
+ return "VISIBILITY";
+ }
+ BLI_assert(!"Should never happen.");
+ return "UNKNOWN";
}
/* Special tag function which tags all components which needs to be tagged
@@ -450,212 +424,202 @@ void deg_graph_node_tag_zero(Main *bmain,
IDNode *id_node,
eUpdateSource update_source)
{
- if (id_node == NULL) {
- return;
- }
- ID *id = id_node->id_orig;
- /* TODO(sergey): Which recalc flags to set here? */
- id->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION);
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- if (comp_node->type == NodeType::ANIMATION) {
- continue;
- }
- comp_node->tag_update(graph, update_source);
- }
- GHASH_FOREACH_END();
- deg_graph_id_tag_legacy_compat(
- bmain, graph, id, (IDRecalcFlag)0, update_source);
+ if (id_node == NULL) {
+ return;
+ }
+ ID *id = id_node->id_orig;
+ /* TODO(sergey): Which recalc flags to set here? */
+ id->recalc |= ID_RECALC_ALL & ~(ID_RECALC_PSYS_ALL | ID_RECALC_ANIMATION);
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ if (comp_node->type == NodeType::ANIMATION) {
+ continue;
+ }
+ comp_node->tag_update(graph, update_source);
+ }
+ GHASH_FOREACH_END();
+ deg_graph_id_tag_legacy_compat(bmain, graph, id, (IDRecalcFlag)0, update_source);
}
void deg_graph_on_visible_update(Main *bmain, Depsgraph *graph)
{
- for (DEG::IDNode *id_node : graph->id_nodes) {
- if (!id_node->visible_components_mask) {
- /* ID has no components which affects anything visible.
- * No need bother with it to tag or anything. */
- continue;
- }
- if (id_node->visible_components_mask ==
- id_node->previously_visible_components_mask)
- {
- /* The ID was already visible and evaluated, all the subsequent
- * updates and tags are to be done explicitly. */
- continue;
- }
- int flag = 0;
- if (!DEG::deg_copy_on_write_is_expanded(id_node->id_cow)) {
- flag |= ID_RECALC_COPY_ON_WRITE;
- /* TODO(sergey): Shouldn't be needed, but currently we are lackign
- * some flushing of evaluated data to the original one, which makes,
- * for example, files saved with the rest pose.
- * Need to solve those issues carefully, for until then we evaluate
- * animation for datablocks which appears in the graph for the first
- * time. */
- flag |= ID_RECALC_ANIMATION;
- }
- /* We only tag components which needs an update. Tagging everything is
- * not a good idea because that might reset particles cache (or any
- * other type of cache).
- *
- * TODO(sergey): Need to generalize this somehow. */
- const ID_Type id_type = GS(id_node->id_orig->name);
- if (id_type == ID_OB) {
- flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
- }
- graph_id_tag_update(bmain,
- graph,
- id_node->id_orig,
- flag,
- DEG_UPDATE_SOURCE_VISIBILITY);
- if (id_type == ID_SCE) {
- /* Make sure collection properties are up to date. */
- id_node->tag_update(graph, DEG_UPDATE_SOURCE_VISIBILITY);
- }
- /* Now when ID is updated to the new visibility state, prevent it from
- * being re-tagged again. Simplest way to do so is to pretend that it
- * was already updated by the "previous" dependency graph.
- *
- * NOTE: Even if the on_visible_update() is called from the state when
- * dependency graph is tagged for relations update, it will be fine:
- * since dependency graph builder re-schedules entry tags, all the
- * tags we request from here will be applied in the updated state of
- * dependency graph. */
- id_node->previously_visible_components_mask =
- id_node->visible_components_mask;
- }
+ for (DEG::IDNode *id_node : graph->id_nodes) {
+ if (!id_node->visible_components_mask) {
+ /* ID has no components which affects anything visible.
+ * No need bother with it to tag or anything. */
+ continue;
+ }
+ if (id_node->visible_components_mask == id_node->previously_visible_components_mask) {
+ /* The ID was already visible and evaluated, all the subsequent
+ * updates and tags are to be done explicitly. */
+ continue;
+ }
+ int flag = 0;
+ if (!DEG::deg_copy_on_write_is_expanded(id_node->id_cow)) {
+ flag |= ID_RECALC_COPY_ON_WRITE;
+ /* TODO(sergey): Shouldn't be needed, but currently we are lackign
+ * some flushing of evaluated data to the original one, which makes,
+ * for example, files saved with the rest pose.
+ * Need to solve those issues carefully, for until then we evaluate
+ * animation for datablocks which appears in the graph for the first
+ * time. */
+ flag |= ID_RECALC_ANIMATION;
+ }
+ /* We only tag components which needs an update. Tagging everything is
+ * not a good idea because that might reset particles cache (or any
+ * other type of cache).
+ *
+ * TODO(sergey): Need to generalize this somehow. */
+ const ID_Type id_type = GS(id_node->id_orig->name);
+ if (id_type == ID_OB) {
+ flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
+ }
+ graph_id_tag_update(bmain, graph, id_node->id_orig, flag, DEG_UPDATE_SOURCE_VISIBILITY);
+ if (id_type == ID_SCE) {
+ /* Make sure collection properties are up to date. */
+ id_node->tag_update(graph, DEG_UPDATE_SOURCE_VISIBILITY);
+ }
+ /* Now when ID is updated to the new visibility state, prevent it from
+ * being re-tagged again. Simplest way to do so is to pretend that it
+ * was already updated by the "previous" dependency graph.
+ *
+ * NOTE: Even if the on_visible_update() is called from the state when
+ * dependency graph is tagged for relations update, it will be fine:
+ * since dependency graph builder re-schedules entry tags, all the
+ * tags we request from here will be applied in the updated state of
+ * dependency graph. */
+ id_node->previously_visible_components_mask = id_node->visible_components_mask;
+ }
}
-} /* namespace */
+} /* namespace */
NodeType geometry_tag_to_component(const ID *id)
{
- const ID_Type id_type = GS(id->name);
- switch (id_type) {
- case ID_OB:
- {
- const Object *object = (Object *)id;
- switch (object->type) {
- case OB_MESH:
- case OB_CURVE:
- case OB_SURF:
- case OB_FONT:
- case OB_LATTICE:
- case OB_MBALL:
- case OB_GPENCIL:
- return NodeType::GEOMETRY;
- case OB_ARMATURE:
- return NodeType::EVAL_POSE;
- /* TODO(sergey): More cases here? */
- }
- break;
- }
- case ID_ME:
- case ID_CU:
- case ID_LT:
- case ID_MB:
- return NodeType::GEOMETRY;
- case ID_PA: /* Particles */
- return NodeType::UNDEFINED;
- case ID_LP:
- return NodeType::PARAMETERS;
- case ID_GD:
- return NodeType::GEOMETRY;
- case ID_PAL: /* Palettes */
- return NodeType::PARAMETERS;
- default:
- break;
- }
- return NodeType::UNDEFINED;
+ const ID_Type id_type = GS(id->name);
+ switch (id_type) {
+ case ID_OB: {
+ const Object *object = (Object *)id;
+ switch (object->type) {
+ case OB_MESH:
+ case OB_CURVE:
+ case OB_SURF:
+ case OB_FONT:
+ case OB_LATTICE:
+ case OB_MBALL:
+ case OB_GPENCIL:
+ return NodeType::GEOMETRY;
+ case OB_ARMATURE:
+ return NodeType::EVAL_POSE;
+ /* TODO(sergey): More cases here? */
+ }
+ break;
+ }
+ case ID_ME:
+ case ID_CU:
+ case ID_LT:
+ case ID_MB:
+ return NodeType::GEOMETRY;
+ case ID_PA: /* Particles */
+ return NodeType::UNDEFINED;
+ case ID_LP:
+ return NodeType::PARAMETERS;
+ case ID_GD:
+ return NodeType::GEOMETRY;
+ case ID_PAL: /* Palettes */
+ return NodeType::PARAMETERS;
+ default:
+ break;
+ }
+ return NodeType::UNDEFINED;
}
void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source)
{
- graph_id_tag_update(bmain, NULL, id, flag, update_source);
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- Depsgraph *depsgraph =
- (Depsgraph *)BKE_scene_get_depsgraph(scene,
- view_layer,
- false);
- if (depsgraph != NULL) {
- graph_id_tag_update(
- bmain, depsgraph, id, flag, update_source);
- }
- }
- }
+ graph_id_tag_update(bmain, NULL, id, flag, update_source);
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph = (Depsgraph *)BKE_scene_get_depsgraph(scene, view_layer, false);
+ if (depsgraph != NULL) {
+ graph_id_tag_update(bmain, depsgraph, id, flag, update_source);
+ }
+ }
+ }
}
-void graph_id_tag_update(Main *bmain,
- Depsgraph *graph,
- ID *id,
- int flag,
- eUpdateSource update_source)
+void graph_id_tag_update(
+ Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source)
{
- const int debug_flags = (graph != NULL)
- ? DEG_debug_flags_get((::Depsgraph *)graph)
- : G.debug;
- if (debug_flags & G_DEBUG_DEPSGRAPH_TAG) {
- printf("%s: id=%s flags=%s source=%s\n",
- __func__,
- id->name,
- stringify_update_bitfield(flag).c_str(),
- update_source_as_string(update_source));
- }
- IDNode *id_node = (graph != NULL) ? graph->find_id_node(id)
- : NULL;
- if (graph != NULL) {
- DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph*>(graph),
- GS(id->name));
- }
- if (flag == 0) {
- deg_graph_node_tag_zero(bmain, graph, id_node, update_source);
- }
- id->recalc |= flag;
- int current_flag = flag;
- while (current_flag != 0) {
- IDRecalcFlag tag =
- (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
- graph_id_tag_update_single_flag(
- bmain, graph, id, id_node, tag, update_source);
- }
- /* Special case for nested node tree datablocks. */
- id_tag_update_ntree_special(bmain, graph, id, flag, update_source);
- /* Direct update tags means that something outside of simulated/cached
- * physics did change and that cache is to be invalidated.
- * This is only needed if data changes. If it's just a drawing, we keep the
- * point cache. */
- if (update_source == DEG_UPDATE_SOURCE_USER_EDIT &&
- flag != ID_RECALC_SHADING)
- {
- graph_id_tag_update_single_flag(
- bmain, graph, id, id_node, ID_RECALC_POINT_CACHE, update_source);
- }
+ const int debug_flags = (graph != NULL) ? DEG_debug_flags_get((::Depsgraph *)graph) : G.debug;
+ if (debug_flags & G_DEBUG_DEPSGRAPH_TAG) {
+ printf("%s: id=%s flags=%s source=%s\n",
+ __func__,
+ id->name,
+ stringify_update_bitfield(flag).c_str(),
+ update_source_as_string(update_source));
+ }
+ IDNode *id_node = (graph != NULL) ? graph->find_id_node(id) : NULL;
+ if (graph != NULL) {
+ DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph *>(graph), GS(id->name));
+ }
+ if (flag == 0) {
+ deg_graph_node_tag_zero(bmain, graph, id_node, update_source);
+ }
+ id->recalc |= flag;
+ int current_flag = flag;
+ while (current_flag != 0) {
+ IDRecalcFlag tag = (IDRecalcFlag)(1 << bitscan_forward_clear_i(&current_flag));
+ graph_id_tag_update_single_flag(bmain, graph, id, id_node, tag, update_source);
+ }
+ /* Special case for nested node tree datablocks. */
+ id_tag_update_ntree_special(bmain, graph, id, flag, update_source);
+ /* Direct update tags means that something outside of simulated/cached
+ * physics did change and that cache is to be invalidated.
+ * This is only needed if data changes. If it's just a drawing, we keep the
+ * point cache. */
+ if (update_source == DEG_UPDATE_SOURCE_USER_EDIT && flag != ID_RECALC_SHADING) {
+ graph_id_tag_update_single_flag(
+ bmain, graph, id, id_node, ID_RECALC_POINT_CACHE, update_source);
+ }
}
} // namespace DEG
const char *DEG_update_tag_as_string(IDRecalcFlag flag)
{
- switch (flag) {
- case ID_RECALC_TRANSFORM: return "TRANSFORM";
- case ID_RECALC_GEOMETRY: return "GEOMETRY";
- case ID_RECALC_ANIMATION: return "ANIMATION";
- case ID_RECALC_PSYS_REDO: return "PSYS_REDO";
- case ID_RECALC_PSYS_RESET: return "PSYS_RESET";
- case ID_RECALC_PSYS_CHILD: return "PSYS_CHILD";
- case ID_RECALC_PSYS_PHYS: return "PSYS_PHYS";
- case ID_RECALC_PSYS_ALL: return "PSYS_ALL";
- case ID_RECALC_COPY_ON_WRITE: return "COPY_ON_WRITE";
- case ID_RECALC_SHADING: return "SHADING";
- case ID_RECALC_SELECT: return "SELECT";
- case ID_RECALC_BASE_FLAGS: return "BASE_FLAGS";
- case ID_RECALC_POINT_CACHE: return "POINT_CACHE";
- case ID_RECALC_EDITORS: return "EDITORS";
- case ID_RECALC_ALL: return "ALL";
- }
- BLI_assert(!"Unhandled update flag, should never happen!");
- return "UNKNOWN";
+ switch (flag) {
+ case ID_RECALC_TRANSFORM:
+ return "TRANSFORM";
+ case ID_RECALC_GEOMETRY:
+ return "GEOMETRY";
+ case ID_RECALC_ANIMATION:
+ return "ANIMATION";
+ case ID_RECALC_PSYS_REDO:
+ return "PSYS_REDO";
+ case ID_RECALC_PSYS_RESET:
+ return "PSYS_RESET";
+ case ID_RECALC_PSYS_CHILD:
+ return "PSYS_CHILD";
+ case ID_RECALC_PSYS_PHYS:
+ return "PSYS_PHYS";
+ case ID_RECALC_PSYS_ALL:
+ return "PSYS_ALL";
+ case ID_RECALC_COPY_ON_WRITE:
+ return "COPY_ON_WRITE";
+ case ID_RECALC_SHADING:
+ return "SHADING";
+ case ID_RECALC_SELECT:
+ return "SELECT";
+ case ID_RECALC_BASE_FLAGS:
+ return "BASE_FLAGS";
+ case ID_RECALC_POINT_CACHE:
+ return "POINT_CACHE";
+ case ID_RECALC_EDITORS:
+ return "EDITORS";
+ case ID_RECALC_ALL:
+ return "ALL";
+ }
+ BLI_assert(!"Unhandled update flag, should never happen!");
+ return "UNKNOWN";
}
/* Data-Based Tagging */
@@ -663,17 +627,16 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
/* Tag given ID for an update in all the dependency graphs. */
void DEG_id_tag_update(ID *id, int flag)
{
- DEG_id_tag_update_ex(G.main, id, flag);
+ DEG_id_tag_update_ex(G.main, id, flag);
}
void DEG_id_tag_update_ex(Main *bmain, ID *id, int flag)
{
- if (id == NULL) {
- /* Ideally should not happen, but old depsgraph allowed this. */
- return;
- }
- DEG::id_tag_update(
- bmain, id, flag, DEG::DEG_UPDATE_SOURCE_USER_EDIT);
+ if (id == NULL) {
+ /* Ideally should not happen, but old depsgraph allowed this. */
+ return;
+ }
+ DEG::id_tag_update(bmain, id, flag, DEG::DEG_UPDATE_SOURCE_USER_EDIT);
}
void DEG_graph_id_tag_update(struct Main *bmain,
@@ -681,132 +644,117 @@ void DEG_graph_id_tag_update(struct Main *bmain,
struct ID *id,
int flag)
{
- DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
- DEG::graph_id_tag_update(
- bmain, graph, id, flag, DEG::DEG_UPDATE_SOURCE_USER_EDIT);
+ DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
+ DEG::graph_id_tag_update(bmain, graph, id, flag, DEG::DEG_UPDATE_SOURCE_USER_EDIT);
}
/* Mark a particular datablock type as having changing. */
void DEG_graph_id_type_tag(Depsgraph *depsgraph, short id_type)
{
- if (id_type == ID_NT) {
- /* Stupid workaround so parent datablocks of nested nodetree get looped
- * over when we loop over tagged datablock types. */
- DEG_graph_id_type_tag(depsgraph, ID_MA);
- DEG_graph_id_type_tag(depsgraph, ID_TE);
- DEG_graph_id_type_tag(depsgraph, ID_LA);
- DEG_graph_id_type_tag(depsgraph, ID_WO);
- DEG_graph_id_type_tag(depsgraph, ID_SCE);
- }
- const int id_type_index = BKE_idcode_to_index(id_type);
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- deg_graph->id_type_updated[id_type_index] = 1;
+ if (id_type == ID_NT) {
+ /* Stupid workaround so parent datablocks of nested nodetree get looped
+ * over when we loop over tagged datablock types. */
+ DEG_graph_id_type_tag(depsgraph, ID_MA);
+ DEG_graph_id_type_tag(depsgraph, ID_TE);
+ DEG_graph_id_type_tag(depsgraph, ID_LA);
+ DEG_graph_id_type_tag(depsgraph, ID_WO);
+ DEG_graph_id_type_tag(depsgraph, ID_SCE);
+ }
+ const int id_type_index = BKE_idcode_to_index(id_type);
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ deg_graph->id_type_updated[id_type_index] = 1;
}
void DEG_id_type_tag(Main *bmain, short id_type)
{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- Depsgraph *depsgraph =
- (Depsgraph *)BKE_scene_get_depsgraph(scene,
- view_layer,
- false);
- if (depsgraph != NULL) {
- DEG_graph_id_type_tag(depsgraph, id_type);
- }
- }
- }
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph = (Depsgraph *)BKE_scene_get_depsgraph(scene, view_layer, false);
+ if (depsgraph != NULL) {
+ DEG_graph_id_type_tag(depsgraph, id_type);
+ }
+ }
+ }
}
void DEG_graph_flush_update(Main *bmain, Depsgraph *depsgraph)
{
- if (depsgraph == NULL) {
- return;
- }
- DEG::deg_graph_flush_updates(bmain, (DEG::Depsgraph *)depsgraph);
+ if (depsgraph == NULL) {
+ return;
+ }
+ DEG::deg_graph_flush_updates(bmain, (DEG::Depsgraph *)depsgraph);
}
/* Update dependency graph when visible scenes/layers changes. */
void DEG_graph_on_visible_update(Main *bmain, Depsgraph *depsgraph)
{
- DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
- DEG::deg_graph_on_visible_update(bmain, graph);
+ DEG::Depsgraph *graph = (DEG::Depsgraph *)depsgraph;
+ DEG::deg_graph_on_visible_update(bmain, graph);
}
void DEG_on_visible_update(Main *bmain, const bool UNUSED(do_time))
{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
- Depsgraph *depsgraph =
- (Depsgraph *)BKE_scene_get_depsgraph(scene,
- view_layer,
- false);
- if (depsgraph != NULL) {
- DEG_graph_on_visible_update(bmain, depsgraph);
- }
- }
- }
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
+ Depsgraph *depsgraph = (Depsgraph *)BKE_scene_get_depsgraph(scene, view_layer, false);
+ if (depsgraph != NULL) {
+ DEG_graph_on_visible_update(bmain, depsgraph);
+ }
+ }
+ }
}
/* Check if something was changed in the database and inform
* editors about this. */
-void DEG_ids_check_recalc(Main *bmain,
- Depsgraph *depsgraph,
- Scene *scene,
- ViewLayer *view_layer,
- bool time)
+void DEG_ids_check_recalc(
+ Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, bool time)
{
- bool updated = time || DEG_id_type_any_updated(depsgraph);
-
- DEGEditorUpdateContext update_ctx = {NULL};
- update_ctx.bmain = bmain;
- update_ctx.depsgraph = depsgraph;
- update_ctx.scene = scene;
- update_ctx.view_layer = view_layer;
- DEG::deg_editors_scene_update(&update_ctx, updated);
+ bool updated = time || DEG_id_type_any_updated(depsgraph);
+
+ DEGEditorUpdateContext update_ctx = {NULL};
+ update_ctx.bmain = bmain;
+ update_ctx.depsgraph = depsgraph;
+ update_ctx.scene = scene;
+ update_ctx.view_layer = view_layer;
+ DEG::deg_editors_scene_update(&update_ctx, updated);
}
-static void deg_graph_clear_id_node_func(
- void *__restrict data_v,
- const int i,
- const ParallelRangeTLS *__restrict /*tls*/)
+static void deg_graph_clear_id_node_func(void *__restrict data_v,
+ const int i,
+ const ParallelRangeTLS *__restrict /*tls*/)
{
- /* TODO: we clear original ID recalc flags here, but this may not work
- * correctly when there are multiple depsgraph with others still using
- * the recalc flag. */
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(data_v);
- DEG::IDNode *id_node = deg_graph->id_nodes[i];
- id_node->id_cow->recalc &= ~ID_RECALC_ALL;
- id_node->id_orig->recalc &= ~ID_RECALC_ALL;
-
- /* Clear embedded node trees too. */
- bNodeTree *ntree_cow = ntreeFromID(id_node->id_cow);
- if (ntree_cow) {
- ntree_cow->id.recalc &= ~ID_RECALC_ALL;
- }
- bNodeTree *ntree_orig = ntreeFromID(id_node->id_orig);
- if (ntree_orig) {
- ntree_orig->id.recalc &= ~ID_RECALC_ALL;
- }
+ /* TODO: we clear original ID recalc flags here, but this may not work
+ * correctly when there are multiple depsgraph with others still using
+ * the recalc flag. */
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(data_v);
+ DEG::IDNode *id_node = deg_graph->id_nodes[i];
+ id_node->id_cow->recalc &= ~ID_RECALC_ALL;
+ id_node->id_orig->recalc &= ~ID_RECALC_ALL;
+
+ /* Clear embedded node trees too. */
+ bNodeTree *ntree_cow = ntreeFromID(id_node->id_cow);
+ if (ntree_cow) {
+ ntree_cow->id.recalc &= ~ID_RECALC_ALL;
+ }
+ bNodeTree *ntree_orig = ntreeFromID(id_node->id_orig);
+ if (ntree_orig) {
+ ntree_orig->id.recalc &= ~ID_RECALC_ALL;
+ }
}
-void DEG_ids_clear_recalc(Main *UNUSED(bmain),
- Depsgraph *depsgraph)
+void DEG_ids_clear_recalc(Main *UNUSED(bmain), Depsgraph *depsgraph)
{
- DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
- /* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags
- * and id_tags storage from the new dependency graph. */
- if (!DEG_id_type_any_updated(depsgraph)) {
- return;
- }
- /* Go over all ID nodes nodes, clearing tags. */
- const int num_id_nodes = deg_graph->id_nodes.size();
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_id_nodes,
- deg_graph,
- deg_graph_clear_id_node_func,
- &settings);
- memset(deg_graph->id_type_updated, 0, sizeof(deg_graph->id_type_updated));
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ /* TODO(sergey): Re-implement POST_UPDATE_HANDLER_WORKAROUND using entry_tags
+ * and id_tags storage from the new dependency graph. */
+ if (!DEG_id_type_any_updated(depsgraph)) {
+ return;
+ }
+ /* Go over all ID nodes nodes, clearing tags. */
+ const int num_id_nodes = deg_graph->id_nodes.size();
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+ BLI_task_parallel_range(0, num_id_nodes, deg_graph, deg_graph_clear_id_node_func, &settings);
+ memset(deg_graph->id_type_updated, 0, sizeof(deg_graph->id_type_updated));
}
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.h b/source/blender/depsgraph/intern/depsgraph_tag.h
index e4d1158aa3c..e79372f2459 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.h
+++ b/source/blender/depsgraph/intern/depsgraph_tag.h
@@ -37,10 +37,7 @@ NodeType geometry_tag_to_component(const ID *id);
void id_tag_update(Main *bmain, ID *id, int flag, eUpdateSource update_source);
/* Tag given ID for an update with in a given dependency graph. */
-void graph_id_tag_update(Main *bmain,
- Depsgraph *graph,
- ID *id,
- int flag,
- eUpdateSource update_source);
+void graph_id_tag_update(
+ Main *bmain, Depsgraph *graph, ID *id, int flag, eUpdateSource update_source);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_type.cc b/source/blender/depsgraph/intern/depsgraph_type.cc
index 5be2cae10d7..ef1fda1df44 100644
--- a/source/blender/depsgraph/intern/depsgraph_type.cc
+++ b/source/blender/depsgraph/intern/depsgraph_type.cc
@@ -25,7 +25,6 @@
#include <cstdlib> // for BLI_assert()
-
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -42,10 +41,10 @@
/* Register all node types */
void DEG_register_node_types(void)
{
- /* register node types */
- DEG::deg_register_base_depsnodes();
- DEG::deg_register_component_depsnodes();
- DEG::deg_register_operation_depsnodes();
+ /* register node types */
+ DEG::deg_register_base_depsnodes();
+ DEG::deg_register_component_depsnodes();
+ DEG::deg_register_operation_depsnodes();
}
/* Free registry on exit */
@@ -53,11 +52,11 @@ void DEG_free_node_types(void)
{
}
-DEG::DEGCustomDataMeshMasks::DEGCustomDataMeshMasks(const CustomData_MeshMasks *other) :
- vert_mask(other->vmask),
- edge_mask(other->emask),
- face_mask(other->fmask),
- loop_mask(other->lmask),
- poly_mask(other->pmask)
+DEG::DEGCustomDataMeshMasks::DEGCustomDataMeshMasks(const CustomData_MeshMasks *other)
+ : vert_mask(other->vmask),
+ edge_mask(other->emask),
+ face_mask(other->fmask),
+ loop_mask(other->lmask),
+ poly_mask(other->pmask)
{
}
diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h
index d96c621f4b2..51ed31b8e25 100644
--- a/source/blender/depsgraph/intern/depsgraph_type.h
+++ b/source/blender/depsgraph/intern/depsgraph_type.h
@@ -46,16 +46,16 @@ struct CustomData_MeshMasks;
namespace DEG {
/* Commonly used types. */
-using std::string;
-using std::vector;
using std::map;
using std::pair;
+using std::string;
using std::unordered_map;
+using std::vector;
/* Commonly used functions. */
+using std::make_pair;
using std::max;
using std::to_string;
-using std::make_pair;
/* Function bindings. */
using std::function;
@@ -68,104 +68,97 @@ using namespace std::placeholders;
*
* TODO(sergey): Find a better place for this. */
enum eUpdateSource {
- /* Update is caused by a time change. */
- DEG_UPDATE_SOURCE_TIME = (1 << 0),
- /* Update caused by user directly or indirectly influencing the node. */
- DEG_UPDATE_SOURCE_USER_EDIT = (1 << 1),
- /* Update is happening as a special response for the relations update. */
- DEG_UPDATE_SOURCE_RELATIONS = (1 << 2),
- /* Update is happening due to visibility change. */
- DEG_UPDATE_SOURCE_VISIBILITY = (1 << 3),
+ /* Update is caused by a time change. */
+ DEG_UPDATE_SOURCE_TIME = (1 << 0),
+ /* Update caused by user directly or indirectly influencing the node. */
+ DEG_UPDATE_SOURCE_USER_EDIT = (1 << 1),
+ /* Update is happening as a special response for the relations update. */
+ DEG_UPDATE_SOURCE_RELATIONS = (1 << 2),
+ /* Update is happening due to visibility change. */
+ DEG_UPDATE_SOURCE_VISIBILITY = (1 << 3),
};
/* C++ wrapper around DNA's CustomData_MeshMasks struct. */
struct DEGCustomDataMeshMasks {
- uint64_t vert_mask;
- uint64_t edge_mask;
- uint64_t face_mask;
- uint64_t loop_mask;
- uint64_t poly_mask;
-
- DEGCustomDataMeshMasks()
- : vert_mask(0),
- edge_mask(0),
- face_mask(0),
- loop_mask(0),
- poly_mask(0)
- {
- }
-
- explicit DEGCustomDataMeshMasks(const CustomData_MeshMasks *other);
-
- DEGCustomDataMeshMasks& operator|=(const DEGCustomDataMeshMasks& other)
- {
- this->vert_mask |= other.vert_mask;
- this->edge_mask |= other.edge_mask;
- this->face_mask |= other.face_mask;
- this->loop_mask |= other.loop_mask;
- this->poly_mask |= other.poly_mask;
- return *this;
- }
-
- DEGCustomDataMeshMasks operator|(const DEGCustomDataMeshMasks& other) const
- {
- DEGCustomDataMeshMasks result;
- result.vert_mask = this->vert_mask | other.vert_mask;
- result.edge_mask = this->edge_mask | other.edge_mask;
- result.face_mask = this->face_mask | other.face_mask;
- result.loop_mask = this->loop_mask | other.loop_mask;
- result.poly_mask = this->poly_mask | other.poly_mask;
- return result;
- }
-
- bool operator==(const DEGCustomDataMeshMasks& other) const
- {
- return (this->vert_mask == other.vert_mask &&
- this->edge_mask == other.edge_mask &&
- this->face_mask == other.face_mask &&
- this->loop_mask == other.loop_mask &&
- this->poly_mask == other.poly_mask);
- }
-
- bool operator!=(const DEGCustomDataMeshMasks& other) const
- {
- return !(*this == other);
- }
-
- static DEGCustomDataMeshMasks MaskVert(const uint64_t vert_mask)
- {
- DEGCustomDataMeshMasks result;
- result.vert_mask = vert_mask;
- return result;
- }
-
- static DEGCustomDataMeshMasks MaskEdge(const uint64_t edge_mask)
- {
- DEGCustomDataMeshMasks result;
- result.edge_mask = edge_mask;
- return result;
- }
-
- static DEGCustomDataMeshMasks MaskFace(const uint64_t face_mask)
- {
- DEGCustomDataMeshMasks result;
- result.face_mask = face_mask;
- return result;
- }
-
- static DEGCustomDataMeshMasks MaskLoop(const uint64_t loop_mask)
- {
- DEGCustomDataMeshMasks result;
- result.loop_mask = loop_mask;
- return result;
- }
-
- static DEGCustomDataMeshMasks MaskPoly(const uint64_t poly_mask)
- {
- DEGCustomDataMeshMasks result;
- result.poly_mask = poly_mask;
- return result;
- }
+ uint64_t vert_mask;
+ uint64_t edge_mask;
+ uint64_t face_mask;
+ uint64_t loop_mask;
+ uint64_t poly_mask;
+
+ DEGCustomDataMeshMasks() : vert_mask(0), edge_mask(0), face_mask(0), loop_mask(0), poly_mask(0)
+ {
+ }
+
+ explicit DEGCustomDataMeshMasks(const CustomData_MeshMasks *other);
+
+ DEGCustomDataMeshMasks &operator|=(const DEGCustomDataMeshMasks &other)
+ {
+ this->vert_mask |= other.vert_mask;
+ this->edge_mask |= other.edge_mask;
+ this->face_mask |= other.face_mask;
+ this->loop_mask |= other.loop_mask;
+ this->poly_mask |= other.poly_mask;
+ return *this;
+ }
+
+ DEGCustomDataMeshMasks operator|(const DEGCustomDataMeshMasks &other) const
+ {
+ DEGCustomDataMeshMasks result;
+ result.vert_mask = this->vert_mask | other.vert_mask;
+ result.edge_mask = this->edge_mask | other.edge_mask;
+ result.face_mask = this->face_mask | other.face_mask;
+ result.loop_mask = this->loop_mask | other.loop_mask;
+ result.poly_mask = this->poly_mask | other.poly_mask;
+ return result;
+ }
+
+ bool operator==(const DEGCustomDataMeshMasks &other) const
+ {
+ return (this->vert_mask == other.vert_mask && this->edge_mask == other.edge_mask &&
+ this->face_mask == other.face_mask && this->loop_mask == other.loop_mask &&
+ this->poly_mask == other.poly_mask);
+ }
+
+ bool operator!=(const DEGCustomDataMeshMasks &other) const
+ {
+ return !(*this == other);
+ }
+
+ static DEGCustomDataMeshMasks MaskVert(const uint64_t vert_mask)
+ {
+ DEGCustomDataMeshMasks result;
+ result.vert_mask = vert_mask;
+ return result;
+ }
+
+ static DEGCustomDataMeshMasks MaskEdge(const uint64_t edge_mask)
+ {
+ DEGCustomDataMeshMasks result;
+ result.edge_mask = edge_mask;
+ return result;
+ }
+
+ static DEGCustomDataMeshMasks MaskFace(const uint64_t face_mask)
+ {
+ DEGCustomDataMeshMasks result;
+ result.face_mask = face_mask;
+ return result;
+ }
+
+ static DEGCustomDataMeshMasks MaskLoop(const uint64_t loop_mask)
+ {
+ DEGCustomDataMeshMasks result;
+ result.loop_mask = loop_mask;
+ return result;
+ }
+
+ static DEGCustomDataMeshMasks MaskPoly(const uint64_t poly_mask)
+ {
+ DEGCustomDataMeshMasks result;
+ result.poly_mask = poly_mask;
+ return result;
+ }
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/depsgraph_update.cc b/source/blender/depsgraph/intern/depsgraph_update.cc
index 1e09b012c01..ed4ec592fc7 100644
--- a/source/blender/depsgraph/intern/depsgraph_update.cc
+++ b/source/blender/depsgraph/intern/depsgraph_update.cc
@@ -34,25 +34,23 @@ static DEG_EditorUpdateSceneCb deg_editor_update_scene_cb = NULL;
void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, ID *id)
{
- if (deg_editor_update_id_cb != NULL) {
- deg_editor_update_id_cb(update_ctx, id);
- }
+ if (deg_editor_update_id_cb != NULL) {
+ deg_editor_update_id_cb(update_ctx, id);
+ }
}
-void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
- bool updated)
+void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx, bool updated)
{
- if (deg_editor_update_scene_cb != NULL) {
- deg_editor_update_scene_cb(update_ctx, updated);
- }
+ if (deg_editor_update_scene_cb != NULL) {
+ deg_editor_update_scene_cb(update_ctx, updated);
+ }
}
} // namespace DEG
/* Set callbacks which are being called when depsgraph changes. */
-void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func)
+void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, DEG_EditorUpdateSceneCb scene_func)
{
- DEG::deg_editor_update_id_cb = id_func;
- DEG::deg_editor_update_scene_cb = scene_func;
+ DEG::deg_editor_update_id_cb = id_func;
+ DEG::deg_editor_update_scene_cb = scene_func;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_update.h b/source/blender/depsgraph/intern/depsgraph_update.h
index 9f886e0dc25..1723658ced3 100644
--- a/source/blender/depsgraph/intern/depsgraph_update.h
+++ b/source/blender/depsgraph/intern/depsgraph_update.h
@@ -28,10 +28,8 @@ struct ID;
namespace DEG {
-void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx,
- struct ID *id);
+void deg_editors_id_update(const DEGEditorUpdateContext *update_ctx, struct ID *id);
-void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx,
- bool updated);
+void deg_editors_scene_update(const DEGEditorUpdateContext *update_ctx, bool updated);
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc
index eaafcffac97..950deee2b07 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval.cc
@@ -64,180 +64,165 @@ static void schedule_children(TaskPool *pool,
const int thread_id);
struct DepsgraphEvalState {
- Depsgraph *graph;
- bool do_stats;
- bool is_cow_stage;
+ Depsgraph *graph;
+ bool do_stats;
+ bool is_cow_stage;
};
-static void deg_task_run_func(TaskPool *pool,
- void *taskdata,
- int thread_id)
+static void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id)
{
- void *userdata_v = BLI_task_pool_userdata(pool);
- DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v;
- OperationNode *node = (OperationNode *)taskdata;
- /* Sanity checks. */
- BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
- /* Perform operation. */
- if (state->do_stats) {
- const double start_time = PIL_check_seconds_timer();
- node->evaluate((::Depsgraph *)state->graph);
- node->stats.current_time += PIL_check_seconds_timer() - start_time;
- }
- else {
- node->evaluate((::Depsgraph *)state->graph);
- }
- /* Schedule children. */
- BLI_task_pool_delayed_push_begin(pool, thread_id);
- schedule_children(pool, state->graph, node, thread_id);
- BLI_task_pool_delayed_push_end(pool, thread_id);
+ void *userdata_v = BLI_task_pool_userdata(pool);
+ DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v;
+ OperationNode *node = (OperationNode *)taskdata;
+ /* Sanity checks. */
+ BLI_assert(!node->is_noop() && "NOOP nodes should not actually be scheduled");
+ /* Perform operation. */
+ if (state->do_stats) {
+ const double start_time = PIL_check_seconds_timer();
+ node->evaluate((::Depsgraph *)state->graph);
+ node->stats.current_time += PIL_check_seconds_timer() - start_time;
+ }
+ else {
+ node->evaluate((::Depsgraph *)state->graph);
+ }
+ /* Schedule children. */
+ BLI_task_pool_delayed_push_begin(pool, thread_id);
+ schedule_children(pool, state->graph, node, thread_id);
+ BLI_task_pool_delayed_push_end(pool, thread_id);
}
struct CalculatePendingData {
- Depsgraph *graph;
+ Depsgraph *graph;
};
static bool check_operation_node_visible(OperationNode *op_node)
{
- const ComponentNode *comp_node = op_node->owner;
- /* Special exception, copy on write component is to be always evaluated,
- * to keep copied "database" in a consistent state. */
- if (comp_node->type == NodeType::COPY_ON_WRITE) {
- return true;
- }
- return comp_node->affects_directly_visible;
+ const ComponentNode *comp_node = op_node->owner;
+ /* Special exception, copy on write component is to be always evaluated,
+ * to keep copied "database" in a consistent state. */
+ if (comp_node->type == NodeType::COPY_ON_WRITE) {
+ return true;
+ }
+ return comp_node->affects_directly_visible;
}
-static void calculate_pending_func(
- void *__restrict data_v,
- const int i,
- const ParallelRangeTLS *__restrict /*tls*/)
+static void calculate_pending_func(void *__restrict data_v,
+ const int i,
+ const ParallelRangeTLS *__restrict /*tls*/)
{
- CalculatePendingData *data = (CalculatePendingData *)data_v;
- Depsgraph *graph = data->graph;
- OperationNode *node = graph->operations[i];
- /* Update counters, applies for both visible and invisible IDs. */
- node->num_links_pending = 0;
- node->scheduled = false;
- /* Invisible IDs requires no pending operations. */
- if (!check_operation_node_visible(node)) {
- return;
- }
- /* No need to bother with anything if node is not tagged for update. */
- if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
- return;
- }
- for (Relation *rel : node->inlinks) {
- if (rel->from->type == NodeType::OPERATION &&
- (rel->flag & RELATION_FLAG_CYCLIC) == 0)
- {
- OperationNode *from = (OperationNode *)rel->from;
- /* TODO(sergey): This is how old layer system was checking for the
- * calculation, but how is it possible that visible object depends
- * on an invisible? This is something what is prohibited after
- * deg_graph_build_flush_layers(). */
- if (!check_operation_node_visible(from)) {
- continue;
- }
- /* No need to vait for operation which is up to date. */
- if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
- continue;
- }
- ++node->num_links_pending;
- }
- }
+ CalculatePendingData *data = (CalculatePendingData *)data_v;
+ Depsgraph *graph = data->graph;
+ OperationNode *node = graph->operations[i];
+ /* Update counters, applies for both visible and invisible IDs. */
+ node->num_links_pending = 0;
+ node->scheduled = false;
+ /* Invisible IDs requires no pending operations. */
+ if (!check_operation_node_visible(node)) {
+ return;
+ }
+ /* No need to bother with anything if node is not tagged for update. */
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
+ return;
+ }
+ for (Relation *rel : node->inlinks) {
+ if (rel->from->type == NodeType::OPERATION && (rel->flag & RELATION_FLAG_CYCLIC) == 0) {
+ OperationNode *from = (OperationNode *)rel->from;
+ /* TODO(sergey): This is how old layer system was checking for the
+ * calculation, but how is it possible that visible object depends
+ * on an invisible? This is something what is prohibited after
+ * deg_graph_build_flush_layers(). */
+ if (!check_operation_node_visible(from)) {
+ continue;
+ }
+ /* No need to vait for operation which is up to date. */
+ if ((from->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
+ continue;
+ }
+ ++node->num_links_pending;
+ }
+ }
}
static void calculate_pending_parents(Depsgraph *graph)
{
- const int num_operations = graph->operations.size();
- CalculatePendingData data;
- data.graph = graph;
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0,
- num_operations,
- &data,
- calculate_pending_func,
- &settings);
+ const int num_operations = graph->operations.size();
+ CalculatePendingData data;
+ data.graph = graph;
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+ BLI_task_parallel_range(0, num_operations, &data, calculate_pending_func, &settings);
}
static void initialize_execution(DepsgraphEvalState *state, Depsgraph *graph)
{
- const bool do_stats = state->do_stats;
- calculate_pending_parents(graph);
- /* Clear tags and other things which needs to be clear. */
- for (OperationNode *node : graph->operations) {
- if (do_stats) {
- node->stats.reset_current();
- }
- }
+ const bool do_stats = state->do_stats;
+ calculate_pending_parents(graph);
+ /* Clear tags and other things which needs to be clear. */
+ for (OperationNode *node : graph->operations) {
+ if (do_stats) {
+ node->stats.reset_current();
+ }
+ }
}
/* Schedule a node if it needs evaluation.
* dec_parents: Decrement pending parents count, true when child nodes are
* scheduled after a task has been completed.
*/
-static void schedule_node(TaskPool *pool, Depsgraph *graph,
- OperationNode *node, bool dec_parents,
- const int thread_id)
+static void schedule_node(
+ TaskPool *pool, Depsgraph *graph, OperationNode *node, bool dec_parents, const int thread_id)
{
- /* No need to schedule nodes of invisible ID. */
- if (!check_operation_node_visible(node)) {
- return;
- }
- /* No need to schedule operations which are not tagged for update, they are
- * considered to be up to date. */
- if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
- return;
- }
- /* TODO(sergey): This is not strictly speaking safe to read
- * num_links_pending. */
- if (dec_parents) {
- BLI_assert(node->num_links_pending > 0);
- atomic_sub_and_fetch_uint32(&node->num_links_pending, 1);
- }
- /* Cal not schedule operation while its dependencies are not yet
- * evaluated. */
- if (node->num_links_pending != 0) {
- return;
- }
- /* During the COW stage only schedule COW nodes. */
- DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool);
- if (state->is_cow_stage) {
- if (node->owner->type != NodeType::COPY_ON_WRITE) {
- return;
- }
- }
- else {
- BLI_assert(node->scheduled || node->owner->type != NodeType::COPY_ON_WRITE);
- }
- /* Actually schedule the node. */
- bool is_scheduled = atomic_fetch_and_or_uint8(
- (uint8_t *)&node->scheduled, (uint8_t)true);
- if (!is_scheduled) {
- if (node->is_noop()) {
- /* skip NOOP node, schedule children right away */
- schedule_children(pool, graph, node, thread_id);
- }
- else {
- /* children are scheduled once this task is completed */
- BLI_task_pool_push_from_thread(pool,
- deg_task_run_func,
- node,
- false,
- TASK_PRIORITY_HIGH,
- thread_id);
- }
- }
+ /* No need to schedule nodes of invisible ID. */
+ if (!check_operation_node_visible(node)) {
+ return;
+ }
+ /* No need to schedule operations which are not tagged for update, they are
+ * considered to be up to date. */
+ if ((node->flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
+ return;
+ }
+ /* TODO(sergey): This is not strictly speaking safe to read
+ * num_links_pending. */
+ if (dec_parents) {
+ BLI_assert(node->num_links_pending > 0);
+ atomic_sub_and_fetch_uint32(&node->num_links_pending, 1);
+ }
+ /* Cal not schedule operation while its dependencies are not yet
+ * evaluated. */
+ if (node->num_links_pending != 0) {
+ return;
+ }
+ /* During the COW stage only schedule COW nodes. */
+ DepsgraphEvalState *state = (DepsgraphEvalState *)BLI_task_pool_userdata(pool);
+ if (state->is_cow_stage) {
+ if (node->owner->type != NodeType::COPY_ON_WRITE) {
+ return;
+ }
+ }
+ else {
+ BLI_assert(node->scheduled || node->owner->type != NodeType::COPY_ON_WRITE);
+ }
+ /* Actually schedule the node. */
+ bool is_scheduled = atomic_fetch_and_or_uint8((uint8_t *)&node->scheduled, (uint8_t) true);
+ if (!is_scheduled) {
+ if (node->is_noop()) {
+ /* skip NOOP node, schedule children right away */
+ schedule_children(pool, graph, node, thread_id);
+ }
+ else {
+ /* children are scheduled once this task is completed */
+ BLI_task_pool_push_from_thread(
+ pool, deg_task_run_func, node, false, TASK_PRIORITY_HIGH, thread_id);
+ }
+ }
}
static void schedule_graph(TaskPool *pool, Depsgraph *graph)
{
- for (OperationNode *node : graph->operations) {
- schedule_node(pool, graph, node, false, 0);
- }
+ for (OperationNode *node : graph->operations) {
+ schedule_node(pool, graph, node, false, 0);
+ }
}
static void schedule_children(TaskPool *pool,
@@ -245,34 +230,29 @@ static void schedule_children(TaskPool *pool,
OperationNode *node,
const int thread_id)
{
- for (Relation *rel : node->outlinks) {
- OperationNode *child = (OperationNode *)rel->to;
- BLI_assert(child->type == NodeType::OPERATION);
- if (child->scheduled) {
- /* Happens when having cyclic dependencies. */
- continue;
- }
- schedule_node(pool,
- graph,
- child,
- (rel->flag & RELATION_FLAG_CYCLIC) == 0,
- thread_id);
- }
+ for (Relation *rel : node->outlinks) {
+ OperationNode *child = (OperationNode *)rel->to;
+ BLI_assert(child->type == NodeType::OPERATION);
+ if (child->scheduled) {
+ /* Happens when having cyclic dependencies. */
+ continue;
+ }
+ schedule_node(pool, graph, child, (rel->flag & RELATION_FLAG_CYCLIC) == 0, thread_id);
+ }
}
static void depsgraph_ensure_view_layer(Depsgraph *graph)
{
- /* We update copy-on-write scene in the following cases:
- * - It was not expanded yet.
- * - It was tagged for update of CoW component.
- * This allows us to have proper view layer pointer. */
- Scene *scene_cow = graph->scene_cow;
- if (!deg_copy_on_write_is_expanded(&scene_cow->id) ||
- scene_cow->id.recalc & ID_RECALC_COPY_ON_WRITE)
- {
- const IDNode *id_node = graph->find_id_node(&graph->scene->id);
- deg_update_copy_on_write_datablock(graph, id_node);
- }
+ /* We update copy-on-write scene in the following cases:
+ * - It was not expanded yet.
+ * - It was tagged for update of CoW component.
+ * This allows us to have proper view layer pointer. */
+ Scene *scene_cow = graph->scene_cow;
+ if (!deg_copy_on_write_is_expanded(&scene_cow->id) ||
+ scene_cow->id.recalc & ID_RECALC_COPY_ON_WRITE) {
+ const IDNode *id_node = graph->find_id_node(&graph->scene->id);
+ deg_update_copy_on_write_datablock(graph, id_node);
+ }
}
/**
@@ -284,58 +264,57 @@ static void depsgraph_ensure_view_layer(Depsgraph *graph)
*/
void deg_evaluate_on_refresh(Depsgraph *graph)
{
- /* Nothing to update, early out. */
- if (BLI_gset_len(graph->entry_tags) == 0) {
- return;
- }
- const bool do_time_debug = ((G.debug & G_DEBUG_DEPSGRAPH_TIME) != 0);
- const double start_time = do_time_debug ? PIL_check_seconds_timer() : 0;
- graph->debug_is_evaluating = true;
- depsgraph_ensure_view_layer(graph);
- /* Set up evaluation state. */
- DepsgraphEvalState state;
- state.graph = graph;
- state.do_stats = do_time_debug;
- /* Set up task scheduler and pull for threaded evaluation. */
- TaskScheduler *task_scheduler;
- bool need_free_scheduler;
- if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- task_scheduler = BLI_task_scheduler_create(1);
- need_free_scheduler = true;
- }
- else {
- task_scheduler = BLI_task_scheduler_get();
- need_free_scheduler = false;
- }
- TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
- /* Prepare all nodes for evaluation. */
- initialize_execution(&state, graph);
- /* Do actual evaluation now. */
- /* First, process all Copy-On-Write nodes. */
- state.is_cow_stage = true;
- schedule_graph(task_pool, graph);
- BLI_task_pool_work_wait_and_reset(task_pool);
- /* After that, process all other nodes. */
- state.is_cow_stage = false;
- schedule_graph(task_pool, graph);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- /* Finalize statistics gathering. This is because we only gather single
- * operation timing here, without aggregating anything to avoid any extra
- * synchronization. */
- if (state.do_stats) {
- deg_eval_stats_aggregate(graph);
- }
- /* Clear any uncleared tags - just in case. */
- deg_graph_clear_tags(graph);
- if (need_free_scheduler) {
- BLI_task_scheduler_free(task_scheduler);
- }
- graph->debug_is_evaluating = false;
- if (do_time_debug) {
- printf("Depsgraph updated in %f seconds.\n",
- PIL_check_seconds_timer() - start_time);
- }
+ /* Nothing to update, early out. */
+ if (BLI_gset_len(graph->entry_tags) == 0) {
+ return;
+ }
+ const bool do_time_debug = ((G.debug & G_DEBUG_DEPSGRAPH_TIME) != 0);
+ const double start_time = do_time_debug ? PIL_check_seconds_timer() : 0;
+ graph->debug_is_evaluating = true;
+ depsgraph_ensure_view_layer(graph);
+ /* Set up evaluation state. */
+ DepsgraphEvalState state;
+ state.graph = graph;
+ state.do_stats = do_time_debug;
+ /* Set up task scheduler and pull for threaded evaluation. */
+ TaskScheduler *task_scheduler;
+ bool need_free_scheduler;
+ if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
+ task_scheduler = BLI_task_scheduler_create(1);
+ need_free_scheduler = true;
+ }
+ else {
+ task_scheduler = BLI_task_scheduler_get();
+ need_free_scheduler = false;
+ }
+ TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state);
+ /* Prepare all nodes for evaluation. */
+ initialize_execution(&state, graph);
+ /* Do actual evaluation now. */
+ /* First, process all Copy-On-Write nodes. */
+ state.is_cow_stage = true;
+ schedule_graph(task_pool, graph);
+ BLI_task_pool_work_wait_and_reset(task_pool);
+ /* After that, process all other nodes. */
+ state.is_cow_stage = false;
+ schedule_graph(task_pool, graph);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+ /* Finalize statistics gathering. This is because we only gather single
+ * operation timing here, without aggregating anything to avoid any extra
+ * synchronization. */
+ if (state.do_stats) {
+ deg_eval_stats_aggregate(graph);
+ }
+ /* Clear any uncleared tags - just in case. */
+ deg_graph_clear_tags(graph);
+ if (need_free_scheduler) {
+ BLI_task_scheduler_free(task_scheduler);
+ }
+ graph->debug_is_evaluating = false;
+ if (do_time_debug) {
+ printf("Depsgraph updated in %f seconds.\n", PIL_check_seconds_timer() - start_time);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 387253ab3fe..01b712fcd87 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -17,7 +17,6 @@
* All rights reserved.
*/
-
/** \file
* \ingroup depsgraph
*/
@@ -95,260 +94,245 @@ extern "C" {
namespace DEG {
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) printf
+#define DEBUG_PRINT \
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) \
+ printf
namespace {
#ifdef NESTED_ID_NASTY_WORKAROUND
union NestedIDHackTempStorage {
- Curve curve;
- FreestyleLineStyle linestyle;
- Light lamp;
- Lattice lattice;
- Material material;
- Mesh mesh;
- Scene scene;
- Tex tex;
- World world;
+ Curve curve;
+ FreestyleLineStyle linestyle;
+ Light lamp;
+ Lattice lattice;
+ Material material;
+ Mesh mesh;
+ Scene scene;
+ Tex tex;
+ World world;
};
/* Set nested owned ID pointers to NULL. */
void nested_id_hack_discard_pointers(ID *id_cow)
{
- switch (GS(id_cow->name)) {
-# define SPECIAL_CASE(id_type, dna_type, field) \
- case id_type: \
- { \
- ((dna_type *)id_cow)->field = NULL; \
- break; \
- }
-
- SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
- SPECIAL_CASE(ID_LA, Light, nodetree)
- SPECIAL_CASE(ID_MA, Material, nodetree)
- SPECIAL_CASE(ID_TE, Tex, nodetree)
- SPECIAL_CASE(ID_WO, World, nodetree)
-
- SPECIAL_CASE(ID_CU, Curve, key)
- SPECIAL_CASE(ID_LT, Lattice, key)
- SPECIAL_CASE(ID_ME, Mesh, key)
-
- case ID_SCE:
- {
- Scene *scene_cow = (Scene *)id_cow;
- /* Node trees always have their own ID node in the graph, and are
- * being copied as part of their copy-on-write process. */
- scene_cow->nodetree = NULL;
- /* Tool settings pointer is shared with the original scene. */
- scene_cow->toolsettings = NULL;
- break;
- }
-
- case ID_OB:
- {
- /* Clear the ParticleSettings pointer to prevent doubly-freeing it. */
- Object *ob = (Object *)id_cow;
- LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
- psys->part = NULL;
- }
- break;
- }
+ switch (GS(id_cow->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field) \
+ case id_type: { \
+ ((dna_type *)id_cow)->field = NULL; \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
+ SPECIAL_CASE(ID_LA, Light, nodetree)
+ SPECIAL_CASE(ID_MA, Material, nodetree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree)
+ SPECIAL_CASE(ID_WO, World, nodetree)
+
+ SPECIAL_CASE(ID_CU, Curve, key)
+ SPECIAL_CASE(ID_LT, Lattice, key)
+ SPECIAL_CASE(ID_ME, Mesh, key)
+
+ case ID_SCE: {
+ Scene *scene_cow = (Scene *)id_cow;
+ /* Node trees always have their own ID node in the graph, and are
+ * being copied as part of their copy-on-write process. */
+ scene_cow->nodetree = NULL;
+ /* Tool settings pointer is shared with the original scene. */
+ scene_cow->toolsettings = NULL;
+ break;
+ }
+
+ case ID_OB: {
+ /* Clear the ParticleSettings pointer to prevent doubly-freeing it. */
+ Object *ob = (Object *)id_cow;
+ LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
+ psys->part = NULL;
+ }
+ break;
+ }
# undef SPECIAL_CASE
- default:
- break;
- }
+ default:
+ break;
+ }
}
/* Set ID pointer of nested owned IDs (nodetree, key) to NULL.
*
* Return pointer to a new ID to be used. */
-const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage,
- const ID *id)
+const ID *nested_id_hack_get_discarded_pointers(NestedIDHackTempStorage *storage, const ID *id)
{
- switch (GS(id->name)) {
-# define SPECIAL_CASE(id_type, dna_type, field, variable) \
- case id_type: \
- { \
- storage->variable = *(dna_type *)id; \
- storage->variable.field = NULL; \
- return &storage->variable.id; \
- }
-
- SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
- SPECIAL_CASE(ID_LA, Light, nodetree, lamp)
- SPECIAL_CASE(ID_MA, Material, nodetree, material)
- SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
- SPECIAL_CASE(ID_WO, World, nodetree, world)
-
- SPECIAL_CASE(ID_CU, Curve, key, curve)
- SPECIAL_CASE(ID_LT, Lattice, key, lattice)
- SPECIAL_CASE(ID_ME, Mesh, key, mesh)
-
- case ID_SCE:
- {
- storage->scene = *(Scene *)id;
- storage->scene.toolsettings = NULL;
- storage->scene.nodetree = NULL;
- return &storage->scene.id;
- }
+ switch (GS(id->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field, variable) \
+ case id_type: { \
+ storage->variable = *(dna_type *)id; \
+ storage->variable.field = NULL; \
+ return &storage->variable.id; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, linestyle)
+ SPECIAL_CASE(ID_LA, Light, nodetree, lamp)
+ SPECIAL_CASE(ID_MA, Material, nodetree, material)
+ SPECIAL_CASE(ID_TE, Tex, nodetree, tex)
+ SPECIAL_CASE(ID_WO, World, nodetree, world)
+
+ SPECIAL_CASE(ID_CU, Curve, key, curve)
+ SPECIAL_CASE(ID_LT, Lattice, key, lattice)
+ SPECIAL_CASE(ID_ME, Mesh, key, mesh)
+
+ case ID_SCE: {
+ storage->scene = *(Scene *)id;
+ storage->scene.toolsettings = NULL;
+ storage->scene.nodetree = NULL;
+ return &storage->scene.id;
+ }
# undef SPECIAL_CASE
- default:
- break;
- }
- return id;
+ default:
+ break;
+ }
+ return id;
}
/* Set ID pointer of nested owned IDs (nodetree, key) to the original value. */
void nested_id_hack_restore_pointers(const ID *old_id, ID *new_id)
{
- if (new_id == NULL) {
- return;
- }
- switch (GS(old_id->name)) {
-# define SPECIAL_CASE(id_type, dna_type, field) \
- case id_type: \
- { \
- ((dna_type *)(new_id))->field = \
- ((dna_type *)(old_id))->field; \
- break; \
- }
-
- SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
- SPECIAL_CASE(ID_LA, Light, nodetree)
- SPECIAL_CASE(ID_MA, Material, nodetree)
- SPECIAL_CASE(ID_SCE, Scene, nodetree)
- SPECIAL_CASE(ID_TE, Tex, nodetree)
- SPECIAL_CASE(ID_WO, World, nodetree)
-
- SPECIAL_CASE(ID_CU, Curve, key)
- SPECIAL_CASE(ID_LT, Lattice, key)
- SPECIAL_CASE(ID_ME, Mesh, key)
-
-#undef SPECIAL_CASE
- default:
- break;
- }
+ if (new_id == NULL) {
+ return;
+ }
+ switch (GS(old_id->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field) \
+ case id_type: { \
+ ((dna_type *)(new_id))->field = ((dna_type *)(old_id))->field; \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree)
+ SPECIAL_CASE(ID_LA, Light, nodetree)
+ SPECIAL_CASE(ID_MA, Material, nodetree)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree)
+ SPECIAL_CASE(ID_WO, World, nodetree)
+
+ SPECIAL_CASE(ID_CU, Curve, key)
+ SPECIAL_CASE(ID_LT, Lattice, key)
+ SPECIAL_CASE(ID_ME, Mesh, key)
+
+# undef SPECIAL_CASE
+ default:
+ break;
+ }
}
/* Remap pointer of nested owned IDs (nodetree. key) to the new ID values. */
void ntree_hack_remap_pointers(const Depsgraph *depsgraph, ID *id_cow)
{
- switch (GS(id_cow->name)) {
-# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
- case id_type: \
- { \
- dna_type *data = (dna_type *)id_cow; \
- if (data->field != NULL) { \
- ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
- if (ntree_id_cow != NULL) { \
- DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
- data->field->id.name, \
- data->field, \
- ntree_id_cow); \
- data->field = (field_type *)ntree_id_cow; \
- } \
- } \
- break; \
- }
-
- SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, bNodeTree)
- SPECIAL_CASE(ID_LA, Light, nodetree, bNodeTree)
- SPECIAL_CASE(ID_MA, Material, nodetree, bNodeTree)
- SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree)
- SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
- SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
-
- SPECIAL_CASE(ID_CU, Curve, key, Key)
- SPECIAL_CASE(ID_LT, Lattice, key, Key)
- SPECIAL_CASE(ID_ME, Mesh, key, Key)
-
-#undef SPECIAL_CASE
- default:
- break;
- }
+ switch (GS(id_cow->name)) {
+# define SPECIAL_CASE(id_type, dna_type, field, field_type) \
+ case id_type: { \
+ dna_type *data = (dna_type *)id_cow; \
+ if (data->field != NULL) { \
+ ID *ntree_id_cow = depsgraph->get_cow_id(&data->field->id); \
+ if (ntree_id_cow != NULL) { \
+ DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n", \
+ data->field->id.name, \
+ data->field, \
+ ntree_id_cow); \
+ data->field = (field_type *)ntree_id_cow; \
+ } \
+ } \
+ break; \
+ }
+
+ SPECIAL_CASE(ID_LS, FreestyleLineStyle, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_LA, Light, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_MA, Material, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_SCE, Scene, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_TE, Tex, nodetree, bNodeTree)
+ SPECIAL_CASE(ID_WO, World, nodetree, bNodeTree)
+
+ SPECIAL_CASE(ID_CU, Curve, key, Key)
+ SPECIAL_CASE(ID_LT, Lattice, key, Key)
+ SPECIAL_CASE(ID_ME, Mesh, key, Key)
+
+# undef SPECIAL_CASE
+ default:
+ break;
+ }
}
-#endif /* NODETREE_NASTY_WORKAROUND */
+#endif /* NODETREE_NASTY_WORKAROUND */
struct ValidateData {
- bool is_valid;
+ bool is_valid;
};
/* Similar to generic BKE_id_copy() but does not require main and assumes pointer
* is already allocated. */
bool id_copy_inplace_no_main(const ID *id, ID *newid)
{
- const ID *id_for_copy = id;
+ const ID *id_for_copy = id;
#ifdef NESTED_ID_NASTY_WORKAROUND
- NestedIDHackTempStorage id_hack_storage;
- id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
+ NestedIDHackTempStorage id_hack_storage;
+ id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, id);
#endif
- bool result = BKE_id_copy_ex(NULL,
- (ID *)id_for_copy,
- &newid,
- (LIB_ID_COPY_LOCALIZE |
- LIB_ID_CREATE_NO_ALLOCATE));
+ bool result = BKE_id_copy_ex(
+ NULL, (ID *)id_for_copy, &newid, (LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE));
#ifdef NESTED_ID_NASTY_WORKAROUND
- if (result) {
- nested_id_hack_restore_pointers(id, newid);
- }
+ if (result) {
+ nested_id_hack_restore_pointers(id, newid);
+ }
#endif
- return result;
+ return result;
}
/* Similar to BKE_scene_copy() but does not require main and assumes pointer
* is already allocated. */
bool scene_copy_inplace_no_main(const Scene *scene, Scene *new_scene)
{
- const ID *id_for_copy = &scene->id;
+ const ID *id_for_copy = &scene->id;
#ifdef NESTED_ID_NASTY_WORKAROUND
- NestedIDHackTempStorage id_hack_storage;
- id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage,
- &scene->id);
+ NestedIDHackTempStorage id_hack_storage;
+ id_for_copy = nested_id_hack_get_discarded_pointers(&id_hack_storage, &scene->id);
#endif
- bool result = BKE_id_copy_ex(NULL,
- id_for_copy,
- (ID **)&new_scene,
- LIB_ID_COPY_LOCALIZE |
- LIB_ID_CREATE_NO_ALLOCATE);
+ bool result = BKE_id_copy_ex(
+ NULL, id_for_copy, (ID **)&new_scene, LIB_ID_COPY_LOCALIZE | LIB_ID_CREATE_NO_ALLOCATE);
#ifdef NESTED_ID_NASTY_WORKAROUND
- if (result) {
- nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
- }
+ if (result) {
+ nested_id_hack_restore_pointers(&scene->id, &new_scene->id);
+ }
#endif
- return result;
+ return result;
}
/* For the given scene get view layer which corresponds to an original for the
* scene's evaluated one. This depends on how the scene is pulled into the
* dependency graph. */
-ViewLayer *get_original_view_layer(const Depsgraph *depsgraph,
- const IDNode *id_node)
+ViewLayer *get_original_view_layer(const Depsgraph *depsgraph, const IDNode *id_node)
{
- if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
- return depsgraph->view_layer;
- }
- else if (id_node->linked_state == DEG_ID_LINKED_VIA_SET) {
- Scene *scene_orig = reinterpret_cast<Scene *>(id_node->id_orig);
- return BKE_view_layer_default_render(scene_orig);
- }
- /* Is possible to have scene linked indirectly (i.e. via the driver) which
- * we need to support. Currently there aer issues somewhere else, which
- * makes testing hard. This is a reported problem, so will eventually be
- * properly fixed.
- *
- * TODO(sergey): Support indirectly linked scene. */
- return NULL;
+ if (id_node->linked_state == DEG_ID_LINKED_DIRECTLY) {
+ return depsgraph->view_layer;
+ }
+ else if (id_node->linked_state == DEG_ID_LINKED_VIA_SET) {
+ Scene *scene_orig = reinterpret_cast<Scene *>(id_node->id_orig);
+ return BKE_view_layer_default_render(scene_orig);
+ }
+ /* Is possible to have scene linked indirectly (i.e. via the driver) which
+ * we need to support. Currently there aer issues somewhere else, which
+ * makes testing hard. This is a reported problem, so will eventually be
+ * properly fixed.
+ *
+ * TODO(sergey): Support indirectly linked scene. */
+ return NULL;
}
/* Remove all view layers but the one which corresponds to an input one. */
@@ -356,102 +340,95 @@ void scene_remove_unused_view_layers(const Depsgraph *depsgraph,
const IDNode *id_node,
Scene *scene_cow)
{
- const ViewLayer *view_layer_input = get_original_view_layer(
- depsgraph, id_node);
- ViewLayer *view_layer_eval = NULL;
- /* Find evaluated view layer. At the same time we free memory used by
- * all other of the view layers. */
- for (ViewLayer *view_layer_cow =
- reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first),
- *view_layer_next;
- view_layer_cow != NULL;
- view_layer_cow = view_layer_next)
- {
- view_layer_next = view_layer_cow->next;
- if (STREQ(view_layer_input->name, view_layer_cow->name)) {
- view_layer_eval = view_layer_cow;
- }
- else {
- BKE_view_layer_free_ex(view_layer_cow, false);
- }
- }
- BLI_assert(view_layer_eval != NULL);
- /* Make evaluated view layer the only one in the evaluated scene. */
- view_layer_eval->prev = view_layer_eval->next = NULL;
- scene_cow->view_layers.first = view_layer_eval;
- scene_cow->view_layers.last = view_layer_eval;
+ const ViewLayer *view_layer_input = get_original_view_layer(depsgraph, id_node);
+ ViewLayer *view_layer_eval = NULL;
+ /* Find evaluated view layer. At the same time we free memory used by
+ * all other of the view layers. */
+ for (ViewLayer *view_layer_cow = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first),
+ *view_layer_next;
+ view_layer_cow != NULL;
+ view_layer_cow = view_layer_next) {
+ view_layer_next = view_layer_cow->next;
+ if (STREQ(view_layer_input->name, view_layer_cow->name)) {
+ view_layer_eval = view_layer_cow;
+ }
+ else {
+ BKE_view_layer_free_ex(view_layer_cow, false);
+ }
+ }
+ BLI_assert(view_layer_eval != NULL);
+ /* Make evaluated view layer the only one in the evaluated scene. */
+ view_layer_eval->prev = view_layer_eval->next = NULL;
+ scene_cow->view_layers.first = view_layer_eval;
+ scene_cow->view_layers.last = view_layer_eval;
}
/* Makes it so given view layer only has bases corresponding to enabled
* objects. */
-void view_layer_remove_disabled_bases(const Depsgraph *depsgraph,
- ViewLayer *view_layer)
+void view_layer_remove_disabled_bases(const Depsgraph *depsgraph, ViewLayer *view_layer)
{
- ListBase enabled_bases = {NULL, NULL};
- LISTBASE_FOREACH_MUTABLE (Base *, base, &view_layer->object_bases) {
- /* TODO(sergey): Would be cool to optimize this somehow, or make it so
- * builder tags bases.
- *
- * NOTE: The idea of using id's tag and check whether its copied ot not
- * is not reliable, since object might be indirectly linked into the
- * graph.
- *
- * NOTE: We are using original base since the object which evaluated base
- * points to is not yet copied. This is dangerous access from evaluated
- * domain to original one, but this is how the entire copy-on-write works:
- * it does need to access original for an initial copy. */
- const bool is_object_enabled =
- deg_check_base_available_for_build(depsgraph, base->base_orig);
- if (is_object_enabled) {
- BLI_addtail(&enabled_bases, base);
- }
- else {
- if (base == view_layer->basact) {
- view_layer->basact = NULL;
- }
- MEM_freeN(base);
- }
- }
- view_layer->object_bases = enabled_bases;
+ ListBase enabled_bases = {NULL, NULL};
+ LISTBASE_FOREACH_MUTABLE(Base *, base, &view_layer->object_bases)
+ {
+ /* TODO(sergey): Would be cool to optimize this somehow, or make it so
+ * builder tags bases.
+ *
+ * NOTE: The idea of using id's tag and check whether its copied ot not
+ * is not reliable, since object might be indirectly linked into the
+ * graph.
+ *
+ * NOTE: We are using original base since the object which evaluated base
+ * points to is not yet copied. This is dangerous access from evaluated
+ * domain to original one, but this is how the entire copy-on-write works:
+ * it does need to access original for an initial copy. */
+ const bool is_object_enabled = deg_check_base_available_for_build(depsgraph, base->base_orig);
+ if (is_object_enabled) {
+ BLI_addtail(&enabled_bases, base);
+ }
+ else {
+ if (base == view_layer->basact) {
+ view_layer->basact = NULL;
+ }
+ MEM_freeN(base);
+ }
+ }
+ view_layer->object_bases = enabled_bases;
}
void view_layer_update_orig_base_pointers(const ViewLayer *view_layer_orig,
ViewLayer *view_layer_eval)
{
- Base *base_orig =
- reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
- LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
- base_eval->base_orig = base_orig;
- base_orig = base_orig->next;
- }
+ Base *base_orig = reinterpret_cast<Base *>(view_layer_orig->object_bases.first);
+ LISTBASE_FOREACH (Base *, base_eval, &view_layer_eval->object_bases) {
+ base_eval->base_orig = base_orig;
+ base_orig = base_orig->next;
+ }
}
void scene_setup_view_layers_before_remap(const Depsgraph *depsgraph,
const IDNode *id_node,
Scene *scene_cow)
{
- scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
+ scene_remove_unused_view_layers(depsgraph, id_node, scene_cow);
}
void scene_setup_view_layers_after_remap(const Depsgraph *depsgraph,
const IDNode *id_node,
Scene *scene_cow)
{
- const ViewLayer *view_layer_orig = get_original_view_layer(
- depsgraph, id_node);
- ViewLayer *view_layer_eval =
- reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
- view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
- view_layer_remove_disabled_bases(depsgraph, view_layer_eval);
- /* TODO(sergey): Remove objects from collections as well.
- * Not a HUGE deal for now, nobody is looking into those CURRENTLY.
- * Still not an excuse to have those. */
+ const ViewLayer *view_layer_orig = get_original_view_layer(depsgraph, id_node);
+ ViewLayer *view_layer_eval = reinterpret_cast<ViewLayer *>(scene_cow->view_layers.first);
+ view_layer_update_orig_base_pointers(view_layer_orig, view_layer_eval);
+ view_layer_remove_disabled_bases(depsgraph, view_layer_eval);
+ /* TODO(sergey): Remove objects from collections as well.
+ * Not a HUGE deal for now, nobody is looking into those CURRENTLY.
+ * Still not an excuse to have those. */
}
/* Check whether given ID is expanded or still a shallow copy. */
BLI_INLINE bool check_datablock_expanded(const ID *id_cow)
{
- return (id_cow->name[0] != '\0');
+ return (id_cow->name[0] != '\0');
}
/* Those are datablocks which are not covered by dependency graph and hence
@@ -461,211 +438,200 @@ BLI_INLINE bool check_datablock_expanded(const ID *id_cow)
* to maintain exception lists all over the code? */
bool check_datablocks_copy_on_writable(const ID *id_orig)
{
- const ID_Type id_type = GS(id_orig->name);
- /* We shouldn't bother if copied ID is same as original one. */
- if (!deg_copy_on_write_is_needed(id_orig)) {
- return false;
- }
- return !ELEM(id_type, ID_BR,
- ID_LS,
- ID_PAL);
+ const ID_Type id_type = GS(id_orig->name);
+ /* We shouldn't bother if copied ID is same as original one. */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return false;
+ }
+ return !ELEM(id_type, ID_BR, ID_LS, ID_PAL);
}
/* Callback for BKE_library_foreach_ID_link which remaps original ID pointer
* with the one created by CoW system. */
struct RemapCallbackUserData {
- /* Dependency graph for which remapping is happening. */
- const Depsgraph *depsgraph;
- /* Create placeholder for ID nodes for cases when we need to remap original
- * ID to it[s CoW version but we don't have required ID node yet.
- *
- * This happens when expansion happens a ta construction time. */
- DepsgraphNodeBuilder *node_builder;
- bool create_placeholders;
+ /* Dependency graph for which remapping is happening. */
+ const Depsgraph *depsgraph;
+ /* Create placeholder for ID nodes for cases when we need to remap original
+ * ID to it[s CoW version but we don't have required ID node yet.
+ *
+ * This happens when expansion happens a ta construction time. */
+ DepsgraphNodeBuilder *node_builder;
+ bool create_placeholders;
};
-int foreach_libblock_remap_callback(void *user_data_v,
- ID *id_self,
- ID **id_p,
- int /*cb_flag*/)
+int foreach_libblock_remap_callback(void *user_data_v, ID *id_self, ID **id_p, int /*cb_flag*/)
{
- if (*id_p == NULL) {
- return IDWALK_RET_NOP;
- }
- RemapCallbackUserData *user_data = (RemapCallbackUserData *)user_data_v;
- const Depsgraph *depsgraph = user_data->depsgraph;
- ID *id_orig = *id_p;
- if (check_datablocks_copy_on_writable(id_orig)) {
- ID *id_cow;
- if (user_data->create_placeholders) {
- /* Special workaround to stop creating temp datablocks for
- * objects which are coming from scene's collection and which
- * are never linked to any of layers.
- *
- * TODO(sergey): Ideally we need to tell ID looper to ignore
- * those or at least make it more reliable check where the
- * pointer is coming from. */
- const ID_Type id_type = GS(id_orig->name);
- const ID_Type id_type_self = GS(id_self->name);
- if (id_type == ID_OB && id_type_self == ID_SCE) {
- IDNode *id_node = depsgraph->find_id_node(id_orig);
- if (id_node == NULL) {
- id_cow = id_orig;
- }
- else {
- id_cow = id_node->id_cow;
- }
- }
- else {
- id_cow = user_data->node_builder->ensure_cow_id(id_orig);
- }
- }
- else {
- id_cow = depsgraph->get_cow_id(id_orig);
- }
- BLI_assert(id_cow != NULL);
- DEG_COW_PRINT(" Remapping datablock for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- *id_p = id_cow;
- }
- return IDWALK_RET_NOP;
+ if (*id_p == NULL) {
+ return IDWALK_RET_NOP;
+ }
+ RemapCallbackUserData *user_data = (RemapCallbackUserData *)user_data_v;
+ const Depsgraph *depsgraph = user_data->depsgraph;
+ ID *id_orig = *id_p;
+ if (check_datablocks_copy_on_writable(id_orig)) {
+ ID *id_cow;
+ if (user_data->create_placeholders) {
+ /* Special workaround to stop creating temp datablocks for
+ * objects which are coming from scene's collection and which
+ * are never linked to any of layers.
+ *
+ * TODO(sergey): Ideally we need to tell ID looper to ignore
+ * those or at least make it more reliable check where the
+ * pointer is coming from. */
+ const ID_Type id_type = GS(id_orig->name);
+ const ID_Type id_type_self = GS(id_self->name);
+ if (id_type == ID_OB && id_type_self == ID_SCE) {
+ IDNode *id_node = depsgraph->find_id_node(id_orig);
+ if (id_node == NULL) {
+ id_cow = id_orig;
+ }
+ else {
+ id_cow = id_node->id_cow;
+ }
+ }
+ else {
+ id_cow = user_data->node_builder->ensure_cow_id(id_orig);
+ }
+ }
+ else {
+ id_cow = depsgraph->get_cow_id(id_orig);
+ }
+ BLI_assert(id_cow != NULL);
+ DEG_COW_PRINT(
+ " Remapping datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
+ *id_p = id_cow;
+ }
+ return IDWALK_RET_NOP;
}
void update_armature_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
- const ID *id_orig, ID *id_cow)
+ const ID *id_orig,
+ ID *id_cow)
{
- const bArmature *armature_orig = (const bArmature *)id_orig;
- bArmature *armature_cow = (bArmature *)id_cow;
- armature_cow->edbo = armature_orig->edbo;
+ const bArmature *armature_orig = (const bArmature *)id_orig;
+ bArmature *armature_cow = (bArmature *)id_cow;
+ armature_cow->edbo = armature_orig->edbo;
}
void update_curve_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
- const ID *id_orig, ID *id_cow)
+ const ID *id_orig,
+ ID *id_cow)
{
- const Curve *curve_orig = (const Curve *)id_orig;
- Curve *curve_cow = (Curve *)id_cow;
- curve_cow->editnurb = curve_orig->editnurb;
- curve_cow->editfont = curve_orig->editfont;
+ const Curve *curve_orig = (const Curve *)id_orig;
+ Curve *curve_cow = (Curve *)id_cow;
+ curve_cow->editnurb = curve_orig->editnurb;
+ curve_cow->editfont = curve_orig->editfont;
}
void update_mball_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
- const ID *id_orig, ID *id_cow)
+ const ID *id_orig,
+ ID *id_cow)
{
- const MetaBall *mball_orig = (const MetaBall *)id_orig;
- MetaBall *mball_cow = (MetaBall *)id_cow;
- mball_cow->editelems = mball_orig->editelems;
+ const MetaBall *mball_orig = (const MetaBall *)id_orig;
+ MetaBall *mball_cow = (MetaBall *)id_cow;
+ mball_cow->editelems = mball_orig->editelems;
}
void update_lattice_edit_mode_pointers(const Depsgraph * /*depsgraph*/,
- const ID *id_orig, ID *id_cow)
+ const ID *id_orig,
+ ID *id_cow)
{
- const Lattice *lt_orig = (const Lattice *)id_orig;
- Lattice *lt_cow = (Lattice *)id_cow;
- lt_cow->editlatt = lt_orig->editlatt;
+ const Lattice *lt_orig = (const Lattice *)id_orig;
+ Lattice *lt_cow = (Lattice *)id_cow;
+ lt_cow->editlatt = lt_orig->editlatt;
}
-void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph,
- const ID *id_orig, ID *id_cow)
+void update_mesh_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
{
- /* For meshes we need to update edit_mesh to make it to point
- * to the CoW version of object.
- *
- * This is kind of confusing, because actual bmesh is not owned by
- * the CoW object, so need to be accurate about using link from
- * edit_mesh to object. */
- const Mesh *mesh_orig = (const Mesh *)id_orig;
- Mesh *mesh_cow = (Mesh *)id_cow;
- if (mesh_orig->edit_mesh == NULL) {
- return;
- }
- mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh);
- mesh_cow->edit_mesh->ob =
- (Object *)depsgraph->get_cow_id(&mesh_orig->edit_mesh->ob->id);
- mesh_cow->edit_mesh->mesh_eval_cage = NULL;
- mesh_cow->edit_mesh->mesh_eval_final = NULL;
+ /* For meshes we need to update edit_mesh to make it to point
+ * to the CoW version of object.
+ *
+ * This is kind of confusing, because actual bmesh is not owned by
+ * the CoW object, so need to be accurate about using link from
+ * edit_mesh to object. */
+ const Mesh *mesh_orig = (const Mesh *)id_orig;
+ Mesh *mesh_cow = (Mesh *)id_cow;
+ if (mesh_orig->edit_mesh == NULL) {
+ return;
+ }
+ mesh_cow->edit_mesh = (BMEditMesh *)MEM_dupallocN(mesh_orig->edit_mesh);
+ mesh_cow->edit_mesh->ob = (Object *)depsgraph->get_cow_id(&mesh_orig->edit_mesh->ob->id);
+ mesh_cow->edit_mesh->mesh_eval_cage = NULL;
+ mesh_cow->edit_mesh->mesh_eval_final = NULL;
}
/* Edit data is stored and owned by original datablocks, copied ones
* are simply referencing to them. */
-void update_edit_mode_pointers(const Depsgraph *depsgraph,
- const ID *id_orig, ID *id_cow)
+void update_edit_mode_pointers(const Depsgraph *depsgraph, const ID *id_orig, ID *id_cow)
{
- const ID_Type type = GS(id_orig->name);
- switch (type) {
- case ID_AR:
- update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
- break;
- case ID_ME:
- update_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow);
- break;
- case ID_CU:
- update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
- break;
- case ID_MB:
- update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow);
- break;
- case ID_LT:
- update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow);
- break;
- default:
- break;
- }
+ const ID_Type type = GS(id_orig->name);
+ switch (type) {
+ case ID_AR:
+ update_armature_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ break;
+ case ID_ME:
+ update_mesh_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ break;
+ case ID_CU:
+ update_curve_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ break;
+ case ID_MB:
+ update_mball_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ break;
+ case ID_LT:
+ update_lattice_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ break;
+ default:
+ break;
+ }
}
-template <typename T>
+template<typename T>
void update_list_orig_pointers(const ListBase *listbase_orig,
ListBase *listbase,
T *T::*orig_field)
{
- T *element_orig = reinterpret_cast<T*>(listbase_orig->first);
- T *element_cow = reinterpret_cast<T*>(listbase->first);
- while (element_orig != NULL) {
- element_cow->*orig_field = element_orig;
- element_cow = element_cow->next;
- element_orig = element_orig->next;
- }
+ T *element_orig = reinterpret_cast<T *>(listbase_orig->first);
+ T *element_cow = reinterpret_cast<T *>(listbase->first);
+ while (element_orig != NULL) {
+ element_cow->*orig_field = element_orig;
+ element_cow = element_cow->next;
+ element_orig = element_orig->next;
+ }
}
-void update_particle_system_orig_pointers(const Object *object_orig,
- Object *object_cow)
+void update_particle_system_orig_pointers(const Object *object_orig, Object *object_cow)
{
- update_list_orig_pointers(&object_orig->particlesystem,
- &object_cow->particlesystem,
- &ParticleSystem::orig_psys);
+ update_list_orig_pointers(
+ &object_orig->particlesystem, &object_cow->particlesystem, &ParticleSystem::orig_psys);
}
void set_particle_system_modifiers_loaded(Object *object_cow)
{
- LISTBASE_FOREACH(ModifierData *, md, &object_cow->modifiers) {
- if (md->type != eModifierType_ParticleSystem) {
- continue;
- }
- ParticleSystemModifierData *psmd =
- reinterpret_cast<ParticleSystemModifierData*>(md);
- psmd->flag |= eParticleSystemFlag_file_loaded;
- }
+ LISTBASE_FOREACH (ModifierData *, md, &object_cow->modifiers) {
+ if (md->type != eModifierType_ParticleSystem) {
+ continue;
+ }
+ ParticleSystemModifierData *psmd = reinterpret_cast<ParticleSystemModifierData *>(md);
+ psmd->flag |= eParticleSystemFlag_file_loaded;
+ }
}
void update_particles_after_copy(const Object *object_orig, Object *object_cow)
{
- update_particle_system_orig_pointers(object_orig, object_cow);
- set_particle_system_modifiers_loaded(object_cow);
+ update_particle_system_orig_pointers(object_orig, object_cow);
+ set_particle_system_modifiers_loaded(object_cow);
}
void update_pose_orig_pointers(const bPose *pose_orig, bPose *pose_cow)
{
- update_list_orig_pointers(&pose_orig->chanbase,
- &pose_cow->chanbase,
- &bPoseChannel::orig_pchan);
+ update_list_orig_pointers(&pose_orig->chanbase, &pose_cow->chanbase, &bPoseChannel::orig_pchan);
}
-void update_modifiers_orig_pointers(const Object *object_orig,
- Object *object_cow)
+void update_modifiers_orig_pointers(const Object *object_orig, Object *object_cow)
{
- update_list_orig_pointers(&object_orig->modifiers,
- &object_cow->modifiers,
- &ModifierData::orig_modifier_data);
+ update_list_orig_pointers(
+ &object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data);
}
/* Do some special treatment of data transfer from original ID to it's
@@ -674,50 +640,47 @@ void update_modifiers_orig_pointers(const Object *object_orig,
* Only use for the newly created CoW datablocks. */
void update_id_after_copy(const Depsgraph *depsgraph,
const IDNode *id_node,
- const ID *id_orig, ID *id_cow)
+ const ID *id_orig,
+ ID *id_cow)
{
- const ID_Type type = GS(id_orig->name);
- switch (type) {
- case ID_OB:
- {
- /* Ensure we don't drag someone's else derived mesh to the
- * new copy of the object. */
- Object *object_cow = (Object *)id_cow;
- const Object *object_orig = (const Object *)id_orig;
- object_cow->mode = object_orig->mode;
- object_cow->sculpt = object_orig->sculpt;
- if (object_cow->type == OB_MESH) {
- object_cow->runtime.mesh_orig = (Mesh *)object_cow->data;
- }
- if (object_cow->type == OB_ARMATURE) {
- const bArmature *armature_orig = (bArmature *)object_orig->data;
- bArmature *armature_cow = (bArmature *)object_cow->data;
- BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
- if (armature_orig->edbo == NULL) {
- update_pose_orig_pointers(object_orig->pose,
- object_cow->pose);
- }
- BKE_pose_pchan_index_rebuild(object_cow->pose);
- }
- update_particles_after_copy(object_orig, object_cow);
- update_modifiers_orig_pointers(object_orig, object_cow);
- break;
- }
- case ID_SCE:
- {
- Scene *scene_cow = (Scene *)id_cow;
- const Scene *scene_orig = (const Scene *)id_orig;
- scene_cow->toolsettings = scene_orig->toolsettings;
- scene_cow->eevee.light_cache = scene_orig->eevee.light_cache;
- scene_setup_view_layers_after_remap(
- depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
- break;
- }
- default:
- break;
- }
- update_edit_mode_pointers(depsgraph, id_orig, id_cow);
- BKE_animsys_update_driver_array(id_cow);
+ const ID_Type type = GS(id_orig->name);
+ switch (type) {
+ case ID_OB: {
+ /* Ensure we don't drag someone's else derived mesh to the
+ * new copy of the object. */
+ Object *object_cow = (Object *)id_cow;
+ const Object *object_orig = (const Object *)id_orig;
+ object_cow->mode = object_orig->mode;
+ object_cow->sculpt = object_orig->sculpt;
+ if (object_cow->type == OB_MESH) {
+ object_cow->runtime.mesh_orig = (Mesh *)object_cow->data;
+ }
+ if (object_cow->type == OB_ARMATURE) {
+ const bArmature *armature_orig = (bArmature *)object_orig->data;
+ bArmature *armature_cow = (bArmature *)object_cow->data;
+ BKE_pose_remap_bone_pointers(armature_cow, object_cow->pose);
+ if (armature_orig->edbo == NULL) {
+ update_pose_orig_pointers(object_orig->pose, object_cow->pose);
+ }
+ BKE_pose_pchan_index_rebuild(object_cow->pose);
+ }
+ update_particles_after_copy(object_orig, object_cow);
+ update_modifiers_orig_pointers(object_orig, object_cow);
+ break;
+ }
+ case ID_SCE: {
+ Scene *scene_cow = (Scene *)id_cow;
+ const Scene *scene_orig = (const Scene *)id_orig;
+ scene_cow->toolsettings = scene_orig->toolsettings;
+ scene_cow->eevee.light_cache = scene_orig->eevee.light_cache;
+ scene_setup_view_layers_after_remap(depsgraph, id_node, reinterpret_cast<Scene *>(id_cow));
+ break;
+ }
+ default:
+ break;
+ }
+ update_edit_mode_pointers(depsgraph, id_orig, id_cow);
+ BKE_animsys_update_driver_array(id_cow);
}
/* This callback is used to validate that all nested ID datablocks are
@@ -727,14 +690,14 @@ int foreach_libblock_validate_callback(void *user_data,
ID **id_p,
int /*cb_flag*/)
{
- ValidateData *data = (ValidateData *)user_data;
- if (*id_p != NULL) {
- if (!check_datablock_expanded(*id_p)) {
- data->is_valid = false;
- /* TODO(sergey): Store which is is not valid? */
- }
- }
- return IDWALK_RET_NOP;
+ ValidateData *data = (ValidateData *)user_data;
+ if (*id_p != NULL) {
+ if (!check_datablock_expanded(*id_p)) {
+ data->is_valid = false;
+ /* TODO(sergey): Store which is is not valid? */
+ }
+ }
+ return IDWALK_RET_NOP;
}
} // namespace
@@ -748,90 +711,84 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
DepsgraphNodeBuilder *node_builder,
bool create_placeholders)
{
- const ID *id_orig = id_node->id_orig;
- ID *id_cow = id_node->id_cow;
- const int id_cow_recalc = id_cow->recalc;
- /* No need to expand such datablocks, their copied ID is same as original
- * one already. */
- if (!deg_copy_on_write_is_needed(id_orig)) {
- return id_cow;
- }
- DEG_COW_PRINT("Expanding datablock for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- /* Sanity checks. */
- /* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
- * rebuilding dependencies. */
- if (check_datablock_expanded(id_cow) && create_placeholders) {
- deg_free_copy_on_write_datablock(id_cow);
- }
- // BLI_assert(check_datablock_expanded(id_cow) == false);
- /* Copy data from original ID to a copied version. */
- /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
- * original geometry arrays for until those are modified. */
- /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
- * just to be able to use existing API. Ideally we need to replace this with
- * in-place copy from existing datablock to a prepared memory.
- *
- * NOTE: We don't use BKE_main_{new,free} because:
- * - We don't want heap-allocations here.
- * - We don't want bmain's content to be freed when main is freed. */
- bool done = false;
- /* First we handle special cases which are not covered by BKE_id_copy() yet.
- * or cases where we want to do something smarter than simple datablock
- * copy. */
- const ID_Type id_type = GS(id_orig->name);
- switch (id_type) {
- case ID_SCE:
- {
- done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
- if (done) {
- /* NOTE: This is important to do before remap, because this
- * function will make it so less IDs are to be remapped. */
- scene_setup_view_layers_before_remap(
- depsgraph, id_node, (Scene *)id_cow);
- }
- break;
- }
- case ID_ME:
- {
- /* TODO(sergey): Ideally we want to handle meshes in a special
- * manner here to avoid initial copy of all the geometry arrays. */
- break;
- }
- default:
- break;
- }
- if (!done) {
- done = id_copy_inplace_no_main(id_orig, id_cow);
- }
- if (!done) {
- BLI_assert(!"No idea how to perform CoW on datablock");
- }
- /* Update pointers to nested ID datablocks. */
- DEG_COW_PRINT(" Remapping ID links for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
+ const ID *id_orig = id_node->id_orig;
+ ID *id_cow = id_node->id_cow;
+ const int id_cow_recalc = id_cow->recalc;
+ /* No need to expand such datablocks, their copied ID is same as original
+ * one already. */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return id_cow;
+ }
+ DEG_COW_PRINT(
+ "Expanding datablock for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
+ /* Sanity checks. */
+ /* NOTE: Disabled for now, conflicts when re-using evaluated datablock when
+ * rebuilding dependencies. */
+ if (check_datablock_expanded(id_cow) && create_placeholders) {
+ deg_free_copy_on_write_datablock(id_cow);
+ }
+ // BLI_assert(check_datablock_expanded(id_cow) == false);
+ /* Copy data from original ID to a copied version. */
+ /* TODO(sergey): Avoid doing full ID copy somehow, make Mesh to reference
+ * original geometry arrays for until those are modified. */
+ /* TODO(sergey): We do some trickery with temp bmain and extra ID pointer
+ * just to be able to use existing API. Ideally we need to replace this with
+ * in-place copy from existing datablock to a prepared memory.
+ *
+ * NOTE: We don't use BKE_main_{new,free} because:
+ * - We don't want heap-allocations here.
+ * - We don't want bmain's content to be freed when main is freed. */
+ bool done = false;
+ /* First we handle special cases which are not covered by BKE_id_copy() yet.
+ * or cases where we want to do something smarter than simple datablock
+ * copy. */
+ const ID_Type id_type = GS(id_orig->name);
+ switch (id_type) {
+ case ID_SCE: {
+ done = scene_copy_inplace_no_main((Scene *)id_orig, (Scene *)id_cow);
+ if (done) {
+ /* NOTE: This is important to do before remap, because this
+ * function will make it so less IDs are to be remapped. */
+ scene_setup_view_layers_before_remap(depsgraph, id_node, (Scene *)id_cow);
+ }
+ break;
+ }
+ case ID_ME: {
+ /* TODO(sergey): Ideally we want to handle meshes in a special
+ * manner here to avoid initial copy of all the geometry arrays. */
+ break;
+ }
+ default:
+ break;
+ }
+ if (!done) {
+ done = id_copy_inplace_no_main(id_orig, id_cow);
+ }
+ if (!done) {
+ BLI_assert(!"No idea how to perform CoW on datablock");
+ }
+ /* Update pointers to nested ID datablocks. */
+ DEG_COW_PRINT(
+ " Remapping ID links for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
#ifdef NESTED_ID_NASTY_WORKAROUND
- ntree_hack_remap_pointers(depsgraph, id_cow);
+ ntree_hack_remap_pointers(depsgraph, id_cow);
#endif
- /* Do it now, so remapping will understand that possibly remapped self ID
- * is not to be remapped again. */
- deg_tag_copy_on_write_id(id_cow, id_orig);
- /* Perform remapping of the nodes. */
- RemapCallbackUserData user_data = {NULL};
- user_data.depsgraph = depsgraph;
- user_data.node_builder = node_builder;
- user_data.create_placeholders = create_placeholders;
- BKE_library_foreach_ID_link(NULL,
- id_cow,
- foreach_libblock_remap_callback,
- (void *)&user_data,
- IDWALK_NOP);
- /* Correct or tweak some pointers which are not taken care by foreach
- * from above. */
- update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
- id_cow->recalc = id_orig->recalc | id_cow_recalc;
- return id_cow;
+ /* Do it now, so remapping will understand that possibly remapped self ID
+ * is not to be remapped again. */
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ /* Perform remapping of the nodes. */
+ RemapCallbackUserData user_data = {NULL};
+ user_data.depsgraph = depsgraph;
+ user_data.node_builder = node_builder;
+ user_data.create_placeholders = create_placeholders;
+ BKE_library_foreach_ID_link(
+ NULL, id_cow, foreach_libblock_remap_callback, (void *)&user_data, IDWALK_NOP);
+ /* Correct or tweak some pointers which are not taken care by foreach
+ * from above. */
+ update_id_after_copy(depsgraph, id_node, id_orig, id_cow);
+ id_cow->recalc = id_orig->recalc | id_cow_recalc;
+ return id_cow;
}
/* NOTE: Depsgraph is supposed to have ID node already. */
@@ -840,12 +797,9 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
DepsgraphNodeBuilder *node_builder,
bool create_placeholders)
{
- DEG::IDNode *id_node = depsgraph->find_id_node(id_orig);
- BLI_assert(id_node != NULL);
- return deg_expand_copy_on_write_datablock(depsgraph,
- id_node,
- node_builder,
- create_placeholders);
+ DEG::IDNode *id_node = depsgraph->find_id_node(id_orig);
+ BLI_assert(id_node != NULL);
+ return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders);
}
namespace {
@@ -859,323 +813,315 @@ namespace {
* By adding type into matching we are at least ensuring that modifier will not
* try to interpret runtime data created by another modifier type. */
class ModifierDataBackupID {
-public:
- ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None)
- {
- }
-
- ModifierDataBackupID(ModifierData *modifier_data, ModifierType type)
- : modifier_data(modifier_data),
- type(type)
- {
- }
-
- bool operator <(const ModifierDataBackupID& other) const {
- if (modifier_data < other.modifier_data) {
- return true;
- }
- if (modifier_data == other.modifier_data) {
- return static_cast<int>(type) < static_cast<int>(other.type);
- }
- return false;
- }
-
- ModifierData *modifier_data;
- ModifierType type;
+ public:
+ ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None)
+ {
+ }
+
+ ModifierDataBackupID(ModifierData *modifier_data, ModifierType type)
+ : modifier_data(modifier_data), type(type)
+ {
+ }
+
+ bool operator<(const ModifierDataBackupID &other) const
+ {
+ if (modifier_data < other.modifier_data) {
+ return true;
+ }
+ if (modifier_data == other.modifier_data) {
+ return static_cast<int>(type) < static_cast<int>(other.type);
+ }
+ return false;
+ }
+
+ ModifierData *modifier_data;
+ ModifierType type;
};
/* Storage for backed up runtime modifier data. */
-typedef map<ModifierDataBackupID, void*> ModifierRuntimeDataBackup;
+typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
struct ObjectRuntimeBackup {
- ObjectRuntimeBackup()
- : base_flag(0),
- base_local_view_bits(0)
- {
- /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
- memset(&runtime, 0, sizeof(runtime));
- }
-
- /* Make a backup of object's evaluation runtime data, additionally
- * make object to be safe for free without invalidating backed up
- * pointers. */
- void init_from_object(Object *object);
- void backup_modifier_runtime_data(Object *object);
-
- /* Restore all fields to the given object. */
- void restore_to_object(Object *object);
- /* NOTE: Will free all runtime data which has not been restored. */
- void restore_modifier_runtime_data(Object *object);
-
- Object_Runtime runtime;
- short base_flag;
- unsigned short base_local_view_bits;
- ModifierRuntimeDataBackup modifier_runtime_data;
+ ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0)
+ {
+ /* TODO(sergey): Use something like BKE_object_runtime_reset(). */
+ memset(&runtime, 0, sizeof(runtime));
+ }
+
+ /* Make a backup of object's evaluation runtime data, additionally
+ * make object to be safe for free without invalidating backed up
+ * pointers. */
+ void init_from_object(Object *object);
+ void backup_modifier_runtime_data(Object *object);
+
+ /* Restore all fields to the given object. */
+ void restore_to_object(Object *object);
+ /* NOTE: Will free all runtime data which has not been restored. */
+ void restore_modifier_runtime_data(Object *object);
+
+ Object_Runtime runtime;
+ short base_flag;
+ unsigned short base_local_view_bits;
+ ModifierRuntimeDataBackup modifier_runtime_data;
};
void ObjectRuntimeBackup::init_from_object(Object *object)
{
- /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
- Mesh *mesh_eval = object->runtime.mesh_eval;
- runtime = object->runtime;
- BKE_object_runtime_reset(object);
- /* Keep bbox (for now at least). */
- object->runtime.bb = runtime.bb;
- /* Object update will override actual object->data to an evaluated version.
- * Need to make sure we don't have data set to evaluated one before free
- * anything. */
- if (mesh_eval != NULL && object->data == mesh_eval) {
- object->data = runtime.mesh_orig;
- }
- /* Make a backup of base flags. */
- base_flag = object->base_flag;
- base_local_view_bits = object->base_local_view_bits;
- /* Backup tuntime data of all modifiers. */
- backup_modifier_runtime_data(object);
+ /* Store evaluated mesh and curve_cache, and make sure we don't free it. */
+ Mesh *mesh_eval = object->runtime.mesh_eval;
+ runtime = object->runtime;
+ BKE_object_runtime_reset(object);
+ /* Keep bbox (for now at least). */
+ object->runtime.bb = runtime.bb;
+ /* Object update will override actual object->data to an evaluated version.
+ * Need to make sure we don't have data set to evaluated one before free
+ * anything. */
+ if (mesh_eval != NULL && object->data == mesh_eval) {
+ object->data = runtime.mesh_orig;
+ }
+ /* Make a backup of base flags. */
+ base_flag = object->base_flag;
+ base_local_view_bits = object->base_local_view_bits;
+ /* Backup tuntime data of all modifiers. */
+ backup_modifier_runtime_data(object);
}
-inline ModifierDataBackupID create_modifier_data_id(
- const ModifierData *modifier_data)
+inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data)
{
- return ModifierDataBackupID(modifier_data->orig_modifier_data,
- static_cast<ModifierType>(modifier_data->type));
+ return ModifierDataBackupID(modifier_data->orig_modifier_data,
+ static_cast<ModifierType>(modifier_data->type));
}
void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
{
- LISTBASE_FOREACH(ModifierData *, modifier_data, &object->modifiers) {
- if (modifier_data->runtime == NULL) {
- continue;
- }
- BLI_assert(modifier_data->orig_modifier_data != NULL);
- ModifierDataBackupID modifier_data_id =
- create_modifier_data_id(modifier_data);
- modifier_runtime_data.insert(
- make_pair(modifier_data_id, modifier_data->runtime));
- modifier_data->runtime = NULL;
- }
+ LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
+ if (modifier_data->runtime == NULL) {
+ continue;
+ }
+ BLI_assert(modifier_data->orig_modifier_data != NULL);
+ ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
+ modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime));
+ modifier_data->runtime = NULL;
+ }
}
void ObjectRuntimeBackup::restore_to_object(Object *object)
{
- Mesh *mesh_orig = object->runtime.mesh_orig;
- BoundBox *bb = object->runtime.bb;
- object->runtime = runtime;
- object->runtime.mesh_orig = mesh_orig;
- object->runtime.bb = bb;
- if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
- if (object->id.recalc & ID_RECALC_GEOMETRY) {
- /* If geometry is tagged for update it means, that part of
- * evaluated mesh are not valid anymore. In this case we can not
- * have any "persistent" pointers to point to an invalid data.
- *
- * We restore object's data datablock to an original copy of
- * that datablock. */
- object->data = mesh_orig;
-
- /* After that, immediately free the invalidated caches. */
- BKE_object_free_derived_caches(object);
- }
- else {
- Mesh *mesh_eval = object->runtime.mesh_eval;
- /* Do same thing as object update: override actual object data
- * pointer with evaluated datablock. */
- object->data = mesh_eval;
- /* Evaluated mesh simply copied edit_mesh pointer from
- * original mesh during update, need to make sure no dead
- * pointers are left behind. */
- mesh_eval->edit_mesh = mesh_orig->edit_mesh;
- }
- }
- object->base_flag = base_flag;
- object->base_local_view_bits = base_local_view_bits;
- /* Restore modifier's runtime data.
- * NOTE: Data of unused modifiers will be freed there. */
- restore_modifier_runtime_data(object);
+ Mesh *mesh_orig = object->runtime.mesh_orig;
+ BoundBox *bb = object->runtime.bb;
+ object->runtime = runtime;
+ object->runtime.mesh_orig = mesh_orig;
+ object->runtime.bb = bb;
+ if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
+ if (object->id.recalc & ID_RECALC_GEOMETRY) {
+ /* If geometry is tagged for update it means, that part of
+ * evaluated mesh are not valid anymore. In this case we can not
+ * have any "persistent" pointers to point to an invalid data.
+ *
+ * We restore object's data datablock to an original copy of
+ * that datablock. */
+ object->data = mesh_orig;
+
+ /* After that, immediately free the invalidated caches. */
+ BKE_object_free_derived_caches(object);
+ }
+ else {
+ Mesh *mesh_eval = object->runtime.mesh_eval;
+ /* Do same thing as object update: override actual object data
+ * pointer with evaluated datablock. */
+ object->data = mesh_eval;
+ /* Evaluated mesh simply copied edit_mesh pointer from
+ * original mesh during update, need to make sure no dead
+ * pointers are left behind. */
+ mesh_eval->edit_mesh = mesh_orig->edit_mesh;
+ }
+ }
+ object->base_flag = base_flag;
+ object->base_local_view_bits = base_local_view_bits;
+ /* Restore modifier's runtime data.
+ * NOTE: Data of unused modifiers will be freed there. */
+ restore_modifier_runtime_data(object);
}
void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
{
- LISTBASE_FOREACH(ModifierData *, modifier_data, &object->modifiers) {
- BLI_assert(modifier_data->orig_modifier_data != NULL);
- ModifierDataBackupID modifier_data_id =
- create_modifier_data_id(modifier_data);
- ModifierRuntimeDataBackup::iterator runtime_data_iterator =
- modifier_runtime_data.find(modifier_data_id);
- if (runtime_data_iterator != modifier_runtime_data.end()) {
- modifier_data->runtime = runtime_data_iterator->second;
- runtime_data_iterator->second = NULL;
- }
- }
- for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) {
- const ModifierDataBackupID modifier_data_id = value.first;
- void *runtime = value.second;
- if (value.second == NULL) {
- continue;
- }
- const ModifierTypeInfo *modifier_type_info =
- modifierType_getInfo(modifier_data_id.type);
- BLI_assert(modifier_type_info != NULL);
- modifier_type_info->freeRuntimeData(runtime);
- }
+ LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
+ BLI_assert(modifier_data->orig_modifier_data != NULL);
+ ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
+ ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find(
+ modifier_data_id);
+ if (runtime_data_iterator != modifier_runtime_data.end()) {
+ modifier_data->runtime = runtime_data_iterator->second;
+ runtime_data_iterator->second = NULL;
+ }
+ }
+ for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) {
+ const ModifierDataBackupID modifier_data_id = value.first;
+ void *runtime = value.second;
+ if (value.second == NULL) {
+ continue;
+ }
+ const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type);
+ BLI_assert(modifier_type_info != NULL);
+ modifier_type_info->freeRuntimeData(runtime);
+ }
}
class RuntimeBackup {
-public:
- RuntimeBackup() : drawdata_ptr(NULL) {
- drawdata_backup.first = drawdata_backup.last = NULL;
- }
+ public:
+ RuntimeBackup() : drawdata_ptr(NULL)
+ {
+ drawdata_backup.first = drawdata_backup.last = NULL;
+ }
- /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */
- void init_from_id(ID *id);
+ /* NOTE: Will reset all runbtime fields which has been backed up to NULL. */
+ void init_from_id(ID *id);
- /* Restore fields to the given ID. */
- void restore_to_id(ID *id);
+ /* Restore fields to the given ID. */
+ void restore_to_id(ID *id);
- ObjectRuntimeBackup object_backup;
- DrawDataList drawdata_backup;
- DrawDataList *drawdata_ptr;
+ ObjectRuntimeBackup object_backup;
+ DrawDataList drawdata_backup;
+ DrawDataList *drawdata_ptr;
};
void RuntimeBackup::init_from_id(ID *id)
{
- if (!check_datablock_expanded(id)) {
- return;
- }
- const ID_Type id_type = GS(id->name);
- switch (id_type) {
- case ID_OB:
- object_backup.init_from_object(reinterpret_cast<Object*>(id));
- break;
- default:
- break;
- }
- /* Note that we never free GPU draw data from here since that's not
- * safe for threading and draw data is likely to be re-used. */
- drawdata_ptr = DRW_drawdatalist_from_id(id);
- if (drawdata_ptr != NULL) {
- drawdata_backup = *drawdata_ptr;
- drawdata_ptr->first = drawdata_ptr->last = NULL;
- }
+ if (!check_datablock_expanded(id)) {
+ return;
+ }
+ const ID_Type id_type = GS(id->name);
+ switch (id_type) {
+ case ID_OB:
+ object_backup.init_from_object(reinterpret_cast<Object *>(id));
+ break;
+ default:
+ break;
+ }
+ /* Note that we never free GPU draw data from here since that's not
+ * safe for threading and draw data is likely to be re-used. */
+ drawdata_ptr = DRW_drawdatalist_from_id(id);
+ if (drawdata_ptr != NULL) {
+ drawdata_backup = *drawdata_ptr;
+ drawdata_ptr->first = drawdata_ptr->last = NULL;
+ }
}
void RuntimeBackup::restore_to_id(ID *id)
{
- const ID_Type id_type = GS(id->name);
- switch (id_type) {
- case ID_OB:
- object_backup.restore_to_object(reinterpret_cast<Object*>(id));
- break;
- default:
- break;
- }
- if (drawdata_ptr != NULL) {
- *drawdata_ptr = drawdata_backup;
- }
+ const ID_Type id_type = GS(id->name);
+ switch (id_type) {
+ case ID_OB:
+ object_backup.restore_to_object(reinterpret_cast<Object *>(id));
+ break;
+ default:
+ break;
+ }
+ if (drawdata_ptr != NULL) {
+ *drawdata_ptr = drawdata_backup;
+ }
}
} // namespace
-ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
- const IDNode *id_node)
+ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
{
- const ID *id_orig = id_node->id_orig;
- ID *id_cow = id_node->id_cow;
- /* Similar to expansion, no need to do anything here. */
- if (!deg_copy_on_write_is_needed(id_orig)) {
- return id_cow;
- }
- RuntimeBackup backup;
- backup.init_from_id(id_cow);
- deg_free_copy_on_write_datablock(id_cow);
- deg_expand_copy_on_write_datablock(depsgraph, id_node);
- backup.restore_to_id(id_cow);
- return id_cow;
+ const ID *id_orig = id_node->id_orig;
+ ID *id_cow = id_node->id_cow;
+ /* Similar to expansion, no need to do anything here. */
+ if (!deg_copy_on_write_is_needed(id_orig)) {
+ return id_cow;
+ }
+ RuntimeBackup backup;
+ backup.init_from_id(id_cow);
+ deg_free_copy_on_write_datablock(id_cow);
+ deg_expand_copy_on_write_datablock(depsgraph, id_node);
+ backup.restore_to_id(id_cow);
+ return id_cow;
}
/* NOTE: Depsgraph is supposed to have ID node already. */
-ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph,
- ID *id_orig)
+ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, ID *id_orig)
{
- DEG::IDNode *id_node = depsgraph->find_id_node(id_orig);
- BLI_assert(id_node != NULL);
- return deg_update_copy_on_write_datablock(depsgraph, id_node);
+ DEG::IDNode *id_node = depsgraph->find_id_node(id_orig);
+ BLI_assert(id_node != NULL);
+ return deg_update_copy_on_write_datablock(depsgraph, id_node);
}
namespace {
void discard_armature_edit_mode_pointers(ID *id_cow)
{
- bArmature *armature_cow = (bArmature *)id_cow;
- armature_cow->edbo = NULL;
+ bArmature *armature_cow = (bArmature *)id_cow;
+ armature_cow->edbo = NULL;
}
void discard_curve_edit_mode_pointers(ID *id_cow)
{
- Curve *curve_cow = (Curve *)id_cow;
- curve_cow->editnurb = NULL;
- curve_cow->editfont = NULL;
+ Curve *curve_cow = (Curve *)id_cow;
+ curve_cow->editnurb = NULL;
+ curve_cow->editfont = NULL;
}
void discard_mball_edit_mode_pointers(ID *id_cow)
{
- MetaBall *mball_cow = (MetaBall *)id_cow;
- mball_cow->editelems = NULL;
+ MetaBall *mball_cow = (MetaBall *)id_cow;
+ mball_cow->editelems = NULL;
}
void discard_lattice_edit_mode_pointers(ID *id_cow)
{
- Lattice *lt_cow = (Lattice *)id_cow;
- lt_cow->editlatt = NULL;
+ Lattice *lt_cow = (Lattice *)id_cow;
+ lt_cow->editlatt = NULL;
}
void discard_mesh_edit_mode_pointers(ID *id_cow)
{
- Mesh *mesh_cow = (Mesh *)id_cow;
- if (mesh_cow->edit_mesh == NULL) {
- return;
- }
- BKE_editmesh_free_derivedmesh(mesh_cow->edit_mesh);
- MEM_freeN(mesh_cow->edit_mesh);
- mesh_cow->edit_mesh = NULL;
+ Mesh *mesh_cow = (Mesh *)id_cow;
+ if (mesh_cow->edit_mesh == NULL) {
+ return;
+ }
+ BKE_editmesh_free_derivedmesh(mesh_cow->edit_mesh);
+ MEM_freeN(mesh_cow->edit_mesh);
+ mesh_cow->edit_mesh = NULL;
}
void discard_scene_pointers(ID *id_cow)
{
- Scene *scene_cow = (Scene *)id_cow;
- scene_cow->toolsettings = NULL;
- scene_cow->eevee.light_cache = NULL;
+ Scene *scene_cow = (Scene *)id_cow;
+ scene_cow->toolsettings = NULL;
+ scene_cow->eevee.light_cache = NULL;
}
/* NULL-ify all edit mode pointers which points to data from
* original object. */
void discard_edit_mode_pointers(ID *id_cow)
{
- const ID_Type type = GS(id_cow->name);
- switch (type) {
- case ID_AR:
- discard_armature_edit_mode_pointers(id_cow);
- break;
- case ID_ME:
- discard_mesh_edit_mode_pointers(id_cow);
- break;
- case ID_CU:
- discard_curve_edit_mode_pointers(id_cow);
- break;
- case ID_MB:
- discard_mball_edit_mode_pointers(id_cow);
- break;
- case ID_LT:
- discard_lattice_edit_mode_pointers(id_cow);
- break;
- case ID_SCE:
- /* Not really edit mode but still needs to run before
- * BKE_libblock_free_datablock() */
- discard_scene_pointers(id_cow);
- break;
- default:
- break;
- }
+ const ID_Type type = GS(id_cow->name);
+ switch (type) {
+ case ID_AR:
+ discard_armature_edit_mode_pointers(id_cow);
+ break;
+ case ID_ME:
+ discard_mesh_edit_mode_pointers(id_cow);
+ break;
+ case ID_CU:
+ discard_curve_edit_mode_pointers(id_cow);
+ break;
+ case ID_MB:
+ discard_mball_edit_mode_pointers(id_cow);
+ break;
+ case ID_LT:
+ discard_lattice_edit_mode_pointers(id_cow);
+ break;
+ case ID_SCE:
+ /* Not really edit mode but still needs to run before
+ * BKE_libblock_free_datablock() */
+ discard_scene_pointers(id_cow);
+ break;
+ default:
+ break;
+ }
}
} // namespace
@@ -1186,83 +1132,77 @@ void discard_edit_mode_pointers(ID *id_cow)
* - Does not free datablock itself. */
void deg_free_copy_on_write_datablock(ID *id_cow)
{
- if (!check_datablock_expanded(id_cow)) {
- /* Actual content was never copied on top of CoW block, we have
- * nothing to free. */
- return;
- }
- const ID_Type type = GS(id_cow->name);
+ if (!check_datablock_expanded(id_cow)) {
+ /* Actual content was never copied on top of CoW block, we have
+ * nothing to free. */
+ return;
+ }
+ const ID_Type type = GS(id_cow->name);
#ifdef NESTED_ID_NASTY_WORKAROUND
- nested_id_hack_discard_pointers(id_cow);
+ nested_id_hack_discard_pointers(id_cow);
#endif
- switch (type) {
- case ID_OB:
- {
- /* TODO(sergey): This workaround is only to prevent free derived
- * caches from modifying object->data. This is currently happening
- * due to mesh/curve datablock boundbox tagging dirty. */
- Object *ob_cow = (Object *)id_cow;
- ob_cow->data = NULL;
- ob_cow->sculpt = NULL;
- break;
- }
- default:
- break;
- }
- discard_edit_mode_pointers(id_cow);
- BKE_libblock_free_datablock(id_cow, 0);
- BKE_libblock_free_data(id_cow, false);
- /* Signal datablock as not being expanded. */
- id_cow->name[0] = '\0';
+ switch (type) {
+ case ID_OB: {
+ /* TODO(sergey): This workaround is only to prevent free derived
+ * caches from modifying object->data. This is currently happening
+ * due to mesh/curve datablock boundbox tagging dirty. */
+ Object *ob_cow = (Object *)id_cow;
+ ob_cow->data = NULL;
+ ob_cow->sculpt = NULL;
+ break;
+ }
+ default:
+ break;
+ }
+ discard_edit_mode_pointers(id_cow);
+ BKE_libblock_free_datablock(id_cow, 0);
+ BKE_libblock_free_data(id_cow, false);
+ /* Signal datablock as not being expanded. */
+ id_cow->name[0] = '\0';
}
-void deg_evaluate_copy_on_write(struct ::Depsgraph *graph,
- const IDNode *id_node)
+void deg_evaluate_copy_on_write(struct ::Depsgraph *graph, const IDNode *id_node)
{
- const DEG::Depsgraph *depsgraph = reinterpret_cast<const DEG::Depsgraph *>(graph);
- DEG_debug_print_eval(graph, __func__, id_node->id_orig->name, id_node->id_cow);
- if (id_node->id_orig == &depsgraph->scene->id) {
- /* NOTE: This is handled by eval_ctx setup routines, which
- * ensures scene and view layer pointers are valid. */
- return;
- }
- deg_update_copy_on_write_datablock(depsgraph, id_node);
+ const DEG::Depsgraph *depsgraph = reinterpret_cast<const DEG::Depsgraph *>(graph);
+ DEG_debug_print_eval(graph, __func__, id_node->id_orig->name, id_node->id_cow);
+ if (id_node->id_orig == &depsgraph->scene->id) {
+ /* NOTE: This is handled by eval_ctx setup routines, which
+ * ensures scene and view layer pointers are valid. */
+ return;
+ }
+ deg_update_copy_on_write_datablock(depsgraph, id_node);
}
bool deg_validate_copy_on_write_datablock(ID *id_cow)
{
- if (id_cow == NULL) {
- return false;
- }
- ValidateData data;
- data.is_valid = true;
- BKE_library_foreach_ID_link(NULL,
- id_cow,
- foreach_libblock_validate_callback,
- &data,
- IDWALK_NOP);
- return data.is_valid;
+ if (id_cow == NULL) {
+ return false;
+ }
+ ValidateData data;
+ data.is_valid = true;
+ BKE_library_foreach_ID_link(NULL, id_cow, foreach_libblock_validate_callback, &data, IDWALK_NOP);
+ return data.is_valid;
}
void deg_tag_copy_on_write_id(ID *id_cow, const ID *id_orig)
{
- BLI_assert(id_cow != id_orig);
- BLI_assert((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
- id_cow->tag |= LIB_TAG_COPIED_ON_WRITE;
- /* This ID is no longer localized, is a self-sustaining copy now. */
- id_cow->tag &= ~LIB_TAG_LOCALIZED;
- id_cow->orig_id = (ID *)id_orig;
+ BLI_assert(id_cow != id_orig);
+ BLI_assert((id_orig->tag & LIB_TAG_COPIED_ON_WRITE) == 0);
+ id_cow->tag |= LIB_TAG_COPIED_ON_WRITE;
+ /* This ID is no longer localized, is a self-sustaining copy now. */
+ id_cow->tag &= ~LIB_TAG_LOCALIZED;
+ id_cow->orig_id = (ID *)id_orig;
}
bool deg_copy_on_write_is_expanded(const ID *id_cow)
{
- return check_datablock_expanded(id_cow);
+ return check_datablock_expanded(id_cow);
}
bool deg_copy_on_write_is_needed(const ID *id_orig)
{
- const ID_Type id_type = GS(id_orig->name);
- return !ELEM(id_type, ID_IM);
+ const ID_Type id_type = GS(id_orig->name);
+ return !ELEM(id_type, ID_IM);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
index 6f9141a7c19..c913bb0f3f2 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.h
@@ -62,10 +62,8 @@ ID *deg_expand_copy_on_write_datablock(const struct Depsgraph *depsgraph,
/* Makes sure given CoW datablock is brought back to state of the original
* datablock.
*/
-ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph,
- const IDNode *id_node);
-ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph,
- struct ID *id_orig);
+ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph, const IDNode *id_node);
+ID *deg_update_copy_on_write_datablock(const struct Depsgraph *depsgraph, struct ID *id_orig);
/* Helper function which frees memory used by copy-on-written databnlock. */
void deg_free_copy_on_write_datablock(struct ID *id_cow);
@@ -73,8 +71,7 @@ void deg_free_copy_on_write_datablock(struct ID *id_cow);
/* Callback function for depsgraph operation node which ensures copy-on-write
* datablock is ready for use by further evaluation routines.
*/
-void deg_evaluate_copy_on_write(struct ::Depsgraph *depsgraph,
- const struct IDNode *id_node);
+void deg_evaluate_copy_on_write(struct ::Depsgraph *depsgraph, const struct IDNode *id_node);
/* Check that given ID is properly expanded and does not have any shallow
* copies inside.
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
index 08c7b87d5e3..0bd5b3b4f82 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc
@@ -70,83 +70,75 @@ extern "C" {
namespace DEG {
enum {
- ID_STATE_NONE = 0,
- ID_STATE_MODIFIED = 1,
+ ID_STATE_NONE = 0,
+ ID_STATE_MODIFIED = 1,
};
enum {
- COMPONENT_STATE_NONE = 0,
- COMPONENT_STATE_SCHEDULED = 1,
- COMPONENT_STATE_DONE = 2,
+ COMPONENT_STATE_NONE = 0,
+ COMPONENT_STATE_SCHEDULED = 1,
+ COMPONENT_STATE_DONE = 2,
};
typedef std::deque<OperationNode *> FlushQueue;
namespace {
-void flush_init_operation_node_func(
- void *__restrict data_v,
- const int i,
- const ParallelRangeTLS *__restrict /*tls*/)
+void flush_init_operation_node_func(void *__restrict data_v,
+ const int i,
+ const ParallelRangeTLS *__restrict /*tls*/)
{
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationNode *node = graph->operations[i];
- node->scheduled = false;
+ Depsgraph *graph = (Depsgraph *)data_v;
+ OperationNode *node = graph->operations[i];
+ node->scheduled = false;
}
-void flush_init_id_node_func(
- void *__restrict data_v,
- const int i,
- const ParallelRangeTLS *__restrict /*tls*/)
+void flush_init_id_node_func(void *__restrict data_v,
+ const int i,
+ const ParallelRangeTLS *__restrict /*tls*/)
{
- Depsgraph *graph = (Depsgraph *)data_v;
- IDNode *id_node = graph->id_nodes[i];
- id_node->custom_flags = ID_STATE_NONE;
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- comp_node->custom_flags = COMPONENT_STATE_NONE;
- GHASH_FOREACH_END();
+ Depsgraph *graph = (Depsgraph *)data_v;
+ IDNode *id_node = graph->id_nodes[i];
+ id_node->custom_flags = ID_STATE_NONE;
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components)
+ comp_node->custom_flags = COMPONENT_STATE_NONE;
+ GHASH_FOREACH_END();
}
BLI_INLINE void flush_prepare(Depsgraph *graph)
{
- {
- const int num_operations = graph->operations.size();
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_operations,
- graph,
- flush_init_operation_node_func,
- &settings);
- }
- {
- const int num_id_nodes = graph->id_nodes.size();
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_id_nodes,
- graph,
- flush_init_id_node_func,
- &settings);
- }
+ {
+ const int num_operations = graph->operations.size();
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+ BLI_task_parallel_range(0, num_operations, graph, flush_init_operation_node_func, &settings);
+ }
+ {
+ const int num_id_nodes = graph->id_nodes.size();
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+ BLI_task_parallel_range(0, num_id_nodes, graph, flush_init_id_node_func, &settings);
+ }
}
BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue)
{
- GSET_FOREACH_BEGIN(OperationNode *, op_node, graph->entry_tags)
- {
- queue->push_back(op_node);
- op_node->scheduled = true;
- DEG_DEBUG_PRINTF((::Depsgraph *)graph,
- EVAL, "Operation is entry point for update: %s\n",
- op_node->identifier().c_str());
- }
- GSET_FOREACH_END();
+ GSET_FOREACH_BEGIN (OperationNode *, op_node, graph->entry_tags) {
+ queue->push_back(op_node);
+ op_node->scheduled = true;
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph,
+ EVAL,
+ "Operation is entry point for update: %s\n",
+ op_node->identifier().c_str());
+ }
+ GSET_FOREACH_END();
}
BLI_INLINE void flush_handle_id_node(IDNode *id_node)
{
- id_node->custom_flags = ID_STATE_MODIFIED;
+ id_node->custom_flags = ID_STATE_MODIFIED;
}
/* TODO(sergey): We can reduce number of arguments here. */
@@ -154,33 +146,31 @@ BLI_INLINE void flush_handle_component_node(IDNode *id_node,
ComponentNode *comp_node,
FlushQueue *queue)
{
- /* We only handle component once. */
- if (comp_node->custom_flags == COMPONENT_STATE_DONE) {
- return;
- }
- comp_node->custom_flags = COMPONENT_STATE_DONE;
- /* Tag all required operations in component for update, unless this is a
- * special component where we don't want all operations to be tagged.
- *
- * TODO(sergey): Make this a more generic solution. */
- if (comp_node->type != NodeType::PARTICLE_SETTINGS &&
- comp_node->type != NodeType::PARTICLE_SYSTEM)
- {
- for (OperationNode *op : comp_node->operations) {
- op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- }
- }
- /* when some target changes bone, we might need to re-run the
- * whole IK solver, otherwise result might be unpredictable. */
- if (comp_node->type == NodeType::BONE) {
- ComponentNode *pose_comp =
- id_node->find_component(NodeType::EVAL_POSE);
- BLI_assert(pose_comp != NULL);
- if (pose_comp->custom_flags == COMPONENT_STATE_NONE) {
- queue->push_front(pose_comp->get_entry_operation());
- pose_comp->custom_flags = COMPONENT_STATE_SCHEDULED;
- }
- }
+ /* We only handle component once. */
+ if (comp_node->custom_flags == COMPONENT_STATE_DONE) {
+ return;
+ }
+ comp_node->custom_flags = COMPONENT_STATE_DONE;
+ /* Tag all required operations in component for update, unless this is a
+ * special component where we don't want all operations to be tagged.
+ *
+ * TODO(sergey): Make this a more generic solution. */
+ if (comp_node->type != NodeType::PARTICLE_SETTINGS &&
+ comp_node->type != NodeType::PARTICLE_SYSTEM) {
+ for (OperationNode *op : comp_node->operations) {
+ op->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ }
+ }
+ /* when some target changes bone, we might need to re-run the
+ * whole IK solver, otherwise result might be unpredictable. */
+ if (comp_node->type == NodeType::BONE) {
+ ComponentNode *pose_comp = id_node->find_component(NodeType::EVAL_POSE);
+ BLI_assert(pose_comp != NULL);
+ if (pose_comp->custom_flags == COMPONENT_STATE_NONE) {
+ queue->push_front(pose_comp->get_entry_operation());
+ pose_comp->custom_flags = COMPONENT_STATE_SCHEDULED;
+ }
+ }
}
/* Schedule children of the given operation node for traversal.
@@ -189,168 +179,161 @@ BLI_INLINE void flush_handle_component_node(IDNode *id_node,
* return value, so it can start being handled right away, without building too
* much of a queue.
*/
-BLI_INLINE OperationNode *flush_schedule_children(
- OperationNode *op_node,
- FlushQueue *queue)
+BLI_INLINE OperationNode *flush_schedule_children(OperationNode *op_node, FlushQueue *queue)
{
- OperationNode *result = NULL;
- for (Relation *rel : op_node->outlinks) {
- /* Flush is forbidden, completely. */
- if (rel->flag & RELATION_FLAG_NO_FLUSH) {
- continue;
- }
- /* Relation only allows flushes on user changes, but the node was not
- * affected by user. */
- if ((rel->flag & RELATION_FLAG_FLUSH_USER_EDIT_ONLY) &&
- (op_node->flag & DEPSOP_FLAG_USER_MODIFIED) == 0)
- {
- continue;
- }
- OperationNode *to_node = (OperationNode *)rel->to;
- /* Always flush flushable flags, so children always know what happened
- * to their parents. */
- to_node->flag |= (op_node->flag & DEPSOP_FLAG_FLUSH);
- /* Flush update over the relation, if it was not flushed yet. */
- if (to_node->scheduled) {
- continue;
- }
- if (result != NULL) {
- queue->push_front(to_node);
- }
- else {
- result = to_node;
- }
- to_node->scheduled = true;
- }
- return result;
+ OperationNode *result = NULL;
+ for (Relation *rel : op_node->outlinks) {
+ /* Flush is forbidden, completely. */
+ if (rel->flag & RELATION_FLAG_NO_FLUSH) {
+ continue;
+ }
+ /* Relation only allows flushes on user changes, but the node was not
+ * affected by user. */
+ if ((rel->flag & RELATION_FLAG_FLUSH_USER_EDIT_ONLY) &&
+ (op_node->flag & DEPSOP_FLAG_USER_MODIFIED) == 0) {
+ continue;
+ }
+ OperationNode *to_node = (OperationNode *)rel->to;
+ /* Always flush flushable flags, so children always know what happened
+ * to their parents. */
+ to_node->flag |= (op_node->flag & DEPSOP_FLAG_FLUSH);
+ /* Flush update over the relation, if it was not flushed yet. */
+ if (to_node->scheduled) {
+ continue;
+ }
+ if (result != NULL) {
+ queue->push_front(to_node);
+ }
+ else {
+ result = to_node;
+ }
+ to_node->scheduled = true;
+ }
+ return result;
}
void flush_engine_data_update(ID *id)
{
- DrawDataList *draw_data_list = DRW_drawdatalist_from_id(id);
- if (draw_data_list == NULL) {
- return;
- }
- LISTBASE_FOREACH (DrawData *, draw_data, draw_data_list) {
- draw_data->recalc |= id->recalc;
- }
+ DrawDataList *draw_data_list = DRW_drawdatalist_from_id(id);
+ if (draw_data_list == NULL) {
+ return;
+ }
+ LISTBASE_FOREACH (DrawData *, draw_data, draw_data_list) {
+ draw_data->recalc |= id->recalc;
+ }
}
/* NOTE: It will also accumulate flags from changed components. */
-void flush_editors_id_update(Depsgraph *graph,
- const DEGEditorUpdateContext *update_ctx)
+void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *update_ctx)
{
- for (IDNode *id_node : graph->id_nodes) {
- if (id_node->custom_flags != ID_STATE_MODIFIED) {
- continue;
- }
- DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph*>(graph),
- GS(id_node->id_orig->name));
- /* TODO(sergey): Do we need to pass original or evaluated ID here? */
- ID *id_orig = id_node->id_orig;
- ID *id_cow = id_node->id_cow;
- /* Copy tag from original data to CoW storage.
- * This is because DEG_id_tag_update() sets tags on original
- * data. */
- id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL);
- /* Gather recalc flags from all changed components. */
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
- continue;
- }
- DepsNodeFactory *factory = type_get_factory(comp_node->type);
- BLI_assert(factory != NULL);
- id_cow->recalc |= factory->id_recalc_tag();
- }
- GHASH_FOREACH_END();
- DEG_DEBUG_PRINTF((::Depsgraph *)graph,
- EVAL, "Accumulated recalc bits for %s: %u\n",
- id_orig->name, (unsigned int)id_cow->recalc);
-
- /* Inform editors. Only if the datablock is being evaluated a second
- * time, to distinguish between user edits and initial evaluation when
- * the datablock becomes visible.
- *
- * TODO: image datablocks do not use COW, so might not be detected
- * correctly. */
- if (deg_copy_on_write_is_expanded(id_cow)) {
- if (graph->is_active) {
- deg_editors_id_update(update_ctx, id_orig);
- }
- /* ID may need to get its auto-override operations refreshed. */
- if (ID_IS_STATIC_OVERRIDE_AUTO(id_orig)) {
- id_orig->tag |= LIB_TAG_OVERRIDESTATIC_AUTOREFRESH;
- }
- /* Inform draw engines that something was changed. */
- flush_engine_data_update(id_cow);
- }
- }
+ for (IDNode *id_node : graph->id_nodes) {
+ if (id_node->custom_flags != ID_STATE_MODIFIED) {
+ continue;
+ }
+ DEG_graph_id_type_tag(reinterpret_cast<::Depsgraph *>(graph), GS(id_node->id_orig->name));
+ /* TODO(sergey): Do we need to pass original or evaluated ID here? */
+ ID *id_orig = id_node->id_orig;
+ ID *id_cow = id_node->id_cow;
+ /* Copy tag from original data to CoW storage.
+ * This is because DEG_id_tag_update() sets tags on original
+ * data. */
+ id_cow->recalc |= (id_orig->recalc & ID_RECALC_ALL);
+ /* Gather recalc flags from all changed components. */
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
+ continue;
+ }
+ DepsNodeFactory *factory = type_get_factory(comp_node->type);
+ BLI_assert(factory != NULL);
+ id_cow->recalc |= factory->id_recalc_tag();
+ }
+ GHASH_FOREACH_END();
+ DEG_DEBUG_PRINTF((::Depsgraph *)graph,
+ EVAL,
+ "Accumulated recalc bits for %s: %u\n",
+ id_orig->name,
+ (unsigned int)id_cow->recalc);
+
+ /* Inform editors. Only if the datablock is being evaluated a second
+ * time, to distinguish between user edits and initial evaluation when
+ * the datablock becomes visible.
+ *
+ * TODO: image datablocks do not use COW, so might not be detected
+ * correctly. */
+ if (deg_copy_on_write_is_expanded(id_cow)) {
+ if (graph->is_active) {
+ deg_editors_id_update(update_ctx, id_orig);
+ }
+ /* ID may need to get its auto-override operations refreshed. */
+ if (ID_IS_STATIC_OVERRIDE_AUTO(id_orig)) {
+ id_orig->tag |= LIB_TAG_OVERRIDESTATIC_AUTOREFRESH;
+ }
+ /* Inform draw engines that something was changed. */
+ flush_engine_data_update(id_cow);
+ }
+ }
}
#ifdef INVALIDATE_ON_FLUSH
void invalidate_tagged_evaluated_transform(ID *id)
{
- const ID_Type id_type = GS(id->name);
- switch (id_type) {
- case ID_OB:
- {
- Object *object = (Object *)id;
- copy_vn_fl((float *)object->obmat, 16, NAN);
- break;
- }
- default:
- break;
- }
+ const ID_Type id_type = GS(id->name);
+ switch (id_type) {
+ case ID_OB: {
+ Object *object = (Object *)id;
+ copy_vn_fl((float *)object->obmat, 16, NAN);
+ break;
+ }
+ default:
+ break;
+ }
}
void invalidate_tagged_evaluated_geometry(ID *id)
{
- const ID_Type id_type = GS(id->name);
- switch (id_type) {
- case ID_OB:
- {
- Object *object = (Object *)id;
- BKE_object_free_derived_caches(object);
- break;
- }
- default:
- break;
- }
+ const ID_Type id_type = GS(id->name);
+ switch (id_type) {
+ case ID_OB: {
+ Object *object = (Object *)id;
+ BKE_object_free_derived_caches(object);
+ break;
+ }
+ default:
+ break;
+ }
}
#endif
void invalidate_tagged_evaluated_data(Depsgraph *graph)
{
#ifdef INVALIDATE_ON_FLUSH
- for (IDNode *id_node : graph->id_nodes) {
- if (id_node->custom_flags != ID_STATE_MODIFIED) {
- continue;
- }
- ID *id_cow = id_node->id_cow;
- if (!deg_copy_on_write_is_expanded(id_cow)) {
- continue;
- }
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
- continue;
- }
- switch (comp_node->type) {
- case ID_RECALC_TRANSFORM:
- invalidate_tagged_evaluated_transform(id_cow);
- break;
- case ID_RECALC_GEOMETRY:
- invalidate_tagged_evaluated_geometry(id_cow);
- break;
- default:
- break;
- }
- }
- GHASH_FOREACH_END();
- }
+ for (IDNode *id_node : graph->id_nodes) {
+ if (id_node->custom_flags != ID_STATE_MODIFIED) {
+ continue;
+ }
+ ID *id_cow = id_node->id_cow;
+ if (!deg_copy_on_write_is_expanded(id_cow)) {
+ continue;
+ }
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ if (comp_node->custom_flags != COMPONENT_STATE_DONE) {
+ continue;
+ }
+ switch (comp_node->type) {
+ case ID_RECALC_TRANSFORM:
+ invalidate_tagged_evaluated_transform(id_cow);
+ break;
+ case ID_RECALC_GEOMETRY:
+ invalidate_tagged_evaluated_geometry(id_cow);
+ break;
+ default:
+ break;
+ }
+ }
+ GHASH_FOREACH_END();
+ }
#else
- (void) graph;
+ (void)graph;
#endif
}
@@ -361,76 +344,71 @@ void invalidate_tagged_evaluated_data(Depsgraph *graph)
*/
void deg_graph_flush_updates(Main *bmain, Depsgraph *graph)
{
- /* Sanity checks. */
- BLI_assert(bmain != NULL);
- BLI_assert(graph != NULL);
- /* Nothing to update, early out. */
- if (BLI_gset_len(graph->entry_tags) == 0) {
- return;
- }
- /* Reset all flags, get ready for the flush. */
- flush_prepare(graph);
- /* Starting from the tagged "entry" nodes, flush outwards. */
- FlushQueue queue;
- flush_schedule_entrypoints(graph, &queue);
- /* Prepare update context for editors. */
- DEGEditorUpdateContext update_ctx;
- update_ctx.bmain = bmain;
- update_ctx.depsgraph = (::Depsgraph *)graph;
- update_ctx.scene = graph->scene;
- update_ctx.view_layer = graph->view_layer;
- /* Do actual flush. */
- while (!queue.empty()) {
- OperationNode *op_node = queue.front();
- queue.pop_front();
- while (op_node != NULL) {
- /* Tag operation as required for update. */
- op_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
- /* Inform corresponding ID and component nodes about the change. */
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
- flush_handle_id_node(id_node);
- flush_handle_component_node(id_node, comp_node, &queue);
- /* Flush to nodes along links. */
- op_node = flush_schedule_children(op_node, &queue);
- }
- }
- /* Inform editors about all changes. */
- flush_editors_id_update(graph, &update_ctx);
- /* Reset evaluation result tagged which is tagged for update to some state
- * which is obvious to catch. */
- invalidate_tagged_evaluated_data(graph);
+ /* Sanity checks. */
+ BLI_assert(bmain != NULL);
+ BLI_assert(graph != NULL);
+ /* Nothing to update, early out. */
+ if (BLI_gset_len(graph->entry_tags) == 0) {
+ return;
+ }
+ /* Reset all flags, get ready for the flush. */
+ flush_prepare(graph);
+ /* Starting from the tagged "entry" nodes, flush outwards. */
+ FlushQueue queue;
+ flush_schedule_entrypoints(graph, &queue);
+ /* Prepare update context for editors. */
+ DEGEditorUpdateContext update_ctx;
+ update_ctx.bmain = bmain;
+ update_ctx.depsgraph = (::Depsgraph *)graph;
+ update_ctx.scene = graph->scene;
+ update_ctx.view_layer = graph->view_layer;
+ /* Do actual flush. */
+ while (!queue.empty()) {
+ OperationNode *op_node = queue.front();
+ queue.pop_front();
+ while (op_node != NULL) {
+ /* Tag operation as required for update. */
+ op_node->flag |= DEPSOP_FLAG_NEEDS_UPDATE;
+ /* Inform corresponding ID and component nodes about the change. */
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+ flush_handle_id_node(id_node);
+ flush_handle_component_node(id_node, comp_node, &queue);
+ /* Flush to nodes along links. */
+ op_node = flush_schedule_children(op_node, &queue);
+ }
+ }
+ /* Inform editors about all changes. */
+ flush_editors_id_update(graph, &update_ctx);
+ /* Reset evaluation result tagged which is tagged for update to some state
+ * which is obvious to catch. */
+ invalidate_tagged_evaluated_data(graph);
}
-static void graph_clear_operation_func(
- void *__restrict data_v,
- const int i,
- const ParallelRangeTLS *__restrict /*tls*/)
+static void graph_clear_operation_func(void *__restrict data_v,
+ const int i,
+ const ParallelRangeTLS *__restrict /*tls*/)
{
- Depsgraph *graph = (Depsgraph *)data_v;
- OperationNode *node = graph->operations[i];
- /* Clear node's "pending update" settings. */
- node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED |
- DEPSOP_FLAG_NEEDS_UPDATE |
- DEPSOP_FLAG_USER_MODIFIED);
+ Depsgraph *graph = (Depsgraph *)data_v;
+ OperationNode *node = graph->operations[i];
+ /* Clear node's "pending update" settings. */
+ node->flag &= ~(DEPSOP_FLAG_DIRECTLY_MODIFIED | DEPSOP_FLAG_NEEDS_UPDATE |
+ DEPSOP_FLAG_USER_MODIFIED);
}
/* Clear tags from all operation nodes. */
void deg_graph_clear_tags(Depsgraph *graph)
{
- /* Go over all operation nodes, clearing tags. */
- {
- const int num_operations = graph->operations.size();
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.min_iter_per_thread = 1024;
- BLI_task_parallel_range(0, num_operations,
- graph,
- graph_clear_operation_func,
- &settings);
- }
- /* Clear any entry tags which haven't been flushed. */
- BLI_gset_clear(graph->entry_tags, NULL);
+ /* Go over all operation nodes, clearing tags. */
+ {
+ const int num_operations = graph->operations.size();
+ ParallelRangeSettings settings;
+ BLI_parallel_range_settings_defaults(&settings);
+ settings.min_iter_per_thread = 1024;
+ BLI_task_parallel_range(0, num_operations, graph, graph_clear_operation_func, &settings);
+ }
+ /* Clear any entry tags which haven't been flushed. */
+ BLI_gset_clear(graph->entry_tags, NULL);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc
index 0bf525a0e19..25c32e88021 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc
@@ -37,24 +37,23 @@ namespace DEG {
void deg_eval_stats_aggregate(Depsgraph *graph)
{
- /* Reset current evaluation stats for ID and component nodes.
- * Those are not filled in by the evaluation engine. */
- for (Node *node : graph->id_nodes) {
- IDNode *id_node = (IDNode *)node;
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
- {
- comp_node->stats.reset_current();
- }
- GHASH_FOREACH_END();
- id_node->stats.reset_current();
- }
- /* Now accumulate operation timings to components and IDs. */
- for (OperationNode *op_node : graph->operations) {
- ComponentNode *comp_node = op_node->owner;
- IDNode *id_node = comp_node->owner;
- id_node->stats.current_time += op_node->stats.current_time;
- comp_node->stats.current_time += op_node->stats.current_time;
- }
+ /* Reset current evaluation stats for ID and component nodes.
+ * Those are not filled in by the evaluation engine. */
+ for (Node *node : graph->id_nodes) {
+ IDNode *id_node = (IDNode *)node;
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) {
+ comp_node->stats.reset_current();
+ }
+ GHASH_FOREACH_END();
+ id_node->stats.reset_current();
+ }
+ /* Now accumulate operation timings to components and IDs. */
+ for (OperationNode *op_node : graph->operations) {
+ ComponentNode *comp_node = op_node->owner;
+ IDNode *id_node = comp_node->owner;
+ id_node->stats.current_time += op_node->stats.current_time;
+ comp_node->stats.current_time += op_node->stats.current_time;
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc
index 1eaee3d9e5b..5692983fbe2 100644
--- a/source/blender/depsgraph/intern/node/deg_node.cc
+++ b/source/blender/depsgraph/intern/node/deg_node.cc
@@ -39,67 +39,92 @@ namespace DEG {
const char *nodeClassAsString(NodeClass node_class)
{
- switch (node_class) {
- case NodeClass::GENERIC: return "GENERIC";
- case NodeClass::COMPONENT: return "COMPONENT";
- case NodeClass::OPERATION: return "OPERATION";
- }
- BLI_assert(!"Unhandled node class, should never happen.");
- return "UNKNOWN";
+ switch (node_class) {
+ case NodeClass::GENERIC:
+ return "GENERIC";
+ case NodeClass::COMPONENT:
+ return "COMPONENT";
+ case NodeClass::OPERATION:
+ return "OPERATION";
+ }
+ BLI_assert(!"Unhandled node class, should never happen.");
+ return "UNKNOWN";
}
const char *nodeTypeAsString(NodeType type)
{
- switch (type) {
- case NodeType::UNDEFINED: return "UNDEFINED";
- case NodeType::OPERATION: return "OPERATION";
- /* **** Generic Types **** */
- case NodeType::TIMESOURCE: return "TIMESOURCE";
- case NodeType::ID_REF: return "ID_REF";
- /* **** Outer Types **** */
- case NodeType::PARAMETERS: return "PARAMETERS";
- case NodeType::PROXY: return "PROXY";
- case NodeType::ANIMATION: return "ANIMATION";
- case NodeType::TRANSFORM: return "TRANSFORM";
- case NodeType::GEOMETRY: return "GEOMETRY";
- case NodeType::SEQUENCER: return "SEQUENCER";
- case NodeType::LAYER_COLLECTIONS: return "LAYER_COLLECTIONS";
- case NodeType::COPY_ON_WRITE: return "COPY_ON_WRITE";
- case NodeType::OBJECT_FROM_LAYER: return "OBJECT_FROM_LAYER";
- /* **** Evaluation-Related Outer Types (with Subdata) **** */
- case NodeType::EVAL_POSE: return "EVAL_POSE";
- case NodeType::BONE: return "BONE";
- case NodeType::PARTICLE_SYSTEM: return "PARTICLE_SYSTEM";
- case NodeType::PARTICLE_SETTINGS: return "PARTICLE_SETTINGS";
- case NodeType::SHADING: return "SHADING";
- case NodeType::SHADING_PARAMETERS: return "SHADING_PARAMETERS";
- case NodeType::CACHE: return "CACHE";
- case NodeType::POINT_CACHE: return "POINT_CACHE";
- case NodeType::BATCH_CACHE: return "BATCH_CACHE";
- /* Duplication. */
- case NodeType::DUPLI: return "DUPLI";
- /* Synchronization. */
- case NodeType::SYNCHRONIZATION: return "SYNCHRONIZATION";
- /* Generic datablock. */
- case NodeType::GENERIC_DATABLOCK: return "GENERIC_DATABLOCK";
-
- /* Total number of meaningful node types. */
- case NodeType::NUM_TYPES: return "SpecialCase";
- }
- BLI_assert(!"Unhandled node type, should never happen.");
- return "UNKNOWN";
+ switch (type) {
+ case NodeType::UNDEFINED:
+ return "UNDEFINED";
+ case NodeType::OPERATION:
+ return "OPERATION";
+ /* **** Generic Types **** */
+ case NodeType::TIMESOURCE:
+ return "TIMESOURCE";
+ case NodeType::ID_REF:
+ return "ID_REF";
+ /* **** Outer Types **** */
+ case NodeType::PARAMETERS:
+ return "PARAMETERS";
+ case NodeType::PROXY:
+ return "PROXY";
+ case NodeType::ANIMATION:
+ return "ANIMATION";
+ case NodeType::TRANSFORM:
+ return "TRANSFORM";
+ case NodeType::GEOMETRY:
+ return "GEOMETRY";
+ case NodeType::SEQUENCER:
+ return "SEQUENCER";
+ case NodeType::LAYER_COLLECTIONS:
+ return "LAYER_COLLECTIONS";
+ case NodeType::COPY_ON_WRITE:
+ return "COPY_ON_WRITE";
+ case NodeType::OBJECT_FROM_LAYER:
+ return "OBJECT_FROM_LAYER";
+ /* **** Evaluation-Related Outer Types (with Subdata) **** */
+ case NodeType::EVAL_POSE:
+ return "EVAL_POSE";
+ case NodeType::BONE:
+ return "BONE";
+ case NodeType::PARTICLE_SYSTEM:
+ return "PARTICLE_SYSTEM";
+ case NodeType::PARTICLE_SETTINGS:
+ return "PARTICLE_SETTINGS";
+ case NodeType::SHADING:
+ return "SHADING";
+ case NodeType::SHADING_PARAMETERS:
+ return "SHADING_PARAMETERS";
+ case NodeType::CACHE:
+ return "CACHE";
+ case NodeType::POINT_CACHE:
+ return "POINT_CACHE";
+ case NodeType::BATCH_CACHE:
+ return "BATCH_CACHE";
+ /* Duplication. */
+ case NodeType::DUPLI:
+ return "DUPLI";
+ /* Synchronization. */
+ case NodeType::SYNCHRONIZATION:
+ return "SYNCHRONIZATION";
+ /* Generic datablock. */
+ case NodeType::GENERIC_DATABLOCK:
+ return "GENERIC_DATABLOCK";
+
+ /* Total number of meaningful node types. */
+ case NodeType::NUM_TYPES:
+ return "SpecialCase";
+ }
+ BLI_assert(!"Unhandled node type, should never happen.");
+ return "UNKNOWN";
}
/*******************************************************************************
* Type information.
*/
-Node::TypeInfo::TypeInfo(NodeType type,
- const char *type_name,
- int id_recalc_tag)
- : type(type),
- type_name(type_name),
- id_recalc_tag(id_recalc_tag)
+Node::TypeInfo::TypeInfo(NodeType type, const char *type_name, int id_recalc_tag)
+ : type(type), type_name(type_name), id_recalc_tag(id_recalc_tag)
{
}
@@ -109,17 +134,17 @@ Node::TypeInfo::TypeInfo(NodeType type,
Node::Stats::Stats()
{
- reset();
+ reset();
}
void Node::Stats::reset()
{
- current_time = 0.0;
+ current_time = 0.0;
}
void Node::Stats::reset_current()
{
- current_time = 0.0;
+ current_time = 0.0;
}
/*******************************************************************************
@@ -128,37 +153,37 @@ void Node::Stats::reset_current()
Node::Node()
{
- name = "";
+ name = "";
}
Node::~Node()
{
- /* Free links. */
- /* NOTE: We only free incoming links. This is to avoid double-free of links
- * when we're trying to free same link from both it's sides. We don't have
- * dangling links so this is not a problem from memory leaks point of view. */
- for (Relation *rel : inlinks) {
- OBJECT_GUARDED_DELETE(rel, Relation);
- }
+ /* Free links. */
+ /* NOTE: We only free incoming links. This is to avoid double-free of links
+ * when we're trying to free same link from both it's sides. We don't have
+ * dangling links so this is not a problem from memory leaks point of view. */
+ for (Relation *rel : inlinks) {
+ OBJECT_GUARDED_DELETE(rel, Relation);
+ }
}
-
/* Generic identifier for Depsgraph Nodes. */
string Node::identifier() const
{
- return string(nodeTypeAsString(type)) + " : " + name;
+ return string(nodeTypeAsString(type)) + " : " + name;
}
-NodeClass Node::get_class() const {
- if (type == NodeType::OPERATION) {
- return NodeClass::OPERATION;
- }
- else if (type < NodeType::PARAMETERS) {
- return NodeClass::GENERIC;
- }
- else {
- return NodeClass::COMPONENT;
- }
+NodeClass Node::get_class() const
+{
+ if (type == NodeType::OPERATION) {
+ return NodeClass::OPERATION;
+ }
+ else if (type < NodeType::PARAMETERS) {
+ return NodeClass::GENERIC;
+ }
+ else {
+ return NodeClass::COMPONENT;
+ }
}
/*******************************************************************************
@@ -173,8 +198,8 @@ static DepsNodeFactoryImpl<IDNode> DNTI_ID_REF;
void deg_register_base_depsnodes()
{
- register_node_typeinfo(&DNTI_TIMESOURCE);
- register_node_typeinfo(&DNTI_ID_REF);
+ register_node_typeinfo(&DNTI_TIMESOURCE);
+ register_node_typeinfo(&DNTI_ID_REF);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index 0677b0edc15..ece43657b38 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -40,154 +40,161 @@ struct Relation;
/* Metatype of Nodes - The general "level" in the graph structure
* the node serves. */
enum class NodeClass {
- /* Types generally unassociated with user-visible entities,
- * but needed for graph functioning. */
- GENERIC = 0,
- /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
- * certain types of evaluation behavior. */
- COMPONENT = 1,
- /* [Inner Node] A glorified function-pointer/callback for scheduling up
- * evaluation operations for components, subject to relationship
- * requirements. */
- OPERATION = 2,
+ /* Types generally unassociated with user-visible entities,
+ * but needed for graph functioning. */
+ GENERIC = 0,
+ /* [Outer Node] An "aspect" of evaluating/updating an ID-Block, requiring
+ * certain types of evaluation behavior. */
+ COMPONENT = 1,
+ /* [Inner Node] A glorified function-pointer/callback for scheduling up
+ * evaluation operations for components, subject to relationship
+ * requirements. */
+ OPERATION = 2,
};
const char *nodeClassAsString(NodeClass node_class);
/* Types of Nodes */
enum class NodeType {
- /* Fallback type for invalid return value */
- UNDEFINED = 0,
- /* Inner Node (Operation) */
- OPERATION,
-
- /* **** Generic Types **** */
-
- /* Time-Source */
- TIMESOURCE,
- /* ID-Block reference - used as landmarks/collection point for components,
- * but not usually part of main graph. */
- ID_REF,
-
- /* **** Outer Types **** */
-
- /* Parameters Component - Default when nothing else fits
- * (i.e. just SDNA property setting). */
- PARAMETERS,
- /* Generic "Proxy-Inherit" Component. */
- PROXY,
- /* Animation Component */
- ANIMATION,
- /* Transform Component (Parenting/Constraints) */
- TRANSFORM,
- /* Geometry Component (Mesh/Displist) */
- GEOMETRY,
- /* Sequencer Component (Scene Only) */
- SEQUENCER,
- /* Component which contains all operations needed for layer collections
- * evaluation. */
- LAYER_COLLECTIONS,
- /* Entry component of majority of ID nodes: prepares CoW pointers for
- * execution. */
- COPY_ON_WRITE,
- /* Used by all operations which are updating object when something is
- * changed in view layer. */
- OBJECT_FROM_LAYER,
- /* Un-interestying datablock, which is a part of dependency graph, but does
- * not have very distinctive update procedure. */
- GENERIC_DATABLOCK,
-
- /* **** Evaluation-Related Outer Types (with Subdata) **** */
-
- /* Pose Component - Owner/Container of Bones Eval */
- EVAL_POSE,
- /* Bone Component - Child/Subcomponent of Pose */
- BONE,
- /* Particle Systems Component */
- PARTICLE_SYSTEM,
- PARTICLE_SETTINGS,
- /* Material Shading Component */
- SHADING,
- SHADING_PARAMETERS,
- /* Point cache Component */
- POINT_CACHE,
- /* Cache Component */
- /* TODO(sergey); Verify that we really need this. */
- CACHE,
- /* Batch Cache Component.
- * TODO (dfelinto/sergey): rename to make it more generic. */
- BATCH_CACHE,
- /* Duplication system. Used to force duplicated objects visible when
- * when duplicator is visible. */
- DUPLI,
- /* Synchronization back to original datablock. */
- SYNCHRONIZATION,
-
- /* Total number of meaningful node types. */
- NUM_TYPES,
+ /* Fallback type for invalid return value */
+ UNDEFINED = 0,
+ /* Inner Node (Operation) */
+ OPERATION,
+
+ /* **** Generic Types **** */
+
+ /* Time-Source */
+ TIMESOURCE,
+ /* ID-Block reference - used as landmarks/collection point for components,
+ * but not usually part of main graph. */
+ ID_REF,
+
+ /* **** Outer Types **** */
+
+ /* Parameters Component - Default when nothing else fits
+ * (i.e. just SDNA property setting). */
+ PARAMETERS,
+ /* Generic "Proxy-Inherit" Component. */
+ PROXY,
+ /* Animation Component */
+ ANIMATION,
+ /* Transform Component (Parenting/Constraints) */
+ TRANSFORM,
+ /* Geometry Component (Mesh/Displist) */
+ GEOMETRY,
+ /* Sequencer Component (Scene Only) */
+ SEQUENCER,
+ /* Component which contains all operations needed for layer collections
+ * evaluation. */
+ LAYER_COLLECTIONS,
+ /* Entry component of majority of ID nodes: prepares CoW pointers for
+ * execution. */
+ COPY_ON_WRITE,
+ /* Used by all operations which are updating object when something is
+ * changed in view layer. */
+ OBJECT_FROM_LAYER,
+ /* Un-interestying datablock, which is a part of dependency graph, but does
+ * not have very distinctive update procedure. */
+ GENERIC_DATABLOCK,
+
+ /* **** Evaluation-Related Outer Types (with Subdata) **** */
+
+ /* Pose Component - Owner/Container of Bones Eval */
+ EVAL_POSE,
+ /* Bone Component - Child/Subcomponent of Pose */
+ BONE,
+ /* Particle Systems Component */
+ PARTICLE_SYSTEM,
+ PARTICLE_SETTINGS,
+ /* Material Shading Component */
+ SHADING,
+ SHADING_PARAMETERS,
+ /* Point cache Component */
+ POINT_CACHE,
+ /* Cache Component */
+ /* TODO(sergey); Verify that we really need this. */
+ CACHE,
+ /* Batch Cache Component.
+ * TODO (dfelinto/sergey): rename to make it more generic. */
+ BATCH_CACHE,
+ /* Duplication system. Used to force duplicated objects visible when
+ * when duplicator is visible. */
+ DUPLI,
+ /* Synchronization back to original datablock. */
+ SYNCHRONIZATION,
+
+ /* Total number of meaningful node types. */
+ NUM_TYPES,
};
const char *nodeTypeAsString(NodeType type);
/* All nodes in Depsgraph are descended from this. */
struct Node {
- /* Helper class for static typeinfo in subclasses. */
- struct TypeInfo {
- TypeInfo(NodeType type,
- const char *type_name,
- int id_recalc_tag = 0);
- NodeType type;
- const char *type_name;
- int id_recalc_tag;
- };
- struct Stats {
- Stats();
- /* Reset all the counters. Including all stats needed for average
- * evaluation time calculation. */
- void reset();
- /* Reset counters needed for the current graph evaluation, does not
- * touch averaging accumulators. */
- void reset_current();
- /* Time spend on this node during current graph evaluation. */
- double current_time;
- };
- /* Relationships between nodes
- * The reason why all depsgraph nodes are descended from this type (apart
- * from basic serialization benefits - from the typeinfo) is that we can
- * have relationships between these nodes. */
- typedef vector<Relation *> Relations;
-
- string name; /* Identifier - mainly for debugging purposes. */
- NodeType type; /* Structural type of node. */
- Relations inlinks; /* Nodes which this one depends on. */
- Relations outlinks; /* Nodes which depend on this one. */
- Stats stats; /* Evaluation statistics. */
-
- /* Generic tags for traversal algorithms and such.
- *
- * Actual meaning of values depends on a specific area. Every area is to
- * clean this before use. */
- int custom_flags;
-
- /* Methods. */
- Node();
- virtual ~Node();
-
- virtual string identifier() const;
-
- virtual void init(const ID * /*id*/, const char * /*subdata*/) {}
-
- virtual void tag_update(Depsgraph * /*graph*/, eUpdateSource /*source*/) {}
-
- virtual OperationNode *get_entry_operation() { return NULL; }
- virtual OperationNode *get_exit_operation() { return NULL; }
-
- virtual NodeClass get_class() const;
+ /* Helper class for static typeinfo in subclasses. */
+ struct TypeInfo {
+ TypeInfo(NodeType type, const char *type_name, int id_recalc_tag = 0);
+ NodeType type;
+ const char *type_name;
+ int id_recalc_tag;
+ };
+ struct Stats {
+ Stats();
+ /* Reset all the counters. Including all stats needed for average
+ * evaluation time calculation. */
+ void reset();
+ /* Reset counters needed for the current graph evaluation, does not
+ * touch averaging accumulators. */
+ void reset_current();
+ /* Time spend on this node during current graph evaluation. */
+ double current_time;
+ };
+ /* Relationships between nodes
+ * The reason why all depsgraph nodes are descended from this type (apart
+ * from basic serialization benefits - from the typeinfo) is that we can
+ * have relationships between these nodes. */
+ typedef vector<Relation *> Relations;
+
+ string name; /* Identifier - mainly for debugging purposes. */
+ NodeType type; /* Structural type of node. */
+ Relations inlinks; /* Nodes which this one depends on. */
+ Relations outlinks; /* Nodes which depend on this one. */
+ Stats stats; /* Evaluation statistics. */
+
+ /* Generic tags for traversal algorithms and such.
+ *
+ * Actual meaning of values depends on a specific area. Every area is to
+ * clean this before use. */
+ int custom_flags;
+
+ /* Methods. */
+ Node();
+ virtual ~Node();
+
+ virtual string identifier() const;
+
+ virtual void init(const ID * /*id*/, const char * /*subdata*/)
+ {
+ }
+
+ virtual void tag_update(Depsgraph * /*graph*/, eUpdateSource /*source*/)
+ {
+ }
+
+ virtual OperationNode *get_entry_operation()
+ {
+ return NULL;
+ }
+ virtual OperationNode *get_exit_operation()
+ {
+ return NULL;
+ }
+
+ virtual NodeClass get_class() const;
};
/* Macros for common static typeinfo. */
-#define DEG_DEPSNODE_DECLARE \
- static const Node::TypeInfo typeinfo
+#define DEG_DEPSNODE_DECLARE static const Node::TypeInfo typeinfo
#define DEG_DEPSNODE_DEFINE(NodeType, type_, tname_) \
- const Node::TypeInfo NodeType::typeinfo = Node::TypeInfo(type_, tname_)
+ const Node::TypeInfo NodeType::typeinfo = Node::TypeInfo(type_, tname_)
void deg_register_base_depsnodes();
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc
index 06ede835a27..dc7ca371de3 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_component.cc
@@ -24,7 +24,7 @@
#include "intern/node/deg_node_component.h"
#include <stdio.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -47,308 +47,281 @@ namespace DEG {
/* Standard Component Methods ============================= */
ComponentNode::OperationIDKey::OperationIDKey()
- : opcode(OperationCode::OPERATION),
- name(""),
- name_tag(-1)
+ : opcode(OperationCode::OPERATION), name(""), name_tag(-1)
{
}
ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode)
- : opcode(opcode),
- name(""),
- name_tag(-1)
+ : opcode(opcode), name(""), name_tag(-1)
{
}
-ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode,
- const char *name,
- int name_tag)
- : opcode(opcode),
- name(name),
- name_tag(name_tag)
+ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode, const char *name, int name_tag)
+ : opcode(opcode), name(name), name_tag(name_tag)
{
}
string ComponentNode::OperationIDKey::identifier() const
{
- const string codebuf = to_string(static_cast<int>(opcode));
- return "OperationIDKey(" + codebuf + ", " + name + ")";
+ const string codebuf = to_string(static_cast<int>(opcode));
+ return "OperationIDKey(" + codebuf + ", " + name + ")";
}
-bool ComponentNode::OperationIDKey::operator==(
- const OperationIDKey &other) const
+bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) const
{
- return (opcode == other.opcode) &&
- (STREQ(name, other.name)) &&
- (name_tag == other.name_tag);
+ return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag);
}
static unsigned int comp_node_hash_key(const void *key_v)
{
- const ComponentNode::OperationIDKey *key =
- reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v);
- int opcode_as_int = static_cast<int>(key->opcode);
- return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int),
- BLI_ghashutil_strhash_p(key->name));
+ const ComponentNode::OperationIDKey *key =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v);
+ int opcode_as_int = static_cast<int>(key->opcode);
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int),
+ BLI_ghashutil_strhash_p(key->name));
}
static bool comp_node_hash_key_cmp(const void *a, const void *b)
{
- const ComponentNode::OperationIDKey *key_a =
- reinterpret_cast<const ComponentNode::OperationIDKey *>(a);
- const ComponentNode::OperationIDKey *key_b =
- reinterpret_cast<const ComponentNode::OperationIDKey *>(b);
- return !(*key_a == *key_b);
+ const ComponentNode::OperationIDKey *key_a =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(a);
+ const ComponentNode::OperationIDKey *key_b =
+ reinterpret_cast<const ComponentNode::OperationIDKey *>(b);
+ return !(*key_a == *key_b);
}
static void comp_node_hash_key_free(void *key_v)
{
- typedef ComponentNode::OperationIDKey OperationIDKey;
- OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v);
- OBJECT_GUARDED_DELETE(key, OperationIDKey);
+ typedef ComponentNode::OperationIDKey OperationIDKey;
+ OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, OperationIDKey);
}
static void comp_node_hash_value_free(void *value_v)
{
- OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v);
- OBJECT_GUARDED_DELETE(op_node, OperationNode);
+ OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v);
+ OBJECT_GUARDED_DELETE(op_node, OperationNode);
}
-ComponentNode::ComponentNode() :
- entry_operation(NULL),
- exit_operation(NULL),
- affects_directly_visible(false)
+ComponentNode::ComponentNode()
+ : entry_operation(NULL), exit_operation(NULL), affects_directly_visible(false)
{
- operations_map = BLI_ghash_new(comp_node_hash_key,
- comp_node_hash_key_cmp,
- "Depsgraph id hash");
+ operations_map = BLI_ghash_new(comp_node_hash_key, comp_node_hash_key_cmp, "Depsgraph id hash");
}
/* Initialize 'component' node - from pointer data given */
-void ComponentNode::init(const ID * /*id*/,
- const char * /*subdata*/)
+void ComponentNode::init(const ID * /*id*/, const char * /*subdata*/)
{
- /* hook up eval context? */
- // XXX: maybe this needs a special API?
+ /* hook up eval context? */
+ // XXX: maybe this needs a special API?
}
/* Free 'component' node */
ComponentNode::~ComponentNode()
{
- clear_operations();
- if (operations_map != NULL) {
- BLI_ghash_free(operations_map,
- comp_node_hash_key_free,
- comp_node_hash_value_free);
- }
+ clear_operations();
+ if (operations_map != NULL) {
+ BLI_ghash_free(operations_map, comp_node_hash_key_free, comp_node_hash_value_free);
+ }
}
string ComponentNode::identifier() const
{
- const string idname = this->owner->name;
- const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
- return typebuf + name + " : " + idname +
- "( affects_directly_visible: " +
- (affects_directly_visible ? "true"
- : "false") + ")";
-;
+ const string idname = this->owner->name;
+ const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
+ return typebuf + name + " : " + idname +
+ "( affects_directly_visible: " + (affects_directly_visible ? "true" : "false") + ")";
+ ;
}
OperationNode *ComponentNode::find_operation(OperationIDKey key) const
{
- OperationNode *node = NULL;
- if (operations_map != NULL) {
- node = (OperationNode *)BLI_ghash_lookup(operations_map, &key);
- }
- else {
- for (OperationNode *op_node : operations) {
- if (op_node->opcode == key.opcode &&
- op_node->name_tag == key.name_tag &&
- STREQ(op_node->name.c_str(), key.name))
- {
- node = op_node;
- break;
- }
- }
- }
- return node;
+ OperationNode *node = NULL;
+ if (operations_map != NULL) {
+ node = (OperationNode *)BLI_ghash_lookup(operations_map, &key);
+ }
+ else {
+ for (OperationNode *op_node : operations) {
+ if (op_node->opcode == key.opcode && op_node->name_tag == key.name_tag &&
+ STREQ(op_node->name.c_str(), key.name)) {
+ node = op_node;
+ break;
+ }
+ }
+ }
+ return node;
}
OperationNode *ComponentNode::find_operation(OperationCode opcode,
- const char *name,
- int name_tag) const
+ const char *name,
+ int name_tag) const
{
- OperationIDKey key(opcode, name, name_tag);
- return find_operation(key);
+ OperationIDKey key(opcode, name, name_tag);
+ return find_operation(key);
}
OperationNode *ComponentNode::get_operation(OperationIDKey key) const
{
- OperationNode *node = find_operation(key);
- if (node == NULL) {
- fprintf(stderr, "%s: find_operation(%s) failed\n",
- this->identifier().c_str(), key.identifier().c_str());
- BLI_assert(!"Request for non-existing operation, should not happen");
- return NULL;
- }
- return node;
+ OperationNode *node = find_operation(key);
+ if (node == NULL) {
+ fprintf(stderr,
+ "%s: find_operation(%s) failed\n",
+ this->identifier().c_str(),
+ key.identifier().c_str());
+ BLI_assert(!"Request for non-existing operation, should not happen");
+ return NULL;
+ }
+ return node;
}
OperationNode *ComponentNode::get_operation(OperationCode opcode,
- const char *name,
- int name_tag) const
+ const char *name,
+ int name_tag) const
{
- OperationIDKey key(opcode, name, name_tag);
- return get_operation(key);
+ OperationIDKey key(opcode, name, name_tag);
+ return get_operation(key);
}
bool ComponentNode::has_operation(OperationIDKey key) const
{
- return find_operation(key) != NULL;
+ return find_operation(key) != NULL;
}
-bool ComponentNode::has_operation(OperationCode opcode,
- const char *name,
- int name_tag) const
+bool ComponentNode::has_operation(OperationCode opcode, const char *name, int name_tag) const
{
- OperationIDKey key(opcode, name, name_tag);
- return has_operation(key);
+ OperationIDKey key(opcode, name, name_tag);
+ return has_operation(key);
}
-OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb& op,
- OperationCode opcode,
- const char *name,
- int name_tag)
+OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op,
+ OperationCode opcode,
+ const char *name,
+ int name_tag)
{
- OperationNode *op_node = find_operation(opcode, name, name_tag);
- if (!op_node) {
- DepsNodeFactory *factory = type_get_factory(NodeType::OPERATION);
- op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
-
- /* register opnode in this component's operation set */
- OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
- BLI_ghash_insert(operations_map, key, op_node);
-
- /* set backlink */
- op_node->owner = this;
- }
- else {
- fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
- this->identifier().c_str(), op_node->identifier().c_str(), op_node);
- BLI_assert(!"Should not happen!");
- }
-
- /* attach extra data */
- op_node->evaluate = op;
- op_node->opcode = opcode;
- op_node->name = name;
- op_node->name_tag = name_tag;
-
- return op_node;
+ OperationNode *op_node = find_operation(opcode, name, name_tag);
+ if (!op_node) {
+ DepsNodeFactory *factory = type_get_factory(NodeType::OPERATION);
+ op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
+
+ /* register opnode in this component's operation set */
+ OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
+ BLI_ghash_insert(operations_map, key, op_node);
+
+ /* set backlink */
+ op_node->owner = this;
+ }
+ else {
+ fprintf(stderr,
+ "add_operation: Operation already exists - %s has %s at %p\n",
+ this->identifier().c_str(),
+ op_node->identifier().c_str(),
+ op_node);
+ BLI_assert(!"Should not happen!");
+ }
+
+ /* attach extra data */
+ op_node->evaluate = op;
+ op_node->opcode = opcode;
+ op_node->name = name;
+ op_node->name_tag = name_tag;
+
+ return op_node;
}
void ComponentNode::set_entry_operation(OperationNode *op_node)
{
- BLI_assert(entry_operation == NULL);
- entry_operation = op_node;
+ BLI_assert(entry_operation == NULL);
+ entry_operation = op_node;
}
void ComponentNode::set_exit_operation(OperationNode *op_node)
{
- BLI_assert(exit_operation == NULL);
- exit_operation = op_node;
+ BLI_assert(exit_operation == NULL);
+ exit_operation = op_node;
}
void ComponentNode::clear_operations()
{
- if (operations_map != NULL) {
- BLI_ghash_clear(operations_map,
- comp_node_hash_key_free,
- comp_node_hash_value_free);
- }
- for (OperationNode *op_node : operations) {
- OBJECT_GUARDED_DELETE(op_node, OperationNode);
- }
- operations.clear();
+ if (operations_map != NULL) {
+ BLI_ghash_clear(operations_map, comp_node_hash_key_free, comp_node_hash_value_free);
+ }
+ for (OperationNode *op_node : operations) {
+ OBJECT_GUARDED_DELETE(op_node, OperationNode);
+ }
+ operations.clear();
}
void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source)
{
- OperationNode *entry_op = get_entry_operation();
- if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
- return;
- }
- for (OperationNode *op_node : operations) {
- op_node->tag_update(graph, source);
- }
- // It is possible that tag happens before finalization.
- if (operations_map != NULL) {
- GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
- {
- op_node->tag_update(graph, source);
- }
- GHASH_FOREACH_END();
- }
+ OperationNode *entry_op = get_entry_operation();
+ if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
+ return;
+ }
+ for (OperationNode *op_node : operations) {
+ op_node->tag_update(graph, source);
+ }
+ // It is possible that tag happens before finalization.
+ if (operations_map != NULL) {
+ GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) {
+ op_node->tag_update(graph, source);
+ }
+ GHASH_FOREACH_END();
+ }
}
OperationNode *ComponentNode::get_entry_operation()
{
- if (entry_operation) {
- return entry_operation;
- }
- else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
- OperationNode *op_node = NULL;
- /* TODO(sergey): This is somewhat slow. */
- GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
- {
- op_node = tmp;
- }
- GHASH_FOREACH_END();
- /* Cache for the subsequent usage. */
- entry_operation = op_node;
- return op_node;
- }
- else if (operations.size() == 1) {
- return operations[0];
- }
- return NULL;
+ if (entry_operation) {
+ return entry_operation;
+ }
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
+ OperationNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ entry_operation = op_node;
+ return op_node;
+ }
+ else if (operations.size() == 1) {
+ return operations[0];
+ }
+ return NULL;
}
OperationNode *ComponentNode::get_exit_operation()
{
- if (exit_operation) {
- return exit_operation;
- }
- else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
- OperationNode *op_node = NULL;
- /* TODO(sergey): This is somewhat slow. */
- GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
- {
- op_node = tmp;
- }
- GHASH_FOREACH_END();
- /* Cache for the subsequent usage. */
- exit_operation = op_node;
- return op_node;
- }
- else if (operations.size() == 1) {
- return operations[0];
- }
- return NULL;
+ if (exit_operation) {
+ return exit_operation;
+ }
+ else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
+ OperationNode *op_node = NULL;
+ /* TODO(sergey): This is somewhat slow. */
+ GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) {
+ op_node = tmp;
+ }
+ GHASH_FOREACH_END();
+ /* Cache for the subsequent usage. */
+ exit_operation = op_node;
+ return op_node;
+ }
+ else if (operations.size() == 1) {
+ return operations[0];
+ }
+ return NULL;
}
void ComponentNode::finalize_build(Depsgraph * /*graph*/)
{
- operations.reserve(BLI_ghash_len(operations_map));
- GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
- {
- operations.push_back(op_node);
- }
- GHASH_FOREACH_END();
- BLI_ghash_free(operations_map,
- comp_node_hash_key_free,
- NULL);
- operations_map = NULL;
+ operations.reserve(BLI_ghash_len(operations_map));
+ GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) {
+ operations.push_back(op_node);
+ }
+ GHASH_FOREACH_END();
+ BLI_ghash_free(operations_map, comp_node_hash_key_free, NULL);
+ operations_map = NULL;
}
/* Bone Component ========================================= */
@@ -356,69 +329,69 @@ void ComponentNode::finalize_build(Depsgraph * /*graph*/)
/* Initialize 'bone component' node - from pointer data given */
void BoneComponentNode::init(const ID *id, const char *subdata)
{
- /* generic component-node... */
- ComponentNode::init(id, subdata);
+ /* generic component-node... */
+ ComponentNode::init(id, subdata);
- /* name of component comes is bone name */
- /* TODO(sergey): This sets name to an empty string because subdata is
- * empty. Is it a bug? */
- //this->name = subdata;
+ /* name of component comes is bone name */
+ /* TODO(sergey): This sets name to an empty string because subdata is
+ * empty. Is it a bug? */
+ //this->name = subdata;
- /* bone-specific node data */
- Object *object = (Object *)id;
- this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
+ /* bone-specific node data */
+ Object *object = (Object *)id;
+ this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
}
/* Register all components. =============================== */
-DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMATION);
+DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMATION);
/* TODO(sergey): Is this a correct tag? */
-DEG_COMPONENT_NODE_DEFINE(BatchCache, BATCH_CACHE, ID_RECALC_SHADING);
-DEG_COMPONENT_NODE_DEFINE(Bone, BONE, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, 0);
-DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC_COPY_ON_WRITE);
-DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
-DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, 0);
-DEG_COMPONENT_NODE_DEFINE(Particles, PARTICLE_SYSTEM, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(ParticleSettings, PARTICLE_SETTINGS, 0);
-DEG_COMPONENT_NODE_DEFINE(PointCache, POINT_CACHE, 0);
-DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
-DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
-DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
+DEG_COMPONENT_NODE_DEFINE(BatchCache, BATCH_CACHE, ID_RECALC_SHADING);
+DEG_COMPONENT_NODE_DEFINE(Bone, BONE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, 0);
+DEG_COMPONENT_NODE_DEFINE(CopyOnWrite, COPY_ON_WRITE, ID_RECALC_COPY_ON_WRITE);
+DEG_COMPONENT_NODE_DEFINE(Geometry, GEOMETRY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
+DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, 0);
+DEG_COMPONENT_NODE_DEFINE(Particles, PARTICLE_SYSTEM, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(ParticleSettings, PARTICLE_SETTINGS, 0);
+DEG_COMPONENT_NODE_DEFINE(PointCache, POINT_CACHE, 0);
+DEG_COMPONENT_NODE_DEFINE(Pose, EVAL_POSE, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Proxy, PROXY, ID_RECALC_GEOMETRY);
+DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
+DEG_COMPONENT_NODE_DEFINE(Shading, SHADING, ID_RECALC_SHADING);
DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_SHADING);
-DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
-DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
-DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
-DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
-DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
+DEG_COMPONENT_NODE_DEFINE(Transform, TRANSFORM, ID_RECALC_TRANSFORM);
+DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
+DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
+DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
+DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
/* Node Types Register =================================== */
void deg_register_component_depsnodes()
{
- register_node_typeinfo(&DNTI_ANIMATION);
- register_node_typeinfo(&DNTI_BONE);
- register_node_typeinfo(&DNTI_CACHE);
- register_node_typeinfo(&DNTI_BATCH_CACHE);
- register_node_typeinfo(&DNTI_COPY_ON_WRITE);
- register_node_typeinfo(&DNTI_GEOMETRY);
- register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
- register_node_typeinfo(&DNTI_PARAMETERS);
- register_node_typeinfo(&DNTI_PARTICLE_SYSTEM);
- register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
- register_node_typeinfo(&DNTI_POINT_CACHE);
- register_node_typeinfo(&DNTI_PROXY);
- register_node_typeinfo(&DNTI_EVAL_POSE);
- register_node_typeinfo(&DNTI_SEQUENCER);
- register_node_typeinfo(&DNTI_SHADING);
- register_node_typeinfo(&DNTI_SHADING_PARAMETERS);
- register_node_typeinfo(&DNTI_TRANSFORM);
- register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
- register_node_typeinfo(&DNTI_DUPLI);
- register_node_typeinfo(&DNTI_SYNCHRONIZATION);
- register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
+ register_node_typeinfo(&DNTI_ANIMATION);
+ register_node_typeinfo(&DNTI_BONE);
+ register_node_typeinfo(&DNTI_CACHE);
+ register_node_typeinfo(&DNTI_BATCH_CACHE);
+ register_node_typeinfo(&DNTI_COPY_ON_WRITE);
+ register_node_typeinfo(&DNTI_GEOMETRY);
+ register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
+ register_node_typeinfo(&DNTI_PARAMETERS);
+ register_node_typeinfo(&DNTI_PARTICLE_SYSTEM);
+ register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
+ register_node_typeinfo(&DNTI_POINT_CACHE);
+ register_node_typeinfo(&DNTI_PROXY);
+ register_node_typeinfo(&DNTI_EVAL_POSE);
+ register_node_typeinfo(&DNTI_SEQUENCER);
+ register_node_typeinfo(&DNTI_SHADING);
+ register_node_typeinfo(&DNTI_SHADING_PARAMETERS);
+ register_node_typeinfo(&DNTI_TRANSFORM);
+ register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
+ register_node_typeinfo(&DNTI_DUPLI);
+ register_node_typeinfo(&DNTI_SYNCHRONIZATION);
+ register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h
index 4392a120935..038b5917a86 100644
--- a/source/blender/depsgraph/intern/node/deg_node_component.h
+++ b/source/blender/depsgraph/intern/node/deg_node_component.h
@@ -42,134 +42,130 @@ struct OperationNode;
/* ID Component - Base type for all components */
struct ComponentNode : public Node {
- /* Key used to look up operations within a component */
- struct OperationIDKey
- {
- OperationCode opcode;
- const char *name;
- int name_tag;
-
- OperationIDKey();
- OperationIDKey(OperationCode opcode);
- OperationIDKey(OperationCode opcode,
- const char *name,
- int name_tag);
-
- string identifier() const;
- bool operator==(const OperationIDKey &other) const;
- };
-
- /* Typedef for container of operations */
- ComponentNode();
- ~ComponentNode();
-
- void init(const ID *id, const char *subdata) override;
-
- virtual string identifier() const override;
-
- /* Find an existing operation, if requested operation does not exist
- * NULL will be returned. */
- OperationNode *find_operation(OperationIDKey key) const;
- OperationNode *find_operation(OperationCode opcode,
- const char *name,
- int name_tag) const;
-
- /* Find an existing operation, will throw an assert() if it does not exist. */
- OperationNode *get_operation(OperationIDKey key) const;
- OperationNode *get_operation(OperationCode opcode,
- const char *name,
- int name_tag) const;
-
- /* Check operation exists and return it. */
- bool has_operation(OperationIDKey key) const;
- bool has_operation(OperationCode opcode,
- const char *name,
- int name_tag) const;
-
- /**
- * Create a new node for representing an operation and add this to graph
- * \warning If an existing node is found, it will be modified. This helps
- * when node may have been partially created earlier (e.g. parent ref before
- * parent item is added)
- *
- * \param type: Operation node type (corresponding to context/component that
- * it operates in)
- * \param optype: Role that operation plays within component
- * (i.e. where in eval process)
- * \param op: The operation to perform
- * \param name: Identifier for operation - used to find/locate it again */
- OperationNode *add_operation(const DepsEvalOperationCb& op,
- OperationCode opcode,
- const char *name,
- int name_tag);
-
- /* Entry/exit operations management.
- *
- * Use those instead of direct set since this will perform sanity checks. */
- void set_entry_operation(OperationNode *op_node);
- void set_exit_operation(OperationNode *op_node);
-
- void clear_operations();
-
- virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
-
- virtual OperationNode *get_entry_operation() override;
- virtual OperationNode *get_exit_operation() override;
-
- void finalize_build(Depsgraph *graph);
-
- IDNode *owner;
-
- /* ** Inner nodes for this component ** */
-
- /* Operations stored as a hash map, for faster build.
- * This hash map will be freed when graph is fully built. */
- GHash *operations_map;
-
- /* This is a "normal" list of operations, used by evaluation
- * and other routines after construction. */
- vector<OperationNode *> operations;
-
- OperationNode *entry_operation;
- OperationNode *exit_operation;
-
- virtual bool depends_on_cow() { return true; }
-
- /* Denotes whether COW component is to be tagged when this component
- * is tagged for update. */
- virtual bool need_tag_cow_before_update() { return true; }
-
- /* Denotes whether this component affects (possibly indirectly) on a
- * directly visible object. */
- bool affects_directly_visible;
+ /* Key used to look up operations within a component */
+ struct OperationIDKey {
+ OperationCode opcode;
+ const char *name;
+ int name_tag;
+
+ OperationIDKey();
+ OperationIDKey(OperationCode opcode);
+ OperationIDKey(OperationCode opcode, const char *name, int name_tag);
+
+ string identifier() const;
+ bool operator==(const OperationIDKey &other) const;
+ };
+
+ /* Typedef for container of operations */
+ ComponentNode();
+ ~ComponentNode();
+
+ void init(const ID *id, const char *subdata) override;
+
+ virtual string identifier() const override;
+
+ /* Find an existing operation, if requested operation does not exist
+ * NULL will be returned. */
+ OperationNode *find_operation(OperationIDKey key) const;
+ OperationNode *find_operation(OperationCode opcode, const char *name, int name_tag) const;
+
+ /* Find an existing operation, will throw an assert() if it does not exist. */
+ OperationNode *get_operation(OperationIDKey key) const;
+ OperationNode *get_operation(OperationCode opcode, const char *name, int name_tag) const;
+
+ /* Check operation exists and return it. */
+ bool has_operation(OperationIDKey key) const;
+ bool has_operation(OperationCode opcode, const char *name, int name_tag) const;
+
+ /**
+ * Create a new node for representing an operation and add this to graph
+ * \warning If an existing node is found, it will be modified. This helps
+ * when node may have been partially created earlier (e.g. parent ref before
+ * parent item is added)
+ *
+ * \param type: Operation node type (corresponding to context/component that
+ * it operates in)
+ * \param optype: Role that operation plays within component
+ * (i.e. where in eval process)
+ * \param op: The operation to perform
+ * \param name: Identifier for operation - used to find/locate it again */
+ OperationNode *add_operation(const DepsEvalOperationCb &op,
+ OperationCode opcode,
+ const char *name,
+ int name_tag);
+
+ /* Entry/exit operations management.
+ *
+ * Use those instead of direct set since this will perform sanity checks. */
+ void set_entry_operation(OperationNode *op_node);
+ void set_exit_operation(OperationNode *op_node);
+
+ void clear_operations();
+
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+
+ virtual OperationNode *get_entry_operation() override;
+ virtual OperationNode *get_exit_operation() override;
+
+ void finalize_build(Depsgraph *graph);
+
+ IDNode *owner;
+
+ /* ** Inner nodes for this component ** */
+
+ /* Operations stored as a hash map, for faster build.
+ * This hash map will be freed when graph is fully built. */
+ GHash *operations_map;
+
+ /* This is a "normal" list of operations, used by evaluation
+ * and other routines after construction. */
+ vector<OperationNode *> operations;
+
+ OperationNode *entry_operation;
+ OperationNode *exit_operation;
+
+ virtual bool depends_on_cow()
+ {
+ return true;
+ }
+
+ /* Denotes whether COW component is to be tagged when this component
+ * is tagged for update. */
+ virtual bool need_tag_cow_before_update()
+ {
+ return true;
+ }
+
+ /* Denotes whether this component affects (possibly indirectly) on a
+ * directly visible object. */
+ bool affects_directly_visible;
};
/* ---------------------------------------- */
-#define DEG_COMPONENT_NODE_DEFINE_TYPEINFO(\
- NodeType, type_, type_name_, id_recalc_tag) \
- const Node::TypeInfo NodeType::typeinfo = \
- Node::TypeInfo(type_, type_name_, id_recalc_tag)
+#define DEG_COMPONENT_NODE_DEFINE_TYPEINFO(NodeType, type_, type_name_, id_recalc_tag) \
+ const Node::TypeInfo NodeType::typeinfo = Node::TypeInfo(type_, type_name_, id_recalc_tag)
#define DEG_COMPONENT_NODE_DECLARE DEG_DEPSNODE_DECLARE
-#define DEG_COMPONENT_NODE_DEFINE(name, NAME, id_recalc_tag) \
- DEG_COMPONENT_NODE_DEFINE_TYPEINFO(name ## ComponentNode, \
- NodeType:: NAME, \
- #name " Component", \
- id_recalc_tag) ; \
- static DepsNodeFactoryImpl<name ## ComponentNode> DNTI_ ## NAME
-
-#define DEG_COMPONENT_NODE_DECLARE_GENERIC(name) \
- struct name ## ComponentNode : public ComponentNode { \
- DEG_COMPONENT_NODE_DECLARE; \
- }
-
-#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \
- struct name ## ComponentNode : public ComponentNode { \
- DEG_COMPONENT_NODE_DECLARE; \
- virtual bool need_tag_cow_before_update() { return false; } \
- }
+#define DEG_COMPONENT_NODE_DEFINE(name, NAME, id_recalc_tag) \
+ DEG_COMPONENT_NODE_DEFINE_TYPEINFO( \
+ name##ComponentNode, NodeType::NAME, #name " Component", id_recalc_tag); \
+ static DepsNodeFactoryImpl<name##ComponentNode> DNTI_##NAME
+
+#define DEG_COMPONENT_NODE_DECLARE_GENERIC(name) \
+ struct name##ComponentNode : public ComponentNode { \
+ DEG_COMPONENT_NODE_DECLARE; \
+ }
+
+#define DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(name) \
+ struct name##ComponentNode : public ComponentNode { \
+ DEG_COMPONENT_NODE_DECLARE; \
+ virtual bool need_tag_cow_before_update() \
+ { \
+ return false; \
+ } \
+ }
DEG_COMPONENT_NODE_DECLARE_GENERIC(Animation);
DEG_COMPONENT_NODE_DECLARE_NO_COW_TAG_ON_UPDATE(BatchCache);
@@ -194,11 +190,11 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock);
/* Bone Component */
struct BoneComponentNode : public ComponentNode {
- void init(const ID *id, const char *subdata);
+ void init(const ID *id, const char *subdata);
- struct bPoseChannel *pchan; /* the bone that this component represents */
+ struct bPoseChannel *pchan; /* the bone that this component represents */
- DEG_COMPONENT_NODE_DECLARE;
+ DEG_COMPONENT_NODE_DECLARE;
};
void deg_register_component_depsnodes();
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.cc b/source/blender/depsgraph/intern/node/deg_node_factory.cc
index e6f2fd1841d..4a11ed2a4fb 100644
--- a/source/blender/depsgraph/intern/node/deg_node_factory.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_factory.cc
@@ -26,21 +26,20 @@
namespace DEG {
/* Global type registry */
-static DepsNodeFactory *
-node_typeinfo_registry[static_cast<int>(NodeType::NUM_TYPES)] = {NULL};
+static DepsNodeFactory *node_typeinfo_registry[static_cast<int>(NodeType::NUM_TYPES)] = {NULL};
void register_node_typeinfo(DepsNodeFactory *factory)
{
- BLI_assert(factory != NULL);
- const int type_as_int = static_cast<int>(factory->type());
- node_typeinfo_registry[type_as_int] = factory;
+ BLI_assert(factory != NULL);
+ const int type_as_int = static_cast<int>(factory->type());
+ node_typeinfo_registry[type_as_int] = factory;
}
DepsNodeFactory *type_get_factory(const NodeType type)
{
- /* Look up type - at worst, it doesn't exist in table yet, and we fail. */
- const int type_as_int = static_cast<int>(type);
- return node_typeinfo_registry[type_as_int];
+ /* Look up type - at worst, it doesn't exist in table yet, and we fail. */
+ const int type_as_int = static_cast<int>(type);
+ return node_typeinfo_registry[type_as_int];
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory.h b/source/blender/depsgraph/intern/node/deg_node_factory.h
index 29a3eebba2b..38487e7f979 100644
--- a/source/blender/depsgraph/intern/node/deg_node_factory.h
+++ b/source/blender/depsgraph/intern/node/deg_node_factory.h
@@ -33,26 +33,21 @@ struct ID;
namespace DEG {
struct DepsNodeFactory {
- virtual NodeType type() const = 0;
- virtual const char *type_name() const = 0;
+ virtual NodeType type() const = 0;
+ virtual const char *type_name() const = 0;
- virtual int id_recalc_tag() const = 0;
+ virtual int id_recalc_tag() const = 0;
- virtual Node *create_node(const ID *id,
- const char *subdata,
- const char *name) const = 0;
+ virtual Node *create_node(const ID *id, const char *subdata, const char *name) const = 0;
};
-template <class ModeObjectType>
-struct DepsNodeFactoryImpl : public DepsNodeFactory {
- virtual NodeType type() const override;
- virtual const char *type_name() const override;
+template<class ModeObjectType> struct DepsNodeFactoryImpl : public DepsNodeFactory {
+ virtual NodeType type() const override;
+ virtual const char *type_name() const override;
- virtual int id_recalc_tag() const override;
+ virtual int id_recalc_tag() const override;
- virtual Node *create_node(const ID *id,
- const char *subdata,
- const char *name) const override;
+ virtual Node *create_node(const ID *id, const char *subdata, const char *name) const override;
};
/* Register typeinfo */
diff --git a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
index f2d478d4c16..ad25ffdf26c 100644
--- a/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
+++ b/source/blender/depsgraph/intern/node/deg_node_factory_impl.h
@@ -29,38 +29,38 @@ struct ID;
namespace DEG {
-template <class ModeObjectType>
-NodeType DepsNodeFactoryImpl<ModeObjectType>::type() const
+template<class ModeObjectType> NodeType DepsNodeFactoryImpl<ModeObjectType>::type() const
{
- return ModeObjectType::typeinfo.type;
+ return ModeObjectType::typeinfo.type;
}
-template <class ModeObjectType>
-const char *DepsNodeFactoryImpl<ModeObjectType>::type_name() const {
- return ModeObjectType::typeinfo.type_name;
+template<class ModeObjectType> const char *DepsNodeFactoryImpl<ModeObjectType>::type_name() const
+{
+ return ModeObjectType::typeinfo.type_name;
}
-template <class ModeObjectType>
-int DepsNodeFactoryImpl<ModeObjectType>::id_recalc_tag() const {
- return ModeObjectType::typeinfo.id_recalc_tag;
+template<class ModeObjectType> int DepsNodeFactoryImpl<ModeObjectType>::id_recalc_tag() const
+{
+ return ModeObjectType::typeinfo.id_recalc_tag;
}
-template <class ModeObjectType>
-Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(
- const ID *id, const char *subdata, const char *name) const
+template<class ModeObjectType>
+Node *DepsNodeFactoryImpl<ModeObjectType>::create_node(const ID *id,
+ const char *subdata,
+ const char *name) const
{
- Node *node = OBJECT_GUARDED_NEW(ModeObjectType);
- /* Populate base node settings. */
- node->type = type();
- /* Set name if provided, or use default type name. */
- if (name[0] != '\0') {
- node->name = name;
- }
- else {
- node->name = type_name();
- }
- node->init(id, subdata);
- return node;
+ Node *node = OBJECT_GUARDED_NEW(ModeObjectType);
+ /* Populate base node settings. */
+ node->type = type();
+ /* Set name if provided, or use default type name. */
+ if (name[0] != '\0') {
+ node->name = name;
+ }
+ else {
+ node->name = type_name();
+ }
+ node->init(id, subdata);
+ return node;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc
index d391f727d35..77e8f4f37e0 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_id.cc
@@ -24,7 +24,7 @@
#include "intern/node/deg_node_id.h"
#include <stdio.h>
-#include <cstring> /* required for STREQ later on. */
+#include <cstring> /* required for STREQ later on. */
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -49,198 +49,188 @@ namespace DEG {
const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state)
{
- switch (linked_state) {
- case DEG_ID_LINKED_INDIRECTLY: return "INDIRECTLY";
- case DEG_ID_LINKED_VIA_SET: return "VIA_SET";
- case DEG_ID_LINKED_DIRECTLY: return "DIRECTLY";
- }
- BLI_assert(!"Unhandled linked state, should never happen.");
- return "UNKNOW";
+ switch (linked_state) {
+ case DEG_ID_LINKED_INDIRECTLY:
+ return "INDIRECTLY";
+ case DEG_ID_LINKED_VIA_SET:
+ return "VIA_SET";
+ case DEG_ID_LINKED_DIRECTLY:
+ return "DIRECTLY";
+ }
+ BLI_assert(!"Unhandled linked state, should never happen.");
+ return "UNKNOW";
}
-IDNode::ComponentIDKey::ComponentIDKey(NodeType type,
- const char *name)
- : type(type), name(name)
+IDNode::ComponentIDKey::ComponentIDKey(NodeType type, const char *name) : type(type), name(name)
{
}
-bool IDNode::ComponentIDKey::operator== (const ComponentIDKey &other) const
+bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const
{
- return type == other.type &&
- STREQ(name, other.name);
+ return type == other.type && STREQ(name, other.name);
}
static unsigned int id_deps_node_hash_key(const void *key_v)
{
- const IDNode::ComponentIDKey *key =
- reinterpret_cast<const IDNode::ComponentIDKey *>(key_v);
- const int type_as_int = static_cast<int>(key->type);
- return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int),
- BLI_ghashutil_strhash_p(key->name));
+ const IDNode::ComponentIDKey *key = reinterpret_cast<const IDNode::ComponentIDKey *>(key_v);
+ const int type_as_int = static_cast<int>(key->type);
+ return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int),
+ BLI_ghashutil_strhash_p(key->name));
}
static bool id_deps_node_hash_key_cmp(const void *a, const void *b)
{
- const IDNode::ComponentIDKey *key_a =
- reinterpret_cast<const IDNode::ComponentIDKey *>(a);
- const IDNode::ComponentIDKey *key_b =
- reinterpret_cast<const IDNode::ComponentIDKey *>(b);
- return !(*key_a == *key_b);
+ const IDNode::ComponentIDKey *key_a = reinterpret_cast<const IDNode::ComponentIDKey *>(a);
+ const IDNode::ComponentIDKey *key_b = reinterpret_cast<const IDNode::ComponentIDKey *>(b);
+ return !(*key_a == *key_b);
}
static void id_deps_node_hash_key_free(void *key_v)
{
- typedef IDNode::ComponentIDKey ComponentIDKey;
- ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
- OBJECT_GUARDED_DELETE(key, ComponentIDKey);
+ typedef IDNode::ComponentIDKey ComponentIDKey;
+ ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v);
+ OBJECT_GUARDED_DELETE(key, ComponentIDKey);
}
static void id_deps_node_hash_value_free(void *value_v)
{
- ComponentNode *comp_node = reinterpret_cast<ComponentNode *>(value_v);
- OBJECT_GUARDED_DELETE(comp_node, ComponentNode);
+ ComponentNode *comp_node = reinterpret_cast<ComponentNode *>(value_v);
+ OBJECT_GUARDED_DELETE(comp_node, ComponentNode);
}
/* Initialize 'id' node - from pointer data given. */
void IDNode::init(const ID *id, const char *UNUSED(subdata))
{
- BLI_assert(id != NULL);
- /* Store ID-pointer. */
- id_orig = (ID *)id;
- eval_flags = 0;
- previous_eval_flags = 0;
- customdata_masks = DEGCustomDataMeshMasks();
- previous_customdata_masks = DEGCustomDataMeshMasks();
- linked_state = DEG_ID_LINKED_INDIRECTLY;
- is_directly_visible = true;
- is_collection_fully_expanded = false;
+ BLI_assert(id != NULL);
+ /* Store ID-pointer. */
+ id_orig = (ID *)id;
+ eval_flags = 0;
+ previous_eval_flags = 0;
+ customdata_masks = DEGCustomDataMeshMasks();
+ previous_customdata_masks = DEGCustomDataMeshMasks();
+ linked_state = DEG_ID_LINKED_INDIRECTLY;
+ is_directly_visible = true;
+ is_collection_fully_expanded = false;
- visible_components_mask = 0;
- previously_visible_components_mask = 0;
+ visible_components_mask = 0;
+ previously_visible_components_mask = 0;
- components = BLI_ghash_new(id_deps_node_hash_key,
- id_deps_node_hash_key_cmp,
- "Depsgraph id components hash");
+ components = BLI_ghash_new(
+ id_deps_node_hash_key, id_deps_node_hash_key_cmp, "Depsgraph id components hash");
}
void IDNode::init_copy_on_write(ID *id_cow_hint)
{
- /* Create pointer as early as possible, so we can use it for function
- * bindings. Rest of data we'll be copying to the new datablock when
- * it is actually needed. */
- if (id_cow_hint != NULL) {
- // BLI_assert(deg_copy_on_write_is_needed(id_orig));
- if (deg_copy_on_write_is_needed(id_orig)) {
- id_cow = id_cow_hint;
- }
- else {
- id_cow = id_orig;
- }
- }
- else if (deg_copy_on_write_is_needed(id_orig)) {
- id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
- DEG_COW_PRINT("Create shallow copy for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- deg_tag_copy_on_write_id(id_cow, id_orig);
- }
- else {
- id_cow = id_orig;
- }
+ /* Create pointer as early as possible, so we can use it for function
+ * bindings. Rest of data we'll be copying to the new datablock when
+ * it is actually needed. */
+ if (id_cow_hint != NULL) {
+ // BLI_assert(deg_copy_on_write_is_needed(id_orig));
+ if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = id_cow_hint;
+ }
+ else {
+ id_cow = id_orig;
+ }
+ }
+ else if (deg_copy_on_write_is_needed(id_orig)) {
+ id_cow = (ID *)BKE_libblock_alloc_notest(GS(id_orig->name));
+ DEG_COW_PRINT(
+ "Create shallow copy for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
+ deg_tag_copy_on_write_id(id_cow, id_orig);
+ }
+ else {
+ id_cow = id_orig;
+ }
}
/* Free 'id' node. */
IDNode::~IDNode()
{
- destroy();
+ destroy();
}
void IDNode::destroy()
{
- if (id_orig == NULL) {
- return;
- }
+ if (id_orig == NULL) {
+ return;
+ }
- BLI_ghash_free(components,
- id_deps_node_hash_key_free,
- id_deps_node_hash_value_free);
+ BLI_ghash_free(components, id_deps_node_hash_key_free, id_deps_node_hash_value_free);
- /* Free memory used by this CoW ID. */
- if (id_cow != id_orig && id_cow != NULL) {
- deg_free_copy_on_write_datablock(id_cow);
- MEM_freeN(id_cow);
- id_cow = NULL;
- DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n",
- id_orig->name, id_orig, id_cow);
- }
+ /* Free memory used by this CoW ID. */
+ if (id_cow != id_orig && id_cow != NULL) {
+ deg_free_copy_on_write_datablock(id_cow);
+ MEM_freeN(id_cow);
+ id_cow = NULL;
+ DEG_COW_PRINT("Destroy CoW for %s: id_orig=%p id_cow=%p\n", id_orig->name, id_orig, id_cow);
+ }
- /* Tag that the node is freed. */
- id_orig = NULL;
+ /* Tag that the node is freed. */
+ id_orig = NULL;
}
string IDNode::identifier() const
{
- char orig_ptr[24], cow_ptr[24];
- BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig);
- BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow);
- return string(nodeTypeAsString(type)) + " : " + name +
- " (orig: " + orig_ptr + ", eval: " + cow_ptr +
- ", is_directly_visible " + (is_directly_visible ? "true"
- : "false") + ")";
+ char orig_ptr[24], cow_ptr[24];
+ BLI_snprintf(orig_ptr, sizeof(orig_ptr), "%p", id_orig);
+ BLI_snprintf(cow_ptr, sizeof(cow_ptr), "%p", id_cow);
+ return string(nodeTypeAsString(type)) + " : " + name + " (orig: " + orig_ptr +
+ ", eval: " + cow_ptr + ", is_directly_visible " +
+ (is_directly_visible ? "true" : "false") + ")";
}
ComponentNode *IDNode::find_component(NodeType type, const char *name) const
{
- ComponentIDKey key(type, name);
- return reinterpret_cast<ComponentNode *>(BLI_ghash_lookup(components, &key));
+ ComponentIDKey key(type, name);
+ return reinterpret_cast<ComponentNode *>(BLI_ghash_lookup(components, &key));
}
ComponentNode *IDNode::add_component(NodeType type, const char *name)
{
- ComponentNode *comp_node = find_component(type, name);
- if (!comp_node) {
- DepsNodeFactory *factory = type_get_factory(type);
- comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
+ ComponentNode *comp_node = find_component(type, name);
+ if (!comp_node) {
+ DepsNodeFactory *factory = type_get_factory(type);
+ comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name);
- /* Register. */
- ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
- BLI_ghash_insert(components, key, comp_node);
- comp_node->owner = this;
- }
- return comp_node;
+ /* Register. */
+ ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name);
+ BLI_ghash_insert(components, key, comp_node);
+ comp_node->owner = this;
+ }
+ return comp_node;
}
void IDNode::tag_update(Depsgraph *graph, eUpdateSource source)
{
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
- {
- comp_node->tag_update(graph, source);
- }
- GHASH_FOREACH_END();
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) {
+ comp_node->tag_update(graph, source);
+ }
+ GHASH_FOREACH_END();
}
void IDNode::finalize_build(Depsgraph *graph)
{
- /* Finalize build of all components. */
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
- {
- comp_node->finalize_build(graph);
- }
- GHASH_FOREACH_END();
- visible_components_mask = get_visible_components_mask();
-}
-
-IDComponentsMask IDNode::get_visible_components_mask() const {
- IDComponentsMask result = 0;
- GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, components)
- {
- if (comp_node->affects_directly_visible) {
- const int component_type_as_int = static_cast<int>(comp_node->type);
- BLI_assert(component_type_as_int < 64);
- result |= (1ULL << component_type_as_int);
- }
- }
- GHASH_FOREACH_END();
- return result;
+ /* Finalize build of all components. */
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) {
+ comp_node->finalize_build(graph);
+ }
+ GHASH_FOREACH_END();
+ visible_components_mask = get_visible_components_mask();
+}
+
+IDComponentsMask IDNode::get_visible_components_mask() const
+{
+ IDComponentsMask result = 0;
+ GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) {
+ if (comp_node->affects_directly_visible) {
+ const int component_type_as_int = static_cast<int>(comp_node->type);
+ BLI_assert(component_type_as_int < 64);
+ result |= (1ULL << component_type_as_int);
+ }
+ }
+ GHASH_FOREACH_END();
+ return result;
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h
index bbf671790c7..34d78e29060 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.h
+++ b/source/blender/depsgraph/intern/node/deg_node_id.h
@@ -35,71 +35,71 @@ typedef uint64_t IDComponentsMask;
/* NOTE: We use max comparison to mark an id node that is linked more than once
* So keep this enum ordered accordingly. */
enum eDepsNode_LinkedState_Type {
- /* Generic indirectly linked id node. */
- DEG_ID_LINKED_INDIRECTLY = 0,
- /* Id node present in the set (background) only. */
- DEG_ID_LINKED_VIA_SET = 1,
- /* Id node directly linked via the SceneLayer. */
- DEG_ID_LINKED_DIRECTLY = 2,
+ /* Generic indirectly linked id node. */
+ DEG_ID_LINKED_INDIRECTLY = 0,
+ /* Id node present in the set (background) only. */
+ DEG_ID_LINKED_VIA_SET = 1,
+ /* Id node directly linked via the SceneLayer. */
+ DEG_ID_LINKED_DIRECTLY = 2,
};
const char *linkedStateAsString(eDepsNode_LinkedState_Type linked_state);
/* ID-Block Reference */
struct IDNode : public Node {
- struct ComponentIDKey {
- ComponentIDKey(NodeType type, const char *name = "");
- bool operator==(const ComponentIDKey &other) const;
+ struct ComponentIDKey {
+ ComponentIDKey(NodeType type, const char *name = "");
+ bool operator==(const ComponentIDKey &other) const;
- NodeType type;
- const char *name;
- };
+ NodeType type;
+ const char *name;
+ };
- virtual void init(const ID *id, const char *subdata) override;
- void init_copy_on_write(ID *id_cow_hint = NULL);
- ~IDNode();
- void destroy();
+ virtual void init(const ID *id, const char *subdata) override;
+ void init_copy_on_write(ID *id_cow_hint = NULL);
+ ~IDNode();
+ void destroy();
- virtual string identifier() const override;
+ virtual string identifier() const override;
- ComponentNode *find_component(NodeType type, const char *name = "") const;
- ComponentNode *add_component(NodeType type, const char *name = "");
+ ComponentNode *find_component(NodeType type, const char *name = "") const;
+ ComponentNode *add_component(NodeType type, const char *name = "");
- virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
- void finalize_build(Depsgraph *graph);
+ void finalize_build(Depsgraph *graph);
- IDComponentsMask get_visible_components_mask() const;
+ IDComponentsMask get_visible_components_mask() const;
- /* ID Block referenced. */
- ID *id_orig;
- ID *id_cow;
+ /* ID Block referenced. */
+ ID *id_orig;
+ ID *id_cow;
- /* Hash to make it faster to look up components. */
- GHash *components;
+ /* Hash to make it faster to look up components. */
+ GHash *components;
- /* Additional flags needed for scene evaluation.
- * TODO(sergey): Only needed for until really granular updates
- * of all the entities. */
- uint32_t eval_flags;
- uint32_t previous_eval_flags;
+ /* Additional flags needed for scene evaluation.
+ * TODO(sergey): Only needed for until really granular updates
+ * of all the entities. */
+ uint32_t eval_flags;
+ uint32_t previous_eval_flags;
- /* Extra customdata mask which needs to be evaluated for the mesh object. */
- DEGCustomDataMeshMasks customdata_masks;
- DEGCustomDataMeshMasks previous_customdata_masks;
+ /* Extra customdata mask which needs to be evaluated for the mesh object. */
+ DEGCustomDataMeshMasks customdata_masks;
+ DEGCustomDataMeshMasks previous_customdata_masks;
- eDepsNode_LinkedState_Type linked_state;
+ eDepsNode_LinkedState_Type linked_state;
- /* Indicates the datablock is visible in the evaluated scene. */
- bool is_directly_visible;
+ /* Indicates the datablock is visible in the evaluated scene. */
+ bool is_directly_visible;
- /* For the collection type of ID, denotes whether collection was fully
- * recursed into. */
- bool is_collection_fully_expanded;
+ /* For the collection type of ID, denotes whether collection was fully
+ * recursed into. */
+ bool is_collection_fully_expanded;
- IDComponentsMask visible_components_mask;
- IDComponentsMask previously_visible_components_mask;
+ IDComponentsMask visible_components_mask;
+ IDComponentsMask previously_visible_components_mask;
- DEG_DEPSNODE_DECLARE;
+ DEG_DEPSNODE_DECLARE;
};
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc
index b0b47f89acf..54a5ecef35c 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc
@@ -37,112 +37,161 @@ namespace DEG {
const char *operationCodeAsString(OperationCode opcode)
{
- switch (opcode) {
- /* Generic Operations. */
- case OperationCode::OPERATION: return "OPERATION";
- case OperationCode::ID_PROPERTY: return "ID_PROPERTY";
- case OperationCode::PARAMETERS_ENTRY: return "PARAMETERS_ENTRY";
- case OperationCode::PARAMETERS_EVAL: return "PARAMETERS_EVAL";
- case OperationCode::PARAMETERS_EXIT: return "PARAMETERS_EXIT";
- /* Animation, Drivers, etc. */
- case OperationCode::ANIMATION_ENTRY: return "ANIMATION_ENTRY";
- case OperationCode::ANIMATION_EVAL: return "ANIMATION_EVAL";
- case OperationCode::ANIMATION_EXIT: return "ANIMATION_EXIT";
- case OperationCode::DRIVER: return "DRIVER";
- /* Scene related. */
- case OperationCode::SCENE_EVAL: return "SCENE_EVAL";
- /* Object related. */
- case OperationCode::OBJECT_BASE_FLAGS: return "OBJECT_BASE_FLAGS";
- /* Transform. */
- case OperationCode::TRANSFORM_INIT: return "TRANSFORM_INIT";
- case OperationCode::TRANSFORM_LOCAL: return "TRANSFORM_LOCAL";
- case OperationCode::TRANSFORM_PARENT: return "TRANSFORM_PARENT";
- case OperationCode::TRANSFORM_CONSTRAINTS:
- return "TRANSFORM_CONSTRAINTS";
- case OperationCode::TRANSFORM_FINAL: return "TRANSFORM_FINAL";
- case OperationCode::TRANSFORM_EVAL: return "TRANSFORM_EVAL";
- case OperationCode::TRANSFORM_SIMULATION_INIT:
- return "TRANSFORM_SIMULATION_INIT";
- /* Rigid body. */
- case OperationCode::RIGIDBODY_REBUILD: return "RIGIDBODY_REBUILD";
- case OperationCode::RIGIDBODY_SIM: return "RIGIDBODY_SIM";
- case OperationCode::RIGIDBODY_TRANSFORM_COPY:
- return "RIGIDBODY_TRANSFORM_COPY";
- /* Geometry. */
- case OperationCode::GEOMETRY_EVAL_INIT: return "GEOMETRY_EVAL_INIT";
- case OperationCode::GEOMETRY_EVAL: return "GEOMETRY_EVAL";
- case OperationCode::GEOMETRY_EVAL_DONE: return "GEOMETRY_EVAL_DONE";
- case OperationCode::GEOMETRY_SHAPEKEY: return "GEOMETRY_SHAPEKEY";
- /* Object data. */
- case OperationCode::LIGHT_PROBE_EVAL: return "LIGHT_PROBE_EVAL";
- case OperationCode::SPEAKER_EVAL: return "SPEAKER_EVAL";
- case OperationCode::ARMATURE_EVAL: return "ARMATURE_EVAL";
- /* Pose. */
- case OperationCode::POSE_INIT: return "POSE_INIT";
- case OperationCode::POSE_INIT_IK: return "POSE_INIT_IK";
- case OperationCode::POSE_CLEANUP: return "POSE_CLEANUP";
- case OperationCode::POSE_DONE: return "POSE_DONE";
- case OperationCode::POSE_IK_SOLVER: return "POSE_IK_SOLVER";
- case OperationCode::POSE_SPLINE_IK_SOLVER:
- return "POSE_SPLINE_IK_SOLVER";
- /* Bone. */
- case OperationCode::BONE_LOCAL: return "BONE_LOCAL";
- case OperationCode::BONE_POSE_PARENT: return "BONE_POSE_PARENT";
- case OperationCode::BONE_CONSTRAINTS: return "BONE_CONSTRAINTS";
- case OperationCode::BONE_READY: return "BONE_READY";
- case OperationCode::BONE_DONE: return "BONE_DONE";
- case OperationCode::BONE_SEGMENTS: return "BONE_SEGMENTS";
- /* Particle System. */
- case OperationCode::PARTICLE_SYSTEM_INIT: return "PARTICLE_SYSTEM_INIT";
- case OperationCode::PARTICLE_SYSTEM_EVAL: return "PARTICLE_SYSTEM_EVAL";
- case OperationCode::PARTICLE_SYSTEM_DONE: return "PARTICLE_SYSTEM_DONE";
- /* Particles Settings. */
- case OperationCode::PARTICLE_SETTINGS_INIT:
- return "PARTICLE_SETTINGS_INIT";
- case OperationCode::PARTICLE_SETTINGS_EVAL:
- return "PARTICLE_SETTINGS_EVAL";
- case OperationCode::PARTICLE_SETTINGS_RESET:
- return "PARTICLE_SETTINGS_RESET";
- /* Point Cache. */
- case OperationCode::POINT_CACHE_RESET: return "POINT_CACHE_RESET";
- /* File cache. */
- case OperationCode::FILE_CACHE_UPDATE: return "FILE_CACHE_UPDATE";
- /* Batch cache. */
- case OperationCode::GEOMETRY_SELECT_UPDATE:
- return "GEOMETRY_SELECT_UPDATE";
- /* Masks. */
- case OperationCode::MASK_ANIMATION: return "MASK_ANIMATION";
- case OperationCode::MASK_EVAL: return "MASK_EVAL";
- /* Collections. */
- case OperationCode::VIEW_LAYER_EVAL: return "VIEW_LAYER_EVAL";
- /* Copy on write. */
- case OperationCode::COPY_ON_WRITE: return "COPY_ON_WRITE";
- /* Shading. */
- case OperationCode::SHADING: return "SHADING";
- case OperationCode::MATERIAL_UPDATE: return "MATERIAL_UPDATE";
- case OperationCode::WORLD_UPDATE: return "WORLD_UPDATE";
- /* Movie clip. */
- case OperationCode::MOVIECLIP_EVAL: return "MOVIECLIP_EVAL";
- case OperationCode::MOVIECLIP_SELECT_UPDATE:
- return "MOVIECLIP_SELECT_UPDATE";
- /* Image. */
- case OperationCode::IMAGE_ANIMATION: return "IMAGE_ANIMATION";
- /* Synchronization. */
- case OperationCode::SYNCHRONIZE_TO_ORIGINAL:
- return "SYNCHRONIZE_TO_ORIGINAL";
- /* Generic datablock. */
- case OperationCode::GENERIC_DATABLOCK_UPDATE:
- return "GENERIC_DATABLOCK_UPDATE";
- /* instancing/duplication. */
- case OperationCode::DUPLI: return "DUPLI";
- }
- BLI_assert(!"Unhandled operation code, should never happen.");
- return "UNKNOWN";
+ switch (opcode) {
+ /* Generic Operations. */
+ case OperationCode::OPERATION:
+ return "OPERATION";
+ case OperationCode::ID_PROPERTY:
+ return "ID_PROPERTY";
+ case OperationCode::PARAMETERS_ENTRY:
+ return "PARAMETERS_ENTRY";
+ case OperationCode::PARAMETERS_EVAL:
+ return "PARAMETERS_EVAL";
+ case OperationCode::PARAMETERS_EXIT:
+ return "PARAMETERS_EXIT";
+ /* Animation, Drivers, etc. */
+ case OperationCode::ANIMATION_ENTRY:
+ return "ANIMATION_ENTRY";
+ case OperationCode::ANIMATION_EVAL:
+ return "ANIMATION_EVAL";
+ case OperationCode::ANIMATION_EXIT:
+ return "ANIMATION_EXIT";
+ case OperationCode::DRIVER:
+ return "DRIVER";
+ /* Scene related. */
+ case OperationCode::SCENE_EVAL:
+ return "SCENE_EVAL";
+ /* Object related. */
+ case OperationCode::OBJECT_BASE_FLAGS:
+ return "OBJECT_BASE_FLAGS";
+ /* Transform. */
+ case OperationCode::TRANSFORM_INIT:
+ return "TRANSFORM_INIT";
+ case OperationCode::TRANSFORM_LOCAL:
+ return "TRANSFORM_LOCAL";
+ case OperationCode::TRANSFORM_PARENT:
+ return "TRANSFORM_PARENT";
+ case OperationCode::TRANSFORM_CONSTRAINTS:
+ return "TRANSFORM_CONSTRAINTS";
+ case OperationCode::TRANSFORM_FINAL:
+ return "TRANSFORM_FINAL";
+ case OperationCode::TRANSFORM_EVAL:
+ return "TRANSFORM_EVAL";
+ case OperationCode::TRANSFORM_SIMULATION_INIT:
+ return "TRANSFORM_SIMULATION_INIT";
+ /* Rigid body. */
+ case OperationCode::RIGIDBODY_REBUILD:
+ return "RIGIDBODY_REBUILD";
+ case OperationCode::RIGIDBODY_SIM:
+ return "RIGIDBODY_SIM";
+ case OperationCode::RIGIDBODY_TRANSFORM_COPY:
+ return "RIGIDBODY_TRANSFORM_COPY";
+ /* Geometry. */
+ case OperationCode::GEOMETRY_EVAL_INIT:
+ return "GEOMETRY_EVAL_INIT";
+ case OperationCode::GEOMETRY_EVAL:
+ return "GEOMETRY_EVAL";
+ case OperationCode::GEOMETRY_EVAL_DONE:
+ return "GEOMETRY_EVAL_DONE";
+ case OperationCode::GEOMETRY_SHAPEKEY:
+ return "GEOMETRY_SHAPEKEY";
+ /* Object data. */
+ case OperationCode::LIGHT_PROBE_EVAL:
+ return "LIGHT_PROBE_EVAL";
+ case OperationCode::SPEAKER_EVAL:
+ return "SPEAKER_EVAL";
+ case OperationCode::ARMATURE_EVAL:
+ return "ARMATURE_EVAL";
+ /* Pose. */
+ case OperationCode::POSE_INIT:
+ return "POSE_INIT";
+ case OperationCode::POSE_INIT_IK:
+ return "POSE_INIT_IK";
+ case OperationCode::POSE_CLEANUP:
+ return "POSE_CLEANUP";
+ case OperationCode::POSE_DONE:
+ return "POSE_DONE";
+ case OperationCode::POSE_IK_SOLVER:
+ return "POSE_IK_SOLVER";
+ case OperationCode::POSE_SPLINE_IK_SOLVER:
+ return "POSE_SPLINE_IK_SOLVER";
+ /* Bone. */
+ case OperationCode::BONE_LOCAL:
+ return "BONE_LOCAL";
+ case OperationCode::BONE_POSE_PARENT:
+ return "BONE_POSE_PARENT";
+ case OperationCode::BONE_CONSTRAINTS:
+ return "BONE_CONSTRAINTS";
+ case OperationCode::BONE_READY:
+ return "BONE_READY";
+ case OperationCode::BONE_DONE:
+ return "BONE_DONE";
+ case OperationCode::BONE_SEGMENTS:
+ return "BONE_SEGMENTS";
+ /* Particle System. */
+ case OperationCode::PARTICLE_SYSTEM_INIT:
+ return "PARTICLE_SYSTEM_INIT";
+ case OperationCode::PARTICLE_SYSTEM_EVAL:
+ return "PARTICLE_SYSTEM_EVAL";
+ case OperationCode::PARTICLE_SYSTEM_DONE:
+ return "PARTICLE_SYSTEM_DONE";
+ /* Particles Settings. */
+ case OperationCode::PARTICLE_SETTINGS_INIT:
+ return "PARTICLE_SETTINGS_INIT";
+ case OperationCode::PARTICLE_SETTINGS_EVAL:
+ return "PARTICLE_SETTINGS_EVAL";
+ case OperationCode::PARTICLE_SETTINGS_RESET:
+ return "PARTICLE_SETTINGS_RESET";
+ /* Point Cache. */
+ case OperationCode::POINT_CACHE_RESET:
+ return "POINT_CACHE_RESET";
+ /* File cache. */
+ case OperationCode::FILE_CACHE_UPDATE:
+ return "FILE_CACHE_UPDATE";
+ /* Batch cache. */
+ case OperationCode::GEOMETRY_SELECT_UPDATE:
+ return "GEOMETRY_SELECT_UPDATE";
+ /* Masks. */
+ case OperationCode::MASK_ANIMATION:
+ return "MASK_ANIMATION";
+ case OperationCode::MASK_EVAL:
+ return "MASK_EVAL";
+ /* Collections. */
+ case OperationCode::VIEW_LAYER_EVAL:
+ return "VIEW_LAYER_EVAL";
+ /* Copy on write. */
+ case OperationCode::COPY_ON_WRITE:
+ return "COPY_ON_WRITE";
+ /* Shading. */
+ case OperationCode::SHADING:
+ return "SHADING";
+ case OperationCode::MATERIAL_UPDATE:
+ return "MATERIAL_UPDATE";
+ case OperationCode::WORLD_UPDATE:
+ return "WORLD_UPDATE";
+ /* Movie clip. */
+ case OperationCode::MOVIECLIP_EVAL:
+ return "MOVIECLIP_EVAL";
+ case OperationCode::MOVIECLIP_SELECT_UPDATE:
+ return "MOVIECLIP_SELECT_UPDATE";
+ /* Image. */
+ case OperationCode::IMAGE_ANIMATION:
+ return "IMAGE_ANIMATION";
+ /* Synchronization. */
+ case OperationCode::SYNCHRONIZE_TO_ORIGINAL:
+ return "SYNCHRONIZE_TO_ORIGINAL";
+ /* Generic datablock. */
+ case OperationCode::GENERIC_DATABLOCK_UPDATE:
+ return "GENERIC_DATABLOCK_UPDATE";
+ /* instancing/duplication. */
+ case OperationCode::DUPLI:
+ return "DUPLI";
+ }
+ BLI_assert(!"Unhandled operation code, should never happen.");
+ return "UNKNOWN";
}
-OperationNode::OperationNode() :
- name_tag(-1),
- flag(0)
+OperationNode::OperationNode() : name_tag(-1), flag(0)
{
}
@@ -152,52 +201,52 @@ OperationNode::~OperationNode()
string OperationNode::identifier() const
{
- return string(operationCodeAsString(opcode)) + "(" + name + ")";
+ return string(operationCodeAsString(opcode)) + "(" + name + ")";
}
/* Full node identifier, including owner name.
* used for logging and debug prints. */
string OperationNode::full_identifier() const
{
- string owner_str = "";
- if (owner->type == NodeType::BONE) {
- owner_str = string(owner->owner->name) + "." + owner->name;
- }
- else {
- owner_str = owner->owner->name;
- }
- return owner_str + "." + identifier();
+ string owner_str = "";
+ if (owner->type == NodeType::BONE) {
+ owner_str = string(owner->owner->name) + "." + owner->name;
+ }
+ else {
+ owner_str = owner->owner->name;
+ }
+ return owner_str + "." + identifier();
}
void OperationNode::tag_update(Depsgraph *graph, eUpdateSource source)
{
- if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
- graph->add_entry_tag(this);
- }
- /* Tag for update, but also note that this was the source of an update. */
- flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
- switch (source) {
- case DEG_UPDATE_SOURCE_TIME:
- case DEG_UPDATE_SOURCE_RELATIONS:
- case DEG_UPDATE_SOURCE_VISIBILITY:
- /* Currently nothing. */
- break;
- case DEG_UPDATE_SOURCE_USER_EDIT:
- flag |= DEPSOP_FLAG_USER_MODIFIED;
- break;
- }
+ if ((flag & DEPSOP_FLAG_NEEDS_UPDATE) == 0) {
+ graph->add_entry_tag(this);
+ }
+ /* Tag for update, but also note that this was the source of an update. */
+ flag |= (DEPSOP_FLAG_NEEDS_UPDATE | DEPSOP_FLAG_DIRECTLY_MODIFIED);
+ switch (source) {
+ case DEG_UPDATE_SOURCE_TIME:
+ case DEG_UPDATE_SOURCE_RELATIONS:
+ case DEG_UPDATE_SOURCE_VISIBILITY:
+ /* Currently nothing. */
+ break;
+ case DEG_UPDATE_SOURCE_USER_EDIT:
+ flag |= DEPSOP_FLAG_USER_MODIFIED;
+ break;
+ }
}
void OperationNode::set_as_entry()
{
- BLI_assert(owner != NULL);
- owner->set_entry_operation(this);
+ BLI_assert(owner != NULL);
+ owner->set_entry_operation(this);
}
void OperationNode::set_as_exit()
{
- BLI_assert(owner != NULL);
- owner->set_exit_operation(this);
+ BLI_assert(owner != NULL);
+ owner->set_exit_operation(this);
}
DEG_DEPSNODE_DEFINE(OperationNode, NodeType::OPERATION, "Operation");
@@ -205,7 +254,7 @@ static DepsNodeFactoryImpl<OperationNode> DNTI_OPERATION;
void deg_register_operation_depsnodes()
{
- register_node_typeinfo(&DNTI_OPERATION);
+ register_node_typeinfo(&DNTI_OPERATION);
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index 56207b08d4a..c959f7f34e0 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -40,158 +40,158 @@ typedef function<void(struct ::Depsgraph *)> DepsEvalOperationCb;
/* Identifiers for common operations (as an enum). */
enum class OperationCode {
- /* Generic Operations. -------------------------------------------------- */
-
- /* Placeholder for operations which don't need special mention */
- OPERATION = 0,
-
- /* Generic parameters evaluation. */
- ID_PROPERTY,
- PARAMETERS_ENTRY,
- PARAMETERS_EVAL,
- PARAMETERS_EXIT,
-
- /* Animation, Drivers, etc. --------------------------------------------- */
- /* NLA + Action */
- ANIMATION_ENTRY,
- ANIMATION_EVAL,
- ANIMATION_EXIT,
- /* Driver */
- DRIVER,
-
- /* Scene related. ------------------------------------------------------- */
- SCENE_EVAL,
-
- /* Object related. ------------------------------------------------------ */
- OBJECT_BASE_FLAGS,
-
- /* Transform. ----------------------------------------------------------- */
- /* Transform entry point. */
- TRANSFORM_INIT,
- /* Local transforms only */
- TRANSFORM_LOCAL,
- /* Parenting */
- TRANSFORM_PARENT,
- /* Constraints */
- TRANSFORM_CONSTRAINTS,
- /* Handle object-level updates, mainly proxies hacks and recalc flags. */
- TRANSFORM_EVAL,
- /* Initializes transformation for simulation.
- * For example, ensures point cache is properly reset before doing rigid
- * body simulation. */
- TRANSFORM_SIMULATION_INIT,
- /* Transform exit point */
- TRANSFORM_FINAL,
-
- /* Rigid body. ---------------------------------------------------------- */
- /* Perform Simulation */
- RIGIDBODY_REBUILD,
- RIGIDBODY_SIM,
- /* Copy results to object */
- RIGIDBODY_TRANSFORM_COPY,
-
- /* Geometry. ------------------------------------------------------------ */
-
- /* Initialize evaluation of the geometry. Is an entry operation of geometry
- * component. */
- GEOMETRY_EVAL_INIT,
- /* Evaluate the whole geometry, including modifiers. */
- GEOMETRY_EVAL,
- /* Evaluation of geometry is completely done.. */
- GEOMETRY_EVAL_DONE,
- /* Evaluation of a shape key.
- * NOTE: Currently only for object data datablocks. */
- GEOMETRY_SHAPEKEY,
-
- /* Object data. --------------------------------------------------------- */
- LIGHT_PROBE_EVAL,
- SPEAKER_EVAL,
- ARMATURE_EVAL,
-
- /* Pose. ---------------------------------------------------------------- */
- /* Init pose, clear flags, etc. */
- POSE_INIT,
- /* Initialize IK solver related pose stuff. */
- POSE_INIT_IK,
- /* Pose is evaluated, and runtime data can be freed. */
- POSE_CLEANUP,
- /* Pose has been fully evaluated and ready to be used by others. */
- POSE_DONE,
- /* IK/Spline Solvers */
- POSE_IK_SOLVER,
- POSE_SPLINE_IK_SOLVER,
-
- /* Bone. ---------------------------------------------------------------- */
- /* Bone local transforms - entry point */
- BONE_LOCAL,
- /* Pose-space conversion (includes parent + restpose, */
- BONE_POSE_PARENT,
- /* Constraints */
- BONE_CONSTRAINTS,
- /* Bone transforms are ready
- *
- * - "READY" This (internal, noop is used to signal that all pre-IK
- * operations are done. Its role is to help mediate situations
- * where cyclic relations may otherwise form (i.e. one bone in
- * chain targeting another in same chain,
- *
- * - "DONE" This noop is used to signal that the bone's final pose
- * transform can be read by others. */
- // TODO: deform mats could get calculated in the final_transform ops...
- BONE_READY,
- BONE_DONE,
- /* B-Bone segment shape computation (after DONE) */
- BONE_SEGMENTS,
-
- /* Particle System. ----------------------------------------------------- */
- PARTICLE_SYSTEM_INIT,
- PARTICLE_SYSTEM_EVAL,
- PARTICLE_SYSTEM_DONE,
-
- /* Particle Settings. --------------------------------------------------- */
- PARTICLE_SETTINGS_INIT,
- PARTICLE_SETTINGS_EVAL,
- PARTICLE_SETTINGS_RESET,
-
- /* Point Cache. --------------------------------------------------------- */
- POINT_CACHE_RESET,
-
- /* File cache. ---------------------------------------------------------- */
- FILE_CACHE_UPDATE,
-
- /* Collections. --------------------------------------------------------- */
- VIEW_LAYER_EVAL,
-
- /* Copy on Write. ------------------------------------------------------- */
- COPY_ON_WRITE,
-
- /* Shading. ------------------------------------------------------------- */
- SHADING,
- MATERIAL_UPDATE,
- WORLD_UPDATE,
-
- /* Batch caches. -------------------------------------------------------- */
- GEOMETRY_SELECT_UPDATE,
-
- /* Masks. --------------------------------------------------------------- */
- MASK_ANIMATION,
- MASK_EVAL,
-
- /* Movie clips. --------------------------------------------------------- */
- MOVIECLIP_EVAL,
- MOVIECLIP_SELECT_UPDATE,
-
- /* Images. -------------------------------------------------------------- */
- IMAGE_ANIMATION,
-
- /* Synchronization clips. ----------------------------------------------- */
- SYNCHRONIZE_TO_ORIGINAL,
-
- /* Generic datablock ---------------------------------------------------- */
- GENERIC_DATABLOCK_UPDATE,
-
- /* Duplication/instancing system. --------------------------------------- */
- DUPLI,
+ /* Generic Operations. -------------------------------------------------- */
+
+ /* Placeholder for operations which don't need special mention */
+ OPERATION = 0,
+
+ /* Generic parameters evaluation. */
+ ID_PROPERTY,
+ PARAMETERS_ENTRY,
+ PARAMETERS_EVAL,
+ PARAMETERS_EXIT,
+
+ /* Animation, Drivers, etc. --------------------------------------------- */
+ /* NLA + Action */
+ ANIMATION_ENTRY,
+ ANIMATION_EVAL,
+ ANIMATION_EXIT,
+ /* Driver */
+ DRIVER,
+
+ /* Scene related. ------------------------------------------------------- */
+ SCENE_EVAL,
+
+ /* Object related. ------------------------------------------------------ */
+ OBJECT_BASE_FLAGS,
+
+ /* Transform. ----------------------------------------------------------- */
+ /* Transform entry point. */
+ TRANSFORM_INIT,
+ /* Local transforms only */
+ TRANSFORM_LOCAL,
+ /* Parenting */
+ TRANSFORM_PARENT,
+ /* Constraints */
+ TRANSFORM_CONSTRAINTS,
+ /* Handle object-level updates, mainly proxies hacks and recalc flags. */
+ TRANSFORM_EVAL,
+ /* Initializes transformation for simulation.
+ * For example, ensures point cache is properly reset before doing rigid
+ * body simulation. */
+ TRANSFORM_SIMULATION_INIT,
+ /* Transform exit point */
+ TRANSFORM_FINAL,
+
+ /* Rigid body. ---------------------------------------------------------- */
+ /* Perform Simulation */
+ RIGIDBODY_REBUILD,
+ RIGIDBODY_SIM,
+ /* Copy results to object */
+ RIGIDBODY_TRANSFORM_COPY,
+
+ /* Geometry. ------------------------------------------------------------ */
+
+ /* Initialize evaluation of the geometry. Is an entry operation of geometry
+ * component. */
+ GEOMETRY_EVAL_INIT,
+ /* Evaluate the whole geometry, including modifiers. */
+ GEOMETRY_EVAL,
+ /* Evaluation of geometry is completely done.. */
+ GEOMETRY_EVAL_DONE,
+ /* Evaluation of a shape key.
+ * NOTE: Currently only for object data datablocks. */
+ GEOMETRY_SHAPEKEY,
+
+ /* Object data. --------------------------------------------------------- */
+ LIGHT_PROBE_EVAL,
+ SPEAKER_EVAL,
+ ARMATURE_EVAL,
+
+ /* Pose. ---------------------------------------------------------------- */
+ /* Init pose, clear flags, etc. */
+ POSE_INIT,
+ /* Initialize IK solver related pose stuff. */
+ POSE_INIT_IK,
+ /* Pose is evaluated, and runtime data can be freed. */
+ POSE_CLEANUP,
+ /* Pose has been fully evaluated and ready to be used by others. */
+ POSE_DONE,
+ /* IK/Spline Solvers */
+ POSE_IK_SOLVER,
+ POSE_SPLINE_IK_SOLVER,
+
+ /* Bone. ---------------------------------------------------------------- */
+ /* Bone local transforms - entry point */
+ BONE_LOCAL,
+ /* Pose-space conversion (includes parent + restpose, */
+ BONE_POSE_PARENT,
+ /* Constraints */
+ BONE_CONSTRAINTS,
+ /* Bone transforms are ready
+ *
+ * - "READY" This (internal, noop is used to signal that all pre-IK
+ * operations are done. Its role is to help mediate situations
+ * where cyclic relations may otherwise form (i.e. one bone in
+ * chain targeting another in same chain,
+ *
+ * - "DONE" This noop is used to signal that the bone's final pose
+ * transform can be read by others. */
+ // TODO: deform mats could get calculated in the final_transform ops...
+ BONE_READY,
+ BONE_DONE,
+ /* B-Bone segment shape computation (after DONE) */
+ BONE_SEGMENTS,
+
+ /* Particle System. ----------------------------------------------------- */
+ PARTICLE_SYSTEM_INIT,
+ PARTICLE_SYSTEM_EVAL,
+ PARTICLE_SYSTEM_DONE,
+
+ /* Particle Settings. --------------------------------------------------- */
+ PARTICLE_SETTINGS_INIT,
+ PARTICLE_SETTINGS_EVAL,
+ PARTICLE_SETTINGS_RESET,
+
+ /* Point Cache. --------------------------------------------------------- */
+ POINT_CACHE_RESET,
+
+ /* File cache. ---------------------------------------------------------- */
+ FILE_CACHE_UPDATE,
+
+ /* Collections. --------------------------------------------------------- */
+ VIEW_LAYER_EVAL,
+
+ /* Copy on Write. ------------------------------------------------------- */
+ COPY_ON_WRITE,
+
+ /* Shading. ------------------------------------------------------------- */
+ SHADING,
+ MATERIAL_UPDATE,
+ WORLD_UPDATE,
+
+ /* Batch caches. -------------------------------------------------------- */
+ GEOMETRY_SELECT_UPDATE,
+
+ /* Masks. --------------------------------------------------------------- */
+ MASK_ANIMATION,
+ MASK_EVAL,
+
+ /* Movie clips. --------------------------------------------------------- */
+ MOVIECLIP_EVAL,
+ MOVIECLIP_SELECT_UPDATE,
+
+ /* Images. -------------------------------------------------------------- */
+ IMAGE_ANIMATION,
+
+ /* Synchronization clips. ----------------------------------------------- */
+ SYNCHRONIZE_TO_ORIGINAL,
+
+ /* Generic datablock ---------------------------------------------------- */
+ GENERIC_DATABLOCK_UPDATE,
+
+ /* Duplication/instancing system. --------------------------------------- */
+ DUPLI,
};
const char *operationCodeAsString(OperationCode opcode);
@@ -199,58 +199,63 @@ const char *operationCodeAsString(OperationCode opcode);
* NOTE: IS a bit shifts to allow usage as an accumulated. bitmask.
*/
enum OperationFlag {
- /* Node needs to be updated. */
- DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
- /* Node was directly modified, causing need for update. */
- DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
- /* Node was updated due to user input. */
- DEPSOP_FLAG_USER_MODIFIED = (1 << 2),
-
- /* Set of flags which gets flushed along the relations. */
- DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
+ /* Node needs to be updated. */
+ DEPSOP_FLAG_NEEDS_UPDATE = (1 << 0),
+ /* Node was directly modified, causing need for update. */
+ DEPSOP_FLAG_DIRECTLY_MODIFIED = (1 << 1),
+ /* Node was updated due to user input. */
+ DEPSOP_FLAG_USER_MODIFIED = (1 << 2),
+
+ /* Set of flags which gets flushed along the relations. */
+ DEPSOP_FLAG_FLUSH = (DEPSOP_FLAG_USER_MODIFIED),
};
/* Atomic Operation - Base type for all operations */
struct OperationNode : public Node {
- OperationNode();
- ~OperationNode();
+ OperationNode();
+ ~OperationNode();
- virtual string identifier() const override;
- string full_identifier() const;
+ virtual string identifier() const override;
+ string full_identifier() const;
- virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
- bool is_noop() const { return (bool)evaluate == false; }
+ bool is_noop() const
+ {
+ return (bool)evaluate == false;
+ }
- virtual OperationNode *get_entry_operation() override {
- return this;
- }
- virtual OperationNode *get_exit_operation() override {
- return this;
- }
+ virtual OperationNode *get_entry_operation() override
+ {
+ return this;
+ }
+ virtual OperationNode *get_exit_operation() override
+ {
+ return this;
+ }
- /* Set this operation as component's entry/exit operation. */
- void set_as_entry();
- void set_as_exit();
+ /* Set this operation as component's entry/exit operation. */
+ void set_as_entry();
+ void set_as_exit();
- /* Component that contains the operation. */
- ComponentNode *owner;
+ /* Component that contains the operation. */
+ ComponentNode *owner;
- /* Callback for operation. */
- DepsEvalOperationCb evaluate;
+ /* Callback for operation. */
+ DepsEvalOperationCb evaluate;
- /* How many inlinks are we still waiting on before we can be evaluated. */
- uint32_t num_links_pending;
- bool scheduled;
+ /* How many inlinks are we still waiting on before we can be evaluated. */
+ uint32_t num_links_pending;
+ bool scheduled;
- /* Identifier for the operation being performed. */
- OperationCode opcode;
- int name_tag;
+ /* Identifier for the operation being performed. */
+ OperationCode opcode;
+ int name_tag;
- /* (OperationFlag) extra settings affecting evaluation. */
- int flag;
+ /* (OperationFlag) extra settings affecting evaluation. */
+ int flag;
- DEG_DEPSNODE_DECLARE;
+ DEG_DEPSNODE_DECLARE;
};
void deg_register_operation_depsnodes();
diff --git a/source/blender/depsgraph/intern/node/deg_node_time.cc b/source/blender/depsgraph/intern/node/deg_node_time.cc
index 24d99d23c25..cae98ef56c0 100644
--- a/source/blender/depsgraph/intern/node/deg_node_time.cc
+++ b/source/blender/depsgraph/intern/node/deg_node_time.cc
@@ -31,10 +31,10 @@ namespace DEG {
void TimeSourceNode::tag_update(Depsgraph *graph, eUpdateSource /*source*/)
{
- for (Relation *rel : outlinks) {
- Node *node = rel->to;
- node->tag_update(graph, DEG_UPDATE_SOURCE_TIME);
- }
+ for (Relation *rel : outlinks) {
+ Node *node = rel->to;
+ node->tag_update(graph, DEG_UPDATE_SOURCE_TIME);
+ }
}
} // namespace DEG
diff --git a/source/blender/depsgraph/intern/node/deg_node_time.h b/source/blender/depsgraph/intern/node/deg_node_time.h
index 44b67ebc307..684414f7780 100644
--- a/source/blender/depsgraph/intern/node/deg_node_time.h
+++ b/source/blender/depsgraph/intern/node/deg_node_time.h
@@ -29,17 +29,17 @@ namespace DEG {
/* Time Source Node. */
struct TimeSourceNode : public Node {
- /* New "current time". */
- float cfra;
+ /* New "current time". */
+ float cfra;
- /* time-offset relative to the "official" time source that this one has. */
- float offset;
+ /* time-offset relative to the "official" time source that this one has. */
+ float offset;
- // TODO: evaluate() operation needed
+ // TODO: evaluate() operation needed
- virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
+ virtual void tag_update(Depsgraph *graph, eUpdateSource source) override;
- DEG_DEPSNODE_DECLARE;
+ DEG_DEPSNODE_DECLARE;
};
} // namespace DEG