diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc')
-rw-r--r-- | source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc | 900 |
1 files changed, 384 insertions, 516 deletions
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index 9d36e9495e3..1d222258449 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -27,7 +27,7 @@ #include <stdio.h> #include <stdlib.h> -#include <cstring> /* required for STREQ later on. */ +#include <cstring> /* required for STREQ later on. */ #include "MEM_guardedalloc.h" @@ -67,166 +67,139 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, bConstraint *con, RootPChanMap *root_map) { - bKinematicConstraint *data = (bKinematicConstraint *)con->data; - /* Attach owner to IK Solver to. */ - bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); - if (rootchan == NULL) { - return; - } - OperationKey pchan_local_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_LOCAL); - OperationKey init_ik_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK); - OperationKey solver_key(&object->id, - NodeType::EVAL_POSE, - rootchan->name, - OperationCode::POSE_IK_SOLVER); - OperationKey pose_cleanup_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); - add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree"); - add_relation(init_ik_key, solver_key, "Init IK -> IK Solver"); - /* Never cleanup before solver is run. */ - add_relation(solver_key, - pose_cleanup_key, - "IK Solver -> Cleanup", - RELATION_FLAG_GODMODE); - /* IK target */ - /* TODO(sergey): This should get handled as part of the constraint code. */ - if (data->tar != NULL) { - /* TODO(sergey): For until we'll store partial matrices in the - * depsgraph, we create dependency between target object and pose eval - * component. - * - * This way we ensuring the whole subtree is updated from scratch - * without need of intermediate matrices. This is an overkill, but good - * enough for testing IK solver. */ - ComponentKey pose_key(&object->id, NodeType::EVAL_POSE); - if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { - /* TODO(sergey): This is only for until granular update stores - * intermediate result. */ - if (data->tar != object) { - /* Different armature - can just read the results. */ - ComponentKey target_key( - &data->tar->id, NodeType::BONE, data->subtarget); - add_relation(target_key, pose_key, con->name); - } - else { - /* Same armature - we'll use the ready state only, just in case - * this bone is in the chain we're solving. */ - OperationKey target_key(&data->tar->id, - NodeType::BONE, - data->subtarget, - OperationCode::BONE_DONE); - add_relation(target_key, solver_key, con->name); - } - } - else if (data->subtarget[0] && - ELEM(data->tar->type, OB_MESH, OB_LATTICE)) - { - /* Vertex group target. */ - /* NOTE: for now, we don't need to represent vertex groups - * separately. */ - ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY); - add_relation(target_key, solver_key, con->name); - add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT)); - } - else { - /* Standard Object Target. */ - ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM); - add_relation(target_key, pose_key, con->name); - } - if (data->tar == object && data->subtarget[0]) { - /* Prevent target's constraints from linking to anything from same - * chain that it controls. */ - root_map->add_bone(data->subtarget, rootchan->name); - } - } - /* Pole Target. */ - /* TODO(sergey): This should get handled as part of the constraint code. */ - if (data->poletar != NULL) { - if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) { - ComponentKey target_key(&data->poletar->id, - NodeType::BONE, - data->polesubtarget); - add_relation(target_key, solver_key, con->name); - } - else if (data->polesubtarget[0] && - ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) - { - /* Vertex group target. */ - /* NOTE: for now, we don't need to represent vertex groups - * separately. */ - ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY); - add_relation(target_key, solver_key, con->name); - add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT)); - } - else { - ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM); - add_relation(target_key, solver_key, con->name); - } - } - DEG_DEBUG_PRINTF( - (::Depsgraph *)graph_, - BUILD, - "\nStarting IK Build: pchan = %s, target = (%s, %s), " - "segcount = %d\n", - pchan->name, data->tar ? data->tar->id.name : "NULL", - data->subtarget, data->rootbone); - bPoseChannel *parchan = pchan; - /* Exclude tip from chain if needed. */ - if (!(data->flag & CONSTRAINT_IK_TIP)) { - parchan = pchan->parent; - } - root_map->add_bone(parchan->name, rootchan->name); - OperationKey parchan_transforms_key(&object->id, NodeType::BONE, - parchan->name, OperationCode::BONE_READY); - add_relation(parchan_transforms_key, solver_key, "IK Solver Owner"); - /* Walk to the chain's root. */ - int segcount = 0; - while (parchan != NULL) { - /* Make IK-solver dependent on this bone's result, since it can only run - * after the standard results of the bone are know. Validate links step - * on the bone will ensure that users of this bone only grab the result - * with IK solver results. */ - if (parchan != pchan) { - OperationKey parent_key(&object->id, - NodeType::BONE, - parchan->name, - OperationCode::BONE_READY); - add_relation(parent_key, solver_key, "IK Chain Parent"); - OperationKey bone_done_key(&object->id, - NodeType::BONE, - parchan->name, - OperationCode::BONE_DONE); - add_relation(solver_key, bone_done_key, "IK Chain Result"); - } - else { - OperationKey final_transforms_key(&object->id, - NodeType::BONE, - parchan->name, - OperationCode::BONE_DONE); - add_relation(solver_key, final_transforms_key, "IK Solver Result"); - } - parchan->flag |= POSE_DONE; - root_map->add_bone(parchan->name, rootchan->name); - /* continue up chain, until we reach target number of items. */ - DEG_DEBUG_PRINTF((::Depsgraph *)graph_, - BUILD, - " %d = %s\n", - segcount, parchan->name); - /* TODO(sergey): This is an arbitrary value, which was just following - * old code convention. */ - segcount++; - if ((segcount == data->rootbone) || (segcount > 255)) { - break; - } - parchan = parchan->parent; - } - OperationKey pose_done_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); - add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link"); + bKinematicConstraint *data = (bKinematicConstraint *)con->data; + /* Attach owner to IK Solver to. */ + bPoseChannel *rootchan = BKE_armature_ik_solver_find_root(pchan, data); + if (rootchan == NULL) { + return; + } + OperationKey pchan_local_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL); + OperationKey init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK); + OperationKey solver_key( + &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_IK_SOLVER); + OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); + add_relation(pchan_local_key, init_ik_key, "IK Constraint -> Init IK Tree"); + add_relation(init_ik_key, solver_key, "Init IK -> IK Solver"); + /* Never cleanup before solver is run. */ + add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup", RELATION_FLAG_GODMODE); + /* IK target */ + /* TODO(sergey): This should get handled as part of the constraint code. */ + if (data->tar != NULL) { + /* TODO(sergey): For until we'll store partial matrices in the + * depsgraph, we create dependency between target object and pose eval + * component. + * + * This way we ensuring the whole subtree is updated from scratch + * without need of intermediate matrices. This is an overkill, but good + * enough for testing IK solver. */ + ComponentKey pose_key(&object->id, NodeType::EVAL_POSE); + if ((data->tar->type == OB_ARMATURE) && (data->subtarget[0])) { + /* TODO(sergey): This is only for until granular update stores + * intermediate result. */ + if (data->tar != object) { + /* Different armature - can just read the results. */ + ComponentKey target_key(&data->tar->id, NodeType::BONE, data->subtarget); + add_relation(target_key, pose_key, con->name); + } + else { + /* Same armature - we'll use the ready state only, just in case + * this bone is in the chain we're solving. */ + OperationKey target_key( + &data->tar->id, NodeType::BONE, data->subtarget, OperationCode::BONE_DONE); + add_relation(target_key, solver_key, con->name); + } + } + else if (data->subtarget[0] && ELEM(data->tar->type, OB_MESH, OB_LATTICE)) { + /* Vertex group target. */ + /* NOTE: for now, we don't need to represent vertex groups + * separately. */ + ComponentKey target_key(&data->tar->id, NodeType::GEOMETRY); + add_relation(target_key, solver_key, con->name); + add_customdata_mask(data->tar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT)); + } + else { + /* Standard Object Target. */ + ComponentKey target_key(&data->tar->id, NodeType::TRANSFORM); + add_relation(target_key, pose_key, con->name); + } + if (data->tar == object && data->subtarget[0]) { + /* Prevent target's constraints from linking to anything from same + * chain that it controls. */ + root_map->add_bone(data->subtarget, rootchan->name); + } + } + /* Pole Target. */ + /* TODO(sergey): This should get handled as part of the constraint code. */ + if (data->poletar != NULL) { + if ((data->poletar->type == OB_ARMATURE) && (data->polesubtarget[0])) { + ComponentKey target_key(&data->poletar->id, NodeType::BONE, data->polesubtarget); + add_relation(target_key, solver_key, con->name); + } + else if (data->polesubtarget[0] && ELEM(data->poletar->type, OB_MESH, OB_LATTICE)) { + /* Vertex group target. */ + /* NOTE: for now, we don't need to represent vertex groups + * separately. */ + ComponentKey target_key(&data->poletar->id, NodeType::GEOMETRY); + add_relation(target_key, solver_key, con->name); + add_customdata_mask(data->poletar, DEGCustomDataMeshMasks::MaskVert(CD_MASK_MDEFORMVERT)); + } + else { + ComponentKey target_key(&data->poletar->id, NodeType::TRANSFORM); + add_relation(target_key, solver_key, con->name); + } + } + DEG_DEBUG_PRINTF((::Depsgraph *)graph_, + BUILD, + "\nStarting IK Build: pchan = %s, target = (%s, %s), " + "segcount = %d\n", + pchan->name, + data->tar ? data->tar->id.name : "NULL", + data->subtarget, + data->rootbone); + bPoseChannel *parchan = pchan; + /* Exclude tip from chain if needed. */ + if (!(data->flag & CONSTRAINT_IK_TIP)) { + parchan = pchan->parent; + } + root_map->add_bone(parchan->name, rootchan->name); + OperationKey parchan_transforms_key( + &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY); + add_relation(parchan_transforms_key, solver_key, "IK Solver Owner"); + /* Walk to the chain's root. */ + int segcount = 0; + while (parchan != NULL) { + /* Make IK-solver dependent on this bone's result, since it can only run + * after the standard results of the bone are know. Validate links step + * on the bone will ensure that users of this bone only grab the result + * with IK solver results. */ + if (parchan != pchan) { + OperationKey parent_key( + &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY); + add_relation(parent_key, solver_key, "IK Chain Parent"); + OperationKey bone_done_key( + &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE); + add_relation(solver_key, bone_done_key, "IK Chain Result"); + } + else { + OperationKey final_transforms_key( + &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE); + add_relation(solver_key, final_transforms_key, "IK Solver Result"); + } + parchan->flag |= POSE_DONE; + root_map->add_bone(parchan->name, rootchan->name); + /* continue up chain, until we reach target number of items. */ + DEG_DEBUG_PRINTF((::Depsgraph *)graph_, BUILD, " %d = %s\n", segcount, parchan->name); + /* TODO(sergey): This is an arbitrary value, which was just following + * old code convention. */ + segcount++; + if ((segcount == data->rootbone) || (segcount > 255)) { + break; + } + parchan = parchan->parent; + } + OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); + add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link"); } /* Spline IK Eval Steps */ @@ -235,375 +208,270 @@ void DepsgraphRelationBuilder::build_splineik_pose(Object *object, bConstraint *con, RootPChanMap *root_map) { - bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; - bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); - OperationKey transforms_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_READY); - OperationKey init_ik_key(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_INIT_IK); - OperationKey solver_key(&object->id, - NodeType::EVAL_POSE, - rootchan->name, - OperationCode::POSE_SPLINE_IK_SOLVER); - OperationKey pose_cleanup_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); - /* Solver depends on initialization. */ - add_relation(init_ik_key, solver_key, "Init IK -> IK Solver"); - /* Never cleanup before solver is run. */ - add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup"); - /* Attach owner to IK Solver. */ - add_relation(transforms_key, - solver_key, - "Spline IK Solver Owner", - RELATION_FLAG_GODMODE); - /* Attach path dependency to solver. */ - if (data->tar != NULL) { - ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY); - add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK"); - ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM); - add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK"); - add_special_eval_flag(&data->tar->id, DAG_EVAL_NEED_CURVE_PATH); - } - pchan->flag |= POSE_DONE; - OperationKey final_transforms_key( - &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE); - add_relation(solver_key, final_transforms_key, "Spline IK Result"); - root_map->add_bone(pchan->name, rootchan->name); - /* Walk to the chain's root/ */ - int segcount = 1; - for (bPoseChannel *parchan = pchan->parent; - parchan != NULL && segcount < data->chainlen; - parchan = parchan->parent, segcount++) - { - /* Make Spline IK solver dependent on this bone's result, since it can - * only run after the standard results of the bone are know. Validate - * links step on the bone will ensure that users of this bone only grab - * the result with IK solver results. */ - OperationKey parent_key(&object->id, - NodeType::BONE, - parchan->name, - OperationCode::BONE_READY); - add_relation(parent_key, solver_key, "Spline IK Solver Update"); - OperationKey bone_done_key(&object->id, - NodeType::BONE, - parchan->name, - OperationCode::BONE_DONE); - add_relation(solver_key, bone_done_key, "Spline IK Solver Result"); - parchan->flag |= POSE_DONE; - root_map->add_bone(parchan->name, rootchan->name); - } - OperationKey pose_done_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); - add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link"); + bSplineIKConstraint *data = (bSplineIKConstraint *)con->data; + bPoseChannel *rootchan = BKE_armature_splineik_solver_find_root(pchan, data); + OperationKey transforms_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY); + OperationKey init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK); + OperationKey solver_key( + &object->id, NodeType::EVAL_POSE, rootchan->name, OperationCode::POSE_SPLINE_IK_SOLVER); + OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); + /* Solver depends on initialization. */ + add_relation(init_ik_key, solver_key, "Init IK -> IK Solver"); + /* Never cleanup before solver is run. */ + add_relation(solver_key, pose_cleanup_key, "IK Solver -> Cleanup"); + /* Attach owner to IK Solver. */ + add_relation(transforms_key, solver_key, "Spline IK Solver Owner", RELATION_FLAG_GODMODE); + /* Attach path dependency to solver. */ + if (data->tar != NULL) { + ComponentKey target_geometry_key(&data->tar->id, NodeType::GEOMETRY); + add_relation(target_geometry_key, solver_key, "Curve.Path -> Spline IK"); + ComponentKey target_transform_key(&data->tar->id, NodeType::TRANSFORM); + add_relation(target_transform_key, solver_key, "Curve.Transform -> Spline IK"); + add_special_eval_flag(&data->tar->id, DAG_EVAL_NEED_CURVE_PATH); + } + pchan->flag |= POSE_DONE; + OperationKey final_transforms_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE); + add_relation(solver_key, final_transforms_key, "Spline IK Result"); + root_map->add_bone(pchan->name, rootchan->name); + /* Walk to the chain's root/ */ + int segcount = 1; + for (bPoseChannel *parchan = pchan->parent; parchan != NULL && segcount < data->chainlen; + parchan = parchan->parent, segcount++) { + /* Make Spline IK solver dependent on this bone's result, since it can + * only run after the standard results of the bone are know. Validate + * links step on the bone will ensure that users of this bone only grab + * the result with IK solver results. */ + OperationKey parent_key(&object->id, NodeType::BONE, parchan->name, OperationCode::BONE_READY); + add_relation(parent_key, solver_key, "Spline IK Solver Update"); + OperationKey bone_done_key( + &object->id, NodeType::BONE, parchan->name, OperationCode::BONE_DONE); + add_relation(solver_key, bone_done_key, "Spline IK Solver Result"); + parchan->flag |= POSE_DONE; + root_map->add_bone(parchan->name, rootchan->name); + } + OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); + add_relation(solver_key, pose_done_key, "PoseEval Result-Bone Link"); } /* Pose/Armature Bones Graph */ void DepsgraphRelationBuilder::build_rig(Object *object) { - /* Armature-Data */ - bArmature *armature = (bArmature *)object->data; - // TODO: selection status? - /* Attach links between pose operations. */ - ComponentKey local_transform(&object->id, NodeType::TRANSFORM); - OperationKey pose_init_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT); - OperationKey pose_init_ik_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK); - OperationKey pose_cleanup_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); - OperationKey pose_done_key( - &object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); - add_relation( - local_transform, pose_init_key, "Local Transform -> Pose Init"); - add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK"); - add_relation( - pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup"); - /* Make sure pose is up-to-date with armature updates. */ - build_armature(armature); - OperationKey armature_key(&armature->id, - NodeType::PARAMETERS, - OperationCode::ARMATURE_EVAL); - add_relation(armature_key, pose_init_key, "Data dependency"); - /* Run cleanup even when there are no bones. */ - add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup"); - /* IK Solvers. - * - * - These require separate processing steps are pose-level to be executed - * between chains of bones (i.e. once the base transforms of a bunch of - * bones is done). - * - * - We build relations for these before the dependencies between operations - * in the same component as it is necessary to check whether such bones - * are in the same IK chain (or else we get weird issues with either - * in-chain references, or with bones being parented to IK'd bones). - * - * Unsolved Issues: - * - Care is needed to ensure that multi-headed trees work out the same as - * in ik-tree building - * - Animated chain-lengths are a problem. */ - RootPChanMap root_map; - bool pose_depends_on_local_transform = false; - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { - switch (con->type) { - case CONSTRAINT_TYPE_KINEMATIC: - build_ik_pose(object, pchan, con, &root_map); - pose_depends_on_local_transform = true; - break; - case CONSTRAINT_TYPE_SPLINEIK: - build_splineik_pose(object, pchan, con, &root_map); - pose_depends_on_local_transform = true; - break; - /* Constraints which needs world's matrix for transform. - * TODO(sergey): More constraints here? */ - case CONSTRAINT_TYPE_ROTLIKE: - case CONSTRAINT_TYPE_SIZELIKE: - case CONSTRAINT_TYPE_LOCLIKE: - case CONSTRAINT_TYPE_TRANSLIKE: - /* TODO(sergey): Add used space check. */ - pose_depends_on_local_transform = true; - break; - default: - break; - } - } - } - // root_map.print_debug(); - if (pose_depends_on_local_transform) { - /* TODO(sergey): Once partial updates are possible use relation between - * object transform and solver itself in it's build function. */ - ComponentKey pose_key(&object->id, NodeType::EVAL_POSE); - ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM); - add_relation(local_transform_key, pose_key, "Local Transforms"); - } - /* Links between operations for each bone. */ - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - OperationKey bone_local_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_LOCAL); - OperationKey bone_pose_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_POSE_PARENT); - OperationKey bone_ready_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_READY); - OperationKey bone_done_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_DONE); - pchan->flag &= ~POSE_DONE; - /* Pose init to bone local. */ - add_relation(pose_init_key, - bone_local_key, - "Pose Init - Bone Local", - RELATION_FLAG_GODMODE); - /* Local to pose parenting operation. */ - add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose"); - /* Parent relation. */ - if (pchan->parent != NULL) { - OperationCode parent_key_opcode; - /* NOTE: this difference in handling allows us to prevent lockups - * while ensuring correct poses for separate chains. */ - if (root_map.has_common_root(pchan->name, pchan->parent->name)) { - parent_key_opcode = OperationCode::BONE_READY; - } - else { - parent_key_opcode = OperationCode::BONE_DONE; - } + /* Armature-Data */ + bArmature *armature = (bArmature *)object->data; + // TODO: selection status? + /* Attach links between pose operations. */ + ComponentKey local_transform(&object->id, NodeType::TRANSFORM); + OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT); + OperationKey pose_init_ik_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT_IK); + OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); + OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); + add_relation(local_transform, pose_init_key, "Local Transform -> Pose Init"); + add_relation(pose_init_key, pose_init_ik_key, "Pose Init -> Pose Init IK"); + add_relation(pose_init_ik_key, pose_done_key, "Pose Init IK -> Pose Cleanup"); + /* Make sure pose is up-to-date with armature updates. */ + build_armature(armature); + OperationKey armature_key(&armature->id, NodeType::PARAMETERS, OperationCode::ARMATURE_EVAL); + add_relation(armature_key, pose_init_key, "Data dependency"); + /* Run cleanup even when there are no bones. */ + add_relation(pose_init_key, pose_cleanup_key, "Init -> Cleanup"); + /* IK Solvers. + * + * - These require separate processing steps are pose-level to be executed + * between chains of bones (i.e. once the base transforms of a bunch of + * bones is done). + * + * - We build relations for these before the dependencies between operations + * in the same component as it is necessary to check whether such bones + * are in the same IK chain (or else we get weird issues with either + * in-chain references, or with bones being parented to IK'd bones). + * + * Unsolved Issues: + * - Care is needed to ensure that multi-headed trees work out the same as + * in ik-tree building + * - Animated chain-lengths are a problem. */ + RootPChanMap root_map; + bool pose_depends_on_local_transform = false; + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + LISTBASE_FOREACH (bConstraint *, con, &pchan->constraints) { + switch (con->type) { + case CONSTRAINT_TYPE_KINEMATIC: + build_ik_pose(object, pchan, con, &root_map); + pose_depends_on_local_transform = true; + break; + case CONSTRAINT_TYPE_SPLINEIK: + build_splineik_pose(object, pchan, con, &root_map); + pose_depends_on_local_transform = true; + break; + /* Constraints which needs world's matrix for transform. + * TODO(sergey): More constraints here? */ + case CONSTRAINT_TYPE_ROTLIKE: + case CONSTRAINT_TYPE_SIZELIKE: + case CONSTRAINT_TYPE_LOCLIKE: + case CONSTRAINT_TYPE_TRANSLIKE: + /* TODO(sergey): Add used space check. */ + pose_depends_on_local_transform = true; + break; + default: + break; + } + } + } + // root_map.print_debug(); + if (pose_depends_on_local_transform) { + /* TODO(sergey): Once partial updates are possible use relation between + * object transform and solver itself in it's build function. */ + ComponentKey pose_key(&object->id, NodeType::EVAL_POSE); + ComponentKey local_transform_key(&object->id, NodeType::TRANSFORM); + add_relation(local_transform_key, pose_key, "Local Transforms"); + } + /* Links between operations for each bone. */ + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + OperationKey bone_local_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL); + OperationKey bone_pose_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_POSE_PARENT); + OperationKey bone_ready_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY); + OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE); + pchan->flag &= ~POSE_DONE; + /* Pose init to bone local. */ + add_relation(pose_init_key, bone_local_key, "Pose Init - Bone Local", RELATION_FLAG_GODMODE); + /* Local to pose parenting operation. */ + add_relation(bone_local_key, bone_pose_key, "Bone Local - Bone Pose"); + /* Parent relation. */ + if (pchan->parent != NULL) { + OperationCode parent_key_opcode; + /* NOTE: this difference in handling allows us to prevent lockups + * while ensuring correct poses for separate chains. */ + if (root_map.has_common_root(pchan->name, pchan->parent->name)) { + parent_key_opcode = OperationCode::BONE_READY; + } + else { + parent_key_opcode = OperationCode::BONE_DONE; + } - OperationKey parent_key(&object->id, - NodeType::BONE, - pchan->parent->name, - parent_key_opcode); - add_relation( - parent_key, bone_pose_key, "Parent Bone -> Child Bone"); - } - /* Build constraints. */ - if (pchan->constraints.first != NULL) { - /* Build relations for indirectly linked objects. */ - BuilderWalkUserData data; - data.builder = this; - BKE_constraints_id_loop( - &pchan->constraints, constraint_walk, &data); - /* Constraints stack and constraint dependencies. */ - build_constraints(&object->id, - NodeType::BONE, - pchan->name, - &pchan->constraints, - &root_map); - /* Pose -> constraints. */ - OperationKey constraints_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_CONSTRAINTS); - add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack"); - add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack"); - /* Constraints -> ready/ */ - /* TODO(sergey): When constraint stack is exploded, this step should - * occur before the first IK solver. */ - add_relation( - constraints_key, bone_ready_key, "Constraints -> Ready"); - } - else { - /* Pose -> Ready */ - add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready"); - } - /* Bone ready -> Bone done. - * NOTE: For bones without IK, this is all that's needed. - * For IK chains however, an additional rel is created from IK - * to done, with transitive reduction removing this one. */ - add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); - /* B-Bone shape is the real final step after Done if present. */ - if (pchan->bone != NULL && pchan->bone->segments > 1) { - OperationKey bone_segments_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_SEGMENTS); - /* B-Bone shape depends on the final position of the bone. */ - add_relation(bone_done_key, - bone_segments_key, - "Done -> B-Bone Segments"); - /* B-Bone shape depends on final position of handle bones. */ - bPoseChannel *prev, *next; - BKE_pchan_bbone_handles_get(pchan, &prev, &next); - if (prev) { - OperationKey prev_key(&object->id, - NodeType::BONE, - prev->name, - OperationCode::BONE_DONE); - add_relation(prev_key, - bone_segments_key, - "Prev Handle -> B-Bone Segments"); - } - if (next) { - OperationKey next_key(&object->id, - NodeType::BONE, - next->name, - OperationCode::BONE_DONE); - add_relation(next_key, - bone_segments_key, - "Next Handle -> B-Bone Segments"); - } - /* Pose requires the B-Bone shape. */ - add_relation(bone_segments_key, - pose_done_key, - "PoseEval Result-Bone Link", - RELATION_FLAG_GODMODE); - add_relation(bone_segments_key, - pose_cleanup_key, - "Cleanup dependency"); - } - else { - /* Assume that all bones must be done for the pose to be ready - * (for deformers). */ - add_relation(bone_done_key, - pose_done_key, - "PoseEval Result-Bone Link"); + OperationKey parent_key(&object->id, NodeType::BONE, pchan->parent->name, parent_key_opcode); + add_relation(parent_key, bone_pose_key, "Parent Bone -> Child Bone"); + } + /* Build constraints. */ + if (pchan->constraints.first != NULL) { + /* Build relations for indirectly linked objects. */ + BuilderWalkUserData data; + data.builder = this; + BKE_constraints_id_loop(&pchan->constraints, constraint_walk, &data); + /* Constraints stack and constraint dependencies. */ + build_constraints(&object->id, NodeType::BONE, pchan->name, &pchan->constraints, &root_map); + /* Pose -> constraints. */ + OperationKey constraints_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_CONSTRAINTS); + add_relation(bone_pose_key, constraints_key, "Pose -> Constraints Stack"); + add_relation(bone_local_key, constraints_key, "Local -> Constraints Stack"); + /* Constraints -> ready/ */ + /* TODO(sergey): When constraint stack is exploded, this step should + * occur before the first IK solver. */ + add_relation(constraints_key, bone_ready_key, "Constraints -> Ready"); + } + else { + /* Pose -> Ready */ + add_relation(bone_pose_key, bone_ready_key, "Pose -> Ready"); + } + /* Bone ready -> Bone done. + * NOTE: For bones without IK, this is all that's needed. + * For IK chains however, an additional rel is created from IK + * to done, with transitive reduction removing this one. */ + add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); + /* B-Bone shape is the real final step after Done if present. */ + if (pchan->bone != NULL && pchan->bone->segments > 1) { + OperationKey bone_segments_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS); + /* B-Bone shape depends on the final position of the bone. */ + add_relation(bone_done_key, bone_segments_key, "Done -> B-Bone Segments"); + /* B-Bone shape depends on final position of handle bones. */ + bPoseChannel *prev, *next; + BKE_pchan_bbone_handles_get(pchan, &prev, &next); + if (prev) { + OperationKey prev_key(&object->id, NodeType::BONE, prev->name, OperationCode::BONE_DONE); + add_relation(prev_key, bone_segments_key, "Prev Handle -> B-Bone Segments"); + } + if (next) { + OperationKey next_key(&object->id, NodeType::BONE, next->name, OperationCode::BONE_DONE); + add_relation(next_key, bone_segments_key, "Next Handle -> B-Bone Segments"); + } + /* Pose requires the B-Bone shape. */ + add_relation( + bone_segments_key, pose_done_key, "PoseEval Result-Bone Link", RELATION_FLAG_GODMODE); + add_relation(bone_segments_key, pose_cleanup_key, "Cleanup dependency"); + } + else { + /* Assume that all bones must be done for the pose to be ready + * (for deformers). */ + add_relation(bone_done_key, pose_done_key, "PoseEval Result-Bone Link"); - /* Bones must be traversed before cleanup. */ - add_relation(bone_done_key, - pose_cleanup_key, - "Done -> Cleanup"); + /* Bones must be traversed before cleanup. */ + add_relation(bone_done_key, pose_cleanup_key, "Done -> Cleanup"); - add_relation(bone_ready_key, - pose_cleanup_key, - "Ready -> Cleanup"); - } - /* Custom shape. */ - if (pchan->custom != NULL) { - build_object(NULL, pchan->custom); - } - } + add_relation(bone_ready_key, pose_cleanup_key, "Ready -> Cleanup"); + } + /* Custom shape. */ + if (pchan->custom != NULL) { + build_object(NULL, pchan->custom); + } + } } void DepsgraphRelationBuilder::build_proxy_rig(Object *object) { - bArmature *armature = (bArmature *)object->data; - Object *proxy_from = object->proxy_from; - build_armature(armature); - OperationKey pose_init_key(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_INIT); - OperationKey pose_done_key(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_DONE); - OperationKey pose_cleanup_key(&object->id, - NodeType::EVAL_POSE, - OperationCode::POSE_CLEANUP); - LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - OperationKey bone_local_key(&object->id, - NodeType::BONE, pchan->name, - OperationCode::BONE_LOCAL); - OperationKey bone_ready_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_READY); - OperationKey bone_done_key(&object->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_DONE); - OperationKey from_bone_done_key(&proxy_from->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_DONE); - add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); - add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); - add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); - add_relation( - bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup"); - add_relation(bone_done_key, - pose_done_key, - "Bone Done -> Pose Done", - RELATION_FLAG_GODMODE); - /* Make sure bone in the proxy is not done before it's FROM is done. */ - if (pchan->bone && pchan->bone->segments > 1) { - OperationKey from_bone_segments_key(&proxy_from->id, - NodeType::BONE, - pchan->name, - OperationCode::BONE_SEGMENTS); - add_relation(from_bone_segments_key, - bone_done_key, - "Bone Segments -> Bone Done", - RELATION_FLAG_GODMODE); - } - else { - add_relation(from_bone_done_key, - bone_done_key, - "Bone Done -> Bone Done"); - } + bArmature *armature = (bArmature *)object->data; + Object *proxy_from = object->proxy_from; + build_armature(armature); + OperationKey pose_init_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_INIT); + OperationKey pose_done_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_DONE); + OperationKey pose_cleanup_key(&object->id, NodeType::EVAL_POSE, OperationCode::POSE_CLEANUP); + LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { + OperationKey bone_local_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_LOCAL); + OperationKey bone_ready_key( + &object->id, NodeType::BONE, pchan->name, OperationCode::BONE_READY); + OperationKey bone_done_key(&object->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE); + OperationKey from_bone_done_key( + &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_DONE); + add_relation(pose_init_key, bone_local_key, "Pose Init -> Bone Local"); + add_relation(bone_local_key, bone_ready_key, "Local -> Ready"); + add_relation(bone_ready_key, bone_done_key, "Ready -> Done"); + add_relation(bone_done_key, pose_cleanup_key, "Bone Done -> Pose Cleanup"); + add_relation(bone_done_key, pose_done_key, "Bone Done -> Pose Done", RELATION_FLAG_GODMODE); + /* Make sure bone in the proxy is not done before it's FROM is done. */ + if (pchan->bone && pchan->bone->segments > 1) { + OperationKey from_bone_segments_key( + &proxy_from->id, NodeType::BONE, pchan->name, OperationCode::BONE_SEGMENTS); + add_relation(from_bone_segments_key, + bone_done_key, + "Bone Segments -> Bone Done", + RELATION_FLAG_GODMODE); + } + else { + add_relation(from_bone_done_key, bone_done_key, "Bone Done -> Bone Done"); + } - /* Parent relation: even though the proxy bone itself doesn't need - * the parent bone, some users expect the parent to be ready if the - * bone itself is (e.g. for computing the local space matrix). - */ - if (pchan->parent != NULL) { - OperationKey parent_key(&object->id, - NodeType::BONE, - pchan->parent->name, - OperationCode::BONE_DONE); - add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone"); - } + /* Parent relation: even though the proxy bone itself doesn't need + * the parent bone, some users expect the parent to be ready if the + * bone itself is (e.g. for computing the local space matrix). + */ + if (pchan->parent != NULL) { + OperationKey parent_key( + &object->id, NodeType::BONE, pchan->parent->name, OperationCode::BONE_DONE); + add_relation(parent_key, bone_done_key, "Parent Bone -> Child Bone"); + } - if (pchan->prop != NULL) { - OperationKey bone_parameters(&object->id, - NodeType::PARAMETERS, - OperationCode::PARAMETERS_EVAL, - pchan->name); - OperationKey from_bone_parameters(&proxy_from->id, - NodeType::PARAMETERS, - OperationCode::PARAMETERS_EVAL, - pchan->name); - add_relation(from_bone_parameters, - bone_parameters, - "Proxy Bone Parameters"); - } - } + if (pchan->prop != NULL) { + OperationKey bone_parameters( + &object->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name); + OperationKey from_bone_parameters( + &proxy_from->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL, pchan->name); + add_relation(from_bone_parameters, bone_parameters, "Proxy Bone Parameters"); + } + } } } // namespace DEG |