Merge branch 'blender2.7'
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder.cc
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2016 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file blender/depsgraph/intern/builder/deg_builder.cc
21  *  \ingroup depsgraph
22  */
23
24 #include "intern/builder/deg_builder.h"
25
26 #include "DNA_anim_types.h"
27 #include "DNA_object_types.h"
28 #include "DNA_ID.h"
29
30 #include "BLI_utildefines.h"
31 #include "BLI_ghash.h"
32 #include "BLI_stack.h"
33
34 extern "C" {
35 #include "BKE_animsys.h"
36 }
37
38 #include "intern/depsgraph.h"
39 #include "intern/depsgraph_tag.h"
40 #include "intern/depsgraph_type.h"
41 #include "intern/eval/deg_eval_copy_on_write.h"
42 #include "intern/node/deg_node.h"
43 #include "intern/node/deg_node_id.h"
44 #include "intern/node/deg_node_component.h"
45 #include "intern/node/deg_node_operation.h"
46
47 #include "DEG_depsgraph.h"
48
49 namespace DEG {
50
51 namespace {
52
53 void deg_graph_build_flush_visibility(Depsgraph *graph)
54 {
55         enum {
56                 DEG_NODE_VISITED = (1 << 0),
57         };
58
59         BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *),
60                                          "DEG flush layers stack");
61         for (IDNode *id_node : graph->id_nodes) {
62                 GHASH_FOREACH_BEGIN(ComponentNode *, comp_node, id_node->components)
63                 {
64                         comp_node->affects_directly_visible |= id_node->is_directly_visible;
65                 }
66                 GHASH_FOREACH_END();
67         }
68         for (OperationNode *op_node : graph->operations) {
69                 op_node->custom_flags = 0;
70                 op_node->num_links_pending = 0;
71                 for (Relation *rel : op_node->outlinks) {
72                         if ((rel->from->type == NodeType::OPERATION) &&
73                             (rel->flag & RELATION_FLAG_CYCLIC) == 0)
74                         {
75                                 ++op_node->num_links_pending;
76                         }
77                 }
78                 if (op_node->num_links_pending == 0) {
79                         BLI_stack_push(stack, &op_node);
80                         op_node->custom_flags |= DEG_NODE_VISITED;
81                 }
82         }
83         while (!BLI_stack_is_empty(stack)) {
84                 OperationNode *op_node;
85                 BLI_stack_pop(stack, &op_node);
86                 /* Flush layers to parents. */
87                 for (Relation *rel : op_node->inlinks) {
88                         if (rel->from->type == NodeType::OPERATION) {
89                                 OperationNode *op_from = (OperationNode *)rel->from;
90                                 op_from->owner->affects_directly_visible |=
91                                         op_node->owner->affects_directly_visible;
92                         }
93                 }
94                 /* Schedule parent nodes. */
95                 for (Relation *rel : op_node->inlinks) {
96                         if (rel->from->type == NodeType::OPERATION) {
97                                 OperationNode *op_from = (OperationNode *)rel->from;
98                                 if ((rel->flag & RELATION_FLAG_CYCLIC) == 0) {
99                                         BLI_assert(op_from->num_links_pending > 0);
100                                         --op_from->num_links_pending;
101                                 }
102                                 if ((op_from->num_links_pending == 0) &&
103                                     (op_from->custom_flags & DEG_NODE_VISITED) == 0)
104                                 {
105                                         BLI_stack_push(stack, &op_from);
106                                         op_from->custom_flags |= DEG_NODE_VISITED;
107                                 }
108                         }
109                 }
110         }
111         BLI_stack_free(stack);
112 }
113
114 }  // namespace
115
116 void deg_graph_build_finalize(Main *bmain, Depsgraph *graph)
117 {
118         /* Make sure dependencies of visible ID datablocks are visible. */
119         deg_graph_build_flush_visibility(graph);
120         /* Re-tag IDs for update if it was tagged before the relations
121          * update tag. */
122         for (IDNode *id_node : graph->id_nodes) {
123                 ID *id = id_node->id_orig;
124                 id_node->finalize_build(graph);
125                 int flag = 0;
126                 /* Tag rebuild if special evaluation flags changed. */
127                 if (id_node->eval_flags != id_node->previous_eval_flags) {
128                         flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
129                 }
130                 /* Tag rebuild if the custom data mask changed. */
131                 if (id_node->customdata_mask != id_node->previous_customdata_mask) {
132                         flag |= ID_RECALC_GEOMETRY;
133                 }
134                 if (!deg_copy_on_write_is_expanded(id_node->id_cow)) {
135                         flag |= ID_RECALC_COPY_ON_WRITE;
136                         /* This means ID is being added to the dependency graph first
137                          * time, which is similar to "ob-visible-change" */
138                         if (GS(id->name) == ID_OB) {
139                                 flag |= ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY;
140                         }
141                 }
142                 if (flag != 0) {
143                         graph_id_tag_update(bmain,
144                                             graph,
145                                             id_node->id_orig,
146                                             flag,
147                                             DEG_UPDATE_SOURCE_RELATIONS);
148                 }
149         }
150 }
151
152 }  // namespace DEG