f5b9a9ed25a77a2005c77d64a8d6fe964f480ce2
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations_impl.h
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) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Lukas Toenne
22  * Contributor(s): Sergey SHarybin
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/builder/deg_builder_relations_impl.h
28  *  \ingroup depsgraph
29  */
30
31 #pragma once
32
33 #include "intern/nodes/deg_node_id.h"
34
35 extern "C" {
36 #include "DNA_ID.h"
37 }
38
39 namespace DEG {
40
41 template <typename KeyType>
42 OperationDepsNode *DepsgraphRelationBuilder::find_operation_node(const KeyType& key)
43 {
44         DepsNode *node = get_node(key);
45         return node != NULL ? node->get_exit_operation() : NULL;
46 }
47
48 template <typename KeyFrom, typename KeyTo>
49 DepsRelation *DepsgraphRelationBuilder::add_relation(const KeyFrom &key_from,
50                                                      const KeyTo &key_to,
51                                                      const char *description,
52                                                      bool check_unique,
53                                                      int flags)
54 {
55         DepsNode *node_from = get_node(key_from);
56         DepsNode *node_to = get_node(key_to);
57         OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
58         OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
59         if (op_from && op_to) {
60                 return add_operation_relation(
61                         op_from, op_to, description, check_unique, flags);
62         }
63         else {
64                 if (!op_from) {
65                         /* XXX TODO handle as error or report if needed */
66                         fprintf(stderr, "add_relation(%s) - Could not find op_from (%s)\n",
67                                 description, key_from.identifier().c_str());
68                 }
69                 else {
70                         fprintf(stderr, "add_relation(%s) - Failed, but op_from (%s) was ok\n",
71                                 description, key_from.identifier().c_str());
72                 }
73                 if (!op_to) {
74                         /* XXX TODO handle as error or report if needed */
75                         fprintf(stderr, "add_relation(%s) - Could not find op_to (%s)\n",
76                                 description, key_to.identifier().c_str());
77                 }
78                 else {
79                         fprintf(stderr, "add_relation(%s) - Failed, but op_to (%s) was ok\n",
80                                 description, key_to.identifier().c_str());
81                 }
82         }
83         return NULL;
84 }
85
86 template <typename KeyFrom, typename KeyTo>
87 DepsRelation *DepsgraphRelationBuilder::add_relation(
88         const KeyFrom& key_from,
89         const KeyTo& key_to,
90         const char *description,
91         eDepsRelation_Flag flag)
92 {
93         return add_relation(
94                 key_from, key_to, description, false, static_cast<int>(flag));
95 }
96
97 template <typename KeyTo>
98 DepsRelation *DepsgraphRelationBuilder::add_relation(
99         const TimeSourceKey &key_from,
100         const KeyTo &key_to,
101         const char *description,
102         bool check_unique,
103         int flags)
104 {
105         TimeSourceDepsNode *time_from = get_node(key_from);
106         DepsNode *node_to = get_node(key_to);
107         OperationDepsNode *op_to = node_to ? node_to->get_entry_operation() : NULL;
108         if (time_from != NULL && op_to != NULL) {
109                 return add_time_relation(
110                         time_from, op_to, description, check_unique, flags);
111         }
112         return NULL;
113 }
114
115 template <typename KeyType>
116 DepsRelation *DepsgraphRelationBuilder::add_node_handle_relation(
117         const KeyType &key_from,
118         const DepsNodeHandle *handle,
119         const char *description,
120         bool check_unique,
121         int flags)
122 {
123         DepsNode *node_from = get_node(key_from);
124         OperationDepsNode *op_from = node_from ? node_from->get_exit_operation() : NULL;
125         OperationDepsNode *op_to = handle->node->get_entry_operation();
126         if (op_from != NULL && op_to != NULL) {
127                 return add_operation_relation(
128                         op_from, op_to, description, check_unique, flags);
129         }
130         else {
131                 if (!op_from) {
132                         fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_from (%s)\n",
133                                 description, key_from.identifier().c_str());
134                 }
135                 if (!op_to) {
136                         fprintf(stderr, "add_node_handle_relation(%s) - Could not find op_to (%s)\n",
137                                 description, key_from.identifier().c_str());
138                 }
139         }
140         return NULL;
141 }
142
143 template <typename KeyType>
144 DepsNodeHandle DepsgraphRelationBuilder::create_node_handle(
145         const KeyType &key,
146         const char *default_name)
147 {
148         return DepsNodeHandle(this, get_node(key), default_name);
149 }
150
151 /* Rig compatibility: we check if bone is using local transform as a variable
152  * for driver on itself and ignore those relations to avoid "false-positive"
153  * dependency cycles.
154  */
155 template <typename KeyFrom, typename KeyTo>
156 bool DepsgraphRelationBuilder::is_same_bone_dependency(const KeyFrom& key_from,
157                                                        const KeyTo& key_to)
158 {
159         /* Get operations for requested keys. */
160         DepsNode *node_from = get_node(key_from);
161         DepsNode *node_to = get_node(key_to);
162         if (node_from == NULL || node_to == NULL) {
163                 return false;
164         }
165         OperationDepsNode *op_from = node_from->get_exit_operation();
166         OperationDepsNode *op_to = node_to->get_entry_operation();
167         if (op_from == NULL || op_to == NULL) {
168                 return false;
169         }
170         /* Different armatures, bone can't be the same. */
171         if (op_from->owner->owner != op_to->owner->owner) {
172                 return false;
173         }
174         /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
175         if (!(op_from->opcode == DEG_OPCODE_BONE_DONE &&
176               op_to->opcode == DEG_OPCODE_BONE_LOCAL))
177         {
178                 return false;
179         }
180         /* ... BUT, we also need to check if it's same bone.  */
181         if (!STREQ(op_from->owner->name, op_to->owner->name)) {
182                 return false;
183         }
184         return true;
185 }
186
187 template <typename KeyFrom, typename KeyTo>
188 bool DepsgraphRelationBuilder::is_same_nodetree_node_dependency(
189         const KeyFrom& key_from,
190         const KeyTo& key_to)
191 {
192         /* Get operations for requested keys. */
193         DepsNode *node_from = get_node(key_from);
194         DepsNode *node_to = get_node(key_to);
195         if (node_from == NULL || node_to == NULL) {
196                 return false;
197         }
198         OperationDepsNode *op_from = node_from->get_exit_operation();
199         OperationDepsNode *op_to = node_to->get_entry_operation();
200         if (op_from == NULL || op_to == NULL) {
201                 return false;
202         }
203         /* Check if this is actually a node tree. */
204         if (GS(op_from->owner->owner->id_orig->name) != ID_NT) {
205                 return false;
206         }
207         /* Different node trees. */
208         if (op_from->owner->owner != op_to->owner->owner) {
209                 return false;
210         }
211         /* We are only interested in relations like BONE_DONE -> BONE_LOCAL... */
212         if (!(op_from->opcode == DEG_OPCODE_PARAMETERS_EVAL &&
213               op_to->opcode == DEG_OPCODE_PARAMETERS_EVAL))
214         {
215                 return false;
216         }
217         return true;
218 }
219
220 }  // namespace DEG