Depsgraph: Comb code to a better state all over
[blender.git] / source / blender / depsgraph / intern / builder / deg_builder_relations_rig.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) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Joshua Leung
22  * Contributor(s): Based on original depsgraph.c code - Blender Foundation (2005-2013)
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/builder/deg_builder_relations_rig.cc
28  *  \ingroup depsgraph
29  *
30  * Methods for constructing depsgraph
31  */
32
33 #include "intern/builder/deg_builder_relations.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <cstring>  /* required for STREQ later on. */
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_utildefines.h"
42 #include "BLI_blenlib.h"
43
44 extern "C" {
45 #include "DNA_action_types.h"
46 #include "DNA_anim_types.h"
47 #include "DNA_armature_types.h"
48 #include "DNA_constraint_types.h"
49 #include "DNA_customdata_types.h"
50 #include "DNA_object_types.h"
51
52 #include "BKE_action.h"
53 #include "BKE_armature.h"
54 #include "BKE_constraint.h"
55 } /* extern "C" */
56
57 #include "DEG_depsgraph.h"
58 #include "DEG_depsgraph_build.h"
59
60 #include "intern/builder/deg_builder.h"
61 #include "intern/builder/deg_builder_pchanmap.h"
62 #include "intern/debug/deg_debug.h"
63 #include "intern/node/deg_node.h"
64 #include "intern/node/deg_node_component.h"
65 #include "intern/node/deg_node_operation.h"
66
67 #include "intern/depsgraph_type.h"
68
69 namespace DEG {
70
71 /* IK Solver Eval Steps */
72 void DepsgraphRelationBuilder::build_ik_pose(Object *object,
73                                              bPoseChannel *pchan,
74                                              bConstraint *con,
75                                              RootPChanMap *root_map)
76 {
77         bKinematicConstraint *data = (bKinematicConstraint *)con->data;
78         /* Attach owner to IK Solver to. */
79         bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data);
80         if (rootchan == NULL) {
81                 return;
82         }
83         OperationKey pchan_local_key(&object->id,
84                                      NodeType::BONE,
85                                      pchan->name,
86                                      OperationCode::BONE_LOCAL);
87         OperationKey init_ik_key(
88                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
89         OperationKey solver_key(&object->id,
90                                 NodeType::EVAL_POSE,
91                                 rootchan->name,
92                                 OperationCode::POSE_IK_SOLVER);
93         OperationKey pose_cleanup_key(
94                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
95         add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree");
96         add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
97         /* Never cleanup before solver is run. */
98         add_relation(solver_key,
99                      pose_cleanup_key,
100                      "IK Solver -> Cleanup",
101                      RELATION_FLAG_GODMODE);
102         /* IK target */
103         /* TODO(sergey): This should get handled as part of the constraint code. */
104         if (data->tar != NULL) {
105                 /* TODO(sergey): For until we'll store partial matricies in the
106                  * depsgraph, we create dependency between target object and pose eval
107                  * component.
108                  *
109                  * This way we ensuring the whole subtree is updated from scratch
110                  * without need of intermediate matricies. This is an overkill, but good
111                  * enough for testing IK solver. */
112                 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
113                 if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) {
114                         /* TODO(sergey): This is only for until granular update stores
115                          * intermediate result. */
116                         if (data->tar != object) {
117                                 /* Different armature - can just read the results. */
118                                 ComponentKey target_key(
119                                         &data->tar->id, NodeType::BONE, data->subtarget);
120                                 add_relation(target_key, pose_key, con->name);
121                         }
122                         else {
123                                 /* Same armature - we'll use the ready state only, just in case
124                                  * this bone is in the chain we're solving. */
125                                 OperationKey target_key(&data->tar->id,
126                                                         NodeType::BONE,
127                                                         data->subtarget,
128                                                         OperationCode::BONE_DONE);
129                                 add_relation(target_key, solver_key, con->name);
130                         }
131                 }
132                 else if (data->subtarget[0] &&
133                          ELEM(data->tar->type, OB_MESH, OB_LATTICE))
134                 {
135                         /* Vertex group target. */
136                         /* NOTE: for now, we don't need to represent vertex groups
137                          * separately. */
138                         ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
139                         add_relation(target_key, solver_key, con->name);
140                         add_customdata_mask(data->tar, CD_MASK_MDEFORMVERT);
141                 }
142                 else {
143                         /* Standard Object Target. */
144                         ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM);
145                         add_relation(target_key, pose_key, con->name);
146                 }
147                 if (data->tar == object && data->subtarget[0]) {
148                         /* Prevent target's constraints from linking to anything from same
149                          * chain that it controls. */
150                         root_map->add_bone(data->subtarget, rootchan->name);
151                 }
152         }
153         /* Pole Target. */
154         /* TODO(sergey): This should get handled as part of the constraint code. */
155         if (data->poletar != NULL) {
156                 if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) {
157                         ComponentKey target_key(&data->poletar->id,
158                                                 NodeType::BONE,
159                                                 data->polesubtarget);
160                         add_relation(target_key, solver_key, con->name);
161                 }
162                 else if (data->polesubtarget[0] &&
163                          ELEM(data->poletar->type, OB_MESH, OB_LATTICE))
164                 {
165                         /* Vertex group target. */
166                         /* NOTE: for now, we don't need to represent vertex groups
167                          * separately. */
168                         ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY);
169                         add_relation(target_key, solver_key, con->name);
170                         add_customdata_mask(data->poletar, CD_MASK_MDEFORMVERT);
171                 }
172                 else {
173                         ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM);
174                         add_relation(target_key, solver_key, con->name);
175                 }
176         }
177         DEG_DEBUG_PRINTF(
178                 (::Depsgraph *)graph_,
179                 BUILD,
180                 "\nStarting IK Build: pchan = %s, target = (%s, %s), "
181                 "segcount = %d\n",
182                 pchan->name, data->tar->id.name, data->subtarget, data->rootbone);
183         bPoseChannel *parchan = pchan;
184         /* Exclude tip from chain if needed. */
185         if (!(data->flag & CONSTRAINT_IK_TIP)) {
186                 parchan = pchan->parent;
187         }
188         root_map->add_bone(parchan->name, rootchan->name);
189         OperationKey parchan_transforms_key(&object->id, NodeType::BONE,
190                                             parchan->name, OperationCode::BONE_READY);
191         add_relation(parchan_transforms_key, solver_key, "IK Solver Owner");
192         /* Walk to the chain's root. */
193         int segcount = 0;
194         while (parchan != NULL) {
195                 /* Make IK-solver dependent on this bone's result, since it can only run
196                  * after the standard results of the bone are know. Validate links step
197                  * on the bone will ensure that users of this bone only grab the result
198                  * with IK solver results. */
199                 if (parchan != pchan) {
200                         OperationKey parent_key(&object->id,
201                                                 NodeType::BONE,
202                                                 parchan->name,
203                                                 OperationCode::BONE_READY);
204                         add_relation(parent_key, solver_key, "IK Chain Parent");
205                         OperationKey bone_done_key(&object->id,
206                                                    NodeType::BONE,
207                                                    parchan->name,
208                                                    OperationCode::BONE_DONE);
209                         add_relation(solver_key, bone_done_key, "IK Chain Result");
210                 }
211                 else {
212                         OperationKey final_transforms_key(&object->id,
213                                                           NodeType::BONE,
214                                                           parchan->name,
215                                                           OperationCode::BONE_DONE);
216                         add_relation(solver_key, final_transforms_key, "IK Solver Result");
217                 }
218                 parchan->flag |= POSE_DONE;
219                 root_map->add_bone(parchan->name, rootchan->name);
220                 /* continue up chain, until we reach target number of items. */
221                 DEG_DEBUG_PRINTF((::Depsgraph *)graph_,
222                                  BUILD,
223                                  "  %d = %s\n",
224                                  segcount, parchan->name);
225                 /* TODO(sergey): This is an arbitrary value, which was just following
226                  * old code convention. */
227                 segcount++;
228                 if ((segcount == data->rootbone) || (segcount > 255)) {
229                         break;
230                 }
231                 parchan  = parchan->parent;
232         }
233         OperationKey pose_done_key(
234                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
235         add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
236 }
237
238 /* Spline IK Eval Steps */
239 void DepsgraphRelationBuilder::build_splineik_pose(Object *object,
240                                                    bPoseChannel *pchan,
241                                                    bConstraint *con,
242                                                    RootPChanMap *root_map)
243 {
244         bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
245         bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data);
246         OperationKey transforms_key(&object->id,
247                                     NodeType::BONE,
248                                     pchan->name,
249                                     OperationCode::BONE_READY);
250         OperationKey init_ik_key(&object->id,
251                                  NodeType::EVAL_POSE,
252                                  OperationCode::POSE_INIT_IK);
253         OperationKey solver_key(&object->id,
254                                 NodeType::EVAL_POSE,
255                                 rootchan->name,
256                                 OperationCode::POSE_SPLINE_IK_SOLVER);
257         OperationKey pose_cleanup_key(
258                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
259         /* Solver depends on initialization. */
260         add_relation(init_ik_key, solver_key, "Init IK -> IK Solver");
261         /* Never cleanup before solver is run. */
262         add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup");
263         /* Attach owner to IK Solver. */
264         add_relation(transforms_key,
265                      solver_key,
266                      "Spline IK Solver Owner",
267                      RELATION_FLAG_GODMODE);
268         /* Attach path dependency to solver. */
269         if (data->tar != NULL) {
270                 /* TODO(sergey): For until we'll store partial matricies in the
271                  * depsgraph, we create dependency between target object and pose eval
272                  * component. See IK pose for a bit more information. */
273                 /* TODO: the bigggest point here is that we need the curve PATH and not
274                  * just the general geometry. */
275                 ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY);
276                 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
277                 add_relation(target_key, pose_key, "Curve.Path -> Spline IK");
278         }
279         pchan->flag |= POSE_DONE;
280         OperationKey final_transforms_key(
281                 &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE);
282         add_relation(solver_key, final_transforms_key, "Spline IK Result");
283         root_map->add_bone(pchan->name, rootchan->name);
284         /* Walk to the chain's root/ */
285         int segcount = 0;
286         for (bPoseChannel *parchan = pchan->parent;
287              parchan != NULL;
288              parchan = parchan->parent)
289         {
290                 /* Make Spline IK solver dependent on this bone's result, since it can
291                  * only run after the standard results of the bone are know. Validate
292                  * links step on the bone will ensure that users of this bone only grab
293                  * the result with IK solver results. */
294                 if (parchan != pchan) {
295                         OperationKey parent_key(&object->id,
296                                                 NodeType::BONE,
297                                                 parchan->name,
298                                                 OperationCode::BONE_READY);
299                         add_relation(parent_key, solver_key, "Spline IK Solver Update");
300                         OperationKey bone_done_key(&object->id,
301                                                    NodeType::BONE,
302                                                    parchan->name,
303                                                    OperationCode::BONE_DONE);
304                         add_relation(solver_key, bone_done_key, "IK Chain Result");
305                 }
306                 parchan->flag |= POSE_DONE;
307                 OperationKey final_transforms_key(&object->id,
308                                                   NodeType::BONE,
309                                                   parchan->name,
310                                                   OperationCode::BONE_DONE);
311                 add_relation(
312                         solver_key, final_transforms_key, "Spline IK Solver Result");
313                 root_map->add_bone(parchan->name, rootchan->name);
314                 /* TODO(sergey): This is an arbitrary value, which was just following
315                  * old code convention. */
316                 segcount++;
317                 if ((segcount == data->chainlen) || (segcount > 255)) {
318                         break;
319                 }
320         }
321         OperationKey pose_done_key(
322                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
323         add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link");
324 }
325
326 /* Pose/Armature Bones Graph */
327 void DepsgraphRelationBuilder::build_rig(Object *object)
328 {
329         /* Armature-Data */
330         bArmature *armature = (bArmature *)object->data;
331         // TODO: selection status?
332         /* Attach links between pose operations. */
333         ComponentKey local_transform(&object->id, NodeType::TRANSFORM);
334         OperationKey pose_init_key(
335                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT);
336         OperationKey pose_init_ik_key(
337                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK);
338         OperationKey pose_cleanup_key(
339                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP);
340         OperationKey pose_done_key(
341                 &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE);
342         add_relation(
343                 local_transform, pose_init_key, "Local Transform -> Pose Init");
344         add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK");
345         add_relation(
346                 pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup");
347         /* Make sure pose is up-to-date with armature updates. */
348         build_armature(armature);
349         OperationKey armature_key(&armature->id,
350                                   NodeType::PARAMETERS,
351                                   OperationCode::PLACEHOLDER,
352                                   "Armature Eval");
353         add_relation(armature_key, pose_init_key, "Data dependency");
354         /* IK Solvers.
355          *
356          * - These require separate processing steps are pose-level to be executed
357          *   between chains of bones (i.e. once the base transforms of a bunch of
358          *   bones is done).
359          *
360          * - We build relations for these before the dependencies between operations
361          *   in the same component as it is necessary to check whether such bones
362          *   are in the same IK chain (or else we get weird issues with either
363          *   in-chain references, or with bones being parented to IK'd bones).
364          *
365          * Unsolved Issues:
366          * - Care is needed to ensure that multi-headed trees work out the same as
367          *   in ik-tree building
368          * - Animated chain-lengths are a problem. */
369         RootPChanMap root_map;
370         bool pose_depends_on_local_transform = false;
371         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
372                 LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) {
373                         switch (con->type) {
374                                 case CONSTRAINT_TYPE_KINEMATIC:
375                                         build_ik_pose(object, pchan, con, &root_map);
376                                         pose_depends_on_local_transform = true;
377                                         break;
378                                 case CONSTRAINT_TYPE_SPLINEIK:
379                                         build_splineik_pose(object, pchan, con, &root_map);
380                                         pose_depends_on_local_transform = true;
381                                         break;
382                                 /* Constraints which needs world's matrix for transform.
383                                  * TODO(sergey): More constraints here? */
384                                 case CONSTRAINT_TYPE_ROTLIKE:
385                                 case CONSTRAINT_TYPE_SIZELIKE:
386                                 case CONSTRAINT_TYPE_LOCLIKE:
387                                 case CONSTRAINT_TYPE_TRANSLIKE:
388                                         /* TODO(sergey): Add used space check. */
389                                         pose_depends_on_local_transform = true;
390                                         break;
391                                 default:
392                                         break;
393                         }
394                 }
395         }
396         // root_map.print_debug();
397         if (pose_depends_on_local_transform) {
398                 /* TODO(sergey): Once partial updates are possible use relation between
399                  * object transform and solver itself in it's build function. */
400                 ComponentKey pose_key(&object->id, NodeType::EVAL_POSE);
401                 ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM);
402                 add_relation(local_transform_key, pose_key, "Local Transforms");
403         }
404         /* Links between operations for each bone. */
405         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
406                 OperationKey bone_local_key(&object->id,
407                                             NodeType::BONE,
408                                             pchan->name,
409                                             OperationCode::BONE_LOCAL);
410                 OperationKey bone_pose_key(&object->id,
411                                            NodeType::BONE,
412                                            pchan->name,
413                                            OperationCode::BONE_POSE_PARENT);
414                 OperationKey bone_ready_key(&object->id,
415                                             NodeType::BONE,
416                                             pchan->name,
417                                             OperationCode::BONE_READY);
418                 OperationKey bone_done_key(&object->id,
419                                            NodeType::BONE,
420                                            pchan->name,
421                                            OperationCode::BONE_DONE);
422                 pchan->flag &= ~POSE_DONE;
423                 /* Pose init to bone local. */
424                 add_relation(pose_init_key,
425                              bone_local_key,
426                              "Pose Init - Bone Local",
427                              RELATION_FLAG_GODMODE);
428                 /* Local to pose parenting operation. */
429                 add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose");
430                 /* Parent relation. */
431                 if (pchan->parent != NULL) {
432                         OperationCode parent_key_opcode;
433                         /* NOTE: this difference in handling allows us to prevent lockups
434                          * while ensuring correct poses for separate chains. */
435                         if (root_map.has_common_root(pchan->name, pchan->parent->name)) {
436                                 parent_key_opcode = OperationCode::BONE_READY;
437                         }
438                         else {
439                                 parent_key_opcode = OperationCode::BONE_DONE;
440                         }
441
442                         OperationKey parent_key(&object->id,
443                                                 NodeType::BONE,
444                                                 pchan->parent->name,
445                                                 parent_key_opcode);
446                         add_relation(
447                                 parent_key, bone_pose_key, "Parent Bone -> Child Bone");
448                 }
449                 /* Build constraints. */
450                 if (pchan->constraints.first != NULL) {
451                         /* Build relations for indirectly linked objects. */
452                         BuilderWalkUserData data;
453                         data.builder = this;
454                         BKE_constraints_id_loop(
455                                 &pchan->constraints, constraint_walk, &data);
456                         /* Constraints stack and constraint dependencies. */
457                         build_constraints(&object->id,
458                                           NodeType::BONE,
459                                           pchan->name,
460                                           &pchan->constraints,
461                                           &root_map);
462                         /* Pose -> constraints. */
463                         OperationKey constraints_key(&object->id,
464                                                      NodeType::BONE,
465                                                      pchan->name,
466                                                      OperationCode::BONE_CONSTRAINTS);
467                         add_relation(bone_pose_key, constraints_key, "Constraints Stack");
468                         /* Constraints -> ready/ */
469                         /* TODO(sergey): When constraint stack is exploded, this step should
470                          * occur before the first IK solver.  */
471                         add_relation(
472                                 constraints_key, bone_ready_key, "Constraints -> Ready");
473                 }
474                 else {
475                         /* Pose -> Ready */
476                         add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready");
477                 }
478                 /* Bone ready -> Bone done.
479                  * NOTE: For bones without IK, this is all that's needed.
480                  *       For IK chains however, an additional rel is created from IK
481                  *       to done, with transitive reduction removing this one. */
482                 add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
483                 /* B-Bone shape is the real final step after Done if present. */
484                 if (pchan->bone != NULL && pchan->bone->segments > 1) {
485                         OperationKey bone_segments_key(&object->id,
486                                                        NodeType::BONE,
487                                                        pchan->name,
488                                                        OperationCode::BONE_SEGMENTS);
489                         /* B-Bone shape depends on the final position of the bone. */
490                         add_relation(bone_done_key,
491                                      bone_segments_key,
492                                      "Done -> B-Bone Segments");
493                         /* B-Bone shape depends on final position of handle bones. */
494                         bPoseChannel *prev, *next;
495                         BKE_pchan_bbone_handles_get(pchan, &prev, &next);
496                         if (prev) {
497                                 OperationKey prev_key(&object->id,
498                                                       NodeType::BONE,
499                                                       prev->name,
500                                                       OperationCode::BONE_DONE);
501                                 add_relation(prev_key,
502                                              bone_segments_key,
503                                              "Prev Handle -> B-Bone Segments");
504                         }
505                         if (next) {
506                                 OperationKey next_key(&object->id,
507                                                       NodeType::BONE,
508                                                       next->name,
509                                                       OperationCode::BONE_DONE);
510                                 add_relation(next_key,
511                                              bone_segments_key,
512                                              "Next Handle -> B-Bone Segments");
513                         }
514                         /* Pose requires the B-Bone shape. */
515                         add_relation(bone_segments_key,
516                                      pose_done_key,
517                                      "PoseEval Result-Bone Link",
518                                      RELATION_FLAG_GODMODE);
519                         add_relation(bone_segments_key,
520                                      pose_cleanup_key,
521                                      "Cleanup dependency");
522                 }
523                 else {
524                         /* Assume that all bones must be done for the pose to be ready
525                          * (for deformers). */
526                         add_relation(bone_done_key,
527                                      pose_done_key,
528                                      "PoseEval Result-Bone Link");
529                         add_relation(bone_done_key,
530                                      pose_cleanup_key,
531                                      "Cleanup dependency");
532                 }
533                 /* Custom shape. */
534                 if (pchan->custom != NULL) {
535                         build_object(NULL, pchan->custom);
536                 }
537         }
538 }
539
540 void DepsgraphRelationBuilder::build_proxy_rig(Object *object)
541 {
542         bArmature *armature = (bArmature *)object->data;
543         Object *proxy_from = object->proxy_from;
544         build_armature(armature);
545         OperationKey pose_init_key(&object->id,
546                                    NodeType::EVAL_POSE,
547                                    OperationCode::POSE_INIT);
548         OperationKey pose_done_key(&object->id,
549                                    NodeType::EVAL_POSE,
550                                    OperationCode::POSE_DONE);
551         OperationKey pose_cleanup_key(&object->id,
552                                       NodeType::EVAL_POSE,
553                                       OperationCode::POSE_CLEANUP);
554         LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
555                 OperationKey bone_local_key(&object->id,
556                                             NodeType::BONE, pchan->name,
557                                             OperationCode::BONE_LOCAL);
558                 OperationKey bone_ready_key(&object->id,
559                                             NodeType::BONE,
560                                             pchan->name,
561                                             OperationCode::BONE_READY);
562                 OperationKey bone_done_key(&object->id,
563                                            NodeType::BONE,
564                                            pchan->name,
565                                            OperationCode::BONE_DONE);
566                 OperationKey from_bone_done_key(&proxy_from->id,
567                                                 NodeType::BONE,
568                                                 pchan->name,
569                                                 OperationCode::BONE_DONE);
570                 add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local");
571                 add_relation(bone_local_key, bone_ready_key, "Local -> Ready");
572                 add_relation(bone_ready_key, bone_done_key, "Ready -> Done");
573                 add_relation(
574                         bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup");
575                 add_relation(bone_done_key,
576                             pose_done_key,
577                             "Bone Done -> Pose Done",
578                             RELATION_FLAG_GODMODE);
579                 /* Make sure bone in the proxy is not done before it's FROM is done. */
580                 if (pchan->bone && pchan->bone->segments > 1) {
581                         OperationKey from_bone_segments_key(&proxy_from->id,
582                                                             NodeType::BONE,
583                                                             pchan->name,
584                                                             OperationCode::BONE_SEGMENTS);
585                         add_relation(from_bone_segments_key,
586                                      bone_done_key,
587                                      "Bone Segments -> Bone Done",
588                                      RELATION_FLAG_GODMODE);
589                 }
590                 else {
591                         add_relation(from_bone_done_key,
592                                      bone_done_key,
593                                      "Bone Done -> Bone Done");
594                 }
595
596                 if (pchan->prop != NULL) {
597                         OperationKey bone_parameters(&object->id,
598                                                      NodeType::PARAMETERS,
599                                                      OperationCode::PARAMETERS_EVAL,
600                                                      pchan->name);
601                         OperationKey from_bone_parameters(&proxy_from->id,
602                                                           NodeType::PARAMETERS,
603                                                           OperationCode::PARAMETERS_EVAL,
604                                                           pchan->name);
605                         add_relation(from_bone_parameters,
606                                      bone_parameters,
607                                      "Proxy Bone Parameters");
608                 }
609         }
610 }
611
612 }  // namespace DEG