Cleanup: whitespace
[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 #include "DNA_anim_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_ID.h"
36
37 #include "BLI_utildefines.h"
38 #include "BLI_ghash.h"
39 #include "BLI_stack.h"
40
41 #include "intern/depsgraph.h"
42 #include "intern/depsgraph_types.h"
43 #include "intern/nodes/deg_node.h"
44 #include "intern/nodes/deg_node_component.h"
45 #include "intern/nodes/deg_node_operation.h"
46
47 #include "util/deg_util_foreach.h"
48
49 #include <cstdio>
50
51 namespace DEG {
52
53 static bool check_object_needs_evaluation(Object *object)
54 {
55         if (object->recalc & OB_RECALC_ALL) {
56                 /* Object is tagged for update anyway, no need to re-tag it. */
57                 return false;
58         }
59         if (object->type == OB_MESH) {
60                 return object->derivedFinal == NULL;
61         }
62         else if (ELEM(object->type,
63                       OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE))
64         {
65                 return object->curve_cache == NULL;
66         }
67         return false;
68 }
69
70 void deg_graph_build_flush_layers(Depsgraph *graph)
71 {
72         BLI_Stack *stack = BLI_stack_new(sizeof(OperationDepsNode *),
73                                          "DEG flush layers stack");
74         foreach (OperationDepsNode *node, graph->operations) {
75                 IDDepsNode *id_node = node->owner->owner;
76                 node->done = 0;
77                 node->num_links_pending = 0;
78                 foreach (DepsRelation *rel, node->outlinks) {
79                         if ((rel->from->type == DEG_NODE_TYPE_OPERATION) &&
80                             (rel->flag & DEPSREL_FLAG_CYCLIC) == 0)
81                         {
82                                 ++node->num_links_pending;
83                         }
84                 }
85                 if (node->num_links_pending == 0) {
86                         BLI_stack_push(stack, &node);
87                         node->done = 1;
88                 }
89                 node->owner->layers = id_node->layers;
90                 id_node->id->tag |= LIB_TAG_DOIT;
91         }
92         while (!BLI_stack_is_empty(stack)) {
93                 OperationDepsNode *node;
94                 BLI_stack_pop(stack, &node);
95                 /* Flush layers to parents. */
96                 foreach (DepsRelation *rel, node->inlinks) {
97                         if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
98                                 OperationDepsNode *from = (OperationDepsNode *)rel->from;
99                                 from->owner->layers |= node->owner->layers;
100                         }
101                 }
102                 /* Schedule parent nodes. */
103                 foreach (DepsRelation *rel, node->inlinks) {
104                         if (rel->from->type == DEG_NODE_TYPE_OPERATION) {
105                                 OperationDepsNode *from = (OperationDepsNode *)rel->from;
106                                 if ((rel->flag & DEPSREL_FLAG_CYCLIC) == 0) {
107                                         BLI_assert(from->num_links_pending > 0);
108                                         --from->num_links_pending;
109                                 }
110                                 if (from->num_links_pending == 0 && from->done == 0) {
111                                         BLI_stack_push(stack, &from);
112                                         from->done = 1;
113                                 }
114                         }
115                 }
116         }
117         BLI_stack_free(stack);
118 }
119
120 void deg_graph_build_finalize(Depsgraph *graph)
121 {
122         /* STEP 1: Make sure new invisible dependencies are ready for use.
123          *
124          * TODO(sergey): This might do a bit of extra tagging, but it's kinda nice
125          * to do it ahead of a time and don't spend time on flushing updates on
126          * every frame change.
127          */
128         GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
129         {
130                 if (id_node->layers == 0) {
131                         ID *id = id_node->id;
132                         if (GS(id->name) == ID_OB) {
133                                 Object *object = (Object *)id;
134                                 if (check_object_needs_evaluation(object)) {
135                                         id_node->tag_update(graph);
136                                 }
137                         }
138                 }
139         }
140         GHASH_FOREACH_END();
141         /* STEP 2: Flush visibility layers from children to parent. */
142         deg_graph_build_flush_layers(graph);
143         /* STEP 3: Re-tag IDs for update if it was tagged before the relations
144          * update tag.
145          */
146         GHASH_FOREACH_BEGIN(IDDepsNode *, id_node, graph->id_hash)
147         {
148                 GHASH_FOREACH_BEGIN(ComponentDepsNode *, comp, id_node->components)
149                 {
150                         id_node->layers |= comp->layers;
151                 }
152                 GHASH_FOREACH_END();
153
154                 if ((id_node->layers & graph->layers) != 0 || graph->layers == 0) {
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                 }
170                 id_node->finalize_build();
171         }
172         GHASH_FOREACH_END();
173 }
174
175 }  // namespace DEG