51d1e08d70a93620407149ed71c610d27c8e3e16
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2016 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Sergey Sharybin
22  * Contributor(s): None Yet
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/builder/deg_builder.cc
28  *  \ingroup depsgraph
29  */
30
31 #include "intern/builder/deg_builder.h"
32
33 // TODO(sergey): Use own wrapper over STD.
34 #include <stack>
35
36 #include "DNA_anim_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_ID.h"
39
40 #include "BLI_utildefines.h"
41 #include "BLI_ghash.h"
42
43 #include "intern/depsgraph.h"
44 #include "intern/depsgraph_types.h"
45 #include "intern/nodes/deg_node.h"
46 #include "intern/nodes/deg_node_component.h"
47 #include "intern/nodes/deg_node_operation.h"
48
49 #include "util/deg_util_foreach.h"
50
51 namespace DEG {
52
53 string deg_fcurve_id_name(const FCurve *fcu)
54 {
55         char index_buf[32];
56         // TODO(sergey): Use int-to-string utility or so.
57         BLI_snprintf(index_buf, sizeof(index_buf), "[%d]", fcu->array_index);
58         return string(fcu->rna_path) + index_buf;
59 }
60
61 static bool check_object_needs_evaluation(Object *object)
62 {
63         if (object->recalc & OB_RECALC_ALL) {
64                 /* Object is tagged for update anyway, no need to re-tag it. */
65                 return false;
66         }
67         if (object->type == OB_MESH) {
68                 return object->derivedFinal == NULL;
69         }
70         else if (ELEM(object->type,
71                       OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
72         {
73                 return object->curve_cache == NULL;
74         }
75         return false;
76 }
77
78 void deg_graph_build_finalize(Depsgraph *graph)
79 {
80         /* STEP 1: Make sure new invisible dependencies are ready for use.
81          *
82          * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
83          * to do it ahead of a time and don't spend time on flushing updates on
84          * every frame change.
85          */
86         GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
87         {
88                 if (id_node->layers == 0) {
89                         ID *id = id_node->id;
90                         if (GS(id->name) == ID_OB) {
91                                 Object *object = (Object *)id;
92                                 if (check_object_needs_evaluation(object)) {
93                                         id_node->tag_update(graph);
94                                 }
95                         }
96                 }
97         }
98         GHASH_FOREACH_END();
99         /* STEP 2: Flush visibility layers from children to parent. */
100         std::stack<OperationDepsNode *> stack;
101         foreach (OperationDepsNode *node, graph->operations) {
102                 IDDepsNode *id_node = node->owner->owner;
103                 node->done = 0;
104                 node->num_links_pending = 0;
105                 foreach (DepsRelation *rel, node->outlinks) {
106                         if ((rel->from->type == DEPSNODE_TYPE_OPERATION) &&
107                             (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
108                         {
109                                 ++node->num_links_pending;
110                         }
111                 }
112                 if (node->num_links_pending == 0) {
113                         stack.push(node);
114                         node->done = 1;
115                 }
116                 node->owner->layers = id_node->layers;
117                 id_node->id->tag |= LIB_TAG_DOIT;
118         }
119         while (!stack.empty()) {
120                 OperationDepsNode *node = stack.top();
121                 stack.pop();
122                 /* Flush layers to parents. */
123                 foreach (DepsRelation *rel, node->inlinks) {
124                         if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
125                                 OperationDepsNode *from = (OperationDepsNode *)rel->from;
126                                 from->owner->layers |= node->owner->layers;
127                         }
128                 }
129                 /* Schedule parent nodes. */
130                 foreach (DepsRelation *rel, node->inlinks) {
131                         if (rel->from->type == DEPSNODE_TYPE_OPERATION) {
132                                 OperationDepsNode *from = (OperationDepsNode *)rel->from;
133                                 if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
134                                         BLI_assert(from->num_links_pending > 0);
135                                         --from->num_links_pending;
136                                 }
137                                 if (from->num_links_pending == 0 && from->done == 0) {
138                                         stack.push(from);
139                                         from->done = 1;
140                                 }
141                         }
142                 }
143         }
144         /* STEP 3: Re-tag IDs for update if it was tagged before the relations
145          * update tag.
146          */
147         GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
148         {
149                 GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components)
150                 {
151                         id_node->layers |= comp->layers;
152                 }
153                 GHASH_FOREACH_END();
154
155                 ID *id = id_node->id;
156                 if ((id->tag & LIB_TAG_ID_RECALC_ALL) &&
157                     (id->tag & LIB_TAG_DOIT))
158                 {
159                         id_node->tag_update(graph);
160                         id->tag &= ~LIB_TAG_DOIT;
161                 }
162                 else if (GS(id->name) == ID_OB) {
163                         Object *object = (Object *)id;
164                         if (object->recalc & OB_RECALC_ALL) {
165                                 id_node->tag_update(graph);
166                                 id->tag &= ~LIB_TAG_DOIT;
167                         }
168                 }
169                 id_node->finalize_build();
170         }
171         GHASH_FOREACH_END();
172 }
173
174 }  // namespace DEG